Browse Source

DATAMONGO-319 - WriteConcern not parsed correctly in namespace handlers

DATAMONGO-311 - Update MongoDB driver to v 2.7.x
pull/1/head
Mark Pollack 14 years ago
parent
commit
64921ddad1
  1. 21
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoDbFactoryParser.java
  2. 13
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoParser.java
  3. 53
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/WriteConcernPropertyEditor.java
  4. 4
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/SimpleMongoDbFactory.java
  5. 40
      spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-1.0.xsd
  6. 54
      spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoDbFactoryParserIntegrationTests.java
  7. 56
      spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MyWriteConcern.java
  8. 24
      spring-data-mongodb/src/test/resources/namespace/db-factory-bean-custom-write-concern.xml
  9. 15
      spring-data-mongodb/src/test/resources/namespace/db-factory-bean.xml

21
spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoDbFactoryParser.java

@ -15,15 +15,20 @@
*/ */
package org.springframework.data.mongodb.config; package org.springframework.data.mongodb.config;
import static org.springframework.data.mongodb.config.BeanNames.*; import static org.springframework.data.mongodb.config.BeanNames.DB_FACTORY;
import static org.springframework.data.mongodb.config.ParsingUtils.*; import static org.springframework.data.mongodb.config.ParsingUtils.getSourceBeanDefinition;
import java.util.Map;
import org.springframework.beans.factory.BeanDefinitionStoreException; import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.CustomEditorConfigurer;
import org.springframework.beans.factory.config.RuntimeBeanReference; import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.support.AbstractBeanDefinition; import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils; import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.ManagedMap;
import org.springframework.beans.factory.xml.AbstractBeanDefinitionParser; import org.springframework.beans.factory.xml.AbstractBeanDefinitionParser;
import org.springframework.beans.factory.xml.BeanDefinitionParser; import org.springframework.beans.factory.xml.BeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext; import org.springframework.beans.factory.xml.ParserContext;
@ -86,6 +91,10 @@ public class MongoDbFactoryParser extends AbstractBeanDefinitionParser {
dbFactoryBuilder.addConstructorArgValue(userCredentials); dbFactoryBuilder.addConstructorArgValue(userCredentials);
} }
//Register property editor to parse WriteConcern
registerWriteConcernPropertyEditor(parserContext.getRegistry());
return getSourceBeanDefinition(dbFactoryBuilder, parserContext, element); return getSourceBeanDefinition(dbFactoryBuilder, parserContext, element);
} }
@ -107,6 +116,14 @@ public class MongoDbFactoryParser extends AbstractBeanDefinitionParser {
parserContext.getRegistry()); parserContext.getRegistry());
} }
private void registerWriteConcernPropertyEditor(BeanDefinitionRegistry registry) {
BeanDefinitionBuilder customEditorConfigurer = BeanDefinitionBuilder.genericBeanDefinition(CustomEditorConfigurer.class);
Map<String, String> customEditors = new ManagedMap<String, String>();
customEditors.put("com.mongodb.WriteConcern", "org.springframework.data.mongodb.config.WriteConcernPropertyEditor");
customEditorConfigurer.addPropertyValue("customEditors", customEditors);
BeanDefinitionReaderUtils.registerWithGeneratedName(customEditorConfigurer.getBeanDefinition(), registry);
}
/** /**
* Returns a {@link BeanDefinition} for a {@link UserCredentials} object. * Returns a {@link BeanDefinition} for a {@link UserCredentials} object.
* *

13
spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoParser.java

@ -53,7 +53,8 @@ public class MongoParser extends AbstractSingleBeanDefinitionParser {
ParsingUtils.parseMongoOptions(element, builder); ParsingUtils.parseMongoOptions(element, builder);
ParsingUtils.parseReplicaSet(element, builder); ParsingUtils.parseReplicaSet(element, builder);
registerCustomEditorConfigurer(parserContext.getRegistry()); registerServerAddressPropertyEditor(parserContext.getRegistry());
registerWriteConcernPropertyEditor(parserContext.getRegistry());
} }
@ -62,7 +63,7 @@ public class MongoParser extends AbstractSingleBeanDefinitionParser {
* registering a 'default' property editor with the container. * registering a 'default' property editor with the container.
* @param parserContext the ParserContext to * @param parserContext the ParserContext to
*/ */
private void registerCustomEditorConfigurer(BeanDefinitionRegistry registry) { private void registerServerAddressPropertyEditor(BeanDefinitionRegistry registry) {
BeanDefinitionBuilder customEditorConfigurer = BeanDefinitionBuilder.genericBeanDefinition(CustomEditorConfigurer.class); BeanDefinitionBuilder customEditorConfigurer = BeanDefinitionBuilder.genericBeanDefinition(CustomEditorConfigurer.class);
Map<String, String> customEditors = new ManagedMap<String, String>(); Map<String, String> customEditors = new ManagedMap<String, String>();
customEditors.put("java.util.List", "org.springframework.data.mongodb.config.ServerAddressPropertyEditor"); customEditors.put("java.util.List", "org.springframework.data.mongodb.config.ServerAddressPropertyEditor");
@ -70,6 +71,14 @@ public class MongoParser extends AbstractSingleBeanDefinitionParser {
BeanDefinitionReaderUtils.registerWithGeneratedName(customEditorConfigurer.getBeanDefinition(), registry); BeanDefinitionReaderUtils.registerWithGeneratedName(customEditorConfigurer.getBeanDefinition(), registry);
} }
private void registerWriteConcernPropertyEditor(BeanDefinitionRegistry registry) {
BeanDefinitionBuilder customEditorConfigurer = BeanDefinitionBuilder.genericBeanDefinition(CustomEditorConfigurer.class);
Map<String, String> customEditors = new ManagedMap<String, String>();
customEditors.put("com.mongodb.WriteConcern", "org.springframework.data.mongodb.config.WriteConcernPropertyEditor");
customEditorConfigurer.addPropertyValue("customEditors", customEditors);
BeanDefinitionReaderUtils.registerWithGeneratedName(customEditorConfigurer.getBeanDefinition(), registry);
}
@Override @Override
protected String resolveId(Element element, AbstractBeanDefinition definition, ParserContext parserContext) protected String resolveId(Element element, AbstractBeanDefinition definition, ParserContext parserContext)
throws BeanDefinitionStoreException { throws BeanDefinitionStoreException {

53
spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/WriteConcernPropertyEditor.java

@ -0,0 +1,53 @@
/*
* Copyright 2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.mongodb.config;
import java.beans.PropertyEditorSupport;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;
import org.springframework.util.StringUtils;
import com.mongodb.ServerAddress;
import com.mongodb.WriteConcern;
/**
* Parse a string to a WriteConcern. If it is a well know String as identified by the WriteConcern.valueOf, use the
* well known WriteConcern value, otherwise pass the string as is to the constructor of the write concern.
* There is no support for other constructor signatures when parsing from a string value.
*
* @author Mark Pollack
*
*/
public class WriteConcernPropertyEditor extends PropertyEditorSupport {
/**
* Parse a string to a List<ServerAddress>
*/
public void setAsText(String writeConcernString) {
WriteConcern writeConcern = WriteConcern.valueOf(writeConcernString);
if (writeConcern != null) {
// have a well known string
setValue(writeConcern);
} else {
// pass on the string to the constructor
setValue(new WriteConcern(writeConcernString));
}
}
}

4
spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/SimpleMongoDbFactory.java

@ -95,6 +95,10 @@ public class SimpleMongoDbFactory implements DisposableBean, MongoDbFactory {
this.writeConcern = writeConcern; this.writeConcern = writeConcern;
} }
public WriteConcern getWriteConcern() {
return writeConcern;
}
/* /*
* (non-Javadoc) * (non-Javadoc)
* @see org.springframework.data.mongodb.MongoDbFactory#getDb() * @see org.springframework.data.mongodb.MongoDbFactory#getDb()

40
spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-1.0.xsd

@ -93,7 +93,19 @@ The password to use when connecting to a MongoDB server.
The Mongo URI string.]]></xsd:documentation> The Mongo URI string.]]></xsd:documentation>
</xsd:annotation> </xsd:annotation>
</xsd:attribute> </xsd:attribute>
<xsd:attribute name="write-concern">
<xsd:annotation>
<xsd:documentation>
The WriteConcern that will be the default value used when asking the MongoDbFactory for a DB object
</xsd:documentation>
</xsd:annotation>
<xsd:simpleType>
<xsd:union memberTypes="writeConcernEnumeration xsd:string"/>
</xsd:simpleType>
</xsd:attribute>
<!-- MLP
<xsd:attributeGroup ref="writeConcern" /> <xsd:attributeGroup ref="writeConcern" />
-->
</xsd:complexType> </xsd:complexType>
</xsd:element> </xsd:element>
@ -259,6 +271,18 @@ The name of the Mongo object that determines what server to monitor. (by default
<xsd:union memberTypes="xsd:string"/> <xsd:union memberTypes="xsd:string"/>
</xsd:simpleType> </xsd:simpleType>
<xsd:simpleType name="writeConcernEnumeration">
<xsd:restriction base="xsd:token">
<xsd:enumeration value="NONE" />
<xsd:enumeration value="NORMAL" />
<xsd:enumeration value="SAFE" />
<xsd:enumeration value="FSYNC_SAFE" />
<xsd:enumeration value="REPLICA_SAFE" />
<xsd:enumeration value="JOURNAL_SAFE" />
<xsd:enumeration value="MAJORITY" />
</xsd:restriction>
</xsd:simpleType>
<!-- MLP
<xsd:attributeGroup name="writeConcern"> <xsd:attributeGroup name="writeConcern">
<xsd:attribute name="write-concern"> <xsd:attribute name="write-concern">
<xsd:simpleType> <xsd:simpleType>
@ -268,11 +292,13 @@ The name of the Mongo object that determines what server to monitor. (by default
<xsd:enumeration value="SAFE" /> <xsd:enumeration value="SAFE" />
<xsd:enumeration value="FSYNC_SAFE" /> <xsd:enumeration value="FSYNC_SAFE" />
<xsd:enumeration value="REPLICA_SAFE" /> <xsd:enumeration value="REPLICA_SAFE" />
<xsd:enumeration value="JOURNAL_SAFE" />
<xsd:enumeration value="MAJORITY" />
</xsd:restriction> </xsd:restriction>
</xsd:simpleType> </xsd:simpleType>
</xsd:attribute> </xsd:attribute>
</xsd:attributeGroup> </xsd:attributeGroup>
-->
<xsd:complexType name="mongoType"> <xsd:complexType name="mongoType">
<xsd:sequence minOccurs="0" maxOccurs="1"> <xsd:sequence minOccurs="0" maxOccurs="1">
<xsd:element name="options" type="optionsType"> <xsd:element name="options" type="optionsType">
@ -288,7 +314,19 @@ The Mongo driver options
</xsd:annotation> </xsd:annotation>
</xsd:element> </xsd:element>
</xsd:sequence> </xsd:sequence>
<xsd:attribute name="write-concern">
<xsd:annotation>
<xsd:documentation>
The WriteConcern that will be the default value used when asking the MongoDbFactory for a DB object
</xsd:documentation>
</xsd:annotation>
<xsd:simpleType>
<xsd:union memberTypes="writeConcernEnumeration xsd:string"/>
</xsd:simpleType>
</xsd:attribute>
<!-- MLP
<xsd:attributeGroup ref="writeConcern" /> <xsd:attributeGroup ref="writeConcern" />
-->
<xsd:attribute name="id" type="xsd:ID" use="optional"> <xsd:attribute name="id" type="xsd:ID" use="optional">
<xsd:annotation> <xsd:annotation>
<xsd:documentation><![CDATA[ <xsd:documentation><![CDATA[

54
spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoDbFactoryParserIntegrationTests.java

@ -18,6 +18,7 @@ package org.springframework.data.mongodb.config;
import static org.hamcrest.Matchers.*; import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*; import static org.junit.Assert.*;
import java.net.UnknownHostException;
import java.util.List; import java.util.List;
import org.junit.Test; import org.junit.Test;
@ -27,12 +28,17 @@ import org.springframework.beans.factory.config.ConstructorArgumentValues;
import org.springframework.beans.factory.config.ConstructorArgumentValues.ValueHolder; import org.springframework.beans.factory.config.ConstructorArgumentValues.ValueHolder;
import org.springframework.beans.factory.parsing.BeanDefinitionParsingException; import org.springframework.beans.factory.parsing.BeanDefinitionParsingException;
import org.springframework.beans.factory.xml.XmlBeanFactory; import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.ClassPathResource;
import org.springframework.data.mongodb.MongoDbFactory; import org.springframework.data.mongodb.MongoDbFactory;
import org.springframework.data.mongodb.core.SimpleMongoDbFactory;
import com.mongodb.DB; import com.mongodb.DB;
import com.mongodb.Mongo; import com.mongodb.Mongo;
import com.mongodb.MongoException;
import com.mongodb.MongoURI; import com.mongodb.MongoURI;
import com.mongodb.WriteConcern;
/** /**
* Integration tests for {@link MongoDbFactoryParser}. * Integration tests for {@link MongoDbFactoryParser}.
@ -41,15 +47,53 @@ import com.mongodb.MongoURI;
*/ */
public class MongoDbFactoryParserIntegrationTests { public class MongoDbFactoryParserIntegrationTests {
@Test
public void testWriteConcern() throws Exception {
SimpleMongoDbFactory dbFactory = new SimpleMongoDbFactory(new Mongo("localhost"), "database");
dbFactory.setWriteConcern(WriteConcern.SAFE);
DB db = dbFactory.getDb();
assertThat(WriteConcern.SAFE, is(dbFactory.getWriteConcern()));
}
@Test @Test
public void parsesWriteConcern() { public void parsesWriteConcern() {
XmlBeanFactory factory = new XmlBeanFactory(new ClassPathResource("namespace/db-factory-bean.xml")); ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("namespace/db-factory-bean.xml");
BeanDefinition definition = factory.getBeanDefinition("first"); assertWriteConcern(ctx, WriteConcern.SAFE);
}
@Test
public void parsesCustomWriteConcern() {
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("namespace/db-factory-bean-custom-write-concern.xml");
assertWriteConcern(ctx, new WriteConcern("rack1"));
}
private void assertWriteConcern(ClassPathXmlApplicationContext ctx, WriteConcern expectedWriteConcern) {
SimpleMongoDbFactory dbFactory = ctx.getBean("first", SimpleMongoDbFactory.class);
DB db = dbFactory.getDb();
assertThat("db", is(db.getName()));
MyWriteConcern myDbFactoryWriteConcern = new MyWriteConcern(dbFactory.getWriteConcern());
MyWriteConcern myDbWriteConcern = new MyWriteConcern(db.getWriteConcern());
MyWriteConcern myExpectedWriteConcern = new MyWriteConcern(expectedWriteConcern);
List<PropertyValue> values = definition.getPropertyValues().getPropertyValueList(); assertThat(myDbFactoryWriteConcern, equalTo(myExpectedWriteConcern));
assertThat(values, hasItem(new PropertyValue("writeConcern", "SAFE"))); assertThat(myDbWriteConcern, equalTo(myExpectedWriteConcern));
assertThat(myDbWriteConcern, equalTo(myDbFactoryWriteConcern));
} }
//This test will fail since equals in WriteConcern uses == for _w and not .equals
public void testWriteConcernEquality() {
String s1 = new String("rack1");
String s2 = new String("rack1");
WriteConcern wc1 = new WriteConcern(s1);
WriteConcern wc2 = new WriteConcern(s2);
assertThat(wc1, equalTo(wc2));
}
@Test @Test
public void createsDbFactoryBean() { public void createsDbFactoryBean() {
XmlBeanFactory factory = new XmlBeanFactory(new ClassPathResource("namespace/db-factory-bean.xml")); XmlBeanFactory factory = new XmlBeanFactory(new ClassPathResource("namespace/db-factory-bean.xml"));
@ -98,7 +142,7 @@ public class MongoDbFactoryParserIntegrationTests {
MongoDbFactory dbFactory = factory.getBean("mongoDbFactory", MongoDbFactory.class); MongoDbFactory dbFactory = factory.getBean("mongoDbFactory", MongoDbFactory.class);
DB db = dbFactory.getDb(); DB db = dbFactory.getDb();
assertThat("database", is(db.getName())); assertThat(db.getName(), is("database"));
} }

56
spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MyWriteConcern.java

@ -0,0 +1,56 @@
package org.springframework.data.mongodb.config;
import com.mongodb.WriteConcern;
public class MyWriteConcern {
public MyWriteConcern(WriteConcern wc) {
this._w = wc.getWObject();
this._continueOnErrorForInsert = wc.getContinueOnErrorForInsert();
this._fsync = wc.getFsync();
this._j = wc.getJ();
this._wtimeout = wc.getWtimeout();
}
Object _w = 0;
int _wtimeout = 0;
boolean _fsync = false;
boolean _j = false;
boolean _continueOnErrorForInsert = false;
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (_continueOnErrorForInsert ? 1231 : 1237);
result = prime * result + (_fsync ? 1231 : 1237);
result = prime * result + (_j ? 1231 : 1237);
result = prime * result + ((_w == null) ? 0 : _w.hashCode());
result = prime * result + _wtimeout;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
MyWriteConcern other = (MyWriteConcern) obj;
if (_continueOnErrorForInsert != other._continueOnErrorForInsert)
return false;
if (_fsync != other._fsync)
return false;
if (_j != other._j)
return false;
if (_w == null) {
if (other._w != null)
return false;
} else if (!_w.equals(other._w))
return false;
if (_wtimeout != other._wtimeout)
return false;
return true;
}
}

24
spring-data-mongodb/src/test/resources/namespace/db-factory-bean-custom-write-concern.xml

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mongo="http://www.springframework.org/schema/data/mongo"
xsi:schemaLocation="http://www.springframework.org/schema/data/mongo http://www.springframework.org/schema/data/mongo/spring-mongo-1.0.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<mongo:db-factory id="first" mongo-ref="mongo" write-concern="rack1" />
<mongo:mongo id="mongo">
<mongo:options max-auto-connect-retry-time="27" />
</mongo:mongo>
<!-- now part of the namespace
<bean class="org.springframework.beans.factory.config.CustomEditorConfigurer">
<property name="customEditors">
<map>
<entry key="com.mongodb.WriteConcern" value="org.springframework.data.mongodb.config.WriteConcernPropertyEditor"/>
</map>
</property>
</bean>
-->
</beans>

15
spring-data-mongodb/src/test/resources/namespace/db-factory-bean.xml

@ -2,12 +2,23 @@
<beans xmlns="http://www.springframework.org/schema/beans" <beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mongo="http://www.springframework.org/schema/data/mongo" xmlns:mongo="http://www.springframework.org/schema/data/mongo"
xsi:schemaLocation="http://www.springframework.org/schema/data/mongo http://www.springframework.org/schema/data/mongo/spring-mongo.xsd xsi:schemaLocation="http://www.springframework.org/schema/data/mongo http://www.springframework.org/schema/data/mongo/spring-mongo-1.0.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<mongo:db-factory id="first" write-concern="SAFE" mongo-ref="mongo" /> <mongo:db-factory id="first" mongo-ref="mongo" write-concern="SAFE" />
<mongo:mongo id="mongo"> <mongo:mongo id="mongo">
<mongo:options max-auto-connect-retry-time="27" /> <mongo:options max-auto-connect-retry-time="27" />
</mongo:mongo> </mongo:mongo>
<!-- now part of the namespace
<bean class="org.springframework.beans.factory.config.CustomEditorConfigurer">
<property name="customEditors">
<map>
<entry key="com.mongodb.WriteConcern" value="org.springframework.data.mongodb.config.WriteConcernPropertyEditor"/>
</map>
</property>
</bean>
-->
</beans> </beans>
Loading…
Cancel
Save