Merge branch 'eugenp:master' into master

This commit is contained in:
cesarevalenti90 2023-01-31 23:03:17 +01:00 committed by GitHub
commit 20915e1718
139 changed files with 3827 additions and 363 deletions

View File

@ -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) - [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) - [Snapshotting Aggregates in Axon](https://www.baeldung.com/axon-snapshotting-aggregates)
- [Dispatching Queries in Axon Framework](https://www.baeldung.com/axon-query-dispatching) - [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)

View File

@ -81,13 +81,22 @@
<dependency> <dependency>
<groupId>org.awaitility</groupId> <groupId>org.awaitility</groupId>
<artifactId>awaitility</artifactId> <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> <scope>test</scope>
</dependency> </dependency>
</dependencies> </dependencies>
<properties> <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> <de.flapdoodle.embed.mongo.version>3.4.8</de.flapdoodle.embed.mongo.version>
</properties> </properties>

View File

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

View File

@ -14,6 +14,20 @@
<version>1.0.0-SNAPSHOT</version> <version>1.0.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath> <relativePath>../../pom.xml</relativePath>
</parent> </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> <build>
<plugins> <plugins>
@ -32,6 +46,8 @@
<properties> <properties>
<maven.compiler.source.version>11</maven.compiler.source.version> <maven.compiler.source.version>11</maven.compiler.source.version>
<maven.compiler.target.version>11</maven.compiler.target.version> <maven.compiler.target.version>11</maven.compiler.target.version>
<jackson.version>2.14.1</jackson.version>
<gson.version>2.10</gson.version>
</properties> </properties>
</project> </project>

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -2,4 +2,5 @@
This module contains articles about the Java List collection This module contains articles about the Java List collection
### Relevant Articles: ### Relevant Articles:
- [Java List Interface](https://www.baeldung.com/java-list-interface)

View File

@ -9,4 +9,5 @@ This module contains articles about core java exceptions
- [“Sneaky Throws” in Java](https://www.baeldung.com/java-sneaky-throws) - [“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) - [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) - [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) - [[<-- Prev]](../core-java-exceptions-3)

View File

@ -14,4 +14,30 @@
<version>0.0.1-SNAPSHOT</version> <version>0.0.1-SNAPSHOT</version>
</parent> </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> </project>

View File

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

View File

@ -0,0 +1,12 @@
package com.baeldung.callbackfunctions;
public interface EventListener {
String onTrigger();
void respondToTrigger();
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -41,7 +41,7 @@ public class InMemoryCompilationUnitTest {
boolean result = task.call(); boolean result = task.call();
if (result) { if (!result) {
diagnostics.getDiagnostics() diagnostics.getDiagnostics()
.forEach(d -> LOGGER.error(String.valueOf(d))); .forEach(d -> LOGGER.error(String.valueOf(d)));
} else { } else {

View File

@ -11,6 +11,8 @@ public class Book implements Serializable {
private transient int copies; private transient int copies;
private final transient String bookCategory = "Fiction"; private final transient String bookCategory = "Fiction";
private final transient String bookCategoryNewOperator = new String("Fiction with new Operator");
public String getBookName() { public String getBookName() {
return bookName; return bookName;
} }
@ -39,4 +41,7 @@ public class Book implements Serializable {
return bookCategory; return bookCategory;
} }
public String getBookCategoryNewOperator() {
return bookCategoryNewOperator;
}
} }

View File

@ -34,7 +34,17 @@ class TransientUnitTest {
assertEquals("Fiction", book2.getBookCategory()); 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 @AfterAll
public static void cleanup() { public static void cleanup() {
File file = new File(BookSerDe.fileName); File file = new File(BookSerDe.fileName);

View File

@ -12,4 +12,5 @@ This module contains articles about core features in the Java language
- [Infinity in Java](https://www.baeldung.com/java-infinity) - [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) - [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) - [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)

View File

@ -13,6 +13,12 @@
<artifactId>core-java-modules</artifactId> <artifactId>core-java-modules</artifactId>
<version>0.0.1-SNAPSHOT</version> <version>0.0.1-SNAPSHOT</version>
</parent> </parent>
<properties>
<commons-lang3.version>3.12.0</commons-lang3.version>
<reflections.version>0.10.2</reflections.version>
</properties>
<build> <build>
<finalName>core-java-lang-5</finalName> <finalName>core-java-lang-5</finalName>
@ -24,4 +30,18 @@
</resources> </resources>
</build> </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> </project>

View File

@ -0,0 +1,5 @@
package com.baeldung.checkinterface;
public class ChildClass1 implements ChildInterface1 {
}

View File

@ -0,0 +1,5 @@
package com.baeldung.checkinterface;
public class ChildClass2 implements ChildInterface2 {
}

View File

@ -0,0 +1,5 @@
package com.baeldung.checkinterface;
public interface ChildInterface1 extends MasterInterface {
}

View File

@ -0,0 +1,5 @@
package com.baeldung.checkinterface;
public interface ChildInterface2 extends MasterInterface {
}

View File

@ -0,0 +1,5 @@
package com.baeldung.checkinterface;
public class MasterClass implements MasterInterface {
}

View File

@ -0,0 +1,5 @@
package com.baeldung.checkinterface;
public interface MasterInterface {
}

View File

@ -0,0 +1,12 @@
package com.baeldung.commandline;
public class CommandLineWithErrorHandling {
public static void main(String[] args) {
if (args.length > 0) {
System.out.println(args[0]);
} else {
System.out.println("No command line arguments were provided.");
}
}
}

View File

@ -0,0 +1,9 @@
package com.baeldung.commandline;
public class CommandLineWithoutErrorHandling {
public static void main(String[] args) {
System.out.println(args[0]);
}
}

View File

@ -0,0 +1,154 @@
package com.baeldung.checkinterface;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.apache.commons.lang3.ClassUtils;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.reflections.ReflectionUtils;
import org.reflections.Reflections;
public class CheckInterfaceUnitTest {
protected static Reflections reflections;
@BeforeAll
public static void initializeReflectionsLibrary() {
reflections = new Reflections("com.baeldung.checkinterface");
}
@Test
public void whenUsingReflectionGetInterfaces_thenDirectlyImplementedInterfaceIsFound() {
ChildClass2 childClass2 = new ChildClass2();
List<Class<?>> interfaces = Arrays.asList(childClass2.getClass().getInterfaces());
assertEquals(1, interfaces.size());
assertTrue(interfaces.contains(ChildInterface2.class));
}
@Test
public void whenUsingReflectionGetInterfaces_thenParentInterfaceIsNotFound() {
ChildClass2 childClass2 = new ChildClass2();
List<Class<?>> interfaces = Arrays.asList(childClass2.getClass().getInterfaces());
assertFalse(interfaces.contains(MasterInterface.class));
}
@Test
public void whenUsingReflectionGetInterfacesRecursively_thenParentInterfaceIsFound() {
Set<Class<?>> interfaces = getAllExtendedOrImplementedInterfacesRecursively(ChildClass2.class);
assertTrue(interfaces.contains(ChildInterface2.class));
assertTrue(interfaces.contains(MasterInterface.class));
}
@Test
public void whenUsingReflectionIsAssignableFrom_thenDirectlyImplementedInterfaceIsFound() {
ChildClass2 childClass2 = new ChildClass2();
assertTrue(ChildInterface2.class.isAssignableFrom(childClass2.getClass()));
}
@Test
public void whenUsingReflectionIsAssignableFrom_thenParentInterfaceIsFound() {
ChildClass2 childClass2 = new ChildClass2();
assertTrue(MasterInterface.class.isAssignableFrom(childClass2.getClass()));
}
@Test
public void whenUsingReflectionIsInstance_thenDirectlyImplementedInterfaceIsFound() {
ChildClass2 childClass2 = new ChildClass2();
assertTrue(ChildInterface2.class.isInstance(childClass2));
}
@Test
public void whenUsingReflectionIsInstance_thenParentInterfaceIsFound() {
ChildClass2 childClass2 = new ChildClass2();
assertTrue(MasterInterface.class.isInstance(childClass2));
}
@Test
public void whenUsingReflectionInstanceOf_thenDirectlyImplementedInterfaceIsFound() {
ChildClass2 childClass2 = new ChildClass2();
assertTrue(childClass2 instanceof ChildInterface2);
}
@Test
public void whenUsingReflectionInstanceOf_thenParentInterfaceIsFound() {
ChildClass2 childClass2 = new ChildClass2();
assertTrue(childClass2 instanceof MasterInterface);
}
@Test
public void whenUsingCommons_thenDirectlyImplementedInterfaceIsFound() {
ChildClass2 childClass2 = new ChildClass2();
List<Class<?>> interfaces = ClassUtils.getAllInterfaces(childClass2.getClass());
assertTrue(interfaces.contains(ChildInterface2.class));
}
@Test
public void whenUsingCommons_thenParentInterfaceIsFound() {
ChildClass2 childClass2 = new ChildClass2();
List<Class<?>> interfaces = ClassUtils.getAllInterfaces(childClass2.getClass());
assertTrue(interfaces.contains(MasterInterface.class));
}
@Test
public void whenUsingReflections_thenDirectlyImplementedInterfaceIsFound() {
ChildClass2 childClass2 = new ChildClass2();
Set<Class<?>> interfaces = reflections.get(ReflectionUtils.Interfaces.of(childClass2.getClass()));
assertTrue(interfaces.contains(ChildInterface2.class));
}
@Test
public void whenUsingReflections_thenParentInterfaceIsFound() {
ChildClass2 childClass2 = new ChildClass2();
Set<Class<?>> interfaces = reflections.get(ReflectionUtils.Interfaces.of(childClass2.getClass()));
assertTrue(interfaces.contains(MasterInterface.class));
}
static Set<Class<?>> getAllExtendedOrImplementedInterfacesRecursively(Class<?> clazz) {
Set<Class<?>> res = new HashSet<Class<?>>();
Class<?>[] interfaces = clazz.getInterfaces();
if (interfaces.length > 0) {
res.addAll(Arrays.asList(interfaces));
for (Class<?> interfaze : interfaces) {
res.addAll(getAllExtendedOrImplementedInterfacesRecursively(interfaze));
}
}
return res;
}
}

View File

@ -0,0 +1,12 @@
package com.baeldung.commandline;
import org.junit.Test;
import static org.junit.Assert.fail;
public class CommandLineWithoutErrorHandlingUnitTest {
@Test(expected = NullPointerException.class)
public void givenNullCommandLineArgument_whenPassedToMainFunction_thenExpectNullPointerException() {
CommandLineWithoutErrorHandling.main(null);
}
}

View File

@ -0,0 +1,78 @@
package com.baeldung.enums.comparestrenum;
import org.junit.jupiter.api.Test;
import java.util.Arrays;
import java.util.Optional;
import static com.baeldung.enums.comparestrenum.Weekday.Fri;
import static com.baeldung.enums.comparestrenum.Weekday.Sat;
import static org.junit.jupiter.api.Assertions.*;
enum Weekday {
Mon("Monday"),
Tue("Tuesday"),
Wed("Wednesday"),
Thu("Thursday"),
Fri("Friday"),
Sat("Saturday");
private String fullName;
Weekday(String fullName) {
this.fullName = fullName;
}
public String getFullName() {
return fullName;
}
static Optional<Weekday> byFullNameIgnoreCase(String givenFullName) {
return Arrays.stream(values()).filter(it -> it.fullName.equalsIgnoreCase(givenFullName)).findAny();
}
static Optional<Weekday> byNameIgnoreCase(String givenName) {
return Arrays.stream(values()).filter(it -> it.name().equalsIgnoreCase(givenName)).findAny();
}
}
public class CompareStringAndEnumUnitTest {
private static final String SAT = "sAt";
private static final String SATURDAY = "sAtuRdAy";
private static final String TYPO_FRI = "ffri";
private static final String TYPO_FRIDAY = "ffriday";
@Test
void givenAString_whenCompareEnumWithName_thenGetExpectedResult() {
assertTrue(SAT.equalsIgnoreCase(Sat.name()));
assertFalse(TYPO_FRI.equalsIgnoreCase(Fri.name()));
}
@Test
void givenAString_whenCompareEnumWithProperty_thenGetExpectedResult() {
assertTrue(SATURDAY.equalsIgnoreCase(Sat.getFullName()));
assertFalse(TYPO_FRI.equalsIgnoreCase(Fri.getFullName()));
}
@Test
void givenAString_whenFindEnumByName_thenGetExpectedResult() {
Optional<Weekday> optResult = Weekday.byNameIgnoreCase(SAT);
assertTrue(optResult.isPresent());
assertEquals(Sat, optResult.get());
Optional<Weekday> optResult2 = Weekday.byNameIgnoreCase(TYPO_FRI);
assertFalse(optResult2.isPresent());
}
@Test
void givenAString_whenFindEnumByProperty_thenGetExpectedResult() {
Optional<Weekday> optResult = Weekday.byFullNameIgnoreCase(SATURDAY);
assertTrue(optResult.isPresent());
assertEquals(Sat, optResult.get());
Optional<Weekday> optResult2 = Weekday.byFullNameIgnoreCase(TYPO_FRIDAY);
assertFalse(optResult2.isPresent());
}
}

View File

@ -25,15 +25,20 @@
<version>${commons-lang3.version}</version> <version>${commons-lang3.version}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>javax.mail</groupId> <groupId>org.eclipse.angus</groupId>
<artifactId>mail</artifactId> <artifactId>angus-mail</artifactId>
<version>${javax.mail.version}</version> <version>${angus.mail.version}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.asynchttpclient</groupId> <groupId>org.asynchttpclient</groupId>
<artifactId>async-http-client</artifactId> <artifactId>async-http-client</artifactId>
<version>${async-http-client.version}</version> <version>${async-http-client.version}</version>
</dependency> </dependency>
<dependency>
<groupId>jakarta.xml.bind</groupId>
<artifactId>jakarta.xml.bind-api</artifactId>
<version>${jakarta.bind.version}</version>
</dependency>
<dependency> <dependency>
<groupId>com.icegreen</groupId> <groupId>com.icegreen</groupId>
<artifactId>greenmail</artifactId> <artifactId>greenmail</artifactId>
@ -48,9 +53,10 @@
<properties> <properties>
<httpclient.version>4.5.9</httpclient.version> <httpclient.version>4.5.9</httpclient.version>
<javax.mail.version>1.5.0-b01</javax.mail.version> <angus.mail.version>2.0.1</angus.mail.version>
<async-http-client.version>2.4.5</async-http-client.version> <async-http-client.version>2.4.5</async-http-client.version>
<greenmail.version>1.5.8</greenmail.version> <jakarta.bind.version>2.3.3</jakarta.bind.version>
<greenmail.version>2.0.0-alpha-3</greenmail.version>
</properties> </properties>
</project> </project>

View File

@ -1,19 +1,20 @@
package com.baeldung.mail; package com.baeldung.mail;
import javax.mail.Authenticator;
import javax.mail.Message;
import javax.mail.Multipart;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import java.io.File; import java.io.File;
import java.net.URI; import java.net.URI;
import java.util.Properties; import java.util.Properties;
import jakarta.mail.Authenticator;
import jakarta.mail.Message;
import jakarta.mail.Multipart;
import jakarta.mail.PasswordAuthentication;
import jakarta.mail.Session;
import jakarta.mail.Transport;
import jakarta.mail.internet.InternetAddress;
import jakarta.mail.internet.MimeBodyPart;
import jakarta.mail.internet.MimeMessage;
import jakarta.mail.internet.MimeMultipart;
public class EmailService { public class EmailService {
private String username; private String username;

View File

@ -1,21 +1,23 @@
package com.baeldung.mail.mailwithattachment; package com.baeldung.mail.mailwithattachment;
import javax.mail.BodyPart;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.net.URI; import java.net.URI;
import java.util.Properties; import java.util.Properties;
import jakarta.mail.Authenticator;
import jakarta.mail.BodyPart;
import jakarta.mail.Message;
import jakarta.mail.MessagingException;
import jakarta.mail.Multipart;
import jakarta.mail.PasswordAuthentication;
import jakarta.mail.Session;
import jakarta.mail.Transport;
import jakarta.mail.internet.InternetAddress;
import jakarta.mail.internet.MimeBodyPart;
import jakarta.mail.internet.MimeMessage;
import jakarta.mail.internet.MimeMultipart;
public class MailWithAttachmentService { public class MailWithAttachmentService {
private final String username; private final String username;
@ -37,7 +39,7 @@ public class MailWithAttachmentService {
props.put("mail.smtp.host", this.host); props.put("mail.smtp.host", this.host);
props.put("mail.smtp.port", this.port); props.put("mail.smtp.port", this.port);
return Session.getInstance(props, new javax.mail.Authenticator() { return Session.getInstance(props, new Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() { protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(username, password); return new PasswordAuthentication(username, password);
} }

View File

@ -1,10 +1,7 @@
package com.baeldung.download; package com.baeldung.download;
import org.junit.After; import static org.junit.Assert.assertTrue;
import org.junit.BeforeClass;
import org.junit.Test;
import javax.xml.bind.DatatypeConverter;
import java.io.IOException; import java.io.IOException;
import java.net.URISyntaxException; import java.net.URISyntaxException;
import java.nio.file.Files; import java.nio.file.Files;
@ -13,7 +10,11 @@ import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import static org.junit.Assert.assertTrue; import javax.xml.bind.DatatypeConverter;
import org.junit.After;
import org.junit.BeforeClass;
import org.junit.Test;
public class FileDownloadIntegrationTest { public class FileDownloadIntegrationTest {

View File

@ -1,17 +1,19 @@
package com.baeldung.mail; package com.baeldung.mail;
import com.icegreen.greenmail.junit.GreenMailRule; import static org.junit.Assert.assertEquals;
import com.icegreen.greenmail.util.ServerSetupTest;
import java.io.IOException;
import org.junit.Before; import org.junit.Before;
import org.junit.Rule; import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import javax.mail.MessagingException; import com.icegreen.greenmail.junit.GreenMailRule;
import javax.mail.internet.MimeMessage; import com.icegreen.greenmail.util.ServerSetupTest;
import javax.mail.internet.MimeMultipart;
import java.io.IOException;
import static org.junit.Assert.assertEquals; import jakarta.mail.MessagingException;
import jakarta.mail.internet.MimeMessage;
import jakarta.mail.internet.MimeMultipart;
public class EmailServiceLiveTest { public class EmailServiceLiveTest {

View File

@ -1,20 +1,20 @@
package com.baeldung.mail.mailwithattachment; package com.baeldung.mail.mailwithattachment;
import static org.junit.Assert.assertEquals;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import com.icegreen.greenmail.configuration.GreenMailConfiguration; import com.icegreen.greenmail.configuration.GreenMailConfiguration;
import com.icegreen.greenmail.junit.GreenMailRule; import com.icegreen.greenmail.junit.GreenMailRule;
import com.icegreen.greenmail.util.GreenMailUtil; import com.icegreen.greenmail.util.GreenMailUtil;
import com.icegreen.greenmail.util.ServerSetupTest; import com.icegreen.greenmail.util.ServerSetupTest;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import javax.annotation.Resource; import jakarta.mail.MessagingException;
import javax.mail.MessagingException; import jakarta.mail.Session;
import javax.mail.Session; import jakarta.mail.internet.MimeMessage;
import javax.mail.internet.MimeMessage; import jakarta.mail.internet.MimeMultipart;
import javax.mail.internet.MimeMultipart;
import static org.junit.Assert.assertEquals;
public class MailWithAttachmentServiceLiveTest { public class MailWithAttachmentServiceLiveTest {
@ -29,7 +29,6 @@ public class MailWithAttachmentServiceLiveTest {
.withUser(USERNAME, PASSWORD) .withUser(USERNAME, PASSWORD)
); );
@Resource
private MailWithAttachmentService emailService; private MailWithAttachmentService emailService;
@Before @Before
@ -73,5 +72,4 @@ public class MailWithAttachmentServiceLiveTest {
return GreenMailUtil.getBody(((MimeMultipart) receivedMessage.getContent()) return GreenMailUtil.getBody(((MimeMultipart) receivedMessage.getContent())
.getBodyPart(2)); .getBodyPart(2));
} }
} }

View File

@ -30,9 +30,9 @@
<version>${tomcat.embeded.version}</version> <version>${tomcat.embeded.version}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.sun.mail</groupId> <groupId>org.eclipse.angus</groupId>
<artifactId>javax.mail</artifactId> <artifactId>angus-mail</artifactId>
<version>${javax.mail.version}</version> <version>${angus.mail.version}</version>
</dependency> </dependency>
<!-- https://mvnrepository.com/artifact/com.github.seancfoley/ipaddress --> <!-- https://mvnrepository.com/artifact/com.github.seancfoley/ipaddress -->
<dependency> <dependency>
@ -95,7 +95,7 @@
<seancfoley.ipaddress.version>5.3.3</seancfoley.ipaddress.version> <seancfoley.ipaddress.version>5.3.3</seancfoley.ipaddress.version>
<jgonian.commons-ip-math.version>1.32</jgonian.commons-ip-math.version> <jgonian.commons-ip-math.version>1.32</jgonian.commons-ip-math.version>
<googlecode.ipv6.version>0.17</googlecode.ipv6.version> <googlecode.ipv6.version>0.17</googlecode.ipv6.version>
<javax.mail.version>1.6.2</javax.mail.version> <angus.mail.version>2.0.1</angus.mail.version>
<apache.commons-validator.version>1.7</apache.commons-validator.version> <apache.commons-validator.version>1.7</apache.commons-validator.version>
</properties> </properties>

View File

@ -6,16 +6,16 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Properties; import java.util.Properties;
import javax.mail.Address; import jakarta.mail.Address;
import javax.mail.Folder; import jakarta.mail.Folder;
import javax.mail.Message; import jakarta.mail.Message;
import javax.mail.MessagingException; import jakarta.mail.MessagingException;
import javax.mail.Multipart; import jakarta.mail.Multipart;
import javax.mail.NoSuchProviderException; import jakarta.mail.NoSuchProviderException;
import javax.mail.Part; import jakarta.mail.Part;
import javax.mail.Session; import jakarta.mail.Session;
import javax.mail.Store; import jakarta.mail.Store;
import javax.mail.internet.MimeBodyPart; import jakarta.mail.internet.MimeBodyPart;
public class DownloadEmailAttachments { public class DownloadEmailAttachments {
private String downloadDirectory; private String downloadDirectory;
@ -24,7 +24,7 @@ public class DownloadEmailAttachments {
this.downloadDirectory = dir; this.downloadDirectory = dir;
} }
public void downloadEmailAttachments(String host, String port, String userName, String password) throws NoSuchProviderException, MessagingException, IOException { public void downloadEmailAttachments(String host, String port, String userName, String password) throws MessagingException, IOException {
Properties properties = setMailServerProperties(host, port); Properties properties = setMailServerProperties(host, port);
Store store = setSessionStoreProperties(userName, password, properties); Store store = setSessionStoreProperties(userName, password, properties);
Folder inbox = store.getFolder("INBOX"); Folder inbox = store.getFolder("INBOX");
@ -67,7 +67,7 @@ public class DownloadEmailAttachments {
return downloadedAttachments; return downloadedAttachments;
} }
public Store setSessionStoreProperties(String userName, String password, Properties properties) throws NoSuchProviderException, MessagingException { public Store setSessionStoreProperties(String userName, String password, Properties properties) throws MessagingException {
Session session = Session.getDefaultInstance(properties); Session session = Session.getDefaultInstance(properties);
Store store = session.getStore("pop3"); Store store = session.getStore("pop3");

View File

@ -6,3 +6,4 @@
- [List All Factors of a Number in Java](https://www.baeldung.com/java-list-factors-integer) - [List All Factors of a Number in Java](https://www.baeldung.com/java-list-factors-integer)
- [Make Division of Two Integers Result in a Float](https://www.baeldung.com/java-integer-division-float-result) - [Make Division of Two Integers Result in a Float](https://www.baeldung.com/java-integer-division-float-result)
- [Creating Random Numbers With No Duplicates in Java](https://www.baeldung.com/java-unique-random-numbers) - [Creating Random Numbers With No Duplicates in Java](https://www.baeldung.com/java-unique-random-numbers)
- [Multiply a BigDecimal by an Integer in Java](https://www.baeldung.com/java-bigdecimal-multiply-integer)

View File

@ -0,0 +1,26 @@
package com.baeldung;
import java.util.Optional;
import org.apache.commons.lang3.ObjectUtils;
public class IntegerNullOrZero {
private IntegerNullOrZero() {
throw new RuntimeException("This class cannot be instantiated.");
}
public static boolean usingStandardWay(Integer num) {
return num == null || num == 0;
}
public static boolean usingTernaryOperator(Integer num) {
return 0 == (num == null ? 0 : num);
}
public static boolean usingOptional(Integer num) {
return Optional.ofNullable(num).orElse(0) == 0;
}
public static boolean usingObjectUtils(Integer num) {
return ObjectUtils.defaultIfNull(num, 0) == 0;
}
}

View File

@ -0,0 +1,22 @@
package com.baeldung.bigdecimaltimesint;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals;
import java.math.BigDecimal;
import org.junit.jupiter.api.Test;
public class BigDecimalxIntegerUnitTest {
private static final BigDecimal BIG = new BigDecimal("42.42");
private static final int INT = 10;
private static final BigDecimal EXPECTED = new BigDecimal("424.2");
@Test
void givenBigDecimalAndInt_whenTimes_thenGetExpectedResult() {
BigDecimal result = BIG.multiply(BigDecimal.valueOf(INT));
assertEquals(0, EXPECTED.compareTo(result));
assertThat(result).isEqualByComparingTo(EXPECTED);
}
}

View File

@ -0,0 +1,69 @@
package com.baeldung.intnullorzero;
import static com.baeldung.IntegerNullOrZero.usingObjectUtils;
import static com.baeldung.IntegerNullOrZero.usingOptional;
import static com.baeldung.IntegerNullOrZero.usingStandardWay;
import static com.baeldung.IntegerNullOrZero.usingTernaryOperator;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import org.junit.jupiter.api.Test;
public class IntegerNullOrZeroUnitTest {
@Test
void givenInts_whenUsingStandardWay_thenGetExpectedResult() {
int n0 = 0;
boolean result0 = usingStandardWay(n0);
assertTrue(result0);
boolean resultNull = usingStandardWay(null);
assertTrue(resultNull);
int n42 = 42;
boolean result42 = usingStandardWay(n42);
assertFalse(result42);
}
@Test
void givenInts_whenUsingTernaryOperator_thenGetExpectedResult() {
int n0 = 0;
boolean result0 = usingTernaryOperator(n0);
assertTrue(result0);
boolean resultNull = usingTernaryOperator(null);
assertTrue(resultNull);
int n42 = 42;
boolean result42 = usingTernaryOperator(n42);
assertFalse(result42);
}
@Test
void givenInts_whenUsingOptional_thenGetExpectedResult() {
int n0 = 0;
boolean result0 = usingOptional(n0);
assertTrue(result0);
boolean resultNull = usingOptional(null);
assertTrue(resultNull);
int n42 = 42;
boolean result42 = usingOptional(n42);
assertFalse(result42);
}
@Test
void givenInts_whenUsingObjectUtils_thenGetExpectedResult() {
int n0 = 0;
boolean result0 = usingObjectUtils(n0);
assertTrue(result0);
boolean resultNull = usingObjectUtils(null);
assertTrue(resultNull);
int n42 = 42;
boolean result42 = usingObjectUtils(n42);
assertFalse(result42);
}
}

View File

@ -14,20 +14,20 @@ public class CustomBatchIterator<T> implements Iterator<List<T>> {
private List<T> currentBatch; private List<T> currentBatch;
private final Iterator<T> iterator; private final Iterator<T> iterator;
public CustomBatchIterator(Iterator<T> sourceIterator, int batchSize) { private CustomBatchIterator(Iterator<T> sourceIterator, int batchSize) {
this.batchSize = batchSize; this.batchSize = batchSize;
this.iterator = sourceIterator; this.iterator = sourceIterator;
} }
@Override @Override
public List<T> next() { public List<T> next() {
prepareNextBatch();
return currentBatch; return currentBatch;
} }
@Override @Override
public boolean hasNext() { public boolean hasNext() {
prepareNextBatch(); return iterator.hasNext();
return currentBatch != null && !currentBatch.isEmpty();
} }
public static <T> Stream<List<T>> batchStreamOf(Stream<T> stream, int batchSize) { public static <T> Stream<List<T>> batchStreamOf(Stream<T> stream, int batchSize) {

View File

@ -0,0 +1,42 @@
package com.baeldung.streams.streamtoiterable;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import joptsimple.internal.Strings;
public class StreamToIterable {
public String streamToIterableLambda(List<String> listOfStrings) {
Stream<String> stringStream = listOfStrings.stream();
StringBuilder sentence = new StringBuilder();
for (String eachString : (Iterable<String>) () -> stringStream.iterator()) {
doSomethingOnString(eachString, sentence);
}
return sentence.toString();
}
public String streamToIterableMethodReference(List<String> listOfStrings) {
Stream<String> stringStream = listOfStrings.stream();
StringBuilder sentence = new StringBuilder();
for (String eachString : (Iterable<String>) stringStream::iterator) {
doSomethingOnString(eachString, sentence);
}
return sentence.toString();
}
public String streamToList(List<String> listOfStrings) {
Stream<String> stringStream = listOfStrings.stream();
StringBuilder sentence = new StringBuilder();
for (String eachString : stringStream.collect(Collectors.toList())) {
doSomethingOnString(eachString, sentence);
}
return sentence.toString();
}
private void doSomethingOnString(String s, StringBuilder sentence) {
if (!Strings.isNullOrEmpty(s)) {
sentence.append(s);
}
}
}

View File

@ -0,0 +1,48 @@
package com.baeldung.streams.streamtoiterable;
import java.util.ArrayList;
import java.util.List;
import org.junit.Assert;
import org.junit.Test;
public class StreamToIterableUnitTest {
@Test
public void givenList_whenLambdaIsUsed_ThenStreamAsIterable(){
StreamToIterable streamToIterable = new StreamToIterable();
String actualString = streamToIterable.streamToIterableLambda(getListOfStrings());
String expectedString = "Thisisasentencewithnospaces";
Assert.assertEquals(expectedString, actualString);
}
@Test
public void givenList_whenMethodReferenceIsUsed_ThenStreamAsIterable(){
StreamToIterable streamToIterable = new StreamToIterable();
String actualString = streamToIterable.streamToIterableMethodReference(getListOfStrings());
String expectedString = "Thisisasentencewithnospaces";
Assert.assertEquals(expectedString, actualString);
}
@Test
public void givenList_whenCollectedToList_ThenStreamAsIterable(){
StreamToIterable streamToIterable = new StreamToIterable();
String actualString = streamToIterable.streamToList(getListOfStrings());
String expectedString = "Thisisasentencewithnospaces";
Assert.assertEquals(expectedString, actualString);
}
private List<String> getListOfStrings(){
List<String> listOfStrings = new ArrayList<>();
listOfStrings.add("This");
listOfStrings.add("is");
listOfStrings.add("a");
listOfStrings.add(null);
listOfStrings.add("sentence");
listOfStrings.add("with");
listOfStrings.add("no");
listOfStrings.add(null);
listOfStrings.add("spaces");
return listOfStrings;
}
}

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" <project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>com.baeldung</groupId> <groupId>com.baeldung</groupId>
<artifactId>multi-module-caching</artifactId> <artifactId>multi-module-caching</artifactId>
@ -25,6 +25,7 @@
</dependencyManagement> </dependencyManagement>
<properties> <properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version> <java.version>1.8</java.version>
<guava.version>31.1-jre</guava.version> <guava.version>31.1-jre</guava.version>
</properties> </properties>

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" <project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>com.baeldung</groupId> <groupId>com.baeldung</groupId>
<artifactId>single-module-caching</artifactId> <artifactId>single-module-caching</artifactId>
@ -48,6 +48,7 @@
<properties> <properties>
<maven.compiler.source>8</maven.compiler.source> <maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target> <maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<guava.version>31.1-jre</guava.version> <guava.version>31.1-jre</guava.version>
</properties> </properties>

View File

@ -0,0 +1 @@
## Relevant Articles:

View File

@ -0,0 +1,3 @@
FROM alpine:latest
MAINTAINER baeldung.com
RUN apk update && apk add iputils && apk add bash && apk add curl

View File

@ -0,0 +1,7 @@
FROM node:8.16.1-alpine
WORKDIR /app
COPY host_docker_internal/package.json /app
COPY host_docker_internal/index.js /app
RUN npm install
CMD node index.js
EXPOSE 8080

View File

@ -0,0 +1,20 @@
services:
alpine-app-1:
container_name: alpine-app-1
image: alpine-app-1
build:
context: ..
dockerfile: Dockerfile
tty: true
ports:
- 8081:8081
alpine-app-2:
container_name: alpine-app-2
image: alpine-app-2
build:
context: ..
dockerfile: Dockerfile
tty: true
ports:
- 8080:8080

View File

@ -0,0 +1,29 @@
services:
alpine-app-1:
container_name: alpine-app-1
extra_hosts: # for linux hosts since version 20.10
- host.docker.internal:host-gateway
build:
context: ..
dockerfile: Dockerfile
image: alpine-app-1
tty: true
networks:
- first-network
node-app:
container_name: node-app
build:
context: ..
dockerfile: Dockerfile.node
image: node-app
ports:
- 8080:8080
networks:
- second-network
networks:
first-network:
driver: bridge
second-network:
driver: bridge

View File

@ -0,0 +1,10 @@
var express = require('express')
var app = express()
app.get('/', function (req, res) {
res.send('Hello World!')
})
app.listen(8080, function () {
console.log('app listening on port 8080!')
})

View File

@ -0,0 +1,14 @@
{
"name": "host_docker_internal",
"version": "1.0.0",
"description": "node js app",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "Baeldung",
"license": "ISC",
"dependencies": {
"express": "^4.18.2"
}
}

View File

@ -0,0 +1,34 @@
services:
alpine-app-1:
container_name: alpine-app-1
build:
context: ..
dockerfile: Dockerfile
image: alpine-app-1
tty: true
ports:
- 8080:8080
networks:
network-example:
ipv4_address: 10.5.0.2
alpine-app-2:
container_name: alpine-app-2
build:
context: ..
dockerfile: Dockerfile
image: alpine-app-2
tty: true
ports:
- 8081:8081
networks:
network-example:
ipv4_address: 10.5.0.3
networks:
network-example:
driver: bridge
ipam:
config:
- subnet: 10.5.0.0/16
gateway: 10.5.0.1

View File

@ -0,0 +1,36 @@
services:
alpine-app-1:
container_name: alpine-app-1
build:
context: ..
dockerfile: Dockerfile
image: alpine-app-1
tty: true
ports:
- 8080:8080
networks:
network-example:
ipv4_address: 192.168.2.2
alpine-app-2:
container_name: alpine-app-2
build:
context: ..
dockerfile: Dockerfile
image: alpine-app-2
tty: true
ports:
- 8081:8081
networks:
network-example:
ipv4_address: 192.168.2.3
networks:
network-example:
driver: macvlan
driver_opts:
parent: enp0s3
ipam:
config:
- subnet: 192.168.2.0/24
gateway: 192.168.2.1

View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>docker-compose-2</artifactId>
<description>Demo project for Spring Boot and Docker - Module docker-compose-2</description>
<parent>
<groupId>com.baeldung</groupId>
<artifactId>parent-boot-2</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../../parent-boot-2</relativePath>
</parent>
</project>

View File

@ -18,6 +18,7 @@
<modules> <modules>
<module>docker-caching</module> <module>docker-caching</module>
<module>docker-compose</module> <module>docker-compose</module>
<module>docker-compose-2</module>
<module>docker-containers</module> <module>docker-containers</module>
<module>docker-images</module> <module>docker-images</module>
<module>docker-spring-boot</module> <module>docker-spring-boot</module>

View File

@ -1,129 +1,171 @@
package com.baeldung.httpclient; package com.baeldung.httpclient;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.assertThat; import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.Mockito.when;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import java.io.IOException; import java.io.IOException;
import java.util.Timer; import java.util.Timer;
import java.util.TimerTask; import java.util.TimerTask;
import java.util.concurrent.TimeUnit;
import org.apache.http.HttpResponse; import org.apache.hc.client5.http.ConnectTimeoutException;
import org.apache.http.client.config.RequestConfig; import org.apache.hc.client5.http.classic.methods.HttpGet;
import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.hc.client5.http.config.ConnectionConfig;
import org.apache.http.client.methods.HttpGet; import org.apache.hc.client5.http.config.RequestConfig;
import org.apache.http.client.params.ClientPNames; import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.http.config.SocketConfig; import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
import org.apache.http.conn.ConnectTimeoutException; import org.apache.hc.client5.http.impl.classic.HttpClientBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.params.CoreConnectionPNames;
import org.apache.http.params.HttpParams;
import org.junit.After;
import org.junit.Ignore;
import org.junit.Test;
public class HttpClientTimeoutLiveTest { import org.apache.hc.client5.http.impl.io.BasicHttpClientConnectionManager;
private CloseableHttpResponse response; import org.apache.hc.core5.http.HttpStatus;
import org.apache.hc.core5.http.io.SocketConfig;
import org.apache.hc.core5.util.Timeout;
@After
public final void after() throws IllegalStateException, IOException {
ResponseUtil.closeResponse(response);
}
// tests import com.baeldung.handler.CustomHttpClientResponseHandler;
@Test
public final void givenUsingOldApi_whenSettingTimeoutViaParameter_thenCorrect() throws IOException { class HttpClientTimeoutLiveTest {
DefaultHttpClient httpClient = new DefaultHttpClient();
int timeout = 5; // seconds
HttpParams httpParams = httpClient.getParams();
httpParams.setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, timeout * 1000);
httpParams.setParameter(CoreConnectionPNames.SO_TIMEOUT, timeout * 1000);
httpParams.setParameter(ClientPNames.CONN_MANAGER_TIMEOUT, new Long(timeout * 1000));
final HttpGet request = new HttpGet("http://www.github.com");
HttpResponse execute = httpClient.execute(request);
assertThat(execute.getStatusLine().getStatusCode(), equalTo(200));
}
@Test @Test
public final void givenUsingNewApi_whenSettingTimeoutViaRequestConfig_thenCorrect() throws IOException { void givenUsingNewApi_whenSettingTimeoutViaHighLevelApi_thenCorrect() throws IOException {
final int timeout = 2;
final RequestConfig config = RequestConfig.custom().setConnectTimeout(timeout * 1000).setConnectionRequestTimeout(timeout * 1000).setSocketTimeout(timeout * 1000).build();
final CloseableHttpClient client = HttpClientBuilder.create().setDefaultRequestConfig(config).build();
final HttpGet request = new HttpGet("http://www.github.com");
response = client.execute(request);
assertThat(response.getStatusLine().getStatusCode(), equalTo(200));
}
@Test
public final void givenUsingNewApi_whenSettingTimeoutViaSocketConfig_thenCorrect() throws IOException {
final int timeout = 2; final int timeout = 2;
final SocketConfig config = SocketConfig.custom().setSoTimeout(timeout * 1000).build(); ConnectionConfig connConfig = ConnectionConfig.custom()
final CloseableHttpClient client = HttpClientBuilder.create().setDefaultSocketConfig(config).build(); .setConnectTimeout(timeout, TimeUnit.MILLISECONDS)
.setSocketTimeout(timeout, TimeUnit.MILLISECONDS)
.build();
RequestConfig requestConfig = RequestConfig.custom()
.setConnectionRequestTimeout(Timeout.ofMilliseconds(2000L))
.build();
BasicHttpClientConnectionManager cm = new BasicHttpClientConnectionManager();
cm.setConnectionConfig(connConfig);
final HttpGet request = new HttpGet("http://www.github.com"); final HttpGet request = new HttpGet("http://www.github.com");
response = client.execute(request); try (CloseableHttpClient client = HttpClientBuilder.create()
.setDefaultRequestConfig(requestConfig)
.setConnectionManager(cm)
.build();
assertThat(response.getStatusLine().getStatusCode(), equalTo(200)); CloseableHttpResponse response = (CloseableHttpResponse) client
.execute(request, new CustomHttpClientResponseHandler())) {
final int statusCode = response.getCode();
assertThat(statusCode, equalTo(HttpStatus.SC_OK));
}
} }
@Test @Test
public final void givenUsingNewApi_whenSettingTimeoutViaHighLevelApi_thenCorrect() throws IOException { void givenUsingNewApi_whenSettingTimeoutViaSocketConfig_thenCorrect() throws IOException {
final int timeout = 5; final int timeout = 2000;
final SocketConfig config = SocketConfig.custom().setSoTimeout(timeout, TimeUnit.MILLISECONDS).build();
final RequestConfig config = RequestConfig.custom().setConnectTimeout(timeout * 1000).setConnectionRequestTimeout(timeout * 1000).setSocketTimeout(timeout * 1000).build(); BasicHttpClientConnectionManager cm = new BasicHttpClientConnectionManager();
final CloseableHttpClient client = HttpClientBuilder.create().setDefaultRequestConfig(config).build(); cm.setSocketConfig(config);
final HttpGet request = new HttpGet("http://www.github.com"); final HttpGet request = new HttpGet("http://www.github.com");
response = client.execute(request); try (CloseableHttpClient client = HttpClientBuilder.create()
.setConnectionManager(cm)
.build();
assertThat(response.getStatusLine().getStatusCode(), equalTo(200)); CloseableHttpResponse response = (CloseableHttpResponse) client
.execute(request, new CustomHttpClientResponseHandler())) {
final int statusCode = response.getCode();
assertThat(statusCode, equalTo(HttpStatus.SC_OK));
}
} }
/** /**
* This simulates a timeout against a domain with multiple routes/IPs to it (not a single raw IP) * This simulates a timeout against a domain with multiple routes/IPs to it (not a single raw IP)
*/ */
@Test(expected = ConnectTimeoutException.class) @Disabled
@Ignore void givenTimeoutIsConfigured_whenTimingOut_thenTimeoutException() throws IOException {
public final void givenTimeoutIsConfigured_whenTimingOut_thenTimeoutException() throws IOException {
final int timeout = 3; final int timeout = 3;
final RequestConfig config = RequestConfig.custom().setConnectTimeout(timeout * 1000).setConnectionRequestTimeout(timeout * 1000).setSocketTimeout(timeout * 1000).build(); ConnectionConfig connConfig = ConnectionConfig.custom()
final CloseableHttpClient client = HttpClientBuilder.create().setDefaultRequestConfig(config).build(); .setConnectTimeout(timeout, TimeUnit.MILLISECONDS)
.setSocketTimeout(timeout, TimeUnit.MILLISECONDS)
.build();
RequestConfig requestConfig = RequestConfig.custom()
.setConnectionRequestTimeout(Timeout.ofMilliseconds(3000L))
.build();
BasicHttpClientConnectionManager cm = new BasicHttpClientConnectionManager();
cm.setConnectionConfig(connConfig);
final HttpGet request = new HttpGet("http://www.google.com:81"); final HttpGet request = new HttpGet("http://www.google.com:81");
client.execute(request);
assertThrows(ConnectTimeoutException.class, () -> {
try (CloseableHttpClient client = HttpClientBuilder.create()
.setDefaultRequestConfig(requestConfig)
.setConnectionManager(cm)
.build();
CloseableHttpResponse response = (CloseableHttpResponse) client
.execute(request, new CustomHttpClientResponseHandler())) {
final int statusCode = response.getCode();
assertThat(statusCode, equalTo(HttpStatus.SC_OK));
}
});
} }
@Test @Test
public void whenSecuredRestApiIsConsumed_then200OK() throws IOException { void whenSecuredRestApiIsConsumed_then200OK() throws IOException {
CloseableHttpClient httpClient = HttpClientBuilder.create().build(); int timeout = 20000; // milliseconds
ConnectionConfig connConfig = ConnectionConfig.custom()
.setConnectTimeout(timeout, TimeUnit.MILLISECONDS)
.setSocketTimeout(timeout, TimeUnit.MILLISECONDS)
.build();
RequestConfig requestConfig = RequestConfig.custom()
.setConnectionRequestTimeout(Timeout.ofMilliseconds(20000L))
.build();
int timeout = 20; // seconds
RequestConfig requestConfig = RequestConfig.custom().setConnectionRequestTimeout(timeout * 1000)
.setConnectTimeout(timeout * 1000).setSocketTimeout(timeout * 1000).build();
HttpGet getMethod = new HttpGet("http://localhost:8082/httpclient-simple/api/bars/1"); HttpGet getMethod = new HttpGet("http://localhost:8082/httpclient-simple/api/bars/1");
getMethod.setConfig(requestConfig); getMethod.setConfig(requestConfig);
int hardTimeout = 5; // seconds
BasicHttpClientConnectionManager cm = new BasicHttpClientConnectionManager();
cm.setConnectionConfig(connConfig);
int hardTimeout = 5000; // milliseconds
TimerTask task = new TimerTask() { TimerTask task = new TimerTask() {
@Override @Override
public void run() { public void run() {
getMethod.abort(); getMethod.abort();
} }
}; };
new Timer(true).schedule(task, hardTimeout * 1000); new Timer(true).schedule(task, hardTimeout);
try (CloseableHttpClient client = HttpClientBuilder.create()
.setDefaultRequestConfig(requestConfig)
.setConnectionManager(cm)
.build();
CloseableHttpResponse response = (CloseableHttpResponse) client
.execute(getMethod, new CustomHttpClientResponseHandler())) {
final int statusCode = response.getCode();
System.out.println("HTTP Status of response: " + statusCode);
assertThat(statusCode, equalTo(HttpStatus.SC_OK));
}
HttpResponse response = httpClient.execute(getMethod);
System.out.println("HTTP Status of response: " + response.getStatusLine().getStatusCode());
} }
} }

View File

@ -0,0 +1,116 @@
package com.baeldung.httpclient;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
import static org.junit.jupiter.api.Assertions.assertThrows;
import java.io.IOException;
import java.util.Timer;
import java.util.TimerTask;
import org.apache.http.HttpResponse;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.config.SocketConfig;
import org.apache.http.conn.ConnectTimeoutException;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
class HttpClientTimeoutV4LiveTest {
private CloseableHttpResponse response;
@AfterEach
public final void after() throws IllegalStateException, IOException {
ResponseUtil.closeResponse(response);
}
@Test
void givenUsingNewApi_whenSettingTimeoutViaRequestConfig_thenCorrect() throws IOException {
final int timeout = 2;
final RequestConfig config = RequestConfig.custom().setConnectTimeout(timeout * 1000).setConnectionRequestTimeout(timeout * 1000).setSocketTimeout(timeout * 1000).build();
final CloseableHttpClient client = HttpClientBuilder.create().setDefaultRequestConfig(config).build();
final HttpGet request = new HttpGet("http://www.github.com");
response = client.execute(request);
assertThat(response.getStatusLine().getStatusCode(), equalTo(200));
}
@Test
void givenUsingNewApi_whenSettingTimeoutViaSocketConfig_thenCorrect() throws IOException {
final int timeout = 2;
final SocketConfig config = SocketConfig.custom().setSoTimeout(timeout * 1000).build();
final CloseableHttpClient client = HttpClientBuilder.create().setDefaultSocketConfig(config).build();
final HttpGet request = new HttpGet("http://www.github.com");
response = client.execute(request);
assertThat(response.getStatusLine().getStatusCode(), equalTo(200));
}
@Test
void givenUsingNewApi_whenSettingTimeoutViaHighLevelApi_thenCorrect() throws IOException {
final int timeout = 5;
final RequestConfig config = RequestConfig.custom().setConnectTimeout(timeout * 1000).setConnectionRequestTimeout(timeout * 1000).setSocketTimeout(timeout * 1000).build();
final CloseableHttpClient client = HttpClientBuilder.create().setDefaultRequestConfig(config).build();
final HttpGet request = new HttpGet("http://www.github.com");
response = client.execute(request);
assertThat(response.getStatusLine().getStatusCode(), equalTo(200));
}
/**
* This simulates a timeout against a domain with multiple routes/IPs to it (not a single raw IP)
*/
@Test
@Disabled
public final void givenTimeoutIsConfigured_whenTimingOut_thenTimeoutException() throws IOException {
final int timeout = 3;
final RequestConfig config = RequestConfig.custom().setConnectTimeout(timeout * 1000).setConnectionRequestTimeout(timeout * 1000).setSocketTimeout(timeout * 1000).build();
final CloseableHttpClient client = HttpClientBuilder.create().setDefaultRequestConfig(config).build();
final HttpGet request = new HttpGet("http://www.google.com:81");
assertThrows(ConnectTimeoutException.class, () -> {
client.execute(request);
});
}
@Test
void whenSecuredRestApiIsConsumed_then200OK() throws IOException {
CloseableHttpClient httpClient = HttpClientBuilder.create().build();
int timeout = 20; // seconds
RequestConfig requestConfig = RequestConfig.custom().setConnectionRequestTimeout(timeout * 1000)
.setConnectTimeout(timeout * 1000).setSocketTimeout(timeout * 1000).build();
HttpGet getMethod = new HttpGet("http://localhost:8082/httpclient-simple/api/bars/1");
getMethod.setConfig(requestConfig);
int hardTimeout = 5; // seconds
TimerTask task = new TimerTask() {
@Override
public void run() {
getMethod.abort();
}
};
new Timer(true).schedule(task, hardTimeout * 1000);
HttpResponse response = httpClient.execute(getMethod);
System.out.println("HTTP Status of response: " + response.getStatusLine().getStatusCode());
}
}

View File

@ -65,14 +65,14 @@
</exclusions> </exclusions>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.sun.mail</groupId> <groupId>org.eclipse.angus</groupId>
<artifactId>javax.mail</artifactId> <artifactId>angus-mail</artifactId>
<version>${javax.mail.version}</version> <version>${angus.mail.version}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>javax.activation</groupId> <groupId>org.eclipse.angus</groupId>
<artifactId>javax.activation-api</artifactId> <artifactId>angus-activation</artifactId>
<version>${javax.activation.version}</version> <version>${angus.activation.version}</version>
<scope>runtime</scope> <scope>runtime</scope>
</dependency> </dependency>
</dependencies> </dependencies>
@ -116,8 +116,8 @@
<json.version>20180130</json.version> <json.version>20180130</json.version>
<logback.contrib.version>0.1.5</logback.contrib.version> <logback.contrib.version>0.1.5</logback.contrib.version>
<docx4j.version>3.3.5</docx4j.version> <docx4j.version>3.3.5</docx4j.version>
<javax.mail.version>1.6.2</javax.mail.version> <angus.mail.version>2.0.1</angus.mail.version>
<javax.activation.version>1.2.0</javax.activation.version> <angus.activation.version>2.0.0</angus.activation.version>
<logback.version>1.3.5</logback.version> <logback.version>1.3.5</logback.version>
<slf4j.version>2.0.4</slf4j.version> <slf4j.version>2.0.4</slf4j.version>
</properties> </properties>

View File

@ -0,0 +1,2 @@
## Relevant Articles
- [Introduction to ScyllaDB with Java](https://www.baeldung.com/java-scylladb)

View File

@ -51,6 +51,7 @@
<module>spring-boot-libraries</module> <module>spring-boot-libraries</module>
<module>spring-boot-libraries-2</module> <module>spring-boot-libraries-2</module>
<module>spring-boot-process-automation</module> <module>spring-boot-process-automation</module>
<module>spring-boot-logging-logback</module>
<module>spring-boot-logging-log4j2</module> <module>spring-boot-logging-log4j2</module>
<module>spring-boot-mvc</module> <module>spring-boot-mvc</module>
<module>spring-boot-mvc-2</module> <module>spring-boot-mvc-2</module>

View File

@ -18,10 +18,6 @@
</parent> </parent>
<dependencies> <dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-resource-server</artifactId> <artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
@ -81,7 +77,7 @@
<plugin> <plugin>
<groupId>org.codehaus.mojo</groupId> <groupId>org.codehaus.mojo</groupId>
<artifactId>jaxb2-maven-plugin</artifactId> <artifactId>jaxb2-maven-plugin</artifactId>
<version>2.3.1</version> <version>2.5.0</version>
<executions> <executions>
<execution> <execution>
<id>xjc</id> <id>xjc</id>
@ -100,5 +96,9 @@
</plugin> </plugin>
</plugins> </plugins>
</build> </build>
<properties>
<start-class>com.baeldung.keycloak.SpringBoot</start-class>
</properties>
</project> </project>

View File

@ -30,7 +30,7 @@ class SecurityConfig {
@Bean @Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.authorizeRequests() http.authorizeRequests()
.antMatchers("/customers*", "/users*") .antMatchers("/customers*")
.hasRole("USER") .hasRole("USER")
.anyRequest() .anyRequest()
.permitAll(); .permitAll();

View File

@ -55,6 +55,10 @@
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId> <artifactId>spring-boot-starter-log4j2</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-spring-boot</artifactId>
</dependency>
<dependency> <dependency>
<groupId>org.projectlombok</groupId> <groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId> <artifactId>lombok</artifactId>

View File

@ -0,0 +1,25 @@
package com.baeldung.extensions;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.PropertySource;
@SpringBootApplication
@PropertySource("classpath:application-log4j2-extensions.properties")
public class SpringBootLog4j2ExtensionsApplication {
private static final Logger logger = LogManager.getLogger(SpringBootLog4j2ExtensionsApplication.class);
public static void main(String[] args) {
SpringApplication.run(SpringBootLog4j2ExtensionsApplication.class, args);
logger.trace("Trace log message");
logger.debug("Debug log message");
logger.info("Info log message");
logger.error("Error log message");
logger.warn("Warn log message");
logger.fatal("Fatal log message");
}
}

View File

@ -0,0 +1,2 @@
logging.config=classpath:log4j2-spring.xml
spring.application.name=log4j2-extension

View File

@ -7,6 +7,11 @@
pattern="%style{%d{ISO8601}}{black} %highlight{%-5level }[%style{%t}{bright,blue}] %style{%C{1.}}{bright,yellow}: %msg%n%throwable" /> pattern="%style{%d{ISO8601}}{black} %highlight{%-5level }[%style{%t}{bright,blue}] %style{%C{1.}}{bright,yellow}: %msg%n%throwable" />
</Console> </Console>
<Console name="Console-Extensions" target="SYSTEM_OUT">
<PatternLayout
pattern="%d %p %c{1.} [%t] ${spring:spring.application.name} %m%n" />
</Console>
<RollingFile name="RollingFile" <RollingFile name="RollingFile"
fileName="./logs/spring-boot-logger-log4j2.log" fileName="./logs/spring-boot-logger-log4j2.log"
filePattern="./logs/$${date:yyyy-MM}/spring-boot-logger-log4j2-%d{-dd-MMMM-yyyy}-%i.log.gz"> filePattern="./logs/$${date:yyyy-MM}/spring-boot-logger-log4j2-%d{-dd-MMMM-yyyy}-%i.log.gz">
@ -37,7 +42,20 @@
</Root> </Root>
<!-- LOG "com.baeldung*" at TRACE level --> <!-- LOG "com.baeldung*" at TRACE level -->
<Logger name="com.baeldung" level="trace"></Logger> <SpringProfile name="!development, !production">
<Logger name="com.baeldung" level="trace"></Logger>
</SpringProfile>
<SpringProfile name="development">
<Logger name="com.baeldung.extensions" level="debug"></Logger>
</SpringProfile>
<SpringProfile name="production">
<Logger name="com.baeldung.extensions" level="error">
<AppenderRef ref="Console-Extensions" />
</Logger>
</SpringProfile>
</Loggers> </Loggers>
</Configuration> </Configuration>

View File

@ -0,0 +1,29 @@
/target/
!.mvn/wrapper/maven-wrapper.jar
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
### NetBeans ###
/nbproject/private/
/build/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
/logs/
/bin/
/mvnw
/mvnw.cmd

View File

@ -0,0 +1,6 @@
## Spring Boot Logging with Logback
This module contains articles about logging in Spring Boot projects with Logback.
### Relevant Articles:

View File

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>spring-boot-logging-logback</artifactId>
<name>spring-boot-logging-logback</name>
<packaging>jar</packaging>
<description>Demo project for Spring Boot Logging with Logback</description>
<parent>
<groupId>com.baeldung.spring-boot-modules</groupId>
<artifactId>spring-boot-modules</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,22 @@
package com.baeldung.extensions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SpringBootLogbackExtensionsApplication {
private static final Logger logger = LoggerFactory.getLogger(SpringBootLogbackExtensionsApplication.class);
public static void main(String[] args) {
SpringApplication.run(SpringBootLogbackExtensionsApplication.class, args);
logger.debug("Debug log message");
logger.info("Info log message");
logger.error("Error log message");
logger.warn("Warn log message");
logger.trace("Trace log message");
}
}

View File

@ -0,0 +1 @@
spring.application.name=logback-extension

View File

@ -0,0 +1,33 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<property name="LOGS" value="./logs" />
<springProperty scope="context" name="application.name" source="spring.application.name" />
<springProfile name="development">
<appender name="Console" class="ch.qos.logback.core.ConsoleAppender">
<layout class="ch.qos.logback.classic.PatternLayout">
<Pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</Pattern>
</layout>
</appender>
<root level="info">
<appender-ref ref="Console" />
</root>
</springProfile>
<springProfile name="production">
<appender name="RollingFile" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${LOGS}/${application.name}.log</file>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<Pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</Pattern>
</encoder>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${LOGS}/archived/${application.name}-%d{yyyy-MM-dd}.log</fileNamePattern>
</rollingPolicy>
</appender>
<root level="info">
<appender-ref ref="RollingFile" />
</root>
</springProfile>
</configuration>

View File

@ -4,3 +4,4 @@ This module contains articles about Spring Web MVC in Spring Boot projects.
### Relevant Articles: ### Relevant Articles:
- [Enable and Disable Endpoints at Runtime With Spring Boot](https://www.baeldung.com/spring-boot-enable-disable-endpoints-at-runtime) - [Enable and Disable Endpoints at Runtime With Spring Boot](https://www.baeldung.com/spring-boot-enable-disable-endpoints-at-runtime)
- [Extracting a Custom Header From the Request](https://www.baeldung.com/spring-extract-custom-header-request)

View File

@ -1,19 +1,18 @@
package com.baeldung.web.log.app; package com.baeldung.web.log.app;
import javax.servlet.ServletRegistration;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.actuate.autoconfigure.security.servlet.ManagementWebSecurityAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration;
import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.PropertySource; import org.springframework.context.annotation.PropertySource;
import com.baeldung.web.log.config.CustomeRequestLoggingFilter;
@EnableAutoConfiguration
@ComponentScan("com.baeldung.web.log") @ComponentScan("com.baeldung.web.log")
@PropertySource("application-log.properties") @PropertySource("application-log.properties")
@SpringBootApplication @SpringBootApplication(exclude = {
SecurityAutoConfiguration.class,
ManagementWebSecurityAutoConfiguration.class
})
public class Application { public class Application {
public static void main(final String[] args) { public static void main(final String[] args) {

View File

@ -0,0 +1,30 @@
package com.baeldung.web.log.app;
import org.springframework.util.StreamUtils;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.*;
public class CachedHttpServletRequest extends HttpServletRequestWrapper {
private byte[] cachedPayload;
public CachedHttpServletRequest(HttpServletRequest request) throws IOException {
super(request);
InputStream requestInputStream = request.getInputStream();
this.cachedPayload = StreamUtils.copyToByteArray(requestInputStream);
}
@Override
public ServletInputStream getInputStream() {
return new CachedServletInputStream(this.cachedPayload);
}
@Override
public BufferedReader getReader() {
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(this.cachedPayload);
return new BufferedReader(new InputStreamReader(byteArrayInputStream));
}
}

View File

@ -0,0 +1,45 @@
package com.baeldung.web.log.app;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
public class CachedServletInputStream extends ServletInputStream {
private final static Logger LOGGER = LoggerFactory.getLogger(CachedServletInputStream.class);
private InputStream cachedInputStream;
public CachedServletInputStream(byte[] cachedBody) {
this.cachedInputStream = new ByteArrayInputStream(cachedBody);
}
@Override
public boolean isFinished() {
try {
return cachedInputStream.available() == 0;
} catch (IOException exp) {
LOGGER.error(exp.getMessage());
}
return false;
}
@Override
public boolean isReady() {
return true;
}
@Override
public void setReadListener(ReadListener readListener) {
throw new UnsupportedOperationException();
}
@Override
public int read() throws IOException {
return cachedInputStream.read();
}
}

View File

@ -0,0 +1,33 @@
package com.baeldung.web.log.app;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
@Order(value = Ordered.HIGHEST_PRECEDENCE)
@Component
@WebFilter(filterName = "RequestCachingFilter", urlPatterns = "/*")
public class RequestCachingFilter extends OncePerRequestFilter {
private final static Logger LOGGER = LoggerFactory.getLogger(RequestCachingFilter.class);
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
CachedHttpServletRequest cachedHttpServletRequest = new CachedHttpServletRequest(request);
LOGGER.info("REQUEST DATA: " + IOUtils.toString(cachedHttpServletRequest.getInputStream(), StandardCharsets.UTF_8));
filterChain.doFilter(cachedHttpServletRequest, response);
}
}

View File

@ -1,44 +0,0 @@
package com.baeldung.web.log.app;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import org.springframework.web.util.ContentCachingRequestWrapper;
import com.baeldung.web.log.util.RequestLoggingUtil;
@Component
public class TaxiFareRequestInterceptor extends HandlerInterceptorAdapter {
private final static Logger LOGGER = LoggerFactory.getLogger(TaxiFareRequestInterceptor.class);
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String postData;
HttpServletRequest requestCacheWrapperObject = null;
try {
// Uncomment to produce the stream closed issue
// postData = RequestLoggingUtil.getStringFromInputStream(request.getInputStream());
// To overcome request stream closed issue
requestCacheWrapperObject = new ContentCachingRequestWrapper(request);
requestCacheWrapperObject.getParameterMap();
} catch (Exception exception) {
exception.printStackTrace();
} finally {
postData = RequestLoggingUtil.readPayload(requestCacheWrapperObject);
LOGGER.info("REQUEST DATA: " + postData);
}
return true;
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
LOGGER.info("RESPONSE: " + response.getStatus());
}
}

View File

@ -1,27 +0,0 @@
package com.baeldung.web.log.config;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;
import org.springframework.web.context.ContextLoaderListener;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;
import org.springframework.web.WebApplicationInitializer;
public class CustomWebAppInitializer implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext container) throws ServletException {
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
context.setConfigLocation("com.baeldung.web.log");
container.addListener(new ContextLoaderListener(context));
ServletRegistration.Dynamic dispatcher = container.addServlet("dispatcher", new DispatcherServlet(context));
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/");
container.addFilter("customRequestLoggingFilter", CustomeRequestLoggingFilter.class).addMappingForServletNames(null, false, "dispatcher");
}
}

View File

@ -1,12 +0,0 @@
package com.baeldung.web.log.config;
import org.springframework.web.filter.CommonsRequestLoggingFilter;
public class CustomeRequestLoggingFilter extends CommonsRequestLoggingFilter {
public CustomeRequestLoggingFilter() {
super.setIncludeQueryString(true);
super.setIncludePayload(true);
super.setMaxPayloadLength(10000);
}
}

View File

@ -14,7 +14,7 @@ public class RequestLoggingFilterConfig {
filter.setIncludePayload(true); filter.setIncludePayload(true);
filter.setMaxPayloadLength(10000); filter.setMaxPayloadLength(10000);
filter.setIncludeHeaders(false); filter.setIncludeHeaders(false);
filter.setAfterMessagePrefix("REQUEST DATA : "); filter.setAfterMessagePrefix("REQUEST DATA: ");
return filter; return filter;
} }
} }

View File

@ -1,19 +0,0 @@
package com.baeldung.web.log.config;
import com.baeldung.web.log.app.TaxiFareRequestInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class TaxiFareMVCConfig implements WebMvcConfigurer {
@Autowired
private TaxiFareRequestInterceptor taxiFareRequestInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(taxiFareRequestInterceptor).addPathPatterns("/taxifare/*/");
}
}

View File

@ -1,38 +0,0 @@
package com.baeldung.web.log.util;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.io.IOUtils;
import org.springframework.web.util.ContentCachingRequestWrapper;
import org.springframework.web.util.WebUtils;
public class RequestLoggingUtil {
public static String getStringFromInputStream(InputStream is) {
StringWriter writer = new StringWriter();
String encoding = "UTF-8";
try {
IOUtils.copy(is, writer, encoding);
} catch (IOException e) {
e.printStackTrace();
}
return writer.toString();
}
public static String readPayload(final HttpServletRequest request) throws IOException {
String payloadData = null;
ContentCachingRequestWrapper contentCachingRequestWrapper = WebUtils.getNativeRequest(request, ContentCachingRequestWrapper.class);
if (null != contentCachingRequestWrapper) {
byte[] buf = contentCachingRequestWrapper.getContentAsByteArray();
if (buf.length > 0) {
payloadData = new String(buf, 0, buf.length, contentCachingRequestWrapper.getCharacterEncoding());
}
}
return payloadData;
}
}

View File

@ -7,6 +7,10 @@
</encoder> </encoder>
</appender> </appender>
<logger name="org.springframework.web.filter.CommonsRequestLoggingFilter">
<level value="DEBUG" />
</logger>
<root level="INFO"> <root level="INFO">
<appender-ref ref="STDOUT" /> <appender-ref ref="STDOUT" />
</root> </root>

View File

@ -1,23 +1,19 @@
package com.baeldung.web.controller; package com.baeldung.web.controller;
import static org.hamcrest.MatcherAssert.assertThat; import com.baeldung.web.log.app.Application;
import static org.hamcrest.Matchers.equalTo; import com.baeldung.web.log.data.TaxiRide;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.client.TestRestTemplate; import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.context.annotation.Configuration; import org.springframework.boot.test.web.server.LocalServerPort;
import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import com.baeldung.web.log.app.Application; import static org.hamcrest.MatcherAssert.assertThat;
import com.baeldung.web.log.data.TaxiRide; import static org.hamcrest.Matchers.equalTo;
@RunWith(SpringRunner.class) @RunWith(SpringRunner.class)
@SpringBootTest(classes = { Application.class, TaxiFareControllerIntegrationTest.SecurityConfig.class}, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) @SpringBootTest(classes = { Application.class}, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class TaxiFareControllerIntegrationTest { public class TaxiFareControllerIntegrationTest {
@LocalServerPort @LocalServerPort
@ -25,8 +21,6 @@ public class TaxiFareControllerIntegrationTest {
@Test @Test
public void givenRequest_whenFetchTaxiFareRateCard_thanOK() { public void givenRequest_whenFetchTaxiFareRateCard_thanOK() {
System.out.println(port);
String URL = "http://localhost:" + port + "/spring-rest"; String URL = "http://localhost:" + port + "/spring-rest";
TestRestTemplate testRestTemplate = new TestRestTemplate(); TestRestTemplate testRestTemplate = new TestRestTemplate();
TaxiRide taxiRide = new TaxiRide(true, 10l); TaxiRide taxiRide = new TaxiRide(true, 10l);
@ -37,16 +31,4 @@ public class TaxiFareControllerIntegrationTest {
assertThat(fare, equalTo("200")); assertThat(fare, equalTo("200"));
} }
@Configuration
static class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
System.out.println("security being set");
http
.authorizeRequests()
.anyRequest().permitAll()
.and()
.csrf().disable();
}
}
} }

View File

@ -10,27 +10,39 @@
<url>http://www.baeldung.com</url> <url>http://www.baeldung.com</url>
<parent> <parent>
<groupId>com.baeldung</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>parent-modules</artifactId> <artifactId>spring-boot-starter-parent</artifactId>
<version>1.0.0-SNAPSHOT</version> <version>3.0.1</version>
<relativePath/> <!-- lookup parent from repository -->
</parent> </parent>
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId> <artifactId>spring-boot-starter-web</artifactId>
<version>${spring.boot.version}</version> </dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.mock-server</groupId>
<artifactId>mockserver-netty</artifactId>
<version>${mockserver.version}</version>
</dependency>
<dependency>
<groupId>org.mock-server</groupId>
<artifactId>mockserver-client-java</artifactId>
<version>${mockserver.version}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId> <artifactId>spring-boot-starter-test</artifactId>
<version>${spring.boot.version}</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.junit.jupiter</groupId> <groupId>io.projectreactor</groupId>
<artifactId>junit-jupiter-api</artifactId> <artifactId>reactor-test</artifactId>
<version>${junit-jupiter.version}</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
</dependencies> </dependencies>
@ -76,13 +88,23 @@
</plugin> </plugin>
</plugins> </plugins>
</pluginManagement> </pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>17</source>
<target>17</target>
</configuration>
</plugin>
</plugins>
</build> </build>
<properties> <properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>11</maven.compiler.source> <maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target> <maven.compiler.target>17</maven.compiler.target>
<spring.boot.version>2.7.5</spring.boot.version> <mockserver.version>5.14.0</mockserver.version>
</properties> </properties>
</project> </project>

View File

@ -0,0 +1,3 @@
package com.baeldung.httpinterface;
public record Book(long id, String title, String author, int year) {}

View File

@ -0,0 +1,23 @@
package com.baeldung.httpinterface;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.web.reactive.function.client.support.WebClientAdapter;
import org.springframework.web.service.invoker.HttpServiceProxyFactory;
@Component
public class BooksClient {
private final BooksService booksService;
public BooksClient(WebClient webClient) {
HttpServiceProxyFactory httpServiceProxyFactory =
HttpServiceProxyFactory.builder(WebClientAdapter.forClient(webClient))
.build();
booksService = httpServiceProxyFactory.createClient(BooksService.class);
}
public BooksService getBooksService() {
return booksService;
}
}

Some files were not shown because too many files have changed in this diff Show More