commit
56f7b49988
|
@ -1,4 +1,4 @@
|
||||||
package com.baeldung.java14.helpfulnullpointerexceptions;
|
package com.baeldung.java14.npe;
|
||||||
|
|
||||||
public class HelpfulNullPointerException {
|
public class HelpfulNullPointerException {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package com.baeldung.java14.helpfulnullpointerexceptions;
|
package com.baeldung.java14.npe;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
|
@ -5,5 +5,5 @@ This module contains articles about sorting arrays in Java
|
||||||
### Relevant Articles:
|
### Relevant Articles:
|
||||||
- [Sorting Arrays in Java](https://www.baeldung.com/java-sorting-arrays)
|
- [Sorting Arrays in Java](https://www.baeldung.com/java-sorting-arrays)
|
||||||
- [Checking If an Array Is Sorted in Java](https://www.baeldung.com/java-check-sorted-array)
|
- [Checking If an Array Is Sorted in Java](https://www.baeldung.com/java-check-sorted-array)
|
||||||
- [How to Reverse an Array in Java](http://www.baeldung.com/java-invert-array)
|
- [How to Reverse an Array in Java](https://www.baeldung.com/java-invert-array)
|
||||||
- [Arrays.sort vs Arrays.parallelSort](https://www.baeldung.com/java-arrays-sort-vs-parallelsort)
|
- [Arrays.sort vs Arrays.parallelSort](https://www.baeldung.com/java-arrays-sort-vs-parallelsort)
|
||||||
|
|
|
@ -4,4 +4,5 @@
|
||||||
|
|
||||||
### Relevant Articles:
|
### Relevant Articles:
|
||||||
- [Using a Mutex Object in Java](https://www.baeldung.com/java-mutex)
|
- [Using a Mutex Object in Java](https://www.baeldung.com/java-mutex)
|
||||||
|
- [Testing Multi-Threaded Code in Java] (https://www.baeldung.com/java-testing-multithreaded)
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,38 @@
|
||||||
<relativePath>../../parent-java</relativePath>
|
<relativePath>../../parent-java</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>junit</groupId>
|
||||||
|
<artifactId>junit</artifactId>
|
||||||
|
<version>4.13</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.googlecode.thread-weaver</groupId>
|
||||||
|
<artifactId>threadweaver</artifactId>
|
||||||
|
<version>0.2</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.google.code.tempus-fugit</groupId>
|
||||||
|
<artifactId>tempus-fugit</artifactId>
|
||||||
|
<version>1.1</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.googlecode.multithreadedtc</groupId>
|
||||||
|
<artifactId>multithreadedtc</artifactId>
|
||||||
|
<version>1.01</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.openjdk.jcstress</groupId>
|
||||||
|
<artifactId>jcstress-core</artifactId>
|
||||||
|
<version>0.5</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
<finalName>core-java-concurrency-2</finalName>
|
<finalName>core-java-concurrency-2</finalName>
|
||||||
<resources>
|
<resources>
|
||||||
|
@ -24,6 +56,51 @@
|
||||||
<filtering>true</filtering>
|
<filtering>true</filtering>
|
||||||
</resource>
|
</resource>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<version>3.1</version>
|
||||||
|
<configuration>
|
||||||
|
<compilerVersion>${javac.target}</compilerVersion>
|
||||||
|
<source>${javac.target}</source>
|
||||||
|
<target>${javac.target}</target>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-shade-plugin</artifactId>
|
||||||
|
<version>2.2</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>main</id>
|
||||||
|
<phase>package</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>shade</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<finalName>jcstress</finalName>
|
||||||
|
<transformers>
|
||||||
|
<transformer
|
||||||
|
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
|
||||||
|
<mainClass>org.openjdk.jcstress.Main</mainClass>
|
||||||
|
</transformer>
|
||||||
|
<transformer
|
||||||
|
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
||||||
|
<resource>META-INF/TestList</resource>
|
||||||
|
</transformer>
|
||||||
|
</transformers>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<javac.target>1.8</javac.target>
|
||||||
|
</properties>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package com.baeldung.concurrent;
|
package com.baeldung.concurrent;
|
||||||
|
|
||||||
|
import org.junit.Ignore;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import edu.umd.cs.mtc.MultithreadedTestCase;
|
import edu.umd.cs.mtc.MultithreadedTestCase;
|
||||||
|
@ -25,9 +26,10 @@ public class MyCounterMultithreadedTCUnitTest extends MultithreadedTestCase {
|
||||||
@SuppressWarnings("deprecation")
|
@SuppressWarnings("deprecation")
|
||||||
@Override
|
@Override
|
||||||
public void finish() {
|
public void finish() {
|
||||||
assertEquals(2, counter.getCount());
|
assertEquals(2, counter.getCount());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Ignore
|
||||||
@Test
|
@Test
|
||||||
public void testCounter() throws Throwable {
|
public void testCounter() throws Throwable {
|
||||||
TestFramework.runManyTimes(new MyCounterMultithreadedTCUnitTest(), 1000);
|
TestFramework.runManyTimes(new MyCounterMultithreadedTCUnitTest(), 1000);
|
|
@ -6,6 +6,7 @@ import java.util.concurrent.CountDownLatch;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
|
|
||||||
|
import org.junit.Ignore;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
public class MyCounterSimpleUnitTest {
|
public class MyCounterSimpleUnitTest {
|
||||||
|
@ -18,7 +19,8 @@ public class MyCounterSimpleUnitTest {
|
||||||
assertEquals(500, counter.getCount());
|
assertEquals(500, counter.getCount());
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Test
|
@Ignore
|
||||||
|
@Test
|
||||||
public void testCounterWithConcurrency() throws InterruptedException {
|
public void testCounterWithConcurrency() throws InterruptedException {
|
||||||
int numberOfThreads = 100;
|
int numberOfThreads = 100;
|
||||||
ExecutorService service = Executors.newFixedThreadPool(10);
|
ExecutorService service = Executors.newFixedThreadPool(10);
|
||||||
|
@ -34,7 +36,8 @@ public class MyCounterSimpleUnitTest {
|
||||||
assertEquals(numberOfThreads, counter.getCount());
|
assertEquals(numberOfThreads, counter.getCount());
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Test
|
@Ignore
|
||||||
|
@Test
|
||||||
public void testSummationWithConcurrencyAndWait() throws InterruptedException {
|
public void testSummationWithConcurrencyAndWait() throws InterruptedException {
|
||||||
int numberOfThreads = 2;
|
int numberOfThreads = 2;
|
||||||
ExecutorService service = Executors.newFixedThreadPool(10);
|
ExecutorService service = Executors.newFixedThreadPool(10);
|
|
@ -3,6 +3,7 @@ package com.baeldung.concurrent;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
import org.junit.AfterClass;
|
import org.junit.AfterClass;
|
||||||
|
import org.junit.Ignore;
|
||||||
import org.junit.Rule;
|
import org.junit.Rule;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
@ -20,6 +21,7 @@ public class MyCounterTempusFugitUnitTest {
|
||||||
|
|
||||||
private static MyCounter counter = new MyCounter();
|
private static MyCounter counter = new MyCounter();
|
||||||
|
|
||||||
|
@Ignore
|
||||||
@Test
|
@Test
|
||||||
@Concurrent(count = 2)
|
@Concurrent(count = 2)
|
||||||
@Repeating(repetition = 10)
|
@Repeating(repetition = 10)
|
|
@ -2,6 +2,7 @@ package com.baeldung.concurrent;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
import org.junit.Ignore;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import com.google.testing.threadtester.AnnotatedTestRunner;
|
import com.google.testing.threadtester.AnnotatedTestRunner;
|
||||||
|
@ -34,6 +35,7 @@ public class MyCounterThreadWeaverUnitTest {
|
||||||
assertEquals(2, counter.getCount());
|
assertEquals(2, counter.getCount());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Ignore
|
||||||
@Test
|
@Test
|
||||||
public void testCounter() {
|
public void testCounter() {
|
||||||
new AnnotatedTestRunner().runTests(this.getClass(), MyCounter.class);
|
new AnnotatedTestRunner().runTests(this.getClass(), MyCounter.class);
|
|
@ -0,0 +1,60 @@
|
||||||
|
package com.baeldung.deadlockAndLivelock;
|
||||||
|
|
||||||
|
import java.util.concurrent.locks.Lock;
|
||||||
|
import java.util.concurrent.locks.ReentrantLock;
|
||||||
|
|
||||||
|
public class DeadlockExample {
|
||||||
|
|
||||||
|
private Lock lock1 = new ReentrantLock(true);
|
||||||
|
private Lock lock2 = new ReentrantLock(true);
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
DeadlockExample deadlock = new DeadlockExample();
|
||||||
|
new Thread(deadlock::operation1, "T1").start();
|
||||||
|
new Thread(deadlock::operation2, "T2").start();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void operation1() {
|
||||||
|
lock1.lock();
|
||||||
|
print("lock1 acquired, waiting to acquire lock2.");
|
||||||
|
sleep(50);
|
||||||
|
|
||||||
|
lock2.lock();
|
||||||
|
print("lock2 acquired");
|
||||||
|
|
||||||
|
print("executing first operation.");
|
||||||
|
|
||||||
|
lock2.unlock();
|
||||||
|
lock1.unlock();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void operation2() {
|
||||||
|
lock2.lock();
|
||||||
|
print("lock2 acquired, waiting to acquire lock1.");
|
||||||
|
sleep(50);
|
||||||
|
|
||||||
|
lock1.lock();
|
||||||
|
print("lock1 acquired");
|
||||||
|
|
||||||
|
print("executing second operation.");
|
||||||
|
|
||||||
|
lock1.unlock();
|
||||||
|
lock2.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void print(String message) {
|
||||||
|
System.out.println("Thread " + Thread.currentThread()
|
||||||
|
.getName() + ": " + message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void sleep(long millis) {
|
||||||
|
try {
|
||||||
|
Thread.sleep(millis);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,86 @@
|
||||||
|
package com.baeldung.deadlockAndLivelock;
|
||||||
|
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.concurrent.locks.Lock;
|
||||||
|
import java.util.concurrent.locks.ReentrantLock;
|
||||||
|
|
||||||
|
public class LivelockExample {
|
||||||
|
|
||||||
|
private Lock lock1 = new ReentrantLock(true);
|
||||||
|
private Lock lock2 = new ReentrantLock(true);
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
LivelockExample livelock = new LivelockExample();
|
||||||
|
new Thread(livelock::operation1, "T1").start();
|
||||||
|
new Thread(livelock::operation2, "T2").start();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void operation1() {
|
||||||
|
while (true) {
|
||||||
|
tryLock(lock1, 50);
|
||||||
|
print("lock1 acquired, trying to acquire lock2.");
|
||||||
|
sleep(50);
|
||||||
|
|
||||||
|
if (tryLock(lock2)) {
|
||||||
|
print("lock2 acquired.");
|
||||||
|
} else {
|
||||||
|
print("cannot acquire lock2, releasing lock1.");
|
||||||
|
lock1.unlock();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
print("executing first operation.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
lock2.unlock();
|
||||||
|
lock1.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void operation2() {
|
||||||
|
while (true) {
|
||||||
|
tryLock(lock2, 50);
|
||||||
|
print("lock2 acquired, trying to acquire lock1.");
|
||||||
|
sleep(50);
|
||||||
|
|
||||||
|
if (tryLock(lock1)) {
|
||||||
|
print("lock1 acquired.");
|
||||||
|
} else {
|
||||||
|
print("cannot acquire lock1, releasing lock2.");
|
||||||
|
lock2.unlock();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
print("executing second operation.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
lock1.unlock();
|
||||||
|
lock2.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void print(String message) {
|
||||||
|
System.out.println("Thread " + Thread.currentThread()
|
||||||
|
.getName() + ": " + message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void sleep(long millis) {
|
||||||
|
try {
|
||||||
|
Thread.sleep(millis);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void tryLock(Lock lock, long millis) {
|
||||||
|
try {
|
||||||
|
lock.tryLock(10, TimeUnit.MILLISECONDS);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean tryLock(Lock lock) {
|
||||||
|
return lock.tryLock();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,7 +0,0 @@
|
||||||
=========
|
|
||||||
|
|
||||||
## Core Java Concurrency Testing Examples
|
|
||||||
|
|
||||||
### Relevant Articles:
|
|
||||||
- [Testing Multi-Threaded Code in Java](https://www.baeldung.com/java-testing-multithreaded)
|
|
||||||
|
|
|
@ -1,93 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
|
||||||
<artifactId>core-java-concurrency-testing</artifactId>
|
|
||||||
<version>0.1.0-SNAPSHOT</version>
|
|
||||||
<name>core-java-concurrency-testing</name>
|
|
||||||
<packaging>jar</packaging>
|
|
||||||
|
|
||||||
<parent>
|
|
||||||
<groupId>com.baeldung</groupId>
|
|
||||||
<artifactId>parent-java</artifactId>
|
|
||||||
<version>0.0.1-SNAPSHOT</version>
|
|
||||||
<relativePath>../../parent-java</relativePath>
|
|
||||||
</parent>
|
|
||||||
|
|
||||||
<dependencies>
|
|
||||||
<dependency>
|
|
||||||
<groupId>junit</groupId>
|
|
||||||
<artifactId>junit</artifactId>
|
|
||||||
<version>4.13</version>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.googlecode.thread-weaver</groupId>
|
|
||||||
<artifactId>threadweaver</artifactId>
|
|
||||||
<version>0.2</version>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.google.code.tempus-fugit</groupId>
|
|
||||||
<artifactId>tempus-fugit</artifactId>
|
|
||||||
<version>1.1</version>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.googlecode.multithreadedtc</groupId>
|
|
||||||
<artifactId>multithreadedtc</artifactId>
|
|
||||||
<version>1.01</version>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.openjdk.jcstress</groupId>
|
|
||||||
<artifactId>jcstress-core</artifactId>
|
|
||||||
<version>0.5</version>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
|
||||||
|
|
||||||
<build>
|
|
||||||
<plugins>
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
|
||||||
<artifactId>maven-compiler-plugin</artifactId>
|
|
||||||
<version>3.1</version>
|
|
||||||
<configuration>
|
|
||||||
<compilerVersion>${javac.target}</compilerVersion>
|
|
||||||
<source>${javac.target}</source>
|
|
||||||
<target>${javac.target}</target>
|
|
||||||
</configuration>
|
|
||||||
</plugin>
|
|
||||||
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
|
||||||
<artifactId>maven-shade-plugin</artifactId>
|
|
||||||
<version>2.2</version>
|
|
||||||
<executions>
|
|
||||||
<execution>
|
|
||||||
<id>main</id>
|
|
||||||
<phase>package</phase>
|
|
||||||
<goals>
|
|
||||||
<goal>shade</goal>
|
|
||||||
</goals>
|
|
||||||
<configuration>
|
|
||||||
<finalName>jcstress</finalName>
|
|
||||||
<transformers>
|
|
||||||
<transformer
|
|
||||||
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
|
|
||||||
<mainClass>org.openjdk.jcstress.Main</mainClass>
|
|
||||||
</transformer>
|
|
||||||
<transformer
|
|
||||||
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
|
|
||||||
<resource>META-INF/TestList</resource>
|
|
||||||
</transformer>
|
|
||||||
</transformers>
|
|
||||||
</configuration>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
|
||||||
</build>
|
|
||||||
|
|
||||||
</project>
|
|
|
@ -1,19 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<configuration>
|
|
||||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
|
||||||
<encoder>
|
|
||||||
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
|
|
||||||
</pattern>
|
|
||||||
</encoder>
|
|
||||||
</appender>
|
|
||||||
|
|
||||||
<logger name="org.springframework" level="WARN" />
|
|
||||||
<logger name="org.springframework.transaction" level="WARN" />
|
|
||||||
|
|
||||||
<!-- in order to debug some marshalling issues, this needs to be TRACE -->
|
|
||||||
<logger name="org.springframework.web.servlet.mvc" level="WARN" />
|
|
||||||
|
|
||||||
<root level="INFO">
|
|
||||||
<appender-ref ref="STDOUT" />
|
|
||||||
</root>
|
|
||||||
</configuration>
|
|
|
@ -1,13 +0,0 @@
|
||||||
*.class
|
|
||||||
|
|
||||||
#folders#
|
|
||||||
/target
|
|
||||||
/neoDb*
|
|
||||||
/data
|
|
||||||
/src/main/webapp/WEB-INF/classes
|
|
||||||
*/META-INF/*
|
|
||||||
|
|
||||||
# Packaged files #
|
|
||||||
*.jar
|
|
||||||
*.war
|
|
||||||
*.ear
|
|
|
@ -29,6 +29,11 @@
|
||||||
<version>${lombok.version}</version>
|
<version>${lombok.version}</version>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.commons</groupId>
|
||||||
|
<artifactId>commons-lang3</artifactId>
|
||||||
|
<version>${commons.lang3.version}</version>
|
||||||
|
</dependency>
|
||||||
<!-- test scoped -->
|
<!-- test scoped -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.assertj</groupId>
|
<groupId>org.assertj</groupId>
|
||||||
|
@ -40,6 +45,7 @@
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<javax.mail.version>1.5.0-b01</javax.mail.version>
|
<javax.mail.version>1.5.0-b01</javax.mail.version>
|
||||||
|
<commons.lang3.version>3.10</commons.lang3.version>
|
||||||
<!-- testing -->
|
<!-- testing -->
|
||||||
<assertj-core.version>3.10.0</assertj-core.version>
|
<assertj-core.version>3.10.0</assertj-core.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
package com.baeldung.exceptions.globalexceptionhandler;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class Arithmetic {
|
||||||
|
|
||||||
|
private static Logger LOGGER = LoggerFactory.getLogger(Arithmetic.class);
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
int result = 30 / 0; // Trying to divide by zero
|
||||||
|
} catch (ArithmeticException e) {
|
||||||
|
LOGGER.error("ArithmeticException caught!");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
package com.baeldung.exceptions.globalexceptionhandler;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class ArrayIndexOutOfBounds {
|
||||||
|
|
||||||
|
private static Logger LOGGER = LoggerFactory.getLogger(ArrayIndexOutOfBounds.class);
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
|
||||||
|
int[] nums = new int[] { 1, 2, 3 };
|
||||||
|
|
||||||
|
try {
|
||||||
|
int numFromNegativeIndex = nums[-1]; // Trying to access at negative index
|
||||||
|
int numFromGreaterIndex = nums[4]; // Trying to access at greater index
|
||||||
|
int numFromLengthIndex = nums[3]; // Trying to access at index equal to size of the array
|
||||||
|
} catch (ArrayIndexOutOfBoundsException e) {
|
||||||
|
LOGGER.error("ArrayIndexOutOfBoundsException caught");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
package com.baeldung.exceptions.globalexceptionhandler;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
class Animal {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class Dog extends Animal {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class Lion extends Animal {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ClassCast {
|
||||||
|
|
||||||
|
private static Logger LOGGER = LoggerFactory.getLogger(ClassCast.class);
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
Animal animalOne = new Dog(); // At runtime the instance is dog
|
||||||
|
Dog bruno = (Dog) animalOne; // Downcasting
|
||||||
|
|
||||||
|
Animal animalTwo = new Lion(); // At runtime the instance is animal
|
||||||
|
Dog tommy = (Dog) animalTwo; // Downcasting
|
||||||
|
} catch (ClassCastException e) {
|
||||||
|
LOGGER.error("ClassCastException caught!");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
package com.baeldung.exceptions.globalexceptionhandler;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.FileReader;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class FileNotFound {
|
||||||
|
|
||||||
|
private static Logger LOGGER = LoggerFactory.getLogger(FileNotFound.class);
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
|
||||||
|
BufferedReader reader = null;
|
||||||
|
try {
|
||||||
|
reader = new BufferedReader(new FileReader(new File("/invalid/file/location")));
|
||||||
|
} catch (FileNotFoundException e) {
|
||||||
|
LOGGER.error("FileNotFoundException caught!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
package com.baeldung.exceptions.globalexceptionhandler;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class GlobalExceptionHandler {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
|
||||||
|
Handler globalExceptionHandler = new Handler();
|
||||||
|
Thread.setDefaultUncaughtExceptionHandler(globalExceptionHandler);
|
||||||
|
new GlobalExceptionHandler().performArithmeticOperation(10, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int performArithmeticOperation(int num1, int num2) {
|
||||||
|
return num1/num2;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class Handler implements Thread.UncaughtExceptionHandler {
|
||||||
|
|
||||||
|
private static Logger LOGGER = LoggerFactory.getLogger(Handler.class);
|
||||||
|
|
||||||
|
public void uncaughtException(Thread t, Throwable e) {
|
||||||
|
LOGGER.info("Unhandled exception caught!");
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
package com.baeldung.exceptions.globalexceptionhandler;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class IllegalArgument {
|
||||||
|
|
||||||
|
private static Logger LOGGER = LoggerFactory.getLogger(IllegalArgument.class);
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
try {
|
||||||
|
Thread.sleep(-1000);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
LOGGER.error("IllegalArgumentException caught!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
package com.baeldung.exceptions.globalexceptionhandler;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class IllegalState {
|
||||||
|
|
||||||
|
private static Logger LOGGER = LoggerFactory.getLogger(IllegalState.class);
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
|
||||||
|
List<Integer> intList = new ArrayList<>();
|
||||||
|
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
intList.add(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
Iterator<Integer> intListIterator = intList.iterator(); // Initialized with index at -1
|
||||||
|
|
||||||
|
try {
|
||||||
|
intListIterator.remove(); // IllegalStateException
|
||||||
|
} catch (IllegalStateException e) {
|
||||||
|
LOGGER.error("IllegalStateException caught!");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
package com.baeldung.exceptions.globalexceptionhandler;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
class ChildThread extends Thread {
|
||||||
|
|
||||||
|
private static Logger LOGGER = LoggerFactory.getLogger(ChildThread.class);
|
||||||
|
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
Thread.sleep(1000);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
LOGGER.error("InterruptedException caught!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public class InterruptedExceptionExample {
|
||||||
|
|
||||||
|
public static void main(String[] args) throws InterruptedException {
|
||||||
|
ChildThread childThread = new ChildThread();
|
||||||
|
childThread.start();
|
||||||
|
childThread.interrupt();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
package com.baeldung.exceptions.globalexceptionhandler;
|
||||||
|
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.URL;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class MalformedURL {
|
||||||
|
|
||||||
|
private static Logger LOGGER = LoggerFactory.getLogger(MalformedURL.class);
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
|
||||||
|
URL baeldungURL = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
baeldungURL = new URL("malformedurl");
|
||||||
|
} catch (MalformedURLException e) {
|
||||||
|
LOGGER.error("MalformedURLException caught!");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
package com.baeldung.exceptions.globalexceptionhandler;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class NullPointer {
|
||||||
|
|
||||||
|
private static Logger LOGGER = LoggerFactory.getLogger(NullPointer.class);
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
|
||||||
|
Person personObj = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
String name = personObj.personName; // Accessing the field of a null object
|
||||||
|
personObj.personName = "Jon Doe"; // Modifying the field of a null object
|
||||||
|
} catch (NullPointerException e) {
|
||||||
|
LOGGER.error("NullPointerException caught!");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Person {
|
||||||
|
|
||||||
|
public String personName;
|
||||||
|
|
||||||
|
public String getPersonName() {
|
||||||
|
return personName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPersonName(String personName) {
|
||||||
|
this.personName = personName;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
package com.baeldung.exceptions.globalexceptionhandler;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class NumberFormat {
|
||||||
|
|
||||||
|
private static Logger LOGGER = LoggerFactory.getLogger(NumberFormat.class);
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
|
||||||
|
String str1 = "100ABCD";
|
||||||
|
|
||||||
|
try {
|
||||||
|
int x = Integer.parseInt(str1); // Converting string with inappropriate format
|
||||||
|
int y = Integer.valueOf(str1);
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
LOGGER.error("NumberFormatException caught!");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
package com.baeldung.exceptions.globalexceptionhandler;
|
||||||
|
|
||||||
|
import java.text.DateFormat;
|
||||||
|
import java.text.ParseException;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class ParseExceptionExample {
|
||||||
|
|
||||||
|
private static Logger LOGGER = LoggerFactory.getLogger(ParseExceptionExample.class);
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
|
||||||
|
DateFormat format = new SimpleDateFormat("MM, dd, yyyy");
|
||||||
|
|
||||||
|
try {
|
||||||
|
format.parse("01, , 2010");
|
||||||
|
} catch (ParseException e) {
|
||||||
|
LOGGER.error("ParseException caught!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
package com.baeldung.exceptions.globalexceptionhandler;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class StringIndexOutOfBounds {
|
||||||
|
|
||||||
|
private static Logger LOGGER = LoggerFactory.getLogger(StringIndexOutOfBounds.class);
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
|
||||||
|
String str = "Hello World";
|
||||||
|
|
||||||
|
try {
|
||||||
|
char charAtNegativeIndex = str.charAt(-1); // Trying to access at negative index
|
||||||
|
char charAtLengthIndex = str.charAt(11); // Trying to access at index equal to size of the string
|
||||||
|
} catch (StringIndexOutOfBoundsException e) {
|
||||||
|
LOGGER.error("StringIndexOutOfBoundsException caught");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,95 @@
|
||||||
|
package com.baeldung.exceptions.rootcausefinder;
|
||||||
|
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.time.Period;
|
||||||
|
import java.time.format.DateTimeParseException;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility class to find root cause exceptions.
|
||||||
|
*/
|
||||||
|
public class RootCauseFinder {
|
||||||
|
|
||||||
|
public static Throwable findCauseUsingPlainJava(Throwable throwable) {
|
||||||
|
Objects.requireNonNull(throwable);
|
||||||
|
Throwable rootCause = throwable;
|
||||||
|
while (rootCause.getCause() != null) {
|
||||||
|
rootCause = rootCause.getCause();
|
||||||
|
}
|
||||||
|
return rootCause;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates the age of a person from a given date.
|
||||||
|
*/
|
||||||
|
static class AgeCalculator {
|
||||||
|
|
||||||
|
private AgeCalculator() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int calculateAge(String birthDate) throws CalculationException {
|
||||||
|
if (birthDate == null || birthDate.isEmpty()) {
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
return Period
|
||||||
|
.between(parseDate(birthDate), LocalDate.now())
|
||||||
|
.getYears();
|
||||||
|
} catch (DateParseException ex) {
|
||||||
|
throw new CalculationException(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static LocalDate parseDate(String birthDateAsString) throws DateParseException {
|
||||||
|
|
||||||
|
LocalDate birthDate;
|
||||||
|
try {
|
||||||
|
birthDate = LocalDate.parse(birthDateAsString);
|
||||||
|
} catch (DateTimeParseException ex) {
|
||||||
|
throw new InvalidFormatException(birthDateAsString, ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (birthDate.isAfter(LocalDate.now())) {
|
||||||
|
throw new DateOutOfRangeException(birthDateAsString);
|
||||||
|
}
|
||||||
|
|
||||||
|
return birthDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static class CalculationException extends Exception {
|
||||||
|
|
||||||
|
CalculationException(DateParseException ex) {
|
||||||
|
super(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class DateParseException extends Exception {
|
||||||
|
|
||||||
|
DateParseException(String input) {
|
||||||
|
super(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
DateParseException(String input, Throwable thr) {
|
||||||
|
super(input, thr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class InvalidFormatException extends DateParseException {
|
||||||
|
|
||||||
|
InvalidFormatException(String input, Throwable thr) {
|
||||||
|
super("Invalid date format: " + input, thr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class DateOutOfRangeException extends DateParseException {
|
||||||
|
|
||||||
|
DateOutOfRangeException(String date) {
|
||||||
|
super("Date out of range: " + date);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,64 @@
|
||||||
|
package com.baeldung.exceptions.globalexceptionhandler;
|
||||||
|
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mockito.ArgumentCaptor;
|
||||||
|
import org.mockito.Captor;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.junit.MockitoJUnitRunner;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import ch.qos.logback.classic.Level;
|
||||||
|
import ch.qos.logback.classic.Logger;
|
||||||
|
import ch.qos.logback.classic.spi.ILoggingEvent;
|
||||||
|
import ch.qos.logback.classic.spi.LoggingEvent;
|
||||||
|
import ch.qos.logback.core.Appender;
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
|
||||||
|
@RunWith(MockitoJUnitRunner.class)
|
||||||
|
public class GlobalExceptionHandlerUnitTest {
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private Appender<ILoggingEvent> mockAppender;
|
||||||
|
|
||||||
|
@Captor
|
||||||
|
private ArgumentCaptor<LoggingEvent> captorLoggingEvent;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setup() {
|
||||||
|
final Logger logger = (Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME);
|
||||||
|
logger.addAppender(mockAppender);
|
||||||
|
|
||||||
|
Handler globalExceptionHandler = new Handler();
|
||||||
|
Thread.setDefaultUncaughtExceptionHandler(globalExceptionHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void teardown() {
|
||||||
|
final Logger logger = (Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME);
|
||||||
|
logger.detachAppender(mockAppender);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenArithmeticException_thenUseUncaughtExceptionHandler() throws InterruptedException {
|
||||||
|
|
||||||
|
Thread globalExceptionHandlerThread = new Thread() {
|
||||||
|
public void run() {
|
||||||
|
GlobalExceptionHandler globalExceptionHandlerObj = new GlobalExceptionHandler();
|
||||||
|
globalExceptionHandlerObj.performArithmeticOperation(99, 0);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
globalExceptionHandlerThread.start();
|
||||||
|
globalExceptionHandlerThread.join();
|
||||||
|
|
||||||
|
verify(mockAppender).doAppend(captorLoggingEvent.capture());
|
||||||
|
LoggingEvent loggingEvent = captorLoggingEvent.getValue();
|
||||||
|
|
||||||
|
assertThat(loggingEvent.getLevel()).isEqualTo(Level.INFO);
|
||||||
|
assertThat(loggingEvent.getFormattedMessage()).isEqualTo("Unhandled exception caught!");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,99 @@
|
||||||
|
package com.baeldung.exceptions.rootcausefinder;
|
||||||
|
|
||||||
|
import com.baeldung.exceptions.rootcausefinder.RootCauseFinder.CalculationException;
|
||||||
|
import com.baeldung.exceptions.rootcausefinder.RootCauseFinder.DateOutOfRangeException;
|
||||||
|
import com.google.common.base.Throwables;
|
||||||
|
import org.apache.commons.lang3.exception.ExceptionUtils;
|
||||||
|
import org.junit.jupiter.api.Assertions;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.time.format.DateTimeParseException;
|
||||||
|
import java.time.temporal.ChronoUnit;
|
||||||
|
|
||||||
|
import static com.baeldung.exceptions.rootcausefinder.RootCauseFinder.AgeCalculator;
|
||||||
|
import static com.baeldung.exceptions.rootcausefinder.RootCauseFinder.findCauseUsingPlainJava;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests the {@link RootCauseFinder}.
|
||||||
|
*/
|
||||||
|
public class RootCauseFinderUnitTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenBirthDate_whenCalculatingAge_thenAgeReturned() {
|
||||||
|
try {
|
||||||
|
int age = AgeCalculator.calculateAge("1990-01-01");
|
||||||
|
Assertions.assertEquals(1990, LocalDate
|
||||||
|
.now()
|
||||||
|
.minus(age, ChronoUnit.YEARS)
|
||||||
|
.getYear());
|
||||||
|
} catch (CalculationException e) {
|
||||||
|
Assertions.fail(e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenWrongFormatDate_whenFindingRootCauseUsingJava_thenRootCauseFound() {
|
||||||
|
try {
|
||||||
|
AgeCalculator.calculateAge("010102");
|
||||||
|
} catch (CalculationException ex) {
|
||||||
|
assertTrue(findCauseUsingPlainJava(ex) instanceof DateTimeParseException);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenOutOfRangeDate_whenFindingRootCauseUsingJava_thenRootCauseFound() {
|
||||||
|
try {
|
||||||
|
AgeCalculator.calculateAge("2020-04-04");
|
||||||
|
} catch (CalculationException ex) {
|
||||||
|
assertTrue(findCauseUsingPlainJava(ex) instanceof DateOutOfRangeException);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenNullDate_whenFindingRootCauseUsingJava_thenRootCauseFound() {
|
||||||
|
try {
|
||||||
|
AgeCalculator.calculateAge(null);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
assertTrue(findCauseUsingPlainJava(ex) instanceof IllegalArgumentException);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenWrongFormatDate_whenFindingRootCauseUsingApacheCommons_thenRootCauseFound() {
|
||||||
|
try {
|
||||||
|
AgeCalculator.calculateAge("010102");
|
||||||
|
} catch (CalculationException ex) {
|
||||||
|
assertTrue(ExceptionUtils.getRootCause(ex) instanceof DateTimeParseException);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenOutOfRangeDate_whenFindingRootCauseUsingApacheCommons_thenRootCauseFound() {
|
||||||
|
try {
|
||||||
|
AgeCalculator.calculateAge("2020-04-04");
|
||||||
|
} catch (CalculationException ex) {
|
||||||
|
assertTrue(ExceptionUtils.getRootCause(ex) instanceof DateOutOfRangeException);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenWrongFormatDate_whenFindingRootCauseUsingGuava_thenRootCauseFound() {
|
||||||
|
try {
|
||||||
|
AgeCalculator.calculateAge("010102");
|
||||||
|
} catch (CalculationException ex) {
|
||||||
|
assertTrue(Throwables.getRootCause(ex) instanceof DateTimeParseException);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenOutOfRangeDate_whenFindingRootCauseUsingGuava_thenRootCauseFound() {
|
||||||
|
try {
|
||||||
|
AgeCalculator.calculateAge("2020-04-04");
|
||||||
|
} catch (CalculationException ex) {
|
||||||
|
assertTrue(Throwables.getRootCause(ex) instanceof DateOutOfRangeException);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,95 @@
|
||||||
|
package com.baeldung.exceptions;
|
||||||
|
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.time.Period;
|
||||||
|
import java.time.format.DateTimeParseException;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility class to find root cause exceptions.
|
||||||
|
*/
|
||||||
|
public class RootCauseFinder {
|
||||||
|
|
||||||
|
public static Throwable findCauseUsingPlainJava(Throwable throwable) {
|
||||||
|
Objects.requireNonNull(throwable);
|
||||||
|
Throwable rootCause = throwable;
|
||||||
|
while (rootCause.getCause() != null) {
|
||||||
|
rootCause = rootCause.getCause();
|
||||||
|
}
|
||||||
|
return rootCause;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates the age of a person from a given date.
|
||||||
|
*/
|
||||||
|
static class AgeCalculator {
|
||||||
|
|
||||||
|
private AgeCalculator() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int calculateAge(String birthDate) throws CalculationException {
|
||||||
|
if (birthDate == null || birthDate.isEmpty()) {
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
return Period
|
||||||
|
.between(parseDate(birthDate), LocalDate.now())
|
||||||
|
.getYears();
|
||||||
|
} catch (DateParseException ex) {
|
||||||
|
throw new CalculationException(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static LocalDate parseDate(String birthDateAsString) throws DateParseException {
|
||||||
|
|
||||||
|
LocalDate birthDate;
|
||||||
|
try {
|
||||||
|
birthDate = LocalDate.parse(birthDateAsString);
|
||||||
|
} catch (DateTimeParseException ex) {
|
||||||
|
throw new InvalidFormatException(birthDateAsString, ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (birthDate.isAfter(LocalDate.now())) {
|
||||||
|
throw new DateOutOfRangeException(birthDateAsString);
|
||||||
|
}
|
||||||
|
|
||||||
|
return birthDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static class CalculationException extends Exception {
|
||||||
|
|
||||||
|
CalculationException(DateParseException ex) {
|
||||||
|
super(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class DateParseException extends Exception {
|
||||||
|
|
||||||
|
DateParseException(String input) {
|
||||||
|
super(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
DateParseException(String input, Throwable thr) {
|
||||||
|
super(input, thr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class InvalidFormatException extends DateParseException {
|
||||||
|
|
||||||
|
InvalidFormatException(String input, Throwable thr) {
|
||||||
|
super("Invalid date format: " + input, thr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class DateOutOfRangeException extends DateParseException {
|
||||||
|
|
||||||
|
DateOutOfRangeException(String date) {
|
||||||
|
super("Date out of range: " + date);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -96,7 +96,7 @@
|
||||||
<!-- testing -->
|
<!-- testing -->
|
||||||
<assertj.version>3.6.1</assertj.version>
|
<assertj.version>3.6.1</assertj.version>
|
||||||
<asspectj.version>1.8.9</asspectj.version>
|
<asspectj.version>1.8.9</asspectj.version>
|
||||||
<powermock.version>2.0.0-RC.4</powermock.version>
|
<powermock.version>2.0.0</powermock.version>
|
||||||
<jmockit.version>1.44</jmockit.version>
|
<jmockit.version>1.44</jmockit.version>
|
||||||
<!-- plugins -->
|
<!-- plugins -->
|
||||||
<maven-surefire-plugin.version>2.22.1</maven-surefire-plugin.version>
|
<maven-surefire-plugin.version>2.22.1</maven-surefire-plugin.version>
|
||||||
|
|
|
@ -0,0 +1,59 @@
|
||||||
|
package com.baeldung.foldvsreduce
|
||||||
|
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.jupiter.api.assertThrows
|
||||||
|
import java.lang.RuntimeException
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
|
class FoldAndReduceTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testReduceLimitations() {
|
||||||
|
val numbers: List<Int> = listOf(1, 2, 3)
|
||||||
|
val sum: Number = numbers.reduce { acc, next -> acc + next }
|
||||||
|
assertEquals(6, sum)
|
||||||
|
|
||||||
|
val emptyList = listOf<Int>()
|
||||||
|
assertThrows<RuntimeException> { emptyList.reduce { acc, next -> acc + next } }
|
||||||
|
|
||||||
|
// doesn't compile
|
||||||
|
// val sum = numbers.reduce { acc, next -> acc.toLong() + next.toLong()}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testFold() {
|
||||||
|
|
||||||
|
val numbers: List<Int> = listOf(1, 2, 3)
|
||||||
|
val sum: Int = numbers.fold(0, { acc, next -> acc + next })
|
||||||
|
assertEquals(6, sum)
|
||||||
|
|
||||||
|
//change result type
|
||||||
|
val sumLong: Long = numbers.fold(0L, { acc, next -> acc + next.toLong() })
|
||||||
|
assertEquals(6L, sumLong)
|
||||||
|
|
||||||
|
val emptyList = listOf<Int>()
|
||||||
|
val emptySum = emptyList.fold(0, { acc, next -> acc + next })
|
||||||
|
assertEquals(0, emptySum)
|
||||||
|
|
||||||
|
//power of changing result type
|
||||||
|
val (even, odd) = numbers.fold(Pair(listOf<Int>(), listOf<Int>()), { acc, next ->
|
||||||
|
if (next % 2 == 0) Pair(acc.first + next, acc.second)
|
||||||
|
else Pair(acc.first, acc.second + next)
|
||||||
|
})
|
||||||
|
|
||||||
|
assertEquals(listOf(2), even)
|
||||||
|
assertEquals(listOf(1, 3), odd)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testVariationsOfFold() {
|
||||||
|
val numbers = listOf(1, 2, 3)
|
||||||
|
val reversed = numbers.foldRight(listOf<Int>(), { next, acc -> acc + next})
|
||||||
|
assertEquals(listOf(3,2,1), reversed)
|
||||||
|
|
||||||
|
val reversedIndexes = numbers.foldRightIndexed(listOf<Int>(), { i, _, acc -> acc + i })
|
||||||
|
assertEquals(listOf(2,1,0), reversedIndexes)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -256,10 +256,9 @@
|
||||||
</execution>
|
</execution>
|
||||||
</executions>
|
</executions>
|
||||||
<configuration>
|
<configuration>
|
||||||
<wsdlDirectory>src/main/resources</wsdlDirectory>
|
<wsdlUrls>
|
||||||
<wsdlFiles>
|
<wsdlUrl>http://localhost:8888/ws/country?wsdl</wsdlUrl>
|
||||||
<wsdlFile>country.wsdl</wsdlFile>
|
</wsdlUrls>
|
||||||
</wsdlFiles>
|
|
||||||
<keep>true</keep>
|
<keep>true</keep>
|
||||||
<packageName>com.baeldung.soap.ws.client.generated</packageName>
|
<packageName>com.baeldung.soap.ws.client.generated</packageName>
|
||||||
<sourceDestDir>src/main/java</sourceDestDir>
|
<sourceDestDir>src/main/java</sourceDestDir>
|
||||||
|
|
|
@ -12,11 +12,11 @@ import javax.xml.ws.WebServiceFeature;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class was generated by the JAX-WS RI.
|
* This class was generated by the JAX-WS RI.
|
||||||
* JAX-WS RI 2.3.2
|
* JAX-WS RI 2.2.9-b130926.1035
|
||||||
* Generated source version: 2.2
|
* Generated source version: 2.2
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@WebServiceClient(name = "CountryServiceImplService", targetNamespace = "http://server.ws.soap.baeldung.com/", wsdlLocation = "file:src/main/resources/country.wsdl")
|
@WebServiceClient(name = "CountryServiceImplService", targetNamespace = "http://server.ws.soap.baeldung.com/", wsdlLocation = "http://localhost:8888/ws/country?wsdl")
|
||||||
public class CountryServiceImplService extends Service {
|
public class CountryServiceImplService extends Service {
|
||||||
|
|
||||||
private final static URL COUNTRYSERVICEIMPLSERVICE_WSDL_LOCATION;
|
private final static URL COUNTRYSERVICEIMPLSERVICE_WSDL_LOCATION;
|
||||||
|
@ -27,7 +27,7 @@ public class CountryServiceImplService extends Service {
|
||||||
URL url = null;
|
URL url = null;
|
||||||
WebServiceException e = null;
|
WebServiceException e = null;
|
||||||
try {
|
try {
|
||||||
url = new URL("file:src/main/resources/country.wsdl");
|
url = new URL("http://localhost:8888/ws/country?wsdl");
|
||||||
} catch (MalformedURLException ex) {
|
} catch (MalformedURLException ex) {
|
||||||
e = new WebServiceException(ex);
|
e = new WebServiceException(ex);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,40 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?><!-- Published by JAX-WS RI (http://jax-ws.java.net). RI's version is JAX-WS RI 2.2.9-b130926.1035 svn-revision#5f6196f2b90e9460065a4c2f4e30e065b245e51e. --><!-- Generated by JAX-WS RI (http://jax-ws.java.net). RI's version is JAX-WS RI 2.2.9-b130926.1035 svn-revision#5f6196f2b90e9460065a4c2f4e30e065b245e51e. -->
|
|
||||||
<definitions xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:wsp="http://www.w3.org/ns/ws-policy"
|
|
||||||
xmlns:wsp1_2="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:wsam="http://www.w3.org/2007/05/addressing/metadata" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
|
|
||||||
xmlns:tns="http://server.ws.soap.baeldung.com/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schemas.xmlsoap.org/wsdl/"
|
|
||||||
targetNamespace="http://server.ws.soap.baeldung.com/" name="CountryServiceImplService">
|
|
||||||
<types>
|
|
||||||
<xsd:schema>
|
|
||||||
<xsd:import namespace="http://server.ws.soap.baeldung.com/" schemaLocation="http://localhost:8888/ws/country?xsd=1"></xsd:import>
|
|
||||||
</xsd:schema>
|
|
||||||
</types>
|
|
||||||
<message name="findByName">
|
|
||||||
<part name="arg0" type="xsd:string"></part>
|
|
||||||
</message>
|
|
||||||
<message name="findByNameResponse">
|
|
||||||
<part name="return" type="tns:country"></part>
|
|
||||||
</message>
|
|
||||||
<portType name="CountryService">
|
|
||||||
<operation name="findByName">
|
|
||||||
<input wsam:Action="http://server.ws.soap.baeldung.com/CountryService/findByNameRequest" message="tns:findByName"></input>
|
|
||||||
<output wsam:Action="http://server.ws.soap.baeldung.com/CountryService/findByNameResponse" message="tns:findByNameResponse"></output>
|
|
||||||
</operation>
|
|
||||||
</portType>
|
|
||||||
<binding name="CountryServiceImplPortBinding" type="tns:CountryService">
|
|
||||||
<soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="rpc"></soap:binding>
|
|
||||||
<operation name="findByName">
|
|
||||||
<soap:operation soapAction=""></soap:operation>
|
|
||||||
<input>
|
|
||||||
<soap:body use="literal" namespace="http://server.ws.soap.baeldung.com/"></soap:body>
|
|
||||||
</input>
|
|
||||||
<output>
|
|
||||||
<soap:body use="literal" namespace="http://server.ws.soap.baeldung.com/"></soap:body>
|
|
||||||
</output>
|
|
||||||
</operation>
|
|
||||||
</binding>
|
|
||||||
<service name="CountryServiceImplService">
|
|
||||||
<port name="CountryServiceImplPort" binding="tns:CountryServiceImplPortBinding">
|
|
||||||
<soap:address location="http://localhost:8888/ws/country"></soap:address>
|
|
||||||
</port>
|
|
||||||
</service>
|
|
||||||
</definitions>
|
|
|
@ -1,20 +1,17 @@
|
||||||
package com.baeldung.batch.understanding;
|
package com.baeldung.batch.understanding;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
import javax.batch.operations.JobOperator;
|
import javax.batch.operations.JobOperator;
|
||||||
import javax.batch.runtime.BatchRuntime;
|
import javax.batch.runtime.BatchRuntime;
|
||||||
import javax.batch.runtime.BatchStatus;
|
import javax.batch.runtime.BatchStatus;
|
||||||
import javax.batch.runtime.JobExecution;
|
import javax.batch.runtime.JobExecution;
|
||||||
import javax.batch.runtime.Metric;
|
|
||||||
import javax.batch.runtime.StepExecution;
|
import javax.batch.runtime.StepExecution;
|
||||||
import com.baeldung.batch.understanding.BatchTestHelper;
|
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.api.Disabled;
|
|
||||||
|
|
||||||
@Disabled("Should be fixed in BAEL-3812")
|
|
||||||
class CustomCheckPointUnitTest {
|
class CustomCheckPointUnitTest {
|
||||||
@Test
|
@Test
|
||||||
public void givenChunk_whenCustomCheckPoint_thenCommitCountIsThree() throws Exception {
|
public void givenChunk_whenCustomCheckPoint_thenCommitCountIsThree() throws Exception {
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
package com.baeldung.batch.understanding;
|
package com.baeldung.batch.understanding;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -13,9 +15,7 @@ import javax.batch.runtime.JobExecution;
|
||||||
import javax.batch.runtime.StepExecution;
|
import javax.batch.runtime.StepExecution;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.api.Disabled;
|
|
||||||
|
|
||||||
@Disabled("Should be fixed in BAEL-3812")
|
|
||||||
class JobSequenceUnitTest {
|
class JobSequenceUnitTest {
|
||||||
@Test
|
@Test
|
||||||
public void givenTwoSteps_thenBatch_CompleteWithSuccess() throws Exception {
|
public void givenTwoSteps_thenBatch_CompleteWithSuccess() throws Exception {
|
||||||
|
|
|
@ -1,17 +1,16 @@
|
||||||
package com.baeldung.batch.understanding;
|
package com.baeldung.batch.understanding;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Disabled;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
import javax.batch.operations.JobOperator;
|
import javax.batch.operations.JobOperator;
|
||||||
import javax.batch.runtime.BatchRuntime;
|
import javax.batch.runtime.BatchRuntime;
|
||||||
import javax.batch.runtime.BatchStatus;
|
import javax.batch.runtime.BatchStatus;
|
||||||
import javax.batch.runtime.JobExecution;
|
import javax.batch.runtime.JobExecution;
|
||||||
import java.util.Properties;
|
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
@Disabled("Should be fixed in BAEL-3812")
|
|
||||||
class SimpleBatchLetUnitTest {
|
class SimpleBatchLetUnitTest {
|
||||||
@Test
|
@Test
|
||||||
public void givenBatchLet_thenBatch_CompleteWithSuccess() throws Exception {
|
public void givenBatchLet_thenBatch_CompleteWithSuccess() throws Exception {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package com.baeldung.batch.understanding;
|
package com.baeldung.batch.understanding;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -14,9 +15,7 @@ import javax.batch.runtime.Metric;
|
||||||
import javax.batch.runtime.StepExecution;
|
import javax.batch.runtime.StepExecution;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.api.Disabled;
|
|
||||||
|
|
||||||
@Disabled("Should be fixed in BAEL-3812")
|
|
||||||
class SimpleChunkUnitTest {
|
class SimpleChunkUnitTest {
|
||||||
@Test
|
@Test
|
||||||
public void givenChunk_thenBatch_CompletesWithSucess() throws Exception {
|
public void givenChunk_thenBatch_CompletesWithSucess() throws Exception {
|
||||||
|
|
|
@ -1,19 +1,18 @@
|
||||||
package com.baeldung.batch.understanding;
|
package com.baeldung.batch.understanding;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Disabled;
|
import static org.junit.Assert.assertEquals;
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
import javax.batch.operations.JobOperator;
|
import javax.batch.operations.JobOperator;
|
||||||
import javax.batch.runtime.BatchRuntime;
|
import javax.batch.runtime.BatchRuntime;
|
||||||
import javax.batch.runtime.BatchStatus;
|
import javax.batch.runtime.BatchStatus;
|
||||||
import javax.batch.runtime.JobExecution;
|
import javax.batch.runtime.JobExecution;
|
||||||
import javax.batch.runtime.StepExecution;
|
import javax.batch.runtime.StepExecution;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Properties;
|
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
@Disabled("Should be fixed in BAEL-3812")
|
|
||||||
class SimpleErrorChunkUnitTest {
|
class SimpleErrorChunkUnitTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
db-url=jdbc:h2:mem:jberet-repo;DB_CLOSE_DELAY=-1
|
|
@ -1013,7 +1013,7 @@
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<lifecycle.mapping.version>1.0.0</lifecycle.mapping.version>
|
<lifecycle.mapping.version>1.0.0</lifecycle.mapping.version>
|
||||||
<spring.web.version>0.24.0-RC.0</spring.web.version>
|
<spring.web.version>0.24.0</spring.web.version>
|
||||||
<!-- Build properties -->
|
<!-- Build properties -->
|
||||||
<maven.version>3.0.0</maven.version>
|
<maven.version>3.0.0</maven.version>
|
||||||
<java.version>1.8</java.version>
|
<java.version>1.8</java.version>
|
||||||
|
|
|
@ -910,6 +910,6 @@
|
||||||
<sonar.tests>${project.basedir}/src/test/</sonar.tests>
|
<sonar.tests>${project.basedir}/src/test/</sonar.tests>
|
||||||
|
|
||||||
<!-- jhipster-needle-maven-property -->
|
<!-- jhipster-needle-maven-property -->
|
||||||
<zalando.version>0.24.0-RC.0</zalando.version>
|
<zalando.version>0.24.0</zalando.version>
|
||||||
</properties>
|
</properties>
|
||||||
</project>
|
</project>
|
||||||
|
|
|
@ -835,7 +835,7 @@
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<lifecycle.mapping.version>1.0.0</lifecycle.mapping.version>
|
<lifecycle.mapping.version>1.0.0</lifecycle.mapping.version>
|
||||||
<spring.web.version>0.24.0-RC.0</spring.web.version>
|
<spring.web.version>0.24.0</spring.web.version>
|
||||||
<!-- Build properties -->
|
<!-- Build properties -->
|
||||||
<maven.version>3.0.0</maven.version>
|
<maven.version>3.0.0</maven.version>
|
||||||
<java.version>1.8</java.version>
|
<java.version>1.8</java.version>
|
||||||
|
|
|
@ -1,6 +0,0 @@
|
||||||
## Maven and Java 11
|
|
||||||
|
|
||||||
This module contains articles about Maven with Java 11+.
|
|
||||||
|
|
||||||
### Relevant Articles:
|
|
||||||
|
|
|
@ -1,17 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
|
||||||
<groupId>com.baeldung.daomodule</groupId>
|
|
||||||
<artifactId>daomodule</artifactId>
|
|
||||||
<version>1.0</version>
|
|
||||||
<name>daomodule</name>
|
|
||||||
<packaging>jar</packaging>
|
|
||||||
|
|
||||||
<parent>
|
|
||||||
<groupId>com.baeldung.multimodule-maven-project</groupId>
|
|
||||||
<artifactId>multimodule-maven-project</artifactId>
|
|
||||||
<version>1.0</version>
|
|
||||||
</parent>
|
|
||||||
|
|
||||||
</project>
|
|
|
@ -1,12 +0,0 @@
|
||||||
package com.baeldung.dao;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
public interface Dao<T> {
|
|
||||||
|
|
||||||
Optional<T> findById(int id);
|
|
||||||
|
|
||||||
List<T> findAll();
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,3 +0,0 @@
|
||||||
module com.baeldung.dao {
|
|
||||||
exports com.baeldung.dao;
|
|
||||||
}
|
|
|
@ -1,22 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
|
||||||
<groupId>com.baeldung.entitymodule</groupId>
|
|
||||||
<artifactId>entitymodule</artifactId>
|
|
||||||
<version>1.0</version>
|
|
||||||
<name>entitymodule</name>
|
|
||||||
<packaging>jar</packaging>
|
|
||||||
|
|
||||||
<parent>
|
|
||||||
<groupId>com.baeldung.multimodule-maven-project</groupId>
|
|
||||||
<artifactId>multimodule-maven-project</artifactId>
|
|
||||||
<version>1.0</version>
|
|
||||||
</parent>
|
|
||||||
|
|
||||||
<properties>
|
|
||||||
<maven.compiler.source>11</maven.compiler.source>
|
|
||||||
<maven.compiler.target>11</maven.compiler.target>
|
|
||||||
</properties>
|
|
||||||
|
|
||||||
</project>
|
|
|
@ -1,19 +0,0 @@
|
||||||
package com.baeldung.entity;
|
|
||||||
|
|
||||||
public class User {
|
|
||||||
|
|
||||||
private final String name;
|
|
||||||
|
|
||||||
public User(String name) {
|
|
||||||
this.name = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getName() {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "User{" + "name=" + name + '}';
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,3 +0,0 @@
|
||||||
module com.baeldung.entity {
|
|
||||||
exports com.baeldung.entity;
|
|
||||||
}
|
|
|
@ -1,38 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
|
||||||
<groupId>com.baeldung.mainappmodule</groupId>
|
|
||||||
<artifactId>mainappmodule</artifactId>
|
|
||||||
<version>1.0</version>
|
|
||||||
<name>mainappmodule</name>
|
|
||||||
<packaging>jar</packaging>
|
|
||||||
|
|
||||||
<parent>
|
|
||||||
<groupId>com.baeldung.multimodule-maven-project</groupId>
|
|
||||||
<artifactId>multimodule-maven-project</artifactId>
|
|
||||||
<version>1.0</version>
|
|
||||||
<entitymodule.version>1.0</entitymodule.version>
|
|
||||||
<daomodule.version>1.0</daomodule.version>
|
|
||||||
<userdaomodule.version>1.0</userdaomodule.version>
|
|
||||||
</parent>
|
|
||||||
|
|
||||||
<dependencies>
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.baeldung.entitymodule</groupId>
|
|
||||||
<artifactId>entitymodule</artifactId>
|
|
||||||
<version>${entitymodule.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.baeldung.daomodule</groupId>
|
|
||||||
<artifactId>daomodule</artifactId>
|
|
||||||
<version>${daomodule.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.baeldung.userdaomodule</groupId>
|
|
||||||
<artifactId>userdaomodule</artifactId>
|
|
||||||
<version>${userdaomodule.version}</version>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
|
||||||
|
|
||||||
</project>
|
|
|
@ -1,19 +0,0 @@
|
||||||
package com.baeldung.mainapp;
|
|
||||||
|
|
||||||
import com.baeldung.dao.Dao;
|
|
||||||
import com.baeldung.entity.User;
|
|
||||||
import com.baeldung.userdao.UserDao;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public class Application {
|
|
||||||
|
|
||||||
public static void main(String[] args) {
|
|
||||||
Map<Integer, User> users = new HashMap<>();
|
|
||||||
users.put(1, new User("Julie"));
|
|
||||||
users.put(2, new User("David"));
|
|
||||||
Dao userDao = new UserDao(users);
|
|
||||||
userDao.findAll().forEach(System.out::println);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,6 +0,0 @@
|
||||||
module com.baeldung.mainapp {
|
|
||||||
requires com.baeldung.entity;
|
|
||||||
requires com.baeldung.userdao;
|
|
||||||
requires com.baeldung.dao;
|
|
||||||
uses com.baeldung.dao.Dao;
|
|
||||||
}
|
|
|
@ -1,66 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
|
||||||
<groupId>com.baeldung.multimodule-maven-project</groupId>
|
|
||||||
<artifactId>multimodule-maven-project</artifactId>
|
|
||||||
<version>1.0</version>
|
|
||||||
<name>multimodule-maven-project</name>
|
|
||||||
<packaging>pom</packaging>
|
|
||||||
|
|
||||||
<parent>
|
|
||||||
<groupId>com.baeldung.maven-java-11</groupId>
|
|
||||||
<artifactId>maven-java-11</artifactId>
|
|
||||||
<version>1.0</version>
|
|
||||||
</parent>
|
|
||||||
|
|
||||||
<modules>
|
|
||||||
<module>entitymodule</module>
|
|
||||||
<module>daomodule</module>
|
|
||||||
<module>userdaomodule</module>
|
|
||||||
<module>mainappmodule</module>
|
|
||||||
</modules>
|
|
||||||
|
|
||||||
<dependencyManagement>
|
|
||||||
<dependencies>
|
|
||||||
<dependency>
|
|
||||||
<groupId>junit</groupId>
|
|
||||||
<artifactId>junit</artifactId>
|
|
||||||
<version>${junit.version}</version>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.assertj</groupId>
|
|
||||||
<artifactId>assertj-core</artifactId>
|
|
||||||
<version>${assertj.version}</version>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
|
||||||
</dependencyManagement>
|
|
||||||
|
|
||||||
<build>
|
|
||||||
<pluginManagement>
|
|
||||||
<plugins>
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
|
||||||
<artifactId>maven-compiler-plugin</artifactId>
|
|
||||||
<version>${compiler.plugin.version}</version>
|
|
||||||
<configuration>
|
|
||||||
<source>${source.version}</source>
|
|
||||||
<target>${target.version}</target>
|
|
||||||
</configuration>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
|
||||||
</pluginManagement>
|
|
||||||
</build>
|
|
||||||
|
|
||||||
<properties>
|
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
|
||||||
<junit.version>4.12</junit.version>
|
|
||||||
<assertj.version>3.12.2</assertj.version>
|
|
||||||
<compiler.plugin.version>3.8.0</compiler.plugin.version>
|
|
||||||
<source.version>11</source.version>
|
|
||||||
<target.version>11</target.version>
|
|
||||||
</properties>
|
|
||||||
|
|
||||||
</project>
|
|
|
@ -1,42 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project
|
|
||||||
xmlns="http://maven.apache.org/POM/4.0.0"
|
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
|
||||||
<groupId>com.baeldung.userdaomodule</groupId>
|
|
||||||
<artifactId>userdaomodule</artifactId>
|
|
||||||
<version>1.0</version>
|
|
||||||
<name>userdaomodule</name>
|
|
||||||
<packaging>jar</packaging>
|
|
||||||
|
|
||||||
<parent>
|
|
||||||
<groupId>com.baeldung.multimodule-maven-project</groupId>
|
|
||||||
<artifactId>multimodule-maven-project</artifactId>
|
|
||||||
<version>1.0</version>
|
|
||||||
</parent>
|
|
||||||
|
|
||||||
<dependencies>
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.baeldung.entitymodule</groupId>
|
|
||||||
<artifactId>entitymodule</artifactId>
|
|
||||||
<version>${entitymodule.version}1.0</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.baeldung.daomodule</groupId>
|
|
||||||
<artifactId>daomodule</artifactId>
|
|
||||||
<version>${daomodule.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>junit</groupId>
|
|
||||||
<artifactId>junit</artifactId>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
|
||||||
|
|
||||||
<properties>
|
|
||||||
<entitymodule.version>1.0</entitymodule.version>
|
|
||||||
<daomodule.version>1.0</daomodule.version>
|
|
||||||
</properties>
|
|
||||||
|
|
||||||
</project>
|
|
|
@ -1,32 +0,0 @@
|
||||||
package com.baeldung.userdao;
|
|
||||||
|
|
||||||
import com.baeldung.dao.Dao;
|
|
||||||
import com.baeldung.entity.User;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
public class UserDao implements Dao<User> {
|
|
||||||
|
|
||||||
private final Map<Integer, User> users;
|
|
||||||
|
|
||||||
public UserDao() {
|
|
||||||
users = new HashMap<>();
|
|
||||||
}
|
|
||||||
|
|
||||||
public UserDao(Map<Integer, User> users) {
|
|
||||||
this.users = users;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<User> findAll() {
|
|
||||||
return new ArrayList<>(users.values());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Optional<User> findById(int id) {
|
|
||||||
return Optional.ofNullable(users.get(id));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,6 +0,0 @@
|
||||||
module com.baeldung.userdao {
|
|
||||||
requires com.baeldung.entity;
|
|
||||||
requires com.baeldung.dao;
|
|
||||||
provides com.baeldung.dao.Dao with com.baeldung.userdao.UserDao;
|
|
||||||
exports com.baeldung.userdao;
|
|
||||||
}
|
|
|
@ -1,36 +0,0 @@
|
||||||
package com.baeldung.userdao.test;
|
|
||||||
|
|
||||||
import com.baeldung.dao.Dao;
|
|
||||||
import com.baeldung.entity.User;
|
|
||||||
import com.baeldung.userdao.UserDao;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Optional;
|
|
||||||
import static org.junit.Assert.*;
|
|
||||||
import static org.hamcrest.CoreMatchers.*;
|
|
||||||
import org.junit.Before;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
public class UserDaoUnitTest {
|
|
||||||
|
|
||||||
private Dao userDao;
|
|
||||||
|
|
||||||
@Before
|
|
||||||
public void setUpUserDaoInstance() {
|
|
||||||
Map<Integer, User> users = new HashMap<>();
|
|
||||||
users.put(1, new User("Julie"));
|
|
||||||
users.put(2, new User("David"));
|
|
||||||
userDao = new UserDao(users);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void givenUserDaoIntance_whenCalledFindById_thenCorrect() {
|
|
||||||
assertThat(userDao.findById(1), isA(Optional.class));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void givenUserDaoIntance_whenCalledFindAll_thenCorrect() {
|
|
||||||
assertThat(userDao.findAll(), isA(List.class));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,27 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
|
||||||
<groupId>com.baeldung.maven-java-11</groupId>
|
|
||||||
<artifactId>maven-java-11</artifactId>
|
|
||||||
<version>1.0</version>
|
|
||||||
<name>maven-java-11</name>
|
|
||||||
<packaging>pom</packaging>
|
|
||||||
|
|
||||||
<parent>
|
|
||||||
<groupId>com.baeldung</groupId>
|
|
||||||
<artifactId>parent-modules</artifactId>
|
|
||||||
<version>1.0.0-SNAPSHOT</version>
|
|
||||||
</parent>
|
|
||||||
|
|
||||||
<modules>
|
|
||||||
<module>multimodule-maven-project</module>
|
|
||||||
</modules>
|
|
||||||
|
|
||||||
<properties>
|
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
|
||||||
<maven.compiler.source>11</maven.compiler.source>
|
|
||||||
<maven.compiler.target>11</maven.compiler.target>
|
|
||||||
</properties>
|
|
||||||
|
|
||||||
</project>
|
|
|
@ -14,8 +14,8 @@ public interface AddressMapper {
|
||||||
@Results(value = { @Result(property = "addressId", column = "addressId"),
|
@Results(value = { @Result(property = "addressId", column = "addressId"),
|
||||||
@Result(property = "streetAddress", column = "streetAddress"),
|
@Result(property = "streetAddress", column = "streetAddress"),
|
||||||
@Result(property = "person", column = "personId", javaType = Person.class, one = @One(select = "getPerson")) })
|
@Result(property = "person", column = "personId", javaType = Person.class, one = @One(select = "getPerson")) })
|
||||||
Address getAddresses(Integer addressID);
|
Address getAddresses(Integer addressId);
|
||||||
|
|
||||||
@Select("SELECT personId FROM address WHERE addressId = #{addressId})")
|
@Select("SELECT personId FROM address WHERE addressId = #{addressId})")
|
||||||
Person getPerson(Integer personId);
|
Person getPerson(Integer addressId);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
package com.baeldung.s;
|
||||||
|
|
||||||
|
public class TextManipulator {
|
||||||
|
private String text;
|
||||||
|
|
||||||
|
public TextManipulator(String text) {
|
||||||
|
this.text = text;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getText() {
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void appendText(String newText) {
|
||||||
|
text = text.concat(newText);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void findWordAndReplace(String word, String replacementWord) {
|
||||||
|
if (text.contains(word)) {
|
||||||
|
text = text.replace(word, replacementWord);
|
||||||
|
} else System.out.println("Word you want to replace is not found in the text");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void findWordAndDelete(String word) {
|
||||||
|
if (text.contains(word)) {
|
||||||
|
text = text.replace(word, "");
|
||||||
|
} else System.out.println("Word you want to delete is not found in the text");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Bad practice when implementing SRP principle, not in the scope of this class
|
||||||
|
public void printText() {
|
||||||
|
System.out.println(textManipulator.getText());
|
||||||
|
}*/
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
package com.baeldung.s;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
public class TextPrinter {
|
||||||
|
TextManipulator textManipulator;
|
||||||
|
|
||||||
|
public TextPrinter(TextManipulator textManipulator) {
|
||||||
|
this.textManipulator = textManipulator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void printText() {
|
||||||
|
System.out.println(textManipulator.getText());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void printOutEachWordOfText() {
|
||||||
|
System.out.println(Arrays.toString(textManipulator.getText().split(" ")));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void printRangeOfCharacters(int startingIndex, int endIndex) {
|
||||||
|
System.out.println(textManipulator.getText().substring(startingIndex, endIndex));
|
||||||
|
}
|
||||||
|
}
|
|
@ -48,6 +48,17 @@
|
||||||
<version>${postgres.version}</version>
|
<version>${postgres.version}</version>
|
||||||
<scope>runtime</scope>
|
<scope>runtime</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.querydsl</groupId>
|
||||||
|
<artifactId>querydsl-apt</artifactId>
|
||||||
|
<version>${querydsl.version}</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.querydsl</groupId>
|
||||||
|
<artifactId>querydsl-jpa</artifactId>
|
||||||
|
<version>${querydsl.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.assertj</groupId>
|
<groupId>org.assertj</groupId>
|
||||||
|
@ -101,23 +112,41 @@
|
||||||
<configuration>
|
<configuration>
|
||||||
<sources>
|
<sources>
|
||||||
<source>target/metamodel</source>
|
<source>target/metamodel</source>
|
||||||
|
<source>${project.build.directory}/generated-sources/java/</source>
|
||||||
</sources>
|
</sources>
|
||||||
</configuration>
|
</configuration>
|
||||||
</execution>
|
</execution>
|
||||||
</executions>
|
</executions>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>com.mysema.maven</groupId>
|
||||||
|
<artifactId>apt-maven-plugin</artifactId>
|
||||||
|
<version>1.1.3</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<goals>
|
||||||
|
<goal>process</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<outputDirectory>target/generated-sources/java</outputDirectory>
|
||||||
|
<processor>com.querydsl.apt.jpa.JPAAnnotationProcessor</processor>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<hibernate.version>5.4.0.Final</hibernate.version>
|
<hibernate.version>5.4.14.Final</hibernate.version>
|
||||||
<eclipselink.version>2.7.4-RC1</eclipselink.version>
|
<eclipselink.version>2.7.4</eclipselink.version>
|
||||||
<postgres.version>42.2.5</postgres.version>
|
<postgres.version>42.2.5</postgres.version>
|
||||||
<javax.persistence-api.version>2.2</javax.persistence-api.version>
|
<javax.persistence-api.version>2.2</javax.persistence-api.version>
|
||||||
<assertj.version>3.11.1</assertj.version>
|
<assertj.version>3.11.1</assertj.version>
|
||||||
<maven-compiler-plugin.version>3.5.1</maven-compiler-plugin.version>
|
<maven-compiler-plugin.version>3.5.1</maven-compiler-plugin.version>
|
||||||
<maven-processor-plugin.version>3.3.3</maven-processor-plugin.version>
|
<maven-processor-plugin.version>3.3.3</maven-processor-plugin.version>
|
||||||
<build-helper-maven-plugin.version>3.0.0</build-helper-maven-plugin.version>
|
<build-helper-maven-plugin.version>3.0.0</build-helper-maven-plugin.version>
|
||||||
|
<querydsl.version>4.3.1</querydsl.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
</project>
|
</project>
|
|
@ -0,0 +1,90 @@
|
||||||
|
package com.baeldung.jpa.unrelated.entities;
|
||||||
|
|
||||||
|
import org.hibernate.annotations.Fetch;
|
||||||
|
import org.hibernate.annotations.FetchMode;
|
||||||
|
import org.hibernate.annotations.NotFound;
|
||||||
|
import org.hibernate.annotations.NotFoundAction;
|
||||||
|
|
||||||
|
import javax.persistence.*;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Table(name = "menu")
|
||||||
|
public class Cocktail {
|
||||||
|
@Id
|
||||||
|
@Column(name = "cocktail_name")
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
private double price;
|
||||||
|
|
||||||
|
@Column(name = "category")
|
||||||
|
private String category;
|
||||||
|
|
||||||
|
@OneToOne
|
||||||
|
@NotFound(action = NotFoundAction.IGNORE)
|
||||||
|
@JoinColumn(name = "cocktail_name",
|
||||||
|
referencedColumnName = "cocktail",
|
||||||
|
insertable = false, updatable = false,
|
||||||
|
foreignKey = @javax.persistence
|
||||||
|
.ForeignKey(value = ConstraintMode.NO_CONSTRAINT))
|
||||||
|
private Recipe recipe;
|
||||||
|
|
||||||
|
@OneToMany(fetch = FetchType.LAZY)
|
||||||
|
@NotFound(action = NotFoundAction.IGNORE)
|
||||||
|
@JoinColumn(
|
||||||
|
name = "cocktail",
|
||||||
|
referencedColumnName = "cocktail_name",
|
||||||
|
insertable = false,
|
||||||
|
updatable = false,
|
||||||
|
foreignKey = @javax.persistence
|
||||||
|
.ForeignKey(value = ConstraintMode.NO_CONSTRAINT))
|
||||||
|
private List<MultipleRecipe> recipeList;
|
||||||
|
|
||||||
|
public Cocktail() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Cocktail(String name, double price, String baseIngredient) {
|
||||||
|
this.name = name;
|
||||||
|
this.price = price;
|
||||||
|
this.category = baseIngredient;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getPrice() {
|
||||||
|
return price;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCategory() {
|
||||||
|
return category;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Recipe getRecipe() {
|
||||||
|
return recipe;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<MultipleRecipe> getRecipeList() {
|
||||||
|
return recipeList;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o)
|
||||||
|
return true;
|
||||||
|
if (o == null || getClass() != o.getClass())
|
||||||
|
return false;
|
||||||
|
Cocktail cocktail = (Cocktail) o;
|
||||||
|
return Double.compare(cocktail.price, price) == 0 &&
|
||||||
|
Objects.equals(name, cocktail.name) &&
|
||||||
|
Objects.equals(category, cocktail.category);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(name, price, category);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,71 @@
|
||||||
|
package com.baeldung.jpa.unrelated.entities;
|
||||||
|
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.Table;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Table(name = "multiple_recipes")
|
||||||
|
public class MultipleRecipe {
|
||||||
|
@Id
|
||||||
|
@Column(name = "id")
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@Column(name = "cocktail")
|
||||||
|
private String cocktail;
|
||||||
|
|
||||||
|
@Column(name = "instructions")
|
||||||
|
private String instructions;
|
||||||
|
|
||||||
|
@Column(name = "base_ingredient")
|
||||||
|
private String baseIngredient;
|
||||||
|
|
||||||
|
public MultipleRecipe() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public MultipleRecipe(Long id, String cocktail,
|
||||||
|
String instructions, String baseIngredient) {
|
||||||
|
this.id = id;
|
||||||
|
this.cocktail = cocktail;
|
||||||
|
this.instructions = instructions;
|
||||||
|
this.baseIngredient = baseIngredient;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCocktail() {
|
||||||
|
return cocktail;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getInstructions() {
|
||||||
|
return instructions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getBaseIngredient() {
|
||||||
|
return baseIngredient;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o)
|
||||||
|
return true;
|
||||||
|
if (o == null || getClass() != o.getClass())
|
||||||
|
return false;
|
||||||
|
MultipleRecipe that = (MultipleRecipe) o;
|
||||||
|
|
||||||
|
return Objects.equals(id, that.id) &&
|
||||||
|
Objects.equals(cocktail, that.cocktail) &&
|
||||||
|
Objects.equals(instructions, that.instructions) &&
|
||||||
|
Objects.equals(baseIngredient, that.baseIngredient);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(id, cocktail,
|
||||||
|
instructions, baseIngredient);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,50 @@
|
||||||
|
package com.baeldung.jpa.unrelated.entities;
|
||||||
|
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.Table;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Table(name="recipes")
|
||||||
|
public class Recipe {
|
||||||
|
@Id
|
||||||
|
@Column(name = "cocktail")
|
||||||
|
private String cocktail;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
private String instructions;
|
||||||
|
|
||||||
|
public Recipe() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Recipe(String cocktail, String instructions) {
|
||||||
|
this.cocktail = cocktail;
|
||||||
|
this.instructions = instructions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCocktail() {
|
||||||
|
return cocktail;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getInstructions() {
|
||||||
|
return instructions;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o)
|
||||||
|
return true;
|
||||||
|
if (o == null || getClass() != o.getClass())
|
||||||
|
return false;
|
||||||
|
Recipe recipe = (Recipe) o;
|
||||||
|
return Objects.equals(cocktail, recipe.cocktail)
|
||||||
|
&& Objects.equals(instructions, recipe.instructions);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(cocktail, instructions);
|
||||||
|
}
|
||||||
|
}
|
|
@ -163,4 +163,25 @@
|
||||||
</properties>
|
</properties>
|
||||||
</persistence-unit>
|
</persistence-unit>
|
||||||
|
|
||||||
|
<persistence-unit name="jpa-h2-unrelated-entities">
|
||||||
|
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
|
||||||
|
<class>com.baeldung.jpa.unrelated.entities.Cocktail</class>
|
||||||
|
<class>com.baeldung.jpa.unrelated.entities.Recipe</class>
|
||||||
|
<class>com.baeldung.jpa.unrelated.entities.MultipleRecipe</class>
|
||||||
|
<exclude-unlisted-classes>true</exclude-unlisted-classes>
|
||||||
|
<properties>
|
||||||
|
<property name="javax.persistence.jdbc.driver"
|
||||||
|
value="org.h2.Driver" />
|
||||||
|
<property name="javax.persistence.jdbc.url"
|
||||||
|
value="jdbc:h2:mem:test" />
|
||||||
|
<property name="javax.persistence.jdbc.user" value="sa" />
|
||||||
|
<property name="javax.persistence.jdbc.password" value="" />
|
||||||
|
<property name="hibernate.dialect"
|
||||||
|
value="org.hibernate.dialect.H2Dialect" />
|
||||||
|
<property name="hibernate.hbm2ddl.auto" value="create" />
|
||||||
|
<property name="show_sql" value="true" />
|
||||||
|
<property name="hibernate.temp.use_jdbc_metadata_defaults"
|
||||||
|
value="false" />
|
||||||
|
</properties>
|
||||||
|
</persistence-unit>
|
||||||
</persistence>
|
</persistence>
|
|
@ -0,0 +1,189 @@
|
||||||
|
package com.baeldung.jpa.unrelated.entities;
|
||||||
|
|
||||||
|
import javax.persistence.*;
|
||||||
|
|
||||||
|
import com.querydsl.jpa.impl.JPAQuery;
|
||||||
|
import org.junit.jupiter.api.*;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
public class UnrelatedEntitiesUnitTest {
|
||||||
|
private static EntityManagerFactory entityManagerFactory;
|
||||||
|
private static EntityManager entityManager;
|
||||||
|
private static Cocktail mojito;
|
||||||
|
private static Cocktail ginTonic;
|
||||||
|
|
||||||
|
@BeforeAll
|
||||||
|
public static void setup() {
|
||||||
|
entityManagerFactory = Persistence.createEntityManagerFactory("jpa-h2-unrelated-entities");
|
||||||
|
entityManager = entityManagerFactory.createEntityManager();
|
||||||
|
mojito = new Cocktail("Mojito", 11, "Rum");
|
||||||
|
ginTonic = new Cocktail("Gin tonic", 8.50, "Gin");
|
||||||
|
entityManager.getTransaction().begin();
|
||||||
|
entityManager.persist(mojito);
|
||||||
|
entityManager.persist(ginTonic);
|
||||||
|
entityManager.persist(new Recipe(mojito.getName(), "Some instructions"));
|
||||||
|
entityManager.persist(new MultipleRecipe(1L, mojito.getName(),
|
||||||
|
"some instructions", mojito.getCategory()));
|
||||||
|
entityManager.persist(new MultipleRecipe(2L, mojito.getName(),
|
||||||
|
"some other instructions", mojito.getCategory()));
|
||||||
|
entityManager.getTransaction().commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterAll
|
||||||
|
public static void closeSession() {
|
||||||
|
entityManager.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenCocktailsWithRecipe_whenQuerying_thenTheExpectedCocktailsReturned() {
|
||||||
|
// JPA
|
||||||
|
Cocktail cocktail = entityManager.createQuery("select c "
|
||||||
|
+ "from Cocktail c join c.recipe", Cocktail.class)
|
||||||
|
.getSingleResult();
|
||||||
|
verifyResult(mojito, cocktail);
|
||||||
|
|
||||||
|
cocktail = entityManager.createQuery("select c "
|
||||||
|
+ "from Cocktail c join Recipe r "
|
||||||
|
+ "on c.name = r.cocktail", Cocktail.class)
|
||||||
|
.getSingleResult();
|
||||||
|
verifyResult(mojito, cocktail);
|
||||||
|
|
||||||
|
// QueryDSL
|
||||||
|
cocktail = new JPAQuery<Cocktail>(entityManager).from(QCocktail.cocktail)
|
||||||
|
.join(QCocktail.cocktail.recipe)
|
||||||
|
.fetchOne();
|
||||||
|
verifyResult(mojito, cocktail);
|
||||||
|
|
||||||
|
cocktail = new JPAQuery<Cocktail>(entityManager).from(QCocktail.cocktail)
|
||||||
|
.join(QRecipe.recipe)
|
||||||
|
.on(QCocktail.cocktail.name.eq(QRecipe.recipe.cocktail))
|
||||||
|
.fetchOne();
|
||||||
|
verifyResult(mojito, cocktail);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenCocktailsWithoutRecipe_whenQuerying_thenTheExpectedCocktailsReturned() {
|
||||||
|
Cocktail cocktail = entityManager.createQuery("select c "
|
||||||
|
+ "from Cocktail c left join c.recipe r "
|
||||||
|
+ "where r is null", Cocktail.class)
|
||||||
|
.getSingleResult();
|
||||||
|
verifyResult(ginTonic, cocktail);
|
||||||
|
|
||||||
|
cocktail = entityManager.createQuery("select c "
|
||||||
|
+ "from Cocktail c left join Recipe r "
|
||||||
|
+ "on c.name = r.cocktail "
|
||||||
|
+ "where r is null", Cocktail.class)
|
||||||
|
.getSingleResult();
|
||||||
|
verifyResult(ginTonic, cocktail);
|
||||||
|
|
||||||
|
QRecipe recipe = new QRecipe("alias");
|
||||||
|
cocktail = new JPAQuery<Cocktail>(entityManager).from(QCocktail.cocktail)
|
||||||
|
.leftJoin(QCocktail.cocktail.recipe, recipe)
|
||||||
|
.where(recipe.isNull())
|
||||||
|
.fetchOne();
|
||||||
|
verifyResult(ginTonic, cocktail);
|
||||||
|
|
||||||
|
cocktail = new JPAQuery<Cocktail>(entityManager).from(QCocktail.cocktail)
|
||||||
|
.leftJoin(QRecipe.recipe)
|
||||||
|
.on(QCocktail.cocktail.name.eq(QRecipe.recipe.cocktail))
|
||||||
|
.where(QRecipe.recipe.isNull())
|
||||||
|
.fetchOne();
|
||||||
|
verifyResult(ginTonic, cocktail);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenCocktailsWithMultipleRecipes_whenQuerying_thenTheExpectedCocktailsReturned() {
|
||||||
|
// JPQL
|
||||||
|
Cocktail cocktail = entityManager.createQuery("select c "
|
||||||
|
+ "from Cocktail c join c.recipeList", Cocktail.class)
|
||||||
|
.getSingleResult();
|
||||||
|
verifyResult(mojito, cocktail);
|
||||||
|
|
||||||
|
cocktail = entityManager.createQuery("select c "
|
||||||
|
+ "from Cocktail c join MultipleRecipe mr "
|
||||||
|
+ "on mr.cocktail = c.name", Cocktail.class)
|
||||||
|
.getSingleResult();
|
||||||
|
verifyResult(mojito, cocktail);
|
||||||
|
|
||||||
|
// QueryDSL
|
||||||
|
cocktail = new JPAQuery<Cocktail>(entityManager).from(QCocktail.cocktail)
|
||||||
|
.join(QCocktail.cocktail.recipeList)
|
||||||
|
.fetchOne();
|
||||||
|
verifyResult(mojito, cocktail);
|
||||||
|
|
||||||
|
cocktail = new JPAQuery<Cocktail>(entityManager).from(QCocktail.cocktail)
|
||||||
|
.join(QMultipleRecipe.multipleRecipe)
|
||||||
|
.on(QCocktail.cocktail.name.eq(QMultipleRecipe.multipleRecipe.cocktail))
|
||||||
|
.fetchOne();
|
||||||
|
verifyResult(mojito, cocktail);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenCocktailsWithoutMultipleRecipes_whenQuerying_thenTheExpectedCocktailsReturned() {
|
||||||
|
// JPQL
|
||||||
|
Cocktail cocktail = entityManager.createQuery("select c "
|
||||||
|
+ "from Cocktail c left join c.recipeList r "
|
||||||
|
+ "where r is null", Cocktail.class)
|
||||||
|
.getSingleResult();
|
||||||
|
verifyResult(ginTonic, cocktail);
|
||||||
|
|
||||||
|
cocktail = entityManager.createQuery("select c "
|
||||||
|
+ "from Cocktail c left join MultipleRecipe r "
|
||||||
|
+ "on c.name = r.cocktail "
|
||||||
|
+ "where r is null", Cocktail.class)
|
||||||
|
.getSingleResult();
|
||||||
|
verifyResult(ginTonic, cocktail);
|
||||||
|
|
||||||
|
// QueryDSL
|
||||||
|
QMultipleRecipe multipleRecipe = new QMultipleRecipe("alias");
|
||||||
|
cocktail = new JPAQuery<Cocktail>(entityManager).from(QCocktail.cocktail)
|
||||||
|
.leftJoin(QCocktail.cocktail.recipeList, multipleRecipe)
|
||||||
|
.where(multipleRecipe.isNull())
|
||||||
|
.fetchOne();
|
||||||
|
verifyResult(ginTonic, cocktail);
|
||||||
|
|
||||||
|
cocktail = new JPAQuery<Cocktail>(entityManager).from(QCocktail.cocktail)
|
||||||
|
.leftJoin(QMultipleRecipe.multipleRecipe)
|
||||||
|
.on(QCocktail.cocktail.name.eq(QMultipleRecipe.multipleRecipe.cocktail))
|
||||||
|
.where(QMultipleRecipe.multipleRecipe.isNull())
|
||||||
|
.fetchOne();
|
||||||
|
verifyResult(ginTonic, cocktail);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenMultipleRecipesWithCocktails_whenQuerying_thenTheExpectedMultipleRecipesReturned() {
|
||||||
|
Consumer<List<MultipleRecipe>> verifyResult = recipes -> {
|
||||||
|
assertEquals(2, recipes.size());
|
||||||
|
recipes.forEach(r -> assertEquals(mojito.getName(), r.getCocktail()));
|
||||||
|
};
|
||||||
|
|
||||||
|
// JPQL
|
||||||
|
List<MultipleRecipe> recipes = entityManager.createQuery("select distinct r "
|
||||||
|
+ "from MultipleRecipe r "
|
||||||
|
+ "join Cocktail c "
|
||||||
|
+ "on r.baseIngredient = c.category",
|
||||||
|
MultipleRecipe.class).getResultList();
|
||||||
|
|
||||||
|
verifyResult.accept(recipes);
|
||||||
|
|
||||||
|
// QueryDSL
|
||||||
|
QCocktail cocktail = QCocktail.cocktail;
|
||||||
|
QMultipleRecipe multipleRecipe = QMultipleRecipe.multipleRecipe;
|
||||||
|
recipes = new JPAQuery<MultipleRecipe>(entityManager).from(multipleRecipe)
|
||||||
|
.join(cocktail)
|
||||||
|
.on(multipleRecipe.baseIngredient.eq(cocktail.category))
|
||||||
|
.fetch();
|
||||||
|
|
||||||
|
verifyResult.accept(recipes);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void verifyResult(Cocktail expectedCocktail, Cocktail queryResult) {
|
||||||
|
assertNotNull(queryResult);
|
||||||
|
assertEquals(expectedCocktail, queryResult);
|
||||||
|
}
|
||||||
|
}
|
|
@ -106,7 +106,7 @@
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<hibernate.version>5.4.0.Final</hibernate.version>
|
<hibernate.version>5.4.0.Final</hibernate.version>
|
||||||
<eclipselink.version>2.7.4-RC1</eclipselink.version>
|
<eclipselink.version>2.7.4</eclipselink.version>
|
||||||
<postgres.version>42.2.5</postgres.version>
|
<postgres.version>42.2.5</postgres.version>
|
||||||
<javax.persistence-api.version>2.2</javax.persistence-api.version>
|
<javax.persistence-api.version>2.2</javax.persistence-api.version>
|
||||||
<maven-processor-plugin.version>3.3.3</maven-processor-plugin.version>
|
<maven-processor-plugin.version>3.3.3</maven-processor-plugin.version>
|
||||||
|
|
|
@ -13,3 +13,12 @@
|
||||||
- [Spring Data Annotations](http://www.baeldung.com/spring-data-annotations)
|
- [Spring Data Annotations](http://www.baeldung.com/spring-data-annotations)
|
||||||
- [Spring Data MongoDB Transactions](https://www.baeldung.com/spring-data-mongodb-transactions )
|
- [Spring Data MongoDB Transactions](https://www.baeldung.com/spring-data-mongodb-transactions )
|
||||||
- [ZonedDateTime with Spring Data MongoDB](https://www.baeldung.com/spring-data-mongodb-zoneddatetime)
|
- [ZonedDateTime with Spring Data MongoDB](https://www.baeldung.com/spring-data-mongodb-zoneddatetime)
|
||||||
|
|
||||||
|
|
||||||
|
## Spring Data MongoDB Live Testing
|
||||||
|
|
||||||
|
|
||||||
|
There are 3 scripts to simplify running live tests:
|
||||||
|
1. [`live-test-setup.sh`](src/live-test/resources/live-test-setup.sh) builds a docker image with the necessary setup and runs it. The environment is ready, when the log stops - it takes approximately 30 seconds.
|
||||||
|
2. [`live-test.sh`](src/live-test/resources/live-test.sh) runs the live tests (but no other tests).
|
||||||
|
3. [`live-test-teardown.sh`](src/live-test/resources/live-test-teardown.sh) stops and removes the docker image.
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
FROM mongo:4.2.1
|
||||||
|
|
||||||
|
COPY init-session.js /docker-entrypoint-initdb.d/
|
||||||
|
|
||||||
|
EXPOSE 27017
|
||||||
|
|
||||||
|
HEALTHCHECK --interval=5s --timeout=3s --start-period=10s CMD mongo db.stats()
|
||||||
|
CMD ["mongod", "--replSet", "rs0"]
|
|
@ -0,0 +1 @@
|
||||||
|
rs.initiate();
|
|
@ -0,0 +1,5 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
docker image build -t spring-data-mongodb:live-test .
|
||||||
|
|
||||||
|
docker run -p 27017:27017 --name spring-data-mongodb-live-test spring-data-mongodb:live-test
|
|
@ -0,0 +1,4 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
docker stop spring-data-mongodb-live-test
|
||||||
|
docker rm spring-data-mongodb-live-test
|
|
@ -0,0 +1,3 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
mvn clean compile test -P live-all -f ../../../pom.xml
|
|
@ -62,24 +62,6 @@ public class MongoTransactionalLiveTest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = MongoCommandException.class)
|
|
||||||
@Transactional
|
|
||||||
public void whenCountDuringMongoTransaction_thenException() {
|
|
||||||
userRepository.save(new User("John", 30));
|
|
||||||
userRepository.save(new User("Ringo", 35));
|
|
||||||
userRepository.count();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@Transactional
|
|
||||||
public void whenQueryDuringMongoTransaction_thenSuccess() {
|
|
||||||
userRepository.save(new User("Jane", 20));
|
|
||||||
userRepository.save(new User("Nick", 33));
|
|
||||||
List<User> users = mongoTemplate.find(new Query(), User.class);
|
|
||||||
|
|
||||||
assertTrue(users.size() > 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ==== Using test instead of before and after due to @transactional doesn't allow list collection
|
// ==== Using test instead of before and after due to @transactional doesn't allow list collection
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
32
pom.xml
32
pom.xml
|
@ -814,6 +814,7 @@
|
||||||
|
|
||||||
<module>vaadin</module>
|
<module>vaadin</module>
|
||||||
<module>vavr</module>
|
<module>vavr</module>
|
||||||
|
<module>vavr-2</module>
|
||||||
</modules>
|
</modules>
|
||||||
</profile>
|
</profile>
|
||||||
|
|
||||||
|
@ -1313,10 +1314,41 @@
|
||||||
|
|
||||||
<module>vaadin</module>
|
<module>vaadin</module>
|
||||||
<module>vavr</module>
|
<module>vavr</module>
|
||||||
|
<module>vavr-2</module>
|
||||||
</modules>
|
</modules>
|
||||||
|
|
||||||
</profile>
|
</profile>
|
||||||
|
|
||||||
|
<profile>
|
||||||
|
<id>live-all</id>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-surefire-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<excludes>
|
||||||
|
<exclude>**/SpringContextTest.java</exclude>
|
||||||
|
<exclude>**/*UnitTest.java</exclude>
|
||||||
|
<exclude>**/*IntegrationTest.java</exclude>
|
||||||
|
<exclude>**/*IntTest.java</exclude>
|
||||||
|
<exclude>**/*LongRunningUnitTest.java</exclude>
|
||||||
|
<exclude>**/*ManualTest.java</exclude>
|
||||||
|
<exclude>**/*JdbcTest.java</exclude>
|
||||||
|
</excludes>
|
||||||
|
<includes>
|
||||||
|
<include>**/*LiveTest.java</include>
|
||||||
|
</includes>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
|
||||||
|
</profile>
|
||||||
|
|
||||||
</profiles>
|
</profiles>
|
||||||
|
|
||||||
<reporting>
|
<reporting>
|
||||||
|
|
|
@ -1,32 +0,0 @@
|
||||||
package com.baeldung.manuallogout;
|
|
||||||
|
|
||||||
import org.springframework.security.core.context.SecurityContextHolder;
|
|
||||||
import org.springframework.stereotype.Controller;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMethod;
|
|
||||||
|
|
||||||
import javax.servlet.http.Cookie;
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
|
||||||
import javax.servlet.http.HttpSession;
|
|
||||||
|
|
||||||
@Controller
|
|
||||||
public class BasicAuthController {
|
|
||||||
|
|
||||||
@RequestMapping(value = {"/basiclogout"}, method = RequestMethod.POST)
|
|
||||||
public String logout(HttpServletRequest request, HttpServletResponse response) {
|
|
||||||
HttpSession session;
|
|
||||||
SecurityContextHolder.clearContext();
|
|
||||||
session = request.getSession(false);
|
|
||||||
if (session != null) {
|
|
||||||
session.invalidate();
|
|
||||||
}
|
|
||||||
for (Cookie cookie : request.getCookies()) {
|
|
||||||
String cookieName = cookie.getName();
|
|
||||||
Cookie cookieToDelete = new Cookie(cookieName, null);
|
|
||||||
cookieToDelete.setMaxAge(0);
|
|
||||||
response.addCookie(cookieToDelete);
|
|
||||||
}
|
|
||||||
return "redirect:/login?logout";
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,29 +0,0 @@
|
||||||
package com.baeldung.manuallogout;
|
|
||||||
|
|
||||||
import org.springframework.security.core.Authentication;
|
|
||||||
import org.springframework.security.core.context.SecurityContextHolder;
|
|
||||||
import org.springframework.security.web.authentication.logout.HeaderWriterLogoutHandler;
|
|
||||||
import org.springframework.security.web.header.writers.ClearSiteDataHeaderWriter;
|
|
||||||
import org.springframework.security.web.header.writers.ClearSiteDataHeaderWriter.Directive;
|
|
||||||
import org.springframework.stereotype.Controller;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMethod;
|
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
|
||||||
|
|
||||||
@Controller
|
|
||||||
public class ClearSiteDataController {
|
|
||||||
|
|
||||||
Directive[] SOURCE = {Directive.COOKIES, Directive.STORAGE, Directive.EXECUTION_CONTEXTS, Directive.CACHE};
|
|
||||||
|
|
||||||
@RequestMapping(value = {"/csdlogout"}, method = RequestMethod.POST)
|
|
||||||
public String logout(HttpServletRequest request, HttpServletResponse response) {
|
|
||||||
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
|
|
||||||
if (auth != null) {
|
|
||||||
ClearSiteDataHeaderWriter csdHeaderWriter = new ClearSiteDataHeaderWriter(SOURCE);
|
|
||||||
new HeaderWriterLogoutHandler(csdHeaderWriter).logout(request, response, auth);
|
|
||||||
}
|
|
||||||
return "redirect:/login?logout";
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,39 +1,80 @@
|
||||||
package com.baeldung.manuallogout;
|
package com.baeldung.manuallogout;
|
||||||
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.core.annotation.Order;
|
||||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||||
|
import org.springframework.security.web.authentication.logout.CookieClearingLogoutHandler;
|
||||||
|
import org.springframework.security.web.authentication.logout.HeaderWriterLogoutHandler;
|
||||||
|
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
|
||||||
|
import org.springframework.security.web.authentication.rememberme.AbstractRememberMeServices;
|
||||||
|
import org.springframework.security.web.header.writers.ClearSiteDataHeaderWriter;
|
||||||
|
|
||||||
|
import javax.servlet.http.Cookie;
|
||||||
|
|
||||||
|
import static org.springframework.security.web.header.writers.ClearSiteDataHeaderWriter.Directive.*;
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
@EnableWebSecurity
|
@EnableWebSecurity
|
||||||
public class SimpleSecurityConfiguration extends WebSecurityConfigurerAdapter {
|
public class SimpleSecurityConfiguration {
|
||||||
|
|
||||||
@Override
|
@Order(3)
|
||||||
protected void configure(HttpSecurity http) throws Exception {
|
@Configuration
|
||||||
http.formLogin()
|
public static class DefaultLogoutConfiguration extends WebSecurityConfigurerAdapter {
|
||||||
.loginProcessingUrl("/login")
|
@Override
|
||||||
.loginPage("/login")
|
protected void configure(HttpSecurity http) throws Exception {
|
||||||
.usernameParameter("username")
|
http
|
||||||
.passwordParameter("password")
|
.antMatcher("/basic/**")
|
||||||
.defaultSuccessUrl("/")
|
.authorizeRequests(authz -> authz.anyRequest().permitAll())
|
||||||
.failureUrl("/login?error");
|
.logout(logout -> logout
|
||||||
|
.logoutUrl("/basic/basiclogout")
|
||||||
|
.addLogoutHandler(new SecurityContextLogoutHandler())
|
||||||
|
.addLogoutHandler(new CookieClearingLogoutHandler(AbstractRememberMeServices.SPRING_SECURITY_REMEMBER_ME_COOKIE_KEY))
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Order(2)
|
||||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
@Configuration
|
||||||
auth.inMemoryAuthentication()
|
public static class AllCookieClearingLogoutConfiguration extends WebSecurityConfigurerAdapter {
|
||||||
.withUser("user")
|
@Override
|
||||||
.password("password")
|
protected void configure(HttpSecurity http) throws Exception {
|
||||||
.roles("USER")
|
http
|
||||||
.and()
|
.antMatcher("/cookies/**")
|
||||||
.withUser("manager")
|
.authorizeRequests(authz -> authz.anyRequest().permitAll())
|
||||||
.password("password")
|
.logout(logout -> logout
|
||||||
.credentialsExpired(true)
|
.logoutUrl("/cookies/cookielogout")
|
||||||
.accountExpired(true)
|
.addLogoutHandler(new SecurityContextLogoutHandler())
|
||||||
.accountLocked(true)
|
.addLogoutHandler((request, response, auth) -> {
|
||||||
.authorities("WRITE_PRIVILEGES", "READ_PRIVILEGES")
|
for (Cookie cookie : request.getCookies()) {
|
||||||
.roles("MANAGER");
|
String cookieName = cookie.getName();
|
||||||
|
Cookie cookieToDelete = new Cookie(cookieName, null);
|
||||||
|
cookieToDelete.setMaxAge(0);
|
||||||
|
response.addCookie(cookieToDelete);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Order(1)
|
||||||
|
@Configuration
|
||||||
|
public static class ClearSiteDataHeaderLogoutConfiguration extends WebSecurityConfigurerAdapter {
|
||||||
|
|
||||||
|
private static final ClearSiteDataHeaderWriter.Directive[] SOURCE =
|
||||||
|
{ CACHE, COOKIES, STORAGE, EXECUTION_CONTEXTS };
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void configure(HttpSecurity http) throws Exception {
|
||||||
|
http
|
||||||
|
.antMatcher("/csd/**")
|
||||||
|
.authorizeRequests(authz -> authz.anyRequest().permitAll())
|
||||||
|
.logout(logout -> logout
|
||||||
|
.logoutUrl("/csd/csdlogout")
|
||||||
|
.addLogoutHandler(new HeaderWriterLogoutHandler(new ClearSiteDataHeaderWriter(SOURCE)))
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
|
||||||
import org.springframework.mock.web.MockHttpServletRequest;
|
import org.springframework.mock.web.MockHttpServletRequest;
|
||||||
import org.springframework.mock.web.MockHttpSession;
|
import org.springframework.mock.web.MockHttpSession;
|
||||||
import org.springframework.security.test.context.support.WithMockUser;
|
import org.springframework.security.test.context.support.WithMockUser;
|
||||||
|
import org.springframework.security.web.authentication.rememberme.AbstractRememberMeServices;
|
||||||
import org.springframework.test.context.junit4.SpringRunner;
|
import org.springframework.test.context.junit4.SpringRunner;
|
||||||
import org.springframework.test.web.servlet.MockMvc;
|
import org.springframework.test.web.servlet.MockMvc;
|
||||||
|
|
||||||
|
@ -36,7 +37,22 @@ public class ManualLogoutIntegrationTest {
|
||||||
|
|
||||||
@WithMockUser(value = "spring")
|
@WithMockUser(value = "spring")
|
||||||
@Test
|
@Test
|
||||||
public void givenLoggedUserWhenUserLogoutThenSessionCleared() throws Exception {
|
public void givenLoggedUserWhenUserLogoutThenSessionClearedAndNecessaryCookieCleared() throws Exception {
|
||||||
|
|
||||||
|
MockHttpServletRequest requestStateAfterLogout = this.mockMvc.perform(post("/basic/basiclogout").secure(true).with(csrf()))
|
||||||
|
.andExpect(status().is3xxRedirection())
|
||||||
|
.andExpect(unauthenticated())
|
||||||
|
.andExpect(cookie().maxAge(AbstractRememberMeServices.SPRING_SECURITY_REMEMBER_ME_COOKIE_KEY, 0))
|
||||||
|
.andReturn()
|
||||||
|
.getRequest();
|
||||||
|
|
||||||
|
HttpSession sessionStateAfterLogout = requestStateAfterLogout.getSession();
|
||||||
|
assertNull(sessionStateAfterLogout.getAttribute(ATTRIBUTE_NAME));
|
||||||
|
}
|
||||||
|
|
||||||
|
@WithMockUser(value = "spring")
|
||||||
|
@Test
|
||||||
|
public void givenLoggedUserWhenUserLogoutThenSessionClearedAndAllCookiesCleared() throws Exception {
|
||||||
|
|
||||||
MockHttpSession session = new MockHttpSession();
|
MockHttpSession session = new MockHttpSession();
|
||||||
session.setAttribute(ATTRIBUTE_NAME, ATTRIBUTE_VALUE);
|
session.setAttribute(ATTRIBUTE_NAME, ATTRIBUTE_VALUE);
|
||||||
|
@ -44,7 +60,7 @@ public class ManualLogoutIntegrationTest {
|
||||||
Cookie randomCookie = new Cookie(COOKIE_NAME, COOKIE_VALUE);
|
Cookie randomCookie = new Cookie(COOKIE_NAME, COOKIE_VALUE);
|
||||||
randomCookie.setMaxAge(EXPIRY); // 10 minutes
|
randomCookie.setMaxAge(EXPIRY); // 10 minutes
|
||||||
|
|
||||||
MockHttpServletRequest requestStateAfterLogout = this.mockMvc.perform(post("/basiclogout").secure(true).with(csrf()).session(session).cookie(randomCookie))
|
MockHttpServletRequest requestStateAfterLogout = this.mockMvc.perform(post("/cookies/cookielogout").secure(true).with(csrf()).session(session).cookie(randomCookie))
|
||||||
.andExpect(status().is3xxRedirection())
|
.andExpect(status().is3xxRedirection())
|
||||||
.andExpect(unauthenticated())
|
.andExpect(unauthenticated())
|
||||||
.andExpect(cookie().maxAge(COOKIE_NAME, 0))
|
.andExpect(cookie().maxAge(COOKIE_NAME, 0))
|
||||||
|
@ -53,15 +69,13 @@ public class ManualLogoutIntegrationTest {
|
||||||
|
|
||||||
HttpSession sessionStateAfterLogout = requestStateAfterLogout.getSession();
|
HttpSession sessionStateAfterLogout = requestStateAfterLogout.getSession();
|
||||||
assertNull(sessionStateAfterLogout.getAttribute(ATTRIBUTE_NAME));
|
assertNull(sessionStateAfterLogout.getAttribute(ATTRIBUTE_NAME));
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@WithMockUser(value = "spring")
|
@WithMockUser(value = "spring")
|
||||||
@Test
|
@Test
|
||||||
public void givenLoggedUserWhenUserLogoutThenClearDataSiteHeaderPresent() throws Exception {
|
public void givenLoggedUserWhenUserLogoutThenClearDataSiteHeaderPresent() throws Exception {
|
||||||
|
|
||||||
this.mockMvc.perform(post("/csdlogout").secure(true).with(csrf()))
|
this.mockMvc.perform(post("/csd/csdlogout").secure(true).with(csrf()))
|
||||||
.andDo(print())
|
.andDo(print())
|
||||||
.andExpect(status().is3xxRedirection())
|
.andExpect(status().is3xxRedirection())
|
||||||
.andExpect(header().exists(CLEAR_SITE_DATA_HEADER))
|
.andExpect(header().exists(CLEAR_SITE_DATA_HEADER))
|
||||||
|
|
|
@ -63,7 +63,7 @@
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
<spring-boot.version>1.5.2.RELEASE</spring-boot.version>
|
<spring-boot.version>2.2.6.RELEASE</spring-boot.version>
|
||||||
<greeter.version>0.0.1-SNAPSHOT</greeter.version>
|
<greeter.version>0.0.1-SNAPSHOT</greeter.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
|
|
|
@ -51,7 +51,7 @@
|
||||||
<properties>
|
<properties>
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
<greeter.version>0.0.1-SNAPSHOT</greeter.version>
|
<greeter.version>0.0.1-SNAPSHOT</greeter.version>
|
||||||
<spring-boot.version>1.5.2.RELEASE</spring-boot.version>
|
<spring-boot.version>2.2.6.RELEASE</spring-boot.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
</project>
|
</project>
|
|
@ -24,6 +24,12 @@
|
||||||
<artifactId>spring-boot-starter-test</artifactId>
|
<artifactId>spring-boot-starter-test</artifactId>
|
||||||
<version>${spring-boot.version}</version>
|
<version>${spring-boot.version}</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>org.junit.vintage</groupId>
|
||||||
|
<artifactId>junit-vintage-engine</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
|
@ -72,7 +78,7 @@
|
||||||
</build>
|
</build>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<spring-boot.version>1.5.10.RELEASE</spring-boot.version>
|
<spring-boot.version>2.2.6.RELEASE</spring-boot.version>
|
||||||
<custom.property>Custom Property Value</custom.property>
|
<custom.property>Custom Property Value</custom.property>
|
||||||
<apache-maven.version>2.7</apache-maven.version>
|
<apache-maven.version>2.7</apache-maven.version>
|
||||||
<exec-maven-plugin.version>1.6.0</exec-maven-plugin.version>
|
<exec-maven-plugin.version>1.6.0</exec-maven-plugin.version>
|
||||||
|
|
|
@ -9,9 +9,9 @@
|
||||||
|
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>com.baeldung</groupId>
|
<groupId>com.baeldung</groupId>
|
||||||
<artifactId>parent-boot-1</artifactId>
|
<artifactId>parent-boot-2</artifactId>
|
||||||
<version>0.0.1-SNAPSHOT</version>
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
<relativePath>../../../parent-boot-1</relativePath>
|
<relativePath>../../../parent-boot-2</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
|
|
@ -2,66 +2,64 @@
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<artifactId>spring-caching</artifactId>
|
<artifactId>spring-caching</artifactId>
|
||||||
<version>0.1-SNAPSHOT</version>
|
<version>0.1-SNAPSHOT</version>
|
||||||
<name>spring-caching</name>
|
<name>spring-caching</name>
|
||||||
<packaging>war</packaging>
|
<packaging>war</packaging>
|
||||||
|
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>com.baeldung</groupId>
|
<groupId>com.baeldung</groupId>
|
||||||
<artifactId>parent-boot-2</artifactId>
|
<artifactId>parent-boot-2</artifactId>
|
||||||
<version>0.0.1-SNAPSHOT</version>
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
<relativePath>../parent-boot-2</relativePath>
|
<relativePath>../parent-boot-2</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<dependencies>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-starter-web</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework</groupId>
|
|
||||||
<artifactId>spring-context</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-starter-cache</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework</groupId>
|
|
||||||
<artifactId>spring-web</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework</groupId>
|
|
||||||
<artifactId>spring-webmvc</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.ehcache</groupId>
|
|
||||||
<artifactId>ehcache</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework</groupId>
|
|
||||||
<artifactId>spring-test</artifactId>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.github.ben-manes.caffeine</groupId>
|
|
||||||
<artifactId>caffeine</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.h2database</groupId>
|
|
||||||
<artifactId>h2</artifactId>
|
|
||||||
<scope>runtime</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-starter-jdbc</artifactId>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
|
||||||
|
|
||||||
<properties>
|
|
||||||
<ehcache.version>3.5.2</ehcache.version>
|
|
||||||
</properties>
|
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-web</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework</groupId>
|
||||||
|
<artifactId>spring-context</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-cache</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework</groupId>
|
||||||
|
<artifactId>spring-web</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework</groupId>
|
||||||
|
<artifactId>spring-webmvc</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.ehcache</groupId>
|
||||||
|
<artifactId>ehcache</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework</groupId>
|
||||||
|
<artifactId>spring-test</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.github.ben-manes.caffeine</groupId>
|
||||||
|
<artifactId>caffeine</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.h2database</groupId>
|
||||||
|
<artifactId>h2</artifactId>
|
||||||
|
<scope>runtime</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-jdbc</artifactId>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
<properties>
|
||||||
|
<ehcache.version>3.5.2</ehcache.version>
|
||||||
|
</properties>
|
||||||
</project>
|
</project>
|
|
@ -72,7 +72,7 @@ node {
|
||||||
if (isUnix()) {
|
if (isUnix()) {
|
||||||
sh 'nohup ./mvnw spring-boot:run -Dserver.port=8989 &'
|
sh 'nohup ./mvnw spring-boot:run -Dserver.port=8989 &'
|
||||||
} else {
|
} else {
|
||||||
bat 'start ./mvnw.cmd spring-boot:run -Dserver.port=8989'
|
bat 'start mvnw.cmd spring-boot:run -Dserver.port=8989'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
## Vavr
|
||||||
|
|
||||||
|
This module contains articles about Vavr.
|
||||||
|
|
||||||
|
### Relevant Articles:
|
||||||
|
- [Introduction to Vavr’s Either](https://www.baeldung.com/vavr-either)
|
||||||
|
- [Interoperability Between Java and Vavr](https://www.baeldung.com/java-vavr)
|
||||||
|
- [[<-- prev]](/vavr)
|
|
@ -0,0 +1,27 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<parent>
|
||||||
|
<artifactId>parent-modules</artifactId>
|
||||||
|
<groupId>com.baeldung</groupId>
|
||||||
|
<version>1.0.0-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<artifactId>vavr-2</artifactId>
|
||||||
|
<name>vavr-2</name>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.vavr</groupId>
|
||||||
|
<artifactId>vavr-test</artifactId>
|
||||||
|
<version>${vavr.version}</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<vavr.version>0.9.1</vavr.version>
|
||||||
|
</properties>
|
||||||
|
</project>
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue