commit
						56f7b49988
					
				| @ -1,4 +1,4 @@ | ||||
| package com.baeldung.java14.helpfulnullpointerexceptions; | ||||
| package com.baeldung.java14.npe; | ||||
| 
 | ||||
| public class HelpfulNullPointerException { | ||||
| 
 | ||||
| @ -1,4 +1,4 @@ | ||||
| package com.baeldung.java14.helpfulnullpointerexceptions; | ||||
| package com.baeldung.java14.npe; | ||||
| 
 | ||||
| import org.junit.Test; | ||||
| 
 | ||||
| @ -5,5 +5,5 @@ This module contains articles about sorting arrays in Java | ||||
| ### Relevant Articles:  | ||||
| - [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) | ||||
| - [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) | ||||
|  | ||||
| @ -4,4 +4,5 @@ | ||||
| 
 | ||||
| ### Relevant Articles:  | ||||
| - [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) | ||||
| 
 | ||||
|  | ||||
| @ -15,6 +15,38 @@ | ||||
|         <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> | ||||
|         <finalName>core-java-concurrency-2</finalName> | ||||
| @ -24,6 +56,51 @@ | ||||
|                 <filtering>true</filtering> | ||||
|             </resource> | ||||
|         </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> | ||||
|      | ||||
|     <properties> | ||||
|         <javac.target>1.8</javac.target> | ||||
|     </properties> | ||||
| 
 | ||||
| </project> | ||||
|  | ||||
| @ -1,5 +1,6 @@ | ||||
| package com.baeldung.concurrent; | ||||
| 
 | ||||
| import org.junit.Ignore; | ||||
| import org.junit.Test; | ||||
| 
 | ||||
| import edu.umd.cs.mtc.MultithreadedTestCase; | ||||
| @ -25,9 +26,10 @@ public class MyCounterMultithreadedTCUnitTest extends MultithreadedTestCase { | ||||
|     @SuppressWarnings("deprecation") | ||||
|     @Override | ||||
|     public void finish() { | ||||
|         assertEquals(2, counter.getCount()); | ||||
|     	assertEquals(2, counter.getCount()); | ||||
|     } | ||||
| 
 | ||||
|     @Ignore | ||||
|     @Test | ||||
|     public void testCounter() throws Throwable { | ||||
|         TestFramework.runManyTimes(new MyCounterMultithreadedTCUnitTest(), 1000); | ||||
| @ -6,6 +6,7 @@ import java.util.concurrent.CountDownLatch; | ||||
| import java.util.concurrent.ExecutorService; | ||||
| import java.util.concurrent.Executors; | ||||
| 
 | ||||
| import org.junit.Ignore; | ||||
| import org.junit.Test; | ||||
| 
 | ||||
| public class MyCounterSimpleUnitTest { | ||||
| @ -18,7 +19,8 @@ public class MyCounterSimpleUnitTest { | ||||
|         assertEquals(500, counter.getCount()); | ||||
|     } | ||||
| 
 | ||||
|     // @Test | ||||
|     @Ignore | ||||
|     @Test | ||||
|     public void testCounterWithConcurrency() throws InterruptedException { | ||||
|         int numberOfThreads = 100; | ||||
|         ExecutorService service = Executors.newFixedThreadPool(10); | ||||
| @ -34,7 +36,8 @@ public class MyCounterSimpleUnitTest { | ||||
|         assertEquals(numberOfThreads, counter.getCount()); | ||||
|     } | ||||
| 
 | ||||
|     // @Test | ||||
|     @Ignore | ||||
|     @Test | ||||
|     public void testSummationWithConcurrencyAndWait() throws InterruptedException { | ||||
|         int numberOfThreads = 2; | ||||
|         ExecutorService service = Executors.newFixedThreadPool(10); | ||||
| @ -3,6 +3,7 @@ package com.baeldung.concurrent; | ||||
| import static org.junit.Assert.assertEquals; | ||||
| 
 | ||||
| import org.junit.AfterClass; | ||||
| import org.junit.Ignore; | ||||
| import org.junit.Rule; | ||||
| import org.junit.Test; | ||||
| 
 | ||||
| @ -20,6 +21,7 @@ public class MyCounterTempusFugitUnitTest { | ||||
| 
 | ||||
|     private static MyCounter counter = new MyCounter(); | ||||
| 
 | ||||
|     @Ignore | ||||
|     @Test | ||||
|     @Concurrent(count = 2) | ||||
|     @Repeating(repetition = 10) | ||||
| @ -2,6 +2,7 @@ package com.baeldung.concurrent; | ||||
| 
 | ||||
| import static org.junit.Assert.assertEquals; | ||||
| 
 | ||||
| import org.junit.Ignore; | ||||
| import org.junit.Test; | ||||
| 
 | ||||
| import com.google.testing.threadtester.AnnotatedTestRunner; | ||||
| @ -34,6 +35,7 @@ public class MyCounterThreadWeaverUnitTest { | ||||
|         assertEquals(2, counter.getCount()); | ||||
|     } | ||||
| 
 | ||||
|     @Ignore | ||||
|     @Test | ||||
|     public void testCounter() { | ||||
|         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> | ||||
|             <scope>provided</scope> | ||||
|         </dependency> | ||||
|         <dependency> | ||||
|             <groupId>org.apache.commons</groupId> | ||||
|             <artifactId>commons-lang3</artifactId> | ||||
|             <version>${commons.lang3.version}</version> | ||||
|         </dependency> | ||||
|         <!-- test scoped --> | ||||
|         <dependency> | ||||
|             <groupId>org.assertj</groupId> | ||||
| @ -40,6 +45,7 @@ | ||||
| 
 | ||||
|     <properties> | ||||
|         <javax.mail.version>1.5.0-b01</javax.mail.version> | ||||
|         <commons.lang3.version>3.10</commons.lang3.version> | ||||
|         <!-- testing --> | ||||
|         <assertj-core.version>3.10.0</assertj-core.version> | ||||
|     </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 --> | ||||
|         <assertj.version>3.6.1</assertj.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> | ||||
|         <!-- plugins --> | ||||
|         <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> | ||||
|                     </executions> | ||||
|                     <configuration> | ||||
|                         <wsdlDirectory>src/main/resources</wsdlDirectory> | ||||
|                         <wsdlFiles> | ||||
|                             <wsdlFile>country.wsdl</wsdlFile>  | ||||
|                         </wsdlFiles> | ||||
|                         <wsdlUrls> | ||||
|                             <wsdlUrl>http://localhost:8888/ws/country?wsdl</wsdlUrl> | ||||
|                         </wsdlUrls> | ||||
|                         <keep>true</keep>  | ||||
|                         <packageName>com.baeldung.soap.ws.client.generated</packageName>  | ||||
|                         <sourceDestDir>src/main/java</sourceDestDir> | ||||
|  | ||||
| @ -12,11 +12,11 @@ import javax.xml.ws.WebServiceFeature; | ||||
| 
 | ||||
| /** | ||||
|  * 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 | ||||
|  *  | ||||
|  */ | ||||
| @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 { | ||||
| 
 | ||||
|     private final static URL COUNTRYSERVICEIMPLSERVICE_WSDL_LOCATION; | ||||
| @ -27,7 +27,7 @@ public class CountryServiceImplService extends Service { | ||||
|         URL url = null; | ||||
|         WebServiceException e = null; | ||||
|         try { | ||||
|             url = new URL("file:src/main/resources/country.wsdl"); | ||||
|             url = new URL("http://localhost:8888/ws/country?wsdl"); | ||||
|         } catch (MalformedURLException 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; | ||||
| 
 | ||||
| import static org.junit.jupiter.api.Assertions.*; | ||||
| import java.util.Map; | ||||
| import static org.junit.jupiter.api.Assertions.assertEquals; | ||||
| 
 | ||||
| import java.util.Properties; | ||||
| 
 | ||||
| import javax.batch.operations.JobOperator; | ||||
| import javax.batch.runtime.BatchRuntime; | ||||
| import javax.batch.runtime.BatchStatus; | ||||
| import javax.batch.runtime.JobExecution; | ||||
| import javax.batch.runtime.Metric; | ||||
| import javax.batch.runtime.StepExecution; | ||||
| import com.baeldung.batch.understanding.BatchTestHelper; | ||||
| 
 | ||||
| import org.junit.jupiter.api.Test; | ||||
| import org.junit.jupiter.api.Disabled; | ||||
| 
 | ||||
| @Disabled("Should be fixed in BAEL-3812") | ||||
| class CustomCheckPointUnitTest { | ||||
|     @Test | ||||
|     public void givenChunk_whenCustomCheckPoint_thenCommitCountIsThree() throws Exception { | ||||
|  | ||||
| @ -1,6 +1,8 @@ | ||||
| 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.List; | ||||
| @ -13,9 +15,7 @@ import javax.batch.runtime.JobExecution; | ||||
| import javax.batch.runtime.StepExecution; | ||||
| 
 | ||||
| import org.junit.jupiter.api.Test; | ||||
| import org.junit.jupiter.api.Disabled; | ||||
| 
 | ||||
| @Disabled("Should be fixed in BAEL-3812") | ||||
| class JobSequenceUnitTest { | ||||
|     @Test | ||||
|     public void givenTwoSteps_thenBatch_CompleteWithSuccess() throws Exception { | ||||
|  | ||||
| @ -1,17 +1,16 @@ | ||||
| package com.baeldung.batch.understanding; | ||||
| 
 | ||||
| import org.junit.jupiter.api.Disabled; | ||||
| import org.junit.jupiter.api.Test; | ||||
| import static org.junit.jupiter.api.Assertions.assertEquals; | ||||
| 
 | ||||
| import java.util.Properties; | ||||
| 
 | ||||
| import javax.batch.operations.JobOperator; | ||||
| import javax.batch.runtime.BatchRuntime; | ||||
| import javax.batch.runtime.BatchStatus; | ||||
| 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 { | ||||
|     @Test | ||||
|     public void givenBatchLet_thenBatch_CompleteWithSuccess() throws Exception { | ||||
|  | ||||
| @ -1,6 +1,7 @@ | ||||
| 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.Map; | ||||
| @ -14,9 +15,7 @@ import javax.batch.runtime.Metric; | ||||
| import javax.batch.runtime.StepExecution; | ||||
| 
 | ||||
| import org.junit.jupiter.api.Test; | ||||
| import org.junit.jupiter.api.Disabled; | ||||
| 
 | ||||
| @Disabled("Should be fixed in BAEL-3812") | ||||
| class SimpleChunkUnitTest { | ||||
|     @Test | ||||
|     public void givenChunk_thenBatch_CompletesWithSucess() throws Exception { | ||||
|  | ||||
| @ -1,19 +1,18 @@ | ||||
| package com.baeldung.batch.understanding; | ||||
| 
 | ||||
| import org.junit.jupiter.api.Disabled; | ||||
| import org.junit.jupiter.api.Test; | ||||
| import static org.junit.Assert.assertEquals; | ||||
| 
 | ||||
| import java.util.List; | ||||
| import java.util.Properties; | ||||
| 
 | ||||
| import javax.batch.operations.JobOperator; | ||||
| import javax.batch.runtime.BatchRuntime; | ||||
| import javax.batch.runtime.BatchStatus; | ||||
| import javax.batch.runtime.JobExecution; | ||||
| 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 { | ||||
| 
 | ||||
|     @Test | ||||
|  | ||||
							
								
								
									
										1
									
								
								jee-7/src/test/resources/jberet.properties
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								jee-7/src/test/resources/jberet.properties
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1 @@ | ||||
| db-url=jdbc:h2:mem:jberet-repo;DB_CLOSE_DELAY=-1 | ||||
| @ -1013,7 +1013,7 @@ | ||||
| 	 | ||||
|     <properties> | ||||
|         <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 --> | ||||
|         <maven.version>3.0.0</maven.version> | ||||
|         <java.version>1.8</java.version> | ||||
|  | ||||
| @ -910,6 +910,6 @@ | ||||
|         <sonar.tests>${project.basedir}/src/test/</sonar.tests> | ||||
| 
 | ||||
|         <!-- jhipster-needle-maven-property --> | ||||
|         <zalando.version>0.24.0-RC.0</zalando.version> | ||||
|         <zalando.version>0.24.0</zalando.version> | ||||
|     </properties>	 | ||||
| </project> | ||||
|  | ||||
| @ -835,7 +835,7 @@ | ||||
| 	 | ||||
|     <properties> | ||||
|         <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 --> | ||||
|         <maven.version>3.0.0</maven.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"), | ||||
| 			@Result(property = "streetAddress", column = "streetAddress"), | ||||
| 			@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})") | ||||
| 	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()); | ||||
|     }*/ | ||||
| } | ||||
							
								
								
									
										23
									
								
								patterns/solid/src/main/java/com/baeldung/s/TextPrinter.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								patterns/solid/src/main/java/com/baeldung/s/TextPrinter.java
									
									
									
									
									
										Normal file
									
								
							| @ -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> | ||||
|             <scope>runtime</scope> | ||||
|         </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> | ||||
|             <groupId>org.assertj</groupId> | ||||
| @ -101,23 +112,41 @@ | ||||
|                         <configuration> | ||||
|                             <sources> | ||||
|                                 <source>target/metamodel</source> | ||||
|                                 <source>${project.build.directory}/generated-sources/java/</source> | ||||
|                             </sources> | ||||
|                         </configuration> | ||||
|                     </execution> | ||||
|                 </executions> | ||||
|             </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> | ||||
|     </build> | ||||
| 
 | ||||
|     <properties> | ||||
|         <hibernate.version>5.4.0.Final</hibernate.version> | ||||
|         <eclipselink.version>2.7.4-RC1</eclipselink.version> | ||||
|         <hibernate.version>5.4.14.Final</hibernate.version> | ||||
|         <eclipselink.version>2.7.4</eclipselink.version> | ||||
|         <postgres.version>42.2.5</postgres.version> | ||||
|         <javax.persistence-api.version>2.2</javax.persistence-api.version> | ||||
|         <assertj.version>3.11.1</assertj.version> | ||||
|         <maven-compiler-plugin.version>3.5.1</maven-compiler-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> | ||||
|         <querydsl.version>4.3.1</querydsl.version> | ||||
|     </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); | ||||
|     } | ||||
| } | ||||
| @ -162,5 +162,26 @@ | ||||
|                       value="false" /> | ||||
|         </properties> | ||||
|     </persistence-unit> | ||||
| 
 | ||||
| </persistence> | ||||
|      | ||||
|     <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> | ||||
|  | ||||
| @ -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> | ||||
|         <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> | ||||
|         <javax.persistence-api.version>2.2</javax.persistence-api.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 MongoDB Transactions](https://www.baeldung.com/spring-data-mongodb-transactions ) | ||||
| - [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 | ||||
| 
 | ||||
|     @Test | ||||
|  | ||||
							
								
								
									
										32
									
								
								pom.xml
									
									
									
									
									
								
							
							
						
						
									
										32
									
								
								pom.xml
									
									
									
									
									
								
							| @ -814,6 +814,7 @@ | ||||
| 
 | ||||
|                 <module>vaadin</module> | ||||
|                 <module>vavr</module> | ||||
|                 <module>vavr-2</module> | ||||
|             </modules> | ||||
|         </profile> | ||||
| 
 | ||||
| @ -1313,10 +1314,41 @@ | ||||
| 
 | ||||
|                 <module>vaadin</module> | ||||
|                 <module>vavr</module> | ||||
|                 <module>vavr-2</module> | ||||
|             </modules> | ||||
| 
 | ||||
|         </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> | ||||
| 
 | ||||
|     <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; | ||||
| 
 | ||||
| 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.web.builders.HttpSecurity; | ||||
| import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; | ||||
| 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 | ||||
| @EnableWebSecurity | ||||
| public class SimpleSecurityConfiguration extends WebSecurityConfigurerAdapter { | ||||
| public class SimpleSecurityConfiguration { | ||||
| 
 | ||||
|     @Override | ||||
|     protected void configure(HttpSecurity http) throws Exception { | ||||
|         http.formLogin() | ||||
|                 .loginProcessingUrl("/login") | ||||
|                 .loginPage("/login") | ||||
|                 .usernameParameter("username") | ||||
|                 .passwordParameter("password") | ||||
|                 .defaultSuccessUrl("/") | ||||
|                 .failureUrl("/login?error"); | ||||
|     @Order(3) | ||||
|     @Configuration | ||||
|     public static class DefaultLogoutConfiguration extends WebSecurityConfigurerAdapter { | ||||
|         @Override | ||||
|         protected void configure(HttpSecurity http) throws Exception { | ||||
|             http | ||||
|                     .antMatcher("/basic/**") | ||||
|                     .authorizeRequests(authz -> authz.anyRequest().permitAll()) | ||||
|                     .logout(logout -> logout | ||||
|                             .logoutUrl("/basic/basiclogout") | ||||
|                             .addLogoutHandler(new SecurityContextLogoutHandler()) | ||||
|                             .addLogoutHandler(new CookieClearingLogoutHandler(AbstractRememberMeServices.SPRING_SECURITY_REMEMBER_ME_COOKIE_KEY)) | ||||
|                     ); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     protected void configure(AuthenticationManagerBuilder auth) throws Exception { | ||||
|         auth.inMemoryAuthentication() | ||||
|                 .withUser("user") | ||||
|                 .password("password") | ||||
|                 .roles("USER") | ||||
|                 .and() | ||||
|                 .withUser("manager") | ||||
|                 .password("password") | ||||
|                 .credentialsExpired(true) | ||||
|                 .accountExpired(true) | ||||
|                 .accountLocked(true) | ||||
|                 .authorities("WRITE_PRIVILEGES", "READ_PRIVILEGES") | ||||
|                 .roles("MANAGER"); | ||||
|     @Order(2) | ||||
|     @Configuration | ||||
|     public static class AllCookieClearingLogoutConfiguration extends WebSecurityConfigurerAdapter { | ||||
|         @Override | ||||
|         protected void configure(HttpSecurity http) throws Exception { | ||||
|             http | ||||
|                     .antMatcher("/cookies/**") | ||||
|                     .authorizeRequests(authz -> authz.anyRequest().permitAll()) | ||||
|                     .logout(logout -> logout | ||||
|                             .logoutUrl("/cookies/cookielogout") | ||||
|                             .addLogoutHandler(new SecurityContextLogoutHandler()) | ||||
|                             .addLogoutHandler((request, response, auth) -> { | ||||
|                                         for (Cookie cookie : request.getCookies()) { | ||||
|                                             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.MockHttpSession; | ||||
| 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.web.servlet.MockMvc; | ||||
| 
 | ||||
| @ -36,7 +37,22 @@ public class ManualLogoutIntegrationTest { | ||||
| 
 | ||||
|     @WithMockUser(value = "spring") | ||||
|     @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(); | ||||
|         session.setAttribute(ATTRIBUTE_NAME, ATTRIBUTE_VALUE); | ||||
| @ -44,7 +60,7 @@ public class ManualLogoutIntegrationTest { | ||||
|         Cookie randomCookie = new Cookie(COOKIE_NAME, COOKIE_VALUE); | ||||
|         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(unauthenticated()) | ||||
|                 .andExpect(cookie().maxAge(COOKIE_NAME, 0)) | ||||
| @ -53,15 +69,13 @@ public class ManualLogoutIntegrationTest { | ||||
| 
 | ||||
|         HttpSession sessionStateAfterLogout = requestStateAfterLogout.getSession(); | ||||
|         assertNull(sessionStateAfterLogout.getAttribute(ATTRIBUTE_NAME)); | ||||
| 
 | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     @WithMockUser(value = "spring") | ||||
|     @Test | ||||
|     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()) | ||||
|                 .andExpect(status().is3xxRedirection()) | ||||
|                 .andExpect(header().exists(CLEAR_SITE_DATA_HEADER)) | ||||
|  | ||||
| @ -63,7 +63,7 @@ | ||||
| 
 | ||||
|     <properties> | ||||
|         <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> | ||||
|     </properties> | ||||
| 
 | ||||
|  | ||||
| @ -51,7 +51,7 @@ | ||||
|     <properties> | ||||
|         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> | ||||
|         <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> | ||||
| 
 | ||||
| </project> | ||||
| @ -24,6 +24,12 @@ | ||||
|             <artifactId>spring-boot-starter-test</artifactId> | ||||
|             <version>${spring-boot.version}</version> | ||||
|             <scope>test</scope> | ||||
|             <exclusions> | ||||
|                 <exclusion> | ||||
|                     <groupId>org.junit.vintage</groupId> | ||||
|                     <artifactId>junit-vintage-engine</artifactId> | ||||
|                 </exclusion> | ||||
|             </exclusions> | ||||
|         </dependency> | ||||
|     </dependencies> | ||||
| 
 | ||||
| @ -72,7 +78,7 @@ | ||||
|     </build> | ||||
| 
 | ||||
|     <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> | ||||
|         <apache-maven.version>2.7</apache-maven.version> | ||||
|         <exec-maven-plugin.version>1.6.0</exec-maven-plugin.version> | ||||
|  | ||||
| @ -9,9 +9,9 @@ | ||||
| 
 | ||||
|     <parent> | ||||
|         <groupId>com.baeldung</groupId> | ||||
|         <artifactId>parent-boot-1</artifactId> | ||||
|         <artifactId>parent-boot-2</artifactId> | ||||
|         <version>0.0.1-SNAPSHOT</version> | ||||
|         <relativePath>../../../parent-boot-1</relativePath> | ||||
|         <relativePath>../../../parent-boot-2</relativePath> | ||||
|     </parent> | ||||
| 
 | ||||
|     <dependencies> | ||||
|  | ||||
| @ -2,66 +2,64 @@ | ||||
| <project xmlns="http://maven.apache.org/POM/4.0.0" | ||||
| 	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||||
| 	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||||
| 	<modelVersion>4.0.0</modelVersion> | ||||
| 	<artifactId>spring-caching</artifactId> | ||||
| 	<version>0.1-SNAPSHOT</version> | ||||
| 	<name>spring-caching</name> | ||||
| 	<packaging>war</packaging> | ||||
|     <modelVersion>4.0.0</modelVersion> | ||||
|     <artifactId>spring-caching</artifactId> | ||||
|     <version>0.1-SNAPSHOT</version> | ||||
|     <name>spring-caching</name> | ||||
|     <packaging>war</packaging> | ||||
| 
 | ||||
| 	<parent> | ||||
| 		<groupId>com.baeldung</groupId> | ||||
| 		<artifactId>parent-boot-2</artifactId> | ||||
| 		<version>0.0.1-SNAPSHOT</version> | ||||
| 		<relativePath>../parent-boot-2</relativePath> | ||||
| 	</parent> | ||||
|     <parent> | ||||
|         <groupId>com.baeldung</groupId> | ||||
|         <artifactId>parent-boot-2</artifactId> | ||||
|         <version>0.0.1-SNAPSHOT</version> | ||||
|         <relativePath>../parent-boot-2</relativePath> | ||||
|     </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> | ||||
| 
 | ||||
| </project> | ||||
|     <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> | ||||
|  | ||||
| @ -72,7 +72,7 @@ node { | ||||
|                     if (isUnix()) { | ||||
|                         sh 'nohup ./mvnw spring-boot:run -Dserver.port=8989 &' | ||||
|                     } else { | ||||
|                         bat 'start ./mvnw.cmd spring-boot:run -Dserver.port=8989' | ||||
|                         bat 'start mvnw.cmd spring-boot:run -Dserver.port=8989' | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|  | ||||
							
								
								
									
										8
									
								
								vavr-2/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								vavr-2/README.md
									
									
									
									
									
										Normal file
									
								
							| @ -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) | ||||
							
								
								
									
										27
									
								
								vavr-2/pom.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								vavr-2/pom.xml
									
									
									
									
									
										Normal file
									
								
							| @ -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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user