committed by
Mark Paluch
parent
e2b388e6b9
commit
e59e147d6f
@@ -31,12 +31,6 @@
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>de.flapdoodle.embed</groupId>
|
||||
<artifactId>de.flapdoodle.embed.mongo</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
|
||||
@@ -29,7 +29,5 @@ import org.springframework.data.mongodb.core.mapping.Field;
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
record Person(@Id ObjectId id, @Field("first_name") String firstname, @Field("last_name") String lastname, int age) {
|
||||
public Person(String firstname, String lastname, int age) {
|
||||
this(null, firstname, lastname, age);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -21,19 +21,19 @@ import static org.springframework.data.mongodb.core.query.Criteria.*;
|
||||
import static org.springframework.data.mongodb.core.query.Query.*;
|
||||
import static org.springframework.data.mongodb.core.query.Update.*;
|
||||
|
||||
import example.springdata.mongodb.util.EmbeddedMongo;
|
||||
import reactor.test.StepVerifier;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
import com.mongodb.client.MongoClient;
|
||||
import com.mongodb.client.model.changestream.ChangeStreamDocument;
|
||||
import com.mongodb.reactivestreams.client.MongoClients;
|
||||
import example.springdata.mongodb.util.MongoContainers;
|
||||
import org.assertj.core.api.Assertions;
|
||||
import org.bson.Document;
|
||||
import org.junit.ClassRule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.bson.types.ObjectId;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.autoconfigure.mongo.embedded.EmbeddedMongoAutoConfiguration;
|
||||
import org.springframework.boot.test.autoconfigure.data.mongo.DataMongoTest;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
@@ -46,11 +46,13 @@ import org.springframework.data.mongodb.core.messaging.ChangeStreamRequest;
|
||||
import org.springframework.data.mongodb.core.messaging.DefaultMessageListenerContainer;
|
||||
import org.springframework.data.mongodb.core.messaging.Message;
|
||||
import org.springframework.data.mongodb.core.messaging.MessageListenerContainer;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
import com.mongodb.client.MongoClient;
|
||||
import com.mongodb.client.model.changestream.ChangeStreamDocument;
|
||||
import com.mongodb.reactivestreams.client.MongoClients;
|
||||
import org.springframework.test.context.DynamicPropertyRegistry;
|
||||
import org.springframework.test.context.DynamicPropertySource;
|
||||
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||
import org.testcontainers.containers.MongoDBContainer;
|
||||
import org.testcontainers.junit.jupiter.Container;
|
||||
import org.testcontainers.junit.jupiter.Testcontainers;
|
||||
import reactor.test.StepVerifier;
|
||||
|
||||
/**
|
||||
* A simple Test demonstrating required {@link Configuration} for consumption of MongoDB
|
||||
@@ -60,11 +62,18 @@ import com.mongodb.reactivestreams.client.MongoClients;
|
||||
* @author Christoph Strobl
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@Testcontainers
|
||||
@ExtendWith(SpringExtension.class)
|
||||
@DataMongoTest
|
||||
public class ChangeStreamsTests {
|
||||
|
||||
public static @ClassRule EmbeddedMongo replSet = EmbeddedMongo.replSet().configure();
|
||||
@Container //
|
||||
private static MongoDBContainer mongoDBContainer = MongoContainers.getDefaultContainer();
|
||||
|
||||
@DynamicPropertySource
|
||||
static void setProperties(DynamicPropertyRegistry registry) {
|
||||
registry.add("spring.data.mongodb.uri", mongoDBContainer::getReplicaSetUrl);
|
||||
}
|
||||
|
||||
@Autowired MessageListenerContainer container; // for imperative style
|
||||
|
||||
@@ -72,14 +81,14 @@ public class ChangeStreamsTests {
|
||||
|
||||
@Autowired ReactiveMongoOperations reactiveTemplate; // for reactive style
|
||||
|
||||
Person gabriel = new Person("Gabriel", "Lorca", 30);
|
||||
Person michael = new Person("Michael", "Burnham", 30);
|
||||
Person ash = new Person("Ash", "Tyler", 35);
|
||||
Person gabriel = new Person(new ObjectId(), "Gabriel", "Lorca", 30);
|
||||
Person michael = new Person(new ObjectId(), "Michael", "Burnham", 30);
|
||||
Person ash = new Person(new ObjectId(), "Ash", "Tyler", 35);
|
||||
|
||||
/**
|
||||
* Configuration? Yes we need a bit of it - Do not worry, it won't be much!
|
||||
*/
|
||||
@SpringBootApplication(exclude = EmbeddedMongoAutoConfiguration.class)
|
||||
@SpringBootApplication()
|
||||
static class Config {
|
||||
|
||||
/**
|
||||
@@ -90,7 +99,7 @@ public class ChangeStreamsTests {
|
||||
*/
|
||||
@Bean
|
||||
MongoClient mongoClient() {
|
||||
return replSet.getMongoClient();
|
||||
return com.mongodb.client.MongoClients.create(mongoDBContainer.getReplicaSetUrl());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -100,7 +109,7 @@ public class ChangeStreamsTests {
|
||||
*/
|
||||
@Bean
|
||||
SimpleMongoClientDatabaseFactory mongoDbFactory() {
|
||||
return new SimpleMongoClientDatabaseFactory(replSet.getMongoClient(), "changestreams");
|
||||
return new SimpleMongoClientDatabaseFactory(mongoClient(), "changestreams");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -110,7 +119,7 @@ public class ChangeStreamsTests {
|
||||
*/
|
||||
@Bean
|
||||
SimpleReactiveMongoDatabaseFactory reactiveMongoDatabaseFactory() {
|
||||
return new SimpleReactiveMongoDatabaseFactory(MongoClients.create(replSet.getConnectionString()),
|
||||
return new SimpleReactiveMongoDatabaseFactory(MongoClients.create(mongoDBContainer.getReplicaSetUrl()),
|
||||
"changestreams");
|
||||
}
|
||||
|
||||
@@ -118,7 +127,7 @@ public class ChangeStreamsTests {
|
||||
* Since listening to a <a href="https://docs.mongodb.com/manual/changeStreams/">Change Stream</a> using the sync
|
||||
* MongoDB Java Driver is a blocking class, we need to move load to another {@link Thread} by simply using a
|
||||
* {@link MessageListenerContainer}.
|
||||
* <p />
|
||||
* <p/>
|
||||
* As this is a {@link org.springframework.context.SmartLifecycle smart lifecycle component} we do actually not need
|
||||
* to worry about its lifecycle, the resource allocation and freeing.
|
||||
*
|
||||
|
||||
@@ -31,12 +31,6 @@
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>de.flapdoodle.embed</groupId>
|
||||
<artifactId>de.flapdoodle.embed.mongo</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
|
||||
@@ -49,14 +49,10 @@ public class ReactiveTransitionService {
|
||||
|
||||
public Mono<Integer> run(Integer id) {
|
||||
|
||||
return template.inTransaction().execute(action -> {
|
||||
|
||||
return lookup(id) //
|
||||
.flatMap(process -> start(action, process)) //
|
||||
.flatMap(process -> start(template, process)) //
|
||||
.flatMap(it -> verify(it)) //
|
||||
.flatMap(process -> finish(action, process));
|
||||
|
||||
}).next().map(Process::id);
|
||||
.flatMap(process -> finish(template, process)).map(Process::id);
|
||||
}
|
||||
|
||||
private Mono<Process> finish(ReactiveMongoOperations operations, Process process) {
|
||||
|
||||
@@ -15,19 +15,21 @@
|
||||
*/
|
||||
package example.springdata.mongodb.imperative;
|
||||
|
||||
import example.springdata.mongodb.Process;
|
||||
import example.springdata.mongodb.State;
|
||||
import example.springdata.mongodb.util.EmbeddedMongo;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import com.mongodb.client.MongoClient;
|
||||
import com.mongodb.client.MongoClients;
|
||||
import com.mongodb.client.model.Filters;
|
||||
import com.mongodb.client.model.Projections;
|
||||
import example.springdata.mongodb.Process;
|
||||
import example.springdata.mongodb.State;
|
||||
import example.springdata.mongodb.util.MongoContainers;
|
||||
import org.assertj.core.api.Assertions;
|
||||
import org.bson.Document;
|
||||
import org.junit.ClassRule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
@@ -35,14 +37,14 @@ import org.springframework.data.mongodb.MongoDatabaseFactory;
|
||||
import org.springframework.data.mongodb.MongoTransactionManager;
|
||||
import org.springframework.data.mongodb.config.AbstractMongoClientConfiguration;
|
||||
import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
import org.springframework.test.context.DynamicPropertyRegistry;
|
||||
import org.springframework.test.context.DynamicPropertySource;
|
||||
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||
|
||||
import com.mongodb.client.MongoClient;
|
||||
import com.mongodb.client.model.Filters;
|
||||
import com.mongodb.client.model.Projections;
|
||||
import org.testcontainers.containers.MongoDBContainer;
|
||||
import org.testcontainers.junit.jupiter.Container;
|
||||
import org.testcontainers.junit.jupiter.Testcontainers;
|
||||
|
||||
/**
|
||||
* Test showing MongoDB Transaction usage through a synchronous (imperative) API using Spring's managed transactions.
|
||||
@@ -51,11 +53,17 @@ import com.mongodb.client.model.Projections;
|
||||
* @currentRead The Core - Peter V. Brett
|
||||
* @see org.springframework.transaction.annotation.Transactional
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@ContextConfiguration
|
||||
@Testcontainers
|
||||
@ExtendWith(SpringExtension.class)
|
||||
public class TransitionServiceTests {
|
||||
|
||||
public static @ClassRule EmbeddedMongo replSet = EmbeddedMongo.replSet().configure();
|
||||
@Container //
|
||||
private static MongoDBContainer mongoDBContainer = MongoContainers.getDefaultContainer();
|
||||
|
||||
@DynamicPropertySource
|
||||
static void setProperties(DynamicPropertyRegistry registry) {
|
||||
registry.add("spring.data.mongodb.uri", mongoDBContainer::getReplicaSetUrl);
|
||||
}
|
||||
|
||||
static final String DB_NAME = "spring-data-tx-examples";
|
||||
|
||||
@@ -73,10 +81,9 @@ public class TransitionServiceTests {
|
||||
return new MongoTransactionManager(dbFactory);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Bean
|
||||
public MongoClient mongoClient() {
|
||||
return replSet.getMongoClient();
|
||||
return MongoClients.create(mongoDBContainer.getReplicaSetUrl());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -110,5 +117,4 @@ public class TransitionServiceTests {
|
||||
return State.valueOf(client.getDatabase(DB_NAME).getCollection("processes").find(Filters.eq("_id", process.id()))
|
||||
.projection(Projections.include("state")).first().get("state", String.class));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -17,16 +17,14 @@ package example.springdata.mongodb.reactive;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
import com.mongodb.reactivestreams.client.MongoClients;
|
||||
import example.springdata.mongodb.Process;
|
||||
import com.mongodb.reactivestreams.client.MongoClient;
|
||||
import example.springdata.mongodb.State;
|
||||
import example.springdata.mongodb.util.EmbeddedMongo;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.test.StepVerifier;
|
||||
|
||||
import example.springdata.mongodb.util.MongoContainers;
|
||||
import org.bson.Document;
|
||||
import org.junit.ClassRule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
@@ -35,13 +33,16 @@ import org.springframework.data.mongodb.ReactiveMongoDatabaseFactory;
|
||||
import org.springframework.data.mongodb.ReactiveMongoTransactionManager;
|
||||
import org.springframework.data.mongodb.config.AbstractReactiveMongoConfiguration;
|
||||
import org.springframework.data.mongodb.repository.config.EnableReactiveMongoRepositories;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
import org.springframework.test.context.DynamicPropertyRegistry;
|
||||
import org.springframework.test.context.DynamicPropertySource;
|
||||
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||
import org.springframework.transaction.ReactiveTransactionManager;
|
||||
import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||
|
||||
import com.mongodb.reactivestreams.client.MongoClient;
|
||||
import com.mongodb.reactivestreams.client.MongoClients;
|
||||
import org.testcontainers.containers.MongoDBContainer;
|
||||
import org.testcontainers.junit.jupiter.Container;
|
||||
import org.testcontainers.junit.jupiter.Testcontainers;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.test.StepVerifier;
|
||||
|
||||
/**
|
||||
* Test showing MongoDB Transaction usage through a reactive API.
|
||||
@@ -49,11 +50,17 @@ import com.mongodb.reactivestreams.client.MongoClients;
|
||||
* @author Christoph Strobl
|
||||
* @currentRead The Core - Peter V. Brett
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@ContextConfiguration
|
||||
@Testcontainers
|
||||
@ExtendWith(SpringExtension.class)
|
||||
public class ReactiveManagedTransitionServiceTests {
|
||||
|
||||
public static @ClassRule EmbeddedMongo replSet = EmbeddedMongo.replSet().configure();
|
||||
@Container //
|
||||
private static MongoDBContainer mongoDBContainer = MongoContainers.getDefaultContainer();
|
||||
|
||||
@DynamicPropertySource
|
||||
static void setProperties(DynamicPropertyRegistry registry) {
|
||||
registry.add("spring.data.mongodb.uri", mongoDBContainer::getReplicaSetUrl);
|
||||
}
|
||||
|
||||
@Autowired ReactiveManagedTransitionService managedTransitionService;
|
||||
@Autowired MongoClient client;
|
||||
@@ -74,7 +81,7 @@ public class ReactiveManagedTransitionServiceTests {
|
||||
@Bean
|
||||
@Override
|
||||
public MongoClient reactiveMongoClient() {
|
||||
return MongoClients.create(replSet.getConnectionString());
|
||||
return MongoClients.create(mongoDBContainer.getReplicaSetUrl());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,107 +0,0 @@
|
||||
/*
|
||||
* Copyright 2018-2021 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
|
||||
*
|
||||
* https://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.reactive;
|
||||
|
||||
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 org.bson.Document;
|
||||
import org.junit.ClassRule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.mongodb.config.AbstractReactiveMongoConfiguration;
|
||||
import org.springframework.data.mongodb.repository.config.EnableReactiveMongoRepositories;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
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
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@ContextConfiguration
|
||||
public class ReactiveTransitionServiceTests {
|
||||
|
||||
public static @ClassRule EmbeddedMongo replSet = EmbeddedMongo.replSet().configure();
|
||||
|
||||
@Autowired ReactiveTransitionService transitionService;
|
||||
@Autowired MongoClient client;
|
||||
|
||||
static final String DB_NAME = "spring-data-reactive-tx-examples";
|
||||
|
||||
@Configuration
|
||||
@ComponentScan
|
||||
@EnableReactiveMongoRepositories
|
||||
static class Config extends AbstractReactiveMongoConfiguration {
|
||||
|
||||
@Bean
|
||||
@Override
|
||||
public MongoClient reactiveMongoClient() {
|
||||
return MongoClients.create(replSet.getConnectionString());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getDatabaseName() {
|
||||
return DB_NAME;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void reactiveTxCommitRollback() {
|
||||
|
||||
for (var i = 0; i < 10; i++) {
|
||||
transitionService.newProcess() //
|
||||
.map(Process::id) //
|
||||
.flatMap(transitionService::run) //
|
||||
.onErrorReturn(-1).as(StepVerifier::create) //
|
||||
.consumeNextWith(val -> {}) //
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
Flux.from(client.getDatabase(DB_NAME).getCollection("processes").find(new Document())) //
|
||||
.buffer(10) //
|
||||
.as(StepVerifier::create) //
|
||||
.consumeNextWith(list -> {
|
||||
|
||||
for (var document : list) {
|
||||
|
||||
System.out.println("document: " + document);
|
||||
|
||||
if (document.getInteger("_id") % 3 == 0) {
|
||||
assertThat(document.getString("state")).isEqualTo(State.CREATED.toString());
|
||||
} else {
|
||||
assertThat(document.getString("state")).isEqualTo(State.DONE.toString());
|
||||
}
|
||||
}
|
||||
|
||||
}) //
|
||||
.verifyComplete();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
spring.data.mongodb.database=spring-data-tx-examples
|
||||
Reference in New Issue
Block a user