diff --git a/aws-app-sync/README.md b/aws-app-sync/README.md
new file mode 100644
index 0000000000..976a999f40
--- /dev/null
+++ b/aws-app-sync/README.md
@@ -0,0 +1,3 @@
+### Relevant Articles:
+
+- [AWS AppSync With Spring Boot](https://www.baeldung.com/aws-appsync-spring)
diff --git a/core-java-modules/core-java-9-new-features/README.md b/core-java-modules/core-java-9-new-features/README.md
index d547b9a221..c2ef63a530 100644
--- a/core-java-modules/core-java-9-new-features/README.md
+++ b/core-java-modules/core-java-9-new-features/README.md
@@ -12,3 +12,4 @@ This module contains articles about core Java features that have been introduced
- [Introduction to Java 9 StackWalking API](https://www.baeldung.com/java-9-stackwalking-api)
- [Java 9 Platform Logging API](https://www.baeldung.com/java-9-logging-api)
- [Java 9 Reactive Streams](https://www.baeldung.com/java-9-reactive-streams)
+- [Multi-Release JAR Files with Maven](https://www.baeldung.com/maven-multi-release-jars)
diff --git a/core-java-modules/core-java-9-new-features/pom.xml b/core-java-modules/core-java-9-new-features/pom.xml
index 23dc659af8..4edf6e4fc5 100644
--- a/core-java-modules/core-java-9-new-features/pom.xml
+++ b/core-java-modules/core-java-9-new-features/pom.xml
@@ -33,8 +33,104 @@
${junit.platform.version}
test
+
+ org.awaitility
+ awaitility
+ ${awaitility.version}
+ test
+
-
+
+
+ incubator-features
+
+ core-java-9-new-features
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ ${maven-compiler-plugin.version}
+
+ ${maven.compiler.source}
+ ${maven.compiler.target}
+ --add-modules=jdk.incubator.httpclient
+
+
+
+ maven-surefire-plugin
+
+ --add-modules=jdk.incubator.httpclient
+
+
+
+
+
+
+ mrjar-generation
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+
+ compile-java-8
+
+ compile
+
+
+ 1.8
+ 1.8
+
+ ${project.basedir}/src/main/java8
+
+
+
+
+ compile-java-9
+ compile
+
+ compile
+
+
+ 9
+
+ ${project.basedir}/src/main/java9
+
+ ${project.build.outputDirectory}/META-INF/versions/9
+
+
+
+ default-testCompile
+ test-compile
+
+ testCompile
+
+
+ true
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-jar-plugin
+ ${maven-jar-plugin.version}
+
+
+
+ true
+
+
+ com.baeldung.multireleaseapp.App
+
+
+
+
+
+
+
+
core-java-9-new-features
@@ -58,12 +154,14 @@
+ 3.0.0
3.10.0
1.2.0
+ 4.0.2
1.9
1.9
- 3.0.0
+ 3.2.0
diff --git a/core-java-modules/core-java-9-new-features/src/main/java/com/baeldung/java9/streams/reactive/flowvsrx/FlowApiLiveVideo.java b/core-java-modules/core-java-9-new-features/src/main/java/com/baeldung/java9/streams/reactive/flowvsrx/FlowApiLiveVideo.java
deleted file mode 100644
index 6f0b49ea0c..0000000000
--- a/core-java-modules/core-java-9-new-features/src/main/java/com/baeldung/java9/streams/reactive/flowvsrx/FlowApiLiveVideo.java
+++ /dev/null
@@ -1,72 +0,0 @@
-package com.baeldung.java9.streams.reactive.flowvsrx;
-
-import java.util.concurrent.Executors;
-import java.util.concurrent.Flow;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.SubmissionPublisher;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicLong;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class FlowApiLiveVideo {
-
- private static Logger log = LoggerFactory.getLogger(FlowApiLiveVideo.class);
-
- static class VideoPlayer implements Flow.Subscriber {
- Flow.Subscription subscription = null;
-
- @Override
- public void onSubscribe(Flow.Subscription subscription) {
- this.subscription = subscription;
- subscription.request(1);
- }
-
- @Override
- public void onNext(VideoFrame item) {
- log.info("play #{}", item.getNumber());
- sleep(30);
- subscription.request(1);
- }
-
- @Override
- public void onError(Throwable throwable) {
- log.error("There is an error in video streaming:{}", throwable.getMessage());
- }
-
- @Override
- public void onComplete() {
- log.error("Video has ended");
- }
- }
-
- static class VideoStreamServer extends SubmissionPublisher {
- public VideoStreamServer() {
- super(Executors.newSingleThreadExecutor(), 1);
- }
- }
-
- private static void sleep(int i) {
- try {
- Thread.sleep(i);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
-
- public static void main(String[] args) {
- VideoStreamServer streamServer = new VideoStreamServer();
- streamServer.subscribe(new VideoPlayer());
-
- ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
- AtomicLong frameNumber = new AtomicLong();
- executor.scheduleWithFixedDelay(() -> {
- streamServer.offer(new VideoFrame(frameNumber.getAndIncrement()), (subscriber, videoFrame) -> {
- subscriber.onError(new RuntimeException("Frame#" + videoFrame.getNumber() + " droped because of back pressure"));
- return true;
- });
- }, 0, 1, TimeUnit.MILLISECONDS);
-
- sleep(1000);
- }
-}
diff --git a/core-java-modules/core-java-9-new-features/src/main/java8/com/baeldung/multireleaseapp/App.java b/core-java-modules/core-java-9-new-features/src/main/java8/com/baeldung/multireleaseapp/App.java
new file mode 100644
index 0000000000..cc00223e05
--- /dev/null
+++ b/core-java-modules/core-java-9-new-features/src/main/java8/com/baeldung/multireleaseapp/App.java
@@ -0,0 +1,14 @@
+package com.baeldung.multireleaseapp;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class App {
+
+ private static final Logger logger = LoggerFactory.getLogger(App.class);
+
+ public static void main(String[] args) {
+ logger.info(String.format("Running on %s", new DefaultVersion().version()));
+ }
+
+}
diff --git a/core-java-modules/core-java-9-new-features/src/main/java8/com/baeldung/multireleaseapp/DefaultVersion.java b/core-java-modules/core-java-9-new-features/src/main/java8/com/baeldung/multireleaseapp/DefaultVersion.java
new file mode 100644
index 0000000000..b24be606de
--- /dev/null
+++ b/core-java-modules/core-java-9-new-features/src/main/java8/com/baeldung/multireleaseapp/DefaultVersion.java
@@ -0,0 +1,9 @@
+package com.baeldung.multireleaseapp;
+
+public class DefaultVersion implements Version {
+
+ @Override
+ public String version() {
+ return System.getProperty("java.version");
+ }
+}
diff --git a/core-java-modules/core-java-9-new-features/src/main/java8/com/baeldung/multireleaseapp/Version.java b/core-java-modules/core-java-9-new-features/src/main/java8/com/baeldung/multireleaseapp/Version.java
new file mode 100644
index 0000000000..ef95f08205
--- /dev/null
+++ b/core-java-modules/core-java-9-new-features/src/main/java8/com/baeldung/multireleaseapp/Version.java
@@ -0,0 +1,5 @@
+package com.baeldung.multireleaseapp;
+
+interface Version {
+ public String version();
+}
\ No newline at end of file
diff --git a/core-java-modules/core-java-9-new-features/src/main/java9/com/baeldung/multireleaseapp/DefaultVersion.java b/core-java-modules/core-java-9-new-features/src/main/java9/com/baeldung/multireleaseapp/DefaultVersion.java
new file mode 100644
index 0000000000..0842f578dd
--- /dev/null
+++ b/core-java-modules/core-java-9-new-features/src/main/java9/com/baeldung/multireleaseapp/DefaultVersion.java
@@ -0,0 +1,9 @@
+package com.baeldung.multireleaseapp;
+
+public class DefaultVersion implements Version {
+
+ @Override
+ public String version() {
+ return Runtime.version().toString();
+ }
+}
diff --git a/core-java-modules/core-java-9-new-features/src/test/java/com/baeldung/java9/httpclient/HttpClientTest.java b/core-java-modules/core-java-9-new-features/src/test/java/com/baeldung/java9/httpclient/HttpClientIntegrationTest.java
similarity index 98%
rename from core-java-modules/core-java-9-new-features/src/test/java/com/baeldung/java9/httpclient/HttpClientTest.java
rename to core-java-modules/core-java-9-new-features/src/test/java/com/baeldung/java9/httpclient/HttpClientIntegrationTest.java
index 5cf3b9098f..fc59ae8d8d 100644
--- a/core-java-modules/core-java-9-new-features/src/test/java/com/baeldung/java9/httpclient/HttpClientTest.java
+++ b/core-java-modules/core-java-9-new-features/src/test/java/com/baeldung/java9/httpclient/HttpClientIntegrationTest.java
@@ -24,7 +24,7 @@ import static org.junit.Assert.assertThat;
/**
* Created by adam.
*/
-public class HttpClientTest {
+public class HttpClientIntegrationTest {
@Test
public void shouldReturnSampleDataContentWhenConnectViaSystemProxy() throws IOException, InterruptedException, URISyntaxException {
@@ -55,7 +55,7 @@ public class HttpClientTest {
.send(request, HttpResponse.BodyHandler.asString());
assertThat(response.statusCode(), equalTo(HttpURLConnection.HTTP_MOVED_PERM));
- assertThat(response.body(), containsString("https://stackoverflow.com/"));
+ assertThat(response.body(), containsString(""));
}
@Test
diff --git a/core-java-modules/core-java-9-new-features/src/test/java/com/baeldung/java9/httpclient/HttpRequestTest.java b/core-java-modules/core-java-9-new-features/src/test/java/com/baeldung/java9/httpclient/HttpRequestIntegrationTest.java
similarity index 99%
rename from core-java-modules/core-java-9-new-features/src/test/java/com/baeldung/java9/httpclient/HttpRequestTest.java
rename to core-java-modules/core-java-9-new-features/src/test/java/com/baeldung/java9/httpclient/HttpRequestIntegrationTest.java
index 7c0e9a90e0..17af7bd8ba 100644
--- a/core-java-modules/core-java-9-new-features/src/test/java/com/baeldung/java9/httpclient/HttpRequestTest.java
+++ b/core-java-modules/core-java-9-new-features/src/test/java/com/baeldung/java9/httpclient/HttpRequestIntegrationTest.java
@@ -22,7 +22,7 @@ import static org.junit.Assert.assertThat;
/**
* Created by adam.
*/
-public class HttpRequestTest {
+public class HttpRequestIntegrationTest {
@Test
public void shouldReturnStatusOKWhenSendGetRequest() throws IOException, InterruptedException, URISyntaxException {
diff --git a/core-java-modules/core-java-9-new-features/src/test/java/com/baeldung/java9/httpclient/HttpResponseTest.java b/core-java-modules/core-java-9-new-features/src/test/java/com/baeldung/java9/httpclient/HttpResponseIntegrationTest.java
similarity index 97%
rename from core-java-modules/core-java-9-new-features/src/test/java/com/baeldung/java9/httpclient/HttpResponseTest.java
rename to core-java-modules/core-java-9-new-features/src/test/java/com/baeldung/java9/httpclient/HttpResponseIntegrationTest.java
index 80295ff34c..5c6f9c8a52 100644
--- a/core-java-modules/core-java-9-new-features/src/test/java/com/baeldung/java9/httpclient/HttpResponseTest.java
+++ b/core-java-modules/core-java-9-new-features/src/test/java/com/baeldung/java9/httpclient/HttpResponseIntegrationTest.java
@@ -18,7 +18,7 @@ import static org.junit.Assert.assertThat;
/**
* Created by adam.
*/
-public class HttpResponseTest {
+public class HttpResponseIntegrationTest {
@Test
public void shouldReturnStatusOKWhenSendGetRequest() throws IOException, InterruptedException, URISyntaxException {
diff --git a/core-java-modules/core-java-9-new-features/src/test/java/com/baeldung/java9/streams.reactive/ReactiveStreamsTest.java b/core-java-modules/core-java-9-new-features/src/test/java/com/baeldung/java9/streams/reactive/ReactiveStreamsUnitTest.java
similarity index 86%
rename from core-java-modules/core-java-9-new-features/src/test/java/com/baeldung/java9/streams.reactive/ReactiveStreamsTest.java
rename to core-java-modules/core-java-9-new-features/src/test/java/com/baeldung/java9/streams/reactive/ReactiveStreamsUnitTest.java
index 647557532d..92cdc1c074 100644
--- a/core-java-modules/core-java-9-new-features/src/test/java/com/baeldung/java9/streams.reactive/ReactiveStreamsTest.java
+++ b/core-java-modules/core-java-9-new-features/src/test/java/com/baeldung/java9/streams/reactive/ReactiveStreamsUnitTest.java
@@ -5,10 +5,12 @@ import org.junit.Test;
import java.util.List;
import java.util.concurrent.SubmissionPublisher;
+import java.util.concurrent.TimeUnit;
-import static org.assertj.core.api.Java6Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.awaitility.Awaitility.await;
-public class ReactiveStreamsTest {
+public class ReactiveStreamsUnitTest {
@Test
public void givenPublisher_whenSubscribeToIt_thenShouldConsumeAllElements() throws InterruptedException {
@@ -25,7 +27,7 @@ public class ReactiveStreamsTest {
//then
- await().atMost(1000, TimeUnit.MILLISECONDS).until(
+ await().atMost(1000, TimeUnit.MILLISECONDS).untilAsserted(
() -> assertThat(subscriber.consumedElements).containsExactlyElementsOf(items)
);
}
@@ -46,7 +48,7 @@ public class ReactiveStreamsTest {
publisher.close();
//then
- await().atMost(1000, TimeUnit.MILLISECONDS).until(
+ await().atMost(1000, TimeUnit.MILLISECONDS).untilAsserted(
() -> assertThat(subscriber.consumedElements).containsExactlyElementsOf(expectedResult)
);
}
@@ -66,7 +68,7 @@ public class ReactiveStreamsTest {
publisher.close();
//then
- await().atMost(1000, TimeUnit.MILLISECONDS).until(
+ await().atMost(1000, TimeUnit.MILLISECONDS).untilAsserted(
() -> assertThat(subscriber.consumedElements).containsExactlyElementsOf(expected)
);
}
diff --git a/core-java-modules/core-java-9-new-features/src/test/java/com/baeldung/java9/streams/reactive/flowvsrx/FlowApiLiveVideo.java b/core-java-modules/core-java-9-new-features/src/test/java/com/baeldung/java9/streams/reactive/flowvsrx/FlowApiLiveVideo.java
new file mode 100644
index 0000000000..8b20555f8f
--- /dev/null
+++ b/core-java-modules/core-java-9-new-features/src/test/java/com/baeldung/java9/streams/reactive/flowvsrx/FlowApiLiveVideo.java
@@ -0,0 +1,71 @@
+package com.baeldung.java9.streams.reactive.flowvsrx;
+
+import java.util.concurrent.Executors;
+import java.util.concurrent.Flow;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.SubmissionPublisher;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicLong;
+
+public class FlowApiLiveVideo {
+
+ static class VideoPlayer implements Flow.Subscriber {
+ Flow.Subscription subscription = null;
+ private long consumerDelay = 30;
+
+ public VideoPlayer(long consumerDelay) {
+ this.consumerDelay = consumerDelay;
+ }
+
+ @Override
+ public void onSubscribe(Flow.Subscription subscription) {
+ this.subscription = subscription;
+ subscription.request(1);
+ }
+
+ @Override
+ public void onNext(VideoFrame item) {
+ try {
+ Thread.sleep(consumerDelay);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ subscription.request(1);
+ }
+
+ @Override
+ public void onError(Throwable throwable) {
+ }
+
+ @Override
+ public void onComplete() {
+ }
+ }
+
+ static class VideoStreamServer extends SubmissionPublisher {
+ ScheduledExecutorService executor = null;
+
+ public VideoStreamServer(int bufferSize) {
+ super(Executors.newSingleThreadExecutor(), bufferSize);
+ executor = Executors.newScheduledThreadPool(1);
+ }
+
+ void startStreaming(long produceDelay, Runnable onDrop) {
+ AtomicLong frameNumber = new AtomicLong();
+ executor.scheduleWithFixedDelay(() -> {
+ offer(new VideoFrame(frameNumber.getAndIncrement()), (subscriber, videoFrame) -> {
+ subscriber.onError(new RuntimeException("Frame#" + videoFrame.getNumber() + " dropped because of back pressure"));
+ onDrop.run();
+ return true;
+ });
+ }, 0, produceDelay, TimeUnit.MILLISECONDS);
+ }
+ }
+
+ public static void streamLiveVideo(long produceDelay, long consumeDelay, int bufferSize, Runnable onError){
+ FlowApiLiveVideo.VideoStreamServer streamServer = new FlowApiLiveVideo.VideoStreamServer(bufferSize);
+ streamServer.subscribe(new FlowApiLiveVideo.VideoPlayer(consumeDelay));
+ streamServer.startStreaming(produceDelay, onError);
+ }
+
+}
diff --git a/core-java-modules/core-java-9-new-features/src/test/java/com/baeldung/java9/streams/reactive/flowvsrx/LiveVideoFlowVsRxUnitTest.java b/core-java-modules/core-java-9-new-features/src/test/java/com/baeldung/java9/streams/reactive/flowvsrx/LiveVideoFlowVsRxUnitTest.java
new file mode 100644
index 0000000000..87021bdfc7
--- /dev/null
+++ b/core-java-modules/core-java-9-new-features/src/test/java/com/baeldung/java9/streams/reactive/flowvsrx/LiveVideoFlowVsRxUnitTest.java
@@ -0,0 +1,61 @@
+package com.baeldung.java9.streams.reactive.flowvsrx;
+
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicLong;
+import org.junit.Test;
+import org.junit.jupiter.api.Assertions;
+
+import static org.awaitility.Awaitility.await;
+
+public class LiveVideoFlowVsRxUnitTest {
+
+ private final static long SLOW_CONSUMER_DELAY = 30;
+ private final static long FAST_CONSUMER_DELAY = 1;
+ private final static long PRODUCER_DELAY = 1;
+ private final static int BUFFER_SIZE = 10;
+ private final static long AWAIT = 1000;
+
+ @Test
+ public void givenSlowVideoPlayer_whenSubscribedToFlowApiLiveVideo_thenExpectErrorOnBackPressure() {
+ AtomicLong errors = new AtomicLong();
+
+ FlowApiLiveVideo.streamLiveVideo(PRODUCER_DELAY, SLOW_CONSUMER_DELAY, BUFFER_SIZE, errors::incrementAndGet);
+
+ await()
+ .atMost(AWAIT, TimeUnit.MILLISECONDS)
+ .untilAsserted(() -> Assertions.assertTrue(errors.get() > 0));
+ }
+
+ @Test
+ public void givenFastVideoPlayer_whenSubscribedToFlowApiLiveVideo_thenExpectNoErrorOnBackPressure() throws InterruptedException {
+ AtomicLong errors = new AtomicLong();
+
+ FlowApiLiveVideo.streamLiveVideo(PRODUCER_DELAY, FAST_CONSUMER_DELAY, BUFFER_SIZE, errors::incrementAndGet);
+
+ Thread.sleep(AWAIT);
+ Assertions.assertEquals(0, errors.get());
+ }
+
+ @Test
+ public void givenSlowVideoPlayer_whenSubscribedToRxJavaLiveVideo_thenExpectErrorOnBackPressure() {
+ AtomicLong errors = new AtomicLong();
+
+ RxJavaLiveVideo.streamLiveVideo(PRODUCER_DELAY, SLOW_CONSUMER_DELAY, BUFFER_SIZE, errors::incrementAndGet);
+
+ await()
+ .atMost(AWAIT, TimeUnit.MILLISECONDS)
+ .untilAsserted(() -> Assertions.assertTrue(errors.get() > 0));
+ }
+
+ @Test
+ public void givenFastVideoPlayer_whenSubscribedToRxJavaLiveVideo_thenExpectNoErrorOnBackPressure() throws InterruptedException {
+ AtomicLong errors = new AtomicLong();
+
+ RxJavaLiveVideo.streamLiveVideo(PRODUCER_DELAY, FAST_CONSUMER_DELAY, BUFFER_SIZE, errors::incrementAndGet);
+
+ Thread.sleep(AWAIT);
+ Assertions.assertEquals(0, errors.get());
+ }
+
+}
+
diff --git a/core-java-modules/core-java-9-new-features/src/main/java/com/baeldung/java9/streams/reactive/flowvsrx/RxJavaLiveVideo.java b/core-java-modules/core-java-9-new-features/src/test/java/com/baeldung/java9/streams/reactive/flowvsrx/RxJavaLiveVideo.java
similarity index 63%
rename from core-java-modules/core-java-9-new-features/src/main/java/com/baeldung/java9/streams/reactive/flowvsrx/RxJavaLiveVideo.java
rename to core-java-modules/core-java-9-new-features/src/test/java/com/baeldung/java9/streams/reactive/flowvsrx/RxJavaLiveVideo.java
index 916c930b38..794d580081 100644
--- a/core-java-modules/core-java-9-new-features/src/main/java/com/baeldung/java9/streams/reactive/flowvsrx/RxJavaLiveVideo.java
+++ b/core-java-modules/core-java-9-new-features/src/test/java/com/baeldung/java9/streams/reactive/flowvsrx/RxJavaLiveVideo.java
@@ -2,37 +2,35 @@ package com.baeldung.java9.streams.reactive.flowvsrx;
import io.reactivex.rxjava3.core.BackpressureOverflowStrategy;
import io.reactivex.rxjava3.core.Flowable;
+import io.reactivex.rxjava3.disposables.Disposable;
import io.reactivex.rxjava3.schedulers.Schedulers;
import java.util.concurrent.Executors;
import java.util.stream.Stream;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
public class RxJavaLiveVideo {
- private static Logger log = LoggerFactory.getLogger(RxJavaLiveVideo.class);
-
- public static void main(String[] args) {
- Flowable
+ public static Disposable streamLiveVideo(long produceDelay, long consumeDelay, int bufferSize, Runnable onError) {
+ return Flowable
.fromStream(Stream.iterate(new VideoFrame(0), videoFrame -> {
- sleep(1);
+ sleep(produceDelay);
return new VideoFrame(videoFrame.getNumber() + 1);
}))
- .onBackpressureBuffer(10, null, BackpressureOverflowStrategy.ERROR)
.subscribeOn(Schedulers.from(Executors.newSingleThreadScheduledExecutor()), true)
+ .onBackpressureBuffer(bufferSize, null, BackpressureOverflowStrategy.ERROR)
.observeOn(Schedulers.from(Executors.newSingleThreadExecutor()))
- .doOnError(Throwable::printStackTrace)
.subscribe(item -> {
- log.info("play #" + item.getNumber());
- sleep(30);
+ sleep(consumeDelay);
+ }, throwable -> {
+ onError.run();
});
}
- private static void sleep(int i) {
+ private static void sleep(long i) {
try {
Thread.sleep(i);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
+
}
diff --git a/core-java-modules/core-java-9-new-features/src/main/java/com/baeldung/java9/streams/reactive/flowvsrx/VideoFrame.java b/core-java-modules/core-java-9-new-features/src/test/java/com/baeldung/java9/streams/reactive/flowvsrx/VideoFrame.java
similarity index 100%
rename from core-java-modules/core-java-9-new-features/src/main/java/com/baeldung/java9/streams/reactive/flowvsrx/VideoFrame.java
rename to core-java-modules/core-java-9-new-features/src/test/java/com/baeldung/java9/streams/reactive/flowvsrx/VideoFrame.java
diff --git a/core-java-modules/core-java-9-new-features/src/test/java/com/baeldung/java9/varhandles/VariableHandlesTest.java b/core-java-modules/core-java-9-new-features/src/test/java/com/baeldung/java9/varhandles/VariableHandlesTest.java
deleted file mode 100644
index 50766502ec..0000000000
--- a/core-java-modules/core-java-9-new-features/src/test/java/com/baeldung/java9/varhandles/VariableHandlesTest.java
+++ /dev/null
@@ -1,106 +0,0 @@
-package com.baeldung.java9.varhandles;
-
-import org.junit.Test;
-
-import java.lang.invoke.MethodHandles;
-import java.lang.invoke.VarHandle;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-public class VariableHandlesTest {
-
- public int publicTestVariable = 1;
- private int privateTestVariable = 1;
- public int variableToSet = 1;
- public int variableToCompareAndSet = 1;
- public int variableToGetAndAdd = 0;
- public byte variableToBitwiseOr = 0;
-
- @Test
- public void whenVariableHandleForPublicVariableIsCreated_ThenItIsInitializedProperly() throws NoSuchFieldException, IllegalAccessException {
- VarHandle publicIntHandle = MethodHandles
- .lookup()
- .in(VariableHandlesTest.class)
- .findVarHandle(VariableHandlesTest.class, "publicTestVariable", int.class);
-
- assertThat(publicIntHandle.coordinateTypes().size() == 1);
- assertThat(publicIntHandle.coordinateTypes().get(0) == VariableHandles.class);
-
- }
-
- @Test
- public void whenVariableHandleForPrivateVariableIsCreated_ThenItIsInitializedProperly() throws NoSuchFieldException, IllegalAccessException {
- VarHandle privateIntHandle = MethodHandles
- .privateLookupIn(VariableHandlesTest.class, MethodHandles.lookup())
- .findVarHandle(VariableHandlesTest.class, "privateTestVariable", int.class);
-
- assertThat(privateIntHandle.coordinateTypes().size() == 1);
- assertThat(privateIntHandle.coordinateTypes().get(0) == VariableHandlesTest.class);
-
- }
-
- @Test
- public void whenVariableHandleForArrayVariableIsCreated_ThenItIsInitializedProperly() throws NoSuchFieldException, IllegalAccessException {
- VarHandle arrayVarHandle = MethodHandles
- .arrayElementVarHandle(int[].class);
-
- assertThat(arrayVarHandle.coordinateTypes().size() == 2);
- assertThat(arrayVarHandle.coordinateTypes().get(0) == int[].class);
- }
-
- @Test
- public void givenVarHandle_whenGetIsInvoked_ThenValueOfVariableIsReturned() throws NoSuchFieldException, IllegalAccessException {
- VarHandle publicIntHandle = MethodHandles
- .lookup()
- .in(VariableHandlesTest.class)
- .findVarHandle(VariableHandlesTest.class, "publicTestVariable", int.class);
-
- assertThat((int) publicIntHandle.get(this) == 1);
- }
-
- @Test
- public void givenVarHandle_whenSetIsInvoked_ThenValueOfVariableIsChanged() throws NoSuchFieldException, IllegalAccessException {
- VarHandle publicIntHandle = MethodHandles
- .lookup()
- .in(VariableHandlesTest.class)
- .findVarHandle(VariableHandlesTest.class, "variableToSet", int.class);
- publicIntHandle.set(this, 15);
-
- assertThat((int) publicIntHandle.get(this) == 15);
- }
-
- @Test
- public void givenVarHandle_whenCompareAndSetIsInvoked_ThenValueOfVariableIsChanged() throws NoSuchFieldException, IllegalAccessException {
- VarHandle publicIntHandle = MethodHandles
- .lookup()
- .in(VariableHandlesTest.class)
- .findVarHandle(VariableHandlesTest.class, "variableToCompareAndSet", int.class);
- publicIntHandle.compareAndSet(this, 1, 100);
-
- assertThat((int) publicIntHandle.get(this) == 100);
- }
-
- @Test
- public void givenVarHandle_whenGetAndAddIsInvoked_ThenValueOfVariableIsChanged() throws NoSuchFieldException, IllegalAccessException {
- VarHandle publicIntHandle = MethodHandles
- .lookup()
- .in(VariableHandlesTest.class)
- .findVarHandle(VariableHandlesTest.class, "variableToGetAndAdd", int.class);
- int before = (int) publicIntHandle.getAndAdd(this, 200);
-
- assertThat(before == 0);
- assertThat((int) publicIntHandle.get(this) == 200);
- }
-
- @Test
- public void givenVarHandle_whenGetAndBitwiseOrIsInvoked_ThenValueOfVariableIsChanged() throws NoSuchFieldException, IllegalAccessException {
- VarHandle publicIntHandle = MethodHandles
- .lookup()
- .in(VariableHandlesTest.class)
- .findVarHandle(VariableHandlesTest.class, "variableToBitwiseOr", byte.class);
- byte before = (byte) publicIntHandle.getAndBitwiseOr(this, (byte) 127);
-
- assertThat(before == 0);
- assertThat(variableToBitwiseOr == 127);
- }
-}
diff --git a/core-java-modules/core-java-9-new-features/src/test/java/com/baeldung/java9/varhandles/VariableHandlesUnitTest.java b/core-java-modules/core-java-9-new-features/src/test/java/com/baeldung/java9/varhandles/VariableHandlesUnitTest.java
new file mode 100644
index 0000000000..a7263f0bb2
--- /dev/null
+++ b/core-java-modules/core-java-9-new-features/src/test/java/com/baeldung/java9/varhandles/VariableHandlesUnitTest.java
@@ -0,0 +1,105 @@
+package com.baeldung.java9.varhandles;
+
+import org.junit.Test;
+
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+
+import static org.junit.Assert.assertEquals;
+
+public class VariableHandlesUnitTest {
+
+ public int publicTestVariable = 1;
+ private int privateTestVariable = 1;
+ public int variableToSet = 1;
+ public int variableToCompareAndSet = 1;
+ public int variableToGetAndAdd = 0;
+ public byte variableToBitwiseOr = 0;
+
+ @Test
+ public void whenVariableHandleForPublicVariableIsCreated_ThenItIsInitializedProperly() throws NoSuchFieldException, IllegalAccessException {
+ VarHandle PUBLIC_TEST_VARIABLE = MethodHandles
+ .lookup()
+ .in(VariableHandlesUnitTest.class)
+ .findVarHandle(VariableHandlesUnitTest.class, "publicTestVariable", int.class);
+
+ assertEquals(1, PUBLIC_TEST_VARIABLE.coordinateTypes().size());
+ assertEquals(VariableHandlesUnitTest.class, PUBLIC_TEST_VARIABLE.coordinateTypes().get(0));
+ }
+
+ @Test
+ public void whenVariableHandleForPrivateVariableIsCreated_ThenItIsInitializedProperly() throws NoSuchFieldException, IllegalAccessException {
+ VarHandle PRIVATE_TEST_VARIABLE = MethodHandles
+ .privateLookupIn(VariableHandlesUnitTest.class, MethodHandles.lookup())
+ .findVarHandle(VariableHandlesUnitTest.class, "privateTestVariable", int.class);
+
+ assertEquals(1, PRIVATE_TEST_VARIABLE.coordinateTypes().size());
+ assertEquals(VariableHandlesUnitTest.class, PRIVATE_TEST_VARIABLE.coordinateTypes().get(0));
+ }
+
+ @Test
+ public void whenVariableHandleForArrayVariableIsCreated_ThenItIsInitializedProperly() throws NoSuchFieldException, IllegalAccessException {
+ VarHandle arrayVarHandle = MethodHandles
+ .arrayElementVarHandle(int[].class);
+
+ assertEquals(2, arrayVarHandle.coordinateTypes().size());
+ assertEquals(int[].class, arrayVarHandle.coordinateTypes().get(0));
+ }
+
+ @Test
+ public void givenVarHandle_whenGetIsInvoked_ThenValueOfVariableIsReturned() throws NoSuchFieldException, IllegalAccessException {
+ VarHandle PUBLIC_TEST_VARIABLE = MethodHandles
+ .lookup()
+ .in(VariableHandlesUnitTest.class)
+ .findVarHandle(VariableHandlesUnitTest.class, "publicTestVariable", int.class);
+
+ assertEquals(1, (int) PUBLIC_TEST_VARIABLE.get(this));
+ }
+
+ @Test
+ public void givenVarHandle_whenSetIsInvoked_ThenValueOfVariableIsChanged() throws NoSuchFieldException, IllegalAccessException {
+ VarHandle VARIABLE_TO_SET = MethodHandles
+ .lookup()
+ .in(VariableHandlesUnitTest.class)
+ .findVarHandle(VariableHandlesUnitTest.class, "variableToSet", int.class);
+
+ VARIABLE_TO_SET.set(this, 15);
+ assertEquals(15, (int) VARIABLE_TO_SET.get(this));
+ }
+
+ @Test
+ public void givenVarHandle_whenCompareAndSetIsInvoked_ThenValueOfVariableIsChanged() throws NoSuchFieldException, IllegalAccessException {
+ VarHandle VARIABLE_TO_COMPARE_AND_SET = MethodHandles
+ .lookup()
+ .in(VariableHandlesUnitTest.class)
+ .findVarHandle(VariableHandlesUnitTest.class, "variableToCompareAndSet", int.class);
+
+ VARIABLE_TO_COMPARE_AND_SET.compareAndSet(this, 1, 100);
+ assertEquals(100, (int) VARIABLE_TO_COMPARE_AND_SET.get(this));
+ }
+
+ @Test
+ public void givenVarHandle_whenGetAndAddIsInvoked_ThenValueOfVariableIsChanged() throws NoSuchFieldException, IllegalAccessException {
+ VarHandle VARIABLE_TO_GET_AND_ADD = MethodHandles
+ .lookup()
+ .in(VariableHandlesUnitTest.class)
+ .findVarHandle(VariableHandlesUnitTest.class, "variableToGetAndAdd", int.class);
+
+ int before = (int) VARIABLE_TO_GET_AND_ADD.getAndAdd(this, 200);
+
+ assertEquals(0, before);
+ assertEquals(200, (int) VARIABLE_TO_GET_AND_ADD.get(this));
+ }
+
+ @Test
+ public void givenVarHandle_whenGetAndBitwiseOrIsInvoked_ThenValueOfVariableIsChanged() throws NoSuchFieldException, IllegalAccessException {
+ VarHandle VARIABLE_TO_BITWISE_OR = MethodHandles
+ .lookup()
+ .in(VariableHandlesUnitTest.class)
+ .findVarHandle(VariableHandlesUnitTest.class, "variableToBitwiseOr", byte.class);
+ byte before = (byte) VARIABLE_TO_BITWISE_OR.getAndBitwiseOr(this, (byte) 127);
+
+ assertEquals(0, before);
+ assertEquals(127, (byte) VARIABLE_TO_BITWISE_OR.get(this));
+ }
+}
diff --git a/core-java-modules/core-java-concurrency-advanced-3/src/main/java/com/baeldung/atomicstampedreference/StampedAccount.java b/core-java-modules/core-java-concurrency-advanced-3/src/main/java/com/baeldung/atomicstampedreference/StampedAccount.java
index 1a46e1ba52..415b24738a 100644
--- a/core-java-modules/core-java-concurrency-advanced-3/src/main/java/com/baeldung/atomicstampedreference/StampedAccount.java
+++ b/core-java-modules/core-java-concurrency-advanced-3/src/main/java/com/baeldung/atomicstampedreference/StampedAccount.java
@@ -9,13 +9,11 @@ public class StampedAccount {
private AtomicStampedReference account = new AtomicStampedReference<>(0, 0);
public int getBalance() {
- return this.account.get(new int[1]);
+ return account.getReference();
}
public int getStamp() {
- int[] stamps = new int[1];
- this.account.get(stamps);
- return stamps[0];
+ return account.getStamp();
}
public boolean deposit(int funds) {
diff --git a/core-java-modules/core-java-io-conversions-2/README.md b/core-java-modules/core-java-io-conversions-2/README.md
index 5cb9c21c54..9ce36e7437 100644
--- a/core-java-modules/core-java-io-conversions-2/README.md
+++ b/core-java-modules/core-java-io-conversions-2/README.md
@@ -5,4 +5,5 @@ This module contains articles about core Java input/output(IO) conversions.
### Relevant Articles:
- [Java InputStream to String](https://www.baeldung.com/convert-input-stream-to-string)
- [Java – Write an InputStream to a File](https://www.baeldung.com/convert-input-stream-to-a-file)
+- [Converting a BufferedReader to a JSONObject](https://www.baeldung.com/java-bufferedreader-to-jsonobject)
- More articles: [[<-- prev]](/core-java-modules/core-java-io-conversions)
diff --git a/core-java-modules/core-java-io-conversions-2/pom.xml b/core-java-modules/core-java-io-conversions-2/pom.xml
index 5312ad645d..46bce7988b 100644
--- a/core-java-modules/core-java-io-conversions-2/pom.xml
+++ b/core-java-modules/core-java-io-conversions-2/pom.xml
@@ -21,6 +21,11 @@
commons-lang3
${commons-lang3.version}
+
+ org.json
+ json
+ 20200518
+
diff --git a/core-java-modules/core-java-io-conversions-2/src/test/java/com/baeldung/bufferedreadertojsonobject/JavaBufferedReaderToJSONObjectUnitTest.java b/core-java-modules/core-java-io-conversions-2/src/test/java/com/baeldung/bufferedreadertojsonobject/JavaBufferedReaderToJSONObjectUnitTest.java
new file mode 100644
index 0000000000..80007e9c2f
--- /dev/null
+++ b/core-java-modules/core-java-io-conversions-2/src/test/java/com/baeldung/bufferedreadertojsonobject/JavaBufferedReaderToJSONObjectUnitTest.java
@@ -0,0 +1,48 @@
+package com.baeldung.bufferedreadertojsonobject;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.nio.charset.StandardCharsets;
+
+import org.json.JSONObject;
+import org.json.JSONTokener;
+import org.junit.Test;
+
+public class JavaBufferedReaderToJSONObjectUnitTest {
+
+ @Test
+ public void givenValidJson_whenUsingBufferedReader_thenJSONTokenerConverts() {
+ byte[] b = "{ \"name\" : \"John\", \"age\" : 18 }".getBytes(StandardCharsets.UTF_8);
+ InputStream is = new ByteArrayInputStream(b);
+ BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(is));
+ JSONTokener tokener = new JSONTokener(bufferedReader);
+ JSONObject json = new JSONObject(tokener);
+
+ assertNotNull(json);
+ assertEquals("John", json.get("name"));
+ assertEquals(18, json.get("age"));
+ }
+
+ @Test
+ public void givenValidJson_whenUsingString_thenJSONObjectConverts() throws IOException {
+ byte[] b = "{ \"name\" : \"John\", \"age\" : 18 }".getBytes(StandardCharsets.UTF_8);
+ InputStream is = new ByteArrayInputStream(b);
+ BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(is));
+ StringBuilder sb = new StringBuilder();
+ String line;
+ while ((line = bufferedReader.readLine()) != null) {
+ sb.append(line);
+ }
+ JSONObject json = new JSONObject(sb.toString());
+
+ assertNotNull(json);
+ assertEquals("John", json.get("name"));
+ assertEquals(18, json.get("age"));
+ }
+}
diff --git a/core-java-modules/core-java-jvm/src/test/java/com/baeldung/error/oom/ExecutorServiceUnitTest.java b/core-java-modules/core-java-jvm/src/test/java/com/baeldung/error/oom/ExecutorServiceUnitTest.java
new file mode 100644
index 0000000000..47bb668727
--- /dev/null
+++ b/core-java-modules/core-java-jvm/src/test/java/com/baeldung/error/oom/ExecutorServiceUnitTest.java
@@ -0,0 +1,40 @@
+package com.baeldung.error.oom;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.IntStream;
+
+import org.junit.jupiter.api.Test;
+
+public class ExecutorServiceUnitTest {
+
+ @Test
+ public void givenAnExecutorService_WhenMoreTasksSubmitted_ThenAdditionalTasksWait() {
+
+ // Given
+ int noOfThreads = 5;
+ ExecutorService executorService = Executors.newFixedThreadPool(noOfThreads);
+
+ Runnable runnableTask = () -> {
+ try {
+ TimeUnit.HOURS.sleep(1);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ };
+
+ // When
+ IntStream.rangeClosed(1, 10)
+ .forEach(i -> executorService.submit(runnableTask));
+
+ // Then
+ assertThat(((ThreadPoolExecutor) executorService).getQueue()
+ .size(), is(equalTo(5)));
+ }
+}
diff --git a/core-java-modules/core-java-lang-2/src/main/java/com/baeldung/inttoenum/PizzaStatus.java b/core-java-modules/core-java-lang-2/src/main/java/com/baeldung/inttoenum/PizzaStatus.java
new file mode 100644
index 0000000000..8d7c626521
--- /dev/null
+++ b/core-java-modules/core-java-lang-2/src/main/java/com/baeldung/inttoenum/PizzaStatus.java
@@ -0,0 +1,36 @@
+package com.baeldung.inttoenum;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public enum PizzaStatus {
+ ORDERED(5),
+ READY(2),
+ DELIVERED(0);
+
+ private int timeToDelivery;
+
+ PizzaStatus(int timeToDelivery) {
+ this.timeToDelivery = timeToDelivery;
+ }
+
+ public int getTimeToDelivery() {
+ return timeToDelivery;
+ }
+
+ private static Map timeToDeliveryToEnumValuesMapping = new HashMap<>();
+
+ static {
+ PizzaStatus[] pizzaStatuses = PizzaStatus.values();
+ for (int pizzaStatusIndex = 0; pizzaStatusIndex < pizzaStatuses.length; pizzaStatusIndex++) {
+ timeToDeliveryToEnumValuesMapping.put(
+ pizzaStatuses[pizzaStatusIndex].getTimeToDelivery(),
+ pizzaStatuses[pizzaStatusIndex]
+ );
+ }
+ }
+
+ public static PizzaStatus castIntToEnum(int timeToDelivery) {
+ return timeToDeliveryToEnumValuesMapping.get(timeToDelivery);
+ }
+}
\ No newline at end of file
diff --git a/core-java-modules/core-java-lang-2/src/test/java/com/baeldung/inttoenum/IntToEnumUnitTest.java b/core-java-modules/core-java-lang-2/src/test/java/com/baeldung/inttoenum/IntToEnumUnitTest.java
new file mode 100644
index 0000000000..876c230827
--- /dev/null
+++ b/core-java-modules/core-java-lang-2/src/test/java/com/baeldung/inttoenum/IntToEnumUnitTest.java
@@ -0,0 +1,27 @@
+package com.baeldung.inttoenum;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+public class IntToEnumUnitTest {
+
+ @Test
+ public void whenIntToEnumUsingValuesMethod_thenReturnEnumObject() {
+ int timeToDeliveryForOrderedPizzaStatus = 5;
+ PizzaStatus[] pizzaStatuses = PizzaStatus.values();
+ PizzaStatus pizzaOrderedStatus = null;
+ for (int pizzaStatusIndex = 0; pizzaStatusIndex < pizzaStatuses.length; pizzaStatusIndex++) {
+ if (pizzaStatuses[pizzaStatusIndex].getTimeToDelivery() == timeToDeliveryForOrderedPizzaStatus) {
+ pizzaOrderedStatus = pizzaStatuses[pizzaStatusIndex];
+ }
+ }
+ assertEquals(pizzaOrderedStatus, PizzaStatus.ORDERED);
+ }
+
+ @Test
+ public void whenIntToEnumUsingMap_thenReturnEnumObject() {
+ int timeToDeliveryForOrderedPizzaStatus = 5;
+ assertEquals(PizzaStatus.castIntToEnum(timeToDeliveryForOrderedPizzaStatus), PizzaStatus.ORDERED);
+ }
+}
\ No newline at end of file
diff --git a/core-java-modules/core-java-lang-oop-generics/src/main/java/com/baeldung/supertype/TypeReference.java b/core-java-modules/core-java-lang-oop-generics/src/main/java/com/baeldung/supertype/TypeReference.java
new file mode 100644
index 0000000000..2021f42239
--- /dev/null
+++ b/core-java-modules/core-java-lang-oop-generics/src/main/java/com/baeldung/supertype/TypeReference.java
@@ -0,0 +1,18 @@
+package com.baeldung.supertype;
+
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+
+public abstract class TypeReference {
+
+ private final Type type;
+
+ public TypeReference() {
+ Type superclass = getClass().getGenericSuperclass();
+ type = ((ParameterizedType) superclass).getActualTypeArguments()[0];
+ }
+
+ public Type getType() {
+ return type;
+ }
+}
diff --git a/core-java-modules/core-java-lang-oop-generics/src/test/java/com/baeldung/supertype/TypeReferenceUnitTest.java b/core-java-modules/core-java-lang-oop-generics/src/test/java/com/baeldung/supertype/TypeReferenceUnitTest.java
new file mode 100644
index 0000000000..24e3b698e2
--- /dev/null
+++ b/core-java-modules/core-java-lang-oop-generics/src/test/java/com/baeldung/supertype/TypeReferenceUnitTest.java
@@ -0,0 +1,24 @@
+package com.baeldung.supertype;
+
+import org.junit.Test;
+
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.Map;
+
+import static org.junit.Assert.assertEquals;
+
+public class TypeReferenceUnitTest {
+
+ @Test
+ public void givenGenericToken_whenUsingSuperTypeToken_thenPreservesTheTypeInfo() {
+ TypeReference
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+ ${maven-surefire-plugin.version}
+
+ 0
+
+
+
- 3.8.1
+ UTF-8
+
9
9
- UTF-8
- 3.12.2
+
+ 3.8.1
+ 2.22.2
+
1.0
+
+ 5.6.2
+ 3.12.2
diff --git a/ddd-modules/sharedkernel/pom.xml b/ddd-modules/sharedkernel/pom.xml
index a61f03a494..1afddf1e22 100644
--- a/ddd-modules/sharedkernel/pom.xml
+++ b/ddd-modules/sharedkernel/pom.xml
@@ -11,8 +11,9 @@
com.baeldung.dddmodules
- dddmodules
+ ddd-modules
1.0
+ ../
diff --git a/ddd-modules/shippingcontext/pom.xml b/ddd-modules/shippingcontext/pom.xml
index 2096923f90..25b5882ef1 100644
--- a/ddd-modules/shippingcontext/pom.xml
+++ b/ddd-modules/shippingcontext/pom.xml
@@ -11,8 +11,9 @@
com.baeldung.dddmodules
- dddmodules
+ ddd-modules
1.0
+ ../
diff --git a/ddd/pom.xml b/ddd/pom.xml
index 1253f2ac48..422f9ccd15 100644
--- a/ddd/pom.xml
+++ b/ddd/pom.xml
@@ -17,6 +17,35 @@
../parent-boot-2
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+ ${maven-surefire-plugin.version}
+
+
+
+
+
+
+
+ org.junit
+ junit-bom
+ ${junit-jupiter.version}
+ pom
+ import
+
+
+ org.springframework.boot
+ spring-boot-dependencies
+ ${spring-boot.version}
+ pom
+ import
+
+
+
+
org.springframework.boot
@@ -26,24 +55,6 @@
org.springframework.boot
spring-boot-starter-data-cassandra
-
- org.junit.jupiter
- junit-jupiter-api
- test
-
-
- org.junit.jupiter
- junit-jupiter-engine
- test
-
-
-
-
- org.junit.platform
- junit-platform-launcher
- ${junit-platform.version}
- test
-
org.joda
joda-money
@@ -95,7 +106,10 @@
- 1.0.1
-
+ 2.22.2
+ 1.0.1
+
+ 5.6.2
+
diff --git a/jee-kotlin/pom.xml b/jee-kotlin/pom.xml
index 9191885bd4..45d5d8ece1 100644
--- a/jee-kotlin/pom.xml
+++ b/jee-kotlin/pom.xml
@@ -221,6 +221,7 @@
org.jboss.logmanager.LogManager
${project.basedir}/target/wildfly-${wildfly.version}
+ 8756
${project.basedir}/target/wildfly-${wildfly.version}/modules
false
@@ -278,9 +279,10 @@
2.0.1.Final
1.0.0.Alpha4
+ 1.1.7
+
3.8.0.Final
3.1.3
-
diff --git a/jee-kotlin/src/main/resources/META-INF/persistence.xml b/jee-kotlin/src/main/resources/META-INF/persistence.xml
index daac86868b..0093792810 100644
--- a/jee-kotlin/src/main/resources/META-INF/persistence.xml
+++ b/jee-kotlin/src/main/resources/META-INF/persistence.xml
@@ -7,7 +7,7 @@
java:jboss/datasources/ExampleDS
- com.enpy.entity.Student
+ com.baeldung.jeekotlin.entity.Student
diff --git a/jhipster/jhipster-uaa/gateway/src/main/java/com/baeldung/jhipster/gateway/web/rest/errors/ExceptionTranslator.java b/jhipster/jhipster-uaa/gateway/src/main/java/com/baeldung/jhipster/gateway/web/rest/errors/ExceptionTranslator.java
index d5c9e577a6..fd6e04dadc 100644
--- a/jhipster/jhipster-uaa/gateway/src/main/java/com/baeldung/jhipster/gateway/web/rest/errors/ExceptionTranslator.java
+++ b/jhipster/jhipster-uaa/gateway/src/main/java/com/baeldung/jhipster/gateway/web/rest/errors/ExceptionTranslator.java
@@ -14,6 +14,7 @@ import org.zalando.problem.Problem;
import org.zalando.problem.ProblemBuilder;
import org.zalando.problem.Status;
import org.zalando.problem.spring.web.advice.ProblemHandling;
+import org.zalando.problem.spring.web.advice.security.SecurityAdviceTrait;
import org.zalando.problem.violations.ConstraintViolationProblem;
import javax.annotation.Nonnull;
@@ -28,7 +29,7 @@ import java.util.stream.Collectors;
* The error response follows RFC7807 - Problem Details for HTTP APIs (https://tools.ietf.org/html/rfc7807)
*/
@ControllerAdvice
-public class ExceptionTranslator implements ProblemHandling {
+public class ExceptionTranslator implements ProblemHandling, SecurityAdviceTrait {
/**
* Post-process the Problem payload to add the message key for the front-end if needed
diff --git a/jhipster/jhipster-uaa/quotes/src/main/java/com/baeldung/jhipster/quotes/web/rest/errors/ExceptionTranslator.java b/jhipster/jhipster-uaa/quotes/src/main/java/com/baeldung/jhipster/quotes/web/rest/errors/ExceptionTranslator.java
index 18baa42736..3bf4995405 100644
--- a/jhipster/jhipster-uaa/quotes/src/main/java/com/baeldung/jhipster/quotes/web/rest/errors/ExceptionTranslator.java
+++ b/jhipster/jhipster-uaa/quotes/src/main/java/com/baeldung/jhipster/quotes/web/rest/errors/ExceptionTranslator.java
@@ -14,6 +14,7 @@ import org.zalando.problem.Problem;
import org.zalando.problem.ProblemBuilder;
import org.zalando.problem.Status;
import org.zalando.problem.spring.web.advice.ProblemHandling;
+import org.zalando.problem.spring.web.advice.security.SecurityAdviceTrait;
import org.zalando.problem.violations.ConstraintViolationProblem;
import javax.annotation.Nonnull;
@@ -28,7 +29,7 @@ import java.util.stream.Collectors;
* The error response follows RFC7807 - Problem Details for HTTP APIs (https://tools.ietf.org/html/rfc7807)
*/
@ControllerAdvice
-public class ExceptionTranslator implements ProblemHandling {
+public class ExceptionTranslator implements ProblemHandling, SecurityAdviceTrait {
/**
* Post-process the Problem payload to add the message key for the front-end if needed
diff --git a/jhipster/jhipster-uaa/uaa/src/main/java/com/baeldung/jhipster/uaa/web/rest/errors/ExceptionTranslator.java b/jhipster/jhipster-uaa/uaa/src/main/java/com/baeldung/jhipster/uaa/web/rest/errors/ExceptionTranslator.java
index 320636c51d..6af9fd126c 100644
--- a/jhipster/jhipster-uaa/uaa/src/main/java/com/baeldung/jhipster/uaa/web/rest/errors/ExceptionTranslator.java
+++ b/jhipster/jhipster-uaa/uaa/src/main/java/com/baeldung/jhipster/uaa/web/rest/errors/ExceptionTranslator.java
@@ -14,6 +14,7 @@ import org.zalando.problem.Problem;
import org.zalando.problem.ProblemBuilder;
import org.zalando.problem.Status;
import org.zalando.problem.spring.web.advice.ProblemHandling;
+import org.zalando.problem.spring.web.advice.security.SecurityAdviceTrait;
import org.zalando.problem.violations.ConstraintViolationProblem;
import javax.annotation.Nonnull;
@@ -28,7 +29,7 @@ import java.util.stream.Collectors;
* The error response follows RFC7807 - Problem Details for HTTP APIs (https://tools.ietf.org/html/rfc7807)
*/
@ControllerAdvice
-public class ExceptionTranslator implements ProblemHandling {
+public class ExceptionTranslator implements ProblemHandling, SecurityAdviceTrait {
/**
* Post-process the Problem payload to add the message key for the front-end if needed
diff --git a/jmh/src/main/java/com/baeldung/BenchMark.java b/jmh/src/main/java/com/baeldung/BenchMark.java
index b0e1caf4dc..3c5c840db2 100644
--- a/jmh/src/main/java/com/baeldung/BenchMark.java
+++ b/jmh/src/main/java/com/baeldung/BenchMark.java
@@ -1,14 +1,20 @@
package com.baeldung;
-import com.google.common.hash.HashFunction;
import com.google.common.hash.Hasher;
import com.google.common.hash.Hashing;
import org.openjdk.jmh.annotations.*;
+import org.openjdk.jmh.infra.Blackhole;
import java.nio.charset.Charset;
+import java.util.concurrent.TimeUnit;
public class BenchMark {
+ @State(Scope.Benchmark)
+ public static class Log {
+ public int x = 8;
+ }
+
@State(Scope.Benchmark)
public static class ExecutionPlan {
@@ -45,4 +51,44 @@ public class BenchMark {
// Do nothing
}
+ @Benchmark
+ @OutputTimeUnit(TimeUnit.NANOSECONDS)
+ @BenchmarkMode(Mode.AverageTime)
+ public void doNothing() {
+
+ }
+
+ @Benchmark
+ @OutputTimeUnit(TimeUnit.NANOSECONDS)
+ @BenchmarkMode(Mode.AverageTime)
+ public void objectCreation() {
+ new Object();
+ }
+
+ @Benchmark
+ @OutputTimeUnit(TimeUnit.NANOSECONDS)
+ @BenchmarkMode(Mode.AverageTime)
+ public Object pillarsOfCreation() {
+ return new Object();
+ }
+
+ @Benchmark
+ @OutputTimeUnit(TimeUnit.NANOSECONDS)
+ @BenchmarkMode(Mode.AverageTime)
+ public void blackHole(Blackhole blackhole) {
+ blackhole.consume(new Object());
+ }
+
+ @Benchmark
+ public double foldedLog() {
+ int x = 8;
+
+ return Math.log(x);
+ }
+
+ @Benchmark
+ public double log(Log input) {
+ return Math.log(input.x);
+ }
+
}
diff --git a/language-interop/README.md b/language-interop/README.md
index a28c4a5405..458f34a119 100644
--- a/language-interop/README.md
+++ b/language-interop/README.md
@@ -3,3 +3,5 @@
This module contains articles about Java interop with other language integrations.
### Relevant Articles:
+
+- [How to Call Python From Java](https://www.baeldung.com/java-working-with-python)
diff --git a/libraries-data-2/pom.xml b/libraries-data-2/pom.xml
index cbb24edd3f..bdfb2c5ed6 100644
--- a/libraries-data-2/pom.xml
+++ b/libraries-data-2/pom.xml
@@ -121,6 +121,11 @@
univocity-parsers
${univocity.version}
+
+ org.apache.kafka
+ kafka-clients
+ ${kafka.version}
+
org.awaitility
awaitility
@@ -184,6 +189,7 @@
RELEASE
3.0
1.8.1
+ 2.5.0
diff --git a/libraries-data-2/src/main/java/com/baeldung/kafka/consumer/CountryPopulation.java b/libraries-data-2/src/main/java/com/baeldung/kafka/consumer/CountryPopulation.java
new file mode 100644
index 0000000000..8c1351642f
--- /dev/null
+++ b/libraries-data-2/src/main/java/com/baeldung/kafka/consumer/CountryPopulation.java
@@ -0,0 +1,28 @@
+package com.baeldung.kafka.consumer;
+
+class CountryPopulation {
+
+ private String country;
+ private Integer population;
+
+ public CountryPopulation(String country, Integer population) {
+ this.country = country;
+ this.population = population;
+ }
+
+ public String getCountry() {
+ return country;
+ }
+
+ public void setCountry(String country) {
+ this.country = country;
+ }
+
+ public Integer getPopulation() {
+ return population;
+ }
+
+ public void setPopulation(Integer population) {
+ this.population = population;
+ }
+}
\ No newline at end of file
diff --git a/libraries-data-2/src/main/java/com/baeldung/kafka/consumer/CountryPopulationConsumer.java b/libraries-data-2/src/main/java/com/baeldung/kafka/consumer/CountryPopulationConsumer.java
new file mode 100644
index 0000000000..ba4dfe6f3b
--- /dev/null
+++ b/libraries-data-2/src/main/java/com/baeldung/kafka/consumer/CountryPopulationConsumer.java
@@ -0,0 +1,60 @@
+package com.baeldung.kafka.consumer;
+
+import java.time.Duration;
+import java.util.Collections;
+import java.util.stream.StreamSupport;
+
+import org.apache.kafka.clients.consumer.Consumer;
+import org.apache.kafka.clients.consumer.ConsumerRecords;
+import org.apache.kafka.common.TopicPartition;
+import org.apache.kafka.common.errors.WakeupException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class CountryPopulationConsumer {
+
+ private static Logger logger = LoggerFactory.getLogger(CountryPopulationConsumer.class);
+
+ private Consumer consumer;
+ private java.util.function.Consumer exceptionConsumer;
+ private java.util.function.Consumer countryPopulationConsumer;
+
+ public CountryPopulationConsumer(
+ Consumer consumer, java.util.function.Consumer exceptionConsumer,
+ java.util.function.Consumer countryPopulationConsumer) {
+ this.consumer = consumer;
+ this.exceptionConsumer = exceptionConsumer;
+ this.countryPopulationConsumer = countryPopulationConsumer;
+ }
+
+ void startBySubscribing(String topic) {
+ consume(() -> consumer.subscribe(Collections.singleton(topic)));
+ }
+
+ void startByAssigning(String topic, int partition) {
+ consume(() -> consumer.assign(Collections.singleton(new TopicPartition(topic, partition))));
+ }
+
+ private void consume(Runnable beforePollingTask) {
+ try {
+ beforePollingTask.run();
+ while (true) {
+ ConsumerRecords records = consumer.poll(Duration.ofMillis(1000));
+ StreamSupport.stream(records.spliterator(), false)
+ .map(record -> new CountryPopulation(record.key(), record.value()))
+ .forEach(countryPopulationConsumer);
+ consumer.commitSync();
+ }
+ } catch (WakeupException e) {
+ logger.info("Shutting down...");
+ } catch (RuntimeException ex) {
+ exceptionConsumer.accept(ex);
+ } finally {
+ consumer.close();
+ }
+ }
+
+ public void stop() {
+ consumer.wakeup();
+ }
+}
\ No newline at end of file
diff --git a/libraries-data-2/src/test/java/com/baeldung/kafka/consumer/CountryPopulationConsumerUnitTest.java b/libraries-data-2/src/test/java/com/baeldung/kafka/consumer/CountryPopulationConsumerUnitTest.java
new file mode 100644
index 0000000000..1b49c71716
--- /dev/null
+++ b/libraries-data-2/src/test/java/com/baeldung/kafka/consumer/CountryPopulationConsumerUnitTest.java
@@ -0,0 +1,100 @@
+package com.baeldung.kafka.consumer;
+
+import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+
+import org.apache.kafka.clients.consumer.ConsumerRecord;
+import org.apache.kafka.clients.consumer.MockConsumer;
+import org.apache.kafka.clients.consumer.OffsetResetStrategy;
+import org.apache.kafka.common.KafkaException;
+import org.apache.kafka.common.TopicPartition;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+class CountryPopulationConsumerUnitTest {
+
+ private static final String TOPIC = "topic";
+ private static final int PARTITION = 0;
+
+ private CountryPopulationConsumer countryPopulationConsumer;
+
+ private List updates;
+ private Throwable pollException;
+
+ private MockConsumer consumer;
+
+ @BeforeEach
+ void setUp() {
+ consumer = new MockConsumer<>(OffsetResetStrategy.EARLIEST);
+ updates = new ArrayList<>();
+ countryPopulationConsumer = new CountryPopulationConsumer(consumer, ex -> this.pollException = ex, updates::add);
+ }
+
+ @Test
+ void whenStartingByAssigningTopicPartition_thenExpectUpdatesAreConsumedCorrectly() {
+ // GIVEN
+ consumer.schedulePollTask(() -> consumer.addRecord(record(TOPIC, PARTITION, "Romania", 19_410_000)));
+ consumer.schedulePollTask(() -> countryPopulationConsumer.stop());
+
+ HashMap startOffsets = new HashMap<>();
+ TopicPartition tp = new TopicPartition(TOPIC, PARTITION);
+ startOffsets.put(tp, 0L);
+ consumer.updateBeginningOffsets(startOffsets);
+
+ // WHEN
+ countryPopulationConsumer.startByAssigning(TOPIC, PARTITION);
+
+ // THEN
+ assertThat(updates).hasSize(1);
+ assertThat(consumer.closed()).isTrue();
+ }
+
+ @Test
+ void whenStartingBySubscribingToTopic_thenExpectUpdatesAreConsumedCorrectly() {
+ // GIVEN
+ consumer.schedulePollTask(() -> {
+ consumer.rebalance(Collections.singletonList(new TopicPartition(TOPIC, 0)));
+ consumer.addRecord(record(TOPIC, PARTITION, "Romania", 19_410_000));
+ });
+ consumer.schedulePollTask(() -> countryPopulationConsumer.stop());
+
+ HashMap startOffsets = new HashMap<>();
+ TopicPartition tp = new TopicPartition(TOPIC, PARTITION);
+ startOffsets.put(tp, 0L);
+ consumer.updateBeginningOffsets(startOffsets);
+
+ // WHEN
+ countryPopulationConsumer.startBySubscribing(TOPIC);
+
+ // THEN
+ assertThat(updates).hasSize(1);
+ assertThat(consumer.closed()).isTrue();
+ }
+
+ @Test
+ void whenStartingBySubscribingToTopicAndExceptionOccurs_thenExpectExceptionIsHandledCorrectly() {
+ // GIVEN
+ consumer.schedulePollTask(() -> consumer.setPollException(new KafkaException("poll exception")));
+ consumer.schedulePollTask(() -> countryPopulationConsumer.stop());
+
+ HashMap startOffsets = new HashMap<>();
+ TopicPartition tp = new TopicPartition(TOPIC, 0);
+ startOffsets.put(tp, 0L);
+ consumer.updateBeginningOffsets(startOffsets);
+
+ // WHEN
+ countryPopulationConsumer.startBySubscribing(TOPIC);
+
+ // THEN
+ assertThat(pollException).isInstanceOf(KafkaException.class).hasMessage("poll exception");
+ assertThat(consumer.closed()).isTrue();
+ }
+
+ private ConsumerRecord record(String topic, int partition, String country, int population) {
+ return new ConsumerRecord<>(topic, partition, 0, country, population);
+ }
+}
\ No newline at end of file
diff --git a/libraries-data-db/pom.xml b/libraries-data-db/pom.xml
index f028ffe8c3..d51580ccbc 100644
--- a/libraries-data-db/pom.xml
+++ b/libraries-data-db/pom.xml
@@ -211,7 +211,7 @@
5.0.2
5.0.4
3.2.0-m7
- 2.7.2
+ 3.4.5
11.22.4
diff --git a/libraries-rpc/README.md b/libraries-rpc/README.md
new file mode 100644
index 0000000000..472aa883ad
--- /dev/null
+++ b/libraries-rpc/README.md
@@ -0,0 +1,3 @@
+### Relevant Articles:
+
+- [Introduction to Finagle](https://www.baeldung.com/java-finagle)
diff --git a/libraries-server-2/.gitignore b/libraries-server-2/.gitignore
new file mode 100644
index 0000000000..e594daf27a
--- /dev/null
+++ b/libraries-server-2/.gitignore
@@ -0,0 +1,9 @@
+*.class
+
+# Folders #
+/gensrc
+/target
+
+# Packaged files #
+*.jar
+/bin/
diff --git a/libraries-server-2/README.md b/libraries-server-2/README.md
new file mode 100644
index 0000000000..38166bcd77
--- /dev/null
+++ b/libraries-server-2/README.md
@@ -0,0 +1,8 @@
+## Server
+
+This module contains articles about server libraries.
+
+### Relevant Articles:
+
+- [HTTP/2 in Jetty](https://www.baeldung.com/jetty-http-2)
+- More articles: [[<-- prev]](../libraries-server)
diff --git a/libraries-server-2/pom.xml b/libraries-server-2/pom.xml
new file mode 100644
index 0000000000..5f500a7ced
--- /dev/null
+++ b/libraries-server-2/pom.xml
@@ -0,0 +1,77 @@
+
+
+ 4.0.0
+ libraries-server-2
+ 0.0.1-SNAPSHOT
+ libraries-server-2
+ war
+
+
+ com.baeldung
+ parent-modules
+ 1.0.0-SNAPSHOT
+
+
+
+
+ org.eclipse.jetty
+ jetty-server
+ ${jetty.version}
+
+
+ org.eclipse.jetty
+ jetty-servlet
+ ${jetty.version}
+
+
+ org.eclipse.jetty
+ jetty-webapp
+ ${jetty.version}
+
+
+
+
+
+
+ org.eclipse.jetty
+ jetty-maven-plugin
+ ${jetty.version}
+
+ 8888
+ quit
+
+ -Xbootclasspath/p:${settings.localRepository}/org/mortbay/jetty/alpn/alpn-boot/${alpn.version}/alpn-boot-${alpn.version}.jar
+
+ ${basedir}/src/main/config/jetty.xml
+
+ /
+
+
+
+
+ org.eclipse.jetty.http2
+ http2-server
+ ${jetty.version}
+
+
+ org.eclipse.jetty
+ jetty-alpn-openjdk8-server
+ ${jetty.version}
+
+
+ org.eclipse.jetty
+ jetty-servlets
+ ${jetty.version}
+
+
+
+
+
+
+
+ 9.4.27.v20200227
+ 8.1.11.v20170118
+
+
+
\ No newline at end of file
diff --git a/libraries-server/src/main/config/jetty.xml b/libraries-server-2/src/main/config/jetty.xml
similarity index 100%
rename from libraries-server/src/main/config/jetty.xml
rename to libraries-server-2/src/main/config/jetty.xml
diff --git a/libraries-server/src/main/java/com/baeldung/jetty/http2/Http2JettyServlet.java b/libraries-server-2/src/main/java/com/baeldung/jetty/http2/Http2JettyServlet.java
similarity index 100%
rename from libraries-server/src/main/java/com/baeldung/jetty/http2/Http2JettyServlet.java
rename to libraries-server-2/src/main/java/com/baeldung/jetty/http2/Http2JettyServlet.java
diff --git a/libraries-server/src/main/resources/keystore.jks b/libraries-server-2/src/main/resources/keystore.jks
similarity index 100%
rename from libraries-server/src/main/resources/keystore.jks
rename to libraries-server-2/src/main/resources/keystore.jks
diff --git a/libraries-server-2/src/main/resources/logback.xml b/libraries-server-2/src/main/resources/logback.xml
new file mode 100644
index 0000000000..7d900d8ea8
--- /dev/null
+++ b/libraries-server-2/src/main/resources/logback.xml
@@ -0,0 +1,13 @@
+
+
+
+
+ %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/libraries-server/src/main/resources/truststore.jks b/libraries-server-2/src/main/resources/truststore.jks
similarity index 100%
rename from libraries-server/src/main/resources/truststore.jks
rename to libraries-server-2/src/main/resources/truststore.jks
diff --git a/libraries-server/src/main/webapp/WEB-INF/web.xml b/libraries-server-2/src/main/webapp/WEB-INF/web.xml
similarity index 100%
rename from libraries-server/src/main/webapp/WEB-INF/web.xml
rename to libraries-server-2/src/main/webapp/WEB-INF/web.xml
diff --git a/libraries-server/src/main/webapp/http2.html b/libraries-server-2/src/main/webapp/http2.html
similarity index 100%
rename from libraries-server/src/main/webapp/http2.html
rename to libraries-server-2/src/main/webapp/http2.html
diff --git a/libraries-server/src/main/webapp/images/homepage-latest_articles.jpg b/libraries-server-2/src/main/webapp/images/homepage-latest_articles.jpg
similarity index 100%
rename from libraries-server/src/main/webapp/images/homepage-latest_articles.jpg
rename to libraries-server-2/src/main/webapp/images/homepage-latest_articles.jpg
diff --git a/libraries-server/src/main/webapp/images/homepage-rest_with_spring.jpg b/libraries-server-2/src/main/webapp/images/homepage-rest_with_spring.jpg
similarity index 100%
rename from libraries-server/src/main/webapp/images/homepage-rest_with_spring.jpg
rename to libraries-server-2/src/main/webapp/images/homepage-rest_with_spring.jpg
diff --git a/libraries-server/src/main/webapp/images/homepage-weekly_reviews.jpg b/libraries-server-2/src/main/webapp/images/homepage-weekly_reviews.jpg
similarity index 100%
rename from libraries-server/src/main/webapp/images/homepage-weekly_reviews.jpg
rename to libraries-server-2/src/main/webapp/images/homepage-weekly_reviews.jpg
diff --git a/libraries-server/src/main/webapp/index.html b/libraries-server-2/src/main/webapp/index.html
similarity index 100%
rename from libraries-server/src/main/webapp/index.html
rename to libraries-server-2/src/main/webapp/index.html
diff --git a/libraries-server/README.md b/libraries-server/README.md
index 7e41f33a0c..570806611f 100644
--- a/libraries-server/README.md
+++ b/libraries-server/README.md
@@ -13,4 +13,4 @@ This module contains articles about server libraries.
- [MQTT Client in Java](https://www.baeldung.com/java-mqtt-client)
- [Guide to XMPP Smack Client](https://www.baeldung.com/xmpp-smack-chat-client)
- [A Guide to NanoHTTPD](https://www.baeldung.com/nanohttpd)
-- [HTTP/2 in Jetty](https://www.baeldung.com/jetty-http-2)
+- More articles: [[more -->]](../libraries-server-2)
\ No newline at end of file
diff --git a/libraries-server/pom.xml b/libraries-server/pom.xml
index eb9cb61e56..d9546f1678 100644
--- a/libraries-server/pom.xml
+++ b/libraries-server/pom.xml
@@ -5,7 +5,6 @@
libraries-server
0.0.1-SNAPSHOT
libraries-server
- war
com.baeldung
@@ -107,50 +106,11 @@
-
-
-
- org.eclipse.jetty
- jetty-maven-plugin
- ${jetty.version}
-
- 8888
- quit
-
- -Xbootclasspath/p:${settings.localRepository}/org/mortbay/jetty/alpn/alpn-boot/${alpn.version}/alpn-boot-${alpn.version}.jar
-
- ${basedir}/src/main/config/jetty.xml
-
- /
-
-
-
-
- org.eclipse.jetty.http2
- http2-server
- ${jetty.version}
-
-
- org.eclipse.jetty
- jetty-alpn-openjdk8-server
- ${jetty.version}
-
-
- org.eclipse.jetty
- jetty-servlets
- ${jetty.version}
-
-
-
-
-
-
3.6.2
4.5.3
9.4.27.v20200227
4.1.20.Final
- 8.1.11.v20170118
8.5.24
4.3.1
1.2.0
diff --git a/netflix-modules/genie/README.md b/netflix-modules/genie/README.md
new file mode 100644
index 0000000000..f6e15ba403
--- /dev/null
+++ b/netflix-modules/genie/README.md
@@ -0,0 +1,3 @@
+### Relevant Articles:
+
+- [Introduction to Netflix Genie](https://www.baeldung.com/netflix-genie-intro)
diff --git a/netty/src/main/java/com/baeldung/http/server/CustomHttpServerHandler.java b/netty/src/main/java/com/baeldung/http/server/CustomHttpServerHandler.java
new file mode 100644
index 0000000000..038f559329
--- /dev/null
+++ b/netty/src/main/java/com/baeldung/http/server/CustomHttpServerHandler.java
@@ -0,0 +1,116 @@
+package com.baeldung.http.server;
+
+import static io.netty.handler.codec.http.HttpResponseStatus.BAD_REQUEST;
+import static io.netty.handler.codec.http.HttpResponseStatus.CONTINUE;
+import static io.netty.handler.codec.http.HttpResponseStatus.OK;
+import static io.netty.handler.codec.http.HttpVersion.HTTP_1_1;
+
+import java.util.Set;
+
+import io.netty.buffer.Unpooled;
+import io.netty.channel.ChannelFutureListener;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.channel.SimpleChannelInboundHandler;
+import io.netty.handler.codec.http.DefaultFullHttpResponse;
+import io.netty.handler.codec.http.FullHttpResponse;
+import io.netty.handler.codec.http.HttpContent;
+import io.netty.handler.codec.http.HttpHeaderNames;
+import io.netty.handler.codec.http.HttpHeaderValues;
+import io.netty.handler.codec.http.HttpObject;
+import io.netty.handler.codec.http.HttpRequest;
+import io.netty.handler.codec.http.HttpUtil;
+import io.netty.handler.codec.http.LastHttpContent;
+import io.netty.handler.codec.http.cookie.Cookie;
+import io.netty.handler.codec.http.cookie.ServerCookieDecoder;
+import io.netty.handler.codec.http.cookie.ServerCookieEncoder;
+import io.netty.util.CharsetUtil;
+
+public class CustomHttpServerHandler extends SimpleChannelInboundHandler
diff --git a/persistence-modules/spring-data-elasticsearch/pom.xml b/persistence-modules/spring-data-elasticsearch/pom.xml
index 3446528323..6a983145ee 100644
--- a/persistence-modules/spring-data-elasticsearch/pom.xml
+++ b/persistence-modules/spring-data-elasticsearch/pom.xml
@@ -15,13 +15,7 @@
org.springframework
- spring-core
- ${spring.version}
-
-
-
- org.springframework
- spring-context
+ spring-web
${spring.version}
@@ -36,6 +30,7 @@
elasticsearch
${elasticsearch.version}
+
com.alibaba
fastjson
@@ -49,8 +44,8 @@
- com.vividsolutions
- jts
+ org.locationtech.jts
+ jts-core
${jts.version}
@@ -60,41 +55,19 @@
-
- org.apache.logging.log4j
- log4j-core
- ${log4j.version}
-
-
-
- org.elasticsearch.client
- transport
- ${elasticsearch.version}
-
-
org.springframework
spring-test
${spring.version}
test
-
-
- net.java.dev.jna
- jna
- ${jna.version}
- test
-
- 3.0.8.RELEASE
- 4.5.2
- 5.6.0
+ 4.0.0.RELEASE
+ 7.6.2
1.2.47
- 0.6
- 1.13
- 2.9.1
+ 0.7
+ 1.15.0
-
\ No newline at end of file
diff --git a/persistence-modules/spring-data-elasticsearch/src/main/java/com/baeldung/spring/data/es/config/Config.java b/persistence-modules/spring-data-elasticsearch/src/main/java/com/baeldung/spring/data/es/config/Config.java
index e6ce795b45..51bbe73e9e 100644
--- a/persistence-modules/spring-data-elasticsearch/src/main/java/com/baeldung/spring/data/es/config/Config.java
+++ b/persistence-modules/spring-data-elasticsearch/src/main/java/com/baeldung/spring/data/es/config/Config.java
@@ -1,19 +1,13 @@
package com.baeldung.spring.data.es.config;
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-
-import org.elasticsearch.client.Client;
-import org.elasticsearch.client.transport.TransportClient;
-import org.elasticsearch.common.settings.Settings;
-import org.elasticsearch.common.transport.InetSocketTransportAddress;
-import org.elasticsearch.transport.client.PreBuiltTransportClient;
-import org.springframework.beans.factory.annotation.Value;
+import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
+import org.springframework.data.elasticsearch.client.ClientConfiguration;
+import org.springframework.data.elasticsearch.client.RestClients;
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
-import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
+import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.repository.config.EnableElasticsearchRepositories;
@Configuration
@@ -21,30 +15,18 @@ import org.springframework.data.elasticsearch.repository.config.EnableElasticsea
@ComponentScan(basePackages = { "com.baeldung.spring.data.es.service" })
public class Config {
- @Value("${elasticsearch.home:/usr/local/Cellar/elasticsearch/5.6.0}")
- private String elasticsearchHome;
-
- @Value("${elasticsearch.cluster.name:elasticsearch}")
- private String clusterName;
-
@Bean
- public Client client() {
- TransportClient client = null;
- try {
- final Settings elasticsearchSettings = Settings.builder()
- .put("client.transport.sniff", true)
- .put("path.home", elasticsearchHome)
- .put("cluster.name", clusterName).build();
- client = new PreBuiltTransportClient(elasticsearchSettings);
- client.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"), 9300));
- } catch (UnknownHostException e) {
- e.printStackTrace();
- }
- return client;
+ RestHighLevelClient client() {
+ ClientConfiguration clientConfiguration = ClientConfiguration.builder()
+ .connectedTo("localhost:9200")
+ .build();
+
+ return RestClients.create(clientConfiguration)
+ .rest();
}
@Bean
public ElasticsearchOperations elasticsearchTemplate() {
- return new ElasticsearchTemplate(client());
+ return new ElasticsearchRestTemplate(client());
}
}
diff --git a/persistence-modules/spring-data-elasticsearch/src/main/java/com/baeldung/spring/data/es/model/Author.java b/persistence-modules/spring-data-elasticsearch/src/main/java/com/baeldung/spring/data/es/model/Author.java
index 38f50e1614..1d596cd92b 100644
--- a/persistence-modules/spring-data-elasticsearch/src/main/java/com/baeldung/spring/data/es/model/Author.java
+++ b/persistence-modules/spring-data-elasticsearch/src/main/java/com/baeldung/spring/data/es/model/Author.java
@@ -1,7 +1,12 @@
package com.baeldung.spring.data.es.model;
+import static org.springframework.data.elasticsearch.annotations.FieldType.Text;
+
+import org.springframework.data.elasticsearch.annotations.Field;
+
public class Author {
+ @Field(type = Text)
private String name;
public Author() {
diff --git a/persistence-modules/spring-data-elasticsearch/src/main/java/com/baeldung/spring/data/es/service/ArticleService.java b/persistence-modules/spring-data-elasticsearch/src/main/java/com/baeldung/spring/data/es/service/ArticleService.java
deleted file mode 100644
index a0f72aa5f7..0000000000
--- a/persistence-modules/spring-data-elasticsearch/src/main/java/com/baeldung/spring/data/es/service/ArticleService.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package com.baeldung.spring.data.es.service;
-
-import java.util.Optional;
-
-import org.springframework.data.domain.Page;
-import org.springframework.data.domain.Pageable;
-
-import com.baeldung.spring.data.es.model.Article;
-
-public interface ArticleService {
- Article save(Article article);
-
- Optional findOne(String id);
-
- Iterable findAll();
-
- Page findByAuthorName(String name, Pageable pageable);
-
- Page findByAuthorNameUsingCustomQuery(String name, Pageable pageable);
-
- Page findByFilteredTagQuery(String tag, Pageable pageable);
-
- Page findByAuthorsNameAndFilteredTagQuery(String name, String tag, Pageable pageable);
-
- long count();
-
- void delete(Article article);
-}
diff --git a/persistence-modules/spring-data-elasticsearch/src/main/java/com/baeldung/spring/data/es/service/ArticleServiceImpl.java b/persistence-modules/spring-data-elasticsearch/src/main/java/com/baeldung/spring/data/es/service/ArticleServiceImpl.java
deleted file mode 100644
index 5064f16508..0000000000
--- a/persistence-modules/spring-data-elasticsearch/src/main/java/com/baeldung/spring/data/es/service/ArticleServiceImpl.java
+++ /dev/null
@@ -1,67 +0,0 @@
-package com.baeldung.spring.data.es.service;
-
-import java.util.Optional;
-
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.data.domain.Page;
-import org.springframework.data.domain.Pageable;
-import org.springframework.stereotype.Service;
-
-import com.baeldung.spring.data.es.model.Article;
-import com.baeldung.spring.data.es.repository.ArticleRepository;
-
-@Service
-public class ArticleServiceImpl implements ArticleService {
-
- private final ArticleRepository articleRepository;
-
- @Autowired
- public ArticleServiceImpl(ArticleRepository articleRepository) {
- this.articleRepository = articleRepository;
- }
-
- @Override
- public Article save(Article article) {
- return articleRepository.save(article);
- }
-
- @Override
- public Optional findOne(String id) {
- return articleRepository.findById(id);
- }
-
- @Override
- public Iterable findAll() {
- return articleRepository.findAll();
- }
-
- @Override
- public Page findByAuthorName(String name, Pageable pageable) {
- return articleRepository.findByAuthorsName(name, pageable);
- }
-
- @Override
- public Page findByAuthorNameUsingCustomQuery(String name, Pageable pageable) {
- return articleRepository.findByAuthorsNameUsingCustomQuery(name, pageable);
- }
-
- @Override
- public Page findByFilteredTagQuery(String tag, Pageable pageable) {
- return articleRepository.findByFilteredTagQuery(tag, pageable);
- }
-
- @Override
- public Page findByAuthorsNameAndFilteredTagQuery(String name, String tag, Pageable pageable) {
- return articleRepository.findByAuthorsNameAndFilteredTagQuery(name, tag, pageable);
- }
-
- @Override
- public long count() {
- return articleRepository.count();
- }
-
- @Override
- public void delete(Article article) {
- articleRepository.delete(article);
- }
-}
diff --git a/persistence-modules/spring-data-elasticsearch/src/test/java/com/baeldung/SpringContextManualTest.java b/persistence-modules/spring-data-elasticsearch/src/test/java/com/baeldung/SpringContextManualTest.java
index c69deeb77c..6572896eca 100644
--- a/persistence-modules/spring-data-elasticsearch/src/test/java/com/baeldung/SpringContextManualTest.java
+++ b/persistence-modules/spring-data-elasticsearch/src/test/java/com/baeldung/SpringContextManualTest.java
@@ -8,10 +8,10 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.baeldung.spring.data.es.config.Config;
/**
+ * This Manual test requires: Elasticsearch instance running on localhost:9200.
*
- * This Manual test requires:
- * * Elasticsearch instance running on host
- *
+ * The following docker command can be used: docker run -d --name es762 -p
+ * 9200:9200 -e "discovery.type=single-node" elasticsearch:7.6.2
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = Config.class)
diff --git a/persistence-modules/spring-data-elasticsearch/src/test/java/com/baeldung/elasticsearch/ElasticSearchManualTest.java b/persistence-modules/spring-data-elasticsearch/src/test/java/com/baeldung/elasticsearch/ElasticSearchManualTest.java
index e43dcdf43e..2ca5f28f13 100644
--- a/persistence-modules/spring-data-elasticsearch/src/test/java/com/baeldung/elasticsearch/ElasticSearchManualTest.java
+++ b/persistence-modules/spring-data-elasticsearch/src/test/java/com/baeldung/elasticsearch/ElasticSearchManualTest.java
@@ -3,43 +3,48 @@ package com.baeldung.elasticsearch;
import static org.junit.Assert.assertEquals;
import java.io.IOException;
-import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import com.alibaba.fastjson.JSON;
import org.elasticsearch.action.DocWriteResponse.Result;
+import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.delete.DeleteResponse;
+import org.elasticsearch.action.get.GetRequest;
+import org.elasticsearch.action.get.GetResponse;
+import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
+import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.search.SearchType;
-import org.elasticsearch.client.Client;
-import org.elasticsearch.common.settings.Settings;
-import org.elasticsearch.common.transport.InetSocketTransportAddress;
+import org.elasticsearch.client.RequestOptions;
+import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
-import org.elasticsearch.transport.client.PreBuiltTransportClient;
+import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.junit.Before;
import org.junit.Test;
-
-import com.alibaba.fastjson.JSON;
+import org.springframework.data.elasticsearch.client.ClientConfiguration;
+import org.springframework.data.elasticsearch.client.RestClients;
/**
+ * This Manual test requires: Elasticsearch instance running on localhost:9200.
*
- * This Manual test requires:
- * * Elasticsearch instance running on host
- * * with cluster name = elasticsearch
- *
+ * The following docker command can be used: docker run -d --name es762 -p
+ * 9200:9200 -e "discovery.type=single-node" elasticsearch:7.6.2
*/
public class ElasticSearchManualTest {
private List listOfPersons = new ArrayList<>();
- private Client client = null;
+ private RestHighLevelClient client = null;
@Before
public void setUp() throws UnknownHostException {
@@ -47,115 +52,122 @@ public class ElasticSearchManualTest {
Person person2 = new Person(25, "Janette Doe", new Date());
listOfPersons.add(person1);
listOfPersons.add(person2);
-
- client = new PreBuiltTransportClient(Settings.builder().put("client.transport.sniff", true)
- .put("cluster.name","elasticsearch").build())
- .addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"), 9300));
+
+ ClientConfiguration clientConfiguration = ClientConfiguration.builder()
+ .connectedTo("localhost:9200")
+ .build();
+ client = RestClients.create(clientConfiguration)
+ .rest();
}
@Test
- public void givenJsonString_whenJavaObject_thenIndexDocument() {
+ public void givenJsonString_whenJavaObject_thenIndexDocument() throws Exception {
String jsonObject = "{\"age\":20,\"dateOfBirth\":1471466076564,\"fullName\":\"John Doe\"}";
- IndexResponse response = client
- .prepareIndex("people", "Doe")
- .setSource(jsonObject, XContentType.JSON)
- .get();
+ IndexRequest request = new IndexRequest("people");
+ request.source(jsonObject, XContentType.JSON);
+
+ IndexResponse response = client.index(request, RequestOptions.DEFAULT);
String index = response.getIndex();
- String type = response.getType();
+ long version = response.getVersion();
assertEquals(Result.CREATED, response.getResult());
- assertEquals(index, "people");
- assertEquals(type, "Doe");
+ assertEquals(1, version);
+ assertEquals("people", index);
}
@Test
- public void givenDocumentId_whenJavaObject_thenDeleteDocument() {
+ public void givenDocumentId_whenJavaObject_thenDeleteDocument() throws Exception {
String jsonObject = "{\"age\":10,\"dateOfBirth\":1471455886564,\"fullName\":\"Johan Doe\"}";
- IndexResponse response = client
- .prepareIndex("people", "Doe")
- .setSource(jsonObject, XContentType.JSON)
- .get();
+ IndexRequest indexRequest = new IndexRequest("people");
+ indexRequest.source(jsonObject, XContentType.JSON);
+
+ IndexResponse response = client.index(indexRequest, RequestOptions.DEFAULT);
String id = response.getId();
- DeleteResponse deleteResponse = client
- .prepareDelete("people", "Doe", id)
- .get();
- assertEquals(Result.DELETED,deleteResponse.getResult());
+ GetRequest getRequest = new GetRequest("people");
+ getRequest.id(id);
+
+ GetResponse getResponse = client.get(getRequest, RequestOptions.DEFAULT);
+ System.out.println(getResponse.getSourceAsString());
+
+ DeleteRequest deleteRequest = new DeleteRequest("people");
+ deleteRequest.id(id);
+
+ DeleteResponse deleteResponse = client.delete(deleteRequest, RequestOptions.DEFAULT);
+
+ assertEquals(Result.DELETED, deleteResponse.getResult());
}
@Test
- public void givenSearchRequest_whenMatchAll_thenReturnAllResults() {
- SearchResponse response = client
- .prepareSearch()
- .execute()
- .actionGet();
- SearchHit[] searchHits = response
- .getHits()
- .getHits();
+ public void givenSearchRequest_whenMatchAll_thenReturnAllResults() throws Exception {
+ SearchRequest searchRequest = new SearchRequest();
+ SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
+ SearchHit[] searchHits = response.getHits()
+ .getHits();
List results = Arrays.stream(searchHits)
- .map(hit -> JSON.parseObject(hit.getSourceAsString(), Person.class))
- .collect(Collectors.toList());
+ .map(hit -> JSON.parseObject(hit.getSourceAsString(), Person.class))
+ .collect(Collectors.toList());
+
+ results.forEach(System.out::println);
}
@Test
- public void givenSearchParameters_thenReturnResults() {
- SearchResponse response = client
- .prepareSearch()
- .setTypes()
- .setSearchType(SearchType.DFS_QUERY_THEN_FETCH)
- .setPostFilter(QueryBuilders
- .rangeQuery("age")
+ public void givenSearchParameters_thenReturnResults() throws Exception {
+ SearchSourceBuilder builder = new SearchSourceBuilder().postFilter(QueryBuilders.rangeQuery("age")
.from(5)
- .to(15))
- .setFrom(0)
- .setSize(60)
- .setExplain(true)
- .execute()
- .actionGet();
+ .to(15));
- SearchResponse response2 = client
- .prepareSearch()
- .setTypes()
- .setSearchType(SearchType.DFS_QUERY_THEN_FETCH)
- .setPostFilter(QueryBuilders.simpleQueryStringQuery("+John -Doe OR Janette"))
- .setFrom(0)
- .setSize(60)
- .setExplain(true)
- .execute()
- .actionGet();
+ SearchRequest searchRequest = new SearchRequest();
+ searchRequest.searchType(SearchType.DFS_QUERY_THEN_FETCH);
+ searchRequest.source(builder);
+
+ SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
+
+ builder = new SearchSourceBuilder().postFilter(QueryBuilders.simpleQueryStringQuery("+John -Doe OR Janette"));
+
+ searchRequest = new SearchRequest();
+ searchRequest.searchType(SearchType.DFS_QUERY_THEN_FETCH);
+ searchRequest.source(builder);
+
+ SearchResponse response2 = client.search(searchRequest, RequestOptions.DEFAULT);
+
+ builder = new SearchSourceBuilder().postFilter(QueryBuilders.matchQuery("John", "Name*"));
+ searchRequest = new SearchRequest();
+ searchRequest.searchType(SearchType.DFS_QUERY_THEN_FETCH);
+ searchRequest.source(builder);
+
+ SearchResponse response3 = client.search(searchRequest, RequestOptions.DEFAULT);
- SearchResponse response3 = client
- .prepareSearch()
- .setTypes()
- .setSearchType(SearchType.DFS_QUERY_THEN_FETCH)
- .setPostFilter(QueryBuilders.matchQuery("John", "Name*"))
- .setFrom(0)
- .setSize(60)
- .setExplain(true)
- .execute()
- .actionGet();
response2.getHits();
response3.getHits();
- final List results = Arrays.stream(response.getHits().getHits())
- .map(hit -> JSON.parseObject(hit.getSourceAsString(), Person.class))
- .collect(Collectors.toList());
+ final List results = Stream.of(response.getHits()
+ .getHits(),
+ response2.getHits()
+ .getHits(),
+ response3.getHits()
+ .getHits())
+ .flatMap(Arrays::stream)
+ .map(hit -> JSON.parseObject(hit.getSourceAsString(), Person.class))
+ .collect(Collectors.toList());
+
+ results.forEach(System.out::println);
}
@Test
public void givenContentBuilder_whenHelpers_thanIndexJson() throws IOException {
- XContentBuilder builder = XContentFactory
- .jsonBuilder()
- .startObject()
- .field("fullName", "Test")
- .field("salary", "11500")
- .field("age", "10")
- .endObject();
- IndexResponse response = client
- .prepareIndex("people", "Doe")
- .setSource(builder)
- .get();
+ XContentBuilder builder = XContentFactory.jsonBuilder()
+ .startObject()
+ .field("fullName", "Test")
+ .field("salary", "11500")
+ .field("age", "10")
+ .endObject();
- assertEquals(Result.CREATED, response.getResult());
+ IndexRequest indexRequest = new IndexRequest("people");
+ indexRequest.source(builder);
+
+ IndexResponse response = client.index(indexRequest, RequestOptions.DEFAULT);
+
+ assertEquals(Result.CREATED, response.getResult());
}
}
diff --git a/persistence-modules/spring-data-elasticsearch/src/test/java/com/baeldung/elasticsearch/GeoQueriesManualTest.java b/persistence-modules/spring-data-elasticsearch/src/test/java/com/baeldung/elasticsearch/GeoQueriesManualTest.java
index f9a42050b6..64b2ea2437 100644
--- a/persistence-modules/spring-data-elasticsearch/src/test/java/com/baeldung/elasticsearch/GeoQueriesManualTest.java
+++ b/persistence-modules/spring-data-elasticsearch/src/test/java/com/baeldung/elasticsearch/GeoQueriesManualTest.java
@@ -1,4 +1,5 @@
package com.baeldung.elasticsearch;
+
import static org.junit.Assert.assertTrue;
import java.io.IOException;
@@ -7,162 +8,169 @@ import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
-import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
+import com.baeldung.spring.data.es.config.Config;
+
+import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
+import org.elasticsearch.action.admin.indices.refresh.RefreshRequest;
+import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
+import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
-import org.elasticsearch.client.Client;
+import org.elasticsearch.client.RequestOptions;
+import org.elasticsearch.client.RestHighLevelClient;
+import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.common.geo.GeoPoint;
import org.elasticsearch.common.geo.ShapeRelation;
-import org.elasticsearch.common.geo.builders.ShapeBuilders;
+import org.elasticsearch.common.geo.builders.EnvelopeBuilder;
import org.elasticsearch.common.unit.DistanceUnit;
import org.elasticsearch.common.xcontent.XContentType;
+import org.elasticsearch.index.query.GeoShapeQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
+import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.locationtech.jts.geom.Coordinate;
import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
-import com.baeldung.spring.data.es.config.Config;
-import com.vividsolutions.jts.geom.Coordinate;
-
/**
+ * This Manual test requires: Elasticsearch instance running on localhost:9200.
*
- * This Manual test requires:
- * * Elasticsearch instance running on host
- * * with cluster name = elasticsearch
- * * and further configurations
- *
+ * The following docker command can be used: docker run -d --name es762 -p
+ * 9200:9200 -e "discovery.type=single-node" elasticsearch:7.6.2
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = Config.class)
public class GeoQueriesManualTest {
private static final String WONDERS_OF_WORLD = "wonders-of-world";
- private static final String WONDERS = "Wonders";
@Autowired
- private ElasticsearchTemplate elasticsearchTemplate;
-
- @Autowired
- private Client client;
+ private RestHighLevelClient client;
@Before
- public void setUp() {
- String jsonObject = "{\"Wonders\":{\"properties\":{\"name\":{\"type\":\"string\",\"index\":\"not_analyzed\"},\"region\":{\"type\":\"geo_shape\",\"tree\":\"quadtree\",\"precision\":\"1m\"},\"location\":{\"type\":\"geo_point\"}}}}";
+ public void setUp() throws Exception {
+ String jsonObject = "{\"properties\":{\"name\":{\"type\":\"text\",\"index\":false},\"region\":{\"type\":\"geo_shape\"},\"location\":{\"type\":\"geo_point\"}}}";
+
CreateIndexRequest req = new CreateIndexRequest(WONDERS_OF_WORLD);
- req.mapping(WONDERS, jsonObject, XContentType.JSON);
- client.admin()
- .indices()
- .create(req)
- .actionGet();
+ req.mapping(jsonObject, XContentType.JSON);
+
+ client.indices()
+ .create(req, RequestOptions.DEFAULT);
}
@Test
- public void givenGeoShapeData_whenExecutedGeoShapeQuery_thenResultNonEmpty() throws IOException{
+ public void givenGeoShapeData_whenExecutedGeoShapeQuery_thenResultNonEmpty() throws IOException {
String jsonObject = "{\"name\":\"Agra\",\"region\":{\"type\":\"envelope\",\"coordinates\":[[75,30.2],[80.1, 25]]}}";
- IndexResponse response = client.prepareIndex(WONDERS_OF_WORLD, WONDERS)
- .setSource(jsonObject, XContentType.JSON)
- .get();
-
+ IndexRequest indexRequest = new IndexRequest(WONDERS_OF_WORLD);
+ indexRequest.source(jsonObject, XContentType.JSON);
+ IndexResponse response = client.index(indexRequest, RequestOptions.DEFAULT);
+
String tajMahalId = response.getId();
- client.admin()
- .indices()
- .prepareRefresh(WONDERS_OF_WORLD)
- .get();
- Coordinate topLeft =new Coordinate(74, 31.2);
- Coordinate bottomRight =new Coordinate(81.1, 24);
- QueryBuilder qb = QueryBuilders
- .geoShapeQuery("region", ShapeBuilders.newEnvelope(topLeft, bottomRight))
- .relation(ShapeRelation.WITHIN);
+ RefreshRequest refreshRequest = new RefreshRequest(WONDERS_OF_WORLD);
+ client.indices()
+ .refresh(refreshRequest, RequestOptions.DEFAULT);
+ Coordinate topLeft = new Coordinate(74, 31.2);
+ Coordinate bottomRight = new Coordinate(81.1, 24);
- SearchResponse searchResponse = client.prepareSearch(WONDERS_OF_WORLD)
- .setTypes(WONDERS)
- .setQuery(qb)
- .execute()
- .actionGet();
+ GeoShapeQueryBuilder qb = QueryBuilders.geoShapeQuery("region", new EnvelopeBuilder(topLeft, bottomRight).buildGeometry());
+ qb.relation(ShapeRelation.INTERSECTS);
+
+ SearchSourceBuilder source = new SearchSourceBuilder().query(qb);
+ SearchRequest searchRequest = new SearchRequest(WONDERS_OF_WORLD);
+ searchRequest.source(source);
+
+ SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
List ids = Arrays.stream(searchResponse.getHits()
- .getHits())
- .map(SearchHit::getId)
- .collect(Collectors.toList());
+ .getHits())
+ .map(SearchHit::getId)
+ .collect(Collectors.toList());
assertTrue(ids.contains(tajMahalId));
}
@Test
- public void givenGeoPointData_whenExecutedGeoBoundingBoxQuery_thenResultNonEmpty() {
+ public void givenGeoPointData_whenExecutedGeoBoundingBoxQuery_thenResultNonEmpty() throws Exception {
String jsonObject = "{\"name\":\"Pyramids of Giza\",\"location\":[31.131302,29.976480]}";
- IndexResponse response = client.prepareIndex(WONDERS_OF_WORLD, WONDERS)
- .setSource(jsonObject, XContentType.JSON)
- .get();
+
+ IndexRequest indexRequest = new IndexRequest(WONDERS_OF_WORLD);
+ indexRequest.source(jsonObject, XContentType.JSON);
+ IndexResponse response = client.index(indexRequest, RequestOptions.DEFAULT);
+
String pyramidsOfGizaId = response.getId();
- client.admin()
- .indices()
- .prepareRefresh(WONDERS_OF_WORLD)
- .get();
+
+ RefreshRequest refreshRequest = new RefreshRequest(WONDERS_OF_WORLD);
+ client.indices()
+ .refresh(refreshRequest, RequestOptions.DEFAULT);
QueryBuilder qb = QueryBuilders.geoBoundingBoxQuery("location")
- .setCorners(31,30,28,32);
-
- SearchResponse searchResponse = client.prepareSearch(WONDERS_OF_WORLD)
- .setTypes(WONDERS)
- .setQuery(qb)
- .execute()
- .actionGet();
+ .setCorners(31, 30, 28, 32);
+
+ SearchSourceBuilder source = new SearchSourceBuilder().query(qb);
+ SearchRequest searchRequest = new SearchRequest(WONDERS_OF_WORLD);
+ searchRequest.source(source);
+
+ SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
+
List ids = Arrays.stream(searchResponse.getHits()
- .getHits())
- .map(SearchHit::getId)
- .collect(Collectors.toList());
+ .getHits())
+ .map(SearchHit::getId)
+ .collect(Collectors.toList());
assertTrue(ids.contains(pyramidsOfGizaId));
}
@Test
- public void givenGeoPointData_whenExecutedGeoDistanceQuery_thenResultNonEmpty() {
+ public void givenGeoPointData_whenExecutedGeoDistanceQuery_thenResultNonEmpty() throws Exception {
String jsonObject = "{\"name\":\"Lighthouse of alexandria\",\"location\":[31.131302,29.976480]}";
- IndexResponse response = client.prepareIndex(WONDERS_OF_WORLD, WONDERS)
- .setSource(jsonObject, XContentType.JSON)
- .get();
+
+ IndexRequest indexRequest = new IndexRequest(WONDERS_OF_WORLD);
+ indexRequest.source(jsonObject, XContentType.JSON);
+ IndexResponse response = client.index(indexRequest, RequestOptions.DEFAULT);
+
String lighthouseOfAlexandriaId = response.getId();
- client.admin()
- .indices()
- .prepareRefresh(WONDERS_OF_WORLD)
- .get();
+
+ RefreshRequest refreshRequest = new RefreshRequest(WONDERS_OF_WORLD);
+ client.indices()
+ .refresh(refreshRequest, RequestOptions.DEFAULT);
QueryBuilder qb = QueryBuilders.geoDistanceQuery("location")
- .point(29.976, 31.131)
- .distance(10, DistanceUnit.MILES);
+ .point(29.976, 31.131)
+ .distance(10, DistanceUnit.MILES);
+
+ SearchSourceBuilder source = new SearchSourceBuilder().query(qb);
+ SearchRequest searchRequest = new SearchRequest(WONDERS_OF_WORLD);
+ searchRequest.source(source);
+
+ SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
- SearchResponse searchResponse = client.prepareSearch(WONDERS_OF_WORLD)
- .setTypes(WONDERS)
- .setQuery(qb)
- .execute()
- .actionGet();
List ids = Arrays.stream(searchResponse.getHits()
- .getHits())
- .map(SearchHit::getId)
- .collect(Collectors.toList());
+ .getHits())
+ .map(SearchHit::getId)
+ .collect(Collectors.toList());
assertTrue(ids.contains(lighthouseOfAlexandriaId));
}
@Test
- public void givenGeoPointData_whenExecutedGeoPolygonQuery_thenResultNonEmpty() {
+ public void givenGeoPointData_whenExecutedGeoPolygonQuery_thenResultNonEmpty() throws Exception {
String jsonObject = "{\"name\":\"The Great Rann of Kutch\",\"location\":[69.859741,23.733732]}";
- IndexResponse response = client.prepareIndex(WONDERS_OF_WORLD, WONDERS)
- .setSource(jsonObject, XContentType.JSON)
- .get();
+
+ IndexRequest indexRequest = new IndexRequest(WONDERS_OF_WORLD);
+ indexRequest.source(jsonObject, XContentType.JSON);
+ IndexResponse response = client.index(indexRequest, RequestOptions.DEFAULT);
+
String greatRannOfKutchid = response.getId();
- client.admin()
- .indices()
- .prepareRefresh(WONDERS_OF_WORLD)
- .get();
+
+ RefreshRequest refreshRequest = new RefreshRequest(WONDERS_OF_WORLD);
+ client.indices()
+ .refresh(refreshRequest, RequestOptions.DEFAULT);
List allPoints = new ArrayList();
allPoints.add(new GeoPoint(22.733, 68.859));
@@ -170,20 +178,23 @@ public class GeoQueriesManualTest {
allPoints.add(new GeoPoint(23, 70.859));
QueryBuilder qb = QueryBuilders.geoPolygonQuery("location", allPoints);
- SearchResponse searchResponse = client.prepareSearch(WONDERS_OF_WORLD)
- .setTypes(WONDERS)
- .setQuery(qb)
- .execute()
- .actionGet();
+ SearchSourceBuilder source = new SearchSourceBuilder().query(qb);
+ SearchRequest searchRequest = new SearchRequest(WONDERS_OF_WORLD);
+ searchRequest.source(source);
+
+ SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
+
List ids = Arrays.stream(searchResponse.getHits()
- .getHits())
- .map(SearchHit::getId)
- .collect(Collectors.toList());
+ .getHits())
+ .map(SearchHit::getId)
+ .collect(Collectors.toList());
assertTrue(ids.contains(greatRannOfKutchid));
}
@After
- public void destroy() {
- elasticsearchTemplate.deleteIndex(WONDERS_OF_WORLD);
+ public void destroy() throws Exception {
+ DeleteIndexRequest deleteIndex = new DeleteIndexRequest(WONDERS_OF_WORLD);
+ client.indices()
+ .delete(deleteIndex, RequestOptions.DEFAULT);
}
}
diff --git a/persistence-modules/spring-data-elasticsearch/src/test/java/com/baeldung/spring/data/es/ElasticSearchManualTest.java b/persistence-modules/spring-data-elasticsearch/src/test/java/com/baeldung/spring/data/es/ElasticSearchManualTest.java
index bed2e2ff25..412cd04e09 100644
--- a/persistence-modules/spring-data-elasticsearch/src/test/java/com/baeldung/spring/data/es/ElasticSearchManualTest.java
+++ b/persistence-modules/spring-data-elasticsearch/src/test/java/com/baeldung/spring/data/es/ElasticSearchManualTest.java
@@ -10,68 +10,71 @@ import static org.junit.Assert.assertNotNull;
import java.util.List;
+import com.baeldung.spring.data.es.config.Config;
+import com.baeldung.spring.data.es.model.Article;
+import com.baeldung.spring.data.es.model.Author;
+import com.baeldung.spring.data.es.repository.ArticleRepository;
+
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
-import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
+import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
+import org.springframework.data.elasticsearch.core.SearchHits;
+import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
-import org.springframework.data.elasticsearch.core.query.SearchQuery;
+import org.springframework.data.elasticsearch.core.query.Query;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
-import com.baeldung.spring.data.es.config.Config;
-import com.baeldung.spring.data.es.model.Article;
-import com.baeldung.spring.data.es.model.Author;
-import com.baeldung.spring.data.es.service.ArticleService;
-
/**
+ * This Manual test requires: Elasticsearch instance running on localhost:9200.
*
- * This Manual test requires:
- * * Elasticsearch instance running on host
- * * with cluster name = elasticsearch
- *
+ * The following docker command can be used: docker run -d --name es762 -p
+ * 9200:9200 -e "discovery.type=single-node" elasticsearch:7.6.2
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = Config.class)
public class ElasticSearchManualTest {
@Autowired
- private ElasticsearchTemplate elasticsearchTemplate;
+ private ElasticsearchRestTemplate elasticsearchTemplate;
@Autowired
- private ArticleService articleService;
+ private ArticleRepository articleRepository;
private final Author johnSmith = new Author("John Smith");
private final Author johnDoe = new Author("John Doe");
@Before
public void before() {
- elasticsearchTemplate.deleteIndex(Article.class);
- elasticsearchTemplate.createIndex(Article.class);
- // don't call putMapping() to test the default mappings
-
Article article = new Article("Spring Data Elasticsearch");
article.setAuthors(asList(johnSmith, johnDoe));
article.setTags("elasticsearch", "spring data");
- articleService.save(article);
+ articleRepository.save(article);
article = new Article("Search engines");
article.setAuthors(asList(johnDoe));
article.setTags("search engines", "tutorial");
- articleService.save(article);
+ articleRepository.save(article);
article = new Article("Second Article About Elasticsearch");
article.setAuthors(asList(johnSmith));
article.setTags("elasticsearch", "spring data");
- articleService.save(article);
+ articleRepository.save(article);
article = new Article("Elasticsearch Tutorial");
article.setAuthors(asList(johnDoe));
article.setTags("elasticsearch");
- articleService.save(article);
+ articleRepository.save(article);
+ }
+
+ @After
+ public void after() {
+ articleRepository.deleteAll();
}
@Test
@@ -81,82 +84,85 @@ public class ElasticSearchManualTest {
Article article = new Article("Making Search Elastic");
article.setAuthors(authors);
- article = articleService.save(article);
+ article = articleRepository.save(article);
assertNotNull(article.getId());
}
@Test
public void givenPersistedArticles_whenSearchByAuthorsName_thenRightFound() {
-
- final Page articleByAuthorName = articleService
- .findByAuthorName(johnSmith.getName(), PageRequest.of(0, 10));
+ final Page articleByAuthorName = articleRepository.findByAuthorsName(johnSmith.getName(), PageRequest.of(0, 10));
assertEquals(2L, articleByAuthorName.getTotalElements());
}
@Test
public void givenCustomQuery_whenSearchByAuthorsName_thenArticleIsFound() {
- final Page articleByAuthorName = articleService.findByAuthorNameUsingCustomQuery("Smith", PageRequest.of(0, 10));
+ final Page articleByAuthorName = articleRepository.findByAuthorsNameUsingCustomQuery("Smith", PageRequest.of(0, 10));
assertEquals(2L, articleByAuthorName.getTotalElements());
}
@Test
public void givenTagFilterQuery_whenSearchByTag_thenArticleIsFound() {
- final Page articleByAuthorName = articleService.findByFilteredTagQuery("elasticsearch", PageRequest.of(0, 10));
+ final Page articleByAuthorName = articleRepository.findByFilteredTagQuery("elasticsearch", PageRequest.of(0, 10));
assertEquals(3L, articleByAuthorName.getTotalElements());
}
@Test
public void givenTagFilterQuery_whenSearchByAuthorsName_thenArticleIsFound() {
- final Page articleByAuthorName = articleService.findByAuthorsNameAndFilteredTagQuery("Doe", "elasticsearch", PageRequest.of(0, 10));
+ final Page articleByAuthorName = articleRepository.findByAuthorsNameAndFilteredTagQuery("Doe", "elasticsearch", PageRequest.of(0, 10));
assertEquals(2L, articleByAuthorName.getTotalElements());
}
@Test
public void givenPersistedArticles_whenUseRegexQuery_thenRightArticlesFound() {
+ final Query searchQuery = new NativeSearchQueryBuilder().withFilter(regexpQuery("title", ".*data.*"))
+ .build();
- final SearchQuery searchQuery = new NativeSearchQueryBuilder().withFilter(regexpQuery("title", ".*data.*"))
- .build();
- final List articles = elasticsearchTemplate.queryForList(searchQuery, Article.class);
+ final SearchHits articles = elasticsearchTemplate.search(searchQuery, Article.class, IndexCoordinates.of("blog"));
- assertEquals(1, articles.size());
+ assertEquals(1, articles.getTotalHits());
}
@Test
public void givenSavedDoc_whenTitleUpdated_thenCouldFindByUpdatedTitle() {
- final SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(fuzzyQuery("title", "serch")).build();
- final List articles = elasticsearchTemplate.queryForList(searchQuery, Article.class);
+ final Query searchQuery = new NativeSearchQueryBuilder().withQuery(fuzzyQuery("title", "serch"))
+ .build();
+ final SearchHits articles = elasticsearchTemplate.search(searchQuery, Article.class, IndexCoordinates.of("blog"));
- assertEquals(1, articles.size());
+ assertEquals(1, articles.getTotalHits());
- final Article article = articles.get(0);
+ final Article article = articles.getSearchHit(0)
+ .getContent();
final String newTitle = "Getting started with Search Engines";
article.setTitle(newTitle);
- articleService.save(article);
+ articleRepository.save(article);
- assertEquals(newTitle, articleService.findOne(article.getId()).get().getTitle());
+ assertEquals(newTitle, articleRepository.findById(article.getId())
+ .get()
+ .getTitle());
}
@Test
public void givenSavedDoc_whenDelete_thenRemovedFromIndex() {
-
final String articleTitle = "Spring Data Elasticsearch";
- final SearchQuery searchQuery = new NativeSearchQueryBuilder()
- .withQuery(matchQuery("title", articleTitle).minimumShouldMatch("75%")).build();
- final List articles = elasticsearchTemplate.queryForList(searchQuery, Article.class);
- assertEquals(1, articles.size());
- final long count = articleService.count();
+ final Query searchQuery = new NativeSearchQueryBuilder().withQuery(matchQuery("title", articleTitle).minimumShouldMatch("75%"))
+ .build();
+ final SearchHits articles = elasticsearchTemplate.search(searchQuery, Article.class, IndexCoordinates.of("blog"));
- articleService.delete(articles.get(0));
+ assertEquals(1, articles.getTotalHits());
+ final long count = articleRepository.count();
- assertEquals(count - 1, articleService.count());
+ articleRepository.delete(articles.getSearchHit(0)
+ .getContent());
+
+ assertEquals(count - 1, articleRepository.count());
}
@Test
public void givenSavedDoc_whenOneTermMatches_thenFindByTitle() {
- final SearchQuery searchQuery = new NativeSearchQueryBuilder()
- .withQuery(matchQuery("title", "Search engines").operator(AND)).build();
- final List articles = elasticsearchTemplate.queryForList(searchQuery, Article.class);
- assertEquals(1, articles.size());
+ final Query searchQuery = new NativeSearchQueryBuilder().withQuery(matchQuery("title", "Search engines").operator(AND))
+ .build();
+ final SearchHits articles = elasticsearchTemplate.search(searchQuery, Article.class, IndexCoordinates.of("blog"));
+ assertEquals(1, articles.getTotalHits());
}
}
diff --git a/persistence-modules/spring-data-elasticsearch/src/test/java/com/baeldung/spring/data/es/ElasticSearchQueryManualTest.java b/persistence-modules/spring-data-elasticsearch/src/test/java/com/baeldung/spring/data/es/ElasticSearchQueryManualTest.java
index 5e24d8398c..aaf0c80097 100644
--- a/persistence-modules/spring-data-elasticsearch/src/test/java/com/baeldung/spring/data/es/ElasticSearchQueryManualTest.java
+++ b/persistence-modules/spring-data-elasticsearch/src/test/java/com/baeldung/spring/data/es/ElasticSearchQueryManualTest.java
@@ -2,7 +2,6 @@ package com.baeldung.spring.data.es;
import static java.util.Arrays.asList;
import static java.util.stream.Collectors.toList;
-import static org.elasticsearch.index.query.Operator.AND;
import static org.elasticsearch.index.query.QueryBuilders.boolQuery;
import static org.elasticsearch.index.query.QueryBuilders.matchPhraseQuery;
import static org.elasticsearch.index.query.QueryBuilders.matchQuery;
@@ -14,190 +13,225 @@ import static org.junit.Assert.assertEquals;
import java.util.List;
import java.util.Map;
+import com.baeldung.spring.data.es.config.Config;
+import com.baeldung.spring.data.es.model.Article;
+import com.baeldung.spring.data.es.model.Author;
+import com.baeldung.spring.data.es.repository.ArticleRepository;
+
import org.apache.lucene.search.join.ScoreMode;
+import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
-import org.elasticsearch.client.Client;
+import org.elasticsearch.client.RequestOptions;
+import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.unit.Fuzziness;
import org.elasticsearch.index.query.MultiMatchQueryBuilder;
+import org.elasticsearch.index.query.Operator;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.search.aggregations.Aggregation;
import org.elasticsearch.search.aggregations.AggregationBuilders;
+import org.elasticsearch.search.aggregations.BucketOrder;
import org.elasticsearch.search.aggregations.bucket.MultiBucketsAggregation;
-import org.elasticsearch.search.aggregations.bucket.terms.StringTerms;
-import org.elasticsearch.search.aggregations.bucket.terms.Terms;
+import org.elasticsearch.search.aggregations.bucket.terms.ParsedStringTerms;
import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
+import org.elasticsearch.search.builder.SearchSourceBuilder;
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
+import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
+import org.springframework.data.elasticsearch.core.SearchHits;
+import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
+import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
-import org.springframework.data.elasticsearch.core.query.SearchQuery;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
-import com.baeldung.spring.data.es.config.Config;
-import com.baeldung.spring.data.es.model.Article;
-import com.baeldung.spring.data.es.model.Author;
-import com.baeldung.spring.data.es.service.ArticleService;
-
/**
+ * This Manual test requires: Elasticsearch instance running on localhost:9200.
*
- * This Manual test requires:
- * * Elasticsearch instance running on host
- * * with cluster name = elasticsearch
- *
+ * The following docker command can be used: docker run -d --name es762 -p
+ * 9200:9200 -e "discovery.type=single-node" elasticsearch:7.6.2
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = Config.class)
public class ElasticSearchQueryManualTest {
@Autowired
- private ElasticsearchTemplate elasticsearchTemplate;
+ private ElasticsearchRestTemplate elasticsearchTemplate;
@Autowired
- private ArticleService articleService;
+ private ArticleRepository articleRepository;
@Autowired
- private Client client;
+ private RestHighLevelClient client;
private final Author johnSmith = new Author("John Smith");
private final Author johnDoe = new Author("John Doe");
@Before
public void before() {
- elasticsearchTemplate.deleteIndex(Article.class);
- elasticsearchTemplate.createIndex(Article.class);
- elasticsearchTemplate.putMapping(Article.class);
- elasticsearchTemplate.refresh(Article.class);
-
Article article = new Article("Spring Data Elasticsearch");
article.setAuthors(asList(johnSmith, johnDoe));
article.setTags("elasticsearch", "spring data");
- articleService.save(article);
+ articleRepository.save(article);
article = new Article("Search engines");
article.setAuthors(asList(johnDoe));
article.setTags("search engines", "tutorial");
- articleService.save(article);
+ articleRepository.save(article);
article = new Article("Second Article About Elasticsearch");
article.setAuthors(asList(johnSmith));
article.setTags("elasticsearch", "spring data");
- articleService.save(article);
+ articleRepository.save(article);
article = new Article("Elasticsearch Tutorial");
article.setAuthors(asList(johnDoe));
article.setTags("elasticsearch");
- articleService.save(article);
+ articleRepository.save(article);
+ }
+
+ @After
+ public void after() {
+ articleRepository.deleteAll();
}
@Test
public void givenFullTitle_whenRunMatchQuery_thenDocIsFound() {
- final SearchQuery searchQuery = new NativeSearchQueryBuilder()
- .withQuery(matchQuery("title", "Search engines").operator(AND)).build();
- final List articles = elasticsearchTemplate.queryForList(searchQuery, Article.class);
- assertEquals(1, articles.size());
+ final NativeSearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchQuery("title", "Search engines").operator(Operator.AND))
+ .build();
+ final SearchHits articles = elasticsearchTemplate.search(searchQuery, Article.class, IndexCoordinates.of("blog"));
+ assertEquals(1, articles.getTotalHits());
}
@Test
public void givenOneTermFromTitle_whenRunMatchQuery_thenDocIsFound() {
- final SearchQuery searchQuery = new NativeSearchQueryBuilder()
- .withQuery(matchQuery("title", "Engines Solutions")).build();
- final List articles = elasticsearchTemplate.queryForList(searchQuery, Article.class);
- assertEquals(1, articles.size());
- assertEquals("Search engines", articles.get(0).getTitle());
+ final NativeSearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchQuery("title", "Engines Solutions"))
+ .build();
+
+ final SearchHits articles = elasticsearchTemplate.search(searchQuery, Article.class, IndexCoordinates.of("blog"));
+
+ assertEquals(1, articles.getTotalHits());
+ assertEquals("Search engines", articles.getSearchHit(0)
+ .getContent()
+ .getTitle());
}
@Test
public void givenPartTitle_whenRunMatchQuery_thenDocIsFound() {
- final SearchQuery searchQuery = new NativeSearchQueryBuilder()
- .withQuery(matchQuery("title", "elasticsearch data")).build();
- final List articles = elasticsearchTemplate.queryForList(searchQuery, Article.class);
- assertEquals(3, articles.size());
+ final NativeSearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchQuery("title", "elasticsearch data"))
+ .build();
+
+ final SearchHits articles = elasticsearchTemplate.search(searchQuery, Article.class, IndexCoordinates.of("blog"));
+
+ assertEquals(3, articles.getTotalHits());
}
@Test
public void givenFullTitle_whenRunMatchQueryOnVerbatimField_thenDocIsFound() {
- SearchQuery searchQuery = new NativeSearchQueryBuilder()
- .withQuery(matchQuery("title.verbatim", "Second Article About Elasticsearch")).build();
- List articles = elasticsearchTemplate.queryForList(searchQuery, Article.class);
- assertEquals(1, articles.size());
+ NativeSearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchQuery("title.verbatim", "Second Article About Elasticsearch"))
+ .build();
+
+ SearchHits articles = elasticsearchTemplate.search(searchQuery, Article.class, IndexCoordinates.of("blog"));
+
+ assertEquals(1, articles.getTotalHits());
searchQuery = new NativeSearchQueryBuilder().withQuery(matchQuery("title.verbatim", "Second Article About"))
- .build();
- articles = elasticsearchTemplate.queryForList(searchQuery, Article.class);
- assertEquals(0, articles.size());
+ .build();
+
+ articles = elasticsearchTemplate.search(searchQuery, Article.class, IndexCoordinates.of("blog"));
+ assertEquals(0, articles.getTotalHits());
}
@Test
public void givenNestedObject_whenQueryByAuthorsName_thenFoundArticlesByThatAuthor() {
final QueryBuilder builder = nestedQuery("authors", boolQuery().must(termQuery("authors.name", "smith")), ScoreMode.None);
- final SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(builder).build();
- final List articles = elasticsearchTemplate.queryForList(searchQuery, Article.class);
+ final NativeSearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(builder)
+ .build();
+ final SearchHits articles = elasticsearchTemplate.search(searchQuery, Article.class, IndexCoordinates.of("blog"));
- assertEquals(2, articles.size());
+ assertEquals(2, articles.getTotalHits());
}
@Test
- public void givenAnalyzedQuery_whenMakeAggregationOnTermCount_thenEachTokenCountsSeparately() {
- final TermsAggregationBuilder aggregation = AggregationBuilders.terms("top_tags").field("title");
- final SearchResponse response = client.prepareSearch("blog").setTypes("article").addAggregation(aggregation)
- .execute().actionGet();
+ public void givenAnalyzedQuery_whenMakeAggregationOnTermCount_thenEachTokenCountsSeparately() throws Exception {
+ final TermsAggregationBuilder aggregation = AggregationBuilders.terms("top_tags")
+ .field("title");
- final Map results = response.getAggregations().asMap();
- final StringTerms topTags = (StringTerms) results.get("top_tags");
+ final SearchSourceBuilder builder = new SearchSourceBuilder().aggregation(aggregation);
+ final SearchRequest searchRequest = new SearchRequest("blog").source(builder);
- final List keys = topTags.getBuckets().stream()
- .map(MultiBucketsAggregation.Bucket::getKeyAsString)
- .sorted()
- .collect(toList());
+ final SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
+
+ final Map results = response.getAggregations()
+ .asMap();
+ final ParsedStringTerms topTags = (ParsedStringTerms) results.get("top_tags");
+
+ final List keys = topTags.getBuckets()
+ .stream()
+ .map(MultiBucketsAggregation.Bucket::getKeyAsString)
+ .sorted()
+ .collect(toList());
assertEquals(asList("about", "article", "data", "elasticsearch", "engines", "search", "second", "spring", "tutorial"), keys);
}
@Test
- public void givenNotAnalyzedQuery_whenMakeAggregationOnTermCount_thenEachTermCountsIndividually() {
- final TermsAggregationBuilder aggregation = AggregationBuilders.terms("top_tags").field("tags")
- .order(Terms.Order.count(false));
- final SearchResponse response = client.prepareSearch("blog").setTypes("article").addAggregation(aggregation)
- .execute().actionGet();
+ public void givenNotAnalyzedQuery_whenMakeAggregationOnTermCount_thenEachTermCountsIndividually() throws Exception {
+ final TermsAggregationBuilder aggregation = AggregationBuilders.terms("top_tags")
+ .field("tags")
+ .order(BucketOrder.count(false));
- final Map results = response.getAggregations().asMap();
- final StringTerms topTags = (StringTerms) results.get("top_tags");
+ final SearchSourceBuilder builder = new SearchSourceBuilder().aggregation(aggregation);
+ final SearchRequest searchRequest = new SearchRequest().indices("blog")
+ .source(builder);
- final List keys = topTags.getBuckets().stream()
- .map(MultiBucketsAggregation.Bucket::getKeyAsString)
- .collect(toList());
+ final SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
+
+ final Map results = response.getAggregations()
+ .asMap();
+ final ParsedStringTerms topTags = (ParsedStringTerms) results.get("top_tags");
+
+ final List keys = topTags.getBuckets()
+ .stream()
+ .map(MultiBucketsAggregation.Bucket::getKeyAsString)
+ .collect(toList());
assertEquals(asList("elasticsearch", "spring data", "search engines", "tutorial"), keys);
}
@Test
public void givenNotExactPhrase_whenUseSlop_thenQueryMatches() {
- final SearchQuery searchQuery = new NativeSearchQueryBuilder()
- .withQuery(matchPhraseQuery("title", "spring elasticsearch").slop(1)).build();
- final List articles = elasticsearchTemplate.queryForList(searchQuery, Article.class);
- assertEquals(1, articles.size());
+ final NativeSearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchPhraseQuery("title", "spring elasticsearch").slop(1))
+ .build();
+
+ final SearchHits articles = elasticsearchTemplate.search(searchQuery, Article.class, IndexCoordinates.of("blog"));
+
+ assertEquals(1, articles.getTotalHits());
}
@Test
public void givenPhraseWithType_whenUseFuzziness_thenQueryMatches() {
- final SearchQuery searchQuery = new NativeSearchQueryBuilder()
- .withQuery(matchQuery("title", "spring date elasticserch").operator(AND).fuzziness(Fuzziness.ONE)
- .prefixLength(3)).build();
+ final NativeSearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(matchQuery("title", "spring date elasticserch").operator(Operator.AND)
+ .fuzziness(Fuzziness.ONE)
+ .prefixLength(3))
+ .build();
- final List articles = elasticsearchTemplate.queryForList(searchQuery, Article.class);
- assertEquals(1, articles.size());
+ final SearchHits articles = elasticsearchTemplate.search(searchQuery, Article.class, IndexCoordinates.of("blog"));
+
+ assertEquals(1, articles.getTotalHits());
}
@Test
public void givenMultimatchQuery_whenDoSearch_thenAllProvidedFieldsMatch() {
- final SearchQuery searchQuery = new NativeSearchQueryBuilder()
- .withQuery(multiMatchQuery("tutorial").field("title").field("tags")
- .type(MultiMatchQueryBuilder.Type.BEST_FIELDS)).build();
+ final NativeSearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(multiMatchQuery("tutorial").field("title")
+ .field("tags")
+ .type(MultiMatchQueryBuilder.Type.BEST_FIELDS))
+ .build();
- final List articles = elasticsearchTemplate.queryForList(searchQuery, Article.class);
- assertEquals(2, articles.size());
+ final SearchHits articles = elasticsearchTemplate.search(searchQuery, Article.class, IndexCoordinates.of("blog"));
+
+ assertEquals(2, articles.getTotalHits());
}
@Test
@@ -205,10 +239,10 @@ public class ElasticSearchQueryManualTest {
final QueryBuilder builder = boolQuery().must(nestedQuery("authors", boolQuery().must(termQuery("authors.name", "doe")), ScoreMode.None))
.filter(termQuery("tags", "elasticsearch"));
- final SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(builder)
+ final NativeSearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(builder)
.build();
- final List articles = elasticsearchTemplate.queryForList(searchQuery, Article.class);
+ final SearchHits articles = elasticsearchTemplate.search(searchQuery, Article.class, IndexCoordinates.of("blog"));
- assertEquals(2, articles.size());
+ assertEquals(2, articles.getTotalHits());
}
}
diff --git a/persistence-modules/spring-data-jpa-5/pom.xml b/persistence-modules/spring-data-jpa-5/pom.xml
index 3053384559..6a5cdc86c2 100644
--- a/persistence-modules/spring-data-jpa-5/pom.xml
+++ b/persistence-modules/spring-data-jpa-5/pom.xml
@@ -1,6 +1,7 @@
+
4.0.0
spring-data-jpa-5
spring-data-jpa-5
@@ -11,7 +12,7 @@
0.0.1-SNAPSHOT
../../parent-boot-2
-
+
org.springframework.boot
@@ -28,10 +29,43 @@
spring-boot-starter-data-jdbc
+
+ org.springframework.boot
+ spring-boot-starter-cache
+
+
com.h2database
h2
+
+
+ org.mapstruct
+ mapstruct-jdk8
+ 1.3.1.Final
+ provided
+
+
-
+
+ src/main/java
+
+
+ maven-compiler-plugin
+ 3.8.1
+
+ 1.8
+ 1.8
+
+
+ org.mapstruct
+ mapstruct-processor
+ 1.3.1.Final
+
+
+
+
+
+
+
diff --git a/persistence-modules/spring-data-jpa-5/src/main/java/com/baeldung/partialupdate/PartialUpdateApplication.java b/persistence-modules/spring-data-jpa-5/src/main/java/com/baeldung/partialupdate/PartialUpdateApplication.java
new file mode 100644
index 0000000000..a750fcadf7
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-5/src/main/java/com/baeldung/partialupdate/PartialUpdateApplication.java
@@ -0,0 +1,12 @@
+package com.baeldung.partialupdate;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class PartialUpdateApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(PartialUpdateApplication.class, args);
+ }
+}
diff --git a/persistence-modules/spring-data-jpa-5/src/main/java/com/baeldung/partialupdate/model/ContactPhone.java b/persistence-modules/spring-data-jpa-5/src/main/java/com/baeldung/partialupdate/model/ContactPhone.java
new file mode 100644
index 0000000000..352e361bd9
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-5/src/main/java/com/baeldung/partialupdate/model/ContactPhone.java
@@ -0,0 +1,22 @@
+package com.baeldung.partialupdate.model;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+
+@Entity
+public class ContactPhone {
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ public long id;
+ @Column(nullable=false)
+ public long customerId;
+ public String phone;
+
+ @Override
+ public String toString() {
+ return phone;
+ }
+}
diff --git a/persistence-modules/spring-data-jpa-5/src/main/java/com/baeldung/partialupdate/model/Customer.java b/persistence-modules/spring-data-jpa-5/src/main/java/com/baeldung/partialupdate/model/Customer.java
new file mode 100644
index 0000000000..b19d0b7952
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-5/src/main/java/com/baeldung/partialupdate/model/Customer.java
@@ -0,0 +1,23 @@
+package com.baeldung.partialupdate.model;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+
+@Entity
+public class Customer {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ public long id;
+ public String name;
+ public String phone;
+ //...
+ public String phone99;
+
+ @Override public String toString() {
+ return String.format("Customer %s, Phone: %s",
+ this.name, this.phone);
+ }
+}
diff --git a/persistence-modules/spring-data-jpa-5/src/main/java/com/baeldung/partialupdate/model/CustomerDto.java b/persistence-modules/spring-data-jpa-5/src/main/java/com/baeldung/partialupdate/model/CustomerDto.java
new file mode 100644
index 0000000000..0ecf206d9a
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-5/src/main/java/com/baeldung/partialupdate/model/CustomerDto.java
@@ -0,0 +1,31 @@
+package com.baeldung.partialupdate.model;
+
+public class CustomerDto {
+ private long id;
+ public String name;
+ public String phone;
+ //...
+ private String phone99;
+
+ public CustomerDto(long id) {
+ this.id = id;
+ }
+
+ public CustomerDto(Customer c) {
+ this.id = c.id;
+ this.name = c.name;
+ this.phone = c.phone;
+ }
+
+ public long getId() {
+ return this.id;
+ }
+
+ public Customer convertToEntity() {
+ Customer c = new Customer();
+ c.id = id;
+ c.name = name;
+ c.phone = phone;
+ return c;
+ }
+}
diff --git a/persistence-modules/spring-data-jpa-5/src/main/java/com/baeldung/partialupdate/model/CustomerStructured.java b/persistence-modules/spring-data-jpa-5/src/main/java/com/baeldung/partialupdate/model/CustomerStructured.java
new file mode 100644
index 0000000000..dd053a963d
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-5/src/main/java/com/baeldung/partialupdate/model/CustomerStructured.java
@@ -0,0 +1,27 @@
+package com.baeldung.partialupdate.model;
+
+import java.util.List;
+
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.OneToMany;
+
+@Entity
+public class CustomerStructured {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ public long id;
+ public String name;
+ @OneToMany(fetch = FetchType.EAGER, targetEntity = ContactPhone.class, mappedBy = "customerId")
+ public List contactPhones;
+
+ @Override public String toString() {
+ return String.format("Customer %s, Phone: %s",
+ this.name, this.contactPhones.stream()
+ .map(e -> e.toString()).reduce("", String::concat));
+ }
+}
diff --git a/persistence-modules/spring-data-jpa-5/src/main/java/com/baeldung/partialupdate/repository/ContactPhoneRepository.java b/persistence-modules/spring-data-jpa-5/src/main/java/com/baeldung/partialupdate/repository/ContactPhoneRepository.java
new file mode 100644
index 0000000000..4668181e05
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-5/src/main/java/com/baeldung/partialupdate/repository/ContactPhoneRepository.java
@@ -0,0 +1,12 @@
+package com.baeldung.partialupdate.repository;
+
+import org.springframework.data.repository.CrudRepository;
+import org.springframework.stereotype.Repository;
+
+import com.baeldung.partialupdate.model.ContactPhone;
+
+@Repository
+public interface ContactPhoneRepository extends CrudRepository {
+ ContactPhone findById(long id);
+ ContactPhone findByCustomerId(long id);
+}
\ No newline at end of file
diff --git a/persistence-modules/spring-data-jpa-5/src/main/java/com/baeldung/partialupdate/repository/CustomerRepository.java b/persistence-modules/spring-data-jpa-5/src/main/java/com/baeldung/partialupdate/repository/CustomerRepository.java
new file mode 100644
index 0000000000..43e61df8ab
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-5/src/main/java/com/baeldung/partialupdate/repository/CustomerRepository.java
@@ -0,0 +1,18 @@
+package com.baeldung.partialupdate.repository;
+
+import org.springframework.data.jpa.repository.Modifying;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.CrudRepository;
+import org.springframework.data.repository.query.Param;
+import org.springframework.stereotype.Repository;
+
+import com.baeldung.partialupdate.model.Customer;
+
+@Repository
+public interface CustomerRepository extends CrudRepository {
+ Customer findById(long id);
+
+ @Modifying
+ @Query("update Customer u set u.phone = :phone where u.id = :id")
+ void updatePhone(@Param(value = "id") long id, @Param(value = "phone") String phone);
+}
\ No newline at end of file
diff --git a/persistence-modules/spring-data-jpa-5/src/main/java/com/baeldung/partialupdate/repository/CustomerStructuredRepository.java b/persistence-modules/spring-data-jpa-5/src/main/java/com/baeldung/partialupdate/repository/CustomerStructuredRepository.java
new file mode 100644
index 0000000000..0f9fd1e92e
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-5/src/main/java/com/baeldung/partialupdate/repository/CustomerStructuredRepository.java
@@ -0,0 +1,11 @@
+package com.baeldung.partialupdate.repository;
+
+import org.springframework.data.repository.CrudRepository;
+import org.springframework.stereotype.Repository;
+
+import com.baeldung.partialupdate.model.CustomerStructured;
+
+@Repository
+public interface CustomerStructuredRepository extends CrudRepository {
+ CustomerStructured findById(long id);
+}
\ No newline at end of file
diff --git a/persistence-modules/spring-data-jpa-5/src/main/java/com/baeldung/partialupdate/service/CustomerService.java b/persistence-modules/spring-data-jpa-5/src/main/java/com/baeldung/partialupdate/service/CustomerService.java
new file mode 100644
index 0000000000..9da97a7775
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-5/src/main/java/com/baeldung/partialupdate/service/CustomerService.java
@@ -0,0 +1,87 @@
+package com.baeldung.partialupdate.service;
+
+import javax.transaction.Transactional;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import com.baeldung.partialupdate.model.ContactPhone;
+import com.baeldung.partialupdate.model.Customer;
+import com.baeldung.partialupdate.model.CustomerDto;
+import com.baeldung.partialupdate.model.CustomerStructured;
+import com.baeldung.partialupdate.repository.ContactPhoneRepository;
+import com.baeldung.partialupdate.repository.CustomerRepository;
+import com.baeldung.partialupdate.repository.CustomerStructuredRepository;
+import com.baeldung.partialupdate.util.CustomerMapper;
+
+@Service
+@Transactional
+public class CustomerService {
+
+ @Autowired
+ CustomerRepository repo;
+ @Autowired
+ CustomerStructuredRepository repo2;
+ @Autowired
+ ContactPhoneRepository repo3;
+ @Autowired
+ CustomerMapper mapper;
+
+ public Customer getCustomer(long id) {
+ return repo.findById(id);
+ }
+
+ public void updateCustomerWithCustomQuery(long id, String phone) {
+ repo.updatePhone(id, phone);
+ }
+
+ public Customer addCustomer(String name) {
+ Customer myCustomer = new Customer();
+ myCustomer.name = name;
+ repo.save(myCustomer);
+ return myCustomer;
+ }
+
+ public Customer updateCustomer(long id, String phone) {
+ Customer myCustomer = repo.findById(id);
+ myCustomer.phone = phone;
+ repo.save(myCustomer);
+ return myCustomer;
+ }
+
+ public Customer addCustomer(CustomerDto dto) {
+ Customer myCustomer = new Customer();
+ mapper.updateCustomerFromDto(dto, myCustomer);
+ repo.save(myCustomer);
+ return myCustomer;
+ }
+
+ public Customer updateCustomer(CustomerDto dto) {
+ Customer myCustomer = repo.findById(dto.getId());
+ mapper.updateCustomerFromDto(dto, myCustomer);
+ repo.save(myCustomer);
+ return myCustomer;
+ }
+
+ public CustomerStructured addCustomerStructured(String name) {
+ CustomerStructured myCustomer = new CustomerStructured();
+ myCustomer.name = name;
+ repo2.save(myCustomer);
+ return myCustomer;
+ }
+
+ public void addCustomerPhone(long customerId, String phone) {
+ ContactPhone myPhone = new ContactPhone();
+ myPhone.phone = phone;
+ myPhone.customerId = customerId;
+ repo3.save(myPhone);
+ }
+
+ public CustomerStructured updateCustomerStructured(long id, String name) {
+ CustomerStructured myCustomer = repo2.findById(id);
+ myCustomer.name = name;
+ repo2.save(myCustomer);
+ return myCustomer;
+ }
+
+}
diff --git a/persistence-modules/spring-data-jpa-5/src/main/java/com/baeldung/partialupdate/util/CustomerMapper.java b/persistence-modules/spring-data-jpa-5/src/main/java/com/baeldung/partialupdate/util/CustomerMapper.java
new file mode 100644
index 0000000000..8a666e3e6c
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-5/src/main/java/com/baeldung/partialupdate/util/CustomerMapper.java
@@ -0,0 +1,15 @@
+package com.baeldung.partialupdate.util;
+
+import org.mapstruct.BeanMapping;
+import org.mapstruct.Mapper;
+import org.mapstruct.MappingTarget;
+import org.mapstruct.NullValuePropertyMappingStrategy;
+
+import com.baeldung.partialupdate.model.Customer;
+import com.baeldung.partialupdate.model.CustomerDto;
+
+@Mapper(componentModel = "spring")
+public interface CustomerMapper {
+ @BeanMapping(nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE)
+ void updateCustomerFromDto(CustomerDto dto, @MappingTarget Customer entity);
+}
diff --git a/persistence-modules/spring-data-jpa-5/src/test/java/com/baeldung/partialupdate/PartialUpdateUnitTest.java b/persistence-modules/spring-data-jpa-5/src/test/java/com/baeldung/partialupdate/PartialUpdateUnitTest.java
new file mode 100644
index 0000000000..874e18c4ad
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-5/src/test/java/com/baeldung/partialupdate/PartialUpdateUnitTest.java
@@ -0,0 +1,63 @@
+package com.baeldung.partialupdate;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import com.baeldung.partialupdate.model.Customer;
+import com.baeldung.partialupdate.model.CustomerDto;
+import com.baeldung.partialupdate.model.CustomerStructured;
+import com.baeldung.partialupdate.service.CustomerService;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = PartialUpdateApplication.class)
+public class PartialUpdateUnitTest {
+
+ @Autowired
+ CustomerService service;
+
+ @Test
+ public void givenCustomer_whenUpdate_thenSuccess() {
+ Customer myCustomer = service.addCustomer("John");
+ myCustomer = service.updateCustomer(myCustomer.id, "+00");
+ assertEquals("+00", myCustomer.phone);
+ }
+
+ @Test
+ public void givenCustomer_whenUpdateWithQuery_thenSuccess() {
+ Customer myCustomer = service.addCustomer("John");
+ service.updateCustomerWithCustomQuery(myCustomer.id, "+88");
+ myCustomer = service.getCustomer(myCustomer.id);
+ assertEquals("+88", myCustomer.phone);
+ }
+
+ @Test
+ public void givenCustomerDto_whenUpdateWithMapper_thenSuccess() {
+ CustomerDto dto = new CustomerDto(new Customer());
+ dto.name = "Johnny";
+ Customer entity = service.addCustomer(dto);
+
+ CustomerDto dto2 = new CustomerDto(entity.id);
+ dto2.phone = "+44";
+ entity = service.updateCustomer(dto2);
+
+ assertEquals("Johnny", entity.name);
+ }
+
+ @Test
+ public void givenCustomerStructured_whenUpdateCustomerPhone_thenSuccess() {
+ CustomerStructured myCustomer = service.addCustomerStructured("John");
+ assertEquals(null, myCustomer.contactPhones);
+
+ service.addCustomerPhone(myCustomer.id, "+44");
+ myCustomer = service.updateCustomerStructured(myCustomer.id, "Mr. John");
+
+ assertNotEquals(null, myCustomer.contactPhones);
+ assertEquals(1, myCustomer.contactPhones.size());
+ }
+}
diff --git a/persistence-modules/spring-data-redis/README.md b/persistence-modules/spring-data-redis/README.md
index 175634376b..95cba2c159 100644
--- a/persistence-modules/spring-data-redis/README.md
+++ b/persistence-modules/spring-data-redis/README.md
@@ -4,7 +4,6 @@
- [Introduction to Spring Data Redis](https://www.baeldung.com/spring-data-redis-tutorial)
- [PubSub Messaging with Spring Data Redis](https://www.baeldung.com/spring-data-redis-pub-sub)
- [An Introduction to Spring Data Redis Reactive](https://www.baeldung.com/spring-data-redis-reactive)
-- [Delete Everything in Redis](https://www.baeldung.com/redis-delete-data)
### Build the Project with Tests Running
```
@@ -15,4 +14,3 @@ mvn clean install
```
mvn test
```
-
diff --git a/persistence-modules/spring-data-redis/src/main/java/com/baeldung/spring/data/redis/config/RedisConfig.java b/persistence-modules/spring-data-redis/src/main/java/com/baeldung/spring/data/redis/config/RedisConfig.java
index fdc279be42..497e1506bd 100644
--- a/persistence-modules/spring-data-redis/src/main/java/com/baeldung/spring/data/redis/config/RedisConfig.java
+++ b/persistence-modules/spring-data-redis/src/main/java/com/baeldung/spring/data/redis/config/RedisConfig.java
@@ -35,18 +35,6 @@ public class RedisConfig {
template.setValueSerializer(new GenericToStringSerializer