DATAMONGO-316 - Replica Set configuration via properties file throws ArrayIndexOutOfBoundsException
This commit is contained in:
@@ -16,9 +16,15 @@
|
||||
|
||||
package org.springframework.data.mongodb.config;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.beans.factory.BeanDefinitionStoreException;
|
||||
import org.springframework.beans.factory.config.CustomEditorConfigurer;
|
||||
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
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.AbstractSingleBeanDefinitionParser;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.data.mongodb.core.MongoFactoryBean;
|
||||
@@ -26,7 +32,7 @@ import org.springframework.util.StringUtils;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
/**
|
||||
* Parser for <mongo;gt; definitions. If no name
|
||||
* Parser for <mongo;gt; definitions.
|
||||
*
|
||||
* @author Mark Pollack
|
||||
*/
|
||||
@@ -39,17 +45,31 @@ public class MongoParser extends AbstractSingleBeanDefinitionParser {
|
||||
|
||||
@Override
|
||||
protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
|
||||
super.doParse(element, builder);
|
||||
|
||||
ParsingUtils.setPropertyValue(element, builder, "port", "port");
|
||||
ParsingUtils.setPropertyValue(element, builder, "host", "host");
|
||||
ParsingUtils.setPropertyValue(element, builder, "write-concern", "writeConcern");
|
||||
|
||||
ParsingUtils.parseMongoOptions(parserContext, element, builder);
|
||||
ParsingUtils.parseReplicaSet(parserContext, element, builder);
|
||||
ParsingUtils.parseMongoOptions(element, builder);
|
||||
ParsingUtils.parseReplicaSet(element, builder);
|
||||
|
||||
registerCustomEditorConfigurer(parserContext.getRegistry());
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* One should only register one bean definition but want to have the convenience of using AbstractSingleBeanDefinitionParser but have the side effect of
|
||||
* registering a 'default' property editor with the container.
|
||||
* @param parserContext the ParserContext to
|
||||
*/
|
||||
private void registerCustomEditorConfigurer(BeanDefinitionRegistry registry) {
|
||||
BeanDefinitionBuilder customEditorConfigurer = BeanDefinitionBuilder.genericBeanDefinition(CustomEditorConfigurer.class);
|
||||
Map<String, String> customEditors = new ManagedMap<String, String>();
|
||||
customEditors.put("java.util.List", "org.springframework.data.mongodb.config.ServerAddressPropertyEditor");
|
||||
customEditorConfigurer.addPropertyValue("customEditors", customEditors);
|
||||
BeanDefinitionReaderUtils.registerWithGeneratedName(customEditorConfigurer.getBeanDefinition(), registry);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String resolveId(Element element, AbstractBeanDefinition definition, ParserContext parserContext)
|
||||
throws BeanDefinitionStoreException {
|
||||
|
||||
@@ -19,15 +19,12 @@ package org.springframework.data.mongodb.config;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.support.ManagedList;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.data.mongodb.core.MongoOptionsFactoryBean;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.util.xml.DomUtils;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import com.mongodb.ServerAddress;
|
||||
|
||||
abstract class ParsingUtils {
|
||||
|
||||
/**
|
||||
@@ -38,22 +35,11 @@ abstract class ParsingUtils {
|
||||
* @param mongoBuilder the bean definition builder to populate
|
||||
* @return true if parsing actually occured, false otherwise
|
||||
*/
|
||||
static boolean parseReplicaSet(ParserContext parserContext, Element element, BeanDefinitionBuilder mongoBuilder) {
|
||||
static boolean parseReplicaSet(Element element, BeanDefinitionBuilder mongoBuilder) {
|
||||
|
||||
String replicaSetString = element.getAttribute("replica-set");
|
||||
if (StringUtils.hasText(replicaSetString)) {
|
||||
ManagedList<Object> serverAddresses = new ManagedList<Object>();
|
||||
String[] replicaSetStringArray = StringUtils.commaDelimitedListToStringArray(replicaSetString);
|
||||
for (String element2 : replicaSetStringArray) {
|
||||
String[] hostAndPort = StringUtils.delimitedListToStringArray(element2, ":");
|
||||
BeanDefinitionBuilder defBuilder = BeanDefinitionBuilder.genericBeanDefinition(ServerAddress.class);
|
||||
defBuilder.addConstructorArgValue(hostAndPort[0]);
|
||||
defBuilder.addConstructorArgValue(hostAndPort[1]);
|
||||
serverAddresses.add(defBuilder.getBeanDefinition());
|
||||
}
|
||||
if (!serverAddresses.isEmpty()) {
|
||||
mongoBuilder.addPropertyValue("replicaSetSeeds", serverAddresses);
|
||||
}
|
||||
mongoBuilder.addPropertyValue("replicaSetSeeds", replicaSetString);
|
||||
}
|
||||
return true;
|
||||
|
||||
@@ -64,7 +50,7 @@ abstract class ParsingUtils {
|
||||
*
|
||||
* @return true if parsing actually occured, false otherwise
|
||||
*/
|
||||
static boolean parseMongoOptions(ParserContext parserContext, Element element, BeanDefinitionBuilder mongoBuilder) {
|
||||
static boolean parseMongoOptions(Element element, BeanDefinitionBuilder mongoBuilder) {
|
||||
Element optionsElement = DomUtils.getChildElementByTagName(element, "options");
|
||||
if (optionsElement == null) {
|
||||
return false;
|
||||
|
||||
@@ -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;
|
||||
|
||||
/**
|
||||
* Parse a string to a List<ServerAddress>. The format is host1:port1,host2:port2,host3:port3.
|
||||
* @author Mark Pollack
|
||||
*
|
||||
*/
|
||||
public class ServerAddressPropertyEditor extends PropertyEditorSupport {
|
||||
|
||||
/**
|
||||
* Parse a string to a List<ServerAddress>
|
||||
*/
|
||||
public void setAsText(String replicaSetString) {
|
||||
|
||||
List<ServerAddress> serverAddresses = new ArrayList<ServerAddress>();
|
||||
String[] replicaSetStringArray = StringUtils.commaDelimitedListToStringArray(replicaSetString);
|
||||
for (String element2 : replicaSetStringArray) {
|
||||
String[] hostAndPort = StringUtils.delimitedListToStringArray(element2, ":");
|
||||
try {
|
||||
serverAddresses.add(new ServerAddress(hostAndPort[0], Integer.parseInt(hostAndPort[1])));
|
||||
} catch (NumberFormatException e) {
|
||||
throw new IllegalArgumentException("Could not parse port " + hostAndPort[1], e );
|
||||
} catch (UnknownHostException e) {
|
||||
throw new IllegalArgumentException("Could not parse host " + hostAndPort[0], e );
|
||||
}
|
||||
}
|
||||
setValue(serverAddresses);
|
||||
}
|
||||
}
|
||||
@@ -45,18 +45,35 @@ public class MongoNamespaceReplicaSetTests extends NamespaceTestSupport {
|
||||
public void testParsingMongoWithReplicaSets() throws Exception {
|
||||
assertTrue(ctx.containsBean("replicaSetMongo"));
|
||||
MongoFactoryBean mfb = (MongoFactoryBean) ctx.getBean("&replicaSetMongo");
|
||||
|
||||
|
||||
List<ServerAddress> replicaSetSeeds = readField("replicaSetSeeds", mfb);
|
||||
assertNotNull(replicaSetSeeds);
|
||||
|
||||
|
||||
assertEquals("127.0.0.1", replicaSetSeeds.get(0).getHost());
|
||||
assertEquals(10001, replicaSetSeeds.get(0).getPort());
|
||||
|
||||
assertEquals("localhost", replicaSetSeeds.get(1).getHost());
|
||||
assertEquals(10002, replicaSetSeeds.get(1).getPort());
|
||||
|
||||
|
||||
assertEquals("localhost", replicaSetSeeds.get(1).getHost());
|
||||
assertEquals(10002, replicaSetSeeds.get(1).getPort());
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testParsingWithPropertyPlaceHolder() throws Exception {
|
||||
assertTrue(ctx.containsBean("manyReplicaSetMongo"));
|
||||
MongoFactoryBean mfb = (MongoFactoryBean) ctx.getBean("&manyReplicaSetMongo");
|
||||
|
||||
List<ServerAddress> replicaSetSeeds = readField("replicaSetSeeds", mfb);
|
||||
assertNotNull(replicaSetSeeds);
|
||||
|
||||
assertEquals("192.168.174.130", replicaSetSeeds.get(0).getHost());
|
||||
assertEquals(27017, replicaSetSeeds.get(0).getPort());
|
||||
assertEquals("192.168.174.130", replicaSetSeeds.get(1).getHost());
|
||||
assertEquals(27018, replicaSetSeeds.get(1).getPort());
|
||||
assertEquals("192.168.174.130", replicaSetSeeds.get(2).getHost());
|
||||
assertEquals(27019, replicaSetSeeds.get(2).getPort());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore("CI infrastructure does not yet support replica sets")
|
||||
public void testMongoWithReplicaSets() {
|
||||
@@ -67,10 +84,10 @@ public class MongoNamespaceReplicaSetTests extends NamespaceTestSupport {
|
||||
assertEquals("localhost", servers.get(1).getHost());
|
||||
assertEquals(10001, servers.get(0).getPort());
|
||||
assertEquals(10002, servers.get(1).getPort());
|
||||
|
||||
|
||||
MongoTemplate template = new MongoTemplate(mongo, "admin");
|
||||
CommandResult result = template.executeCommand("{replSetGetStatus : 1}");
|
||||
assertEquals("blort", result.getString("set"));
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,11 @@
|
||||
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
|
||||
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
|
||||
|
||||
|
||||
<context:property-placeholder location="classpath:replicaSet.properties"/>
|
||||
|
||||
<mongo:mongo id="manyReplicaSetMongo" replica-set="${mongo.hosts}"/>
|
||||
|
||||
<mongo:mongo id="replicaSetMongo" replica-set="127.0.0.1:10001,localhost:10002"/>
|
||||
|
||||
<!--
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
mongo.hosts=192.168.174.130:27017,192.168.174.130:27018,192.168.174.130:27019
|
||||
Reference in New Issue
Block a user