Merge branch 'eugenp:master' into BAEL-7618
This commit is contained in:
commit
dfbe49790a
@ -7,4 +7,5 @@
|
||||
- [Rotate Arrays in Java](https://www.baeldung.com/java-rotate-arrays)
|
||||
- [Find Missing Number From a Given Array in Java](https://www.baeldung.com/java-array-find-missing-number)
|
||||
- [Calculate Weighted Mean in Java](https://www.baeldung.com/java-compute-weighted-average)
|
||||
- [Check if Two Strings Are Rotations of Each Other](https://www.baeldung.com/java-string-check-strings-rotations)
|
||||
- More articles: [[<-- prev]](/algorithms-miscellaneous-6)
|
||||
|
@ -191,7 +191,7 @@
|
||||
<bval.version>2.0.6</bval.version>
|
||||
<javax.validation.validation-api.version>2.0.1.Final</javax.validation.validation-api.version>
|
||||
<meecrowave-junit.version>1.2.15</meecrowave-junit.version>
|
||||
<okhttp.version>4.12.0</okhttp.version>
|
||||
<okhttp.version>5.0.0-alpha.12</okhttp.version>
|
||||
<meecrowave-jpa.version>1.2.15</meecrowave-jpa.version>
|
||||
<meecrowave-core.version>1.2.15</meecrowave-core.version>
|
||||
<meecrowave-maven-plugin.version>1.2.15</meecrowave-maven-plugin.version>
|
||||
|
@ -1,2 +1,3 @@
|
||||
## Relevant Articles
|
||||
- [Deprecate Finalization in Java 18](https://www.baeldung.com/java-18-deprecate-finalization)
|
||||
- [Simple Web Server in Java 18](https://www.baeldung.com/simple-web-server-java-18)
|
||||
|
@ -22,7 +22,7 @@
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
<version>31.1-jre</version>
|
||||
<version>${guava.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
@ -29,4 +29,4 @@
|
||||
<properties>
|
||||
<vavr.version>0.10.4</vavr.version>
|
||||
</properties>
|
||||
</project>
|
||||
</project>
|
||||
|
@ -0,0 +1,54 @@
|
||||
package com.baeldung.modifyandprint;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
public class ModifyAndPrintListElementsUnitTest {
|
||||
|
||||
private final Logger log = LoggerFactory.getLogger(ModifyAndPrintListElementsUnitTest.class);
|
||||
|
||||
@Test
|
||||
void whenPrintingInForEach_thenListIsPrinted() {
|
||||
List<String> theList = Lists.newArrayList("Kai", "Liam", "Eric", "Kevin");
|
||||
theList.forEach(element -> log.info(element));
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenUsingModifyAndPrintingSeparately_thenListIsModifiedAndPrinted() {
|
||||
List<String> theList = Lists.newArrayList("Kai", "Liam", "Eric", "Kevin");
|
||||
theList.replaceAll(element -> element.toUpperCase());
|
||||
theList.forEach(element -> log.info(element));
|
||||
assertEquals(List.of("KAI", "LIAM", "ERIC", "KEVIN"), theList);
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenPrintingInMap_thenStreamIsModifiedAndPrinted() {
|
||||
List<String> theList = List.of("Kai", "Liam", "Eric", "Kevin");
|
||||
List<String> newList = theList.stream()
|
||||
.map(element -> {
|
||||
String newElement = element.toUpperCase();
|
||||
log.info(newElement);
|
||||
return newElement;
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
assertEquals(List.of("KAI", "LIAM", "ERIC", "KEVIN"), newList);
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenPrintingInPeek_thenStreamIsModifiedAndPrinted() {
|
||||
List<String> theList = List.of("Kai", "Liam", "Eric", "Kevin");
|
||||
List<String> newList = theList.stream()
|
||||
.map(element -> element.toUpperCase())
|
||||
.peek(element-> log.info(element))
|
||||
.collect(Collectors.toList());
|
||||
assertEquals(List.of("KAI", "LIAM", "ERIC", "KEVIN"), newList);
|
||||
}
|
||||
}
|
@ -8,4 +8,5 @@
|
||||
- [How to Sort LinkedHashMap by Values in Java](https://www.baeldung.com/java-sort-linkedhashmap-using-values)
|
||||
- [How to Increment a Map Value in Java](https://www.baeldung.com/java-increment-map-value)
|
||||
- [Collect Stream of entrySet() to a LinkedHashMap](https://www.baeldung.com/java-linkedhashmap-entryset-stream)
|
||||
- [How to Pretty-Print a Map in Java](https://www.baeldung.com/java-map-pretty-print)
|
||||
- More articles: [[<-- prev]](/core-java-modules/core-java-collections-maps-6)
|
||||
|
@ -35,7 +35,7 @@
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
<version>32.1.1-jre</version>
|
||||
<version>${guava.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
|
@ -9,3 +9,5 @@
|
||||
- [Parallelize for Loop in Java](https://www.baeldung.com/java-for-loop-parallel)
|
||||
- [How to Effectively Unit Test CompletableFuture](https://www.baeldung.com/java-completablefuture-unit-test)
|
||||
- [How to Collect All Results and Handle Exceptions With CompletableFuture in a Loop](https://www.baeldung.com/java-completablefuture-collect-results-handle-exceptions)
|
||||
- [CompletableFuture runAsync() vs. supplyAsync() in Java](https://www.baeldung.com/java-completablefuture-runasync-supplyasync)
|
||||
- [Difference Between thenApply() and thenApplyAsync() in CompletableFuture](https://www.baeldung.com/java-completablefuture-thenapply-thenapplyasync)
|
||||
|
@ -17,4 +17,5 @@
|
||||
- [Validate if a String Is a Valid Geo Coordinate](https://www.baeldung.com/java-geo-coordinates-validation)
|
||||
- [Rotate a Vertex Around a Certain Point in Java](https://www.baeldung.com/java-rotate-vertex-around-point)
|
||||
- [Calculating the Power of Any Number in Java Without Using Math pow() Method](https://www.baeldung.com/java-calculating-the-power-without-math-pow)
|
||||
- [Solving Rod Cutting Problem in Java](https://www.baeldung.com/java-rod-cutting-problem)
|
||||
- More articles: [[<-- Prev]](/core-java-modules/core-java-lang-math-2)
|
||||
|
@ -1,19 +1,21 @@
|
||||
package com.baeldung.outofmemoryerror;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
public class OutOfMemoryGCLimitExceed {
|
||||
public static void addRandomDataToMap() {
|
||||
Map<Integer, String> dataMap = new HashMap<>();
|
||||
Random r = new Random();
|
||||
|
||||
public static final Random RANDOM = new Random();
|
||||
|
||||
public static void addRandomDataToList() {
|
||||
List<String> dataList = new LinkedList<>();
|
||||
while (true) {
|
||||
dataMap.put(r.nextInt(), String.valueOf(r.nextInt()));
|
||||
dataList.add(String.valueOf(RANDOM.nextInt()));
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
OutOfMemoryGCLimitExceed.addRandomDataToMap();
|
||||
OutOfMemoryGCLimitExceed.addRandomDataToList();
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
## Relevant Articles
|
||||
- [Java 8 Stream Operation on the Empty List](https://www.baeldung.com/java-empty-list-stream-ops)
|
||||
- [Get a Range of Items from a Stream in Java](https://www.baeldung.com/java-stream-get-range)
|
||||
|
||||
|
@ -6,3 +6,4 @@ This module contains articles about string-related algorithms.
|
||||
- [Rotating a Java String By n Characters](https://www.baeldung.com/java-rotate-string-by-n-characters)
|
||||
- [Remove Characters From a String That Are in the Other String](https://www.baeldung.com/java-strings-character-difference)
|
||||
- [Run-Length Encoding and Decoding in Java](https://www.baeldung.com/java-rle-compression)
|
||||
- [Check if a String Is Equal to Its Mirror Reflection](https://www.baeldung.com/java-string-mirror-image-test)
|
||||
|
@ -1,2 +1,6 @@
|
||||
### Relevant Articles:
|
||||
- [Count Uppercase and Lowercase Letters in a String](https://www.baeldung.com/java-string-count-letters-uppercase-lowercase)
|
||||
- [Find The Largest Number in a String](https://www.baeldung.com/java-find-largest-number-string)
|
||||
- [Check if String is Base64 Encoded](https://www.baeldung.com/java-check-string-base64-encoding)
|
||||
- [Find an Unique Email Address in a List](https://www.baeldung.com/java-find-unique-email-address)
|
||||
- [Get First n Characters in a String in Java](https://www.baeldung.com/get-first-n-characters-in-a-string-in-java)
|
||||
|
@ -1,83 +0,0 @@
|
||||
package com.baeldung.uuid;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Methods are called by reflection in the unit test
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class UUIDPositiveLongGenerator {
|
||||
public long getLeastSignificantBits() {
|
||||
return Math.abs(UUID.randomUUID().getLeastSignificantBits());
|
||||
}
|
||||
|
||||
public long getMostSignificantBits() {
|
||||
return Math.abs(UUID.randomUUID().getMostSignificantBits());
|
||||
}
|
||||
|
||||
public long combineByteBuffer() {
|
||||
UUID uuid = UUID.randomUUID();
|
||||
ByteBuffer bb = ByteBuffer.wrap(new byte[16]);
|
||||
bb.putLong(uuid.getMostSignificantBits());
|
||||
bb.putLong(uuid.getLeastSignificantBits());
|
||||
bb.rewind();
|
||||
return Math.abs(bb.getLong());
|
||||
}
|
||||
|
||||
public long combineBitwise() {
|
||||
UUID uniqueUUID = UUID.randomUUID();
|
||||
long mostSignificantBits = uniqueUUID.getMostSignificantBits();
|
||||
long leastSignificantBits = uniqueUUID.getLeastSignificantBits();
|
||||
return Math.abs((mostSignificantBits << 32) | (leastSignificantBits & 0xFFFFFFFFL));
|
||||
}
|
||||
|
||||
public long combineDirect() {
|
||||
UUID uniqueUUID = UUID.randomUUID();
|
||||
long mostSignificantBits = uniqueUUID.getMostSignificantBits();
|
||||
long leastSignificantBits = uniqueUUID.getLeastSignificantBits();
|
||||
return Math.abs(mostSignificantBits ^ (leastSignificantBits >> 1));
|
||||
}
|
||||
|
||||
public long combinePermutation() {
|
||||
UUID uuid = UUID.randomUUID();
|
||||
long mostSigBits = uuid.getMostSignificantBits();
|
||||
long leastSigBits = uuid.getLeastSignificantBits();
|
||||
byte[] uuidBytes = new byte[16];
|
||||
|
||||
for (int i = 0; i < 8; i++) {
|
||||
uuidBytes[i] = (byte) (mostSigBits >>> (8 * (7 - i)));
|
||||
uuidBytes[i + 8] = (byte) (leastSigBits >>> (8 * (7 - i)));
|
||||
}
|
||||
|
||||
long result = 0;
|
||||
for (byte b : uuidBytes) {
|
||||
result = (result << 8) | (b & 0xFF);
|
||||
}
|
||||
return Math.abs(result);
|
||||
}
|
||||
|
||||
public long combineWithSecureRandom() {
|
||||
UUID uniqueUUID = UUID.randomUUID();
|
||||
SecureRandom secureRandom = new SecureRandom();
|
||||
long randomBits = secureRandom.nextLong();
|
||||
|
||||
long mostSignificantBits = uniqueUUID.getMostSignificantBits() ^ randomBits;
|
||||
long leastSignificantBits = uniqueUUID.getLeastSignificantBits();
|
||||
|
||||
return Math.abs((mostSignificantBits << 32) | (leastSignificantBits & 0xFFFFFFFFL));
|
||||
}
|
||||
|
||||
public long combineWithNanoTime() {
|
||||
UUID uniqueUUID = UUID.randomUUID();
|
||||
long nanoTime = System.nanoTime();
|
||||
|
||||
long mostSignificantBits = uniqueUUID.getMostSignificantBits() ^ nanoTime;
|
||||
long leastSignificantBits = uniqueUUID.getLeastSignificantBits();
|
||||
|
||||
return Math.abs((mostSignificantBits << 32) | (leastSignificantBits & 0xFFFFFFFFL));
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -2,42 +2,21 @@ package com.baeldung.uuid;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class UUIDPositiveLongGeneratorUnitTest {
|
||||
|
||||
private final UUIDPositiveLongGenerator uuidLongGenerator = new UUIDPositiveLongGenerator();
|
||||
|
||||
private final Set<Long> uniqueValues = new HashSet<>();
|
||||
|
||||
@Test
|
||||
void whenForeachMethods_thenRetryWhileNotUnique() throws Exception {
|
||||
for (Method method : uuidLongGenerator.getClass().getDeclaredMethods()) {
|
||||
long uniqueValue;
|
||||
do uniqueValue = (long) method.invoke(uuidLongGenerator); while (!isUnique(uniqueValue));
|
||||
assertThat(uniqueValue).isPositive();
|
||||
}
|
||||
public void whenGetMostSignificantBits_thenAssertPositive() {
|
||||
long randomPositiveLong = Math.abs(UUID.randomUUID().getMostSignificantBits());
|
||||
assertThat(randomPositiveLong).isNotNegative();
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenGivenLongValue_thenCheckUniqueness() {
|
||||
long uniqueValue = generateUniqueLong();
|
||||
assertThat(uniqueValue).isPositive();
|
||||
public void whenGetLeastSignificantBits_thenAssertPositive() {
|
||||
long randomPositiveLong = Math.abs(UUID.randomUUID().getLeastSignificantBits());
|
||||
assertThat(randomPositiveLong).isNotNegative();
|
||||
}
|
||||
|
||||
private long generateUniqueLong() {
|
||||
long uniqueValue;
|
||||
do uniqueValue = uuidLongGenerator.combineBitwise(); while (!isUnique(uniqueValue));
|
||||
return uniqueValue;
|
||||
}
|
||||
|
||||
private boolean isUnique(long value) {
|
||||
// Implement uniqueness checking logic, for example, by checking in the database
|
||||
return uniqueValues.add(value);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -66,7 +66,7 @@
|
||||
|
||||
<properties>
|
||||
<exchange-rate-api.version>1.0.0-SNAPSHOT</exchange-rate-api.version>
|
||||
<okhttp.version>4.12.0</okhttp.version>
|
||||
<okhttp.version>5.0.0-alpha.12</okhttp.version>
|
||||
<javax.json.bind-api.version>1.0</javax.json.bind-api.version>
|
||||
<yasson.version>1.0.1</yasson.version>
|
||||
<javax.json.version>1.1.2</javax.json.version>
|
||||
|
@ -15,12 +15,14 @@
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
<version>${guava.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>8</maven.compiler.source>
|
||||
<maven.compiler.target>8</maven.compiler.target>
|
||||
<guava.version>33.0.0-jre</guava.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
@ -9,9 +9,9 @@
|
||||
|
||||
<parent>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>parent-boot-2</artifactId>
|
||||
<artifactId>parent-boot-3</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<relativePath>../../parent-boot-2</relativePath>
|
||||
<relativePath>../../parent-boot-3</relativePath>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
|
@ -2,12 +2,12 @@
|
||||
#
|
||||
# docker build -f src/main/docker/Dockerfile .
|
||||
|
||||
FROM adoptopenjdk:11-jre-hotspot as builder
|
||||
FROM openjdk:17-jdk-alpine as builder
|
||||
ARG JAR_FILE=target/*.jar
|
||||
COPY ${JAR_FILE} application.jar
|
||||
RUN java -Djarmode=layertools -jar application.jar extract
|
||||
|
||||
FROM adoptopenjdk:11-jre-hotspot
|
||||
FROM openjdk:17-jdk-alpine
|
||||
COPY --from=builder dependencies/ ./
|
||||
COPY --from=builder spring-boot-loader/ ./
|
||||
COPY --from=builder internal-dependencies/ ./
|
||||
|
@ -6,6 +6,6 @@
|
||||
# To run with profiles:
|
||||
# docker run -e "SPRING_PROFILES_ACTIVE=test1,test2,test3" docker-with-spring-profile:latest
|
||||
|
||||
FROM openjdk:11
|
||||
FROM openjdk:17-jdk-alpine
|
||||
COPY target/*.jar app.jar
|
||||
ENTRYPOINT ["java", "-jar", "/app.jar"]
|
||||
|
@ -8,3 +8,4 @@ This module contains articles about Jackson custom conversions.
|
||||
- [Serialize Only Fields That Meet a Custom Criteria With Jackson](https://www.baeldung.com/jackson-serialize-field-custom-criteria)
|
||||
- [Calling Default Serializer from Custom Serializer in Jackson](https://www.baeldung.com/jackson-call-default-serializer-from-custom-serializer)
|
||||
- [OffsetDateTime Serialization With Jackson](https://www.baeldung.com/java-jackson-offsetdatetime)
|
||||
- [Create JavaType From Class with Jackson](https://www.baeldung.com/java-javatype-class-jackson)
|
||||
|
@ -11,3 +11,4 @@ This module contains articles about IO data processing libraries.
|
||||
- [Introduction To Docx4J](https://www.baeldung.com/docx4j)
|
||||
- [Breaking YAML Strings Over Multiple Lines](https://www.baeldung.com/yaml-multi-line)
|
||||
- [Different Serialization Approaches for Java](https://www.baeldung.com/java-serialization-approaches)
|
||||
- [A Guide to etcd](https://www.baeldung.com/java-etcd-guide)
|
||||
|
@ -109,9 +109,9 @@
|
||||
</build>
|
||||
|
||||
<properties>
|
||||
<okhttp.version>4.12.0</okhttp.version>
|
||||
<okhttp.version>5.0.0-alpha.12</okhttp.version>
|
||||
<gson.version>2.10.1</gson.version>
|
||||
<mockwebserver.version>4.9.1</mockwebserver.version>
|
||||
<mockwebserver.version>5.0.0-alpha.12</mockwebserver.version>
|
||||
<jetty.httpclient.version>1.0.3</jetty.httpclient.version>
|
||||
<jetty.server.version>9.4.19.v20190610</jetty.server.version>
|
||||
<rxjava2.version>2.2.11</rxjava2.version>
|
||||
|
@ -52,17 +52,10 @@ public class BinaryFileDownloaderUnitTest {
|
||||
verify(writer).close();
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void givenUrlAndResponseWithNullBody_whenDownload_thenExpectIllegalStateException() throws Exception {
|
||||
@Test(expected = NullPointerException.class)
|
||||
public void givenUrlAndResponseWithNullBody_whenDownload_thenExpectNullPointerException() throws Exception {
|
||||
String url = "http://example.com/file";
|
||||
Call call = mock(Call.class);
|
||||
when(client.newCall(any(Request.class))).thenReturn(call);
|
||||
Response response = createResponse(url, null);
|
||||
when(call.execute()).thenReturn(response);
|
||||
|
||||
tested.download(url);
|
||||
|
||||
verify(writer, times(0)).write(any(InputStream.class), anyDouble());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
@ -13,13 +13,11 @@
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
<!-- Dependencies for response decoder with okhttp -->
|
||||
<dependency>
|
||||
<groupId>com.squareup.okhttp3</groupId>
|
||||
<artifactId>okhttp</artifactId>
|
||||
<version>${com.squareup.okhttp3.version}</version>
|
||||
</dependency>
|
||||
<!-- Dependencies for google http client -->
|
||||
<dependency>
|
||||
<groupId>com.google.http-client</groupId>
|
||||
<artifactId>google-http-client</artifactId>
|
||||
@ -30,7 +28,6 @@
|
||||
<artifactId>google-http-client-jackson2</artifactId>
|
||||
<version>${googleclient.version}</version>
|
||||
</dependency>
|
||||
<!-- Retrofit -->
|
||||
<dependency>
|
||||
<groupId>com.squareup.retrofit2</groupId>
|
||||
<artifactId>retrofit</artifactId>
|
||||
@ -46,7 +43,6 @@
|
||||
<artifactId>adapter-rxjava</artifactId>
|
||||
<version>${retrofit.version}</version>
|
||||
</dependency>
|
||||
<!-- https://mvnrepository.com/artifact/org.asynchttpclient/async-http-client -->
|
||||
<dependency>
|
||||
<groupId>org.asynchttpclient</groupId>
|
||||
<artifactId>async-http-client</artifactId>
|
||||
@ -68,7 +64,6 @@
|
||||
<artifactId>unirest-java</artifactId>
|
||||
<version>${unirest.version}</version>
|
||||
</dependency>
|
||||
<!-- javalin -->
|
||||
<dependency>
|
||||
<groupId>io.javalin</groupId>
|
||||
<artifactId>javalin</artifactId>
|
||||
@ -105,7 +100,7 @@
|
||||
<properties>
|
||||
<gson.version>2.10.1</gson.version>
|
||||
<httpclient.version>4.5.3</httpclient.version>
|
||||
<com.squareup.okhttp3.version>4.12.0</com.squareup.okhttp3.version>
|
||||
<com.squareup.okhttp3.version>5.0.0-alpha.12</com.squareup.okhttp3.version>
|
||||
<googleclient.version>1.23.0</googleclient.version>
|
||||
<async.http.client.version>2.2.0</async.http.client.version>
|
||||
<retrofit.version>2.3.0</retrofit.version>
|
||||
|
@ -30,6 +30,12 @@
|
||||
<artifactId>jetty-webapp</artifactId>
|
||||
<version>${jetty.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.netty</groupId>
|
||||
<artifactId>netty-all</artifactId>
|
||||
<version>${netty.version}</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
@ -73,6 +79,7 @@
|
||||
<properties>
|
||||
<jetty.version>9.4.27.v20200227</jetty.version>
|
||||
<alpn.version>8.1.11.v20170118</alpn.version>
|
||||
<netty.version>4.1.104.Final</netty.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
@ -0,0 +1,77 @@
|
||||
package com.baeldung.netty.customhandlersandlisteners;
|
||||
|
||||
import java.util.Scanner;
|
||||
|
||||
import com.baeldung.netty.customhandlersandlisteners.handler.ClientEventHandler;
|
||||
import com.baeldung.netty.customhandlersandlisteners.listener.ChannelInfoListener;
|
||||
|
||||
import io.netty.bootstrap.Bootstrap;
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelFuture;
|
||||
import io.netty.channel.ChannelInitializer;
|
||||
import io.netty.channel.EventLoopGroup;
|
||||
import io.netty.channel.nio.NioEventLoopGroup;
|
||||
import io.netty.channel.socket.SocketChannel;
|
||||
import io.netty.channel.socket.nio.NioSocketChannel;
|
||||
import io.netty.handler.codec.string.StringDecoder;
|
||||
import io.netty.handler.codec.string.StringEncoder;
|
||||
|
||||
public class ChatClientMain {
|
||||
|
||||
private static final String SYSTEM_USER = System.getProperty("user.name");
|
||||
private static String user;
|
||||
|
||||
public static void main(String[] args) {
|
||||
EventLoopGroup group = new NioEventLoopGroup();
|
||||
try (Scanner scanner = new Scanner(System.in)) {
|
||||
Bootstrap bootstrap = new Bootstrap();
|
||||
bootstrap.group(group)
|
||||
.channel(NioSocketChannel.class)
|
||||
.handler(new ChannelInitializer<SocketChannel>() {
|
||||
@Override
|
||||
public void initChannel(SocketChannel channel) throws Exception {
|
||||
channel.pipeline()
|
||||
.addFirst(new StringDecoder(), new ClientEventHandler(), new StringEncoder());
|
||||
}
|
||||
});
|
||||
|
||||
ChannelFuture future = bootstrap.connect(ChatServerMain.HOST, ChatServerMain.PORT)
|
||||
.sync();
|
||||
|
||||
future.addListener(new ChannelInfoListener("connected to server"));
|
||||
Channel channel = future.sync()
|
||||
.channel();
|
||||
|
||||
messageLoop(scanner, channel);
|
||||
|
||||
channel.close();
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
Thread.currentThread().interrupt();
|
||||
} finally {
|
||||
group.shutdownGracefully();
|
||||
}
|
||||
}
|
||||
|
||||
private static void messageLoop(Scanner scanner, Channel channel) throws InterruptedException {
|
||||
Thread.sleep(50);
|
||||
|
||||
if (user == null) {
|
||||
System.out.printf("your name [%s]: ", SYSTEM_USER);
|
||||
user = scanner.nextLine();
|
||||
if (user.isEmpty())
|
||||
user = SYSTEM_USER;
|
||||
}
|
||||
|
||||
System.out.print("> ");
|
||||
while (scanner.hasNext()) {
|
||||
String message = scanner.nextLine();
|
||||
if (message.equals("exit"))
|
||||
break;
|
||||
|
||||
ChannelFuture sent = channel.writeAndFlush(user + ";" + message);
|
||||
sent.addListener(new ChannelInfoListener("message sent"));
|
||||
sent.addListener(future -> System.out.print("> "));
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
package com.baeldung.netty.customhandlersandlisteners;
|
||||
|
||||
import com.baeldung.netty.customhandlersandlisteners.handler.ServerEventHandler;
|
||||
import com.baeldung.netty.customhandlersandlisteners.listener.ChannelInfoListener;
|
||||
|
||||
import io.netty.bootstrap.ServerBootstrap;
|
||||
import io.netty.channel.ChannelFuture;
|
||||
import io.netty.channel.ChannelInitializer;
|
||||
import io.netty.channel.EventLoopGroup;
|
||||
import io.netty.channel.nio.NioEventLoopGroup;
|
||||
import io.netty.channel.socket.SocketChannel;
|
||||
import io.netty.channel.socket.nio.NioServerSocketChannel;
|
||||
import io.netty.handler.codec.string.StringDecoder;
|
||||
import io.netty.handler.codec.string.StringEncoder;
|
||||
|
||||
public final class ChatServerMain {
|
||||
|
||||
public static final String HOST = "localhost";
|
||||
public static final int PORT = 8081;
|
||||
|
||||
public static void main(String[] args) {
|
||||
EventLoopGroup serverGroup = new NioEventLoopGroup(1);
|
||||
EventLoopGroup clientGroup = new NioEventLoopGroup();
|
||||
try {
|
||||
ServerBootstrap bootstrap = new ServerBootstrap();
|
||||
bootstrap.group(serverGroup, clientGroup)
|
||||
.channel(NioServerSocketChannel.class)
|
||||
.childHandler(new ChannelInitializer<SocketChannel>() {
|
||||
@Override
|
||||
public void initChannel(SocketChannel channel) throws Exception {
|
||||
channel.pipeline()
|
||||
.addFirst(new StringDecoder(), new ServerEventHandler(), new StringEncoder());
|
||||
}
|
||||
});
|
||||
|
||||
ChannelFuture future = bootstrap.bind(HOST, PORT)
|
||||
.sync();
|
||||
|
||||
System.out.println("chat server started. ready to accept clients.");
|
||||
future.addListener(new ChannelInfoListener("server online"));
|
||||
|
||||
future.channel()
|
||||
.closeFuture()
|
||||
.sync();
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
Thread.currentThread().interrupt();
|
||||
} finally {
|
||||
serverGroup.shutdownGracefully();
|
||||
clientGroup.shutdownGracefully();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
package com.baeldung.netty.customhandlersandlisteners.handler;
|
||||
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.SimpleChannelInboundHandler;
|
||||
|
||||
public class ClientEventHandler extends SimpleChannelInboundHandler<String> {
|
||||
|
||||
@Override
|
||||
protected void channelRead0(ChannelHandlerContext context, String msg) {
|
||||
System.out.println(msg);
|
||||
}
|
||||
}
|
@ -0,0 +1,67 @@
|
||||
package com.baeldung.netty.customhandlersandlisteners.handler;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.Map;
|
||||
import java.util.Queue;
|
||||
|
||||
import com.baeldung.netty.customhandlersandlisteners.listener.ChannelInfoListener;
|
||||
import com.baeldung.netty.customhandlersandlisteners.model.Message;
|
||||
import com.baeldung.netty.customhandlersandlisteners.model.OfflineMessage;
|
||||
import com.baeldung.netty.customhandlersandlisteners.model.OnlineMessage;
|
||||
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelFuture;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.SimpleChannelInboundHandler;
|
||||
|
||||
public class ServerEventHandler extends SimpleChannelInboundHandler<String> {
|
||||
|
||||
private static final Map<String, Channel> clients = new HashMap<>();
|
||||
private static final int MAX_HISTORY = 5;
|
||||
private static final Queue<String> history = new LinkedList<>();
|
||||
|
||||
private void handleBroadcast(Message message, ChannelHandlerContext context) {
|
||||
final String channelId = id(context.channel());
|
||||
|
||||
System.out.printf("[clients: %d] message: %s\n", clients.size(), message);
|
||||
clients.forEach((id, channel) -> {
|
||||
if (!id.equals(channelId)) {
|
||||
ChannelFuture relay = channel.writeAndFlush(message.toString());
|
||||
relay.addListener(new ChannelInfoListener("message relayed to " + id));
|
||||
}
|
||||
});
|
||||
|
||||
history.add(message.toString() + "\n");
|
||||
if (history.size() > MAX_HISTORY)
|
||||
history.poll();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelRead0(ChannelHandlerContext context, String msg) {
|
||||
handleBroadcast(Message.parse(msg), context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelActive(final ChannelHandlerContext context) {
|
||||
Channel channel = context.channel();
|
||||
clients.put(id(channel), channel);
|
||||
|
||||
history.forEach(channel::writeAndFlush);
|
||||
|
||||
handleBroadcast(new OnlineMessage(id(channel)), context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelInactive(ChannelHandlerContext context) {
|
||||
Channel channel = context.channel();
|
||||
clients.remove(id(channel));
|
||||
|
||||
handleBroadcast(new OfflineMessage(id(channel)), context);
|
||||
}
|
||||
|
||||
private static String id(Channel channel) {
|
||||
return channel.id()
|
||||
.asShortText();
|
||||
}
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
package com.baeldung.netty.customhandlersandlisteners.listener;
|
||||
|
||||
import java.time.Instant;
|
||||
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelFuture;
|
||||
import io.netty.util.concurrent.GenericFutureListener;
|
||||
|
||||
public class ChannelInfoListener implements GenericFutureListener<ChannelFuture> {
|
||||
|
||||
private final String event;
|
||||
|
||||
public ChannelInfoListener(String event) {
|
||||
this.event = event;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void operationComplete(ChannelFuture future) throws Exception {
|
||||
Channel channel = future.channel();
|
||||
String status = "OK";
|
||||
|
||||
if (!future.isSuccess()) {
|
||||
status = "FAILED";
|
||||
future.cause()
|
||||
.printStackTrace();
|
||||
}
|
||||
|
||||
System.out.printf("%s - channel#%s %s: %s%n", Instant.now(), channel.id()
|
||||
.asShortText(), status, event);
|
||||
}
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
package com.baeldung.netty.customhandlersandlisteners.model;
|
||||
|
||||
import java.time.Instant;
|
||||
|
||||
public class Message {
|
||||
|
||||
private final Instant time;
|
||||
private final String user;
|
||||
private final String message;
|
||||
|
||||
public Message(String user, String message) {
|
||||
this.time = Instant.now();
|
||||
this.user = user;
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public Instant getTime() {
|
||||
return time;
|
||||
}
|
||||
|
||||
public String getUser() {
|
||||
return user;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return time + " - " + user + ": " + message;
|
||||
}
|
||||
|
||||
public static Message parse(String string) {
|
||||
String[] arr = string.split(";", 2);
|
||||
return new Message(arr[0], arr[1]);
|
||||
}
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
package com.baeldung.netty.customhandlersandlisteners.model;
|
||||
|
||||
public class OfflineMessage extends Message {
|
||||
|
||||
public OfflineMessage(String info) {
|
||||
super("system", "client went offline: " + info);
|
||||
}
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
package com.baeldung.netty.customhandlersandlisteners.model;
|
||||
|
||||
public class OnlineMessage extends Message {
|
||||
|
||||
public OnlineMessage(String info) {
|
||||
super("system", "client online: " + info);
|
||||
}
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
package com.baeldung.netty.customhandlersandlisteners;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import com.baeldung.netty.customhandlersandlisteners.handler.ClientEventHandler;
|
||||
import com.baeldung.netty.customhandlersandlisteners.handler.ServerEventHandler;
|
||||
|
||||
import io.netty.channel.embedded.EmbeddedChannel;
|
||||
|
||||
class ChatIntegrationTest {
|
||||
|
||||
private static final String MSG_1 = "Alice;Anyone there?!";
|
||||
private static final String MSG_2 = "Bob;Hi, Alice!";
|
||||
|
||||
@Test
|
||||
void whenMessagesWrittenToServer_thenMessagesConsumed() {
|
||||
EmbeddedChannel server = new EmbeddedChannel(new ServerEventHandler());
|
||||
|
||||
assertTrue(server.writeOutbound(MSG_1));
|
||||
assertTrue(server.writeOutbound(MSG_2));
|
||||
|
||||
assertEquals(2, server.outboundMessages()
|
||||
.size());
|
||||
|
||||
assertEquals(MSG_1, server.readOutbound()
|
||||
.toString());
|
||||
assertEquals(MSG_2, server.readOutbound()
|
||||
.toString());
|
||||
|
||||
server.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenClientReceivesMessages_thenMessagesConsumed() {
|
||||
EmbeddedChannel client = new EmbeddedChannel(new ClientEventHandler());
|
||||
|
||||
assertTrue(client.writeOutbound(MSG_1));
|
||||
assertTrue(client.writeOutbound(MSG_2));
|
||||
|
||||
assertEquals(2, client.outboundMessages()
|
||||
.size());
|
||||
|
||||
assertEquals(MSG_1, client.readOutbound()
|
||||
.toString());
|
||||
assertEquals(MSG_2, client.readOutbound()
|
||||
.toString());
|
||||
|
||||
client.close();
|
||||
}
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
package com.baeldung.netty.customhandlersandlisteners;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
|
||||
import java.time.Instant;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import com.baeldung.netty.customhandlersandlisteners.model.Message;
|
||||
|
||||
class MessageUnitTest {
|
||||
|
||||
@Test
|
||||
void whenBroadcastMessage_thenParsedSuccessfully() {
|
||||
String input = "Bob;Hello, world; go!";
|
||||
Message message = Message.parse(input);
|
||||
|
||||
assertEquals("Bob", message.getUser());
|
||||
assertEquals("Hello, world; go!", message.getMessage());
|
||||
assertNotNull(message.getTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenNewMessage_thenExpectedFormat() {
|
||||
Message message = new Message("Alice", "Testing");
|
||||
Instant time = message.getTime();
|
||||
|
||||
String expected = time + " - Alice: Testing";
|
||||
assertEquals(expected, message.toString());
|
||||
}
|
||||
}
|
@ -49,11 +49,11 @@
|
||||
|
||||
<properties>
|
||||
<jool.version>0.9.12</jool.version>
|
||||
<parallel-collectors.version>1.1.0</parallel-collectors.version>
|
||||
<parallel-collectors.version>2.6.0</parallel-collectors.version>
|
||||
<vavr.version>0.9.0</vavr.version>
|
||||
<eclipse-collections.version>8.2.0</eclipse-collections.version>
|
||||
<streamex.version>0.8.1</streamex.version>
|
||||
<protonpack.version>1.15</protonpack.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
||||
</project>
|
||||
|
@ -1,5 +1,6 @@
|
||||
package com.baeldung.parallel_collectors;
|
||||
|
||||
import com.pivovarit.collectors.ParallelCollectors;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Arrays;
|
||||
@ -12,13 +13,15 @@ import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static com.pivovarit.collectors.ParallelCollectors.parallel;
|
||||
import static com.pivovarit.collectors.ParallelCollectors.parallelOrdered;
|
||||
import static com.pivovarit.collectors.ParallelCollectors.parallelToCollection;
|
||||
import static com.pivovarit.collectors.ParallelCollectors.parallelToList;
|
||||
import static com.pivovarit.collectors.ParallelCollectors.parallelToMap;
|
||||
import static com.pivovarit.collectors.ParallelCollectors.parallelToOrderedStream;
|
||||
import static com.pivovarit.collectors.ParallelCollectors.parallelToStream;
|
||||
import static java.util.concurrent.CompletableFuture.completedFuture;
|
||||
import static java.util.stream.Collectors.toCollection;
|
||||
import static java.util.stream.Collectors.toList;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class ParallelCollectorsUnitTest {
|
||||
|
||||
@ -28,21 +31,21 @@ public class ParallelCollectorsUnitTest {
|
||||
|
||||
List<String> results = ids.parallelStream()
|
||||
.map(i -> fetchById(i))
|
||||
.collect(Collectors.toList());
|
||||
.collect(toList());
|
||||
|
||||
System.out.println(results);
|
||||
assertThat(results).containsExactly("user-1", "user-2", "user-3");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldProcessInParallelWithParallelCollectors() {
|
||||
public void shouldCollectInParallel() {
|
||||
ExecutorService executor = Executors.newFixedThreadPool(10);
|
||||
|
||||
List<Integer> ids = Arrays.asList(1, 2, 3);
|
||||
|
||||
CompletableFuture<List<String>> results = ids.stream()
|
||||
.collect(parallelToList(ParallelCollectorsUnitTest::fetchById, executor, 4));
|
||||
CompletableFuture<Stream<String>> results = ids.stream()
|
||||
.collect(parallel(ParallelCollectorsUnitTest::fetchById, executor, 4));
|
||||
|
||||
System.out.println(results.join());
|
||||
assertThat(results.join()).containsExactly("user-1", "user-2", "user-3");
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -51,11 +54,10 @@ public class ParallelCollectorsUnitTest {
|
||||
|
||||
List<Integer> ids = Arrays.asList(1, 2, 3);
|
||||
|
||||
List<String> results = ids.stream()
|
||||
.collect(parallelToList(ParallelCollectorsUnitTest::fetchById, executor, 4))
|
||||
.join();
|
||||
CompletableFuture<List<String>> results = ids.stream()
|
||||
.collect(parallel(ParallelCollectorsUnitTest::fetchById, toList(), executor, 4));
|
||||
|
||||
System.out.println(results); // [user-1, user-2, user-3]
|
||||
assertThat(results.join()).containsExactly("user-1", "user-2", "user-3");
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -64,11 +66,11 @@ public class ParallelCollectorsUnitTest {
|
||||
|
||||
List<Integer> ids = Arrays.asList(1, 2, 3);
|
||||
|
||||
List<String> results = ids.stream()
|
||||
.collect(parallelToCollection(i -> fetchById(i), LinkedList::new, executor, 4))
|
||||
.join();
|
||||
CompletableFuture<List<String>> results = ids.stream()
|
||||
.collect(parallel(i -> fetchById(i), toCollection(LinkedList::new), executor, 4));
|
||||
|
||||
System.out.println(results); // [user-1, user-2, user-3]
|
||||
assertThat(results.join())
|
||||
.containsExactly("user-1", "user-2", "user-3");
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -77,12 +79,13 @@ public class ParallelCollectorsUnitTest {
|
||||
|
||||
List<Integer> ids = Arrays.asList(1, 2, 3);
|
||||
|
||||
Map<Integer, List<String>> results = ids.stream()
|
||||
.collect(parallelToStream(i -> fetchById(i), executor, 4))
|
||||
.thenApply(stream -> stream.collect(Collectors.groupingBy(i -> i.length())))
|
||||
.join();
|
||||
CompletableFuture<Map<Integer, List<String>>> results = ids.stream()
|
||||
.collect(parallel(i -> fetchById(i), executor, 4))
|
||||
.thenApply(stream -> stream.collect(Collectors.groupingBy(String::length)));
|
||||
|
||||
System.out.println(results); // [user-1, user-2, user-3]
|
||||
assertThat(results.join())
|
||||
.hasSize(1)
|
||||
.containsEntry(6, Arrays.asList("user-1", "user-2", "user-3"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -91,9 +94,10 @@ public class ParallelCollectorsUnitTest {
|
||||
|
||||
List<Integer> ids = Arrays.asList(1, 2, 3);
|
||||
|
||||
ids.stream()
|
||||
.collect(parallel(ParallelCollectorsUnitTest::fetchByIdWithRandomDelay, executor, 4))
|
||||
.forEach(System.out::println);
|
||||
Stream<String> result = ids.stream()
|
||||
.collect(parallelToStream(ParallelCollectorsUnitTest::fetchByIdWithRandomDelay, executor, 4));
|
||||
|
||||
assertThat(result).contains("user-1", "user-2", "user-3");
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -102,9 +106,10 @@ public class ParallelCollectorsUnitTest {
|
||||
|
||||
List<Integer> ids = Arrays.asList(1, 2, 3);
|
||||
|
||||
ids.stream()
|
||||
.collect(parallelOrdered(ParallelCollectorsUnitTest::fetchByIdWithRandomDelay, executor, 4))
|
||||
.forEach(System.out::println);
|
||||
Stream<String> result = ids.stream()
|
||||
.collect(parallelToOrderedStream(ParallelCollectorsUnitTest::fetchByIdWithRandomDelay, executor, 4));
|
||||
|
||||
assertThat(result).containsExactly("user-1", "user-2", "user-3");
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -113,24 +118,14 @@ public class ParallelCollectorsUnitTest {
|
||||
|
||||
List<Integer> ids = Arrays.asList(1, 2, 3);
|
||||
|
||||
Map<Integer, String> results = ids.stream()
|
||||
.collect(parallelToMap(i -> i, ParallelCollectorsUnitTest::fetchById, executor, 4))
|
||||
.join();
|
||||
CompletableFuture<Map<Integer, String>> results = ids.stream()
|
||||
.collect(parallel(i -> i, Collectors.toMap(i -> i, ParallelCollectorsUnitTest::fetchById), executor, 4));
|
||||
|
||||
System.out.println(results); // {1=user-1, 2=user-2, 3=user-3}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldCollectToTreeMap() {
|
||||
ExecutorService executor = Executors.newFixedThreadPool(10);
|
||||
|
||||
List<Integer> ids = Arrays.asList(1, 2, 3);
|
||||
|
||||
Map<Integer, String> results = ids.stream()
|
||||
.collect(parallelToMap(i -> i, ParallelCollectorsUnitTest::fetchById, TreeMap::new, executor, 4))
|
||||
.join();
|
||||
|
||||
System.out.println(results); // {1=user-1, 2=user-2, 3=user-3}
|
||||
assertThat(results.join())
|
||||
.hasSize(3)
|
||||
.containsEntry(1, "user-1")
|
||||
.containsEntry(2, "user-2")
|
||||
.containsEntry(3, "user-3");
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -139,11 +134,24 @@ public class ParallelCollectorsUnitTest {
|
||||
|
||||
List<Integer> ids = Arrays.asList(1, 2, 3);
|
||||
|
||||
Map<Integer, String> results = ids.stream()
|
||||
.collect(parallelToMap(i -> i, ParallelCollectorsUnitTest::fetchById, TreeMap::new, (s1, s2) -> s1, executor, 4))
|
||||
.join();
|
||||
CompletableFuture<Map<Integer, String>> results = ids.stream()
|
||||
.collect(parallel(i -> i, Collectors.toMap(i -> i, ParallelCollectorsUnitTest::fetchById, (u1, u2) -> u1, TreeMap::new), executor, 4));
|
||||
|
||||
System.out.println(results); // {1=user-1, 2=user-2, 3=user-3}
|
||||
assertThat(results.join())
|
||||
.hasSize(3)
|
||||
.containsEntry(1, "user-1")
|
||||
.containsEntry(2, "user-2")
|
||||
.containsEntry(3, "user-3");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldCollectListOfFutures() {
|
||||
List<CompletableFuture<Integer>> futures = Arrays.asList(completedFuture(1), completedFuture(2), completedFuture(3));
|
||||
|
||||
CompletableFuture<List<Integer>> result = futures.stream()
|
||||
.collect(ParallelCollectors.toFuture());
|
||||
|
||||
assertThat(result.join()).containsExactly(1, 2, 3);
|
||||
}
|
||||
|
||||
private static String fetchById(int id) {
|
||||
|
@ -20,6 +20,7 @@
|
||||
<module>logback</module>
|
||||
<module>log-mdc</module>
|
||||
<module>tinylog2</module>
|
||||
<module>logging-techniques</module>
|
||||
</modules>
|
||||
|
||||
</project>
|
@ -19,6 +19,7 @@
|
||||
</modules>
|
||||
|
||||
<!--comment section below to provoke version collision in project-collision module -->
|
||||
<!--Don't Update the version here as it shows the collision when compiling with maven.-->
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
|
@ -12,6 +12,7 @@
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
<!--Don't Update the version here as it shows the collision when compiling with maven.-->
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
|
@ -12,6 +12,7 @@
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
<!--Don't Update the version here as it shows the collision when compiling with maven.-->
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
|
@ -90,7 +90,7 @@
|
||||
</build>
|
||||
|
||||
<properties>
|
||||
<okhttp.version>4.12.0</okhttp.version>
|
||||
<okhttp.version>5.0.0-alpha.12</okhttp.version>
|
||||
<javax.json.version>1.1</javax.json.version>
|
||||
<osgi.version>6.0.0</osgi.version>
|
||||
<maven-bundle-plugin.version>3.3.0</maven-bundle-plugin.version>
|
||||
|
@ -130,7 +130,7 @@
|
||||
<hibernate.version>6.2.0.Final</hibernate.version>
|
||||
<postgresql.version>42.5.4</postgresql.version>
|
||||
<hsqldb.version>2.7.1</hsqldb.version>
|
||||
<testcontainers.version>1.16.3</testcontainers.version>
|
||||
<testcontainers.version>1.19.6</testcontainers.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
||||
|
@ -3,3 +3,4 @@
|
||||
- [List vs. Set in @OneToMany JPA](https://www.baeldung.com/spring-jpa-onetomany-list-vs-set)
|
||||
- [N+1 Problem in Hibernate and Spring Data JPA](https://www.baeldung.com/spring-hibernate-n1-problem)
|
||||
- [Get All Results at Once in a Spring Boot Paged Query Method](https://www.baeldung.com/spring-boot-paged-query-all-results)
|
||||
- [Calling Custom Database Functions With JPA and Spring Boot](https://www.baeldung.com/spring-data-jpa-custom-database-functions)
|
||||
|
@ -0,0 +1,2 @@
|
||||
### Relevant Articles:
|
||||
- [@DataJpaTest and Repository Class in JUnit](https://www.baeldung.com/junit-datajpatest-repository)
|
@ -0,0 +1,86 @@
|
||||
package com.baeldung.queryhint;
|
||||
|
||||
import java.sql.Date;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.NamedQueries;
|
||||
import javax.persistence.NamedQuery;
|
||||
import javax.persistence.QueryHint;
|
||||
import javax.persistence.Table;
|
||||
|
||||
import org.springframework.data.jpa.repository.QueryHints;
|
||||
|
||||
@Entity
|
||||
@Table(name = "app_user")
|
||||
@NamedQueries({ @NamedQuery(name = "selectEmployee", query = "SELECT e FROM Employee e", hints = @QueryHint(name = "org.hibernate.fetchSize", value = "50")) })
|
||||
public class Employee {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
private String username;
|
||||
private String password;
|
||||
private String gender;
|
||||
private String name;
|
||||
private Date joinDate;
|
||||
private int age;
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public void setUsername(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
public void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
public String getGender() {
|
||||
return gender;
|
||||
}
|
||||
|
||||
public void setGender(String gender) {
|
||||
this.gender = gender;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Date getJoinDate() {
|
||||
return joinDate;
|
||||
}
|
||||
|
||||
public void setJoinDate(Date joinDate) {
|
||||
this.joinDate = joinDate;
|
||||
}
|
||||
|
||||
public int getAge() {
|
||||
return age;
|
||||
}
|
||||
|
||||
public void setAge(int age) {
|
||||
this.age = age;
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
package com.baeldung.queryhint;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication
|
||||
public class EmployeeApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(EmployeeApplication.class);
|
||||
}
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
package com.baeldung.queryhint;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.persistence.QueryHint;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.QueryHints;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@Repository
|
||||
public interface EmployeeRepository extends JpaRepository<Employee, Long> {
|
||||
|
||||
@QueryHints(value = { @QueryHint(name = "org.hibernate.fetchSize", value = "50") })
|
||||
List<Employee> findByGender(String gender);
|
||||
|
||||
@QueryHints(value = { @QueryHint(name = "javax.persistence.query.timeout", value = "5000") })
|
||||
List<Employee> findActiveEmployees(long inactiveDaysThreshold);
|
||||
|
||||
@QueryHints(value = { @QueryHint(name = "jakarta.persistence.cache.retrieveMode", value = "USE"),
|
||||
@QueryHint(name = "jakarta.persistence.cache.storeMode", value = "USE") })
|
||||
List<Employee> findEmployeesByName(String name);
|
||||
|
||||
@QueryHints(@QueryHint(name = "org.hibernate.readOnly", value = "true"))
|
||||
Employee findByUsername(String username);
|
||||
|
||||
@QueryHints(value = { @QueryHint(name = "org.hibernate.comment", value = "Retrieve employee older than specified age\"") })
|
||||
List<Employee> findByAgeGreaterThan(int age);
|
||||
}
|
@ -34,7 +34,7 @@
|
||||
<dependency>
|
||||
<groupId>org.testcontainers</groupId>
|
||||
<artifactId>postgresql</artifactId>
|
||||
<version>${testcontainers.postgresql.version}</version>
|
||||
<version>${testcontainers.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@ -65,8 +65,7 @@
|
||||
|
||||
<properties>
|
||||
<start-class>com.baeldung.boot.Application</start-class>
|
||||
<testcontainers.postgresql.version>1.10.6</testcontainers.postgresql.version>
|
||||
<postgresql.version>42.2.5</postgresql.version>
|
||||
<testcontainers.version>1.19.6</testcontainers.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
@ -28,10 +28,6 @@
|
||||
<artifactId>guava</artifactId>
|
||||
<version>${guava.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.h2database</groupId>
|
||||
<artifactId>h2</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.ttddyy</groupId>
|
||||
<artifactId>datasource-proxy</artifactId>
|
||||
@ -58,7 +54,7 @@
|
||||
|
||||
<properties>
|
||||
<datasource-proxy.version>1.4.1</datasource-proxy.version>
|
||||
<testcontainers.version>1.12.2</testcontainers.version>
|
||||
<testcontainers.version>1.19.6</testcontainers.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
@ -98,7 +98,7 @@
|
||||
|
||||
<properties>
|
||||
<mapstruct.version>1.6.0.Beta1</mapstruct.version>
|
||||
<testcontainers.version>1.19.1</testcontainers.version>
|
||||
<testcontainers.version>1.19.6</testcontainers.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
@ -65,8 +65,7 @@
|
||||
|
||||
<properties>
|
||||
<start-class>com.baeldung.boot.Application</start-class>
|
||||
<testcontainers.postgresql.version>1.10.6</testcontainers.postgresql.version>
|
||||
<postgresql.version>42.2.5</postgresql.version>
|
||||
<testcontainers.postgresql.version>1.19.6</testcontainers.postgresql.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
@ -76,6 +76,16 @@
|
||||
<artifactId>logback-classic</artifactId>
|
||||
<version>${logback.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.hypersistence</groupId>
|
||||
<artifactId>hypersistence-utils-hibernate-62</artifactId>
|
||||
<version>${hypersistence-utils.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.vladmihalcea</groupId>
|
||||
<artifactId>db-util</artifactId>
|
||||
<version>${db.util.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
@ -130,6 +140,8 @@
|
||||
<properties>
|
||||
<hypersistance-utils-hibernate-55.version>3.7.0</hypersistance-utils-hibernate-55.version>
|
||||
<postgresql.version>42.7.1</postgresql.version>
|
||||
<db.util.version>1.0.7</db.util.version>
|
||||
<hypersistence-utils.version>3.7.0</hypersistence-utils.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
@ -0,0 +1,51 @@
|
||||
package com.baeldung.spring.data.persistence.findvsget.entity;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.OneToMany;
|
||||
import javax.persistence.OneToOne;
|
||||
import javax.persistence.Table;
|
||||
|
||||
@Entity
|
||||
@Table(name = "group")
|
||||
public class Group {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
private String name;
|
||||
@OneToOne
|
||||
private User administrator;
|
||||
@OneToMany(mappedBy = "id")
|
||||
private Set<User> users = new HashSet<>();
|
||||
public void addUser(User user) {
|
||||
users.add(user);
|
||||
}
|
||||
public Set<User> getUsers() {
|
||||
return users;
|
||||
}
|
||||
public void setUsers(Set<User> users) {
|
||||
this.users = users;
|
||||
}
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
public User getAdministrator() {
|
||||
return administrator;
|
||||
}
|
||||
public void setAdministrator(User administrator) {
|
||||
this.administrator = administrator;
|
||||
}
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
package com.baeldung.spring.data.persistence.findvsget.repository;
|
||||
|
||||
import com.baeldung.spring.data.persistence.findvsget.entity.Group;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
public interface GroupRepository extends JpaRepository<Group, Long> {
|
||||
|
||||
}
|
@ -0,0 +1,87 @@
|
||||
package com.baeldung.spring.data.persistence.findvsget;
|
||||
|
||||
import static com.vladmihalcea.sql.SQLStatementCountValidator.assertInsertCount;
|
||||
import static com.vladmihalcea.sql.SQLStatementCountValidator.assertSelectCount;
|
||||
import static org.assertj.core.api.AssertionsForClassTypes.assertThatExceptionOfType;
|
||||
import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat;
|
||||
|
||||
import com.baeldung.spring.data.persistence.findvsget.entity.Group;
|
||||
import com.baeldung.spring.data.persistence.findvsget.entity.User;
|
||||
import com.baeldung.spring.data.persistence.findvsget.repository.GroupRepository;
|
||||
import com.baeldung.spring.data.persistence.findvsget.repository.SimpleUserRepository;
|
||||
import io.hypersistence.utils.jdbc.validator.SQLStatementCountValidator;
|
||||
import java.util.Optional;
|
||||
import org.hibernate.LazyInitializationException;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.dao.DataIntegrityViolationException;
|
||||
|
||||
class AdditionalLookupIntegrationTest extends DatabaseConfigurationBaseIntegrationTest {
|
||||
|
||||
@Autowired
|
||||
private SimpleUserRepository userRepository;
|
||||
@Autowired
|
||||
private GroupRepository groupRepository;
|
||||
|
||||
@BeforeEach
|
||||
void setup() {
|
||||
SQLStatementCountValidator.reset();
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenEmptyGroup_whenAssigningAdministratorWithGetByReference_thenNoAdditionalLookupHappens() {
|
||||
User user = userRepository.getReferenceById(1L);
|
||||
Group group = new Group();
|
||||
group.setAdministrator(user);
|
||||
groupRepository.save(group);
|
||||
assertSelectCount(0);
|
||||
assertInsertCount(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenEmptyGroup_whenAssigningIncorrectAdministratorWithGetByReference_thenErrorIsThrown() {
|
||||
User user = userRepository.getReferenceById(-1L);
|
||||
Group group = new Group();
|
||||
group.setAdministrator(user);
|
||||
assertThatExceptionOfType(DataIntegrityViolationException.class)
|
||||
.isThrownBy(() -> {
|
||||
groupRepository.save(group);
|
||||
});
|
||||
assertSelectCount(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenEmptyGroup_whenAssigningAdministratorWithFindBy_thenAdditionalLookupHappens() {
|
||||
Optional<User> optionalUser = userRepository.findById(1L);
|
||||
assertThat(optionalUser).isPresent();
|
||||
User user = optionalUser.get();
|
||||
Group group = new Group();
|
||||
group.setAdministrator(user);
|
||||
groupRepository.save(group);
|
||||
assertSelectCount(2);
|
||||
assertInsertCount(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenEmptyGroup_whenAddingUserWithGetByReference_thenTryToAccessInternalsAndThrowError() {
|
||||
User user = userRepository.getReferenceById(1L);
|
||||
Group group = new Group();
|
||||
assertThatExceptionOfType(LazyInitializationException.class)
|
||||
.isThrownBy(() -> {
|
||||
group.addUser(user);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenEmptyGroup_whenAddingUserWithFindBy_thenAdditionalLookupHappens() {
|
||||
Optional<User> optionalUser = userRepository.findById(1L);
|
||||
assertThat(optionalUser).isPresent();
|
||||
User user = optionalUser.get();
|
||||
Group group = new Group();
|
||||
group.addUser(user);
|
||||
groupRepository.save(group);
|
||||
assertSelectCount(1);
|
||||
assertInsertCount(1);
|
||||
}
|
||||
}
|
@ -4,7 +4,9 @@ import static com.baeldung.spring.data.persistence.findvsget.UserProvider.userSo
|
||||
import static org.assertj.core.api.Assumptions.assumeThat;
|
||||
|
||||
import com.baeldung.spring.data.persistence.findvsget.entity.User;
|
||||
import com.baeldung.spring.data.persistence.findvsget.repository.GroupRepository;
|
||||
import com.baeldung.spring.data.persistence.findvsget.repository.SimpleUserRepository;
|
||||
import com.baeldung.spring.data.persistence.util.TestConfig;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
@ -13,7 +15,7 @@ import org.junit.jupiter.params.provider.Arguments;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
|
||||
@SpringBootTest(classes = ApplicationConfig.class, properties = {
|
||||
@SpringBootTest(classes = {ApplicationConfig.class, TestConfig.class}, properties = {
|
||||
"spring.jpa.generate-ddl=true",
|
||||
"spring.jpa.show-sql=false"
|
||||
})
|
||||
@ -22,7 +24,10 @@ abstract class DatabaseConfigurationBaseIntegrationTest {
|
||||
private static final int NUMBER_OF_USERS = 10;
|
||||
|
||||
@Autowired
|
||||
private SimpleUserRepository repository;
|
||||
private SimpleUserRepository userRepository;
|
||||
|
||||
@Autowired
|
||||
private GroupRepository groupRepository;
|
||||
|
||||
@BeforeEach
|
||||
void populateDatabase() {
|
||||
@ -30,13 +35,14 @@ abstract class DatabaseConfigurationBaseIntegrationTest {
|
||||
.map(Arguments::get)
|
||||
.map(s -> new User(((Long) s[0]), s[1].toString(), s[2].toString()))
|
||||
.collect(Collectors.toList());
|
||||
repository.saveAll(users);
|
||||
assumeThat(repository.findAll()).hasSize(NUMBER_OF_USERS);
|
||||
userRepository.saveAll(users);
|
||||
assumeThat(userRepository.findAll()).hasSize(NUMBER_OF_USERS);
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void clearDatabase() {
|
||||
repository.deleteAll();
|
||||
groupRepository.deleteAll();
|
||||
userRepository.deleteAll();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,36 @@
|
||||
package com.baeldung.spring.data.persistence.util;
|
||||
|
||||
import io.hypersistence.utils.logging.InlineQueryLogEntryCreator;
|
||||
import javax.sql.DataSource;
|
||||
import net.ttddyy.dsproxy.listener.ChainListener;
|
||||
import net.ttddyy.dsproxy.listener.DataSourceQueryCountListener;
|
||||
import net.ttddyy.dsproxy.listener.logging.SLF4JQueryLoggingListener;
|
||||
import net.ttddyy.dsproxy.support.ProxyDataSourceBuilder;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class DataSourceWrapper implements BeanPostProcessor {
|
||||
|
||||
public Object postProcessBeforeInitialization(Object bean, String beanName) {
|
||||
return bean;
|
||||
}
|
||||
|
||||
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
|
||||
if (bean instanceof DataSource) {
|
||||
DataSource originalDataSource = ((DataSource) bean);
|
||||
ChainListener listener = new ChainListener();
|
||||
SLF4JQueryLoggingListener loggingListener = new SLF4JQueryLoggingListener();
|
||||
loggingListener.setQueryLogEntryCreator(new InlineQueryLogEntryCreator());
|
||||
listener.addListener(loggingListener);
|
||||
listener.addListener(new DataSourceQueryCountListener());
|
||||
return ProxyDataSourceBuilder
|
||||
.create(originalDataSource)
|
||||
.name("DS-Proxy")
|
||||
.listener(listener)
|
||||
.build();
|
||||
}
|
||||
return bean;
|
||||
}
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
package com.baeldung.spring.data.persistence.util;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
public class TestConfig {
|
||||
|
||||
@Bean
|
||||
public DataSourceWrapper dataSourceWrapper() {
|
||||
return new DataSourceWrapper();
|
||||
}
|
||||
|
||||
}
|
9
pom.xml
9
pom.xml
@ -8,9 +8,6 @@
|
||||
<artifactId>parent-modules</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
<name>parent-modules</name>
|
||||
<modules>
|
||||
<module>libraries-data-io-2</module>
|
||||
</modules>
|
||||
|
||||
<packaging>pom</packaging>
|
||||
|
||||
@ -402,8 +399,6 @@
|
||||
|
||||
<modules>
|
||||
<module>spring-4</module>
|
||||
<module>spring-6</module>
|
||||
|
||||
<module>spring-cloud-modules</module>
|
||||
<!-- <module>spring-cloud-cli</module> --> <!-- Not a maven project -->
|
||||
|
||||
@ -803,6 +798,7 @@
|
||||
<module>spring-5-webflux-2</module>
|
||||
<module>spring-5-webflux</module>
|
||||
<module>spring-5</module>
|
||||
<module>spring-6</module>
|
||||
<module>spring-6-rsocket</module>
|
||||
<module>spring-activiti</module>
|
||||
<module>spring-actuator</module>
|
||||
@ -876,6 +872,7 @@
|
||||
<module>xml-2</module>
|
||||
<module>xml</module>
|
||||
<module>xstream</module>
|
||||
<module>libraries-data-io-2</module>
|
||||
</modules>
|
||||
|
||||
<properties>
|
||||
@ -1048,6 +1045,7 @@
|
||||
<module>spring-5-webflux-2</module>
|
||||
<module>spring-5-webflux</module>
|
||||
<module>spring-5</module>
|
||||
<module>spring-6</module>
|
||||
<module>spring-6-rsocket</module>
|
||||
<module>spring-activiti</module>
|
||||
<module>spring-actuator</module>
|
||||
@ -1121,6 +1119,7 @@
|
||||
<module>xml-2</module>
|
||||
<module>xml</module>
|
||||
<module>xstream</module>
|
||||
<module>libraries-data-io-2</module>
|
||||
</modules>
|
||||
|
||||
<properties>
|
||||
|
@ -17,7 +17,7 @@
|
||||
<module>apache-shiro</module>
|
||||
<module>cas</module>
|
||||
<module>cloud-foundry-uaa</module>
|
||||
<!-- <module>java-ee-8-security-api</module>-->
|
||||
<!-- <module>java-ee-8-security-api</module>--> <!--JAVA-31843-->
|
||||
<module>jee-7-security</module>
|
||||
<module>jjwt</module>
|
||||
<module>jwt</module>
|
||||
|
@ -86,7 +86,7 @@
|
||||
<dependency>
|
||||
<groupId>com.squareup.okhttp3</groupId>
|
||||
<artifactId>mockwebserver</artifactId>
|
||||
<version>4.12.0</version> <!-- this can be removed when we migrate spring-boot-dependencies to the latest version -->
|
||||
<version>${mockwebserver.version}</version> <!-- this can be removed when we migrate spring-boot-dependencies to the latest version -->
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
@ -125,6 +125,7 @@
|
||||
<reactor.version>3.4.5</reactor.version>
|
||||
<caffeine.version>3.1.8</caffeine.version>
|
||||
<testcontainers-mongodb.version>1.16.2</testcontainers-mongodb.version>
|
||||
<mockwebserver.version>5.0.0-alpha.12</mockwebserver.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
@ -75,7 +75,12 @@
|
||||
<dependency>
|
||||
<groupId>com.squareup.okhttp3</groupId>
|
||||
<artifactId>mockwebserver</artifactId>
|
||||
<version>4.12.0</version> <!-- this can be removed when we migrate spring-boot-dependencies to the latest version -->
|
||||
<version>${mockwebserver.version}</version> <!-- this can be removed when we migrate spring-boot-dependencies to the latest version -->
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jetbrains.kotlin</groupId>
|
||||
<artifactId>kotlin-stdlib</artifactId>
|
||||
<version>${kotlin-stdlib.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
@ -88,4 +93,9 @@
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<properties>
|
||||
<mockwebserver.version>5.0.0-alpha.12</mockwebserver.version>
|
||||
<kotlin-stdlib.version>2.0.0-Beta4</kotlin-stdlib.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
@ -37,6 +37,10 @@
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-hateoas</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-webflux</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.json.bind</groupId>
|
||||
<artifactId>javax.json.bind-api</artifactId>
|
||||
@ -96,6 +100,12 @@
|
||||
<artifactId>spring-restdocs-restassured</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.restdocs</groupId>
|
||||
<artifactId>spring-restdocs-webtestclient</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.zaxxer</groupId>
|
||||
<artifactId>HikariCP</artifactId>
|
||||
|
@ -0,0 +1,12 @@
|
||||
package com.baeldung.queryparamdoc;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration;
|
||||
|
||||
@SpringBootApplication(exclude = SecurityAutoConfiguration.class)
|
||||
public class Application {
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(Application.class, args);
|
||||
}
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
package com.baeldung.queryparamdoc;
|
||||
|
||||
public class Book {
|
||||
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
package com.baeldung.queryparamdoc;
|
||||
|
||||
import java.util.List;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/books")
|
||||
public class BookController {
|
||||
|
||||
private final BookService service;
|
||||
|
||||
public BookController(BookService service) {
|
||||
this.service = service;
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
public List<Book> getBooks(@RequestParam(name = "page") Integer page) {
|
||||
return service.getBooks(page);
|
||||
}
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
package com.baeldung.queryparamdoc;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class BookService {
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public List<Book> getBooks(Integer page) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
package com.baeldung.queryparamdoc;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document;
|
||||
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.documentationConfiguration;
|
||||
import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessRequest;
|
||||
import static org.springframework.restdocs.operation.preprocess.Preprocessors.preprocessResponse;
|
||||
import static org.springframework.restdocs.operation.preprocess.Preprocessors.prettyPrint;
|
||||
import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName;
|
||||
import static org.springframework.restdocs.request.RequestDocumentation.requestParameters;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.webAppContextSetup;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration;
|
||||
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
|
||||
import org.springframework.restdocs.RestDocumentationContextProvider;
|
||||
import org.springframework.restdocs.RestDocumentationExtension;
|
||||
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
|
||||
@ExtendWith({RestDocumentationExtension.class, SpringExtension.class})
|
||||
@WebMvcTest(controllers = {BookController.class, BookService.class},
|
||||
excludeAutoConfiguration = SecurityAutoConfiguration.class)
|
||||
class BookControllerMvcIntegrationTest {
|
||||
|
||||
@Autowired
|
||||
private MockMvc mockMvc;
|
||||
|
||||
@BeforeEach
|
||||
public void setUp(WebApplicationContext webApplicationContext, RestDocumentationContextProvider restDocumentation) {
|
||||
this.mockMvc = webAppContextSetup(webApplicationContext)
|
||||
.apply(documentationConfiguration(restDocumentation))
|
||||
.alwaysDo(document("{method-name}", preprocessRequest(prettyPrint()), preprocessResponse(prettyPrint())))
|
||||
.build();
|
||||
}
|
||||
|
||||
@Test
|
||||
void smokeTest() {
|
||||
assertThat(mockMvc).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenEndpoint_whenSendGetRequest_thenSuccessfulResponse() throws Exception {
|
||||
mockMvc.perform(get("/books?page=2"))
|
||||
.andExpect(status().isOk())
|
||||
.andDo(document("books",
|
||||
requestParameters(parameterWithName("page").description("The page to retrieve"))));
|
||||
}
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
package com.baeldung.queryparamdoc;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName;
|
||||
import static org.springframework.restdocs.request.RequestDocumentation.requestParameters;
|
||||
import static org.springframework.restdocs.webtestclient.WebTestClientRestDocumentation.document;
|
||||
import static org.springframework.restdocs.webtestclient.WebTestClientRestDocumentation.documentationConfiguration;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.autoconfigure.web.reactive.WebFluxTest;
|
||||
import org.springframework.boot.test.context.TestConfiguration;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.restdocs.RestDocumentationContextProvider;
|
||||
import org.springframework.restdocs.RestDocumentationExtension;
|
||||
import org.springframework.security.test.context.support.WithMockUser;
|
||||
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||
import org.springframework.test.web.reactive.server.WebTestClient;
|
||||
|
||||
@ExtendWith({RestDocumentationExtension.class, SpringExtension.class})
|
||||
@WebFluxTest
|
||||
class BookControllerReactiveIntegrationTest {
|
||||
|
||||
@Autowired
|
||||
private WebTestClient webTestClient;
|
||||
|
||||
@BeforeEach
|
||||
public void setUp(ApplicationContext webApplicationContext, RestDocumentationContextProvider restDocumentation) {
|
||||
this.webTestClient = WebTestClient.bindToApplicationContext(webApplicationContext)
|
||||
.configureClient()
|
||||
.filter(documentationConfiguration(restDocumentation))
|
||||
.build();
|
||||
}
|
||||
|
||||
@Test
|
||||
void smokeTest() {
|
||||
assertThat(webTestClient).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockUser
|
||||
void givenEndpoint_whenSendGetRequest_thenSuccessfulResponse() {
|
||||
webTestClient.get().uri("/books?page=2")
|
||||
.exchange().expectStatus().isOk().expectBody()
|
||||
.consumeWith(document("books",
|
||||
requestParameters(parameterWithName("page").description("The page to retrieve"))));
|
||||
}
|
||||
|
||||
@TestConfiguration
|
||||
public static class TestConfig {
|
||||
|
||||
@Bean
|
||||
BookService bookService() {
|
||||
return new BookService();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
package com.baeldung.queryparamdoc;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.hamcrest.core.Is.is;
|
||||
import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName;
|
||||
import static org.springframework.restdocs.request.RequestDocumentation.requestParameters;
|
||||
import static org.springframework.restdocs.restassured3.RestAssuredRestDocumentation.document;
|
||||
import static org.springframework.restdocs.restassured3.RestAssuredRestDocumentation.documentationConfiguration;
|
||||
|
||||
import io.restassured.RestAssured;
|
||||
import io.restassured.builder.RequestSpecBuilder;
|
||||
import io.restassured.specification.RequestSpecification;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureWebMvc;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
|
||||
import org.springframework.boot.test.web.server.LocalServerPort;
|
||||
import org.springframework.restdocs.RestDocumentationContextProvider;
|
||||
import org.springframework.restdocs.RestDocumentationExtension;
|
||||
import org.springframework.security.test.context.support.WithMockUser;
|
||||
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||
|
||||
@ExtendWith({RestDocumentationExtension.class, SpringExtension.class})
|
||||
@AutoConfigureWebMvc
|
||||
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
|
||||
class BookControllerRestAssuredIntegrationTest {
|
||||
|
||||
private RequestSpecification spec;
|
||||
|
||||
@BeforeEach
|
||||
void setUp(RestDocumentationContextProvider restDocumentation, @LocalServerPort int port) {
|
||||
this.spec = new RequestSpecBuilder().addFilter(documentationConfiguration(restDocumentation))
|
||||
.setPort(port)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Test
|
||||
void smokeTest() {
|
||||
assertThat(spec).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockUser
|
||||
void givenEndpoint_whenSendGetRequest_thenSuccessfulResponse() {
|
||||
RestAssured.given(this.spec).filter(document("users", requestParameters(
|
||||
parameterWithName("page").description("The page to retrieve"))))
|
||||
.when().get("/books?page=2")
|
||||
.then().assertThat().statusCode(is(200));
|
||||
}
|
||||
}
|
@ -50,6 +50,7 @@
|
||||
<module>spring-boot-keycloak-2</module>
|
||||
<!-- <module>spring-boot-libraries</module>--> <!-- failing after upgrading to spring boot 3.2.x -->
|
||||
<!-- <module>spring-boot-libraries-2</module>--> <!-- failing after upgrading to spring boot 3.2.x -->
|
||||
<module>spring-boot-libraries-3</module>
|
||||
<module>spring-boot-process-automation</module>
|
||||
<module>spring-boot-logging-logback</module>
|
||||
<module>spring-boot-logging-log4j2</module>
|
||||
|
@ -1,3 +1,4 @@
|
||||
## Relevant Articles
|
||||
- [Built-in Testcontainers Support in Spring Boot](https://www.baeldung.com/spring-boot-built-in-testcontainers)
|
||||
- [How to Reuse Testcontainers in Java](https://www.baeldung.com/java-reuse-testcontainers)
|
||||
- [Testcontainers Desktop](https://www.baeldung.com/testcontainers-desktop)
|
||||
|
@ -56,6 +56,11 @@
|
||||
<artifactId>problem-spring-web</artifactId>
|
||||
<version>${problem-spring-web.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.zalando</groupId>
|
||||
<artifactId>jackson-datatype-problem</artifactId>
|
||||
<version>${jackson-datatype-problem.version}</version>
|
||||
</dependency>
|
||||
<!-- ShedLock -->
|
||||
<dependency>
|
||||
<groupId>net.javacrumbs.shedlock</groupId>
|
||||
@ -217,21 +222,22 @@
|
||||
<!-- The main class to start by executing java -jar -->
|
||||
<start-class>com.baeldung.graphql.DemoApplication</start-class>
|
||||
<tomee-servlet-api.version>8.5.11</tomee-servlet-api.version>
|
||||
<togglz.version>2.4.1.Final</togglz.version>
|
||||
<togglz.version>4.4.0</togglz.version>
|
||||
<rome.version>1.9.0</rome.version>
|
||||
<chaos.monkey.version>2.0.0</chaos.monkey.version>
|
||||
<graphql-spring-boot-starter.version>5.0.2</graphql-spring-boot-starter.version>
|
||||
<graphql-java-tools.version>5.2.4</graphql-java-tools.version>
|
||||
<git-commit-id-plugin.version>2.2.4</git-commit-id-plugin.version>
|
||||
<modelmapper.version>3.2.0</modelmapper.version>
|
||||
<problem-spring-web.version>0.23.0</problem-spring-web.version>
|
||||
<problem-spring-web.version>0.29.1</problem-spring-web.version>
|
||||
<jackson-datatype-problem.version>0.27.1</jackson-datatype-problem.version>
|
||||
<shedlock.version>5.10.0</shedlock.version>
|
||||
<barbecue.version>1.5-beta1</barbecue.version>
|
||||
<barcode4j.version>2.1</barcode4j.version>
|
||||
<qrgen.version>2.6.0</qrgen.version>
|
||||
<zxing.version>3.3.0</zxing.version>
|
||||
<bucket4j.version>8.1.0</bucket4j.version>
|
||||
<bucket4j-spring-boot-starter.version>0.8.1</bucket4j-spring-boot-starter.version>
|
||||
<bucket4j.version>8.9.0</bucket4j.version>
|
||||
<bucket4j-spring-boot-starter.version>0.10.3</bucket4j-spring-boot-starter.version>
|
||||
<caffeine.version>3.1.8</caffeine.version>
|
||||
</properties>
|
||||
|
||||
|
@ -2,8 +2,8 @@ package com.baeldung.boot.problem.configuration;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.zalando.problem.ProblemModule;
|
||||
import org.zalando.problem.validation.ConstraintViolationProblemModule;
|
||||
import org.zalando.problem.jackson.ProblemModule;
|
||||
import org.zalando.problem.violations.ConstraintViolationProblemModule;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
|
@ -22,10 +22,11 @@ public class SecurityConfiguration {
|
||||
@Bean
|
||||
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
||||
return http.csrf(AbstractHttpConfigurer::disable)
|
||||
.authorizeHttpRequests(request -> request.requestMatchers(new AntPathRequestMatcher("/"))
|
||||
.authorizeHttpRequests(request -> request.requestMatchers(new AntPathRequestMatcher("/tasks/**"))
|
||||
.permitAll())
|
||||
.exceptionHandling(exceptionHandling -> exceptionHandling.authenticationEntryPoint(problemSupport)
|
||||
.accessDeniedHandler(problemSupport))
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@ -64,6 +65,7 @@ public class ProblemDemoControllerIntegrationTest {
|
||||
.andExpect(status().isNotImplemented());
|
||||
}
|
||||
|
||||
@Ignore
|
||||
@Test
|
||||
public void whenMakeDeleteCall_thenReturnForbiddenProblemResponse() throws Exception {
|
||||
mockMvc.perform(delete("/tasks/2").contentType(MediaType.APPLICATION_PROBLEM_JSON_VALUE))
|
||||
|
@ -1,6 +1,9 @@
|
||||
package com.baeldung.spring.servicevalidation.controller;
|
||||
|
||||
import jakarta.validation.ConstraintViolation;
|
||||
import jakarta.validation.ConstraintViolationException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
@ -15,8 +18,12 @@ public class UserAccountController {
|
||||
private UserAccountService service;
|
||||
|
||||
@PostMapping("/addUserAccount")
|
||||
public Object addUserAccount(@RequestBody UserAccount userAccount) {
|
||||
return service.addUserAccount(userAccount);
|
||||
public ResponseEntity<?> addUserAccount(@RequestBody UserAccount userAccount) {
|
||||
try {
|
||||
return ResponseEntity.ok(service.addUserAccount(userAccount));
|
||||
} catch(ConstraintViolationException e) {
|
||||
return ResponseEntity.badRequest().body(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -2,3 +2,4 @@
|
||||
|
||||
### Relevant Articles:
|
||||
- [Introduction to Spring Cloud AWS 3.0 – SQS Integration](https://www.baeldung.com/java-spring-cloud-aws-v3-intro)
|
||||
- [Message Acknowledgement in Spring Cloud AWS SQS v3](https://www.baeldung.com/java-spring-cloud-aws-v3-message-acknowledgement)
|
||||
|
@ -115,6 +115,7 @@
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
<maven.compiler.target>17</maven.compiler.target>
|
||||
<wiremock.version>3.3.1</wiremock.version>
|
||||
<junit-jupiter.version>5.10.2</junit-jupiter.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
@ -3,3 +3,4 @@
|
||||
- [How to Catch Deserialization Errors in Spring-Kafka?](https://www.baeldung.com/spring-kafka-deserialization-errors)
|
||||
- [View Kafka Headers in Java](https://www.baeldung.com/java-kafka-view-headers)
|
||||
- [Understanding Kafka InstanceAlreadyExistsException in Java](https://www.baeldung.com/kafka-instancealreadyexistsexception)
|
||||
- [Difference Between GroupId and ConsumerId in Apache Kafka](https://www.baeldung.com/apache-kafka-groupid-vs-consumerid)
|
||||
|
@ -67,7 +67,12 @@
|
||||
<dependency>
|
||||
<groupId>com.squareup.okhttp3</groupId>
|
||||
<artifactId>mockwebserver</artifactId>
|
||||
<version>4.12.0</version>
|
||||
<version>${mockwebserver.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jetbrains.kotlin</groupId>
|
||||
<artifactId>kotlin-stdlib</artifactId>
|
||||
<version>${kotlin-stdlib.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
@ -86,6 +91,8 @@
|
||||
<properties>
|
||||
<reactor-spring.version>1.0.1.RELEASE</reactor-spring.version>
|
||||
<spring-cloud.version>2021.0.4</spring-cloud.version>
|
||||
<mockwebserver.version>5.0.0-alpha.12</mockwebserver.version>
|
||||
<kotlin-stdlib.version>2.0.0-Beta4</kotlin-stdlib.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
@ -125,6 +125,11 @@
|
||||
<version>${jetty-reactive-httpclient.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jetbrains.kotlin</groupId>
|
||||
<artifactId>kotlin-stdlib</artifactId>
|
||||
<version>${kotlin-stdlib.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
@ -179,10 +184,11 @@
|
||||
<reactor-spring.version>1.0.1.RELEASE</reactor-spring.version>
|
||||
<geronimo-json_1.1_spec.version>1.0</geronimo-json_1.1_spec.version>
|
||||
<jetty-reactive-httpclient.version>1.1.6</jetty-reactive-httpclient.version>
|
||||
<okhttp.version>4.12.0</okhttp.version>
|
||||
<okhttp.version>5.0.0-alpha.12</okhttp.version>
|
||||
<reactor-test.version>3.5.3</reactor-test.version>
|
||||
<wiremock-standalone.version>2.26.0</wiremock-standalone.version>
|
||||
<spring-cloud-starter-openfeign.version>3.1.4</spring-cloud-starter-openfeign.version>
|
||||
<kotlin-stdlib.version>2.0.0-Beta4</kotlin-stdlib.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
@ -54,6 +54,7 @@
|
||||
<module>spring-security-azuread</module>
|
||||
<module>spring-security-oauth2-testing</module>
|
||||
<module>spring-security-saml2</module>
|
||||
<module>spring-security-oauth2-bff/backend</module>
|
||||
</modules>
|
||||
|
||||
</project>
|
@ -63,7 +63,7 @@
|
||||
</build>
|
||||
|
||||
<properties>
|
||||
<testcontainers.version>1.16.2</testcontainers.version>
|
||||
<testcontainers.version>1.19.6</testcontainers.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
@ -3,7 +3,6 @@
|
||||
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>
|
||||
<!-- NOT NEEDED - JSP <groupId>com.baeldung</groupId> -->
|
||||
<artifactId>test-containers</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<name>test-containers</name>
|
||||
@ -65,7 +64,7 @@
|
||||
|
||||
<properties>
|
||||
<junit.platform.version>1.5.0</junit.platform.version>
|
||||
<testcontainers.version>1.11.4</testcontainers.version>
|
||||
<testcontainers.version>1.19.6</testcontainers.version>
|
||||
<postgresql.version>42.2.6</postgresql.version>
|
||||
<selenium-remote-driver.version>3.141.59</selenium-remote-driver.version>
|
||||
</properties>
|
||||
|
@ -76,8 +76,8 @@
|
||||
<rest-assured.version>3.1.1</rest-assured.version>
|
||||
<application.class>com.baeldung.jooby.App</application.class>
|
||||
<maven-shade-plugin.version>3.2.4</maven-shade-plugin.version>
|
||||
<squareup.okhttp.version>5.0.0-alpha.12</squareup.okhttp.version>
|
||||
<maven-compiler.version>3.12.1</maven-compiler.version>
|
||||
<squareup.okhttp.version>4.12.0</squareup.okhttp.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
Loading…
x
Reference in New Issue
Block a user