Switch MongoDB samples to records.

See #606.
This commit is contained in:
Mark Paluch
2021-04-28 15:18:59 +02:00
parent b44dc3dea1
commit e565f33872
69 changed files with 395 additions and 555 deletions

View File

@@ -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();
}

View File

@@ -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());
}
}
}

View File

@@ -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;
}

View File

@@ -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);
}
}

View File

@@ -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") //

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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) {
}
}

View File

@@ -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();
}
}

View File

@@ -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);
}
}

View File

@@ -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

View File

@@ -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);
};
}
}

View File

@@ -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 {

View File

@@ -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) {
}

View File

@@ -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;
}

View File

@@ -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) {
}

View File

@@ -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);

View File

@@ -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);
}

View File

@@ -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");
}
}

View File

@@ -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);

View File

@@ -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));
}

View File

@@ -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();
}
}

View File

@@ -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"));

View File

@@ -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);
}
}

View File

@@ -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) {
}

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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.

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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;
}
}

View File

@@ -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);
}

View File

@@ -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) {
}

View File

@@ -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) {
}

View File

@@ -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());

View File

@@ -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();
}
}

View File

@@ -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));

View File

@@ -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));
}

View File

@@ -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);
}

View File

@@ -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;

View File

@@ -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);
}
}

View File

@@ -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();

View File

@@ -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")) //

View File

@@ -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")) //

View File

@@ -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;

View File

@@ -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 + '\'' + '}';
}
}

View File

@@ -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);

View File

@@ -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();

View File

@@ -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;
}

View File

@@ -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), //

View File

@@ -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), //

View File

@@ -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);
}
}

View File

@@ -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));

View File

@@ -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 + "]";
}
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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) {
}

View File

@@ -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");
}
}

View File

@@ -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);
}

View File

@@ -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);
}
}

View File

@@ -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));
}

View File

@@ -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);

View File

@@ -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);

View File

@@ -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())) //

View File

@@ -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();