Merge branch 'eugenp:master' into master

This commit is contained in:
Ulisses Lima 2022-08-15 22:44:44 -03:00 committed by GitHub
commit 56dae14bff
47 changed files with 582 additions and 173 deletions

5
.gitignore vendored
View File

@ -99,4 +99,7 @@ spring-boot-modules/spring-boot-react/frontend/yarn.lock
spring-boot-modules/spring-boot-properties-3/*.log
# SDKMan
.sdkmanrc
.sdkmanrc
# Localstack
**/.localstack

View File

@ -13,18 +13,32 @@
<version>1.0.0-SNAPSHOT</version>
</parent>
<dependencies>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>${guava.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>
<properties>
<combinatoricslib3.version>3.3.3</combinatoricslib3.version>
<commons-collections4.version>4.4</commons-collections4.version>
</properties>
<dependencies>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>${guava.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.github.dpaukov</groupId>
<artifactId>combinatoricslib3</artifactId>
<version>${combinatoricslib3.version}</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
<version>${commons-collections4.version}</version>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,14 @@
package com.baeldung.algorithms.stringpermutation;
import java.util.List;
import java.util.stream.Collectors;
public class ArrayHelper {
private ArrayHelper() {
}
static List<Character> toCharacterList(final String string) {
return string.chars().mapToObj(s -> ((char) s)).collect(Collectors.toList());
}
}

View File

@ -0,0 +1,20 @@
package com.baeldung.algorithms.stringpermutation;
import java.util.Collection;
import java.util.List;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.iterators.PermutationIterator;
public class StringPermutationsApache {
public Collection<List<Character>> eagerPermutationWithRepetitions(final String string) {
final List<Character> characters = ArrayHelper.toCharacterList(string);
return CollectionUtils.permutations(characters);
}
public PermutationIterator<Character> lazyPermutationWithoutRepetitions(final String string) {
final List<Character> characters = ArrayHelper.toCharacterList(string);
return new PermutationIterator<>(characters);
}
}

View File

@ -0,0 +1,26 @@
package com.baeldung.algorithms.stringpermutation;
import java.util.List;
import java.util.stream.Collectors;
import org.paukov.combinatorics3.Generator;
import org.paukov.combinatorics3.PermutationGenerator.TreatDuplicatesAs;
public class StringPermutationsCombinatoricsLib {
public List<List<Character>> permutationWithoutRepetitions(final String string) {
List<Character> chars = ArrayHelper.toCharacterList(string);
return Generator.permutation(chars)
.simple()
.stream()
.collect(Collectors.toList());
}
public List<List<Character>> permutationWithRepetitions(final String string) {
List<Character> chars = ArrayHelper.toCharacterList(string);
return Generator.permutation(chars)
.simple(TreatDuplicatesAs.IDENTICAL)
.stream()
.collect(Collectors.toList());
}
}

View File

@ -0,0 +1,18 @@
package com.baeldung.algorithms.stringpermutation;
import com.google.common.collect.Collections2;
import java.util.Collection;
import java.util.List;
public class StringPermutationsGuava {
public Collection<List<Character>> permutationWithRepetitions(final String string) {
final List<Character> characters = ArrayHelper.toCharacterList(string);
return Collections2.permutations(characters);
}
public Collection<List<Character>> permutationWithoutRepetitions(final String string) {
final List<Character> characters = ArrayHelper.toCharacterList(string);
return Collections2.orderedPermutations(characters);
}
}

View File

@ -0,0 +1,43 @@
package com.baeldung.algorithms.stringpermutation;
import static org.assertj.core.api.Assertions.assertThat;
import java.util.Collection;
import java.util.List;
import org.apache.commons.collections4.iterators.PermutationIterator;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
class StringPermutationsApacheUnitTest {
@CsvSource({"abc, 6",
"hello, 120",
"aaaaaa, 720"})
@DisplayName("Apache permutation for ")
void testPermutationsWithRepetitions(String string, int numberOfPermutations) {
StringPermutationsApache permutationGenerator = new StringPermutationsApache();
final Collection<List<Character>> permutations = permutationGenerator.eagerPermutationWithRepetitions(string);
final int size = permutations.size();
assertThat(permutations)
.as("\"%s\" should have %d permutation, but had %d", string, numberOfPermutations, size)
.hasSize(numberOfPermutations);
}
@ParameterizedTest
@CsvSource({"abc, 6",
"hello, 120",
"aaaaaa, 720"})
void testPermutationsWithoutRepetitions(String string, int numberOfPermutations) {
StringPermutationsApache permutationGenerator = new StringPermutationsApache();
final PermutationIterator<Character> permutations = permutationGenerator.lazyPermutationWithoutRepetitions(string);
int size = 0;
while (permutations.hasNext()) {
permutations.next();
++size;
}
assertThat(size)
.as("\"%s\" should have %d permutation, but had %d", string, numberOfPermutations, size)
.isEqualTo(numberOfPermutations);
}
}

View File

@ -0,0 +1,36 @@
package com.baeldung.algorithms.stringpermutation;
import static org.assertj.core.api.Assertions.assertThat;
import java.util.List;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
class StringPermutationsCombinatoricsLibUnitTest {
@ParameterizedTest
@CsvSource({"abc, 6",
"hello, 120",
"aaaaaa, 720"})
void testPermutationsWithRepetitions(String string, int numberOfPermutations) {
StringPermutationsCombinatoricsLib permutationGenerator = new StringPermutationsCombinatoricsLib();
final List<List<Character>> permutations = permutationGenerator.permutationWithRepetitions(string);
final int size = permutations.size();
assertThat(permutations)
.as("\"%s\" should have %d permutation, but had %d", string, numberOfPermutations, size)
.hasSize(numberOfPermutations);
}
@ParameterizedTest
@CsvSource({"abc, 6",
"hello, 60",
"aaaaaa, 1"})
void testPermutationsWithoutRepetitions(String string, int numberOfPermutations) {
StringPermutationsCombinatoricsLib permutationGenerator = new StringPermutationsCombinatoricsLib();
final List<List<Character>> permutations = permutationGenerator.permutationWithoutRepetitions(string);
final int size = permutations.size();
assertThat(permutations)
.as("\"%s\" should have %d permutation, but had %d", string, numberOfPermutations, size)
.hasSize(numberOfPermutations);
}
}

View File

@ -0,0 +1,38 @@
package com.baeldung.algorithms.stringpermutation;
import static org.assertj.core.api.Assertions.assertThat;
import java.util.Collection;
import java.util.List;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
class StringPermutationsGuavaUnitTest {
@ParameterizedTest
@CsvSource({"abc, 6",
"hello, 120",
"aaaaaa, 720"})
void testPermutationsWithRepetitions(String string, int numberOfPermutations) {
StringPermutationsGuava permutationGenerator = new StringPermutationsGuava();
final Collection<List<Character>> permutations = permutationGenerator.permutationWithRepetitions(string);
final int size = permutations.size();
assertThat(permutations)
.as("\"%s\" should have %d permutation, but had %d", string, numberOfPermutations, size)
.hasSize(numberOfPermutations);
}
@ParameterizedTest
@CsvSource({"abc, 6",
"hello, 60",
"aaaaaa, 1"})
void testPermutationsWithoutRepetitions(String string, int numberOfPermutations) {
StringPermutationsGuava permutationGenerator = new StringPermutationsGuava();
final Collection<List<Character>> permutations = permutationGenerator.permutationWithoutRepetitions(string);
final int size = permutations.size();
assertThat(permutations)
.as("\"%s\" should have %d permutation, but had %d", string, numberOfPermutations, size)
.hasSize(numberOfPermutations);
}
}

View File

@ -6,4 +6,6 @@ This module contains articles about the Java List collection
- [Working With a List of Lists in Java](https://www.baeldung.com/java-list-of-lists)
- [Reverse an ArrayList in Java](https://www.baeldung.com/java-reverse-arraylist)
- [Sort a List Alphabetically in Java](https://www.baeldung.com/java-sort-list-alphabetically)
- [Arrays.asList() vs Collections.singletonList()](https://www.baeldung.com/java-aslist-vs-singletonlist)
- [Replace Element at a Specific Index in a Java ArrayList](https://www.baeldung.com/java-arraylist-replace-at-index)
- [[<-- Prev]](/core-java-modules/core-java-collections-list-3)

View File

@ -8,4 +8,5 @@
- [Java Map keySet() vs. entrySet() vs. values() Methods](https://www.baeldung.com/java-map-entries-methods)
- [Java IdentityHashMap Class and Its Use Cases](https://www.baeldung.com/java-identityhashmap)
- [How to Invert a Map in Java](https://www.baeldung.com/java-invert-map)
- [Implementing a Map with Multiple Keys in Java](https://www.baeldung.com/java-multiple-keys-map)
- More articles: [[<-- prev]](../core-java-collections-maps-4)

View File

@ -7,3 +7,4 @@
- [Producer-Consumer Problem With Example in Java](https://www.baeldung.com/java-producer-consumer-problem)
- [Acquire a Lock by a Key in Java](https://www.baeldung.com/java-acquire-lock-by-key)
- [Differences Between set() and lazySet() in Java Atomic Variables](https://www.baeldung.com/java-atomic-set-vs-lazyset)
- [Volatile vs. Atomic Variables in Java](https://www.baeldung.com/java-volatile-vs-atomic)

View File

@ -7,4 +7,5 @@ This module contains articles about core java exceptions
- [Java Missing Return Statement](https://www.baeldung.com/java-missing-return-statement)
- [Convert long to int Type in Java](https://www.baeldung.com/java-convert-long-to-int)
- [“Sneaky Throws” in Java](https://www.baeldung.com/java-sneaky-throws)
- [[<-- Prev]](../core-java-exceptions-3)
- [Get the Current Stack Trace in Java](https://www.baeldung.com/java-get-current-stack-trace)
- [[<-- Prev]](../core-java-exceptions-3)

View File

@ -11,3 +11,4 @@ This module contains article about constructors in Java
- [Constructors in Java Abstract Classes](https://www.baeldung.com/java-abstract-classes-constructors)
- [Java Implicit Super Constructor is Undefined Error](https://www.baeldung.com/java-implicit-super-constructor-is-undefined-error)
- [Constructor Specification in Java](https://www.baeldung.com/java-constructor-specification)
- [Static vs. Instance Initializer Block in Java](https://www.baeldung.com/java-static-instance-initializer-blocks)

View File

@ -17,9 +17,9 @@ import static org.junit.Assert.assertTrue;
public class FileDownloadIntegrationTest {
static String FILE_URL = "https://s3.amazonaws.com/baeldung.com/Do+JSON+with+Jackson+by+Baeldung.pdf";
static String FILE_URL = "https://s3.amazonaws.com/baeldung.com/Do+JSON+with+Jackson.pdf?__s=vatuzcrazsqopnn7finb";
static String FILE_NAME = "file.dat";
static String FILE_MD5_HASH = "753197aa27f162faa3e3c2e48ee5eb07";
static String FILE_MD5_HASH = "CE20E17B1E1FBF65A85E74AC00FA1FD8";
@Test
public void givenJavaIO_whenDownloadingFile_thenDownloadShouldBeCorrect() throws NoSuchAlgorithmException, IOException {

View File

@ -1,2 +1,3 @@
### Relevant Articles:
- [Check if a Number Is Odd or Even](https://www.baeldung.com/java-check-number-parity)
- [How to Check Whether an Integer Exists in a Range with Java](https://www.baeldung.com/java-interval-contains-integer)

View File

@ -2,3 +2,4 @@
- [Count Occurrences Using Java groupingBy Collector](https://www.baeldung.com/java-groupingby-count)
- [How to Split a Stream into Multiple Streams](https://www.baeldung.com/java-split-stream)
- [Filter Java Stream to 1 and Only 1 Element](https://www.baeldung.com/java-filter-stream-unique-element)

View File

@ -0,0 +1,29 @@
package com.baeldung.chararraytostring;
import static org.junit.Assert.assertEquals;
import org.junit.Test;
public class IntToStringUnitTest {
@Test
public void whenValidIntIsPassed_thenShouldConvertToString() {
assertEquals("11", Integer.toString(11));
assertEquals("11", Integer.toString(+11));
assertEquals("-11", Integer.toString(-11));
}
@Test
public void whenValidIntIsPassed_thenShouldConvertToValidString() {
assertEquals("11", String.valueOf(11));
assertEquals("11", String.valueOf(+11));
assertEquals("-11", String.valueOf(-11));
}
@Test(expected = NullPointerException.class)
public void whenNullIntegerObjectIsPassed_thenShouldThrowException() {
Integer i = null;
System.out.println(String.valueOf(i)); // it prints "null"
System.out.println(i.toString());
}
}

View File

@ -0,0 +1,31 @@
package com.baeldung.namedformatting;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class NamedFormatter {
private NamedFormatter() {}
public static String format(String template, Map<String, Object> parameters) {
StringBuilder newTemplate = new StringBuilder(template);
List<Object> valueList = new ArrayList<>();
Matcher matcher = Pattern.compile("[$][{](\\w+)}").matcher(template);
while (matcher.find()) {
String key = matcher.group(1);
String paramName = "${" + key + "}";
int index = newTemplate.indexOf(paramName);
if (index != -1) {
newTemplate.replace(index, index + paramName.length(), "%s");
valueList.add(parameters.get(key));
}
}
return String.format(newTemplate.toString(), valueList.toArray());
}
}

View File

@ -0,0 +1,47 @@
package com.baeldung.namedformatting;
import org.apache.commons.text.StrSubstitutor;
import org.junit.jupiter.api.Test;
import java.util.HashMap;
import java.util.Map;
import static org.assertj.core.api.Assertions.assertThat;
class NamedFormatterUnitTest {
private static final String TEMPLATE = "Text: [${text}] Number: [${number}] Text again: [${text}]";
@Test
void givenTemplateWithNamedParam_whenCallingCommonsTextStrSubstitutor_shouldGetExpectedResult() {
Map<String, Object> params = new HashMap<>();
params.put("text", "It's awesome!");
params.put("number", 42);
String result = StrSubstitutor.replace(TEMPLATE, params, "${", "}");
assertThat(result).isEqualTo("Text: [It's awesome!] Number: [42] Text again: [It's awesome!]");
}
@Test
void givenTemplateWithNamedParam_whenCallingCommonsTextStrSubstitutorWithParameterNames_shouldNotWorkAsExpected() {
Map<String, Object> params = new HashMap<>();
params.put("text", "'${number}' is a placeholder.");
params.put("number", 42);
String result = StrSubstitutor.replace(TEMPLATE, params, "${", "}");
assertThat(result).isNotEqualTo("Text: ['${number}' is a placeholder.] Number: [42] Text again: ['${number}' is a placeholder.]");
assertThat(result).isEqualTo("Text: ['42' is a placeholder.] Number: [42] Text again: ['42' is a placeholder.]");
}
@Test
void givenTemplateWithNamedParam_whenCallingNamedFormatter_shouldGetExpectedResult() {
Map<String, Object> params = new HashMap<>();
params.put("text", "It's awesome!");
params.put("number", 42);
String result = NamedFormatter.format(TEMPLATE, params);
assertThat(result).isEqualTo("Text: [It's awesome!] Number: [42] Text again: [It's awesome!]");
params.put("text", "'${number}' is a placeholder.");
result = NamedFormatter.format(TEMPLATE, params);
assertThat(result).isEqualTo("Text: ['${number}' is a placeholder.] Number: [42] Text again: ['${number}' is a placeholder.]");
}
}

View File

@ -0,0 +1,15 @@
services:
mysql-db:
image: mysql:latest
environment:
- MYSQL_ROOT_PASSWORD=password
- MYSQL_ROOT_HOST=localhost
ports:
- '3306:3306'
volumes:
- first-volume-data:/var/lib/mysql
- ./init.sql:/docker-entrypoint-initdb.d/init.sql
volumes:
first-volume-data:
external: true

View File

@ -0,0 +1,9 @@
CREATE DATABASE IF NOT EXISTS test;
use test;
CREATE TABLE IF NOT EXISTS test_table (id int, description varchar(255));
INSERT INTO test_table VALUES (1, 'TEST_1');
INSERT INTO test_table VALUES (2, 'TEST_2');
INSERT INTO test_table VALUES (3, 'TEST_3');

View File

@ -0,0 +1,15 @@
services:
localstack:
privileged: true
image: localstack/localstack:latest
container_name: localstack
ports:
- '4563-4599:4563-4599'
- '8055:8080'
environment:
- SERVICES=s3
- DEBUG=1
- DATA_DIR=/tmp/localstack/data
volumes:
- './.localstack:/var/lib/localstack'
- '/var/run/docker.sock:/var/run/docker.sock'

View File

@ -0,0 +1,15 @@
services:
my_app:
image: web-app:latest
container_name: web-app
ports:
- "8080:8080"
volumes:
- first-volume-data:/container-path-1
- second-volume-data:/container-path-2:ro
volumes:
first-volume-data:
driver: local
second-volume-data:
driver: local

View File

@ -0,0 +1,4 @@
### Relevant Articles:
- [Dockerizing a Java Application](https://www.baeldung.com/java-dockerize-app)

View File

@ -150,9 +150,9 @@
<properties>
<orika.version>1.5.4</orika.version>
<dozer.version>6.5.0</dozer.version>
<mapstruct.version>1.3.1.Final</mapstruct.version>
<modelmapper.version>2.3.8</modelmapper.version>
<dozer.version>6.5.2</dozer.version>
<mapstruct.version>1.5.2.Final</mapstruct.version>
<modelmapper.version>3.1.0</modelmapper.version>
<jmapper.version>1.6.1.CR2</jmapper.version>
<!-- Java source/target to use for compilation. -->
<javac.target>1.8</javac.target>

View File

@ -29,6 +29,11 @@ public class WebClientController {
return bodyString.map(body -> "processed-" + body);
}
@PostMapping("/resource-override")
public Mono<String> postStringResourceOverride(@RequestBody Mono<String> bodyString) {
return bodyString.map(body -> "override-processed-" + body);
}
@PostMapping("/resource-foo")
public Mono<String> postFooResource(@RequestBody Mono<Foo> bodyFoo) {
return bodyFoo.map(foo -> "processedFoo-" + foo.getName());

View File

@ -54,58 +54,44 @@ class WebClientIntegrationTest {
@Test
void givenDifferentWebClientCreationMethods_whenUsed_thenObtainExpectedResponse() {
// WebClient creation
WebClient client1 = WebClient.create();
WebClient client2 = WebClient.create("http://localhost:" + port);
WebClient client3 = WebClient.builder()
.baseUrl("http://localhost:" + port)
.defaultCookie("cookieKey", "cookieValue")
.defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
.defaultUriVariables(Collections.singletonMap("url", "http://localhost:8080"))
.build();
// response assertions
WebClient client1 = WebClient.builder().clientConnector(httpConnector()).build();
StepVerifier.create(retrieveResponse(client1.post()
.uri("http://localhost:" + port + "/resource")))
.expectNext("processed-bodyValue")
.verifyComplete();
WebClient client2 = WebClient.builder().baseUrl("http://localhost:" + port)
.clientConnector(httpConnector()).build();
StepVerifier.create(retrieveResponse(client2))
.expectNext("processed-bodyValue")
.verifyComplete();
WebClient client3 = WebClient.builder()
.baseUrl("http://localhost:" + port)
.clientConnector(httpConnector())
.defaultCookie("cookieKey", "cookieValue")
.defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
.defaultUriVariables(Collections.singletonMap("url", "http://localhost:8080"))
.build();
StepVerifier.create(retrieveResponse(client3))
.expectNext("processed-bodyValue")
.verifyComplete();
// assert response without specifying URI
StepVerifier.create(retrieveResponse(client1))
.expectErrorMatches(ex -> WebClientRequestException.class.isAssignableFrom(ex.getClass()) && ex.getMessage()
.contains("Connection refused"))
.verify();
}
@Test
void givenWebClientCreationWithoutUri_whenUsed_thenObtainExpectedResponse() {
WebClient client = WebClient.create();
StepVerifier.create(retrieveResponse(client))
.expectErrorMatches(ex -> WebClientRequestException.class.isAssignableFrom(ex.getClass()) && ex.getMessage()
.contains("Connection refused"))
.verify();
}
@Test
void givenDifferentMethodSpecifications_whenUsed_thenObtainExpectedResponse() {
// request specification
RequestBodyUriSpec uriSpecPost1 = createDefaultClient().method(HttpMethod.POST);
RequestBodyUriSpec uriSpecPost2 = createDefaultClient().post();
RequestHeadersUriSpec<?> requestGet = createDefaultClient().get();
// response assertions
RequestBodyUriSpec uriSpecPost1 = createDefaultClient().method(HttpMethod.POST);
StepVerifier.create(retrieveResponse(uriSpecPost1))
.expectNext("processed-bodyValue")
.verifyComplete();
RequestBodyUriSpec uriSpecPost2 = createDefaultClient().post();
StepVerifier.create(retrieveResponse(uriSpecPost2))
.expectNext("processed-bodyValue")
.verifyComplete();
RequestHeadersUriSpec<?> requestGet = createDefaultClient().get();
StepVerifier.create(retrieveGetResponse(requestGet))
.expectNextMatches(nextMap -> nextMap.get("field")
.equals("value"))
@ -114,21 +100,21 @@ class WebClientIntegrationTest {
@Test
void givenDifferentUriSpecifications_whenUsed_thenObtainExpectedResponse() {
// uri specification
RequestBodySpec bodySpecUsingString = createDefaultPostRequest().uri("/resource");
RequestBodySpec bodySpecUsingUriBuilder = createDefaultPostRequest().uri(
uriBuilder -> uriBuilder.pathSegment("resource")
.build());
RequestBodySpec bodySpecusingURI = createDefaultPostRequest().uri(
URI.create("http://localhost:" + port + "/resource"));
// response assertions
RequestBodySpec bodySpecUsingString = createDefaultPostRequest().uri("/resource");
StepVerifier.create(retrieveResponse(bodySpecUsingString))
.expectNext("processed-bodyValue")
.verifyComplete();
RequestBodySpec bodySpecUsingUriBuilder = createDefaultPostRequest().uri(
uriBuilder -> uriBuilder.pathSegment("resource")
.build());
StepVerifier.create(retrieveResponse(bodySpecUsingUriBuilder))
.expectNext("processed-bodyValue")
.verifyComplete();
RequestBodySpec bodySpecusingURI = createDefaultPostRequest().uri(
URI.create("http://localhost:" + port + "/resource"));
StepVerifier.create(retrieveResponse(bodySpecusingURI))
.expectNext("processed-bodyValue")
.verifyComplete();
@ -136,21 +122,23 @@ class WebClientIntegrationTest {
@Test
void givenOverriddenUriSpecifications_whenUsed_thenObtainExpectedResponse() {
RequestBodySpec bodySpecOverriddenBaseUri = createDefaultPostRequest().uri(URI.create("/resource"));
RequestBodySpec bodySpecOverriddenBaseUri = createDefaultPostRequest()
.uri(URI.create("http://localhost:" + port + "/resource-override"));
StepVerifier.create(retrieveResponse(bodySpecOverriddenBaseUri))
.expectErrorMatches(ex -> WebClientRequestException.class.isAssignableFrom(ex.getClass()) && ex.getMessage()
.contains("Connection refused"))
.verify();
.expectNext("override-processed-bodyValue")
.verifyComplete();
RequestBodySpec bodySpecOverriddenBaseUri2 = WebClient.builder()
.clientConnector(httpConnector())
.baseUrl("http://localhost:" + port)
.build()
.post()
.uri(URI.create("/resource"));
.uri(URI.create("http://localhost:" + port + "/resource-override"));
StepVerifier.create(retrieveResponse(bodySpecOverriddenBaseUri2))
.expectErrorMatches(ex -> WebClientRequestException.class.isAssignableFrom(ex.getClass()) && ex.getMessage()
.contains("Connection refused"))
.verify();
.expectNext("override-processed-bodyValue")
.verifyComplete();
}
@Test
@ -195,7 +183,7 @@ class WebClientIntegrationTest {
StepVerifier.create(retrieveResponse(headersSpecPlainObject))
.expectError(CodecException.class)
.verify();
// assert response for request with no body
// assert response for request without body
Mono<Map<String, String>> responsePostWithNoBody = createDefaultPostResourceRequest().exchangeToMono(
responseHandler -> {
assertThat(responseHandler.statusCode()).isEqualTo(HttpStatus.BAD_REQUEST);
@ -294,7 +282,17 @@ class WebClientIntegrationTest {
// helper methods to create default instances
private WebClient createDefaultClient() {
return WebClient.create("http://localhost:" + port);
return WebClient.builder()
.baseUrl("http://localhost:" + port)
.clientConnector(httpConnector())
.build();
}
private static ReactorClientHttpConnector httpConnector() {
HttpClient httpClient = HttpClient
.create()
.wiretap(true);
return new ReactorClientHttpConnector(httpClient);
}
private RequestBodyUriSpec createDefaultPostRequest() {
@ -315,35 +313,30 @@ class WebClientIntegrationTest {
.uri("/resource")
.bodyValue(BODY_VALUE)
.retrieve()
.bodyToMono(String.class)
.log();
.bodyToMono(String.class);
}
private Mono<String> retrieveResponse(RequestBodyUriSpec spec) {
return spec.uri("/resource")
.bodyValue(BODY_VALUE)
.retrieve()
.bodyToMono(String.class)
.log();
.bodyToMono(String.class);
}
private Mono<Map<String, String>> retrieveGetResponse(RequestHeadersUriSpec<?> spec) {
return spec.uri("/resource")
.retrieve()
.bodyToMono(MAP_RESPONSE_REF)
.log();
.bodyToMono(MAP_RESPONSE_REF);
}
private Mono<String> retrieveResponse(RequestBodySpec spec) {
return spec.bodyValue(BODY_VALUE)
.retrieve()
.bodyToMono(String.class)
.log();
.bodyToMono(String.class);
}
private Mono<String> retrieveResponse(RequestHeadersSpec<?> spec) {
return spec.retrieve()
.bodyToMono(String.class)
.log();
.bodyToMono(String.class);
}
}

View File

@ -9,6 +9,9 @@
name="com.baeldung.reactive.debugging.consumer.service.FooService">
<appender-ref ref="LISTAPPENDER" />
</logger>
<logger name="reactor.netty.http.client" level="INFO"/>
<root level="info">
<appender-ref ref="CONSOLE" />
<appender-ref ref="LISTAPPENDER" />

View File

@ -0,0 +1,4 @@
### Relevant Articles:
- [Spring Boot 3 and Spring Framework 6.0 What's New](https://www.baeldung.com/spring-boot-3-spring-6-new)

View File

@ -9,5 +9,6 @@ This module contains articles about various Spring Boot libraries
- [An Introduction to Kong](https://www.baeldung.com/kong)
- [Getting Started With GraphQL SPQR and Spring Boot](https://www.baeldung.com/spring-boot-graphql-spqr)
- [How to Test GraphQL Using Postman](https://www.baeldung.com/graphql-postman)
- [Scanning Java Annotations At Runtime](https://www.baeldung.com/java-scan-annotations-runtime)
More articles: [[prev -->]](/spring-boot-modules/spring-boot-libraries)

View File

@ -1,3 +1,4 @@
### Relevant Articles:
- [Instantiating Multiple Beans of the Same Class with Spring Annotations](https://www.baeldung.com/spring-same-class-multiple-beans)
- [Using Environment Variables in Spring Boot's application.properties](https://www.baeldung.com/spring-boot-properties-env-variables)

View File

@ -100,6 +100,18 @@
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-jdk14</artifactId>
@ -206,7 +218,6 @@
<properties>
<jersey.version>2.29.1</jersey.version>
<jackson.version>2.11.1</jackson.version>
<cargo-maven2-plugin.version>1.6.1</cargo-maven2-plugin.version>
<httpcore.version>4.4.9</httpcore.version>
<httpclient.version>4.5.5</httpclient.version>

View File

@ -27,11 +27,11 @@ import org.springframework.test.context.junit4.SpringRunner;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.utility.DockerImageName;
import com.baeldung.spring.jms.testing.TestContainersActiveMqIntegrationTest.TestConfiguration;
import com.baeldung.spring.jms.testing.TestContainersActiveMqLiveTest.TestConfiguration;
@RunWith(SpringRunner.class)
@ContextConfiguration(classes = { TestConfiguration.class, MessageSender.class })
public class TestContainersActiveMqIntegrationTest {
public class TestContainersActiveMqLiveTest {
@ClassRule
public static GenericContainer<?> activeMqContainer = new GenericContainer<>(DockerImageName.parse("rmohr/activemq:5.14.3")).withExposedPorts(61616);

View File

@ -10,6 +10,7 @@ This module contains articles about Spring with Kafka
- [Send Large Messages With Kafka](https://www.baeldung.com/java-kafka-send-large-message)
- [Configuring Kafka SSL Using Spring Boot](https://www.baeldung.com/spring-boot-kafka-ssl)
- [Kafka Streams With Spring Boot](https://www.baeldung.com/spring-boot-kafka-streams)
- [Get the Number of Messages in an Apache Kafka Topic](https://www.baeldung.com/java-kafka-count-topic-messages)
### Intro

View File

@ -7,4 +7,5 @@ The "REST With Spring" Classes: http://github.learnspringsecurity.com
### Relevant Articles:
- [Spring Security: Upgrading the Deprecated WebSecurityConfigurerAdapter](https://www.baeldung.com/spring-deprecated-websecurityconfigureradapter)
- More articles: [[<-- prev]](/spring-security-modules/spring-security-web-boot-3)

View File

@ -4,4 +4,5 @@ This module contains articles about Spring Security with Thymeleaf.
### Relevant Articles:
- [Spring Security with Thymeleaf](https://www.baeldung.com/spring-security-thymeleaf)
- [Spring Security with Thymeleaf](https://www.baeldung.com/spring-security-thymeleaf)
- [Display Logged-in User's Information in Thymeleaf](https://www.baeldung.com/spring-thymeleaf-user-info)

View File

@ -96,7 +96,7 @@ if(hasProperty('target') && target == 'android') {
ext {
swagger_annotations_version = "1.5.22"
jackson_version = "2.10.1"
jackson_version = "2.13.3"
jackson_databind_version = "2.10.1"
jackson_databind_nullable_version = "0.2.1"
spring_web_version = "4.3.9.RELEASE"

View File

@ -95,7 +95,7 @@ if(hasProperty('target') && target == 'android') {
ext {
swagger_annotations_version = "1.5.15"
jackson_version = "2.8.9"
jackson_version = "2.13.3"
spring_web_version = "4.3.9.RELEASE"
jodatime_version = "2.9.9"
junit_version = "4.12"

View File

@ -14,7 +14,7 @@ import org.springframework.web.client.RestTemplate;
public class LargeFileDownloadIntegrationTest {
static String FILE_URL = "https://s3.amazonaws.com/baeldung.com/Do+JSON+with+Jackson+by+Baeldung.pdf";
static String FILE_URL = "https://s3.amazonaws.com/baeldung.com/Do+JSON+with+Jackson.pdf?__s=vatuzcrazsqopnn7finb";
RestTemplate restTemplate;

View File

@ -7,4 +7,5 @@ This module contains articles about Spring with Thymeleaf
- [Changing the Thymeleaf Template Directory in Spring Boot](https://www.baeldung.com/spring-thymeleaf-template-directory)
- [How to Create an Executable JAR with Maven](https://www.baeldung.com/executable-jar-with-maven)
- [Spring MVC Data and Thymeleaf](https://www.baeldung.com/spring-mvc-thymeleaf-data)
- [Upload Image With Spring Boot and Thymeleaf](https://www.baeldung.com/spring-boot-thymeleaf-image-upload)
- [[<-- prev]](/spring-thymeleaf)

View File

@ -1,37 +1,32 @@
package com.baeldung.mockito;
import org.junit.Test;
import static org.junit.Assert.assertNotEquals;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import com.baeldung.mockito.MyList;
import org.junit.Test;
public class MockFinalsUnitTest {
@Test
public void whenMockFinalClassMockWorks() {
@Test
public void whenMockFinalMethodMockWorks() {
MyList myList = new MyList();
MyList mock = mock(MyList.class);
when(mock.finalMethod()).thenReturn(1);
assertThat(mock.finalMethod()).isNotEqualTo(myList.finalMethod());
}
@Test
public void whenMockFinalClassMockWorks() {
FinalList finalList = new FinalList();
FinalList mock = mock(FinalList.class);
when(mock.size()).thenReturn(2);
assertNotEquals(mock.size(), finalList.size());
}
@Test
public void whenMockFinalMethodMockWorks() {
MyList myList = new MyList();
MyList mock = mock(MyList.class);
when(mock.finalMethod()).thenReturn(1);
assertNotEquals(mock.finalMethod(), myList.finalMethod());
assertThat(mock.size()).isNotEqualTo(finalList.size());
}
}
}

View File

@ -1,12 +1,18 @@
package com.baeldung.mockito.argumentcaptor;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.*;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;
import static org.junit.Assert.*;
@RunWith(MockitoJUnitRunner.class)
public class EmailServiceUnitTest {
@ -32,7 +38,7 @@ public class EmailServiceUnitTest {
Mockito.verify(platform).deliver(emailCaptor.capture());
Email emailCaptorValue = emailCaptor.getValue();
assertEquals(Format.TEXT_ONLY, emailCaptorValue.getFormat());
assertThat(emailCaptorValue.getFormat()).isEqualTo(Format.TEXT_ONLY);
}
@Test
@ -45,7 +51,7 @@ public class EmailServiceUnitTest {
Mockito.verify(platform).deliver(emailCaptor.capture());
Email value = emailCaptor.getValue();
assertEquals(Format.HTML, value.getFormat());
assertThat(value.getFormat()).isEqualTo(Format.HTML);
}
@Test
@ -54,7 +60,7 @@ public class EmailServiceUnitTest {
ServiceStatus serviceStatus = emailService.checkServiceStatus();
assertEquals(ServiceStatus.UP, serviceStatus);
assertThat(serviceStatus).isEqualTo(ServiceStatus.UP);
}
@Test
@ -63,7 +69,7 @@ public class EmailServiceUnitTest {
ServiceStatus serviceStatus = emailService.checkServiceStatus();
assertEquals(ServiceStatus.DOWN, serviceStatus);
assertThat(serviceStatus).isEqualTo(ServiceStatus.DOWN);
}
@Test
@ -80,7 +86,7 @@ public class EmailServiceUnitTest {
Mockito.when(platform.authenticate(credentialsCaptor.capture())).thenReturn(AuthenticationStatus.AUTHENTICATED);
assertTrue(emailService.authenticatedSuccessfully(credentials));
assertEquals(credentials, credentialsCaptor.getValue());
assertThat(credentialsCaptor.getValue()).isEqualTo(credentials);
}
@Test

View File

@ -0,0 +1,30 @@
package com.baeldung.mockito.spy;
import static org.assertj.core.api.Assertions.assertThatNoException;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import java.util.ArrayList;
import java.util.List;
import org.junit.Test;
import org.mockito.Mockito;
import org.mockito.exceptions.misusing.NotAMockException;
public class MockitoMisusingMockOrSpyUnitTest {
@Test
public void givenNotASpy_whenDoReturn_thenThrowNotAMock() {
List<String> list = new ArrayList<String>();
assertThatThrownBy(() -> Mockito.doReturn(100).when(list).size())
.isInstanceOf(NotAMockException.class)
.hasMessageContaining("Argument passed to when() is not a mock!");
}
@Test
public void givenASpy_whenDoReturn_thenNoError() {
final List<String> spyList = Mockito.spy(new ArrayList<>());
assertThatNoException().isThrownBy(() -> Mockito.doReturn(100).when(spyList).size());
}
}

View File

@ -1,38 +0,0 @@
package com.baeldung.mockito.spy;
import org.junit.After;
import org.junit.Test;
import org.mockito.Mockito;
import org.mockito.exceptions.misusing.NotAMockException;
import org.mockito.internal.progress.ThreadSafeMockingProgress;
import java.util.ArrayList;
import java.util.List;
import static org.hamcrest.CoreMatchers.containsString;
import static org.junit.Assert.assertThat;
import static org.junit.jupiter.api.Assertions.fail;
public class MockitoMisusingUnitTest {
@After
public void tearDown() {
ThreadSafeMockingProgress.mockingProgress().reset();
}
@Test
public void givenNotASpy_whenDoReturn_thenThrowNotAMock() {
try {
List<String> list = new ArrayList<String>();
Mockito.doReturn(100, Mockito.withSettings().lenient())
.when(list)
.size();
fail("Should have thrown a NotAMockException because 'list' is not a mock!");
} catch (NotAMockException e) {
assertThat(e.getMessage(), containsString("Argument passed to when() is not a mock!"));
}
}
}

View File

@ -1,22 +1,20 @@
package com.baeldung.mockito.spy;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.assertEquals;
import java.util.ArrayList;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.mockito.Spy;
import org.mockito.junit.MockitoJUnitRunner;
import java.util.ArrayList;
import java.util.List;
import static org.junit.Assert.assertEquals;
@RunWith(MockitoJUnitRunner.class)
public class MockitoSpyUnitTest {
@Spy
private List<String> aSpyList = new ArrayList<String>();
@Test
public void whenSpyingOnList_thenCorrect() {
final List<String> list = new ArrayList<String>();
@ -28,9 +26,12 @@ public class MockitoSpyUnitTest {
Mockito.verify(spyList).add("one");
Mockito.verify(spyList).add("two");
assertEquals(2, spyList.size());
assertThat(spyList).hasSize(2);
}
@Spy
private List<String> aSpyList = new ArrayList<String>();
@Test
public void whenUsingTheSpyAnnotation_thenObjectIsSpied() {
aSpyList.add("one");
@ -39,7 +40,7 @@ public class MockitoSpyUnitTest {
Mockito.verify(aSpyList).add("one");
Mockito.verify(aSpyList).add("two");
assertEquals(2, aSpyList.size());
assertThat(aSpyList).hasSize(2);
}
@Test
@ -50,7 +51,7 @@ public class MockitoSpyUnitTest {
assertEquals(0, spyList.size());
Mockito.doReturn(100).when(spyList).size();
assertEquals(100, spyList.size());
assertThat(spyList).hasSize(100);
}
@Test
@ -60,17 +61,17 @@ public class MockitoSpyUnitTest {
mockedList.add("one");
Mockito.verify(mockedList).add("one");
assertEquals(0, mockedList.size());
assertThat(mockedList).hasSize(0);
}
@Test
public void whenCreateSpy_thenCreate() {
final List<String> spyList = Mockito.spy(new ArrayList<String>());
final List<String> spyList = Mockito.spy(new ArrayList<>());
spyList.add("one");
Mockito.verify(spyList).add("one");
assertEquals(1, spyList.size());
assertThat(spyList).hasSize(1);
}
}

View File

@ -1,15 +1,23 @@
package com.baeldung.mockito.voidmethods;
import com.baeldung.mockito.MyList;
import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.isA;
import static org.mockito.ArgumentMatchers.isNull;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doCallRealMethod;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.junit.MockitoJUnitRunner;
import org.mockito.stubbing.Answer;
import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.*;
import com.baeldung.mockito.MyList;
@RunWith(MockitoJUnitRunner.class)
public class MockitoVoidMethodsUnitTest {