diff --git a/mongodb/pom.xml b/mongodb/pom.xml
index 5fe2180c..f7788b91 100644
--- a/mongodb/pom.xml
+++ b/mongodb/pom.xml
@@ -28,6 +28,7 @@
security
text-search
transactions
+ util
@@ -56,7 +57,7 @@
de.flapdoodle.embed
de.flapdoodle.embed.mongo
- runtime
+ provided
diff --git a/mongodb/transactions/pom.xml b/mongodb/transactions/pom.xml
index 1b7d6d19..c06f8297 100644
--- a/mongodb/transactions/pom.xml
+++ b/mongodb/transactions/pom.xml
@@ -1,72 +1,56 @@
- 4.0.0
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ 4.0.0
-
- org.springframework.data.examples
- spring-data-mongodb-examples
- 2.0.0.BUILD-SNAPSHOT
-
+
+ org.springframework.data.examples
+ spring-data-mongodb-examples
+ 2.0.0.BUILD-SNAPSHOT
+
- spring-data-mongodb-transactions
- Spring Data MongoDB - Transactions
+ spring-data-mongodb-transactions
+ Spring Data MongoDB - Transactions
-
+
+ 3.8.0-beta2
+ 1.9.0-beta1
+ Lovelace-M3
+
-
- org.springframework.boot
- spring-boot-starter-data-mongodb-reactive
-
-
- org.mongodb
- mongodb-driver
-
-
-
+
-
- org.springframework.data
- spring-data-mongodb
- 2.1.0.BUILD-SNAPSHOT
-
+
-
- org.springframework.data
- spring-data-commons
- 2.1.0.BUILD-SNAPSHOT
-
+
+ spring-data-next
+
+ Lovelace-M3
+
+
-
- org.mongodb
- mongo-java-driver
- 3.8.0-beta2
-
+
-
- org.mongodb
- mongodb-driver-async
- 3.8.0-beta2
-
+
-
- org.mongodb
- mongodb-driver-reactivestreams
- 1.9.0-beta1
-
+
+ org.springframework.boot
+ spring-boot-starter-data-mongodb-reactive
+
-
- io.projectreactor
- reactor-core
- 3.1.7.RELEASE
-
+
+ ${project.groupId}
+ spring-data-mongodb-example-utils
+ ${project.version}
+ test
+
-
- io.projectreactor
- reactor-test
- 3.1.7.RELEASE
- test
-
+
+ io.projectreactor
+ reactor-test
+ 3.1.7.RELEASE
+ test
+
-
+
diff --git a/mongodb/transactions/src/main/java/example/springdata/mongodb/reactive/ReactiveTransitionService.java b/mongodb/transactions/src/main/java/example/springdata/mongodb/reactive/ReactiveTransitionService.java
index 4ff966bf..126a3406 100644
--- a/mongodb/transactions/src/main/java/example/springdata/mongodb/reactive/ReactiveTransitionService.java
+++ b/mongodb/transactions/src/main/java/example/springdata/mongodb/reactive/ReactiveTransitionService.java
@@ -53,7 +53,7 @@ public class ReactiveTransitionService {
return lookup(id) //
.flatMap(process -> start(action, process)) //
- .flatMap(this::verify) //
+ .flatMap(it -> verify(it)) //
.flatMap(process -> finish(action, process));
}).next().map(Process::getId);
diff --git a/mongodb/transactions/src/test/java/example/springdata/mongodb/reactive/ReactiveTransitionServiceTests.java b/mongodb/transactions/src/test/java/example/springdata/mongodb/reactive/ReactiveTransitionServiceTests.java
index 26c14c10..c75eacc6 100644
--- a/mongodb/transactions/src/test/java/example/springdata/mongodb/reactive/ReactiveTransitionServiceTests.java
+++ b/mongodb/transactions/src/test/java/example/springdata/mongodb/reactive/ReactiveTransitionServiceTests.java
@@ -19,9 +19,9 @@ import static org.assertj.core.api.Assertions.*;
import example.springdata.mongodb.Process;
import example.springdata.mongodb.State;
+import example.springdata.mongodb.util.EmbeddedMongo;
import reactor.core.publisher.Flux;
import reactor.test.StepVerifier;
-import utils.EmbeddedMongo;
import org.bson.Document;
import org.junit.ClassRule;
@@ -40,6 +40,8 @@ import com.mongodb.reactivestreams.client.MongoClient;
import com.mongodb.reactivestreams.client.MongoClients;
/**
+ * Test showing MongoDB Transaction usage through a reactive API.
+ *
* @author Christoph Strobl
* @currentRead The Core - Peter V. Brett
*/
diff --git a/mongodb/transactions/src/test/java/example/springdata/mongodb/sync/TransitionServiceTests.java b/mongodb/transactions/src/test/java/example/springdata/mongodb/sync/TransitionServiceTests.java
index 89efbc60..61f8fd94 100644
--- a/mongodb/transactions/src/test/java/example/springdata/mongodb/sync/TransitionServiceTests.java
+++ b/mongodb/transactions/src/test/java/example/springdata/mongodb/sync/TransitionServiceTests.java
@@ -17,7 +17,7 @@ package example.springdata.mongodb.sync;
import example.springdata.mongodb.Process;
import example.springdata.mongodb.State;
-import utils.EmbeddedMongo;
+import example.springdata.mongodb.util.EmbeddedMongo;
import java.util.function.Consumer;
@@ -36,6 +36,7 @@ import org.springframework.data.mongodb.config.AbstractMongoConfiguration;
import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@@ -44,10 +45,13 @@ import com.mongodb.client.model.Filters;
import com.mongodb.client.model.Projections;
/**
+ * Test showing MongoDB Transaction usage through a synchronous (imperative) API using Spring's managed transactions.
+ *
* @author Christoph Strobl
* @currentRead The Core - Peter V. Brett
+ * @see org.springframework.transaction.annotation.Transactional
*/
-@RunWith(SpringJUnit4ClassRunner.class)
+@RunWith(SpringRunner.class)
@ContextConfiguration
public class TransitionServiceTests {
diff --git a/mongodb/transactions/src/test/resources/logback.xml b/mongodb/transactions/src/test/resources/logback.xml
index 7869183a..910b1b43 100644
--- a/mongodb/transactions/src/test/resources/logback.xml
+++ b/mongodb/transactions/src/test/resources/logback.xml
@@ -7,7 +7,7 @@
-
+
diff --git a/mongodb/util/pom.xml b/mongodb/util/pom.xml
new file mode 100644
index 00000000..8d47af8a
--- /dev/null
+++ b/mongodb/util/pom.xml
@@ -0,0 +1,28 @@
+
+ 4.0.0
+
+
+ org.springframework.data.examples
+ spring-data-mongodb-examples
+ 2.0.0.BUILD-SNAPSHOT
+
+
+ spring-data-mongodb-example-utils
+ Spring Data MongoDB - Example Utilities
+
+
+
+
+ junit
+ junit
+
+
+
+ org.mongodb
+ mongo-java-driver
+
+
+
+
+
diff --git a/mongodb/transactions/src/test/java/utils/EmbeddedMongo.java b/mongodb/util/src/main/java/example/springdata/mongodb/util/EmbeddedMongo.java
similarity index 76%
rename from mongodb/transactions/src/test/java/utils/EmbeddedMongo.java
rename to mongodb/util/src/main/java/example/springdata/mongodb/util/EmbeddedMongo.java
index 26e09da1..cef508a2 100644
--- a/mongodb/transactions/src/test/java/utils/EmbeddedMongo.java
+++ b/mongodb/util/src/main/java/example/springdata/mongodb/util/EmbeddedMongo.java
@@ -13,8 +13,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package utils;
+package example.springdata.mongodb.util;
+import de.flapdoodle.embed.mongo.Command;
import de.flapdoodle.embed.mongo.config.IMongoCmdOptions;
import de.flapdoodle.embed.mongo.config.IMongodConfig;
import de.flapdoodle.embed.mongo.config.IMongosConfig;
@@ -26,8 +27,9 @@ import de.flapdoodle.embed.mongo.config.Storage;
import de.flapdoodle.embed.mongo.distribution.Feature;
import de.flapdoodle.embed.mongo.distribution.IFeatureAwareVersion;
import de.flapdoodle.embed.mongo.distribution.Versions;
-import de.flapdoodle.embed.mongo.tests.MongosSystemForTestFactory;
+import de.flapdoodle.embed.process.config.io.ProcessOutput;
import de.flapdoodle.embed.process.distribution.GenericVersion;
+import de.flapdoodle.embed.process.io.Processors;
import de.flapdoodle.embed.process.runtime.Network;
import java.io.IOException;
@@ -37,6 +39,7 @@ import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
+import java.util.function.Function;
import org.junit.rules.ExternalResource;
import org.slf4j.Logger;
@@ -48,7 +51,10 @@ import com.mongodb.MongoClient;
import com.mongodb.MongoClientURI;
/**
+ * {@link org.junit.rules.TestRule} for a MongoDB server resource that is started/stopped along the test lifecycle.
+ *
* @author Christoph Strobl
+ * @author Mark Paluch
*/
public class EmbeddedMongo extends ExternalResource {
@@ -70,10 +76,20 @@ public class EmbeddedMongo extends ExternalResource {
this.resource = resource;
}
+ /**
+ * Create a new {@link Builder} to build {@link EmbeddedMongo}.
+ *
+ * @return
+ */
public static Builder builder() {
return new Builder();
}
+ /**
+ * Create a new {@link Builder} that is initialized as replica set to build {@link EmbeddedMongo}.
+ *
+ * @return
+ */
public static Builder replSet() {
return replSet(DEFAULT_REPLICA_SET_NAME);
}
@@ -82,12 +98,16 @@ public class EmbeddedMongo extends ExternalResource {
return new Builder().withReplicaSetName(replicaSetName);
}
+ /**
+ * {@link Builder} for {@link EmbeddedMongo}.
+ */
public static class Builder {
IFeatureAwareVersion version;
String replicaSetName;
List serverPorts;
List configServerPorts;
+ boolean silent = true;
Builder() {
@@ -97,30 +117,62 @@ public class EmbeddedMongo extends ExternalResource {
configServerPorts = Collections.emptyList();
}
+ /**
+ * Configure the MongoDB {@link IFeatureAwareVersion version}.
+ *
+ * @param version
+ * @return
+ */
public Builder withVersion(IFeatureAwareVersion version) {
this.version = version;
return this;
}
+ /**
+ * Configure the replica set name.
+ *
+ * @param version
+ * @return
+ */
public Builder withReplicaSetName(String replicaSetName) {
this.replicaSetName = replicaSetName;
return this;
}
+ /**
+ * Configure the server ports.
+ *
+ * @param version
+ * @return
+ */
public Builder withServerPorts(Integer... ports) {
this.serverPorts = Arrays.asList(ports);
return this;
}
+ /**
+ * Configure whether to stay silent (stream only Mongo process errors to stdout) or to stream all process output to
+ * stdout. By default, only process errors are forwarded to stdout.
+ *
+ * @param silent
+ * @return
+ */
+ public Builder withSilent(boolean silent) {
+
+ this.silent = silent;
+ return this;
+ }
+
public EmbeddedMongo configure() {
if (serverPorts.size() > 1 || StringUtils.hasText(replicaSetName)) {
String rsName = StringUtils.hasText(replicaSetName) ? replicaSetName : DEFAULT_REPLICA_SET_NAME;
- return new EmbeddedMongo(new ReplSet(version, rsName, serverPorts.toArray(new Integer[serverPorts.size()])));
+ return new EmbeddedMongo(
+ new ReplSet(version, rsName, silent, serverPorts.toArray(new Integer[serverPorts.size()])));
}
throw new UnsupportedOperationException("implement me");
@@ -155,12 +207,24 @@ public class EmbeddedMongo extends ExternalResource {
}
}
+ /**
+ * Interface specifying a test resource which exposes lifecycle methods and connection coordinates.
+ */
interface TestResource {
+ /**
+ * Start the resource.
+ */
void start();
+ /**
+ * Stop the resource.
+ */
void stop();
+ /**
+ * @return the connection string to configure a MongoDB client.
+ */
String connectionString();
default MongoClient mongoClient() {
@@ -179,10 +243,11 @@ public class EmbeddedMongo extends ExternalResource {
private final int mongosPort;
private final Integer[] serverPorts;
private final Integer[] configServerPorts;
+ private final Function outputFunction;
private MongosSystemForTestFactory mongosTestFactory;
- ReplSet(IFeatureAwareVersion serverVersion, String replicaSetName, Integer... serverPorts) {
+ ReplSet(IFeatureAwareVersion serverVersion, String replicaSetName, boolean silent, Integer... serverPorts) {
this.serverVersion = serverVersion;
this.replicaSetName = replicaSetName;
@@ -190,6 +255,13 @@ public class EmbeddedMongo extends ExternalResource {
this.configServerPorts = defaultPortsIfRequired(null);
this.configServerReplicaSetName = DEFAULT_CONFIG_SERVER_REPLICA_SET_NAME;
this.mongosPort = randomOrDefaultServerPort();
+
+ if (silent) {
+ outputFunction = it -> new ProcessOutput(Processors.silent(),
+ Processors.namedConsole("[ " + it.commandName() + " error]"), Processors.console());
+ } else {
+ outputFunction = it -> ProcessOutput.getDefaultInstance(it.commandName());
+ }
}
Integer[] defaultPortsIfRequired(Integer[] ports) {
@@ -226,7 +298,7 @@ public class EmbeddedMongo extends ExternalResource {
configServerReplicaSetName, configServerPorts[0]);
mongosTestFactory = new MongosSystemForTestFactory(mongosConfig, replicaSets, Collections.emptyList(),
- DEFAULT_SHARDING, DEFAULT_SHARDING, DEFAULT_SHARD_KEY);
+ DEFAULT_SHARDING, DEFAULT_SHARDING, DEFAULT_SHARD_KEY, outputFunction);
try {
LOGGER.info(String.format("Starting config servers at ports %s",
@@ -244,15 +316,17 @@ public class EmbeddedMongo extends ExternalResource {
}
private List initReplicaSet() {
- List replicaSet1 = new ArrayList<>();
+
+ List rs = new ArrayList<>();
for (int port : serverPorts) {
- replicaSet1.add(defaultMongodConfig(serverVersion, port, defaultCommandOptions(), false, true, replicaSetName));
+ rs.add(defaultMongodConfig(serverVersion, port, defaultCommandOptions(), false, true, replicaSetName));
}
- return replicaSet1;
+ return rs;
}
private List initConfigServers() {
+
List configServers = new ArrayList<>(configServerPorts.length);
for (Integer port : configServerPorts) {
@@ -280,6 +354,9 @@ public class EmbeddedMongo extends ExternalResource {
}
}
+ /**
+ * @return Default {@link IMongoCmdOptions command options}.
+ */
private static IMongoCmdOptions defaultCommandOptions() {
return new MongoCmdOptionsBuilder() //
@@ -291,12 +368,25 @@ public class EmbeddedMongo extends ExternalResource {
.build();
}
+ /**
+ * Create a default {@code mongod} config.
+ *
+ * @param version
+ * @param port
+ * @param cmdOptions
+ * @param configServer
+ * @param shardServer
+ * @param replicaSet
+ * @return
+ */
private static IMongodConfig defaultMongodConfig(IFeatureAwareVersion version, int port, IMongoCmdOptions cmdOptions,
boolean configServer, boolean shardServer, String replicaSet) {
try {
+
MongodConfigBuilder builder = new MongodConfigBuilder() //
.version(version) //
+ .withLaunchArgument("--quiet") //
.net(new Net(LOCALHOST, port, Network.localhostIsIPv6())) //
.configServer(configServer).cmdOptions(cmdOptions); //
@@ -318,12 +408,24 @@ public class EmbeddedMongo extends ExternalResource {
}
}
+ /**
+ * Create a default {@code mongos} config.
+ *
+ * @param version
+ * @param port
+ * @param cmdOptions
+ * @param configServerReplicaSet
+ * @param configServerPort
+ * @return
+ */
private static IMongosConfig defaultMongosConfig(IFeatureAwareVersion version, int port, IMongoCmdOptions cmdOptions,
String configServerReplicaSet, int configServerPort) {
try {
+
MongosConfigBuilder builder = new MongosConfigBuilder() //
.version(version) //
+ .withLaunchArgument("--quiet", null) //
.net(new Net(LOCALHOST, port, Network.localhostIsIPv6())) //
.cmdOptions(cmdOptions);
diff --git a/mongodb/util/src/main/java/example/springdata/mongodb/util/MongosSystemForTestFactory.java b/mongodb/util/src/main/java/example/springdata/mongodb/util/MongosSystemForTestFactory.java
new file mode 100644
index 00000000..0dc39091
--- /dev/null
+++ b/mongodb/util/src/main/java/example/springdata/mongodb/util/MongosSystemForTestFactory.java
@@ -0,0 +1,280 @@
+/*
+ * Copyright 2018 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 example.springdata.mongodb.util;
+
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Function;
+import java.util.Map.Entry;
+
+import com.mongodb.*;
+import de.flapdoodle.embed.process.config.IRuntimeConfig;
+import de.flapdoodle.embed.process.config.io.ProcessOutput;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import de.flapdoodle.embed.mongo.Command;
+import de.flapdoodle.embed.mongo.MongodExecutable;
+import de.flapdoodle.embed.mongo.MongodProcess;
+import de.flapdoodle.embed.mongo.MongodStarter;
+import de.flapdoodle.embed.mongo.MongosExecutable;
+import de.flapdoodle.embed.mongo.MongosProcess;
+import de.flapdoodle.embed.mongo.MongosStarter;
+import de.flapdoodle.embed.mongo.config.IMongodConfig;
+import de.flapdoodle.embed.mongo.config.IMongosConfig;
+import de.flapdoodle.embed.mongo.config.RuntimeConfigBuilder;
+
+class MongosSystemForTestFactory {
+
+ private final static Logger logger = LoggerFactory
+ .getLogger(MongosSystemForTestFactory.class);
+
+ public static final String ADMIN_DATABASE_NAME = "admin";
+ public static final String LOCAL_DATABASE_NAME = "local";
+ public static final String REPLICA_SET_NAME = "rep1";
+ public static final String OPLOG_COLLECTION = "oplog.rs";
+
+ private final IMongosConfig config;
+ private final Map> replicaSets;
+ private final List configServers;
+ private final String shardDatabase;
+ private final String shardCollection;
+ private final String shardKey;
+ private final Function outputFunction;
+
+ private MongosExecutable mongosExecutable;
+ private MongosProcess mongosProcess;
+ private List mongodProcessList;
+ private List mongodConfigProcessList;
+
+ public MongosSystemForTestFactory(IMongosConfig config,
+ Map> replicaSets,
+ List configServers, String shardDatabase,
+ String shardCollection, String shardKey, Function outputFunction) {
+ this.config = config;
+ this.replicaSets = replicaSets;
+ this.configServers = configServers;
+ this.shardDatabase = shardDatabase;
+ this.shardCollection = shardCollection;
+ this.shardKey = shardKey;
+ this.outputFunction = outputFunction;
+ }
+
+ public void start() throws Throwable {
+ this.mongodProcessList = new ArrayList<>();
+ this.mongodConfigProcessList = new ArrayList<>();
+ for (Entry> entry : replicaSets.entrySet()) {
+ initializeReplicaSet(entry);
+ }
+ for (IMongodConfig config : configServers) {
+ initializeConfigServer(config);
+ }
+ initializeMongos();
+ configureMongos();
+ }
+
+ private void initializeReplicaSet(Entry> entry)
+ throws Exception {
+ String replicaName = entry.getKey();
+ List mongoConfigList = entry.getValue();
+
+ if (mongoConfigList.size() < 3) {
+ throw new Exception(
+ "A replica set must contain at least 3 members.");
+ }
+ // Create 3 mongod processes
+ for (IMongodConfig mongoConfig : mongoConfigList) {
+ if (!mongoConfig.replication().getReplSetName().equals(replicaName)) {
+ throw new Exception(
+ "Replica set name must match in mongo configuration");
+ }
+ IRuntimeConfig runtimeConfig = new RuntimeConfigBuilder()
+ .defaultsWithLogger(Command.MongoD,logger)
+ .processOutput(outputFunction.apply(Command.MongoD))
+ .build();
+ MongodStarter starter = MongodStarter.getInstance(runtimeConfig);
+ MongodExecutable mongodExe = starter.prepare(mongoConfig);
+ MongodProcess process = mongodExe.start();
+ mongodProcessList.add(process);
+ }
+ Thread.sleep(1000);
+ MongoClientOptions mo = MongoClientOptions.builder()
+ .connectTimeout(10)
+ .build();
+ MongoClient mongo = new MongoClient(new ServerAddress(mongoConfigList.get(0).net()
+ .getServerAddress().getHostName(), mongoConfigList.get(0).net()
+ .getPort()), mo);
+ DB mongoAdminDB = mongo.getDB(ADMIN_DATABASE_NAME);
+
+ CommandResult cr = mongoAdminDB
+ .command(new BasicDBObject("isMaster", 1));
+ logger.info("isMaster: {}", cr);
+
+ // Build BSON object replica set settings
+ DBObject replicaSetSetting = new BasicDBObject();
+ replicaSetSetting.put("_id", replicaName);
+ BasicDBList members = new BasicDBList();
+ int i = 0;
+ for (IMongodConfig mongoConfig : mongoConfigList) {
+ DBObject host = new BasicDBObject();
+ host.put("_id", i++);
+ host.put("host", mongoConfig.net().getServerAddress().getHostName()
+ + ":" + mongoConfig.net().getPort());
+ members.add(host);
+ }
+
+ replicaSetSetting.put("members", members);
+ logger.info(replicaSetSetting.toString());
+ // Initialize replica set
+ cr = mongoAdminDB.command(new BasicDBObject("replSetInitiate",
+ replicaSetSetting));
+ logger.info("replSetInitiate: {}", cr);
+
+ Thread.sleep(5000);
+ cr = mongoAdminDB.command(new BasicDBObject("replSetGetStatus", 1));
+ logger.info("replSetGetStatus: {}", cr);
+
+ // Check replica set status before to proceed
+ while (!isReplicaSetStarted(cr)) {
+ logger.info("Waiting for 3 seconds...");
+ Thread.sleep(1000);
+ cr = mongoAdminDB.command(new BasicDBObject("replSetGetStatus", 1));
+ logger.info("replSetGetStatus: {}", cr);
+ }
+
+ mongo.close();
+ mongo = null;
+ }
+
+ private boolean isReplicaSetStarted(BasicDBObject setting) {
+ if (setting.get("members") == null) {
+ return false;
+ }
+
+ BasicDBList members = (BasicDBList) setting.get("members");
+ for (Object m : members.toArray()) {
+ BasicDBObject member = (BasicDBObject) m;
+ logger.info(member.toString());
+ int state = member.getInt("state");
+ logger.info("state: {}", state);
+ // 1 - PRIMARY, 2 - SECONDARY, 7 - ARBITER
+ if (state != 1 && state != 2 && state != 7) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private void initializeConfigServer(IMongodConfig config) throws Exception {
+ if (!config.isConfigServer()) {
+ throw new Exception(
+ "Mongo configuration is not a defined for a config server.");
+ }
+ MongodStarter starter = MongodStarter.getDefaultInstance();
+ MongodExecutable mongodExe = starter.prepare(config);
+ MongodProcess process = mongodExe.start();
+ mongodProcessList.add(process);
+ }
+
+ private void initializeMongos() throws Exception {
+ MongosStarter runtime = MongosStarter.getInstance(new RuntimeConfigBuilder()
+ .defaultsWithLogger(Command.MongoS,logger)
+ .processOutput(outputFunction.apply(Command.MongoS))
+ .build());
+
+ mongosExecutable = runtime.prepare(config);
+ mongosProcess = mongosExecutable.start();
+ }
+
+ private void configureMongos() throws Exception {
+ CommandResult cr;
+ MongoClientOptions options = MongoClientOptions.builder()
+ .connectTimeout(10)
+ .build();
+ try (MongoClient mongo = new MongoClient(
+ new ServerAddress(this.config.net().getServerAddress()
+ .getHostName(), this.config.net().getPort()), options)) {
+ DB mongoAdminDB = mongo.getDB(ADMIN_DATABASE_NAME);
+
+ // Add shard from the replica set list
+ for (Entry> entry : this.replicaSets
+ .entrySet()) {
+ String replicaName = entry.getKey();
+ String command = "";
+ for (IMongodConfig mongodConfig : entry.getValue()) {
+ if (command.isEmpty()) {
+ command = replicaName + "/";
+ } else {
+ command += ",";
+ }
+ command += mongodConfig.net().getServerAddress().getHostName()
+ + ":" + mongodConfig.net().getPort();
+ }
+ logger.info("Execute add shard command: {}", command);
+ cr = mongoAdminDB.command(new BasicDBObject("addShard", command));
+ logger.info(cr.toString());
+ }
+
+ logger.info("Execute list shards.");
+ cr = mongoAdminDB.command(new BasicDBObject("listShards", 1));
+ logger.info(cr.toString());
+
+ // Enabled sharding at database level
+ logger.info("Enabled sharding at database level");
+ cr = mongoAdminDB.command(new BasicDBObject("enableSharding",
+ this.shardDatabase));
+ logger.info(cr.toString());
+
+ // Create index in sharded collection
+ logger.info("Create index in sharded collection");
+ DB db = mongo.getDB(this.shardDatabase);
+ db.getCollection(this.shardCollection).createIndex(this.shardKey);
+
+ // Shard the collection
+ logger.info("Shard the collection: {}.{}", this.shardDatabase, this.shardCollection);
+ DBObject cmd = new BasicDBObject();
+ cmd.put("shardCollection", this.shardDatabase + "." + this.shardCollection);
+ cmd.put("key", new BasicDBObject(this.shardKey, 1));
+ cr = mongoAdminDB.command(cmd);
+ logger.info(cr.toString());
+
+ logger.info("Get info from config/shards");
+ DBCursor cursor = mongo.getDB("config").getCollection("shards").find();
+ while (cursor.hasNext()) {
+ DBObject item = cursor.next();
+ logger.info(item.toString());
+ }
+ }
+
+ }
+
+ public Mongo getMongo() throws UnknownHostException, MongoException {
+ return new MongoClient(new ServerAddress(mongosProcess.getConfig().net()
+ .getServerAddress(), mongosProcess.getConfig().net().getPort()));
+ }
+
+ public void stop() {
+ for (MongodProcess process : this.mongodProcessList) {
+ process.stop();
+ }
+ for (MongodProcess process : this.mongodConfigProcessList) {
+ process.stop();
+ }
+ this.mongosProcess.stop();
+ }
+}