Merge branch 'eugenp:master' into master
This commit is contained in:
+2
-1
@@ -20,4 +20,5 @@ Two scripts are included to easily start middleware using Docker matching the pr
|
||||
- [Multi-Entity Aggregates in Axon](https://www.baeldung.com/java-axon-multi-entity-aggregates)
|
||||
- [Snapshotting Aggregates in Axon](https://www.baeldung.com/axon-snapshotting-aggregates)
|
||||
- [Dispatching Queries in Axon Framework](https://www.baeldung.com/axon-query-dispatching)
|
||||
- [Persisting the Query Model](https://www.baeldung.com/axon-persisting-query-model)
|
||||
- [Persisting the Query Model](https://www.baeldung.com/persisting-the-query-model)
|
||||
- [Using and testing Axon applications via REST](https://www.baeldung.com/using-and-testing-axon-applications-via-rest)
|
||||
|
||||
+11
-2
@@ -81,13 +81,22 @@
|
||||
<dependency>
|
||||
<groupId>org.awaitility</groupId>
|
||||
<artifactId>awaitility</artifactId>
|
||||
<version>4.2.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-webflux</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.projectreactor.netty</groupId>
|
||||
<artifactId>reactor-netty-http</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<properties>
|
||||
<axon-bom.version>4.6.2</axon-bom.version>
|
||||
<axon-bom.version>4.6.3</axon-bom.version>
|
||||
<de.flapdoodle.embed.mongo.version>3.4.8</de.flapdoodle.embed.mongo.version>
|
||||
</properties>
|
||||
|
||||
|
||||
@@ -0,0 +1,187 @@
|
||||
package com.baeldung.axon.gui;
|
||||
|
||||
import com.baeldung.axon.OrderApplication;
|
||||
import com.baeldung.axon.querymodel.OrderResponse;
|
||||
import com.baeldung.axon.querymodel.OrderStatusResponse;
|
||||
|
||||
import org.junit.jupiter.api.*;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.boot.test.web.server.LocalServerPort;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.client.reactive.ReactorClientHttpConnector;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.web.reactive.function.client.WebClient;
|
||||
import org.springframework.web.reactive.function.client.WebClientResponseException;
|
||||
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
import reactor.netty.http.client.HttpClient;
|
||||
import reactor.test.StepVerifier;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
@SpringBootTest(classes = OrderApplication.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
|
||||
class OrderRestEndpointIntegrationTest {
|
||||
|
||||
@LocalServerPort
|
||||
private int port;
|
||||
|
||||
@Test
|
||||
@DirtiesContext
|
||||
void givenCreateOrderCalled_whenCallingAllOrders_thenOneCreatedOrderIsReturned() {
|
||||
WebClient client = WebClient.builder()
|
||||
.clientConnector(httpConnector())
|
||||
.build();
|
||||
createRandomNewOrder(client);
|
||||
StepVerifier.create(retrieveListResponse(client.get()
|
||||
.uri("http://localhost:" + port + "/all-orders")))
|
||||
.expectNextMatches(list -> 1 == list.size() && list.get(0)
|
||||
.getOrderStatus() == OrderStatusResponse.CREATED)
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DirtiesContext
|
||||
void givenCreateOrderCalledThreeTimesAnd_whenCallingAllOrdersStreaming_thenTwoCreatedOrdersAreReturned() {
|
||||
WebClient client = WebClient.builder()
|
||||
.clientConnector(httpConnector())
|
||||
.build();
|
||||
for (int i = 0; i < 3; i++) {
|
||||
createRandomNewOrder(client);
|
||||
}
|
||||
StepVerifier.create(retrieveStreamingResponse(client.get()
|
||||
.uri("http://localhost:" + port + "/all-orders-streaming")))
|
||||
.expectNextMatches(o -> o.getOrderStatus() == OrderStatusResponse.CREATED)
|
||||
.expectNextMatches(o -> o.getOrderStatus() == OrderStatusResponse.CREATED)
|
||||
.expectNextMatches(o -> o.getOrderStatus() == OrderStatusResponse.CREATED)
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DirtiesContext
|
||||
void givenRuleExistThatNeedConfirmationBeforeShipping_whenCallingShipUnconfirmed_thenErrorReturned() {
|
||||
WebClient client = WebClient.builder()
|
||||
.clientConnector(httpConnector())
|
||||
.build();
|
||||
StepVerifier.create(retrieveResponse(client.post()
|
||||
.uri("http://localhost:" + port + "/ship-unconfirmed-order")))
|
||||
.verifyError(WebClientResponseException.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DirtiesContext
|
||||
void givenShipOrderCalled_whenCallingAllShippedChairs_then234PlusOneIsReturned() {
|
||||
WebClient client = WebClient.builder()
|
||||
.clientConnector(httpConnector())
|
||||
.build();
|
||||
verifyVoidPost(client, "http://localhost:" + port + "/ship-order");
|
||||
StepVerifier.create(retrieveIntegerResponse(client.get()
|
||||
.uri("http://localhost:" + port + "/total-shipped/Deluxe Chair")))
|
||||
.assertNext(r -> assertEquals(235, r))
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DirtiesContext
|
||||
void givenOrdersAreUpdated_whenCallingOrderUpdates_thenUpdatesReturned() {
|
||||
WebClient updaterClient = WebClient.builder()
|
||||
.clientConnector(httpConnector())
|
||||
.build();
|
||||
WebClient receiverClient = WebClient.builder()
|
||||
.clientConnector(httpConnector())
|
||||
.build();
|
||||
String orderId = UUID.randomUUID()
|
||||
.toString();
|
||||
String productId = UUID.randomUUID()
|
||||
.toString();
|
||||
StepVerifier.create(retrieveResponse(updaterClient.post()
|
||||
.uri("http://localhost:" + port + "/order/" + orderId)))
|
||||
.assertNext(Assertions::assertNotNull)
|
||||
.verifyComplete();
|
||||
ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
|
||||
executor.schedule(() -> addIncrementDecrementConfirmAndShipProduct(orderId, productId), 1L, TimeUnit.SECONDS);
|
||||
try {
|
||||
StepVerifier.create(retrieveStreamingResponse(receiverClient.get()
|
||||
.uri("http://localhost:" + port + "/order-updates/" + orderId)))
|
||||
.assertNext(p -> assertTrue(p.getProducts()
|
||||
.isEmpty()))
|
||||
.assertNext(p -> assertEquals(1, p.getProducts()
|
||||
.get(productId)))
|
||||
.assertNext(p -> assertEquals(2, p.getProducts()
|
||||
.get(productId)))
|
||||
.assertNext(p -> assertEquals(1, p.getProducts()
|
||||
.get(productId)))
|
||||
.assertNext(p -> assertEquals(OrderStatusResponse.CONFIRMED, p.getOrderStatus()))
|
||||
.assertNext(p -> assertEquals(OrderStatusResponse.SHIPPED, p.getOrderStatus()))
|
||||
.thenCancel()
|
||||
.verify();
|
||||
} finally {
|
||||
executor.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
private void addIncrementDecrementConfirmAndShipProduct(String orderId, String productId) {
|
||||
WebClient client = WebClient.builder()
|
||||
.clientConnector(httpConnector())
|
||||
.build();
|
||||
String base = "http://localhost:" + port + "/order/" + orderId;
|
||||
verifyVoidPost(client, base + "/product/" + productId);
|
||||
verifyVoidPost(client, base + "/product/" + productId + "/increment");
|
||||
verifyVoidPost(client, base + "/product/" + productId + "/decrement");
|
||||
verifyVoidPost(client, base + "/confirm");
|
||||
verifyVoidPost(client, base + "/ship");
|
||||
}
|
||||
|
||||
private void createRandomNewOrder(WebClient client){
|
||||
StepVerifier.create(retrieveResponse(client.post()
|
||||
.uri("http://localhost:" + port + "/order")))
|
||||
.assertNext(Assertions::assertNotNull)
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
private void verifyVoidPost(WebClient client, String uri) {
|
||||
StepVerifier.create(retrieveResponse(client.post()
|
||||
.uri(uri)))
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
private static ReactorClientHttpConnector httpConnector() {
|
||||
HttpClient httpClient = HttpClient.create()
|
||||
.wiretap(true);
|
||||
return new ReactorClientHttpConnector(httpClient);
|
||||
}
|
||||
|
||||
private Mono<String> retrieveResponse(WebClient.RequestBodySpec spec) {
|
||||
return spec.retrieve()
|
||||
.bodyToMono(String.class);
|
||||
}
|
||||
|
||||
private Mono<ResponseList> retrieveListResponse(WebClient.RequestHeadersSpec<?> spec) {
|
||||
return spec.accept(MediaType.APPLICATION_JSON)
|
||||
.retrieve()
|
||||
.bodyToMono(ResponseList.class);
|
||||
}
|
||||
|
||||
private Mono<Integer> retrieveIntegerResponse(WebClient.RequestHeadersSpec<?> spec) {
|
||||
return spec.retrieve()
|
||||
.bodyToMono(Integer.class);
|
||||
}
|
||||
|
||||
private Flux<OrderResponse> retrieveStreamingResponse(WebClient.RequestHeadersSpec<?> spec) {
|
||||
return spec.retrieve()
|
||||
.bodyToFlux(OrderResponse.class);
|
||||
}
|
||||
|
||||
private static class ResponseList extends ArrayList<OrderResponse> {
|
||||
|
||||
private ResponseList() {
|
||||
super();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -14,6 +14,20 @@
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<artifactId>gson</artifactId>
|
||||
<version>${gson.version}</version>
|
||||
</dependency>
|
||||
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
<version>${jackson.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
@@ -32,6 +46,8 @@
|
||||
<properties>
|
||||
<maven.compiler.source.version>11</maven.compiler.source.version>
|
||||
<maven.compiler.target.version>11</maven.compiler.target.version>
|
||||
<jackson.version>2.14.1</jackson.version>
|
||||
<gson.version>2.10</gson.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,73 @@
|
||||
package com.baeldung.httppojo;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class Todo {
|
||||
|
||||
int userId;
|
||||
int id;
|
||||
String title;
|
||||
boolean completed;
|
||||
|
||||
public Todo() {
|
||||
}
|
||||
|
||||
public Todo(int userId, int id, String title, boolean completed) {
|
||||
this.userId = userId;
|
||||
this.id = id;
|
||||
this.title = title;
|
||||
this.completed = completed;
|
||||
}
|
||||
|
||||
public int getUserId() {
|
||||
return userId;
|
||||
}
|
||||
|
||||
public void setUserId(int userId) {
|
||||
this.userId = userId;
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public boolean isCompleted() {
|
||||
return completed;
|
||||
}
|
||||
|
||||
public void setCompleted(boolean completed) {
|
||||
this.completed = completed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o)
|
||||
return true;
|
||||
if (o == null || getClass() != o.getClass())
|
||||
return false;
|
||||
Todo todo = (Todo) o;
|
||||
return userId == todo.userId && id == todo.id && completed == todo.completed && Objects.equals(title, todo.title);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(userId, id, title, completed);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "{" + "userId=" + userId + ", id=" + id + ", title='" + title + '\'' + ", completed=" + completed + '}';
|
||||
}
|
||||
}
|
||||
+107
@@ -0,0 +1,107 @@
|
||||
package com.baeldung.httppojo;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.net.http.HttpClient;
|
||||
import java.net.http.HttpRequest;
|
||||
import java.net.http.HttpResponse;
|
||||
import java.net.http.HttpResponse.BodyHandlers;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletionException;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
|
||||
public class TodoAppClient {
|
||||
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
|
||||
Gson gson = new GsonBuilder().create();
|
||||
|
||||
public String sampleApiRequest() throws Exception {
|
||||
HttpClient client = HttpClient.newHttpClient();
|
||||
HttpRequest request = HttpRequest.newBuilder()
|
||||
.uri(URI.create("https://jsonplaceholder.typicode.com/todos"))
|
||||
.build();
|
||||
|
||||
HttpResponse<String> response = client.send(request, BodyHandlers.ofString());
|
||||
|
||||
return response.body();
|
||||
|
||||
}
|
||||
|
||||
public Todo syncGson() throws Exception {
|
||||
String response = sampleApiRequest();
|
||||
|
||||
List<Todo> todo = gson.fromJson(response, new TypeToken<List<Todo>>() {
|
||||
}.getType());
|
||||
|
||||
return todo.get(1);
|
||||
|
||||
}
|
||||
|
||||
public Todo syncJackson() throws Exception {
|
||||
String response = sampleApiRequest();
|
||||
|
||||
Todo[] todo = objectMapper.readValue(response, Todo[].class);
|
||||
|
||||
return todo[1];
|
||||
|
||||
}
|
||||
|
||||
public Todo asyncJackson() throws Exception {
|
||||
|
||||
HttpRequest request = HttpRequest.newBuilder()
|
||||
.uri(URI.create("https://jsonplaceholder.typicode.com/todos"))
|
||||
.build();
|
||||
|
||||
TodoAppClient todoAppClient = new TodoAppClient();
|
||||
|
||||
List<Todo> todo = HttpClient.newHttpClient()
|
||||
.sendAsync(request, BodyHandlers.ofString())
|
||||
.thenApply(HttpResponse::body)
|
||||
.thenApply(todoAppClient::readValueJackson)
|
||||
.get();
|
||||
|
||||
return todo.get(1);
|
||||
|
||||
}
|
||||
|
||||
public Todo asyncGson() throws Exception {
|
||||
|
||||
HttpRequest request = HttpRequest.newBuilder()
|
||||
.uri(URI.create("https://jsonplaceholder.typicode.com/todos"))
|
||||
.build();
|
||||
TodoAppClient todoAppClient = new TodoAppClient();
|
||||
|
||||
List<Todo> todo = HttpClient.newHttpClient()
|
||||
.sendAsync(request, BodyHandlers.ofString())
|
||||
.thenApply(HttpResponse::body)
|
||||
.thenApply(todoAppClient::readValueGson)
|
||||
.get();
|
||||
|
||||
return todo.get(1);
|
||||
|
||||
}
|
||||
|
||||
List<Todo> readValueJackson(String content) {
|
||||
|
||||
try {
|
||||
return objectMapper.readValue(content, new TypeReference<List<Todo>>() {
|
||||
});
|
||||
} catch (IOException ioe) {
|
||||
throw new CompletionException(ioe);
|
||||
}
|
||||
}
|
||||
|
||||
List<Todo> readValueGson(String content) {
|
||||
|
||||
return gson.fromJson(content, new TypeToken<List<Todo>>() {
|
||||
}.getType());
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
package com.baeldung.httppojo;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public class HttpClientPojoClassUnitTest {
|
||||
|
||||
Todo expectedTodo = new Todo(1, 2, "quis ut nam facilis et officia qui", false);
|
||||
|
||||
@Test
|
||||
public void givenSampleApiCall_whenResponseIsMappedByGson_thenCompareResponseMappedByGson() throws Exception {
|
||||
TodoAppClient sampleGson = new TodoAppClient();
|
||||
|
||||
assertEquals(expectedTodo, sampleGson.syncGson());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenSampleApiCall_whenResponseIsMappedByJackson_thenCompareResponseMappedByJackson() throws Exception {
|
||||
TodoAppClient sampleJackson = new TodoAppClient();
|
||||
|
||||
assertEquals(expectedTodo, sampleJackson.syncJackson());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenSampleRestApi_whenApiIsConsumedByHttpClient_thenCompareJsonString() throws Exception {
|
||||
TodoAppClient sampleTest = new TodoAppClient();
|
||||
assertNotNull(sampleTest.sampleApiRequest());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenSampleApiAsyncCall_whenResponseIsMappedByJackson_thenCompareResponseMappedByJackson() throws Exception {
|
||||
TodoAppClient sampleAsynJackson = new TodoAppClient();
|
||||
assertEquals(expectedTodo, sampleAsynJackson.asyncJackson());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenSampleApiAsyncCall_whenResponseIsMappedByGson_thenCompareResponseMappedByGson() throws Exception {
|
||||
TodoAppClient sampleAsynGson = new TodoAppClient();
|
||||
assertEquals(expectedTodo, sampleAsynGson.asyncGson());
|
||||
}
|
||||
|
||||
}
|
||||
+122
@@ -0,0 +1,122 @@
|
||||
package com.baeldung.features;
|
||||
|
||||
import jdk.incubator.concurrent.StructuredTaskScope;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.*;
|
||||
|
||||
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
|
||||
import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy;
|
||||
|
||||
public class JEP428StructuredConcurrencyUnitTest {
|
||||
|
||||
private static final String ERROR_MESSAGE = "Failed to get the result";
|
||||
|
||||
@Test
|
||||
public void givenStructuredConcurrency_whenThrowingException_thenCorrect() {
|
||||
assertThatThrownBy(() -> {
|
||||
try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
|
||||
Future<Shelter> shelter = scope.fork(this::getShelter);
|
||||
Future<List<Dog>> dogs = scope.fork(this::getDogsWithException);
|
||||
scope.throwIfFailed(e -> new RuntimeException(ERROR_MESSAGE));
|
||||
scope.join();
|
||||
Response response = new Response(shelter.resultNow(), dogs.resultNow());
|
||||
|
||||
assertThat(response).isNotNull();
|
||||
assertThat(response.shelter()).isNotNull();
|
||||
assertThat(response.dogs()).isNotNull();
|
||||
assertThat(response.dogs().size()).isEqualTo(2);
|
||||
}
|
||||
}).isInstanceOf(RuntimeException.class)
|
||||
.hasMessage(ERROR_MESSAGE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenStructuredConcurrency_whenSlowTasksReachesDeadline_thenCorrect() {
|
||||
assertThatThrownBy(() -> {
|
||||
try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
|
||||
Future<Shelter> shelter = scope.fork(this::getShelter);
|
||||
Future<List<Dog>> dogs = scope.fork(this::getDogsSlowly);
|
||||
scope.throwIfFailed(e -> new RuntimeException(ERROR_MESSAGE));
|
||||
scope.join();
|
||||
scope.joinUntil(Instant.now().plusMillis(50));
|
||||
Response response = new Response(shelter.resultNow(), dogs.resultNow());
|
||||
|
||||
assertThat(response).isNotNull();
|
||||
assertThat(response.shelter()).isNotNull();
|
||||
assertThat(response.dogs()).isNotNull();
|
||||
assertThat(response.dogs().size()).isEqualTo(2);
|
||||
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}).isInstanceOf(IllegalStateException.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenStructuredConcurrency_whenResultNow_thenCorrect() {
|
||||
try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
|
||||
Future<Shelter> shelter = scope.fork(this::getShelter);
|
||||
Future<List<Dog>> dogs = scope.fork(this::getDogs);
|
||||
scope.join();
|
||||
|
||||
Response response = new Response(shelter.resultNow(), dogs.resultNow());
|
||||
|
||||
assertThat(response).isNotNull();
|
||||
assertThat(response.shelter()).isNotNull();
|
||||
assertThat(response.dogs()).isNotNull();
|
||||
assertThat(response.dogs().size()).isEqualTo(2);
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenUnstructuredConcurrency_whenGet_thenCorrect() {
|
||||
Future<Shelter> shelter;
|
||||
Future<List<Dog>> dogs;
|
||||
try (ExecutorService executorService = Executors.newFixedThreadPool(3)) {
|
||||
shelter = executorService.submit(this::getShelter);
|
||||
dogs = executorService.submit(this::getDogs);
|
||||
Shelter theShelter = shelter.get(); // Join the shelter
|
||||
List<Dog> theDogs = dogs.get(); // Join the dogs
|
||||
Response response = new Response(theShelter, theDogs);
|
||||
|
||||
assertThat(response).isNotNull();
|
||||
assertThat(response.shelter()).isNotNull();
|
||||
assertThat(response.dogs()).isNotNull();
|
||||
assertThat(response.dogs().size()).isEqualTo(2);
|
||||
|
||||
} catch (ExecutionException | InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private Shelter getShelter() {
|
||||
return new Shelter("Shelter");
|
||||
}
|
||||
|
||||
private List<Dog> getDogs() {
|
||||
return List.of(new Dog("Buddy"), new Dog("Simba"));
|
||||
}
|
||||
|
||||
private List<Dog> getDogsWithException() {
|
||||
throw new RuntimeException(ERROR_MESSAGE);
|
||||
}
|
||||
|
||||
private List<Dog> getDogsSlowly() throws InterruptedException {
|
||||
Thread.sleep(1500);
|
||||
throw new RuntimeException(ERROR_MESSAGE);
|
||||
}
|
||||
|
||||
record Shelter(String name) {
|
||||
}
|
||||
|
||||
record Dog(String name) {
|
||||
}
|
||||
|
||||
record Response(Shelter shelter, List<Dog> dogs) {
|
||||
}
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
package com.baeldung.initializearraylistwithnullorzeros;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class InitializeArrayListWithNullOrZeros {
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
ArrayList<Integer> arrayList = new ArrayList<>();
|
||||
for (int i = 0; i< 10; i++) {
|
||||
arrayList.add(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+74
@@ -0,0 +1,74 @@
|
||||
package com.baeldung.initializearraylistwithnullorzeros;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.IntStream;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class InitializeArrayListWithNullOrZerosUnitTest {
|
||||
|
||||
@Test
|
||||
public void whenInitializingListWithNCopies_thenListIsCorrectlyPopulated() {
|
||||
// when
|
||||
ArrayList<Integer> list = IntStream.of(new int[10])
|
||||
.boxed()
|
||||
.collect(Collectors.toCollection(ArrayList::new));
|
||||
|
||||
// then
|
||||
Assertions.assertEquals(10, list.size());
|
||||
Assertions.assertTrue(list.stream().allMatch(elem -> elem == 0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenInitializingListWithStream_thenListIsCorrectlyPopulated() {
|
||||
|
||||
// when
|
||||
ArrayList<Integer> listWithZeros = Stream.generate(() -> 0)
|
||||
.limit(10).collect(Collectors.toCollection(ArrayList::new));
|
||||
|
||||
ArrayList<Object> listWithNulls = Stream.generate(() -> null)
|
||||
.limit(10).collect(Collectors.toCollection(ArrayList::new));
|
||||
|
||||
// then
|
||||
Assertions.assertEquals(10, listWithZeros.size());
|
||||
Assertions.assertTrue(listWithZeros.stream().allMatch(elem -> elem == 0));
|
||||
|
||||
Assertions.assertEquals(10, listWithNulls.size());
|
||||
Assertions.assertTrue(listWithNulls.stream().allMatch(Objects::isNull));
|
||||
}
|
||||
|
||||
@Test public void whenInitializingListWithIntStream_thenListIsCorrectlyPopulated() {
|
||||
// when
|
||||
ArrayList<Integer> list = IntStream.of(new int[10])
|
||||
.boxed()
|
||||
.collect(Collectors.toCollection(ArrayList::new));
|
||||
|
||||
// then
|
||||
Assertions.assertEquals(10, list.size());
|
||||
Assertions.assertTrue(list.stream().allMatch(elem -> elem == 0)); }
|
||||
|
||||
@Test
|
||||
public void whenInitializingListWithAsList_thenListIsCorrectlyPopulated() {
|
||||
// when
|
||||
Integer[] integers = new Integer[10];
|
||||
Arrays.fill(integers, 0);
|
||||
List<Integer> integerList = new ArrayList<>(Arrays.asList(integers));
|
||||
|
||||
// then
|
||||
Assertions.assertEquals(10, integerList.size());
|
||||
Assertions.assertTrue(integerList.stream().allMatch(elem -> elem == 0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenInitializingListWithVector_thenListIsCorrectlyPopulated() {
|
||||
// when
|
||||
List<Integer> integerList = new Vector<>() {{setSize(10);}};
|
||||
|
||||
// then
|
||||
Assertions.assertEquals(10, integerList.size());
|
||||
Assertions.assertTrue(integerList.stream().allMatch(Objects::isNull));
|
||||
}
|
||||
}
|
||||
@@ -2,4 +2,5 @@
|
||||
|
||||
This module contains articles about the Java List collection
|
||||
|
||||
### Relevant Articles:
|
||||
### Relevant Articles:
|
||||
- [Java List Interface](https://www.baeldung.com/java-list-interface)
|
||||
|
||||
@@ -9,4 +9,5 @@ This module contains articles about core java exceptions
|
||||
- [“Sneaky Throws” in Java](https://www.baeldung.com/java-sneaky-throws)
|
||||
- [Get the Current Stack Trace in Java](https://www.baeldung.com/java-get-current-stack-trace)
|
||||
- [Errors and Exceptions in Java](https://www.baeldung.com/java-errors-vs-exceptions)
|
||||
- [Fix the IllegalArgumentException: No enum const class](https://www.baeldung.com/java-fix-no-enum-const-class)
|
||||
- [[<-- Prev]](../core-java-exceptions-3)
|
||||
|
||||
@@ -14,4 +14,30 @@
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-inline</artifactId>
|
||||
<version>${mockito-inline.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<finalName>core-java-functional</finalName>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>src/main/resources</directory>
|
||||
<filtering>true</filtering>
|
||||
</resource>
|
||||
</resources>
|
||||
</build>
|
||||
|
||||
<properties>
|
||||
<mockito-inline.version>3.8.0</mockito-inline.version>
|
||||
<assertj.version>3.22.0</assertj.version>
|
||||
<commons-lang3.version>3.12.0</commons-lang3.version>
|
||||
<vavr.version>0.10.4</vavr.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
package com.baeldung.callbackfunctions;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class ConsumerCallback {
|
||||
public void getAge(int initialAge, Consumer<Integer> callback) {
|
||||
callback.accept(initialAge);
|
||||
}
|
||||
|
||||
public void increaseAge(int initialAge, int ageDifference, Consumer<Integer> callback) {
|
||||
System.out.println("===== Increase age ====");
|
||||
|
||||
int newAge = initialAge + ageDifference;
|
||||
callback.accept(newAge);
|
||||
|
||||
}
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
package com.baeldung.callbackfunctions;
|
||||
|
||||
public interface EventListener {
|
||||
|
||||
String onTrigger();
|
||||
|
||||
void respondToTrigger();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
package com.baeldung.callbackfunctions.asynchronous;
|
||||
|
||||
import com.baeldung.callbackfunctions.EventListener;
|
||||
|
||||
public class AsynchronousEventConsumer{
|
||||
|
||||
private EventListener listener;
|
||||
|
||||
public AsynchronousEventConsumer(EventListener listener) {
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
public void doAsynchronousOperation()
|
||||
{
|
||||
System.out.println("Performing operation in Asynchronous Task");
|
||||
|
||||
new Thread(() -> listener.onTrigger()).start();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
package com.baeldung.callbackfunctions.asynchronous;
|
||||
|
||||
import com.baeldung.callbackfunctions.EventListener;
|
||||
|
||||
public class AsynchronousEventListenerImpl implements EventListener {
|
||||
|
||||
@Override
|
||||
public String onTrigger()
|
||||
{
|
||||
respondToTrigger();
|
||||
return "Asynchronously running callback function";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void respondToTrigger(){
|
||||
System.out.println("This is a side effect of the asynchronous trigger.");
|
||||
}
|
||||
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
package com.baeldung.callbackfunctions.synchronous;
|
||||
|
||||
import com.baeldung.callbackfunctions.EventListener;
|
||||
|
||||
public class SynchronousEventConsumer {
|
||||
|
||||
private final EventListener eventListener;
|
||||
|
||||
public SynchronousEventConsumer(EventListener listener)
|
||||
{
|
||||
this.eventListener = listener;
|
||||
}
|
||||
|
||||
public String doSynchronousOperation()
|
||||
{
|
||||
System.out.println("Performing callback before synchronous Task");
|
||||
|
||||
return eventListener.onTrigger();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
package com.baeldung.callbackfunctions.synchronous;
|
||||
|
||||
import com.baeldung.callbackfunctions.EventListener;
|
||||
|
||||
public class SynchronousEventListenerImpl implements EventListener {
|
||||
|
||||
@Override
|
||||
public String onTrigger()
|
||||
{
|
||||
return "Synchronously running callback function";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void respondToTrigger(){
|
||||
System.out.println("Response to trigger");
|
||||
}
|
||||
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
package com.baeldung.callbackfunctions;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.mockito.Mockito;
|
||||
import com.baeldung.callbackfunctions.EventListener;
|
||||
import com.baeldung.callbackfunctions.asynchronous.AsynchronousEventConsumer;
|
||||
import com.baeldung.callbackfunctions.asynchronous.AsynchronousEventListenerImpl;
|
||||
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
public class AsynchronousCallbackUnitTest {
|
||||
|
||||
@Test
|
||||
public void whenCallbackIsInvokedAsynchronously_shouldRunAsynchronousOperation(){
|
||||
EventListener listener = Mockito.mock(AsynchronousEventListenerImpl.class);
|
||||
AsynchronousEventConsumer asynchronousEventListenerConsumer = new AsynchronousEventConsumer(listener);
|
||||
asynchronousEventListenerConsumer.doAsynchronousOperation();
|
||||
|
||||
verify(listener, times(1)).onTrigger();
|
||||
}
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
package com.baeldung.callbackfunctions;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import com.baeldung.callbackfunctions.ConsumerCallback;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
public class ConsumerCallbackUnitTest {
|
||||
|
||||
@Test
|
||||
public void whenIncreasingInitialAgeByGivenValueThroughCallback_shouldIncreaseAge(){
|
||||
ConsumerCallback consumerCallback = new ConsumerCallback();
|
||||
consumerCallback.getAge(20, (initialAge) -> {
|
||||
int ageDifference = 10;
|
||||
consumerCallback.increaseAge(initialAge, ageDifference, (newAge) -> {
|
||||
assertEquals(initialAge + ageDifference, newAge);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
package callbackFunctions;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import com.baeldung.callbackfunctions.EventListener;
|
||||
import com.baeldung.callbackfunctions.synchronous.SynchronousEventConsumer;
|
||||
import com.baeldung.callbackfunctions.synchronous.SynchronousEventListenerImpl;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
|
||||
public class SynchronousCallbackUnitTest {
|
||||
|
||||
@Test
|
||||
public void whenCallbackIsInvokedSynchronously_shouldRunSynchronousOperation(){
|
||||
EventListener listener = new SynchronousEventListenerImpl();
|
||||
SynchronousEventConsumer synchronousEventConsumer = new SynchronousEventConsumer(listener);
|
||||
String result = synchronousEventConsumer.doSynchronousOperation();
|
||||
|
||||
assertNotNull(result);
|
||||
assertEquals("Synchronously running callback function", result);
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -41,7 +41,7 @@ public class InMemoryCompilationUnitTest {
|
||||
|
||||
boolean result = task.call();
|
||||
|
||||
if (result) {
|
||||
if (!result) {
|
||||
diagnostics.getDiagnostics()
|
||||
.forEach(d -> LOGGER.error(String.valueOf(d)));
|
||||
} else {
|
||||
|
||||
@@ -11,6 +11,8 @@ public class Book implements Serializable {
|
||||
private transient int copies;
|
||||
private final transient String bookCategory = "Fiction";
|
||||
|
||||
private final transient String bookCategoryNewOperator = new String("Fiction with new Operator");
|
||||
|
||||
public String getBookName() {
|
||||
return bookName;
|
||||
}
|
||||
@@ -39,4 +41,7 @@ public class Book implements Serializable {
|
||||
return bookCategory;
|
||||
}
|
||||
|
||||
public String getBookCategoryNewOperator() {
|
||||
return bookCategoryNewOperator;
|
||||
}
|
||||
}
|
||||
|
||||
+11
-1
@@ -34,7 +34,17 @@ class TransientUnitTest {
|
||||
|
||||
assertEquals("Fiction", book2.getBookCategory());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
void givenFinalTransientWithNewOperator_whenSerDe_thenValuePersisted() throws Exception {
|
||||
Book book = new Book();
|
||||
|
||||
BookSerDe.serialize(book);
|
||||
Book book2 = BookSerDe.deserialize();
|
||||
|
||||
assertNull(book2.getBookCategoryNewOperator());
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
public static void cleanup() {
|
||||
File file = new File(BookSerDe.fileName);
|
||||
|
||||
@@ -12,4 +12,5 @@ This module contains articles about core features in the Java language
|
||||
- [Infinity in Java](https://www.baeldung.com/java-infinity)
|
||||
- [Type Parameter vs Wildcard in Java Generics](https://www.baeldung.com/java-generics-type-parameter-vs-wildcard)
|
||||
- [Convert Between int and char in Java](https://www.baeldung.com/java-convert-int-char)
|
||||
-
|
||||
- [Converting a Number from One Base to Another in Java](https://www.baeldung.com/java-converting-a-number-from-one-base-to-another)
|
||||
- [Check if Command-Line Arguments Are Null in Java](https://www.baeldung.com/java-check-command-line-args)
|
||||
|
||||
@@ -13,6 +13,12 @@
|
||||
<artifactId>core-java-modules</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
<commons-lang3.version>3.12.0</commons-lang3.version>
|
||||
<reflections.version>0.10.2</reflections.version>
|
||||
</properties>
|
||||
|
||||
|
||||
<build>
|
||||
<finalName>core-java-lang-5</finalName>
|
||||
@@ -24,4 +30,18 @@
|
||||
</resources>
|
||||
</build>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
<version>${commons-lang3.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.reflections</groupId>
|
||||
<artifactId>reflections</artifactId>
|
||||
<version>${reflections.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
package com.baeldung.checkinterface;
|
||||
|
||||
public class ChildClass1 implements ChildInterface1 {
|
||||
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
package com.baeldung.checkinterface;
|
||||
|
||||
public class ChildClass2 implements ChildInterface2 {
|
||||
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
package com.baeldung.checkinterface;
|
||||
|
||||
public interface ChildInterface1 extends MasterInterface {
|
||||
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user