-
Notifications
You must be signed in to change notification settings - Fork 2.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
IT for MongoDB with Panache transaction
- Loading branch information
1 parent
9113938
commit 87a72f9
Showing
11 changed files
with
428 additions
and
7 deletions.
There are no files selected for viewing
14 changes: 14 additions & 0 deletions
14
...db-panache/src/main/java/io/quarkus/it/mongodb/panache/transaction/TransactionPerson.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
package io.quarkus.it.mongodb.panache.transaction; | ||
|
||
import org.bson.codecs.pojo.annotations.BsonId; | ||
|
||
import io.quarkus.mongodb.panache.MongoEntity; | ||
import io.quarkus.mongodb.panache.PanacheMongoEntityBase; | ||
|
||
@MongoEntity(database = "transaction-person") | ||
public class TransactionPerson extends PanacheMongoEntityBase { | ||
@BsonId | ||
public Long id; | ||
public String firstname; | ||
public String lastname; | ||
} |
97 changes: 97 additions & 0 deletions
97
...he/src/main/java/io/quarkus/it/mongodb/panache/transaction/TransactionPersonResource.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
package io.quarkus.it.mongodb.panache.transaction; | ||
|
||
import java.net.URI; | ||
import java.util.ArrayList; | ||
import java.util.List; | ||
|
||
import javax.annotation.PostConstruct; | ||
import javax.inject.Inject; | ||
import javax.inject.Named; | ||
import javax.transaction.Transactional; | ||
import javax.ws.rs.*; | ||
import javax.ws.rs.core.MediaType; | ||
import javax.ws.rs.core.Response; | ||
|
||
import com.mongodb.client.MongoClient; | ||
|
||
@Path("/transaction") | ||
@Produces(MediaType.APPLICATION_JSON) | ||
@Consumes(MediaType.APPLICATION_JSON) | ||
public class TransactionPersonResource { | ||
@Inject | ||
@Named("cl2") | ||
MongoClient mongoClient; | ||
|
||
@PostConstruct | ||
void initDb() { | ||
// in case of transaction, the collection needs to exist prior to using it | ||
if (!mongoClient.getDatabase("transaction-person").listCollectionNames().into(new ArrayList<>()) | ||
.contains("TransactionPerson")) { | ||
mongoClient.getDatabase("transaction-person").createCollection("TransactionPerson"); | ||
} | ||
} | ||
|
||
@GET | ||
@Transactional | ||
public List<TransactionPerson> getPersons() { | ||
return TransactionPerson.listAll(); | ||
} | ||
|
||
@POST | ||
@Transactional | ||
public Response addPerson(TransactionPerson person) { | ||
person.persist(); | ||
return Response.created(URI.create("/transaction/imperative/" + person.id.toString())).build(); | ||
} | ||
|
||
@POST | ||
@Path("/twice") | ||
@Transactional | ||
public void addPersonTwice(TransactionPerson person) { | ||
person.persist(); | ||
person.persist();//this should throw an exception, and the first person should not have been created | ||
} | ||
|
||
@PUT | ||
@Transactional | ||
public Response updatePerson(TransactionPerson person) { | ||
person.update(); | ||
return Response.accepted().build(); | ||
} | ||
|
||
@DELETE | ||
@Path("/{id}") | ||
@Transactional | ||
public void deletePerson(@PathParam("id") String id) { | ||
TransactionPerson person = TransactionPerson.findById(Long.parseLong(id)); | ||
person.delete(); | ||
} | ||
|
||
@GET | ||
@Path("/{id}") | ||
@Transactional | ||
public TransactionPerson getPerson(@PathParam("id") String id) { | ||
return TransactionPerson.findById(Long.parseLong(id)); | ||
} | ||
|
||
@GET | ||
@Path("/count") | ||
@Transactional | ||
public long countAll() { | ||
return TransactionPerson.count(); | ||
} | ||
|
||
@DELETE | ||
@Transactional | ||
public void deleteAll() { | ||
TransactionPerson.deleteAll(); | ||
} | ||
|
||
@POST | ||
@Path("/rename") | ||
@Transactional | ||
public Response rename(@QueryParam("previousName") String previousName, @QueryParam("newName") String newName) { | ||
TransactionPerson.update("lastname", newName).where("lastname", previousName); | ||
return Response.ok().build(); | ||
} | ||
} |
4 changes: 2 additions & 2 deletions
4
integration-tests/mongodb-panache/src/main/resources/application.properties
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
153 changes: 153 additions & 0 deletions
153
...godb-panache/src/test/java/io/quarkus/it/mongodb/panache/MongoReplicaSetTestResource.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,153 @@ | ||
package io.quarkus.it.mongodb.panache; | ||
|
||
import static org.awaitility.Awaitility.await; | ||
|
||
import java.io.IOException; | ||
import java.net.UnknownHostException; | ||
import java.util.ArrayList; | ||
import java.util.Collections; | ||
import java.util.List; | ||
import java.util.Map; | ||
import java.util.concurrent.TimeUnit; | ||
|
||
import org.bson.Document; | ||
import org.jboss.logging.Logger; | ||
|
||
import com.mongodb.ConnectionString; | ||
import com.mongodb.MongoClientSettings; | ||
import com.mongodb.client.MongoClient; | ||
import com.mongodb.client.MongoClients; | ||
import com.mongodb.client.MongoDatabase; | ||
|
||
import de.flapdoodle.embed.mongo.MongodExecutable; | ||
import de.flapdoodle.embed.mongo.MongodStarter; | ||
import de.flapdoodle.embed.mongo.config.IMongodConfig; | ||
import de.flapdoodle.embed.mongo.config.MongoCmdOptionsBuilder; | ||
import de.flapdoodle.embed.mongo.config.MongodConfigBuilder; | ||
import de.flapdoodle.embed.mongo.config.Net; | ||
import de.flapdoodle.embed.mongo.distribution.Version; | ||
import de.flapdoodle.embed.process.runtime.Network; | ||
import io.quarkus.test.common.QuarkusTestResourceLifecycleManager; | ||
|
||
public class MongoReplicaSetTestResource implements QuarkusTestResourceLifecycleManager { | ||
|
||
private static final Logger LOGGER = Logger.getLogger(MongoReplicaSetTestResource.class); | ||
private static List<MongodExecutable> MONGOS = new ArrayList<>(); | ||
|
||
@Override | ||
public Map<String, String> start() { | ||
try { | ||
List<IMongodConfig> configs = new ArrayList<>(); | ||
for (int i = 0; i < 2; i++) { | ||
int port = 27018 + i; | ||
configs.add(buildMongodConfiguration("localhost", port, true)); | ||
} | ||
configs.forEach(config -> { | ||
MongodExecutable exec = MongodStarter.getDefaultInstance().prepare(config); | ||
MONGOS.add(exec); | ||
try { | ||
exec.start(); | ||
} catch (IOException e) { | ||
LOGGER.error("Unable to start the mongo instance", e); | ||
} | ||
}); | ||
initializeReplicaSet(configs); | ||
return Collections.emptyMap(); | ||
} catch (Exception e) { | ||
throw new RuntimeException(e); | ||
} | ||
} | ||
|
||
@Override | ||
public void stop() { | ||
MONGOS.forEach(mongod -> { | ||
try { | ||
mongod.stop(); | ||
} catch (Exception e) { | ||
LOGGER.error("Unable to stop MongoDB", e); | ||
} | ||
}); | ||
} | ||
|
||
private static void initializeReplicaSet(final List<IMongodConfig> mongodConfigList) throws UnknownHostException { | ||
final String arbitrerAddress = "mongodb://" + mongodConfigList.get(0).net().getServerAddress().getHostName() + ":" | ||
+ mongodConfigList.get(0).net().getPort(); | ||
final MongoClientSettings mo = MongoClientSettings.builder() | ||
.applyConnectionString(new ConnectionString(arbitrerAddress)).build(); | ||
|
||
try (MongoClient mongo = MongoClients.create(mo)) { | ||
final MongoDatabase mongoAdminDB = mongo.getDatabase("admin"); | ||
|
||
Document cr = mongoAdminDB.runCommand(new Document("isMaster", 1)); | ||
LOGGER.infof("isMaster: %s", cr); | ||
|
||
// Build replica set configuration settings | ||
final Document rsConfiguration = buildReplicaSetConfiguration(mongodConfigList); | ||
LOGGER.infof("replSetSettings: %s", rsConfiguration); | ||
|
||
// Initialize replica set | ||
cr = mongoAdminDB.runCommand(new Document("replSetInitiate", rsConfiguration)); | ||
LOGGER.infof("replSetInitiate: %s", cr); | ||
|
||
// Check replica set status before to proceed | ||
await() | ||
.pollInterval(100, TimeUnit.MILLISECONDS) | ||
.atMost(1, TimeUnit.MINUTES) | ||
.until(() -> { | ||
Document result = mongoAdminDB.runCommand(new Document("replSetGetStatus", 1)); | ||
LOGGER.infof("replSetGetStatus: %s", result); | ||
return !isReplicaSetStarted(result); | ||
}); | ||
} | ||
} | ||
|
||
private static Document buildReplicaSetConfiguration(final List<IMongodConfig> configList) throws UnknownHostException { | ||
final Document replicaSetSetting = new Document(); | ||
replicaSetSetting.append("_id", "test001"); | ||
|
||
final List<Document> members = new ArrayList<>(); | ||
int i = 0; | ||
for (final IMongodConfig mongoConfig : configList) { | ||
members.add(new Document().append("_id", i++).append("host", | ||
mongoConfig.net().getServerAddress().getHostName() + ":" + mongoConfig.net().getPort())); | ||
} | ||
|
||
replicaSetSetting.append("members", members); | ||
return replicaSetSetting; | ||
} | ||
|
||
private static boolean isReplicaSetStarted(final Document setting) { | ||
if (!setting.containsKey("members")) { | ||
return false; | ||
} | ||
|
||
@SuppressWarnings("unchecked") | ||
final List<Document> members = setting.get("members", List.class); | ||
for (final Document member : members) { | ||
LOGGER.infof("replica set member %s", member); | ||
final int state = member.getInteger("state"); | ||
LOGGER.infof("state: %s", state); | ||
// 1 - PRIMARY, 2 - SECONDARY, 7 - ARBITER | ||
if (state != 1 && state != 2 && state != 7) { | ||
return false; | ||
} | ||
} | ||
return true; | ||
} | ||
|
||
private static IMongodConfig buildMongodConfiguration(String url, int port, final boolean configureReplicaSet) | ||
throws IOException { | ||
final MongodConfigBuilder builder = new MongodConfigBuilder() | ||
.version(Version.Main.V4_0) | ||
.net(new Net(url, port, Network.localhostIsIPv6())); | ||
if (configureReplicaSet) { | ||
builder.withLaunchArgument("--replSet", "test001"); | ||
builder.cmdOptions(new MongoCmdOptionsBuilder() | ||
.syncDelay(5) | ||
.useSmallFiles(true) | ||
.useNoJournal(false) | ||
.build()); | ||
} | ||
return builder.build(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.