@@ -60,7 +60,7 @@ class ExpressionIntegrationTests {
|
||||
employeeRepository.findAllByName("Walter") //
|
||||
.contextWrite(Context.of(Tenant.class, new Tenant("breaking-bad"))).as(StepVerifier::create) //
|
||||
.assertNext(actual -> {
|
||||
assertThat(actual.getTenantId()).isEqualTo("breaking-bad");
|
||||
assertThat(actual.tenantId()).isEqualTo("breaking-bad");
|
||||
}).verifyComplete();
|
||||
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import lombok.Value;
|
||||
import org.jmolecules.ddd.types.AggregateRoot;
|
||||
import org.jmolecules.ddd.types.Association;
|
||||
import org.jmolecules.ddd.types.Identifier;
|
||||
@@ -46,7 +47,7 @@ public class Order implements AggregateRoot<Order, Order.OrderId> {
|
||||
|
||||
public Order(Customer customer) {
|
||||
|
||||
this.id = new OrderId(UUID.randomUUID());
|
||||
this.id = OrderId.of(UUID.randomUUID());
|
||||
this.customer = Association.forAggregate(customer);
|
||||
this.lineItems = new ArrayList<>();
|
||||
}
|
||||
@@ -60,10 +61,13 @@ public class Order implements AggregateRoot<Order, Order.OrderId> {
|
||||
return this;
|
||||
}
|
||||
|
||||
public record OrderId(UUID orderId) implements Identifier {
|
||||
@Value(staticConstructor = "of")
|
||||
public static class OrderId implements Identifier {
|
||||
|
||||
UUID orderId;
|
||||
|
||||
public static OrderId create() {
|
||||
return new OrderId(UUID.randomUUID());
|
||||
return OrderId.of(UUID.randomUUID());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,20 +17,12 @@ package example.springdata.mongodb.aggregation;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import lombok.Value;
|
||||
|
||||
/**
|
||||
* A DTO to represent invoices.
|
||||
*
|
||||
* @author Thomas Darimont
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@Value
|
||||
public class Invoice {
|
||||
public record Invoice(String orderId, double taxAmount, double netAmount, double totalAmount, List<LineItem> items) {
|
||||
|
||||
private final String orderId;
|
||||
private final double taxAmount;
|
||||
private final double netAmount;
|
||||
private final double totalAmount;
|
||||
private final List<LineItem> items;
|
||||
}
|
||||
|
||||
@@ -15,9 +15,6 @@
|
||||
*/
|
||||
package example.springdata.mongodb.aggregation;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import org.springframework.data.annotation.PersistenceConstructor;
|
||||
|
||||
/**
|
||||
@@ -26,18 +23,15 @@ import org.springframework.data.annotation.PersistenceConstructor;
|
||||
* @author Thomas Darimont
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@Data
|
||||
@RequiredArgsConstructor(onConstructor = @__(@PersistenceConstructor))
|
||||
public class LineItem {
|
||||
|
||||
private final String caption;
|
||||
private final double price;
|
||||
public record LineItem(String caption, double price, int quantity) {
|
||||
|
||||
int quantity = 1;
|
||||
|
||||
public LineItem(String caption, double price, int quantity) {
|
||||
|
||||
this(caption, price);
|
||||
this.quantity = quantity;
|
||||
@PersistenceConstructor
|
||||
public LineItem {
|
||||
}
|
||||
|
||||
public LineItem(String caption, double price) {
|
||||
this(caption, price, 1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ class OrderRepositoryImpl implements OrderRepositoryCustom {
|
||||
@Override
|
||||
public Invoice getInvoiceFor(Order order) {
|
||||
|
||||
AggregationResults<Invoice> results = operations.aggregate(newAggregation(Order.class, //
|
||||
var results = operations.aggregate(newAggregation(Order.class, //
|
||||
match(where("id").is(order.getId())), //
|
||||
unwind("items"), //
|
||||
project("id", "customerId", "items") //
|
||||
|
||||
@@ -15,17 +15,11 @@
|
||||
*/
|
||||
package example.springdata.mongodb.aggregation;
|
||||
|
||||
import lombok.Value;
|
||||
|
||||
import org.springframework.data.annotation.Id;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
@Value
|
||||
public class OrdersPerCustomer {
|
||||
public record OrdersPerCustomer(@Id String customerId, Long total) {
|
||||
|
||||
@Id //
|
||||
private String customerId;
|
||||
private Long total;
|
||||
}
|
||||
|
||||
@@ -54,33 +54,33 @@ public class OrderRepositoryIntegrationTests {
|
||||
@Test
|
||||
public void createsInvoiceViaProgrammaticAggregation() {
|
||||
|
||||
Order order = new Order("c42", new Date()).//
|
||||
var order = new Order("c42", new Date()).//
|
||||
addItem(product1).addItem(product2).addItem(product3);
|
||||
order = repository.save(order);
|
||||
|
||||
Invoice invoice = repository.getInvoiceFor(order);
|
||||
var invoice = repository.getInvoiceFor(order);
|
||||
|
||||
assertThat(invoice).isNotNull();
|
||||
assertThat(invoice.getOrderId()).isEqualTo(order.getId());
|
||||
assertThat(invoice.getNetAmount()).isCloseTo(8.3D, offset(0.00001));
|
||||
assertThat(invoice.getTaxAmount()).isCloseTo(1.577D, offset(0.00001));
|
||||
assertThat(invoice.getTotalAmount()).isCloseTo(9.877, offset(0.00001));
|
||||
assertThat(invoice.orderId()).isEqualTo(order.getId());
|
||||
assertThat(invoice.netAmount()).isCloseTo(8.3D, offset(0.00001));
|
||||
assertThat(invoice.taxAmount()).isCloseTo(1.577D, offset(0.00001));
|
||||
assertThat(invoice.totalAmount()).isCloseTo(9.877, offset(0.00001));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createsInvoiceViaDeclarativeAggregation() {
|
||||
|
||||
Order order = new Order("c42", new Date()).//
|
||||
var order = new Order("c42", new Date()).//
|
||||
addItem(product1).addItem(product2).addItem(product3);
|
||||
order = repository.save(order);
|
||||
|
||||
Invoice invoice = repository.aggregateInvoiceForOrder(order.getId());
|
||||
var invoice = repository.aggregateInvoiceForOrder(order.getId());
|
||||
|
||||
assertThat(invoice).isNotNull();
|
||||
assertThat(invoice.getOrderId()).isEqualTo(order.getId());
|
||||
assertThat(invoice.getNetAmount()).isCloseTo(8.3D, offset(0.00001));
|
||||
assertThat(invoice.getTaxAmount()).isCloseTo(1.577D, offset(0.00001));
|
||||
assertThat(invoice.getTotalAmount()).isCloseTo(9.877, offset(0.00001));
|
||||
assertThat(invoice.orderId()).isEqualTo(order.getId());
|
||||
assertThat(invoice.netAmount()).isCloseTo(8.3D, offset(0.00001));
|
||||
assertThat(invoice.taxAmount()).isCloseTo(1.577D, offset(0.00001));
|
||||
assertThat(invoice.totalAmount()).isCloseTo(9.877, offset(0.00001));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -18,10 +18,6 @@ package example.springdata.mongodb.aggregation;
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.springframework.data.mongodb.core.aggregation.Aggregation.*;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Value;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.List;
|
||||
|
||||
@@ -37,8 +33,6 @@ import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.domain.Sort.Direction;
|
||||
import org.springframework.data.mongodb.core.MongoOperations;
|
||||
import org.springframework.data.mongodb.core.aggregation.Aggregation;
|
||||
import org.springframework.data.mongodb.core.aggregation.AggregationResults;
|
||||
import org.springframework.data.mongodb.core.aggregation.ArithmeticOperators;
|
||||
import org.springframework.data.mongodb.core.aggregation.ArrayOperators;
|
||||
import org.springframework.data.mongodb.core.aggregation.BucketAutoOperation.Granularities;
|
||||
@@ -67,10 +61,10 @@ public class SpringBooksIntegrationTests {
|
||||
|
||||
if (operations.count(new Query(), "books") == 0) {
|
||||
|
||||
File file = new ClassPathResource("books.json").getFile();
|
||||
String content = Files.contentOf(file, StandardCharsets.UTF_8);
|
||||
Document wrapper = Document.parse("{wrapper: " + content + "}");
|
||||
List<Object> books = wrapper.getList("wrapper", Object.class);
|
||||
var file = new ClassPathResource("books.json").getFile();
|
||||
var content = Files.contentOf(file, StandardCharsets.UTF_8);
|
||||
var wrapper = Document.parse("{wrapper: " + content + "}");
|
||||
var books = wrapper.getList("wrapper", Object.class);
|
||||
|
||||
operations.insert(books, "books");
|
||||
}
|
||||
@@ -82,11 +76,14 @@ public class SpringBooksIntegrationTests {
|
||||
@Test
|
||||
public void shouldRetrieveOrderedBookTitles() {
|
||||
|
||||
Aggregation aggregation = newAggregation( //
|
||||
record BookTitle(String title) {
|
||||
}
|
||||
|
||||
var aggregation = newAggregation( //
|
||||
sort(Direction.ASC, "volumeInfo.title"), //
|
||||
project().and("volumeInfo.title").as("title"));
|
||||
|
||||
AggregationResults<BookTitle> result = operations.aggregate(aggregation, "books", BookTitle.class);
|
||||
var result = operations.aggregate(aggregation, "books", BookTitle.class);
|
||||
|
||||
assertThat(result.getMappedResults())//
|
||||
.extracting("title")//
|
||||
@@ -99,13 +96,13 @@ public class SpringBooksIntegrationTests {
|
||||
@Test
|
||||
public void shouldRetrieveBooksPerPublisher() {
|
||||
|
||||
Aggregation aggregation = newAggregation( //
|
||||
var aggregation = newAggregation( //
|
||||
group("volumeInfo.publisher") //
|
||||
.count().as("count"), //
|
||||
sort(Direction.DESC, "count"), //
|
||||
project("count").and("_id").as("publisher"));
|
||||
|
||||
AggregationResults<BooksPerPublisher> result = operations.aggregate(aggregation, "books", BooksPerPublisher.class);
|
||||
var result = operations.aggregate(aggregation, "books", BooksPerPublisher.class);
|
||||
|
||||
assertThat(result).hasSize(27);
|
||||
assertThat(result).extracting("publisher").containsSequence("Apress", "Packt Publishing Ltd");
|
||||
@@ -118,20 +115,20 @@ public class SpringBooksIntegrationTests {
|
||||
@Test
|
||||
public void shouldRetrieveBooksPerPublisherWithTitles() {
|
||||
|
||||
Aggregation aggregation = newAggregation( //
|
||||
var aggregation = newAggregation( //
|
||||
group("volumeInfo.publisher") //
|
||||
.count().as("count") //
|
||||
.addToSet("volumeInfo.title").as("titles"), //
|
||||
sort(Direction.DESC, "count"), //
|
||||
project("count", "titles").and("_id").as("publisher"));
|
||||
|
||||
AggregationResults<BooksPerPublisher> result = operations.aggregate(aggregation, "books", BooksPerPublisher.class);
|
||||
var result = operations.aggregate(aggregation, "books", BooksPerPublisher.class);
|
||||
|
||||
BooksPerPublisher booksPerPublisher = result.getMappedResults().get(0);
|
||||
var booksPerPublisher = result.getMappedResults().get(0);
|
||||
|
||||
assertThat(booksPerPublisher.getPublisher()).isEqualTo("Apress");
|
||||
assertThat(booksPerPublisher.getCount()).isEqualTo(26);
|
||||
assertThat(booksPerPublisher.getTitles()).contains("Expert Spring MVC and Web Flow", "Pro Spring Boot");
|
||||
assertThat(booksPerPublisher.publisher()).isEqualTo("Apress");
|
||||
assertThat(booksPerPublisher.count()).isEqualTo(26);
|
||||
assertThat(booksPerPublisher.titles()).contains("Expert Spring MVC and Web Flow", "Pro Spring Boot");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -140,18 +137,18 @@ public class SpringBooksIntegrationTests {
|
||||
@Test
|
||||
public void shouldRetrieveDataRelatedBooks() {
|
||||
|
||||
Aggregation aggregation = newAggregation( //
|
||||
var aggregation = newAggregation( //
|
||||
match(Criteria.where("volumeInfo.title").regex("data", "i")), //
|
||||
replaceRoot("volumeInfo"), //
|
||||
project("title", "authors"), //
|
||||
sort(Direction.ASC, "title"));
|
||||
|
||||
AggregationResults<BookAndAuthors> result = operations.aggregate(aggregation, "books", BookAndAuthors.class);
|
||||
var result = operations.aggregate(aggregation, "books", BookAndAuthors.class);
|
||||
|
||||
BookAndAuthors bookAndAuthors = result.getMappedResults().get(1);
|
||||
var bookAndAuthors = result.getMappedResults().get(1);
|
||||
|
||||
assertThat(bookAndAuthors.getTitle()).isEqualTo("Spring Data");
|
||||
assertThat(bookAndAuthors.getAuthors()).contains("Mark Pollack", "Oliver Gierke", "Thomas Risberg", "Jon Brisbin",
|
||||
assertThat(bookAndAuthors.title()).isEqualTo("Spring Data");
|
||||
assertThat(bookAndAuthors.authors()).contains("Mark Pollack", "Oliver Gierke", "Thomas Risberg", "Jon Brisbin",
|
||||
"Michael Hunger");
|
||||
}
|
||||
|
||||
@@ -161,7 +158,10 @@ public class SpringBooksIntegrationTests {
|
||||
@Test
|
||||
public void shouldRetrievePagesPerAuthor() {
|
||||
|
||||
Aggregation aggregation = newAggregation( //
|
||||
record PagesPerAuthor(@Id String author, int totalPageCount, int approxWritten) {
|
||||
}
|
||||
|
||||
var aggregation = newAggregation( //
|
||||
match(Criteria.where("volumeInfo.authors").exists(true)), //
|
||||
replaceRoot("volumeInfo"), //
|
||||
project("authors", "pageCount") //
|
||||
@@ -174,13 +174,13 @@ public class SpringBooksIntegrationTests {
|
||||
.sum("pagesPerAuthor").as("approxWritten"), //
|
||||
sort(Direction.DESC, "totalPageCount"));
|
||||
|
||||
AggregationResults<PagesPerAuthor> result = operations.aggregate(aggregation, "books", PagesPerAuthor.class);
|
||||
var result = operations.aggregate(aggregation, "books", PagesPerAuthor.class);
|
||||
|
||||
PagesPerAuthor pagesPerAuthor = result.getMappedResults().get(0);
|
||||
var pagesPerAuthor = result.getMappedResults().get(0);
|
||||
|
||||
assertThat(pagesPerAuthor.getAuthor()).isEqualTo("Josh Long");
|
||||
assertThat(pagesPerAuthor.getTotalPageCount()).isEqualTo(1892);
|
||||
assertThat(pagesPerAuthor.getApproxWritten()).isEqualTo(573);
|
||||
assertThat(pagesPerAuthor.author()).isEqualTo("Josh Long");
|
||||
assertThat(pagesPerAuthor.totalPageCount()).isEqualTo(1892);
|
||||
assertThat(pagesPerAuthor.approxWritten()).isEqualTo(573);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -189,7 +189,7 @@ public class SpringBooksIntegrationTests {
|
||||
@Test
|
||||
public void shouldCategorizeBooksInBuckets() {
|
||||
|
||||
Aggregation aggregation = newAggregation( //
|
||||
var aggregation = newAggregation( //
|
||||
replaceRoot("volumeInfo"), //
|
||||
match(Criteria.where("pageCount").exists(true)),
|
||||
bucketAuto("pageCount", 10) //
|
||||
@@ -197,20 +197,20 @@ public class SpringBooksIntegrationTests {
|
||||
.andOutput("title").push().as("titles") //
|
||||
.andOutput("titles").count().as("count"));
|
||||
|
||||
AggregationResults<BookFacetPerPage> result = operations.aggregate(aggregation, "books", BookFacetPerPage.class);
|
||||
var result = operations.aggregate(aggregation, "books", BookFacetPerPage.class);
|
||||
|
||||
List<BookFacetPerPage> mappedResults = result.getMappedResults();
|
||||
var mappedResults = result.getMappedResults();
|
||||
|
||||
BookFacetPerPage facet_20_to_100_pages = mappedResults.get(0);
|
||||
assertThat(facet_20_to_100_pages.getId().getMin()).isEqualTo(20);
|
||||
assertThat(facet_20_to_100_pages.getId().getMax()).isEqualTo(100);
|
||||
assertThat(facet_20_to_100_pages.getCount()).isEqualTo(12);
|
||||
var facet_20_to_100_pages = mappedResults.get(0);
|
||||
assertThat(facet_20_to_100_pages.id().min()).isEqualTo(20);
|
||||
assertThat(facet_20_to_100_pages.id().max()).isEqualTo(100);
|
||||
assertThat(facet_20_to_100_pages.count()).isEqualTo(12);
|
||||
|
||||
BookFacetPerPage facet_100_to_500_pages = mappedResults.get(1);
|
||||
assertThat(facet_100_to_500_pages.getId().getMin()).isEqualTo(100);
|
||||
assertThat(facet_100_to_500_pages.getId().getMax()).isEqualTo(500);
|
||||
assertThat(facet_100_to_500_pages.getCount()).isEqualTo(63);
|
||||
assertThat(facet_100_to_500_pages.getTitles()).contains("Spring Data");
|
||||
var facet_100_to_500_pages = mappedResults.get(1);
|
||||
assertThat(facet_100_to_500_pages.id().min()).isEqualTo(100);
|
||||
assertThat(facet_100_to_500_pages.id().max()).isEqualTo(500);
|
||||
assertThat(facet_100_to_500_pages.count()).isEqualTo(63);
|
||||
assertThat(facet_100_to_500_pages.titles()).contains("Spring Data");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -221,7 +221,7 @@ public class SpringBooksIntegrationTests {
|
||||
@SuppressWarnings("unchecked")
|
||||
public void shouldCategorizeInMultipleFacetsByPriceAndAuthor() {
|
||||
|
||||
Aggregation aggregation = newAggregation( //
|
||||
var aggregation = newAggregation( //
|
||||
match(Criteria.where("volumeInfo.authors").exists(true).and("volumeInfo.publisher").exists(true)),
|
||||
facet() //
|
||||
.and(match(Criteria.where("saleInfo.listPrice").exists(true)), //
|
||||
@@ -240,55 +240,23 @@ public class SpringBooksIntegrationTests {
|
||||
.andOutput("author").push().as("authors") //
|
||||
).as("authors"));
|
||||
|
||||
AggregationResults<Document> result = operations.aggregate(aggregation, "books", Document.class);
|
||||
var result = operations.aggregate(aggregation, "books", Document.class);
|
||||
|
||||
Document uniqueMappedResult = result.getUniqueMappedResult();
|
||||
var uniqueMappedResult = result.getUniqueMappedResult();
|
||||
|
||||
assertThat((List<Object>) uniqueMappedResult.get("prices")).hasSize(3);
|
||||
assertThat((List<Object>) uniqueMappedResult.get("authors")).hasSize(8);
|
||||
}
|
||||
|
||||
@Value
|
||||
@Getter
|
||||
static class BookTitle {
|
||||
String title;
|
||||
record BooksPerPublisher(String publisher, int count, List<String> titles) {
|
||||
}
|
||||
|
||||
@Value
|
||||
@Getter
|
||||
static class BooksPerPublisher {
|
||||
String publisher;
|
||||
int count;
|
||||
List<String> titles;
|
||||
record BookAndAuthors(String title, List<String> authors) {
|
||||
}
|
||||
|
||||
@Value
|
||||
@Getter
|
||||
static class BookAndAuthors {
|
||||
String title;
|
||||
List<String> authors;
|
||||
record BookFacetPerPage(BookFacetPerPageId id, int count, List<String> titles) {
|
||||
}
|
||||
|
||||
@Value
|
||||
@Getter
|
||||
static class PagesPerAuthor {
|
||||
@Id String author;
|
||||
int totalPageCount;
|
||||
int approxWritten;
|
||||
}
|
||||
|
||||
@Value
|
||||
@Getter
|
||||
static class BookFacetPerPage {
|
||||
BookFacetPerPageId id;
|
||||
int count;
|
||||
List<String> titles;
|
||||
}
|
||||
|
||||
@Value
|
||||
@Getter
|
||||
static class BookFacetPerPageId {
|
||||
int min;
|
||||
int max;
|
||||
record BookFacetPerPageId(int min, int max) {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ class CollectingMessageListener<S, T> implements MessageListener<S, T> {
|
||||
|
||||
void awaitNextMessages(int count) throws InterruptedException {
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
for (var i = 0; i < count; i++) {
|
||||
messages.take();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,9 +15,8 @@
|
||||
*/
|
||||
package example.springdata.mongodb;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import org.bson.types.ObjectId;
|
||||
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.mongodb.core.mapping.Field;
|
||||
|
||||
@@ -29,21 +28,8 @@ import org.springframework.data.mongodb.core.mapping.Field;
|
||||
*
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
@Data
|
||||
class Person {
|
||||
|
||||
@Id ObjectId id;
|
||||
|
||||
@Field("first_name") private String firstname;
|
||||
|
||||
@Field("last_name") private String lastname;
|
||||
|
||||
private int age;
|
||||
|
||||
Person(String firstname, String lastname, int age) {
|
||||
|
||||
this.firstname = firstname;
|
||||
this.lastname = lastname;
|
||||
this.age = age;
|
||||
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,9 +21,7 @@ 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 com.mongodb.client.MongoClient;
|
||||
import example.springdata.mongodb.util.EmbeddedMongo;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.test.StepVerifier;
|
||||
|
||||
import java.time.Duration;
|
||||
@@ -32,13 +30,13 @@ 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.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;
|
||||
import org.springframework.data.mongodb.core.ChangeStreamEvent;
|
||||
import org.springframework.data.mongodb.core.ChangeStreamOptions;
|
||||
import org.springframework.data.mongodb.core.MongoTemplate;
|
||||
import org.springframework.data.mongodb.core.ReactiveMongoOperations;
|
||||
@@ -48,9 +46,9 @@ 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.data.mongodb.core.messaging.Subscription;
|
||||
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;
|
||||
|
||||
@@ -150,14 +148,14 @@ public class ChangeStreamsTests {
|
||||
@Test
|
||||
public void imperativeChangeEvents() throws InterruptedException {
|
||||
|
||||
CollectingMessageListener<ChangeStreamDocument<Document>, Person> messageListener = new CollectingMessageListener<>();
|
||||
var messageListener = new CollectingMessageListener<ChangeStreamDocument<Document>, Person>();
|
||||
|
||||
ChangeStreamRequest<Person> request = ChangeStreamRequest.builder(messageListener) //
|
||||
var request = ChangeStreamRequest.builder(messageListener) //
|
||||
.collection("person") //
|
||||
.filter(newAggregation(match(where("operationType").is("insert")))) // we are only interested in inserts
|
||||
.build();
|
||||
|
||||
Subscription subscription = container.register(request, Person.class);
|
||||
var subscription = container.register(request, Person.class);
|
||||
subscription.await(Duration.ofMillis(200)); // wait till the subscription becomes active
|
||||
|
||||
template.save(gabriel);
|
||||
@@ -168,7 +166,7 @@ public class ChangeStreamsTests {
|
||||
assertThat(messageListener.messageCount()).isEqualTo(2); // first two insert events, so far so good
|
||||
|
||||
template.update(Person.class) //
|
||||
.matching(query(where("id").is(ash.getId()))) //
|
||||
.matching(query(where("id").is(ash.id()))) //
|
||||
.apply(update("age", 40)) //
|
||||
.first();
|
||||
|
||||
@@ -189,7 +187,7 @@ public class ChangeStreamsTests {
|
||||
@Test
|
||||
public void reactiveChangeEvents() {
|
||||
|
||||
Flux<ChangeStreamEvent<Person>> changeStream = reactiveTemplate.changeStream("person",
|
||||
var changeStream = reactiveTemplate.changeStream("person",
|
||||
ChangeStreamOptions.builder().filter(newAggregation(match(where("operationType").is("insert")))).build(),
|
||||
Person.class);
|
||||
|
||||
@@ -207,7 +205,7 @@ public class ChangeStreamsTests {
|
||||
.then(() -> {
|
||||
|
||||
StepVerifier.create(reactiveTemplate.update(Person.class) //
|
||||
.matching(query(where("id").is(ash.getId()))) //
|
||||
.matching(query(where("id").is(ash.id()))) //
|
||||
.apply(update("age", 40)) //
|
||||
.first()).expectNextCount(1).verifyComplete();
|
||||
}).expectNoEvent(Duration.ofMillis(200)) // updates are skipped
|
||||
|
||||
@@ -21,7 +21,6 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.data.mongodb.core.mapping.event.BeforeConvertCallback;
|
||||
|
||||
|
||||
/**
|
||||
* Test configuration to connect to a MongoDB named "test" using a {@code MongoClient}. <br />
|
||||
* Also enables Spring Data repositories for MongoDB.
|
||||
@@ -44,11 +43,29 @@ class ApplicationConfiguration {
|
||||
|
||||
return (immutablePerson, collection) -> {
|
||||
|
||||
int randomNumber = ThreadLocalRandom.current().nextInt(1, 100);
|
||||
var randomNumber = ThreadLocalRandom.current().nextInt(1, 100);
|
||||
|
||||
// withRandomNumber is a so called wither method returning a new instance of the entity with a new value assigned
|
||||
return immutablePerson.withRandomNumber(randomNumber);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the {@link BeforeConvertCallback} used to update an {@link ImmutableRecord} before handing over the newly
|
||||
* created instance to the actual mapping layer performing the conversion into the store native
|
||||
* {@link org.bson.Document} representation.
|
||||
*
|
||||
* @return a {@link BeforeConvertCallback} for {@link ImmutablePerson}.
|
||||
*/
|
||||
@Bean
|
||||
BeforeConvertCallback<ImmutableRecord> beforeRecordConvertCallback() {
|
||||
|
||||
return (rec, collection) -> {
|
||||
|
||||
var randomNumber = ThreadLocalRandom.current().nextInt(1, 100);
|
||||
|
||||
return new ImmutableRecord(rec.id(), randomNumber);
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ package example.springdata.mongodb.immutable;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.experimental.Wither;
|
||||
import lombok.With;
|
||||
|
||||
import org.bson.types.ObjectId;
|
||||
|
||||
@@ -26,7 +26,7 @@ import org.bson.types.ObjectId;
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
@Wither
|
||||
@With
|
||||
@Getter
|
||||
@RequiredArgsConstructor
|
||||
public class ImmutablePerson {
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright 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
|
||||
*
|
||||
* 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.immutable;
|
||||
|
||||
import org.bson.types.ObjectId;
|
||||
|
||||
record ImmutableRecord(ObjectId id, int randomNumber) {
|
||||
}
|
||||
@@ -15,15 +15,11 @@
|
||||
*/
|
||||
package example.springdata.mongodb.projections;
|
||||
|
||||
import lombok.Value;
|
||||
|
||||
/**
|
||||
* A sample DTO only containing the firstname.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@Value
|
||||
class CustomerDto {
|
||||
record CustomerDto(String firstname) {
|
||||
|
||||
String firstname;
|
||||
}
|
||||
|
||||
@@ -15,40 +15,12 @@
|
||||
*/
|
||||
package example.springdata.mongodb.unwrapping;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Value object capturing the {@code email} address.
|
||||
*
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
public class Email { // might as well be a record type in more recent java versions
|
||||
|
||||
private final String email;
|
||||
|
||||
public Email(String email) {
|
||||
this.email = email;
|
||||
}
|
||||
|
||||
public String getEmail() {
|
||||
return email;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return email;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
Email email1 = (Email) o;
|
||||
return Objects.equals(email, email1.email);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(email);
|
||||
}
|
||||
public record Email(String email) {
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -83,7 +83,7 @@ public class User {
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
User user = (User) o;
|
||||
var user = (User) o;
|
||||
return Objects.equals(id, user.id) &&
|
||||
Objects.equals(userName, user.userName) &&
|
||||
Objects.equals(email, user.email);
|
||||
|
||||
@@ -38,7 +38,7 @@ public class UserName { // might as well be a record type in more recent java ve
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
UserName userName = (UserName) o;
|
||||
var userName = (UserName) o;
|
||||
return Objects.equals(username, userName.username);
|
||||
}
|
||||
|
||||
|
||||
@@ -71,12 +71,12 @@ public class AdvancedIntegrationTests {
|
||||
// execute another finder without meta attributes that should not be picked up
|
||||
repository.findByLastname(dave.getLastname(), Sort.by("firstname"));
|
||||
|
||||
FindIterable<Document> cursor = operations.getCollection(ApplicationConfiguration.SYSTEM_PROFILE_DB)
|
||||
var cursor = operations.getCollection(ApplicationConfiguration.SYSTEM_PROFILE_DB)
|
||||
.find(new BasicDBObject("query.$comment", AdvancedRepository.META_COMMENT));
|
||||
|
||||
for (Document document : cursor) {
|
||||
for (var document : cursor) {
|
||||
|
||||
Document query = (Document) document.get("query");
|
||||
var query = (Document) document.get("query");
|
||||
assertThat(query).containsKey("foo");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,7 +76,7 @@ public class ServersideScriptTests {
|
||||
@Ignore
|
||||
public void complexScriptExecutionSimulatingPutIfAbsent() {
|
||||
|
||||
Customer ned = new Customer("Ned", "Stark");
|
||||
var ned = new Customer("Ned", "Stark");
|
||||
ned.setId("ned-stark");
|
||||
|
||||
// #1: on first insert null has to be returned
|
||||
@@ -94,14 +94,14 @@ public class ServersideScriptTests {
|
||||
|
||||
private ExecutableMongoScript createExecutablePutIfAbsentScript(Customer customer) {
|
||||
|
||||
String collectionName = operations.getCollectionName(Customer.class);
|
||||
Object id = operations.getConverter().getMappingContext().getRequiredPersistentEntity(Customer.class)
|
||||
var collectionName = operations.getCollectionName(Customer.class);
|
||||
var id = operations.getConverter().getMappingContext().getRequiredPersistentEntity(Customer.class)
|
||||
.getIdentifierAccessor(customer).getIdentifier();
|
||||
|
||||
Document document = new Document();
|
||||
var document = new Document();
|
||||
operations.getConverter().write(customer, document);
|
||||
|
||||
String scriptString = String.format(
|
||||
var scriptString = String.format(
|
||||
"object = db.%1$s.findOne({\"_id\": \"%2$s\"}); if (object == null) { db.%1s.insert(%3$s); return null; } else { return object; }",
|
||||
collectionName, id, document);
|
||||
|
||||
|
||||
@@ -65,7 +65,7 @@ public class CustomerRepositoryIntegrationTest {
|
||||
@Test
|
||||
public void setsIdOnSave() {
|
||||
|
||||
Customer dave = repository.save(new Customer("Dave", "Matthews"));
|
||||
var dave = repository.save(new Customer("Dave", "Matthews"));
|
||||
assertThat(dave.getId(), is(notNullValue()));
|
||||
}
|
||||
|
||||
@@ -75,8 +75,8 @@ public class CustomerRepositoryIntegrationTest {
|
||||
@Test
|
||||
public void findCustomersUsingQuerydslSort() {
|
||||
|
||||
QCustomer customer = QCustomer.customer;
|
||||
List<Customer> result = repository.findByLastname("Matthews", new QSort(customer.firstname.asc()));
|
||||
var customer = QCustomer.customer;
|
||||
var result = repository.findByLastname("Matthews", new QSort(customer.firstname.asc()));
|
||||
|
||||
assertThat(result, hasSize(2));
|
||||
assertThat(result.get(0), is(dave));
|
||||
@@ -89,7 +89,7 @@ public class CustomerRepositoryIntegrationTest {
|
||||
@Test
|
||||
public void findCustomersAsStream() {
|
||||
|
||||
try (Stream<Customer> result = repository.findAllByCustomQueryWithStream()) {
|
||||
try (var result = repository.findAllByCustomQueryWithStream()) {
|
||||
result.forEach(System.out::println);
|
||||
}
|
||||
}
|
||||
@@ -100,24 +100,24 @@ public class CustomerRepositoryIntegrationTest {
|
||||
@Test
|
||||
public void exposesGeoSpatialFunctionality() {
|
||||
|
||||
GeospatialIndex indexDefinition = new GeospatialIndex("address.location");
|
||||
var indexDefinition = new GeospatialIndex("address.location");
|
||||
indexDefinition.getIndexOptions().put("min", -180);
|
||||
indexDefinition.getIndexOptions().put("max", 180);
|
||||
|
||||
operations.indexOps(Customer.class).ensureIndex(indexDefinition);
|
||||
|
||||
Customer ollie = new Customer("Oliver", "Gierke");
|
||||
var ollie = new Customer("Oliver", "Gierke");
|
||||
ollie.setAddress(new Address(new Point(52.52548, 13.41477)));
|
||||
ollie = repository.save(ollie);
|
||||
|
||||
Point referenceLocation = new Point(52.51790, 13.41239);
|
||||
Distance oneKilometer = new Distance(1, Metrics.KILOMETERS);
|
||||
var referenceLocation = new Point(52.51790, 13.41239);
|
||||
var oneKilometer = new Distance(1, Metrics.KILOMETERS);
|
||||
|
||||
GeoResults<Customer> result = repository.findByAddressLocationNear(referenceLocation, oneKilometer);
|
||||
var result = repository.findByAddressLocationNear(referenceLocation, oneKilometer);
|
||||
|
||||
assertThat(result.getContent(), hasSize(1));
|
||||
|
||||
Distance distanceToFirstStore = result.getContent().get(0).getDistance();
|
||||
var distanceToFirstStore = result.getContent().get(0).getDistance();
|
||||
assertThat(distanceToFirstStore.getMetric(), is(Metrics.KILOMETERS));
|
||||
assertThat(distanceToFirstStore.getValue(), closeTo(0.862, 0.001));
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ package example.springdata.mongodb.immutable;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
import org.bson.types.ObjectId;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
@@ -49,12 +50,29 @@ public class ImmutableEntityIntegrationTest {
|
||||
@Test
|
||||
public void setsRandomNumberOnSave() {
|
||||
|
||||
ImmutablePerson unsaved = new ImmutablePerson();
|
||||
var unsaved = new ImmutablePerson();
|
||||
assertThat(unsaved.getRandomNumber()).isZero();
|
||||
|
||||
ImmutablePerson saved = operations.save(unsaved);
|
||||
var saved = operations.save(unsaved);
|
||||
|
||||
assertThat(saved.getId()).isNotNull();
|
||||
assertThat(saved.getRandomNumber()).isNotZero();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test case to show that automatically generated ids are assigned to the immutable domain object and how the
|
||||
* {@link ImmutableRecord#getRandomNumber()} gets set via {@link ApplicationConfiguration#beforeConvertCallback()}.
|
||||
*/
|
||||
@Test
|
||||
public void setsRandomNumberOnSaveRecord() {
|
||||
|
||||
var unsaved = new ImmutableRecord(null, 0);
|
||||
assertThat(unsaved.randomNumber()).isZero();
|
||||
|
||||
var saved = operations.save(unsaved);
|
||||
|
||||
assertThat(saved.id()).isNotNull();
|
||||
assertThat(saved.randomNumber()).isNotZero();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@ public class CustomerRepositoryIntegrationTest {
|
||||
@Test
|
||||
public void projectsEntityIntoInterface() {
|
||||
|
||||
Collection<CustomerProjection> result = customers.findAllProjectedBy();
|
||||
var result = customers.findAllProjectedBy();
|
||||
|
||||
assertThat(result, hasSize(2));
|
||||
assertThat(result.iterator().next().getFirstname(), is("Dave"));
|
||||
@@ -72,16 +72,16 @@ public class CustomerRepositoryIntegrationTest {
|
||||
@Test
|
||||
public void projectsToDto() {
|
||||
|
||||
Collection<CustomerDto> result = customers.findAllDtoedBy();
|
||||
var result = customers.findAllDtoedBy();
|
||||
|
||||
assertThat(result, hasSize(2));
|
||||
assertThat(result.iterator().next().getFirstname(), is("Dave"));
|
||||
assertThat(result.iterator().next().firstname(), is("Dave"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void projectsDynamically() {
|
||||
|
||||
Collection<CustomerProjection> result = customers.findByFirstname("Dave", CustomerProjection.class);
|
||||
var result = customers.findByFirstname("Dave", CustomerProjection.class);
|
||||
|
||||
assertThat(result, hasSize(1));
|
||||
assertThat(result.iterator().next().getFirstname(), is("Dave"));
|
||||
@@ -90,7 +90,7 @@ public class CustomerRepositoryIntegrationTest {
|
||||
@Test
|
||||
public void projectsIndividualDynamically() {
|
||||
|
||||
CustomerSummary result = customers.findProjectedById(dave.getId(), CustomerSummary.class);
|
||||
var result = customers.findProjectedById(dave.getId(), CustomerSummary.class);
|
||||
|
||||
assertThat(result, is(notNullValue()));
|
||||
assertThat(result.getFullName(), is("Dave Matthews"));
|
||||
@@ -102,7 +102,7 @@ public class CustomerRepositoryIntegrationTest {
|
||||
@Test
|
||||
public void projectIndividualInstance() {
|
||||
|
||||
CustomerProjection result = customers.findProjectedById(dave.getId());
|
||||
var result = customers.findProjectedById(dave.getId());
|
||||
|
||||
assertThat(result, is(notNullValue()));
|
||||
assertThat(result.getFirstname(), is("Dave"));
|
||||
@@ -112,7 +112,7 @@ public class CustomerRepositoryIntegrationTest {
|
||||
@Test
|
||||
public void supportsProjectionInCombinationWithPagination() {
|
||||
|
||||
Page<CustomerProjection> page = customers
|
||||
var page = customers
|
||||
.findPagedProjectedBy(PageRequest.of(0, 1, Sort.by(Direction.ASC, "lastname")));
|
||||
|
||||
assertThat(page.getContent().get(0).getFirstname(), is("Carter"));
|
||||
|
||||
@@ -53,13 +53,13 @@ class UnwrappingIntegrationTests {
|
||||
@Test
|
||||
void documentStructure() {
|
||||
|
||||
org.bson.Document stored = operations.execute(User.class, collection -> {
|
||||
var stored = operations.execute(User.class, collection -> {
|
||||
return collection.find(Filters.eq("_id", rogelio.getId())).first();
|
||||
});
|
||||
|
||||
assertThat(stored).containsAllEntriesOf(new Document("_id", rogelio.getId())
|
||||
.append("username", rogelio.getUserName().getUsername())
|
||||
.append("primary_email", rogelio.getEmail().getEmail())
|
||||
.append("primary_email", rogelio.getEmail().email())
|
||||
);
|
||||
}
|
||||
|
||||
@@ -77,6 +77,6 @@ class UnwrappingIntegrationTests {
|
||||
*/
|
||||
@Test
|
||||
void queryViaPropertyOfValueType() {
|
||||
assertThat(repository.findByEmailEmail(jane.getEmail().getEmail())).isEqualTo(jane);
|
||||
assertThat(repository.findByEmailEmail(jane.getEmail().email())).isEqualTo(jane);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,14 +15,8 @@
|
||||
*/
|
||||
package example.springdata.mongodb.fluent;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
@Data
|
||||
class Human {
|
||||
|
||||
final String firstname;
|
||||
final String lastname;
|
||||
record Human(String firstname, String lastname) {
|
||||
}
|
||||
|
||||
@@ -15,8 +15,6 @@
|
||||
*/
|
||||
package example.springdata.mongodb.fluent;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.geo.Point;
|
||||
import org.springframework.data.mongodb.core.index.GeoSpatialIndexed;
|
||||
@@ -24,9 +22,6 @@ import org.springframework.data.mongodb.core.index.GeoSpatialIndexed;
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
@Data
|
||||
public class Planet {
|
||||
public record Planet(@Id String name, @GeoSpatialIndexed Point coordinates) {
|
||||
|
||||
final @Id String name;
|
||||
final @GeoSpatialIndexed Point coordinates;
|
||||
}
|
||||
|
||||
@@ -40,30 +40,30 @@ public class ApplicationConfiguration {
|
||||
template.dropCollection(COLLECTION);
|
||||
}
|
||||
|
||||
GeospatialIndex index = new GeospatialIndex("homePlanet.coordinates") //
|
||||
var index = new GeospatialIndex("homePlanet.coordinates") //
|
||||
.typed(GeoSpatialIndexType.GEO_2DSPHERE) //
|
||||
.named("planet-coordinate-idx");
|
||||
|
||||
template.createCollection(COLLECTION);
|
||||
template.indexOps(SWCharacter.class).ensureIndex(index);
|
||||
|
||||
Planet alderaan = new Planet("alderaan", new Point(-73.9667, 40.78));
|
||||
Planet stewjon = new Planet("stewjon", new Point(-73.9836, 40.7538));
|
||||
Planet tatooine = new Planet("tatooine", new Point(-73.9928, 40.7193));
|
||||
var alderaan = new Planet("alderaan", new Point(-73.9667, 40.78));
|
||||
var stewjon = new Planet("stewjon", new Point(-73.9836, 40.7538));
|
||||
var tatooine = new Planet("tatooine", new Point(-73.9928, 40.7193));
|
||||
|
||||
Jedi anakin = new Jedi("anakin", "skywalker");
|
||||
var anakin = new Jedi("anakin", "skywalker");
|
||||
anakin.setHomePlanet(tatooine);
|
||||
|
||||
Jedi luke = new Jedi("luke", "skywalker");
|
||||
var luke = new Jedi("luke", "skywalker");
|
||||
luke.setHomePlanet(tatooine);
|
||||
|
||||
Jedi leia = new Jedi("leia", "organa");
|
||||
var leia = new Jedi("leia", "organa");
|
||||
leia.setHomePlanet(alderaan);
|
||||
|
||||
Jedi obiWan = new Jedi("obi-wan", "kenobi");
|
||||
var obiWan = new Jedi("obi-wan", "kenobi");
|
||||
obiWan.setHomePlanet(stewjon);
|
||||
|
||||
Human han = new Human("han", "solo");
|
||||
var han = new Human("han", "solo");
|
||||
|
||||
template.save(anakin, COLLECTION);
|
||||
template.save(luke, COLLECTION);
|
||||
|
||||
@@ -111,7 +111,7 @@ public class FluentMongoApiTests {
|
||||
@Test
|
||||
public void fetchInterfaceProjection() {
|
||||
|
||||
Sith anakin = mongoOps.query(SWCharacter.class) // SWCharacter does only define the collection, id and name
|
||||
var anakin = mongoOps.query(SWCharacter.class) // SWCharacter does only define the collection, id and name
|
||||
.as(Sith.class) // use an interface as return type to create a projection
|
||||
.matching(query(where("firstname").is("anakin"))) // so properties are taken as is
|
||||
.oneValue();
|
||||
@@ -179,7 +179,7 @@ public class FluentMongoApiTests {
|
||||
@Test
|
||||
public void geoNearQuery() {
|
||||
|
||||
GeoResults<Jedi> results = mongoOps.query(SWCharacter.class) // SWCharacter defines collection, id and name
|
||||
var results = mongoOps.query(SWCharacter.class) // SWCharacter defines collection, id and name
|
||||
.as(Jedi.class) // but we want to map the results to Jedi
|
||||
.near(alderaanWithin3Parsecs) // and find those with home planet near alderaan
|
||||
.all();
|
||||
@@ -204,7 +204,7 @@ public class FluentMongoApiTests {
|
||||
@Test
|
||||
public void querySpecificCollection() {
|
||||
|
||||
List<Human> skywalkers = mongoOps.query(Human.class) // Human does not define a collection via @Document
|
||||
var skywalkers = mongoOps.query(Human.class) // Human does not define a collection via @Document
|
||||
.inCollection("star-wars") // so we set an explicit collection name
|
||||
.matching(query(where("lastname").is("skywalker"))) // to find all documents with a matching "lastname"
|
||||
.all();
|
||||
@@ -218,7 +218,7 @@ public class FluentMongoApiTests {
|
||||
@Test
|
||||
public void justInsertOne() {
|
||||
|
||||
SWCharacter chewbacca = new SWCharacter("Chewbacca");
|
||||
var chewbacca = new SWCharacter("Chewbacca");
|
||||
|
||||
mongoOps.insert(SWCharacter.class).one(chewbacca);
|
||||
|
||||
@@ -241,7 +241,7 @@ public class FluentMongoApiTests {
|
||||
@Test
|
||||
public void updateAndUpsert() {
|
||||
|
||||
UpdateResult result = mongoOps.update(Jedi.class) // Jedi defines the collection and field mapping
|
||||
var result = mongoOps.update(Jedi.class) // Jedi defines the collection and field mapping
|
||||
.matching(query(where("lastname").is("windu"))) // so "last" maps to "lastname".
|
||||
.apply(update("name", "mence")) // We'll update the "firstname" to "mence"
|
||||
.upsert(); // and add a new document if it does not exist already.
|
||||
|
||||
@@ -45,11 +45,11 @@ public class ApplicationConfiguration {
|
||||
*/
|
||||
public @Bean AbstractRepositoryPopulatorFactoryBean repositoryPopulator() {
|
||||
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
var mapper = new ObjectMapper();
|
||||
mapper.addMixIn(GeoJsonPoint.class, GeoJsonPointMixin.class);
|
||||
mapper.configure(FAIL_ON_UNKNOWN_PROPERTIES, false);
|
||||
|
||||
Jackson2RepositoryPopulatorFactoryBean factoryBean = new Jackson2RepositoryPopulatorFactoryBean();
|
||||
var factoryBean = new Jackson2RepositoryPopulatorFactoryBean();
|
||||
factoryBean.setResources(new Resource[] { new ClassPathResource("starbucks-in-nyc.json") });
|
||||
factoryBean.setMapper(mapper);
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
*/
|
||||
package example.springdata.mongodb.geojson;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.Value;
|
||||
|
||||
import org.springframework.data.mongodb.core.geo.GeoJsonPoint;
|
||||
import org.springframework.data.mongodb.core.mapping.Document;
|
||||
@@ -23,26 +23,7 @@ import org.springframework.data.mongodb.core.mapping.Document;
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
@Data
|
||||
@Document(collection = "starbucks")
|
||||
public class Store {
|
||||
public record Store(String id, String name, String street, String city, GeoJsonPoint location) {
|
||||
|
||||
String id;
|
||||
String name;
|
||||
String street;
|
||||
String city;
|
||||
|
||||
/**
|
||||
* {@code location} is stored in GeoJSON format.
|
||||
*
|
||||
* <pre>
|
||||
* <code>
|
||||
* {
|
||||
* "type" : "Point",
|
||||
* "coordinates" : [ x, y ]
|
||||
* }
|
||||
* </code>
|
||||
* </pre>
|
||||
*/
|
||||
GeoJsonPoint location;
|
||||
}
|
||||
|
||||
@@ -114,11 +114,11 @@ public class StoreRepositoryTests {
|
||||
@Test
|
||||
public void findStoresThatIntersectGivenPolygon() {
|
||||
|
||||
Document geoJsonDbo = new Document();
|
||||
var geoJsonDbo = new Document();
|
||||
|
||||
operations.getConverter().write(GEO_JSON_POLYGON, geoJsonDbo);
|
||||
|
||||
BasicQuery bq = new BasicQuery(
|
||||
var bq = new BasicQuery(
|
||||
new Document("location", new Document("$geoIntersects", new Document("$geometry", geoJsonDbo))));
|
||||
|
||||
operations.find(bq, Store.class).forEach(System.out::println);
|
||||
|
||||
@@ -15,25 +15,9 @@
|
||||
*/
|
||||
package example.springdata.mongodb.gridfs;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import org.springframework.data.annotation.Id;
|
||||
|
||||
/**
|
||||
* @author Hartmut Lang
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
public class Customer {
|
||||
public record Customer(String firstName, String lastName) {
|
||||
|
||||
@Id private String id;
|
||||
|
||||
private String firstName;
|
||||
private String lastName;
|
||||
|
||||
public Customer(String firstName, String lastName) {
|
||||
this.firstName = firstName;
|
||||
this.lastName = lastName;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,7 +65,7 @@ public class GridFsTests {
|
||||
}
|
||||
|
||||
// get file or resource by filename
|
||||
GridFSFile file = gridFsOperations.findOne(query(whereFilename().is("example-file.txt")));
|
||||
var file = gridFsOperations.findOne(query(whereFilename().is("example-file.txt")));
|
||||
|
||||
assertThat(file.getFilename()).isEqualTo("example-file.txt");
|
||||
}
|
||||
@@ -76,12 +76,12 @@ public class GridFsTests {
|
||||
try (InputStream is = new BufferedInputStream(new ClassPathResource("./example-file.txt").getInputStream())) {
|
||||
|
||||
// store file with metaData
|
||||
Customer customerMetaData = new Customer("Hardy", "Lang");
|
||||
var customerMetaData = new Customer("Hardy", "Lang");
|
||||
gridFsOperations.store(is, "example-file.txt", customerMetaData);
|
||||
}
|
||||
|
||||
// search by metaData
|
||||
GridFSFile file = gridFsOperations.findOne(query(whereMetaData("firstName").is("Hardy")));
|
||||
var file = gridFsOperations.findOne(query(whereMetaData("firstName").is("Hardy")));
|
||||
assertThat(file.getFilename()).isEqualTo("example-file.txt");
|
||||
}
|
||||
|
||||
@@ -96,10 +96,10 @@ public class GridFsTests {
|
||||
// store file
|
||||
gridFsOperations.store(new ByteArrayInputStream(bytes), "example-file.txt");
|
||||
|
||||
GridFsResource resource = gridFsOperations.getResource("example-file.txt");
|
||||
var resource = gridFsOperations.getResource("example-file.txt");
|
||||
|
||||
byte[] loaded;
|
||||
try (InputStream is = resource.getInputStream()) {
|
||||
try (var is = resource.getInputStream()) {
|
||||
loaded = StreamUtils.copyToByteArray(is);
|
||||
}
|
||||
|
||||
|
||||
@@ -15,12 +15,8 @@
|
||||
*/
|
||||
package example.springdata.mongodb.customer;
|
||||
|
||||
import lombok.Value;
|
||||
|
||||
import org.jmolecules.ddd.annotation.ValueObject;
|
||||
|
||||
@Value
|
||||
@ValueObject
|
||||
public class Address {
|
||||
private final String street, city, zipCode;
|
||||
public record Address(String street, String city, String zipCode) {
|
||||
}
|
||||
|
||||
@@ -15,12 +15,8 @@
|
||||
*/
|
||||
package example.springdata.mongodb.order;
|
||||
|
||||
import lombok.Value;
|
||||
|
||||
import org.jmolecules.ddd.annotation.ValueObject;
|
||||
|
||||
@Value
|
||||
@ValueObject
|
||||
public class LineItem {
|
||||
String description;
|
||||
public record LineItem(String description) {
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ public class Order implements AggregateRoot<Order, Order.OrderId> {
|
||||
|
||||
public Order addLineItem(String description) {
|
||||
|
||||
LineItem item = new LineItem(description);
|
||||
var item = new LineItem(description);
|
||||
|
||||
this.lineItems.add(item);
|
||||
|
||||
@@ -61,7 +61,7 @@ public class Order implements AggregateRoot<Order, Order.OrderId> {
|
||||
@Value(staticConstructor = "of")
|
||||
public static class OrderId implements Identifier {
|
||||
|
||||
private final UUID orderId;
|
||||
UUID orderId;
|
||||
|
||||
public static OrderId create() {
|
||||
return OrderId.of(UUID.randomUUID());
|
||||
|
||||
@@ -25,11 +25,10 @@ import example.springdata.mongodb.order.Orders;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
|
||||
|
||||
/**
|
||||
* @author Oliver Drotbohm
|
||||
@@ -43,9 +42,9 @@ class ApplicationIntegrationTests {
|
||||
@Test
|
||||
void exposesAssociationInMetamodel() {
|
||||
|
||||
MongoMappingContext mapping = context.getBean(MongoMappingContext.class);
|
||||
MongoPersistentEntity<?> entity = mapping.getRequiredPersistentEntity(Order.class);
|
||||
MongoPersistentProperty customer = entity.getRequiredPersistentProperty("customer");
|
||||
var mapping = context.getBean(MongoMappingContext.class);
|
||||
var entity = mapping.getRequiredPersistentEntity(Order.class);
|
||||
var customer = entity.getRequiredPersistentProperty("customer");
|
||||
|
||||
assertThat(customer.isAssociation()).isTrue();
|
||||
}
|
||||
@@ -53,19 +52,19 @@ class ApplicationIntegrationTests {
|
||||
@Test
|
||||
void persistsDomainModel() {
|
||||
|
||||
Address address = new Address("41 Greystreet", "Dreaming Tree", "2731");
|
||||
var address = new Address("41 Greystreet", "Dreaming Tree", "2731");
|
||||
|
||||
Customers customers = context.getBean(Customers.class);
|
||||
Customer customer = customers.save(new Customer("Dave", "Matthews", address));
|
||||
var customers = context.getBean(Customers.class);
|
||||
var customer = customers.save(new Customer("Dave", "Matthews", address));
|
||||
|
||||
Orders orders = context.getBean(Orders.class);
|
||||
var orders = context.getBean(Orders.class);
|
||||
|
||||
Order order = new Order(customer)
|
||||
var order = new Order(customer)
|
||||
.addLineItem("Foo")
|
||||
.addLineItem("Bar");
|
||||
|
||||
Order result = orders.save(order);
|
||||
var result = orders.save(order);
|
||||
|
||||
assertThat(customers.resolveRequired(result.getCustomer()));
|
||||
assertThat(customers.resolveRequired(result.getCustomer())).isNotNull();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,7 +68,7 @@ public class ContactRepositoryIntegrationTests {
|
||||
@Test
|
||||
public void countByConcreteSubtypeExample() {
|
||||
|
||||
Example<Person> example = Example.of(new Person(null, null, null));
|
||||
var example = Example.of(new Person(null, null, null));
|
||||
|
||||
assertThat(userRepository.count(example), is(3L));
|
||||
}
|
||||
@@ -79,7 +79,7 @@ public class ContactRepositoryIntegrationTests {
|
||||
@Test
|
||||
public void findAllPersonsBySimpleExample() {
|
||||
|
||||
Example<Person> example = Example.of(new Person(".*", null, null), //
|
||||
var example = Example.of(new Person(".*", null, null), //
|
||||
matching().withStringMatcher(StringMatcher.REGEX));
|
||||
|
||||
assertThat(userRepository.findAll(example), containsInAnyOrder(skyler, walter, flynn));
|
||||
@@ -92,7 +92,7 @@ public class ContactRepositoryIntegrationTests {
|
||||
@Test
|
||||
public void findAllRelativesBySimpleExample() {
|
||||
|
||||
Example<Relative> example = Example.of(new Relative(".*", null, null), //
|
||||
var example = Example.of(new Relative(".*", null, null), //
|
||||
matching().withStringMatcher(StringMatcher.REGEX));
|
||||
|
||||
assertThat(contactRepository.findAll(example), containsInAnyOrder(hank, marie));
|
||||
|
||||
@@ -76,7 +76,7 @@ public class MongoOperationsIntegrationTests {
|
||||
@Test
|
||||
public void ignoreNullProperties() {
|
||||
|
||||
Query query = query(byExample(new Person(null, null, 17)));
|
||||
var query = query(byExample(new Person(null, null, 17)));
|
||||
|
||||
assertThat(operations.find(query, Person.class), hasItems(flynn));
|
||||
}
|
||||
@@ -87,7 +87,7 @@ public class MongoOperationsIntegrationTests {
|
||||
@Test
|
||||
public void substringMatching() {
|
||||
|
||||
Example<Person> example = Example.of(new Person("er", null, null), matching().//
|
||||
var example = Example.of(new Person("er", null, null), matching().//
|
||||
withStringMatcher(StringMatcher.ENDING));
|
||||
|
||||
assertThat(operations.find(query(byExample(example)), Person.class), hasItems(skyler, walter));
|
||||
@@ -99,8 +99,8 @@ public class MongoOperationsIntegrationTests {
|
||||
@Test
|
||||
public void regexMatching() {
|
||||
|
||||
Example<Person> example = Example.of(new Person("(Skyl|Walt)er", null, null), matching().//
|
||||
withMatcher("firstname", matcher -> matcher.regex()));
|
||||
var example = Example.of(new Person("(Skyl|Walt)er", null, null), matching().//
|
||||
withMatcher("firstname", GenericPropertyMatcher::regex));
|
||||
|
||||
assertThat(operations.find(query(byExample(example)), Person.class), hasItems(skyler, walter));
|
||||
}
|
||||
@@ -111,7 +111,7 @@ public class MongoOperationsIntegrationTests {
|
||||
@Test
|
||||
public void matchStartingStringsIgnoreCase() {
|
||||
|
||||
Example<Person> example = Example.of(new Person("Walter", "WHITE", null), matching(). //
|
||||
var example = Example.of(new Person("Walter", "WHITE", null), matching(). //
|
||||
withIgnorePaths("age").//
|
||||
withMatcher("firstname", startsWith()).//
|
||||
withMatcher("lastname", ignoreCase()));
|
||||
@@ -125,10 +125,10 @@ public class MongoOperationsIntegrationTests {
|
||||
@Test
|
||||
public void configuringMatchersUsingLambdas() {
|
||||
|
||||
Example<Person> example = Example.of(new Person("Walter", "WHITE", null), matching().//
|
||||
var example = Example.of(new Person("Walter", "WHITE", null), matching().//
|
||||
withIgnorePaths("age"). //
|
||||
withMatcher("firstname", matcher -> matcher.startsWith()). //
|
||||
withMatcher("lastname", matcher -> matcher.ignoreCase()));
|
||||
withMatcher("firstname", GenericPropertyMatcher::startsWith). //
|
||||
withMatcher("lastname", GenericPropertyMatcher::ignoreCase));
|
||||
|
||||
assertThat(operations.find(query(byExample(example)), Person.class), hasItems(flynn, walter));
|
||||
}
|
||||
@@ -139,8 +139,8 @@ public class MongoOperationsIntegrationTests {
|
||||
@Test
|
||||
public void valueTransformer() {
|
||||
|
||||
Example<Person> example = Example.of(new Person(null, "White", 99), matching(). //
|
||||
withMatcher("age", matcher -> matcher.transform(value -> Optional.of(Integer.valueOf(50)))));
|
||||
var example = Example.of(new Person(null, "White", 99), matching(). //
|
||||
withMatcher("age", matcher -> matcher.transform(value -> Optional.of(50))));
|
||||
|
||||
assertThat(operations.find(query(byExample(example)), Person.class), hasItems(walter));
|
||||
}
|
||||
|
||||
@@ -64,7 +64,7 @@ public class UserRepositoryIntegrationTests {
|
||||
@Test
|
||||
public void countBySimpleExample() {
|
||||
|
||||
Example<Person> example = Example.of(new Person(null, "White", null));
|
||||
var example = Example.of(new Person(null, "White", null));
|
||||
|
||||
assertThat(repository.count(example)).isEqualTo(3L);
|
||||
}
|
||||
@@ -75,7 +75,7 @@ public class UserRepositoryIntegrationTests {
|
||||
@Test
|
||||
public void ignorePropertiesAndMatchByAge() {
|
||||
|
||||
Example<Person> example = Example.of(flynn, matching(). //
|
||||
var example = Example.of(flynn, matching(). //
|
||||
withIgnorePaths("firstname", "lastname"));
|
||||
|
||||
assertThat(repository.findOne(example)).contains(flynn);
|
||||
@@ -87,7 +87,7 @@ public class UserRepositoryIntegrationTests {
|
||||
@Test
|
||||
public void substringMatching() {
|
||||
|
||||
Example<Person> example = Example.of(new Person("er", null, null), matching(). //
|
||||
var example = Example.of(new Person("er", null, null), matching(). //
|
||||
withStringMatcher(StringMatcher.ENDING));
|
||||
|
||||
assertThat(repository.findAll(example)).containsExactlyInAnyOrder(skyler, walter);
|
||||
@@ -99,8 +99,8 @@ public class UserRepositoryIntegrationTests {
|
||||
@Test
|
||||
public void regexMatching() {
|
||||
|
||||
Example<Person> example = Example.of(new Person("(Skyl|Walt)er", null, null), matching(). //
|
||||
withMatcher("firstname", matcher -> matcher.regex()));
|
||||
var example = Example.of(new Person("(Skyl|Walt)er", null, null), matching(). //
|
||||
withMatcher("firstname", GenericPropertyMatcher::regex));
|
||||
|
||||
assertThat(repository.findAll(example)).contains(skyler, walter);
|
||||
}
|
||||
@@ -111,7 +111,7 @@ public class UserRepositoryIntegrationTests {
|
||||
@Test
|
||||
public void matchStartingStringsIgnoreCase() {
|
||||
|
||||
Example<Person> example = Example.of(new Person("Walter", "WHITE", null), matching(). //
|
||||
var example = Example.of(new Person("Walter", "WHITE", null), matching(). //
|
||||
withIgnorePaths("age"). //
|
||||
withMatcher("firstname", startsWith()). //
|
||||
withMatcher("lastname", ignoreCase()));
|
||||
@@ -125,10 +125,10 @@ public class UserRepositoryIntegrationTests {
|
||||
@Test
|
||||
public void configuringMatchersUsingLambdas() {
|
||||
|
||||
Example<Person> example = Example.of(new Person("Walter", "WHITE", null), matching(). //
|
||||
var example = Example.of(new Person("Walter", "WHITE", null), matching(). //
|
||||
withIgnorePaths("age"). //
|
||||
withMatcher("firstname", matcher -> matcher.startsWith()). //
|
||||
withMatcher("lastname", matcher -> matcher.ignoreCase()));
|
||||
withMatcher("firstname", GenericPropertyMatcher::startsWith). //
|
||||
withMatcher("lastname", GenericPropertyMatcher::ignoreCase));
|
||||
|
||||
assertThat(repository.findAll(example)).containsExactlyInAnyOrder(flynn, walter);
|
||||
}
|
||||
@@ -139,8 +139,8 @@ public class UserRepositoryIntegrationTests {
|
||||
@Test
|
||||
public void valueTransformer() {
|
||||
|
||||
Example<Person> example = Example.of(new Person(null, "White", 99), matching(). //
|
||||
withMatcher("age", matcher -> matcher.transform(value -> Optional.of(Integer.valueOf(50)))));
|
||||
var example = Example.of(new Person(null, "White", 99), matching(). //
|
||||
withMatcher("age", matcher -> matcher.transform(value -> Optional.of(50))));
|
||||
|
||||
assertThat(repository.findAll(example)).containsExactlyInAnyOrder(walter);
|
||||
}
|
||||
|
||||
@@ -80,7 +80,7 @@ public class Customer {
|
||||
if (o == null || getClass() != o.getClass())
|
||||
return false;
|
||||
|
||||
Customer customer = (Customer) o;
|
||||
var customer = (Customer) o;
|
||||
|
||||
if (id != null ? !id.equals(customer.id) : customer.id != null)
|
||||
return false;
|
||||
@@ -91,7 +91,7 @@ public class Customer {
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = id != null ? id.hashCode() : 0;
|
||||
var result = id != null ? id.hashCode() : 0;
|
||||
result = 31 * result + (firstname != null ? firstname.hashCode() : 0);
|
||||
result = 31 * result + (lastname != null ? lastname.hashCode() : 0);
|
||||
return result;
|
||||
|
||||
@@ -15,10 +15,8 @@
|
||||
*/
|
||||
package example.springdata.mongodb.people;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.annotation.PersistenceConstructor;
|
||||
import org.springframework.data.mongodb.core.mapping.Document;
|
||||
|
||||
/**
|
||||
@@ -26,13 +24,14 @@ import org.springframework.data.mongodb.core.mapping.Document;
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
@Data
|
||||
@RequiredArgsConstructor
|
||||
@Document
|
||||
public class Person {
|
||||
public record Person(@Id String id, String firstname, String lastname, int age) {
|
||||
|
||||
private @Id String id;
|
||||
private final String firstname;
|
||||
private final String lastname;
|
||||
private final int age;
|
||||
@PersistenceConstructor
|
||||
public Person {
|
||||
}
|
||||
|
||||
public Person(String firstname, String lastname, int age) {
|
||||
this(null, firstname, lastname, age);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ public class ReactiveMongoTemplateIntegrationTest {
|
||||
|
||||
StepVerifier.create(template.dropCollection(Person.class)).verifyComplete();
|
||||
|
||||
Flux<Person> insertAll = template
|
||||
var insertAll = template
|
||||
.insertAll(Flux.just(new Person("Walter", "White", 50), //
|
||||
new Person("Skyler", "White", 45), //
|
||||
new Person("Saul", "Goodman", 42), //
|
||||
@@ -66,7 +66,7 @@ public class ReactiveMongoTemplateIntegrationTest {
|
||||
@Test
|
||||
public void shouldInsertAndCountData() {
|
||||
|
||||
Mono<Long> count = template.count(new Query(), Person.class) //
|
||||
var count = template.count(new Query(), Person.class) //
|
||||
.doOnNext(System.out::println) //
|
||||
.thenMany(template.insertAll(Arrays.asList(new Person("Hank", "Schrader", 43), //
|
||||
new Person("Mike", "Ehrmantraut", 62)))) //
|
||||
@@ -83,7 +83,7 @@ public class ReactiveMongoTemplateIntegrationTest {
|
||||
@Test
|
||||
public void convertReactorTypesToRxJava2() {
|
||||
|
||||
Flux<Person> flux = template.find(Query.query(Criteria.where("lastname").is("White")), Person.class);
|
||||
var flux = template.find(Query.query(Criteria.where("lastname").is("White")), Person.class);
|
||||
|
||||
long count = RxReactiveStreams.toObservable(flux).count().toSingle().toBlocking().value();
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@ public class ReactivePersonRepositoryIntegrationTest {
|
||||
@Before
|
||||
public void setUp() {
|
||||
|
||||
Mono<MongoCollection<Document>> recreateCollection = operations.collectionExists(Person.class) //
|
||||
var recreateCollection = operations.collectionExists(Person.class) //
|
||||
.flatMap(exists -> exists ? operations.dropCollection(Person.class) : Mono.just(exists)) //
|
||||
.then(operations.createCollection(Person.class, CollectionOptions.empty() //
|
||||
.size(1024 * 1024) //
|
||||
@@ -61,7 +61,7 @@ public class ReactivePersonRepositoryIntegrationTest {
|
||||
|
||||
StepVerifier.create(recreateCollection).expectNextCount(1).verifyComplete();
|
||||
|
||||
Flux<Person> insertAll = operations.insertAll(Flux.just(new Person("Walter", "White", 50), //
|
||||
var insertAll = operations.insertAll(Flux.just(new Person("Walter", "White", 50), //
|
||||
new Person("Skyler", "White", 45), //
|
||||
new Person("Saul", "Goodman", 42), //
|
||||
new Person("Jesse", "Pinkman", 27)).collectList());
|
||||
@@ -76,7 +76,7 @@ public class ReactivePersonRepositoryIntegrationTest {
|
||||
@Test
|
||||
public void shouldInsertAndCountData() {
|
||||
|
||||
Mono<Long> saveAndCount = repository.count() //
|
||||
var saveAndCount = repository.count() //
|
||||
.doOnNext(System.out::println) //
|
||||
.thenMany(repository.saveAll(Flux.just(new Person("Hank", "Schrader", 43), //
|
||||
new Person("Mike", "Ehrmantraut", 62)))) //
|
||||
@@ -106,7 +106,7 @@ public class ReactivePersonRepositoryIntegrationTest {
|
||||
|
||||
Queue<Person> people = new ConcurrentLinkedQueue<>();
|
||||
|
||||
Disposable disposable = repository.findWithTailableCursorBy() //
|
||||
var disposable = repository.findWithTailableCursorBy() //
|
||||
.doOnNext(System.out::println) //
|
||||
.doOnNext(people::add) //
|
||||
.doOnComplete(() -> System.out.println("Complete")) //
|
||||
|
||||
@@ -57,7 +57,7 @@ public class RxJava2PersonRepositoryIntegrationTest {
|
||||
@Before
|
||||
public void setUp() {
|
||||
|
||||
Mono<MongoCollection<Document>> recreateCollection = operations.collectionExists(Person.class) //
|
||||
var recreateCollection = operations.collectionExists(Person.class) //
|
||||
.flatMap(exists -> exists ? operations.dropCollection(Person.class) : Mono.just(exists)) //
|
||||
.then(operations.createCollection(Person.class, CollectionOptions.empty() //
|
||||
.size(1024 * 1024) //
|
||||
@@ -83,7 +83,7 @@ public class RxJava2PersonRepositoryIntegrationTest {
|
||||
@Test
|
||||
public void shouldInsertAndCountData() {
|
||||
|
||||
Flowable<Person> people = Flowable.just(new Person("Hank", "Schrader", 43), //
|
||||
var people = Flowable.just(new Person("Hank", "Schrader", 43), //
|
||||
new Person("Mike", "Ehrmantraut", 62));
|
||||
|
||||
repository.count() //
|
||||
@@ -124,7 +124,7 @@ public class RxJava2PersonRepositoryIntegrationTest {
|
||||
|
||||
Queue<Person> people = new ConcurrentLinkedQueue<>();
|
||||
|
||||
Disposable subscription = repository.findWithTailableCursorBy() //
|
||||
var subscription = repository.findWithTailableCursorBy() //
|
||||
.doOnNext(System.out::println) //
|
||||
.doOnNext(people::add) //
|
||||
.doOnComplete(() -> System.out.println("Complete")) //
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
Configure a `RepositoryMethodInvocationListener` to capture invocation metrics on `Repository` interfaces.
|
||||
|
||||
```java
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
class RepositoryMetricsConfiguration {
|
||||
|
||||
@@ -16,13 +17,13 @@ class RepositoryMetricsConfiguration {
|
||||
@Override
|
||||
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
|
||||
|
||||
if (bean instanceof RepositoryFactoryBeanSupport) {
|
||||
if (bean instanceof RepositoryFactoryBeanSupport<?, ?, ?> repositoryFactoryBean) {
|
||||
|
||||
RepositoryFactoryBeanSupport<?, ?, ?> repositoryFactoryBean = (RepositoryFactoryBeanSupport<?, ?, ?>) bean;
|
||||
|
||||
repositoryFactoryBean.addRepositoryFactoryCustomizer(repositoryFactory -> {
|
||||
repositoryFactory.addInvocationListener(System.out::println); // register the invocation listener
|
||||
});
|
||||
repositoryFactoryBean
|
||||
.addRepositoryFactoryCustomizer(repositoryFactory -> {
|
||||
repositoryFactory
|
||||
.addInvocationListener(System.out::println); // register the invocation listener
|
||||
});
|
||||
}
|
||||
|
||||
return bean;
|
||||
|
||||
@@ -20,30 +20,6 @@ import org.springframework.data.annotation.Id;
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
public class Person {
|
||||
public record Person(@Id String id, String name) {
|
||||
|
||||
@Id String id;
|
||||
|
||||
String name;
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Person{" + "id='" + id + '\'' + ", name='" + name + '\'' + '}';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,9 +37,7 @@ public class RepositoryMetricsConfiguration {
|
||||
@Override
|
||||
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
|
||||
|
||||
if (bean instanceof RepositoryFactoryBeanSupport) {
|
||||
|
||||
RepositoryFactoryBeanSupport<?, ?, ?> repositoryFactoryBean = (RepositoryFactoryBeanSupport<?, ?, ?>) bean;
|
||||
if (bean instanceof RepositoryFactoryBeanSupport<?, ?, ?> repositoryFactoryBean) {
|
||||
|
||||
repositoryFactoryBean.addRepositoryFactoryCustomizer(repositoryFactory -> {
|
||||
repositoryFactory.addInvocationListener(System.out::println);
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
*/
|
||||
package example.springdata.mongodb;
|
||||
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.test.StepVerifier;
|
||||
|
||||
import java.time.Duration;
|
||||
@@ -39,19 +38,15 @@ class DemoApplicationTests {
|
||||
@Test
|
||||
void repositoryMetrics() throws InterruptedException {
|
||||
|
||||
Person fiona = new Person();
|
||||
fiona.id = "p-1";
|
||||
fiona.name = "fiona";
|
||||
var fiona = new Person("p-1", "fiona");
|
||||
|
||||
Person frank = new Person();
|
||||
frank.id = "p-2";
|
||||
frank.name = "frank";
|
||||
var frank = new Person("p-2", "frank");
|
||||
|
||||
System.out.println("- Execute - Save Fiona -");
|
||||
repo.save(fiona).then().as(StepVerifier::create).verifyComplete();
|
||||
|
||||
System.out.println("- Prepare - Find All -"); // Nothing captured - Invocation will happen in line 53 when subscribing
|
||||
Flux<Person> all = repo.findAll();
|
||||
var all = repo.findAll();
|
||||
|
||||
System.out.println("- Execute - Save Frank -");
|
||||
repo.save(frank).as(StepVerifier::create).expectNextCount(1).verifyComplete();
|
||||
|
||||
@@ -15,10 +15,6 @@
|
||||
*/
|
||||
package example.springdata.mongodb.schema;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.mongodb.core.mapping.Document;
|
||||
import org.springframework.lang.Nullable;
|
||||
@@ -26,14 +22,7 @@ import org.springframework.lang.Nullable;
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Document("star-wars")
|
||||
class Jedi {
|
||||
record Jedi(@Id String id, @Nullable String name, @Nullable String lastname, @Nullable Integer age) {
|
||||
|
||||
@Id String id;
|
||||
@Nullable String name;
|
||||
@Nullable String lastname;
|
||||
@Nullable Integer age;
|
||||
}
|
||||
|
||||
@@ -74,7 +74,7 @@ public class DocumentValidation {
|
||||
@Test
|
||||
public void criteriaValidator() {
|
||||
|
||||
Validator validator = Validator.criteria( //
|
||||
var validator = Validator.criteria( //
|
||||
where("name").exists(true).ne(null).type(2) // non null String
|
||||
.and("age").exists(true).ne(null).type(16).gte(0).lte(125)) // non null int between 0 and 125
|
||||
;
|
||||
@@ -116,7 +116,7 @@ public class DocumentValidation {
|
||||
@Test
|
||||
public void schemaValidator() {
|
||||
|
||||
Validator validator = Validator.schema(MongoJsonSchema.builder() //
|
||||
var validator = Validator.schema(MongoJsonSchema.builder() //
|
||||
.required("name", "age") //
|
||||
.properties( //
|
||||
string("name").minLength(1), //
|
||||
|
||||
@@ -75,13 +75,13 @@ public class SchemaQuery {
|
||||
@Test
|
||||
public void criteriaValidator() {
|
||||
|
||||
Jedi luke = new Jedi("luke", "luke", "skywalker", 25);
|
||||
Jedi yoda = new Jedi("yoda", "yoda", null, 900);
|
||||
var luke = new Jedi("luke", "luke", "skywalker", 25);
|
||||
var yoda = new Jedi("yoda", "yoda", null, 900);
|
||||
|
||||
mongoOps.save(luke);
|
||||
mongoOps.save(yoda);
|
||||
|
||||
MongoJsonSchema schema = MongoJsonSchema.builder() //
|
||||
var schema = MongoJsonSchema.builder() //
|
||||
.required("name", "age") //
|
||||
.properties( //
|
||||
string("name").minLength(1), //
|
||||
|
||||
@@ -15,21 +15,21 @@
|
||||
*/
|
||||
package example.springdata.mongodb.security;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.annotation.PersistenceConstructor;
|
||||
|
||||
/**
|
||||
* An entity to represent a {@link Person}.
|
||||
*
|
||||
* @author Thomas Darimont
|
||||
*/
|
||||
@Data
|
||||
@RequiredArgsConstructor
|
||||
public class Person {
|
||||
public record Person(@Id String id, String firstname, String lastname) {
|
||||
|
||||
private @Id String id;
|
||||
private final String firstname;
|
||||
private final String lastname;
|
||||
@PersistenceConstructor
|
||||
public Person {
|
||||
}
|
||||
|
||||
public Person(String firstname, String lastname) {
|
||||
this(null, firstname, lastname);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@ public class PersonRepositoryIntegrationTest {
|
||||
|
||||
SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken(dave, "x"));
|
||||
|
||||
List<Person> persons = repository.findAllForCurrentUserById();
|
||||
var persons = repository.findAllForCurrentUserById();
|
||||
|
||||
assertThat(persons, hasSize(1));
|
||||
assertThat(persons, contains(dave));
|
||||
@@ -70,11 +70,11 @@ public class PersonRepositoryIntegrationTest {
|
||||
@Test
|
||||
public void adminCallingShouldReturnAllUsers() throws Exception {
|
||||
|
||||
UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(admin, "x",
|
||||
var auth = new UsernamePasswordAuthenticationToken(admin, "x",
|
||||
Collections.singleton(new SimpleGrantedAuthority("ROLE_ADMIN")));
|
||||
SecurityContextHolder.getContext().setAuthentication(auth);
|
||||
|
||||
List<Person> persons = repository.findAllForCurrentUserById();
|
||||
var persons = repository.findAllForCurrentUserById();
|
||||
|
||||
assertThat(persons, hasSize(4));
|
||||
assertThat(persons, containsInAnyOrder(admin, dave, carter, oliver));
|
||||
|
||||
@@ -17,8 +17,6 @@ package example.springdata.mongodb.textsearch;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.mongodb.core.index.TextIndexed;
|
||||
import org.springframework.data.mongodb.core.mapping.Document;
|
||||
@@ -31,17 +29,7 @@ import org.springframework.data.mongodb.core.mapping.TextScore;
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@Document
|
||||
@Data
|
||||
public class BlogPost {
|
||||
public record BlogPost(@Id String id, @TextIndexed(weight = 3) String title, @TextIndexed(weight = 2) String content,
|
||||
@TextIndexed List<String> categories, @TextScore Float score) {
|
||||
|
||||
private @Id String id;
|
||||
private @TextIndexed(weight = 3) String title;
|
||||
private @TextIndexed(weight = 2) String content;
|
||||
private @TextIndexed List<String> categories;
|
||||
private @TextScore Float score;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "BlogPost [id=" + id + ", score=" + score + ", title=" + title + ", categories=" + categories + "]";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ public class MongoTestConfiguration {
|
||||
|
||||
public @Bean Jackson2RepositoryPopulatorFactoryBean repositoryPopulator() {
|
||||
|
||||
Jackson2RepositoryPopulatorFactoryBean factoryBean = new Jackson2RepositoryPopulatorFactoryBean();
|
||||
var factoryBean = new Jackson2RepositoryPopulatorFactoryBean();
|
||||
factoryBean.setResources(new Resource[] { new ClassPathResource("spring-blog.atom.json") });
|
||||
return factoryBean;
|
||||
}
|
||||
@@ -49,7 +49,7 @@ public class MongoTestConfiguration {
|
||||
@PostConstruct
|
||||
private void postConstruct() {
|
||||
|
||||
IndexResolver resolver = IndexResolver.create(operations.getConverter().getMappingContext());
|
||||
var resolver = IndexResolver.create(operations.getConverter().getMappingContext());
|
||||
|
||||
resolver.resolveIndexFor(BlogPost.class).forEach(operations.indexOps(BlogPost.class)::ensureIndex);
|
||||
}
|
||||
|
||||
@@ -47,8 +47,8 @@ public class TextSearchRepositoryTests {
|
||||
@Test
|
||||
public void findAllBlogPostsWithRelease() {
|
||||
|
||||
TextCriteria criteria = TextCriteria.forDefaultLanguage().matchingAny("release");
|
||||
List<BlogPost> blogPosts = repo.findAllBy(criteria);
|
||||
var criteria = TextCriteria.forDefaultLanguage().matchingAny("release");
|
||||
var blogPosts = repo.findAllBy(criteria);
|
||||
|
||||
printResult(blogPosts, criteria);
|
||||
}
|
||||
@@ -59,8 +59,8 @@ public class TextSearchRepositoryTests {
|
||||
@Test
|
||||
public void findAllBlogPostsWithReleaseButHeyIDoWantTheEngineeringStuff() {
|
||||
|
||||
TextCriteria criteria = TextCriteria.forDefaultLanguage().matchingAny("release").notMatching("engineering");
|
||||
List<BlogPost> blogPosts = repo.findAllBy(criteria);
|
||||
var criteria = TextCriteria.forDefaultLanguage().matchingAny("release").notMatching("engineering");
|
||||
var blogPosts = repo.findAllBy(criteria);
|
||||
|
||||
printResult(blogPosts, criteria);
|
||||
}
|
||||
@@ -71,8 +71,8 @@ public class TextSearchRepositoryTests {
|
||||
@Test
|
||||
public void findAllBlogPostsByPhrase() {
|
||||
|
||||
TextCriteria criteria = TextCriteria.forDefaultLanguage().matchingPhrase("release candidate");
|
||||
List<BlogPost> blogPosts = repo.findAllBy(criteria);
|
||||
var criteria = TextCriteria.forDefaultLanguage().matchingPhrase("release candidate");
|
||||
var blogPosts = repo.findAllBy(criteria);
|
||||
|
||||
printResult(blogPosts, criteria);
|
||||
}
|
||||
@@ -83,8 +83,8 @@ public class TextSearchRepositoryTests {
|
||||
@Test
|
||||
public void findAllBlogPostsByPhraseSortByScore() {
|
||||
|
||||
TextCriteria criteria = TextCriteria.forDefaultLanguage().matchingPhrase("release candidate");
|
||||
List<BlogPost> blogPosts = repo.findAllByOrderByScoreDesc(criteria);
|
||||
var criteria = TextCriteria.forDefaultLanguage().matchingPhrase("release candidate");
|
||||
var blogPosts = repo.findAllByOrderByScoreDesc(criteria);
|
||||
|
||||
printResult(blogPosts, criteria);
|
||||
}
|
||||
|
||||
@@ -59,8 +59,8 @@ public class TextSearchTemplateTests {
|
||||
@Test
|
||||
public void findAllBlogPostsWithRelease() {
|
||||
|
||||
TextCriteria criteria = TextCriteria.forDefaultLanguage().matchingAny("release");
|
||||
List<BlogPost> blogPosts = operations.find(query(criteria), BlogPost.class);
|
||||
var criteria = TextCriteria.forDefaultLanguage().matchingAny("release");
|
||||
var blogPosts = operations.find(query(criteria), BlogPost.class);
|
||||
|
||||
printResult(blogPosts, criteria);
|
||||
}
|
||||
@@ -71,13 +71,13 @@ public class TextSearchTemplateTests {
|
||||
@Test
|
||||
public void findAllBlogPostsByPhraseSortByScore() {
|
||||
|
||||
TextCriteria criteria = TextCriteria.forDefaultLanguage().matchingPhrase("release");
|
||||
var criteria = TextCriteria.forDefaultLanguage().matchingPhrase("release");
|
||||
|
||||
TextQuery query = new TextQuery(criteria);
|
||||
var query = new TextQuery(criteria);
|
||||
query.setScoreFieldName("score");
|
||||
query.sortByScore();
|
||||
|
||||
List<BlogPost> blogPosts = operations.find(query, BlogPost.class);
|
||||
var blogPosts = operations.find(query, BlogPost.class);
|
||||
|
||||
printResult(blogPosts, criteria);
|
||||
}
|
||||
|
||||
@@ -50,12 +50,12 @@ public enum BlogPostInitializer {
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
private void loadFromClasspathSource(MongoOperations operations) throws Exception {
|
||||
|
||||
Jackson2ResourceReader reader = new Jackson2ResourceReader();
|
||||
var reader = new Jackson2ResourceReader();
|
||||
|
||||
Object source = reader.readFrom(new ClassPathResource("spring-blog.atom.json"), this.getClass().getClassLoader());
|
||||
var source = reader.readFrom(new ClassPathResource("spring-blog.atom.json"), this.getClass().getClassLoader());
|
||||
|
||||
if (source instanceof Iterable) {
|
||||
((Iterable) source).forEach(element -> operations.save(element));
|
||||
((Iterable) source).forEach(operations::save);
|
||||
} else {
|
||||
operations.save(source);
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ public class ConsoleResultPrinter {
|
||||
System.out.println(String.format("XXXXXXXXXXXX -- Found %s blogPosts matching '%s' --XXXXXXXXXXXX",
|
||||
blogPosts.size(), criteria != null ? criteria.getCriteriaObject() : ""));
|
||||
|
||||
for (BlogPost blogPost : blogPosts) {
|
||||
for (var blogPost : blogPosts) {
|
||||
System.out.println(blogPost);
|
||||
}
|
||||
|
||||
|
||||
@@ -15,9 +15,6 @@
|
||||
*/
|
||||
package example.springdata.mongodb;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.mongodb.core.mapping.Document;
|
||||
|
||||
@@ -25,13 +22,7 @@ import org.springframework.data.mongodb.core.mapping.Document;
|
||||
* @author Christoph Strobl
|
||||
* @currentRead The Core - Peter V. Brett
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@Document("processes")
|
||||
public class Process {
|
||||
|
||||
@Id Integer id;
|
||||
State state;
|
||||
int transitionCount;
|
||||
public record Process(@Id Integer id, State state, int transitionCount) {
|
||||
|
||||
}
|
||||
|
||||
@@ -49,9 +49,9 @@ class TransitionService {
|
||||
@Transactional
|
||||
public void run(Integer id) {
|
||||
|
||||
Process process = lookup(id);
|
||||
var process = lookup(id);
|
||||
|
||||
if (!State.CREATED.equals(process.getState())) {
|
||||
if (!State.CREATED.equals(process.state())) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -62,13 +62,13 @@ class TransitionService {
|
||||
|
||||
private void finish(Process process) {
|
||||
|
||||
template.update(Process.class).matching(Query.query(Criteria.where("id").is(process.getId())))
|
||||
template.update(Process.class).matching(Query.query(Criteria.where("id").is(process.id())))
|
||||
.apply(Update.update("state", State.DONE).inc("transitionCount", 1)).first();
|
||||
}
|
||||
|
||||
void start(Process process) {
|
||||
|
||||
template.update(Process.class).matching(Query.query(Criteria.where("id").is(process.getId())))
|
||||
template.update(Process.class).matching(Query.query(Criteria.where("id").is(process.id())))
|
||||
.apply(Update.update("state", State.ACTIVE).inc("transitionCount", 1)).first();
|
||||
}
|
||||
|
||||
@@ -77,6 +77,6 @@ class TransitionService {
|
||||
}
|
||||
|
||||
void verify(Process process) {
|
||||
Assert.state(process.getId() % 3 != 0, "We're sorry but we needed to drop that one");
|
||||
Assert.state(process.id() % 3 != 0, "We're sorry but we needed to drop that one");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,21 +52,21 @@ public class ReactiveManagedTransitionService {
|
||||
|
||||
return lookup(id) //
|
||||
.flatMap(process -> start(template, process)) //
|
||||
.flatMap(it -> verify(it)) //
|
||||
.flatMap(this::verify) //
|
||||
.flatMap(process -> finish(template, process)) //
|
||||
.map(Process::getId);
|
||||
.map(Process::id);
|
||||
}
|
||||
|
||||
private Mono<Process> finish(ReactiveMongoOperations operations, Process process) {
|
||||
|
||||
return operations.update(Process.class).matching(Query.query(Criteria.where("id").is(process.getId())))
|
||||
return operations.update(Process.class).matching(Query.query(Criteria.where("id").is(process.id())))
|
||||
.apply(Update.update("state", State.DONE).inc("transitionCount", 1)).first() //
|
||||
.then(Mono.just(process));
|
||||
}
|
||||
|
||||
Mono<Process> start(ReactiveMongoOperations operations, Process process) {
|
||||
|
||||
return operations.update(Process.class).matching(Query.query(Criteria.where("id").is(process.getId())))
|
||||
return operations.update(Process.class).matching(Query.query(Criteria.where("id").is(process.id())))
|
||||
.apply(Update.update("state", State.ACTIVE).inc("transitionCount", 1)).first() //
|
||||
.then(Mono.just(process));
|
||||
}
|
||||
@@ -77,7 +77,7 @@ public class ReactiveManagedTransitionService {
|
||||
|
||||
Mono<Process> verify(Process process) {
|
||||
|
||||
Assert.state(process.getId() % 3 != 0, "We're sorry but we needed to drop that one");
|
||||
Assert.state(process.id() % 3 != 0, "We're sorry but we needed to drop that one");
|
||||
return Mono.just(process);
|
||||
}
|
||||
|
||||
|
||||
@@ -56,19 +56,19 @@ public class ReactiveTransitionService {
|
||||
.flatMap(it -> verify(it)) //
|
||||
.flatMap(process -> finish(action, process));
|
||||
|
||||
}).next().map(Process::getId);
|
||||
}).next().map(Process::id);
|
||||
}
|
||||
|
||||
private Mono<Process> finish(ReactiveMongoOperations operations, Process process) {
|
||||
|
||||
return operations.update(Process.class).matching(Query.query(Criteria.where("id").is(process.getId())))
|
||||
return operations.update(Process.class).matching(Query.query(Criteria.where("id").is(process.id())))
|
||||
.apply(Update.update("state", State.DONE).inc("transitionCount", 1)).first() //
|
||||
.then(Mono.just(process));
|
||||
}
|
||||
|
||||
Mono<Process> start(ReactiveMongoOperations operations, Process process) {
|
||||
|
||||
return operations.update(Process.class).matching(Query.query(Criteria.where("id").is(process.getId())))
|
||||
return operations.update(Process.class).matching(Query.query(Criteria.where("id").is(process.id())))
|
||||
.apply(Update.update("state", State.ACTIVE).inc("transitionCount", 1)).first() //
|
||||
.then(Mono.just(process));
|
||||
}
|
||||
@@ -79,7 +79,7 @@ public class ReactiveTransitionService {
|
||||
|
||||
Mono<Process> verify(Process process) {
|
||||
|
||||
Assert.state(process.getId() % 3 != 0, "We're sorry but we needed to drop that one");
|
||||
Assert.state(process.id() % 3 != 0, "We're sorry but we needed to drop that one");
|
||||
return Mono.just(process);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,13 +88,13 @@ public class TransitionServiceTests {
|
||||
@Test
|
||||
public void txCommitRollback() {
|
||||
|
||||
for (int i = 0; i < 10; i++) {
|
||||
for (var i = 0; i < 10; i++) {
|
||||
|
||||
Process process = transitionService.newProcess();
|
||||
var process = transitionService.newProcess();
|
||||
|
||||
try {
|
||||
|
||||
transitionService.run(process.getId());
|
||||
transitionService.run(process.id());
|
||||
Assertions.assertThat(stateInDb(process)).isEqualTo(State.DONE);
|
||||
} catch (IllegalStateException e) {
|
||||
Assertions.assertThat(stateInDb(process)).isEqualTo(State.CREATED);
|
||||
@@ -107,7 +107,7 @@ public class TransitionServiceTests {
|
||||
|
||||
State stateInDb(Process process) {
|
||||
|
||||
return State.valueOf(client.getDatabase(DB_NAME).getCollection("processes").find(Filters.eq("_id", process.getId()))
|
||||
return State.valueOf(client.getDatabase(DB_NAME).getCollection("processes").find(Filters.eq("_id", process.id()))
|
||||
.projection(Projections.include("state")).first().get("state", String.class));
|
||||
}
|
||||
|
||||
|
||||
@@ -86,9 +86,9 @@ public class ReactiveManagedTransitionServiceTests {
|
||||
@Test
|
||||
public void reactiveTxCommitRollback() {
|
||||
|
||||
for (int i = 0; i < 10; i++) {
|
||||
for (var i = 0; i < 10; i++) {
|
||||
managedTransitionService.newProcess() //
|
||||
.map(Process::getId) //
|
||||
.map(Process::id) //
|
||||
.flatMap(managedTransitionService::run) //
|
||||
.onErrorReturn(-1).as(StepVerifier::create) //
|
||||
.consumeNextWith(val -> {}) //
|
||||
@@ -100,7 +100,7 @@ public class ReactiveManagedTransitionServiceTests {
|
||||
.as(StepVerifier::create) //
|
||||
.consumeNextWith(list -> {
|
||||
|
||||
for (Document document : list) {
|
||||
for (var document : list) {
|
||||
|
||||
System.out.println("document: " + document);
|
||||
|
||||
|
||||
@@ -76,9 +76,9 @@ public class ReactiveTransitionServiceTests {
|
||||
@Test
|
||||
public void reactiveTxCommitRollback() {
|
||||
|
||||
for (int i = 0; i < 10; i++) {
|
||||
for (var i = 0; i < 10; i++) {
|
||||
transitionService.newProcess() //
|
||||
.map(Process::getId) //
|
||||
.map(Process::id) //
|
||||
.flatMap(transitionService::run) //
|
||||
.onErrorReturn(-1).as(StepVerifier::create) //
|
||||
.consumeNextWith(val -> {}) //
|
||||
@@ -90,7 +90,7 @@ public class ReactiveTransitionServiceTests {
|
||||
.as(StepVerifier::create) //
|
||||
.consumeNextWith(list -> {
|
||||
|
||||
for (Document document : list) {
|
||||
for (var document : list) {
|
||||
|
||||
System.out.println("document: " + document);
|
||||
|
||||
|
||||
@@ -171,7 +171,7 @@ public class EmbeddedMongo extends ExternalResource {
|
||||
|
||||
if (serverPorts.size() > 1 || StringUtils.hasText(replicaSetName)) {
|
||||
|
||||
String rsName = StringUtils.hasText(replicaSetName) ? replicaSetName : DEFAULT_REPLICA_SET_NAME;
|
||||
var rsName = StringUtils.hasText(replicaSetName) ? replicaSetName : DEFAULT_REPLICA_SET_NAME;
|
||||
return new EmbeddedMongo(
|
||||
new ReplSet(version, rsName, silent, serverPorts.toArray(new Integer[serverPorts.size()])));
|
||||
}
|
||||
@@ -306,7 +306,7 @@ public class EmbeddedMongo extends ExternalResource {
|
||||
replicaSets.put(replicaSetName, initReplicaSet());
|
||||
|
||||
// create mongos
|
||||
MongosConfig mongosConfig = defaultMongosConfig(serverVersion, mongosPort, defaultCommandOptions(),
|
||||
var mongosConfig = defaultMongosConfig(serverVersion, mongosPort, defaultCommandOptions(),
|
||||
configServerReplicaSetName, configServerPorts[0]);
|
||||
|
||||
mongosTestFactory = new MongosSystemForTestFactory(mongosConfig, replicaSets, Collections.emptyList(),
|
||||
@@ -341,7 +341,7 @@ public class EmbeddedMongo extends ExternalResource {
|
||||
|
||||
List<MongodConfig> configServers = new ArrayList<>(configServerPorts.length);
|
||||
|
||||
for (Integer port : configServerPorts) {
|
||||
for (var port : configServerPorts) {
|
||||
configServers.add(
|
||||
defaultMongodConfig(serverVersion, port, defaultCommandOptions(), true, false, configServerReplicaSetName));
|
||||
}
|
||||
@@ -396,7 +396,7 @@ public class EmbeddedMongo extends ExternalResource {
|
||||
|
||||
try {
|
||||
|
||||
ImmutableMongodConfig.Builder builder = MongodConfig.builder() //
|
||||
var builder = MongodConfig.builder() //
|
||||
.version(version) //
|
||||
.putArgs("--quiet", null) //
|
||||
.net(new Net(LOCALHOST, port, Network.localhostIsIPv6())) //
|
||||
@@ -435,7 +435,7 @@ public class EmbeddedMongo extends ExternalResource {
|
||||
|
||||
try {
|
||||
|
||||
ImmutableMongosConfig.Builder builder = MongosConfig.builder() //
|
||||
var builder = MongosConfig.builder() //
|
||||
.version(version) //
|
||||
.putArgs("--quiet", null) //
|
||||
.net(new Net(LOCALHOST, port, Network.localhostIsIPv6())) //
|
||||
|
||||
@@ -90,10 +90,10 @@ class MongosSystemForTestFactory {
|
||||
public void start() throws Throwable {
|
||||
this.mongodProcessList = new ArrayList<>();
|
||||
this.mongodConfigProcessList = new ArrayList<>();
|
||||
for (Entry<String, List<MongodConfig>> entry : replicaSets.entrySet()) {
|
||||
for (var entry : replicaSets.entrySet()) {
|
||||
initializeReplicaSet(entry);
|
||||
}
|
||||
for (MongodConfig config : configServers) {
|
||||
for (var config : configServers) {
|
||||
initializeConfigServer(config);
|
||||
}
|
||||
initializeMongos();
|
||||
@@ -102,15 +102,15 @@ class MongosSystemForTestFactory {
|
||||
|
||||
private void initializeReplicaSet(Entry<String, List<MongodConfig>> entry)
|
||||
throws Exception {
|
||||
String replicaName = entry.getKey();
|
||||
List<MongodConfig> mongoConfigList = entry.getValue();
|
||||
var replicaName = entry.getKey();
|
||||
var mongoConfigList = entry.getValue();
|
||||
|
||||
if (mongoConfigList.size() < 3) {
|
||||
throw new Exception(
|
||||
"A replica set must contain at least 3 members.");
|
||||
}
|
||||
// Create 3 mongod processes
|
||||
for (MongodConfig mongoConfig : mongoConfigList) {
|
||||
for (var mongoConfig : mongoConfigList) {
|
||||
if (!mongoConfig.replication().getReplSetName().equals(replicaName)) {
|
||||
throw new Exception(
|
||||
"Replica set name must match in mongo configuration");
|
||||
@@ -119,28 +119,28 @@ class MongosSystemForTestFactory {
|
||||
// .defaultsWithLogger(Command.MongoD,logger)
|
||||
.processOutput(outputFunction.apply(Command.MongoD))
|
||||
.build();
|
||||
MongodStarter starter = MongodStarter.getInstance(runtimeConfig);
|
||||
MongodExecutable mongodExe = starter.prepare(mongoConfig);
|
||||
MongodProcess process = mongodExe.start();
|
||||
var starter = MongodStarter.getInstance(runtimeConfig);
|
||||
var mongodExe = starter.prepare(mongoConfig);
|
||||
var process = mongodExe.start();
|
||||
mongodProcessList.add(process);
|
||||
}
|
||||
Thread.sleep(1000);
|
||||
MongoClientSettings mo = MongoClientSettings.builder()
|
||||
var mo = MongoClientSettings.builder()
|
||||
.applyToSocketSettings(builder -> builder.connectTimeout(10, TimeUnit.SECONDS)).applyToClusterSettings(
|
||||
builder -> builder.hosts(Collections.singletonList(toAddress(mongoConfigList.get(0).net()))))
|
||||
.build();
|
||||
MongoClient mongo = MongoClients.create(mo);
|
||||
MongoDatabase mongoAdminDB = mongo.getDatabase(ADMIN_DATABASE_NAME);
|
||||
var mongo = MongoClients.create(mo);
|
||||
var mongoAdminDB = mongo.getDatabase(ADMIN_DATABASE_NAME);
|
||||
|
||||
Document cr = mongoAdminDB.runCommand(new Document("isMaster", 1));
|
||||
var cr = mongoAdminDB.runCommand(new Document("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 (MongodConfig mongoConfig : mongoConfigList) {
|
||||
var members = new BasicDBList();
|
||||
var i = 0;
|
||||
for (var mongoConfig : mongoConfigList) {
|
||||
DBObject host = new BasicDBObject();
|
||||
host.put("_id", i++);
|
||||
host.put("host", mongoConfig.net().getServerAddress().getHostName()
|
||||
@@ -176,11 +176,11 @@ class MongosSystemForTestFactory {
|
||||
return false;
|
||||
}
|
||||
|
||||
List members = (List) setting.get("members");
|
||||
for (Object m : members) {
|
||||
Document member = (Document) m;
|
||||
var members = (List) setting.get("members");
|
||||
for (var m : members) {
|
||||
var member = (Document) m;
|
||||
logger.info(member.toString());
|
||||
int state = member.getInteger("state", 0);
|
||||
var state = member.getInteger("state", 0);
|
||||
logger.info("state: {}", state);
|
||||
// 1 - PRIMARY, 2 - SECONDARY, 7 - ARBITER
|
||||
if (state != 1 && state != 2 && state != 7) {
|
||||
@@ -195,14 +195,14 @@ class MongosSystemForTestFactory {
|
||||
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();
|
||||
var starter = MongodStarter.getDefaultInstance();
|
||||
var mongodExe = starter.prepare(config);
|
||||
var process = mongodExe.start();
|
||||
mongodProcessList.add(process);
|
||||
}
|
||||
|
||||
private void initializeMongos() throws Exception {
|
||||
MongosStarter runtime = MongosStarter.getInstance(RuntimeConfig.builder()
|
||||
var runtime = MongosStarter.getInstance(RuntimeConfig.builder()
|
||||
// .defaultsWithLogger(Command.MongoS,logger)
|
||||
.processOutput(outputFunction.apply(Command.MongoS))
|
||||
.build());
|
||||
@@ -213,19 +213,19 @@ class MongosSystemForTestFactory {
|
||||
|
||||
private void configureMongos() throws Exception {
|
||||
Document cr;
|
||||
MongoClientSettings options = MongoClientSettings.builder()
|
||||
var options = MongoClientSettings.builder()
|
||||
.applyToSocketSettings(builder -> builder.connectTimeout(10, TimeUnit.SECONDS))
|
||||
.applyToClusterSettings(builder -> builder.hosts(Collections.singletonList(toAddress(this.config.net()))))
|
||||
.build();
|
||||
try (MongoClient mongo = MongoClients.create(options)) {
|
||||
MongoDatabase mongoAdminDB = mongo.getDatabase(ADMIN_DATABASE_NAME);
|
||||
try (var mongo = MongoClients.create(options)) {
|
||||
var mongoAdminDB = mongo.getDatabase(ADMIN_DATABASE_NAME);
|
||||
|
||||
// Add shard from the replica set list
|
||||
for (Entry<String, List<MongodConfig>> entry : this.replicaSets
|
||||
for (var entry : this.replicaSets
|
||||
.entrySet()) {
|
||||
String replicaName = entry.getKey();
|
||||
String command = "";
|
||||
for (MongodConfig mongodConfig : entry.getValue()) {
|
||||
var replicaName = entry.getKey();
|
||||
var command = "";
|
||||
for (var mongodConfig : entry.getValue()) {
|
||||
if (command.isEmpty()) {
|
||||
command = replicaName + "/";
|
||||
} else {
|
||||
@@ -251,22 +251,20 @@ class MongosSystemForTestFactory {
|
||||
|
||||
// Create index in sharded collection
|
||||
logger.info("Create index in sharded collection");
|
||||
MongoDatabase db = mongo.getDatabase(this.shardDatabase);
|
||||
var db = mongo.getDatabase(this.shardDatabase);
|
||||
db.getCollection(this.shardCollection).createIndex(new Document(this.shardKey, 1));
|
||||
|
||||
// Shard the collection
|
||||
logger.info("Shard the collection: {}.{}", this.shardDatabase, this.shardCollection);
|
||||
Document cmd = new Document();
|
||||
var cmd = new Document();
|
||||
cmd.put("shardCollection", this.shardDatabase + "." + this.shardCollection);
|
||||
cmd.put("key", new BasicDBObject(this.shardKey, 1));
|
||||
cr = mongoAdminDB.runCommand(cmd);
|
||||
logger.info(cr.toString());
|
||||
|
||||
logger.info("Get info from config/shards");
|
||||
FindIterable<Document> cursor = mongo.getDatabase("config").getCollection("shards").find();
|
||||
MongoCursor<Document> iterator = cursor.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
Document item = iterator.next();
|
||||
var cursor = mongo.getDatabase("config").getCollection("shards").find();
|
||||
for (Document item : cursor) {
|
||||
logger.info(item.toString());
|
||||
}
|
||||
}
|
||||
@@ -279,10 +277,10 @@ class MongosSystemForTestFactory {
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
for (MongodProcess process : this.mongodProcessList) {
|
||||
for (var process : this.mongodProcessList) {
|
||||
process.stop();
|
||||
}
|
||||
for (MongodProcess process : this.mongodConfigProcessList) {
|
||||
for (var process : this.mongodConfigProcessList) {
|
||||
process.stop();
|
||||
}
|
||||
this.mongosProcess.stop();
|
||||
|
||||
Reference in New Issue
Block a user