Merge branch 'eugenmaster'
This commit is contained in:
		
						commit
						352e7ca9db
					
				| @ -1,4 +1,4 @@ | ||||
| ### Relevant Articles: | ||||
| 
 | ||||
| - [Deploy Spring Boot App to Azure](http://www.baeldung.com/spring-boot-azure) | ||||
| - [Deploy a Spring Boot App to Azure](http://www.baeldung.com/spring-boot-azure) | ||||
| 
 | ||||
|  | ||||
| @ -1,5 +1,5 @@ | ||||
| ### Relevant Articles:  | ||||
| 
 | ||||
| - [Blade - A Complete GuideBook](http://www.baeldung.com/blade)  | ||||
| - [Blade – A Complete Guidebook](http://www.baeldung.com/blade)  | ||||
| 
 | ||||
| Run Integration Tests with `mvn integration-test` | ||||
| Run Integration Tests with `mvn integration-test` | ||||
|  | ||||
| @ -8,6 +8,8 @@ | ||||
| - [Types of Strings in Groovy](https://www.baeldung.com/groovy-strings) | ||||
| - [A Quick Guide to Iterating a Map in Groovy](https://www.baeldung.com/groovy-map-iterating) | ||||
| - [An Introduction to Traits in Groovy](https://www.baeldung.com/groovy-traits) | ||||
| - [Closures in Groovy](https://www.baeldung.com/groovy-closures) | ||||
| - [Finding Elements in Collections in Groovy](https://www.baeldung.com/groovy-collections-find-elements) | ||||
| - [Lists in Groovy](https://www.baeldung.com/groovy-lists) | ||||
| - [Converting a String to a Date in Groovy](https://www.baeldung.com/groovy-string-to-date) | ||||
| - [Guide to I/O in Groovy](https://www.baeldung.com/groovy-io) | ||||
| - [Guide to I/O in Groovy](https://www.baeldung.com/groovy-io) | ||||
| @ -0,0 +1,44 @@ | ||||
| package com.baeldung.strings | ||||
| 
 | ||||
| import spock.lang.Specification | ||||
| 
 | ||||
| import java.util.regex.Pattern | ||||
| 
 | ||||
| class StringMatchingSpec extends Specification { | ||||
| 
 | ||||
|     def "pattern operator example"() { | ||||
|         given: "a pattern" | ||||
|         def p = ~'foo' | ||||
| 
 | ||||
|         expect: | ||||
|         p instanceof Pattern | ||||
| 
 | ||||
|         and: "you can use slash strings to avoid escaping of blackslash" | ||||
|         def digitPattern = ~/\d*/ | ||||
|         digitPattern.matcher('4711').matches() | ||||
|     } | ||||
| 
 | ||||
|     def "match operator example"() { | ||||
|         expect: | ||||
|         'foobar' ==~ /.*oba.*/ | ||||
| 
 | ||||
|         and: "matching is strict" | ||||
|         !('foobar' ==~ /foo/) | ||||
|     } | ||||
| 
 | ||||
|     def "find operator example"() { | ||||
|         when: "using the find operator" | ||||
|         def matcher = 'foo and bar, baz and buz' =~ /(\w+) and (\w+)/ | ||||
| 
 | ||||
|         then: "will find groups" | ||||
|         matcher.size() == 2 | ||||
| 
 | ||||
|         and: "can access groups using array" | ||||
|         matcher[0][0] == 'foo and bar' | ||||
|         matcher[1][2] == 'buz' | ||||
| 
 | ||||
|         and: "you can use it as a predicate" | ||||
|         'foobarbaz' =~ /bar/ | ||||
|     } | ||||
| 
 | ||||
| } | ||||
| @ -6,3 +6,4 @@ | ||||
| - [Java 11 Nest Based Access Control](https://www.baeldung.com/java-nest-based-access-control) | ||||
| - [Exploring the New HTTP Client in Java 9 and 11](https://www.baeldung.com/java-9-http-client) | ||||
| - [An Introduction to Epsilon GC: A No-Op Experimental Garbage Collector](https://www.baeldung.com/jvm-epsilon-gc-garbage-collector) | ||||
| - [Guide to jlink](https://www.baeldung.com/jlink) | ||||
|  | ||||
| @ -3,7 +3,7 @@ | ||||
| ## Core Java 8 Cookbooks and Examples | ||||
| 
 | ||||
| ### Relevant Articles:  | ||||
| - [Java 8 Collectors](http://www.baeldung.com/java-8-collectors) | ||||
| - [Guide to Java 8’s Collectors](http://www.baeldung.com/java-8-collectors) | ||||
| - [Functional Interfaces in Java 8](http://www.baeldung.com/java-8-functional-interfaces) | ||||
| - [Java 8 – Powerful Comparison with Lambdas](http://www.baeldung.com/java-8-sort-lambda) | ||||
| - [New Features in Java 8](http://www.baeldung.com/java-8-new-features) | ||||
|  | ||||
| @ -5,26 +5,21 @@ | ||||
| [Java 9 New Features](http://www.baeldung.com/new-java-9) | ||||
| 
 | ||||
| ### Relevant Articles: | ||||
| - [Java 9 Stream API Improvements](http://www.baeldung.com/java-9-stream-api) | ||||
| - [Java 9 Convenience Factory Methods for Collections](http://www.baeldung.com/java-9-collections-factory-methods)  | ||||
| 
 | ||||
| - [Java 9 New Features](https://www.baeldung.com/new-java-9) | ||||
| - [New Stream Collectors in Java 9](http://www.baeldung.com/java9-stream-collectors) | ||||
| - [Java 9 CompletableFuture API Improvements](http://www.baeldung.com/java-9-completablefuture) | ||||
| - [Introduction to Java 9 StackWalking API](http://www.baeldung.com/java-9-stackwalking-api) | ||||
| - [Introduction to Project Jigsaw](http://www.baeldung.com/project-jigsaw-java-modularity) | ||||
| - [Java 9 Optional API Additions](http://www.baeldung.com/java-9-optional) | ||||
| - [Java 9 Reactive Streams](http://www.baeldung.com/java-9-reactive-streams) | ||||
| - [Java 9 java.util.Objects Additions](http://www.baeldung.com/java-9-objects-new) | ||||
| - [Java 9 Variable Handles Demistyfied](http://www.baeldung.com/java-variable-handles) | ||||
| - [Java 9 Variable Handles Demystified](http://www.baeldung.com/java-variable-handles) | ||||
| - [Exploring the New HTTP Client in Java 9 and 11](http://www.baeldung.com/java-9-http-client) | ||||
| - [Method Handles in Java](http://www.baeldung.com/java-method-handles) | ||||
| - [Introduction to Chronicle Queue](http://www.baeldung.com/java-chronicle-queue) | ||||
| - [A Guide to Java 9 Modularity](http://www.baeldung.com/java-9-modularity) | ||||
| - [Optional orElse Optional](http://www.baeldung.com/java-optional-or-else-optional) | ||||
| - [Java 9 java.lang.Module API](http://www.baeldung.com/java-9-module-api) | ||||
| - [Iterate Through a Range of Dates in Java](https://www.baeldung.com/java-iterate-date-range) | ||||
| - [Initialize a HashMap in Java](https://www.baeldung.com/java-initialize-hashmap) | ||||
| - [Java 9 Platform Logging API](https://www.baeldung.com/java-9-logging-api) | ||||
| - [Immutable Set in Java](https://www.baeldung.com/java-immutable-set) | ||||
| - [Multi-Release Jar Files](https://www.baeldung.com/java-multi-release-jar) | ||||
| - [Ahead of Time Compilation (AoT)](https://www.baeldung.com/ahead-of-time-compilation) | ||||
| - [Java 9 Process API Improvements](https://www.baeldung.com/java-9-process-api) | ||||
| - [Guide to java.lang.Process API](https://www.baeldung.com/java-process-api) | ||||
| 
 | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										6
									
								
								core-java-collections-map/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								core-java-collections-map/README.md
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,6 @@ | ||||
| ========= | ||||
| 
 | ||||
| ## Core Java Collections 2 | ||||
| 
 | ||||
| ### Relevant Articles:  | ||||
| - Java - Copying a HashMap | ||||
							
								
								
									
										78
									
								
								core-java-collections-map/pom.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								core-java-collections-map/pom.xml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,78 @@ | ||||
| <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-collections-map</artifactId> | ||||
|     <version>0.1.0-SNAPSHOT</version> | ||||
|     <name>core-java-collections-map</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>org.apache.commons</groupId> | ||||
|             <artifactId>commons-collections4</artifactId> | ||||
|             <version>${commons-collections4.version}</version> | ||||
|         </dependency> | ||||
|         <dependency> | ||||
|             <groupId>org.apache.commons</groupId> | ||||
|             <artifactId>commons-lang3</artifactId> | ||||
|             <version>${commons-lang3.version}</version> | ||||
|         </dependency> | ||||
|         <dependency> | ||||
|             <groupId>org.eclipse.collections</groupId> | ||||
|             <artifactId>eclipse-collections</artifactId> | ||||
|             <version>${eclipse.collections.version}</version> | ||||
|         </dependency> | ||||
|         <dependency> | ||||
|             <groupId>org.assertj</groupId> | ||||
|             <artifactId>assertj-core</artifactId> | ||||
|             <version>${assertj.version}</version> | ||||
|             <scope>test</scope> | ||||
|         </dependency> | ||||
|         <dependency> | ||||
|             <groupId>org.junit.platform</groupId> | ||||
|             <artifactId>junit-platform-runner</artifactId> | ||||
|             <version>${junit.platform.version}</version> | ||||
|             <scope>test</scope> | ||||
|         </dependency> | ||||
|         <dependency> | ||||
|             <groupId>org.openjdk.jmh</groupId> | ||||
|             <artifactId>jmh-core</artifactId> | ||||
|             <version>${openjdk.jmh.version}</version> | ||||
|         </dependency> | ||||
|         <dependency> | ||||
|             <groupId>org.openjdk.jmh</groupId> | ||||
|             <artifactId>jmh-generator-annprocess</artifactId> | ||||
|             <version>${openjdk.jmh.version}</version> | ||||
|         </dependency> | ||||
|         <dependency> | ||||
|             <groupId>org.apache.commons</groupId> | ||||
|             <artifactId>commons-exec</artifactId> | ||||
|             <version>${commons-exec.version}</version> | ||||
|         </dependency> | ||||
|         <dependency> | ||||
|             <groupId>org.projectlombok</groupId> | ||||
|             <artifactId>lombok</artifactId> | ||||
|             <version>${lombok.version}</version> | ||||
|             <scope>provided</scope> | ||||
|         </dependency> | ||||
|     </dependencies> | ||||
| 
 | ||||
|     <properties> | ||||
|         <openjdk.jmh.version>1.19</openjdk.jmh.version> | ||||
|         <junit.platform.version>1.2.0</junit.platform.version> | ||||
|         <commons-lang3.version>3.8.1</commons-lang3.version> | ||||
|         <commons-collections4.version>4.1</commons-collections4.version> | ||||
|         <collections-generic.version>4.01</collections-generic.version> | ||||
|         <avaitility.version>1.7.0</avaitility.version> | ||||
|         <assertj.version>3.11.1</assertj.version> | ||||
|         <eclipse.collections.version>7.1.0</eclipse.collections.version> | ||||
| 		<commons-exec.version>1.3</commons-exec.version> | ||||
|     </properties> | ||||
| </project> | ||||
| @ -0,0 +1,55 @@ | ||||
| package com.baeldung.copyinghashmap; | ||||
| 
 | ||||
| import java.util.HashMap; | ||||
| import java.util.Map; | ||||
| import java.util.Map.Entry; | ||||
| import java.util.Set; | ||||
| import java.util.stream.Collectors; | ||||
| 
 | ||||
| import org.apache.commons.lang3.SerializationUtils; | ||||
| 
 | ||||
| public class CopyHashMap { | ||||
|      | ||||
|     public static <String, Employee> HashMap<String, Employee> copyUsingConstructor(HashMap<String, Employee> originalMap) { | ||||
|         return new HashMap<String, Employee>(originalMap); | ||||
|     } | ||||
|      | ||||
|     public static <String, Employee> HashMap<String, Employee> copyUsingClone(HashMap<String, Employee> originalMap) { | ||||
|         return (HashMap<String, Employee>) originalMap.clone(); | ||||
|     } | ||||
| 
 | ||||
|     public static <String, Employee> HashMap<String, Employee> copyUsingPut(HashMap<String, Employee> originalMap) { | ||||
|         HashMap<String, Employee> shallowCopy = new HashMap<String, Employee>(); | ||||
|         Set<Entry<String, Employee>> entries = originalMap.entrySet(); | ||||
|         for(Map.Entry<String, Employee> mapEntry: entries) { | ||||
|             shallowCopy.put(mapEntry.getKey(), mapEntry.getValue()); | ||||
|         } | ||||
|          | ||||
|         return shallowCopy; | ||||
|     } | ||||
|      | ||||
|     public static <String, Employee> HashMap<String, Employee> copyUsingPutAll(HashMap<String, Employee> originalMap) { | ||||
|         HashMap<String, Employee> shallowCopy = new HashMap<String, Employee>(); | ||||
|         shallowCopy.putAll(originalMap); | ||||
|          | ||||
|         return shallowCopy; | ||||
|     } | ||||
|      | ||||
|     public static <String, Employee> HashMap<String, Employee> copyUsingJava8Stream(HashMap<String, Employee> originalMap) { | ||||
|         Set<Entry<String, Employee>> entries = originalMap.entrySet(); | ||||
|         HashMap<String, Employee> shallowCopy = (HashMap<String, Employee>) entries | ||||
|             .stream() | ||||
|             .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); | ||||
|          | ||||
|         return shallowCopy; | ||||
|     } | ||||
|      | ||||
|     public static <String, Employee> HashMap<String, Employee> shallowCopy(HashMap<String, Employee> originalMap) { | ||||
|         return (HashMap<String, Employee>) originalMap.clone(); | ||||
|     } | ||||
|      | ||||
|     public static <String, Employee> HashMap<String, Employee> deepCopy(HashMap<String, Employee> originalMap) { | ||||
|         return SerializationUtils.clone(originalMap); | ||||
|     } | ||||
|      | ||||
| } | ||||
| @ -0,0 +1,77 @@ | ||||
| package com.baeldung.copyinghashmap; | ||||
| 
 | ||||
| import static org.assertj.core.api.Assertions.assertThat; | ||||
| 
 | ||||
| import java.util.HashMap; | ||||
| import java.util.Map; | ||||
| 
 | ||||
| import org.junit.Test; | ||||
| 
 | ||||
| import com.google.common.collect.ImmutableMap; | ||||
| 
 | ||||
| public class CopyHashMapUnitTest { | ||||
|      | ||||
|     @Test | ||||
|     public void givenHashMap_whenShallowCopy_thenCopyisNotSameAsOriginal() { | ||||
|          | ||||
|         HashMap<String, Employee> map = new HashMap<>(); | ||||
|         Employee emp1 = new Employee("John"); | ||||
|         Employee emp2 = new Employee("Norman"); | ||||
|         map.put("emp1",emp1); | ||||
|         map.put("emp2",emp2); | ||||
|      | ||||
|         HashMap<String, Employee> shallowCopy = CopyHashMap.shallowCopy(map); | ||||
|          | ||||
|         assertThat(shallowCopy).isNotSameAs(map); | ||||
|          | ||||
|     } | ||||
|      | ||||
|     @Test | ||||
|     public void givenHashMap_whenShallowCopyModifyingOriginalObject_thenCopyShouldChange() { | ||||
|          | ||||
|         HashMap<String, Employee> map = new HashMap<>(); | ||||
|         Employee emp1 = new Employee("John"); | ||||
|         Employee emp2 = new Employee("Norman"); | ||||
|         map.put("emp1",emp1); | ||||
|         map.put("emp2",emp2); | ||||
|          | ||||
|         HashMap<String, Employee> shallowCopy = CopyHashMap.shallowCopy(map); | ||||
|          | ||||
|         emp1.setName("Johny"); | ||||
|          | ||||
|         assertThat(shallowCopy.get("emp1")).isEqualTo(map.get("emp1")); | ||||
|          | ||||
|     } | ||||
|      | ||||
|     @Test | ||||
|     public void givenHashMap_whenDeepCopyModifyingOriginalObject_thenCopyShouldNotChange() { | ||||
|          | ||||
|         HashMap<String, Employee> map = new HashMap<>(); | ||||
|         Employee emp1 = new Employee("John"); | ||||
|         Employee emp2 = new Employee("Norman"); | ||||
|         map.put("emp1",emp1); | ||||
|         map.put("emp2",emp2); | ||||
|         HashMap<String, Employee> deepCopy = CopyHashMap.deepCopy(map); | ||||
|          | ||||
|         emp1.setName("Johny"); | ||||
|          | ||||
|         assertThat(deepCopy.get("emp1")).isNotEqualTo(map.get("emp1")); | ||||
|          | ||||
|     } | ||||
|      | ||||
|     @Test | ||||
|     public void givenImmutableMap_whenCopyUsingGuava_thenCopyShouldNotChange() { | ||||
|         Employee emp1 = new Employee("John"); | ||||
|         Employee emp2 = new Employee("Norman"); | ||||
|          | ||||
|         Map<String, Employee> map = ImmutableMap.<String, Employee> builder() | ||||
|             .put("emp1",emp1) | ||||
|             .put("emp2",emp2) | ||||
|             .build(); | ||||
|         Map<String, Employee> shallowCopy = ImmutableMap.copyOf(map); | ||||
|          | ||||
|         assertThat(shallowCopy).isSameAs(map); | ||||
|          | ||||
|     } | ||||
| 
 | ||||
| } | ||||
| @ -0,0 +1,28 @@ | ||||
| package com.baeldung.copyinghashmap; | ||||
| 
 | ||||
| import java.io.Serializable; | ||||
| 
 | ||||
| public class Employee implements Serializable{ | ||||
|      | ||||
|     private String name; | ||||
|      | ||||
|     public Employee(String name) { | ||||
|         super(); | ||||
|         this.name = name; | ||||
|     } | ||||
|     public String getName() { | ||||
|         return name; | ||||
|     } | ||||
|      | ||||
|     public void setName(String name) { | ||||
|         this.name = name; | ||||
|     } | ||||
|      | ||||
|     @Override | ||||
|     public String toString() { | ||||
|         return this.name; | ||||
|     } | ||||
|   | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| @ -3,7 +3,7 @@ | ||||
| ## Core Java Collections Cookbooks and Examples | ||||
| 
 | ||||
| ### Relevant Articles:  | ||||
| - [Java - Combine Multiple Collections](http://www.baeldung.com/java-combine-multiple-collections) | ||||
| - [Java – Combine Multiple Collections](http://www.baeldung.com/java-combine-multiple-collections) | ||||
| - [HashSet and TreeSet Comparison](http://www.baeldung.com/java-hashset-vs-treeset) | ||||
| - [Collect a Java Stream to an Immutable Collection](http://www.baeldung.com/java-stream-immutable-collection) | ||||
| - [Introduction to the Java ArrayDeque](http://www.baeldung.com/java-array-deque) | ||||
|  | ||||
| @ -12,7 +12,7 @@ | ||||
| - [Guide to the Java Phaser](http://www.baeldung.com/java-phaser) | ||||
| - [An Introduction to Atomic Variables in Java](http://www.baeldung.com/java-atomic-variables) | ||||
| - [CyclicBarrier in Java](http://www.baeldung.com/java-cyclic-barrier) | ||||
| - [Guide to Volatile Keyword in Java](http://www.baeldung.com/java-volatile) | ||||
| - [Guide to the Volatile Keyword in Java](http://www.baeldung.com/java-volatile) | ||||
| - [Semaphores in Java](http://www.baeldung.com/java-semaphore) | ||||
| - [Daemon Threads in Java](http://www.baeldung.com/java-daemon-thread) | ||||
| - [Priority-based Job Scheduling in Java](http://www.baeldung.com/java-priority-job-schedule) | ||||
| @ -20,6 +20,6 @@ | ||||
| - [Print Even and Odd Numbers Using 2 Threads](https://www.baeldung.com/java-even-odd-numbers-with-2-threads) | ||||
| - [Java CyclicBarrier vs CountDownLatch](https://www.baeldung.com/java-cyclicbarrier-countdownlatch) | ||||
| - [Guide to the Fork/Join Framework in Java](http://www.baeldung.com/java-fork-join) | ||||
| - [A Guide to ThreadLocalRandom in Java](http://www.baeldung.com/java-thread-local-random) | ||||
| - [Guide to ThreadLocalRandom in Java](http://www.baeldung.com/java-thread-local-random) | ||||
| - [The Thread.join() Method in Java](http://www.baeldung.com/java-thread-join) | ||||
| - [Passing Parameters to Java Threads](https://www.baeldung.com/java-thread-parameters) | ||||
|  | ||||
| @ -7,13 +7,13 @@ | ||||
| - [A Guide to the Java ExecutorService](http://www.baeldung.com/java-executor-service-tutorial) | ||||
| - [Guide to java.util.concurrent.Future](http://www.baeldung.com/java-future) | ||||
| - [Difference Between Wait and Sleep in Java](http://www.baeldung.com/java-wait-and-sleep) | ||||
| - [Guide to Synchronized Keyword in Java](http://www.baeldung.com/java-synchronized) | ||||
| - [Guide to the Synchronized Keyword in Java](http://www.baeldung.com/java-synchronized) | ||||
| - [Overview of the java.util.concurrent](http://www.baeldung.com/java-util-concurrent) | ||||
| - [Implementing a Runnable vs Extending a Thread](http://www.baeldung.com/java-runnable-vs-extending-thread) | ||||
| - [How to Kill a Java Thread](http://www.baeldung.com/java-thread-stop) | ||||
| - [ExecutorService - Waiting for Threads to Finish](http://www.baeldung.com/java-executor-wait-for-threads) | ||||
| - [ExecutorService – Waiting for Threads to Finish](http://www.baeldung.com/java-executor-wait-for-threads) | ||||
| - [wait and notify() Methods in Java](http://www.baeldung.com/java-wait-notify) | ||||
| - [Life Cycle of a Thread in Java](http://www.baeldung.com/java-thread-lifecycle) | ||||
| - [Runnable vs. Callable in Java](http://www.baeldung.com/java-runnable-callable) | ||||
| - [What is Thread-Safety and How to Achieve it](https://www.baeldung.com/java-thread-safety) | ||||
| - [What is Thread-Safety and How to Achieve it?](https://www.baeldung.com/java-thread-safety) | ||||
| - [How to Start a Thread in Java](https://www.baeldung.com/java-start-thread) | ||||
|  | ||||
| @ -6,7 +6,7 @@ | ||||
| - [How to Read a Large File Efficiently with Java](http://www.baeldung.com/java-read-lines-large-file) | ||||
| - [Java InputStream to String](http://www.baeldung.com/convert-input-stream-to-string) | ||||
| - [Java – Write to File](http://www.baeldung.com/java-write-to-file) | ||||
| - [Java - Convert File to InputStream](http://www.baeldung.com/convert-file-to-input-stream) | ||||
| - [Java – Convert File to InputStream](http://www.baeldung.com/convert-file-to-input-stream) | ||||
| - [Java Scanner](http://www.baeldung.com/java-scanner) | ||||
| - [Java – Byte Array to Writer](http://www.baeldung.com/java-convert-byte-array-to-writer) | ||||
| - [Java – Directory Size](http://www.baeldung.com/java-folder-size) | ||||
| @ -14,7 +14,7 @@ | ||||
| - [File Size in Java](http://www.baeldung.com/java-file-size) | ||||
| - [Comparing getPath(), getAbsolutePath(), and getCanonicalPath() in Java](http://www.baeldung.com/java-path) | ||||
| - [Using Java MappedByteBuffer](http://www.baeldung.com/java-mapped-byte-buffer) | ||||
| - [Copy a File with Java](http://www.baeldung.com/java-copy-file) | ||||
| - [How to Copy a File with Java](http://www.baeldung.com/java-copy-file) | ||||
| - [Java – Append Data to a File](http://www.baeldung.com/java-append-to-file) | ||||
| - [FileNotFoundException in Java](http://www.baeldung.com/java-filenotfound-exception) | ||||
| - [How to Read a File in Java](http://www.baeldung.com/reading-file-in-java) | ||||
|  | ||||
| @ -3,4 +3,4 @@ | ||||
| ## Core Java JVM Cookbooks and Examples | ||||
| 
 | ||||
| ### Relevant Articles:  | ||||
| - [Method Inlining in the JVM](http://www.baeldung.com/method-inlining-in-the-jvm/) | ||||
| - [Method Inlining in the JVM](https://www.baeldung.com/jvm-method-inlining) | ||||
|  | ||||
							
								
								
									
										19
									
								
								core-java-lambdas/pom.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								core-java-lambdas/pom.xml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,19 @@ | ||||
| <?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-lambdas</artifactId> | ||||
|   <version>0.1.0-SNAPSHOT</version> | ||||
|   <name>core-java</name> | ||||
|   <packaging>jar</packaging> | ||||
| 
 | ||||
|   <parent> | ||||
|     <groupId>com.baeldung</groupId> | ||||
|     <artifactId>parent-java</artifactId> | ||||
|     <version>0.0.1-SNAPSHOT</version> | ||||
|     <relativePath>../parent-java</relativePath> | ||||
|   </parent> | ||||
| 
 | ||||
| 
 | ||||
| </project> | ||||
| @ -0,0 +1,88 @@ | ||||
| package com.baeldung.lambdas; | ||||
| 
 | ||||
| import java.util.Random; | ||||
| import java.util.concurrent.ExecutorService; | ||||
| import java.util.concurrent.Executors; | ||||
| import java.util.function.Supplier; | ||||
| import java.util.stream.IntStream; | ||||
| 
 | ||||
| /** | ||||
|  * Class with examples about working with capturing lambdas. | ||||
|  */ | ||||
| public class LambdaVariables { | ||||
| 
 | ||||
|     private volatile boolean run = true; | ||||
|     private int start = 0; | ||||
| 
 | ||||
|     private ExecutorService executor = Executors.newFixedThreadPool(3); | ||||
| 
 | ||||
|     public static void main(String[] args) { | ||||
|         new LambdaVariables().localVariableMultithreading(); | ||||
|     } | ||||
| 
 | ||||
|     Supplier<Integer> incrementer(int start) { | ||||
|         return () -> start; // can't modify start parameter inside the lambda | ||||
|     } | ||||
| 
 | ||||
|     Supplier<Integer> incrementer() { | ||||
|         return () -> start++; | ||||
|     } | ||||
| 
 | ||||
|     public void localVariableMultithreading() { | ||||
|         boolean run = true; | ||||
|         executor.execute(() -> { | ||||
|             while (run) { | ||||
|                 // do operation | ||||
|             } | ||||
|         }); | ||||
|         // commented because it doesn't compile, it's just an example of non-final local variables in lambdas | ||||
|         // run = false; | ||||
|     } | ||||
| 
 | ||||
|     public void instanceVariableMultithreading() { | ||||
|         executor.execute(() -> { | ||||
|             while (run) { | ||||
|                 // do operation | ||||
|             } | ||||
|         }); | ||||
| 
 | ||||
|         run = false; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * WARNING: always avoid this workaround!! | ||||
|      */ | ||||
|     public void workaroundSingleThread() { | ||||
|         int[] holder = new int[] { 2 }; | ||||
|         IntStream sums = IntStream | ||||
|           .of(1, 2, 3) | ||||
|           .map(val -> val + holder[0]); | ||||
| 
 | ||||
|         holder[0] = 0; | ||||
| 
 | ||||
|         System.out.println(sums.sum()); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * WARNING: always avoid this workaround!! | ||||
|      */ | ||||
|     public void workaroundMultithreading() { | ||||
|         int[] holder = new int[] { 2 }; | ||||
|         Runnable runnable = () -> System.out.println(IntStream | ||||
|           .of(1, 2, 3) | ||||
|           .map(val -> val + holder[0]) | ||||
|           .sum()); | ||||
| 
 | ||||
|         new Thread(runnable).start(); | ||||
| 
 | ||||
|         // simulating some processing | ||||
|         try { | ||||
|             Thread.sleep(new Random().nextInt(3) * 1000L); | ||||
|         } catch (InterruptedException e) { | ||||
|             throw new RuntimeException(e); | ||||
|         } | ||||
| 
 | ||||
|         holder[0] = 0; | ||||
|     } | ||||
| 
 | ||||
| } | ||||
| @ -10,7 +10,7 @@ | ||||
| - [How to Make a Deep Copy of an Object in Java](http://www.baeldung.com/java-deep-copy) | ||||
| - [Guide to Inheritance in Java](http://www.baeldung.com/java-inheritance) | ||||
| - [Object Type Casting in Java](http://www.baeldung.com/java-type-casting) | ||||
| - [The "final" Keyword in Java](http://www.baeldung.com/java-final) | ||||
| - [The “final” Keyword in Java](http://www.baeldung.com/java-final) | ||||
| - [Type Erasure in Java Explained](http://www.baeldung.com/java-type-erasure) | ||||
| - [Pass-By-Value as a Parameter Passing Mechanism in Java](http://www.baeldung.com/java-pass-by-value-or-pass-by-reference) | ||||
| - [Variable and Method Hiding in Java](http://www.baeldung.com/java-variable-method-hiding) | ||||
|  | ||||
| @ -12,7 +12,7 @@ | ||||
| - [Dynamic Proxies in Java](http://www.baeldung.com/java-dynamic-proxies) | ||||
| - [Java Double Brace Initialization](http://www.baeldung.com/java-double-brace-initialization) | ||||
| - [Guide to the Diamond Operator in Java](http://www.baeldung.com/java-diamond-operator) | ||||
| - [Quick Example - Comparator vs Comparable in Java](http://www.baeldung.com/java-comparator-comparable) | ||||
| - [Comparator and Comparable in Java](http://www.baeldung.com/java-comparator-comparable) | ||||
| - [The Java continue and break Keywords](http://www.baeldung.com/java-continue-and-break) | ||||
| - [Nested Classes in Java](http://www.baeldung.com/java-nested-classes) | ||||
| - [A Guide to Inner Interfaces in Java](http://www.baeldung.com/java-inner-interfaces) | ||||
|  | ||||
| @ -14,4 +14,5 @@ | ||||
| - [A Guide to Java Sockets](http://www.baeldung.com/a-guide-to-java-sockets) | ||||
| - [Guide to Java URL Encoding/Decoding](http://www.baeldung.com/java-url-encoding-decoding) | ||||
| - [Do a Simple HTTP Request in Java](http://www.baeldung.com/java-http-request) | ||||
| - [Difference between URL and URI](http://www.baeldung.com/java-url-vs-uri) | ||||
| - [Difference between URL and URI](http://www.baeldung.com/java-url-vs-uri) | ||||
| - [Read an InputStream using the Java Server Socket](https://www.baeldung.com/java-inputstream-server-socket) | ||||
|  | ||||
| @ -29,7 +29,7 @@ | ||||
| - [What is the serialVersionUID?](http://www.baeldung.com/java-serial-version-uid) | ||||
| - [A Guide to the ResourceBundle](http://www.baeldung.com/java-resourcebundle) | ||||
| - [Class Loaders in Java](http://www.baeldung.com/java-classloaders) | ||||
| - [Guide to Java Clock Class](http://www.baeldung.com/java-clock) | ||||
| - [Guide to the Java Clock Class](http://www.baeldung.com/java-clock) | ||||
| - [Importance of Main Manifest Attribute in a Self-Executing JAR](http://www.baeldung.com/java-jar-executable-manifest-main-class) | ||||
| - [Java Global Exception Handler](http://www.baeldung.com/java-global-exception-handler) | ||||
| - [How to Get the Size of an Object in Java](http://www.baeldung.com/java-size-of-object) | ||||
|  | ||||
| @ -2,5 +2,8 @@ | ||||
| 
 | ||||
| - [Void Type in Kotlin](https://www.baeldung.com/kotlin-void-type) | ||||
| - [How to use Kotlin Range Expressions](https://www.baeldung.com/kotlin-ranges) | ||||
| - [Creating a Kotlin Range Iterator on a Custom Object](https://www.baeldung.com/kotlin-custom-range-iterator) | ||||
| - [Kotlin Scope Functions](https://www.baeldung.com/kotlin-scope-functions) | ||||
| - [Kotlin Annotations](https://www.baeldung.com/kotlin-annotations) | ||||
| - [Split a List into Parts in Kotlin](https://www.baeldung.com/kotlin-split-list-into-parts) | ||||
| - [String Comparison in Kotlin](https://www.baeldung.com/kotlin-string-comparison) | ||||
| - [String Comparison in Kotlin](https://www.baeldung.com/kotlin-string-comparison) | ||||
| @ -0,0 +1,18 @@ | ||||
| package com.baeldung.inputstream | ||||
| 
 | ||||
| import java.io.InputStream | ||||
| 
 | ||||
| fun InputStream.readUpToChar(stopChar: Char): String { | ||||
|     val stringBuilder = StringBuilder() | ||||
|     var currentChar = this.read().toChar() | ||||
|     while (currentChar != stopChar) { | ||||
|         stringBuilder.append(currentChar) | ||||
|         currentChar = this.read().toChar() | ||||
|         if (this.available() <= 0) { | ||||
|             stringBuilder.append(currentChar) | ||||
|             break | ||||
|         } | ||||
|     } | ||||
|     return stringBuilder.toString() | ||||
| } | ||||
| 
 | ||||
| @ -0,0 +1,71 @@ | ||||
| package com.baeldung.inputstream | ||||
| 
 | ||||
| import kotlinx.io.core.use | ||||
| import org.junit.Test | ||||
| import java.io.BufferedReader | ||||
| import java.io.File | ||||
| import kotlin.test.assertEquals | ||||
| 
 | ||||
| class InputStreamToStringTest { | ||||
|     private val fileName = "src/test/resources/inputstream2string.txt" | ||||
|     private val fileFullContent = "Computer programming can be a hassle\r\n" + | ||||
|             "It's like trying to take a defended castle" | ||||
| 
 | ||||
|     @Test | ||||
|     fun whenReadFileWithBufferedReader_thenFullFileContentIsReadAsString() { | ||||
|         val file = File(fileName) | ||||
|         val inputStream = file.inputStream() | ||||
|         val content = inputStream.bufferedReader().use(BufferedReader::readText) | ||||
|         assertEquals(fileFullContent, content) | ||||
|     } | ||||
|     @Test | ||||
|     fun whenReadFileWithBufferedReaderReadText_thenFullFileContentIsReadAsString() { | ||||
|         val file = File(fileName) | ||||
|         val inputStream = file.inputStream() | ||||
|         val reader = BufferedReader(inputStream.reader()) | ||||
|         var content: String | ||||
|         try { | ||||
|             content = reader.readText() | ||||
|         } finally { | ||||
|             reader.close() | ||||
|         } | ||||
|         assertEquals(fileFullContent, content) | ||||
|     } | ||||
|     @Test | ||||
|     fun whenReadFileWithBufferedReaderManually_thenFullFileContentIsReadAsString() { | ||||
|         val file = File(fileName) | ||||
|         val inputStream = file.inputStream() | ||||
|         val reader = BufferedReader(inputStream.reader()) | ||||
|         val content = StringBuilder() | ||||
|         try { | ||||
|             var line = reader.readLine() | ||||
|             while (line != null) { | ||||
|                 content.append(line) | ||||
|                 line = reader.readLine() | ||||
|             } | ||||
|         } finally { | ||||
|             reader.close() | ||||
|         } | ||||
|         assertEquals(fileFullContent.replace("\r\n", ""), content.toString()) | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     fun whenReadFileUpToStopChar_thenPartBeforeStopCharIsReadAsString() { | ||||
|         val file = File(fileName) | ||||
|         val inputStream = file.inputStream() | ||||
|         val content = inputStream.use { it.readUpToChar(' ') } | ||||
|         assertEquals("Computer", content) | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     fun whenReadFileWithoutContainingStopChar_thenFullFileContentIsReadAsString() { | ||||
|         val file = File(fileName) | ||||
|         val inputStream = file.inputStream() | ||||
|         val content = inputStream.use { it.readUpToChar('-') } | ||||
|         assertEquals(fileFullContent, content) | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
							
								
								
									
										2
									
								
								core-kotlin-2/src/test/resources/inputstream2string.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								core-kotlin-2/src/test/resources/inputstream2string.txt
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,2 @@ | ||||
| Computer programming can be a hassle | ||||
| It's like trying to take a defended castle | ||||
| @ -1,7 +1,7 @@ | ||||
| ## Relevant articles: | ||||
| 
 | ||||
| - [Introduction to the Kotlin Language](http://www.baeldung.com/kotlin) | ||||
| - [A guide to the “when{}” block in Kotlin](http://www.baeldung.com/kotlin-when) | ||||
| - [Guide to the “when{}” Block in Kotlin](http://www.baeldung.com/kotlin-when) | ||||
| - [Comprehensive Guide to Null Safety in Kotlin](http://www.baeldung.com/kotlin-null-safety) | ||||
| - [Kotlin Java Interoperability](http://www.baeldung.com/kotlin-java-interoperability) | ||||
| - [Difference Between “==” and “===” operators in Kotlin](http://www.baeldung.com/kotlin-equality-operators) | ||||
|  | ||||
| @ -3,7 +3,7 @@ | ||||
| ### Relevant Articles: | ||||
| - [Introduction to Couchbase SDK for Java](http://www.baeldung.com/java-couchbase-sdk) | ||||
| - [Using Couchbase in a Spring Application](http://www.baeldung.com/couchbase-sdk-spring) | ||||
| - [Asynchronous Batch Opereations in Couchbase](http://www.baeldung.com/async-batch-operations-in-couchbase) | ||||
| - [Asynchronous Batch Operations in Couchbase](http://www.baeldung.com/async-batch-operations-in-couchbase) | ||||
| - [Querying Couchbase with MapReduce Views](http://www.baeldung.com/couchbase-query-mapreduce-view) | ||||
| - [Querying Couchbase with N1QL](http://www.baeldung.com/n1ql-couchbase) | ||||
| 
 | ||||
|  | ||||
| @ -11,6 +11,6 @@ | ||||
| - [Convert JSON to a Map Using Gson](https://www.baeldung.com/gson-json-to-map) | ||||
| - [Working with Primitive Values in Gson](https://www.baeldung.com/java-gson-primitives) | ||||
| - [Convert String to JsonObject with Gson](https://www.baeldung.com/gson-string-to-jsonobject) | ||||
| - [Mapping Multiple JSON Fields to One Java Field](https://www.baeldung.com/json-multiple-fields-single-java-field) | ||||
| - [Mapping Multiple JSON Fields to a Single Java Field](https://www.baeldung.com/json-multiple-fields-single-java-field) | ||||
| - [Serializing and Deserializing a List with Gson](https://www.baeldung.com/gson-list) | ||||
| 
 | ||||
|  | ||||
| @ -1,4 +1,4 @@ | ||||
| ### Relevant articles: | ||||
| - [New Stream, Comparator and Collector Functionality in Guava 21](http://www.baeldung.com/guava-21-new) | ||||
| - [New Stream, Comparator and Collector in Guava 21](http://www.baeldung.com/guava-21-new) | ||||
| - [New in Guava 21 common.util.concurrent](http://www.baeldung.com/guava-21-util-concurrent) | ||||
| - [Zipping Collections in Java](http://www.baeldung.com/java-collections-zip) | ||||
|  | ||||
| @ -9,7 +9,7 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring | ||||
| 
 | ||||
| - [HttpClient 4 – Send Custom Cookie](http://www.baeldung.com/httpclient-4-cookies) | ||||
| - [HttpClient 4 – Get the Status Code](http://www.baeldung.com/httpclient-status-code) | ||||
| - [HttpClient 4 – Cancel / Abort Request](http://www.baeldung.com/httpclient-cancel-request) | ||||
| - [HttpClient 4 – Cancel Request](http://www.baeldung.com/httpclient-cancel-request) | ||||
| - [HttpClient 4 Cookbook](http://www.baeldung.com/httpclient4) | ||||
| - [Unshorten URLs with HttpClient](http://www.baeldung.com/unshorten-url-httpclient) | ||||
| - [HttpClient 4 – Follow Redirects for POST](http://www.baeldung.com/httpclient-redirect-on-http-post) | ||||
|  | ||||
| @ -16,7 +16,7 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring | ||||
| - [Jackson – Bidirectional Relationships](http://www.baeldung.com/jackson-bidirectional-relationships-and-infinite-recursion) | ||||
| - [Jackson JSON Tutorial](http://www.baeldung.com/jackson) | ||||
| - [Jackson – Working with Maps and nulls](http://www.baeldung.com/jackson-map-null-values-or-null-key) | ||||
| - [Jackson – Decide What Fields Get Serialized/Deserializaed](http://www.baeldung.com/jackson-field-serializable-deserializable-or-not) | ||||
| - [Jackson – Decide What Fields Get Serialized/Deserialized](http://www.baeldung.com/jackson-field-serializable-deserializable-or-not) | ||||
| - [Jackson Annotation Examples](http://www.baeldung.com/jackson-annotations) | ||||
| - [Working with Tree Model Nodes in Jackson](http://www.baeldung.com/jackson-json-node-tree-model) | ||||
| - [Jackson vs Gson](http://www.baeldung.com/jackson-vs-gson) | ||||
|  | ||||
							
								
								
									
										2
									
								
								java-collections-maps-2/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								java-collections-maps-2/README.md
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,2 @@ | ||||
| ## Relevant Articles: | ||||
| - [Map of Primitives in Java](https://www.baeldung.com/java-map-primitives) | ||||
							
								
								
									
										2
									
								
								java-dates-2/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								java-dates-2/README.md
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,2 @@ | ||||
| ## Relevant Articles: | ||||
| - [Converting Between LocalDate and XMLGregorianCalendar](https://www.baeldung.com/java-localdate-to-xmlgregoriancalendar) | ||||
| @ -8,7 +8,7 @@ | ||||
| - [Java 8 and Infinite Streams](http://www.baeldung.com/java-inifinite-streams) | ||||
| - [Java 8 Stream findFirst() vs. findAny()](http://www.baeldung.com/java-stream-findfirst-vs-findany) | ||||
| - [How to Get the Last Element of a Stream in Java?](http://www.baeldung.com/java-stream-last-element) | ||||
| - [”Stream has already been operated upon or closed” Exception in Java](http://www.baeldung.com/java-stream-operated-upon-or-closed-exception) | ||||
| - [“Stream has already been operated upon or closed” Exception in Java](http://www.baeldung.com/java-stream-operated-upon-or-closed-exception) | ||||
| - [Iterable to Stream in Java](http://www.baeldung.com/java-iterable-to-stream) | ||||
| - [How to Iterate Over a Stream With Indices](http://www.baeldung.com/java-stream-indices) | ||||
| - [Primitive Type Streams in Java 8](http://www.baeldung.com/java-8-primitive-streams) | ||||
|  | ||||
| @ -10,3 +10,5 @@ | ||||
| - [Introduction to Arrow in Kotlin](https://www.baeldung.com/kotlin-arrow) | ||||
| - [Kotlin with Ktor](https://www.baeldung.com/kotlin-ktor) | ||||
| - [REST API With Kotlin and Kovert](https://www.baeldung.com/kotlin-kovert) | ||||
| - [MockK: A Mocking Library for Kotlin](https://www.baeldung.com/kotlin-mockk) | ||||
| - [Kotlin Immutable Collections](https://www.baeldung.com/kotlin-immutable-collections) | ||||
| @ -32,6 +32,12 @@ | ||||
|             <version>${scribejava.version}</version> | ||||
|         </dependency> | ||||
| 
 | ||||
|         <dependency> | ||||
|             <groupId>com.google.crypto.tink</groupId> | ||||
|             <artifactId>tink</artifactId> | ||||
|             <version>${tink.version}</version> | ||||
|         </dependency> | ||||
| 
 | ||||
|         <dependency> | ||||
|             <groupId>junit</groupId> | ||||
|             <artifactId>junit</artifactId> | ||||
| @ -55,6 +61,7 @@ | ||||
|         <scribejava.version>5.6.0</scribejava.version> | ||||
| 		<spring-security-oauth2.version>2.3.3.RELEASE</spring-security-oauth2.version> | ||||
| 		<passay.version>1.3.1</passay.version> | ||||
|         <tink.version>1.2.2</tink.version> | ||||
| 		<cryptacular.version>1.2.2</cryptacular.version> | ||||
|     </properties> | ||||
| </project> | ||||
|  | ||||
| @ -0,0 +1,101 @@ | ||||
| package com.baeldung.tink; | ||||
| 
 | ||||
| import com.google.crypto.tink.*; | ||||
| import com.google.crypto.tink.aead.AeadConfig; | ||||
| import com.google.crypto.tink.aead.AeadFactory; | ||||
| import com.google.crypto.tink.aead.AeadKeyTemplates; | ||||
| import com.google.crypto.tink.config.TinkConfig; | ||||
| import com.google.crypto.tink.hybrid.HybridDecryptFactory; | ||||
| import com.google.crypto.tink.hybrid.HybridEncryptFactory; | ||||
| import com.google.crypto.tink.hybrid.HybridKeyTemplates; | ||||
| import com.google.crypto.tink.mac.MacFactory; | ||||
| import com.google.crypto.tink.mac.MacKeyTemplates; | ||||
| import com.google.crypto.tink.signature.PublicKeySignFactory; | ||||
| import com.google.crypto.tink.signature.PublicKeyVerifyFactory; | ||||
| import com.google.crypto.tink.signature.SignatureKeyTemplates; | ||||
| import org.junit.Assert; | ||||
| import org.junit.Test; | ||||
| 
 | ||||
| import java.security.GeneralSecurityException; | ||||
| 
 | ||||
| public class TinkUnitTest { | ||||
| 
 | ||||
|     private static final String PLAINTEXT = "BAELDUNG"; | ||||
|     private static final String DATA = "TINK"; | ||||
| 
 | ||||
|     @Test | ||||
|     public void givenPlaintext_whenEncryptWithAead_thenPlaintextIsEncrypted() throws GeneralSecurityException { | ||||
| 
 | ||||
|         AeadConfig.register(); | ||||
| 
 | ||||
|         KeysetHandle keysetHandle = KeysetHandle.generateNew( | ||||
|                 AeadKeyTemplates.AES256_GCM); | ||||
| 
 | ||||
|         Aead aead = AeadFactory.getPrimitive(keysetHandle); | ||||
| 
 | ||||
|         byte[] ciphertext = aead.encrypt(PLAINTEXT.getBytes(), | ||||
|                 DATA.getBytes()); | ||||
| 
 | ||||
|         Assert.assertNotEquals(PLAINTEXT, new String(ciphertext)); | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     public void givenData_whenComputeMAC_thenVerifyMAC() throws GeneralSecurityException { | ||||
| 
 | ||||
|         TinkConfig.register(); | ||||
| 
 | ||||
|         KeysetHandle keysetHandle = KeysetHandle.generateNew( | ||||
|                 MacKeyTemplates.HMAC_SHA256_128BITTAG); | ||||
| 
 | ||||
|         Mac mac = MacFactory.getPrimitive(keysetHandle); | ||||
| 
 | ||||
|         byte[] tag = mac.computeMac(DATA.getBytes()); | ||||
| 
 | ||||
|         mac.verifyMac(tag, DATA.getBytes()); | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     public void givenData_whenSignData_thenVerifySignature() throws GeneralSecurityException { | ||||
| 
 | ||||
|         TinkConfig.register(); | ||||
| 
 | ||||
|         KeysetHandle privateKeysetHandle = KeysetHandle.generateNew( | ||||
|                 SignatureKeyTemplates.ECDSA_P256); | ||||
| 
 | ||||
|         PublicKeySign signer = PublicKeySignFactory.getPrimitive(privateKeysetHandle); | ||||
| 
 | ||||
|         byte[] signature = signer.sign(DATA.getBytes()); | ||||
| 
 | ||||
|         KeysetHandle publicKeysetHandle = | ||||
|                 privateKeysetHandle.getPublicKeysetHandle(); | ||||
| 
 | ||||
|         PublicKeyVerify verifier = PublicKeyVerifyFactory.getPrimitive(publicKeysetHandle); | ||||
| 
 | ||||
|         verifier.verify(signature, DATA.getBytes()); | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     public void givenPlaintext_whenEncryptWithHybridEncryption_thenVerifyDecryptedIsEqual() throws GeneralSecurityException { | ||||
| 
 | ||||
|         TinkConfig.register(); | ||||
| 
 | ||||
|         KeysetHandle privateKeysetHandle = KeysetHandle.generateNew( | ||||
|                 HybridKeyTemplates.ECIES_P256_HKDF_HMAC_SHA256_AES128_CTR_HMAC_SHA256); | ||||
| 
 | ||||
|         KeysetHandle publicKeysetHandle = privateKeysetHandle.getPublicKeysetHandle(); | ||||
| 
 | ||||
|         HybridEncrypt hybridEncrypt = HybridEncryptFactory.getPrimitive(publicKeysetHandle); | ||||
| 
 | ||||
|         HybridDecrypt hybridDecrypt = HybridDecryptFactory.getPrimitive(privateKeysetHandle); | ||||
| 
 | ||||
|         String contextInfo = "Tink"; | ||||
| 
 | ||||
|         byte[] ciphertext = hybridEncrypt.encrypt(PLAINTEXT.getBytes(), contextInfo.getBytes()); | ||||
| 
 | ||||
|         byte[] plaintextDecrypted = hybridDecrypt.decrypt(ciphertext, contextInfo.getBytes()); | ||||
| 
 | ||||
|         Assert.assertEquals(PLAINTEXT,new String(plaintextDecrypted)); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| @ -3,7 +3,7 @@ | ||||
| - [Embedded Jetty Server in Java](http://www.baeldung.com/jetty-embedded) | ||||
| - [Introduction to Netty](http://www.baeldung.com/netty) | ||||
| - [Exceptions in Netty](http://www.baeldung.com/netty-exception-handling) | ||||
| - [Programatically Create, Configure, and Run a Tomcat Server](http://www.baeldung.com/tomcat-programmatic-setup) | ||||
| - [Programmatically Create, Configure and Run a Tomcat Server](http://www.baeldung.com/tomcat-programmatic-setup) | ||||
| - [Creating and Configuring Jetty 9 Server in Java](http://www.baeldung.com/jetty-java-programmatic) | ||||
| - [Testing Netty with EmbeddedChannel](http://www.baeldung.com/testing-netty-embedded-channel) | ||||
| - [MQTT Client in Java](https://www.baeldung.com/java-mqtt-client) | ||||
|  | ||||
| @ -6,7 +6,7 @@ | ||||
| - [Introduction to Apache Flink with Java](http://www.baeldung.com/apache-flink) | ||||
| - [Introduction to JSONassert](http://www.baeldung.com/jsonassert) | ||||
| - [Intro to JaVers](http://www.baeldung.com/javers) | ||||
| - [Intro to Serenity BDD](http://www.baeldung.com/serenity-bdd) | ||||
| - [Introduction to Serenity BDD](http://www.baeldung.com/serenity-bdd) | ||||
| - [Merging Streams in Java](http://www.baeldung.com/java-merge-streams) | ||||
| - [Serenity BDD and Screenplay](http://www.baeldung.com/serenity-screenplay) | ||||
| - [Introduction to Quartz](http://www.baeldung.com/quartz) | ||||
| @ -14,14 +14,14 @@ | ||||
| - [Software Transactional Memory in Java Using Multiverse](http://www.baeldung.com/java-multiverse-stm) | ||||
| - [Serenity BDD with Spring and JBehave](http://www.baeldung.com/serenity-spring-jbehave) | ||||
| - [Locality-Sensitive Hashing in Java Using Java-LSH](http://www.baeldung.com/locality-sensitive-hashing) | ||||
| - [Introduction to Awaitility](http://www.baeldung.com/awaitlity-testing) | ||||
| - [Introduction to Awaitlity](http://www.baeldung.com/awaitlity-testing) | ||||
| - [Guide to the HyperLogLog Algorithm](http://www.baeldung.com/java-hyperloglog) | ||||
| - [Introduction to Neuroph](http://www.baeldung.com/neuroph) | ||||
| - [Quick Guide to RSS with Rome](http://www.baeldung.com/rome-rss) | ||||
| - [Introduction to PCollections](http://www.baeldung.com/java-pcollections) | ||||
| - [Introduction to Hoverfly in Java](http://www.baeldung.com/hoverfly) | ||||
| - [Introduction to Eclipse Collections](http://www.baeldung.com/eclipse-collections) | ||||
| - [DistinctBy in Java Stream API](http://www.baeldung.com/java-streams-distinct-by) | ||||
| - [DistinctBy in the Java Stream API](http://www.baeldung.com/java-streams-distinct-by) | ||||
| - [Introduction to NoException](http://www.baeldung.com/no-exception) | ||||
| - [Introduction to Conflict-Free Replicated Data Types](http://www.baeldung.com/java-conflict-free-replicated-data-types) | ||||
| - [Introduction to javax.measure](http://www.baeldung.com/javax-measure) | ||||
| @ -36,7 +36,7 @@ | ||||
| - [Introduction To Docx4J](http://www.baeldung.com/docx4j) | ||||
| - [Introduction to StreamEx](http://www.baeldung.com/streamex) | ||||
| - [Introduction to BouncyCastle with Java](http://www.baeldung.com/java-bouncy-castle) | ||||
| - [Guide to google-http-client](http://www.baeldung.com/google-http-client) | ||||
| - [A Guide to Google-Http-Client](http://www.baeldung.com/google-http-client) | ||||
| - [Interact with Google Sheets from Java](http://www.baeldung.com/google-sheets-java-client) | ||||
| - [A Docker Guide for Java](http://www.baeldung.com/docker-java-api) | ||||
| - [Introduction To OpenCSV](http://www.baeldung.com/opencsv) | ||||
|  | ||||
| @ -4,5 +4,4 @@ | ||||
| ### Relevant Articles: | ||||
| 
 | ||||
| - [Creating a Custom Logback Appender](http://www.baeldung.com/custom-logback-appender) | ||||
| - [Get Log Output in JSON Format](http://www.baeldung.com/java-log-json-output) | ||||
| - [A Guide To Logback](http://www.baeldung.com/logback) | ||||
|  | ||||
| @ -4,3 +4,4 @@ | ||||
| - [Log4j 2 and Lambda Expressions](http://www.baeldung.com/log4j-2-lazy-logging) | ||||
| - [Programmatic Configuration with Log4j 2](http://www.baeldung.com/log4j2-programmatic-config) | ||||
| - [Creating a Custom Log4j2 Appender](https://www.baeldung.com/log4j2-custom-appender) | ||||
| - [Get Log Output in JSON](http://www.baeldung.com/java-log-json-output) | ||||
|  | ||||
| @ -0,0 +1,3 @@ | ||||
| ### Relevant Articles: | ||||
| 
 | ||||
| - [Get Log Output in JSON](https://www.baeldung.com/java-log-json-output) | ||||
| @ -3,3 +3,4 @@ | ||||
| - [Introduction to Intercepting Filter Pattern in Java](http://www.baeldung.com/intercepting-filter-pattern-in-java) | ||||
| - [Introduction to the Null Object Pattern](https://www.baeldung.com/java-null-object-pattern) | ||||
| - [The Dependency Inversion Principle in Java](https://www.baeldung.com/java-dependency-inversion-principle) | ||||
| - [Avoid Check for Null Statement in Java](https://www.baeldung.com/java-avoid-null-check) | ||||
|  | ||||
| @ -19,4 +19,4 @@ | ||||
| - [The Command Pattern in Java](http://www.baeldung.com/java-command-pattern) | ||||
| - [Java Constructors vs Static Factory Methods](https://www.baeldung.com/java-constructors-vs-static-factory-methods) | ||||
| - [The Adapter Pattern in Java](https://www.baeldung.com/java-adapter-pattern) | ||||
| - [Currying in Java](https://baeldung.com/currying-in-java) | ||||
| - [Currying in Java](https://www.baeldung.com/java-currying) | ||||
|  | ||||
| @ -1,5 +1,5 @@ | ||||
| ### Relevant Articles: | ||||
| 
 | ||||
| - [A Guide to Solid Principles](https://www.baeldung.com/solid-principles) | ||||
| - [A Solid Guide to Solid Principles](https://www.baeldung.com/solid-principles) | ||||
| 
 | ||||
| 
 | ||||
|  | ||||
| @ -11,3 +11,5 @@ | ||||
| - [Pessimistic Locking in JPA](http://www.baeldung.com/jpa-pessimistic-locking) | ||||
| - [Get All Data from a Table with Hibernate](https://www.baeldung.com/hibernate-select-all) | ||||
| - [Spring Data with Reactive Cassandra](https://www.baeldung.com/spring-data-cassandra-reactive) | ||||
| - [Spring Data JPA – Derived Delete Methods](https://www.baeldung.com/spring-data-jpa-deleteby) | ||||
| - [Difference Between save() and saveAndFlush() in Spring Data JPA](https://www.baeldung.com/spring-data-jpa-save-saveandflush) | ||||
|  | ||||
| @ -6,15 +6,21 @@ | ||||
|     <version>0.1.0-SNAPSHOT</version> | ||||
|     <name>core-java-persistence</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>org.postgresql</groupId> | ||||
|             <artifactId>postgresql</artifactId> | ||||
|             <version>${postgresql.version}</version> | ||||
|             <scope>test</scope> | ||||
|         </dependency> | ||||
|         <dependency> | ||||
|             <groupId>org.assertj</groupId> | ||||
|             <artifactId>assertj-core</artifactId> | ||||
| @ -52,7 +58,7 @@ | ||||
|             <version>${springframework.boot.spring-boot-starter.version}</version> | ||||
|         </dependency> | ||||
|     </dependencies> | ||||
|     	 | ||||
| 
 | ||||
|     <build> | ||||
|         <finalName>core-java-persistence</finalName> | ||||
|         <resources> | ||||
| @ -62,8 +68,10 @@ | ||||
|             </resource> | ||||
|         </resources> | ||||
|     </build> | ||||
|     	 | ||||
| 
 | ||||
|     <properties> | ||||
|         <postgresql.version>42.2.5.jre7</postgresql.version> | ||||
|         <mysql-connector.version>8.0.15</mysql-connector.version> | ||||
|         <assertj-core.version>3.10.0</assertj-core.version> | ||||
|         <h2database.version>1.4.197</h2database.version> | ||||
|         <commons-dbcp2.version>2.4.0</commons-dbcp2.version> | ||||
| @ -72,5 +80,5 @@ | ||||
|         <springframework.boot.spring-boot-starter.version>1.5.8.RELEASE</springframework.boot.spring-boot-starter.version> | ||||
|         <springframework.spring-web.version>4.3.4.RELEASE</springframework.spring-web.version> | ||||
|     </properties> | ||||
|     	 | ||||
| 
 | ||||
| </project> | ||||
| @ -0,0 +1,41 @@ | ||||
| package com.baeldung.jdbc.joins; | ||||
| 
 | ||||
| class ArticleWithAuthor { | ||||
| 
 | ||||
|         private String title; | ||||
| 
 | ||||
|         private String authorFirstName; | ||||
| 
 | ||||
|         private String authorLastName; | ||||
| 
 | ||||
|         public ArticleWithAuthor(String title, String authorFirstName, String authorLastName) { | ||||
|                 this.title = title; | ||||
|                 this.authorFirstName = authorFirstName; | ||||
|                 this.authorLastName = authorLastName; | ||||
|         } | ||||
| 
 | ||||
|         public String getTitle() { | ||||
|                 return title; | ||||
|         } | ||||
| 
 | ||||
|         public void setTitle(String title) { | ||||
|                 this.title = title; | ||||
|         } | ||||
| 
 | ||||
|         public String getAuthorFirstName() { | ||||
|                 return authorFirstName; | ||||
|         } | ||||
| 
 | ||||
|         public void setAuthorFirstName(String authorFirstName) { | ||||
|                 this.authorFirstName = authorFirstName; | ||||
|         } | ||||
| 
 | ||||
|         public String getAuthorLastName() { | ||||
|                 return authorLastName; | ||||
|         } | ||||
| 
 | ||||
|         public void setAuthorLastName(String authorLastName) { | ||||
|                 this.authorLastName = authorLastName; | ||||
|         } | ||||
| 
 | ||||
| } | ||||
| @ -0,0 +1,61 @@ | ||||
| package com.baeldung.jdbc.joins; | ||||
| 
 | ||||
| import java.sql.Connection; | ||||
| import java.sql.ResultSet; | ||||
| import java.sql.SQLException; | ||||
| import java.sql.Statement; | ||||
| import java.util.ArrayList; | ||||
| import java.util.List; | ||||
| 
 | ||||
| class ArticleWithAuthorDAO { | ||||
| 
 | ||||
|         private static final String QUERY_TEMPLATE = "SELECT ARTICLE.TITLE, AUTHOR.LAST_NAME, AUTHOR.FIRST_NAME FROM ARTICLE %s AUTHOR ON AUTHOR.id=ARTICLE.AUTHOR_ID"; | ||||
|         private final Connection connection; | ||||
| 
 | ||||
|         ArticleWithAuthorDAO(Connection connection) { | ||||
|                 this.connection = connection; | ||||
|         } | ||||
| 
 | ||||
|         List<ArticleWithAuthor> articleInnerJoinAuthor() { | ||||
|                 String query = String.format(QUERY_TEMPLATE, "INNER JOIN"); | ||||
|                 return executeQuery(query); | ||||
|         } | ||||
| 
 | ||||
|         List<ArticleWithAuthor> articleLeftJoinAuthor() { | ||||
|                 String query = String.format(QUERY_TEMPLATE, "LEFT JOIN"); | ||||
|                 return executeQuery(query); | ||||
|         } | ||||
| 
 | ||||
|         List<ArticleWithAuthor> articleRightJoinAuthor() { | ||||
|                 String query = String.format(QUERY_TEMPLATE, "RIGHT JOIN"); | ||||
|                 return executeQuery(query); | ||||
|         } | ||||
| 
 | ||||
|         List<ArticleWithAuthor> articleFullJoinAuthor() { | ||||
|                 String query = String.format(QUERY_TEMPLATE, "FULL JOIN"); | ||||
|                 return executeQuery(query); | ||||
|         } | ||||
| 
 | ||||
|         private List<ArticleWithAuthor> executeQuery(String query) { | ||||
|                 try (Statement statement = connection.createStatement()) { | ||||
|                         ResultSet resultSet = statement.executeQuery(query); | ||||
|                         return mapToList(resultSet); | ||||
|                 } catch (SQLException e) { | ||||
|                         e.printStackTrace(); | ||||
|                 } | ||||
|                 return null; | ||||
|         } | ||||
| 
 | ||||
|         private List<ArticleWithAuthor> mapToList(ResultSet resultSet) throws SQLException { | ||||
|                 List<ArticleWithAuthor> list = new ArrayList<>(); | ||||
|                 while (resultSet.next()) { | ||||
|                         ArticleWithAuthor articleWithAuthor = new ArticleWithAuthor( | ||||
|                             resultSet.getString("TITLE"), | ||||
|                             resultSet.getString("FIRST_NAME"), | ||||
|                             resultSet.getString("LAST_NAME") | ||||
|                         ); | ||||
|                         list.add(articleWithAuthor); | ||||
|                 } | ||||
|                 return list; | ||||
|         } | ||||
| } | ||||
| @ -0,0 +1,89 @@ | ||||
| package com.baeldung.jdbc.joins; | ||||
| 
 | ||||
| import org.junit.After; | ||||
| import org.junit.Before; | ||||
| import org.junit.Test; | ||||
| 
 | ||||
| import java.sql.Connection; | ||||
| import java.sql.DriverManager; | ||||
| import java.sql.SQLException; | ||||
| import java.sql.Statement; | ||||
| import java.util.List; | ||||
| 
 | ||||
| import static org.assertj.core.api.Assertions.assertThat; | ||||
| 
 | ||||
| public class ArticleWithAuthorDAOIntegrationTest { | ||||
|         private Connection connection; | ||||
| 
 | ||||
|         private ArticleWithAuthorDAO articleWithAuthorDAO; | ||||
| 
 | ||||
|         @Before | ||||
|         public void setup() throws ClassNotFoundException, SQLException { | ||||
|                 Class.forName("org.postgresql.Driver"); | ||||
|                 connection = DriverManager.getConnection("jdbc:postgresql://localhost:5432/myDb", "user", "pass"); | ||||
|                 articleWithAuthorDAO = new ArticleWithAuthorDAO(connection); | ||||
|                 Statement statement = connection.createStatement(); | ||||
|                 String createAuthorSql = "CREATE TABLE IF NOT EXISTS AUTHOR (ID int NOT NULL PRIMARY KEY, FIRST_NAME varchar(255), LAST_NAME varchar(255));"; | ||||
|                 String createArticleSql = "CREATE TABLE IF NOT EXISTS ARTICLE (ID int NOT NULL PRIMARY KEY, TITLE varchar(255) NOT NULL, AUTHOR_ID int, FOREIGN KEY(AUTHOR_ID) REFERENCES AUTHOR(ID));"; | ||||
|                 statement.execute(createAuthorSql); | ||||
|                 statement.execute(createArticleSql); | ||||
| 
 | ||||
|                 insertTestData(statement); | ||||
|         } | ||||
| 
 | ||||
|         @Test | ||||
|         public void whenQueryWithInnerJoin_thenShouldReturnProperRows() { | ||||
|                 List<ArticleWithAuthor> articleWithAuthorList = articleWithAuthorDAO.articleInnerJoinAuthor(); | ||||
| 
 | ||||
|                 assertThat(articleWithAuthorList).hasSize(4); | ||||
|                 assertThat(articleWithAuthorList).noneMatch(row -> row.getAuthorFirstName() == null || row.getTitle() == null); | ||||
|         } | ||||
| 
 | ||||
|         @Test | ||||
|         public void whenQueryWithLeftJoin_thenShouldReturnProperRows() { | ||||
|                 List<ArticleWithAuthor> articleWithAuthorList = articleWithAuthorDAO.articleLeftJoinAuthor(); | ||||
| 
 | ||||
|                 assertThat(articleWithAuthorList).hasSize(5); | ||||
|                 assertThat(articleWithAuthorList).anyMatch(row -> row.getAuthorFirstName() == null); | ||||
|         } | ||||
| 
 | ||||
|         @Test | ||||
|         public void whenQueryWithRightJoin_thenShouldReturnProperRows() { | ||||
|                 List<ArticleWithAuthor> articleWithAuthorList = articleWithAuthorDAO.articleRightJoinAuthor(); | ||||
| 
 | ||||
|                 assertThat(articleWithAuthorList).hasSize(5); | ||||
|                 assertThat(articleWithAuthorList).anyMatch(row -> row.getTitle() == null); | ||||
|         } | ||||
| 
 | ||||
|         @Test | ||||
|         public void whenQueryWithFullJoin_thenShouldReturnProperRows() { | ||||
|                 List<ArticleWithAuthor> articleWithAuthorList = articleWithAuthorDAO.articleFullJoinAuthor(); | ||||
| 
 | ||||
|                 assertThat(articleWithAuthorList).hasSize(6); | ||||
|                 assertThat(articleWithAuthorList).anyMatch(row -> row.getTitle() == null); | ||||
|                 assertThat(articleWithAuthorList).anyMatch(row -> row.getAuthorFirstName() == null); | ||||
|         } | ||||
| 
 | ||||
|         @After | ||||
|         public void cleanup() throws SQLException { | ||||
|                 connection.createStatement().execute("DROP TABLE ARTICLE"); | ||||
|                 connection.createStatement().execute("DROP TABLE AUTHOR"); | ||||
|                 connection.close(); | ||||
|         } | ||||
| 
 | ||||
|         public void insertTestData(Statement statement) throws SQLException { | ||||
|                 String insertAuthors = "INSERT INTO AUTHOR VALUES " | ||||
|                     + "(1, 'Siena', 'Kerr')," | ||||
|                     + "(2, 'Daniele', 'Ferguson')," | ||||
|                     + "(3, 'Luciano', 'Wise')," | ||||
|                     + "(4, 'Jonas', 'Lugo');"; | ||||
|                 String insertArticles = "INSERT INTO ARTICLE VALUES " | ||||
|                     + "(1, 'First steps in Java', 1)," | ||||
|                     + "(2, 'SpringBoot tutorial', 1)," | ||||
|                     + "(3, 'Java 12 insights', null)," | ||||
|                     + "(4, 'SQL JOINS', 2)," | ||||
|                     + "(5, 'Introduction to Spring Security', 3);"; | ||||
|                 statement.execute(insertAuthors); | ||||
|                 statement.execute(insertArticles); | ||||
|         } | ||||
| } | ||||
| @ -32,3 +32,4 @@ | ||||
| - [Common Hibernate Exceptions](https://www.baeldung.com/hibernate-exceptions) | ||||
| - [Hibernate Aggregate Functions](https://www.baeldung.com/hibernate-aggregate-functions) | ||||
| - [Hibernate Query Plan Cache](https://www.baeldung.com/hibernate-query-plan-cache) | ||||
| - [TransactionRequiredException Error](https://www.baeldung.com/jpa-transaction-required-exception) | ||||
|  | ||||
| @ -2,7 +2,7 @@ | ||||
| 
 | ||||
| - [A Guide to SqlResultSetMapping](http://www.baeldung.com/jpa-sql-resultset-mapping) | ||||
| - [A Guide to Stored Procedures with JPA](http://www.baeldung.com/jpa-stored-procedures) | ||||
| - [Fixing the JPA error “java.lang.String cannot be cast to Ljava.lang.String;”](https://www.baeldung.com/jpa-error-java-lang-string-cannot-be-cast)  | ||||
| - [Fixing the JPA error “java.lang.String cannot be cast to [Ljava.lang.String;”]](https://www.baeldung.com/jpa-error-java-lang-string-cannot-be-cast)  | ||||
| - [JPA Entity Graph](https://www.baeldung.com/jpa-entity-graph) | ||||
| - [JPA 2.2 Support for Java 8 Date/Time Types](https://www.baeldung.com/jpa-java-time) | ||||
| - [Converting Between LocalDate and SQL Date](https://www.baeldung.com/java-convert-localdate-sql-date) | ||||
|  | ||||
| @ -0,0 +1,12 @@ | ||||
| package com.baeldung.h2db.springboot; | ||||
| 
 | ||||
| import org.springframework.boot.SpringApplication; | ||||
| import org.springframework.boot.autoconfigure.SpringBootApplication; | ||||
| 
 | ||||
| @SpringBootApplication | ||||
| public class SpringBootH2Application { | ||||
| 
 | ||||
|     public static void main(String... args) { | ||||
|         SpringApplication.run(SpringBootH2Application.class, args); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,10 @@ | ||||
| package com.baeldung.h2db.springboot.daos; | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| import com.baeldung.h2db.springboot.models.User; | ||||
| import org.springframework.data.repository.CrudRepository; | ||||
| 
 | ||||
| public interface UserRepository extends CrudRepository<User, Integer> { | ||||
| } | ||||
| @ -0,0 +1,54 @@ | ||||
| package com.baeldung.h2db.springboot.models; | ||||
| 
 | ||||
| import javax.persistence.Entity; | ||||
| import javax.persistence.GeneratedValue; | ||||
| import javax.persistence.Id; | ||||
| import javax.persistence.Table; | ||||
| 
 | ||||
| @Table(name = "users") | ||||
| @Entity | ||||
| public class User { | ||||
| 
 | ||||
|     @Id | ||||
|     @GeneratedValue | ||||
|     private int id; | ||||
| 
 | ||||
|     private String firstName; | ||||
| 
 | ||||
|     private String lastName; | ||||
| 
 | ||||
|     public User() { } | ||||
| 
 | ||||
|     public int getId() { | ||||
|         return id; | ||||
|     } | ||||
| 
 | ||||
|     public void setId(int id) { | ||||
|         this.id = id; | ||||
|     } | ||||
| 
 | ||||
|     public String getFirstName() { | ||||
|         return firstName; | ||||
|     } | ||||
| 
 | ||||
|     public void setFirstName(String firstName) { | ||||
|         this.firstName = firstName; | ||||
|     } | ||||
| 
 | ||||
|     public String getLastName() { | ||||
|         return lastName; | ||||
|     } | ||||
| 
 | ||||
|     public void setLastName(String lastName) { | ||||
|         this.lastName = lastName; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public String toString() { | ||||
|         return "User{" + | ||||
|                 "id=" + id + | ||||
|                 ", firstName='" + firstName + '\'' + | ||||
|                 ", lastName='" + lastName + '\'' + | ||||
|                 '}'; | ||||
|     } | ||||
| } | ||||
| @ -2,7 +2,7 @@ spring.datasource.url=jdbc:h2:mem:mydb | ||||
| spring.datasource.driverClassName=org.h2.Driver | ||||
| spring.datasource.username=sa | ||||
| spring.datasource.password= | ||||
| spring.jpa.hibernate.ddl-auto=create | ||||
| spring.jpa.hibernate.ddl-auto=create-drop | ||||
| spring.h2.console.enabled=true | ||||
| spring.h2.console.path=/h2-console | ||||
| debug=true | ||||
| @ -0,0 +1,50 @@ | ||||
| package com.baeldung; | ||||
| 
 | ||||
| import com.baeldung.h2db.springboot.SpringBootH2Application; | ||||
| import com.baeldung.h2db.springboot.daos.UserRepository; | ||||
| import com.baeldung.h2db.springboot.models.User; | ||||
| import org.junit.Test; | ||||
| import org.junit.runner.RunWith; | ||||
| import org.springframework.beans.factory.annotation.Autowired; | ||||
| import org.springframework.boot.test.context.SpringBootTest; | ||||
| import org.springframework.test.context.junit4.SpringRunner; | ||||
| 
 | ||||
| import java.util.List; | ||||
| 
 | ||||
| import static org.junit.Assert.*; | ||||
| 
 | ||||
| @RunWith(SpringRunner.class) | ||||
| @SpringBootTest(classes = SpringBootH2Application.class) | ||||
| public class SpringBootH2IntegrationTest { | ||||
| 
 | ||||
|     @Autowired | ||||
|     private UserRepository userRepository; | ||||
| 
 | ||||
|     @Test | ||||
|     public void contextLoads() { } | ||||
| 
 | ||||
|     @Test | ||||
|     public void givenUserProfile_whenAddUser_thenCreateNewUser() { | ||||
|         User user = new User(); | ||||
|         user.setFirstName("John"); | ||||
|         user.setLastName("Doe"); | ||||
|         userRepository.save(user); | ||||
|         List<User> users = (List<User>) userRepository.findAll(); | ||||
|         assertFalse(users.isEmpty()); | ||||
| 
 | ||||
|         String firstName = "Aliko"; | ||||
|         String lastName = "Dangote"; | ||||
|         User user1 = userRepository.findById(users.get(0).getId()).get(); | ||||
|         user1.setLastName(lastName); | ||||
|         user1.setFirstName(firstName); | ||||
|         userRepository.save(user1); | ||||
| 
 | ||||
|         user = userRepository.findById(user.getId()).get(); | ||||
|         assertEquals(user.getFirstName(), firstName); | ||||
|         assertEquals(user.getLastName(), lastName); | ||||
| 
 | ||||
|         userRepository.deleteById(user.getId()); | ||||
|         assertTrue( ((List<User>) userRepository.findAll()).isEmpty()); | ||||
|     } | ||||
| 
 | ||||
| } | ||||
| @ -8,3 +8,4 @@ | ||||
| - [Integrating Spring Boot with HSQLDB](https://www.baeldung.com/spring-boot-hsqldb) | ||||
| - [Configuring a DataSource Programmatically in Spring Boot](https://www.baeldung.com/spring-boot-configure-data-source-programmatic) | ||||
| - [Resolving “Failed to Configure a DataSource” Error](https://www.baeldung.com/spring-boot-failed-to-configure-data-source) | ||||
| - [Spring Boot with Hibernate](https://www.baeldung.com/spring-boot-hibernate) | ||||
|  | ||||
| @ -2,7 +2,7 @@ | ||||
| 
 | ||||
| ### Relevant Articles: | ||||
| - [Intro to Spring Data Couchbase](http://www.baeldung.com/spring-data-couchbase) | ||||
| - [Entity Validation, Query Consistency, and Optimistic Locking in Spring Data Couchbase](http://www.baeldung.com/entity-validation-locking-and-query-consistency-in-spring-data-couchbase) | ||||
| - [Entity Validation, Optimistic Locking, and Query Consistency in Spring Data Couchbase](http://www.baeldung.com/entity-validation-locking-and-query-consistency-in-spring-data-couchbase) | ||||
| - [Multiple Buckets and Spatial View Queries in Spring Data Couchbase](http://www.baeldung.com/spring-data-couchbase-buckets-and-spatial-view-queries) | ||||
| 
 | ||||
| ### Overview | ||||
|  | ||||
| @ -3,3 +3,4 @@ | ||||
| ## Spring Data JPA Example Project | ||||
| 
 | ||||
| ### Relevant Articles:  | ||||
| - [Spring Data JPA – Derived Delete Methods](https://www.baeldung.com/spring-data-jpa-deleteby) | ||||
|  | ||||
| @ -1,4 +1,4 @@ | ||||
| package com.baeldung.customer; | ||||
| package com.baeldung.entity; | ||||
| 
 | ||||
| import javax.persistence.Entity; | ||||
| import javax.persistence.GeneratedValue; | ||||
| @ -1,5 +1,6 @@ | ||||
| package com.baeldung.customer; | ||||
| package com.baeldung.repository; | ||||
| 
 | ||||
| import com.baeldung.entity.Customer; | ||||
| import org.springframework.data.jpa.repository.JpaRepository; | ||||
| import org.springframework.data.jpa.repository.Query; | ||||
| import org.springframework.data.repository.query.Param; | ||||
| @ -4,6 +4,7 @@ import static org.assertj.core.api.Assertions.assertThat; | ||||
| 
 | ||||
| import com.baeldung.joins.model.Department; | ||||
| import com.baeldung.joins.model.Phone; | ||||
| import java.util.Collection; | ||||
| import java.util.List; | ||||
| import javax.persistence.EntityManager; | ||||
| import javax.persistence.PersistenceContext; | ||||
| @ -79,11 +80,11 @@ public class JpaJoinsIntegrationTest { | ||||
| 
 | ||||
|     @Test | ||||
|     public void whenCollectionValuedAssociationIsJoined_ThenCanSelect() { | ||||
|         TypedQuery<Phone> query = entityManager.createQuery("SELECT ph FROM Employee e JOIN e.phones ph ", Phone.class); | ||||
|         TypedQuery<Phone> query = entityManager.createQuery("SELECT ph FROM Employee e JOIN e.phones ph WHERE ph LIKE '1%'", Phone.class); | ||||
| 
 | ||||
|         List<Phone> resultList = query.getResultList(); | ||||
| 
 | ||||
|         assertThat(resultList).hasSize(3); | ||||
|         assertThat(resultList).hasSize(1); | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
| @ -122,9 +123,20 @@ public class JpaJoinsIntegrationTest { | ||||
|     @Test | ||||
|     public void whenLeftAndFetchKeywordsAreSpecified_ThenCreatesOuterFetchJoin() { | ||||
|         TypedQuery<Department> query = entityManager.createQuery("SELECT d FROM Department d LEFT JOIN FETCH d.employees", Department.class); | ||||
| 
 | ||||
|         List<Department> resultList = query.getResultList(); | ||||
| 
 | ||||
|         assertThat(resultList).hasSize(4); | ||||
|         assertThat(resultList).extracting("name") | ||||
|             .containsOnly("Infra", "Accounting", "Accounting", "Management"); | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     public void whenCollectionValuedAssociationIsSpecifiedInSelect_ThenReturnsCollections() { | ||||
|         TypedQuery<Collection> query = entityManager.createQuery("SELECT e.phones FROM Employee e", Collection.class); | ||||
| 
 | ||||
|         List<Collection> resultList = query.getResultList(); | ||||
| 
 | ||||
|         assertThat(resultList).extracting("number").containsOnly("111", "222", "333"); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -1,8 +1,6 @@ | ||||
| package com.baeldung.customer; | ||||
| package com.baeldung.repository; | ||||
| 
 | ||||
| import com.baeldung.config.PersistenceConfiguration; | ||||
| import com.baeldung.config.PersistenceProductConfiguration; | ||||
| import com.baeldung.config.PersistenceUserConfiguration; | ||||
| import com.baeldung.entity.Customer; | ||||
| import org.junit.After; | ||||
| import org.junit.Before; | ||||
| import org.junit.Test; | ||||
| @ -17,7 +15,7 @@ import java.util.List; | ||||
| 
 | ||||
| import static org.junit.Assert.assertEquals; | ||||
| 
 | ||||
| @DataJpaTest(excludeAutoConfiguration = { PersistenceConfiguration.class, PersistenceUserConfiguration.class, PersistenceProductConfiguration.class }) | ||||
| @DataJpaTest | ||||
| @RunWith(SpringRunner.class) | ||||
| public class CustomerRepositoryIntegrationTest { | ||||
| 
 | ||||
| @ -5,7 +5,7 @@ | ||||
| ### Relevant Articles:  | ||||
| - [Spring JPA – Multiple Databases](http://www.baeldung.com/spring-data-jpa-multiple-databases) | ||||
| - [Spring Data JPA – Adding a Method in All Repositories](http://www.baeldung.com/spring-data-jpa-method-in-all-repositories) | ||||
| - [Advanced Tagging Implementation with JPA](http://www.baeldung.com/jpa-tagging-advanced) | ||||
| - [An Advanced Tagging Implementation with JPA](http://www.baeldung.com/jpa-tagging-advanced) | ||||
| - [Spring Data JPA @Query](http://www.baeldung.com/spring-data-jpa-query) | ||||
| - [Spring Data Annotations](http://www.baeldung.com/spring-data-annotations) | ||||
| - [Spring Data Java 8 Support](http://www.baeldung.com/spring-data-java-8) | ||||
|  | ||||
							
								
								
									
										19
									
								
								pom.xml
									
									
									
									
									
								
							
							
						
						
									
										19
									
								
								pom.xml
									
									
									
									
									
								
							| @ -381,10 +381,12 @@ | ||||
|                 <!-- <module>core-java-12</module> --> <!-- We haven't upgraded to java 12. Fixing in BAEL-10841 --> | ||||
|                 <module>core-java-8</module> | ||||
|                 <module>core-java-8-2</module> | ||||
| 		<module>core-java-lambdas</module> | ||||
|                 <!--<module>core-java-9</module> --> <!-- We haven't upgraded to java 9. Fixing in BAEL-10841 --> | ||||
|                 <!--<module>core-java-os</module> --> <!-- We haven't upgraded to java 9.--> | ||||
|                 <module>core-java-arrays</module> | ||||
|                 <module>core-java-collections</module> | ||||
|                 <module>core-java-collections-map</module> | ||||
|                 <module>core-java-collections-list</module> | ||||
|                 <module>core-java-concurrency-basic</module> | ||||
|                 <module>core-java-concurrency-collections</module> | ||||
| @ -538,7 +540,8 @@ | ||||
| 			    <module>software-security/sql-injection-samples</module> | ||||
| 				 | ||||
| 				<module>tensorflow-java</module> | ||||
| 				 | ||||
| 				<module>spring-boot-flowable</module> | ||||
| 					 | ||||
| 			</modules> | ||||
| 
 | ||||
| 		</profile> | ||||
| @ -584,6 +587,7 @@ | ||||
|                  | ||||
|                 <module>spring-5</module> | ||||
|                 <module>spring-5-webflux</module> | ||||
|                 <module>spring-5-data-reactive</module> | ||||
|                 <module>spring-5-mvc</module> | ||||
|                 <module>spring-5-reactive</module> | ||||
|                 <module>spring-5-reactive-client</module> | ||||
| @ -596,6 +600,7 @@ | ||||
|                 <module>spring-akka</module> | ||||
|                 <module>spring-all</module> | ||||
|                 <module>spring-amqp</module> | ||||
|                 <module>spring-amqp-simple</module> | ||||
|                 <module>spring-aop</module> | ||||
|                 <module>spring-apache-camel</module> | ||||
|                 <module>spring-batch</module> | ||||
| @ -762,6 +767,7 @@ | ||||
|                 <module>xstream</module> | ||||
| 				 | ||||
| 				<module>tensorflow-java</module> | ||||
| 				<module>spring-boot-flowable</module> | ||||
|                  | ||||
|             </modules> | ||||
| 
 | ||||
| @ -904,6 +910,8 @@ | ||||
| 				<module>persistence-modules/spring-data-eclipselink</module> | ||||
| 				<module>persistence-modules/spring-data-solr</module> | ||||
| 				<module>persistence-modules/spring-hibernate-5</module> | ||||
| 				 | ||||
| 				<module>spring-boot-flowable</module> | ||||
| 			</modules> | ||||
| 
 | ||||
| 		</profile> | ||||
| @ -956,9 +964,6 @@ | ||||
|                 <module>persistence-modules/java-mongodb</module> | ||||
|                 <module>persistence-modules/jnosql</module>              | ||||
| 
 | ||||
|                 <module>spring-5-data-reactive</module> <!-- very long running. Fixing in BAEL-10891  --> | ||||
|                 <module>spring-amqp-simple</module> <!-- very long running. Fixing in BAEL-10891 --> | ||||
|                  | ||||
|                 <module>vaadin</module>             | ||||
|             </modules> | ||||
|         </profile> | ||||
| @ -1041,6 +1046,7 @@ | ||||
|                 <!--<module>core-java-os</module> --> <!-- We haven't upgraded to java 9.--> | ||||
|                 <module>core-java-arrays</module> | ||||
|                 <module>core-java-collections</module> | ||||
|                 <module>core-java-collections-map</module> | ||||
|                 <module>core-java-collections-list</module> | ||||
|                 <module>core-java-concurrency-basic</module> | ||||
|                 <module>core-java-concurrency-collections</module> | ||||
| @ -1228,6 +1234,7 @@ | ||||
|                 <module>spring-4</module> | ||||
|                  | ||||
|                 <module>spring-5</module> | ||||
|                 <module>spring-5-data-reactive</module> | ||||
|                 <module>spring-5-mvc</module> | ||||
|                 <module>spring-5-reactive</module> | ||||
|                 <module>spring-5-reactive-client</module> | ||||
| @ -1240,6 +1247,7 @@ | ||||
|                 <module>spring-akka</module> | ||||
|                 <module>spring-all</module> | ||||
|                 <module>spring-amqp</module> | ||||
|                 <module>spring-amqp-simple</module> | ||||
|                 <module>spring-aop</module> | ||||
|                 <module>spring-apache-camel</module> | ||||
|                 <module>spring-batch</module> | ||||
| @ -1452,9 +1460,6 @@ | ||||
|                 <module>persistence-modules/java-mongodb</module> | ||||
|                 <module>persistence-modules/jnosql</module>              | ||||
| 
 | ||||
|                 <module>spring-5-data-reactive</module> <!-- very long running. Fixing in BAEL-10891  --> | ||||
|                 <module>spring-amqp-simple</module> <!-- very long running. Fixing in BAEL-10891 --> | ||||
|                  | ||||
|                 <module>vaadin</module>             | ||||
|             </modules> | ||||
| 
 | ||||
|  | ||||
| @ -2,8 +2,8 @@ | ||||
| 
 | ||||
| - [RxJava and Error Handling](http://www.baeldung.com/rxjava-error-handling) | ||||
| - [RxJava 2 – Flowable](http://www.baeldung.com/rxjava-2-flowable) | ||||
| - [RxJava 2 - Completable](http://www.baeldung.com/rxjava-completable) | ||||
| - [RxJava Maybe](http://www.baeldung.com/rxjava-maybe) | ||||
| - [Introduction to RxRelay for RxJava](http://www.baeldung.com/rx-relay) | ||||
| - [Combining RxJava Completables](https://www.baeldung.com/rxjava-completable) | ||||
| - [Converting Synchronous and Asynchronous APIs to Observables using RxJava2](https://www.baeldung.com/rxjava-apis-to-observables) | ||||
| - [RxJava Hooks](https://www.baeldung.com/rxjava-hooks) | ||||
|  | ||||
| @ -17,7 +17,7 @@ import static org.junit.Assert.assertNotNull; | ||||
| 
 | ||||
| @RunWith(SpringRunner.class) | ||||
| @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = Spring5ReactiveApplication.class) | ||||
| public class AccountCrudRepositoryIntegrationTest { | ||||
| public class AccountCrudRepositoryManualTest { | ||||
| 
 | ||||
|     @Autowired | ||||
|     AccountCrudRepository repository; | ||||
| @ -19,7 +19,7 @@ import static org.springframework.data.domain.ExampleMatcher.GenericPropertyMatc | ||||
| 
 | ||||
| @RunWith(SpringRunner.class) | ||||
| @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = Spring5ReactiveApplication.class) | ||||
| public class AccountMongoRepositoryIntegrationTest { | ||||
| public class AccountMongoRepositoryManualTest { | ||||
| 
 | ||||
|     @Autowired | ||||
|     AccountMongoRepository repository; | ||||
| @ -15,7 +15,7 @@ import static org.junit.Assert.assertNotNull; | ||||
| 
 | ||||
| @RunWith(SpringRunner.class) | ||||
| @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = Spring5ReactiveApplication.class) | ||||
| public class AccountRxJavaRepositoryIntegrationTest { | ||||
| public class AccountRxJavaRepositoryManualTest { | ||||
| 
 | ||||
|     @Autowired | ||||
|     AccountRxJavaRepository repository; | ||||
| @ -16,7 +16,7 @@ import static org.junit.jupiter.api.Assertions.*; | ||||
| 
 | ||||
| @RunWith(SpringRunner.class) | ||||
| @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = Spring5ReactiveApplication.class) | ||||
| public class AccountTemplateOperationsIntegrationTest { | ||||
| public class AccountTemplateOperationsManualTest { | ||||
| 
 | ||||
|     @Autowired | ||||
|     AccountTemplateOperations accountTemplate; | ||||
| @ -1,5 +1,5 @@ | ||||
| ## Relevant articles: | ||||
| 
 | ||||
| - [Spring Security 5 -OAuth2 Login](http://www.baeldung.com/spring-security-5-oauth2-login) | ||||
| - [Spring Security 5 – OAuth2 Login](http://www.baeldung.com/spring-security-5-oauth2-login) | ||||
| - [Extracting Principal and Authorities using Spring Security OAuth](https://www.baeldung.com/spring-security-oauth-principal-authorities-extractor) | ||||
| - [Customizing Authorization and Token Requests with Spring Security 5.1 Client](https://www.baeldung.com/spring-security-custom-oauth-requests) | ||||
|  | ||||
							
								
								
									
										4
									
								
								spring-5-webflux/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								spring-5-webflux/README.md
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,4 @@ | ||||
| ## Relevant articles: | ||||
| 
 | ||||
| - [Spring Boot Reactor Netty Configuration](https://www.baeldung.com/spring-boot-reactor-netty) | ||||
| - [How to Return 404 with Spring WebFlux](https://www.baeldung.com/spring-webflux-404) | ||||
| @ -14,7 +14,7 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring | ||||
| - [Properties with Spring and Spring Boot](http://www.baeldung.com/properties-with-spring) - checkout the `org.baeldung.properties` package for all scenarios of properties injection and usage | ||||
| - [Spring Profiles](http://www.baeldung.com/spring-profiles) | ||||
| - [A Spring Custom Annotation for a Better DAO](http://www.baeldung.com/spring-annotation-bean-pre-processor) | ||||
| - [What's New in Spring 4.3?](http://www.baeldung.com/whats-new-in-spring-4-3) | ||||
| - [What’s New in Spring 4.3?](http://www.baeldung.com/whats-new-in-spring-4-3) | ||||
| - [Running Setup Data on Startup in Spring](http://www.baeldung.com/running-setup-logic-on-startup-in-spring) | ||||
| - [Quick Guide to Spring Controllers](http://www.baeldung.com/spring-controllers) | ||||
| - [Quick Guide to Spring Bean Scopes](http://www.baeldung.com/spring-bean-scopes) | ||||
| @ -34,3 +34,4 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring | ||||
| - [Spring Events](https://www.baeldung.com/spring-events) | ||||
| - [Spring Null-Safety Annotations](https://www.baeldung.com/spring-null-safety-annotations) | ||||
| - [Spring JDBC](https://www.baeldung.com/spring-jdbc-jdbctemplate) | ||||
| - [Using @Autowired in Abstract Classes](https://www.baeldung.com/spring-autowired-abstract-class) | ||||
|  | ||||
| @ -6,5 +6,5 @@ | ||||
| ### Relevant Articles:  | ||||
| - [Introduction to Spring Batch](http://www.baeldung.com/introduction-to-spring-batch) | ||||
| - [Spring Batch using Partitioner](http://www.baeldung.com/spring-batch-partitioner) | ||||
| - [Spring Batch Tasklets vs Chunks Approach](http://www.baeldung.com/spring-batch-tasklet-chunk) | ||||
| - [Spring Batch – Tasklets vs Chunks](http://www.baeldung.com/spring-batch-tasklet-chunk) | ||||
| - [How to Trigger and Stop a Scheduled Spring Batch Job](http://www.baeldung.com/spring-batch-start-stop-job) | ||||
|  | ||||
| @ -1,2 +1,2 @@ | ||||
| ### Relevant Articles: | ||||
| - [Formatting JSON Dates in Spring ](https://www.baeldung.com/spring-boot-formatting-json-dates) | ||||
| - [Formatting JSON Dates in Spring Boot](https://www.baeldung.com/spring-boot-formatting-json-dates) | ||||
|  | ||||
							
								
								
									
										3
									
								
								spring-boot-flowable/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								spring-boot-flowable/README.md
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | ||||
| ### Relevant articles | ||||
| 
 | ||||
| - [Introduction to Flowable](http://www.baeldung.com/flowable) | ||||
							
								
								
									
										58
									
								
								spring-boot-flowable/pom.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								spring-boot-flowable/pom.xml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,58 @@ | ||||
| <?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>spring-boot-flowable</artifactId> | ||||
| 	<packaging>war</packaging> | ||||
| 	<name>spring-boot-flowable</name> | ||||
| 	<description>Spring Boot Flowable Module</description> | ||||
| 	<parent> | ||||
| 		<artifactId>parent-boot-2</artifactId> | ||||
| 		<groupId>com.baeldung</groupId> | ||||
| 		<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>com.h2database</groupId> | ||||
| 			<artifactId>h2</artifactId> | ||||
| 			<scope>runtime</scope> | ||||
| 		</dependency> | ||||
| 		<dependency> | ||||
| 			<groupId>org.flowable</groupId> | ||||
| 			<artifactId>flowable-spring-boot-starter-rest</artifactId> | ||||
| 			<version>${flowable.version}</version> | ||||
| 		</dependency> | ||||
| 		<dependency> | ||||
| 			<groupId>org.flowable</groupId> | ||||
| 			<artifactId>flowable-spring-boot-starter-actuator</artifactId> | ||||
| 			<version>${flowable.version}</version> | ||||
| 		</dependency> | ||||
| 		<dependency> | ||||
| 			<groupId>org.springframework.boot</groupId> | ||||
| 			<artifactId>spring-boot-starter-test</artifactId> | ||||
| 			<scope>test</scope> | ||||
| 		</dependency> | ||||
| 		<dependency> | ||||
| 			<groupId>org.junit.jupiter</groupId> | ||||
| 			<artifactId>junit-jupiter-engine</artifactId> | ||||
| 			<scope>test</scope> | ||||
| 		</dependency> | ||||
| 	</dependencies> | ||||
| 	<build> | ||||
| 		<plugins> | ||||
| 			<plugin> | ||||
| 				<groupId>org.springframework.boot</groupId> | ||||
| 				<artifactId>spring-boot-maven-plugin</artifactId> | ||||
| 			</plugin> | ||||
| 		</plugins> | ||||
| 	</build> | ||||
| 	<properties> | ||||
| 		<flowable.version>6.4.1</flowable.version> | ||||
| 	</properties> | ||||
| </project> | ||||
| @ -0,0 +1,13 @@ | ||||
| package com.baeldung; | ||||
| 
 | ||||
| import org.springframework.boot.SpringApplication; | ||||
| import org.springframework.boot.autoconfigure.SpringBootApplication; | ||||
| 
 | ||||
| @SpringBootApplication | ||||
| public class Application { | ||||
| 
 | ||||
|     public static void main(String[] args) { | ||||
|         SpringApplication.run(Application.class, args); | ||||
|     } | ||||
| 
 | ||||
| } | ||||
| @ -0,0 +1,32 @@ | ||||
| package com.baeldung.controller; | ||||
| 
 | ||||
| import java.util.List; | ||||
| 
 | ||||
| import org.springframework.beans.factory.annotation.Autowired; | ||||
| import org.springframework.web.bind.annotation.GetMapping; | ||||
| import org.springframework.web.bind.annotation.PostMapping; | ||||
| import org.springframework.web.bind.annotation.RequestBody; | ||||
| import org.springframework.web.bind.annotation.RequestParam; | ||||
| import org.springframework.web.bind.annotation.RestController; | ||||
| 
 | ||||
| import com.baeldung.domain.Approval; | ||||
| import com.baeldung.domain.Article; | ||||
| import com.baeldung.service.ArticleWorkflowService; | ||||
| 
 | ||||
| @RestController | ||||
| public class ArticleWorkflowController { | ||||
|     @Autowired | ||||
|     private ArticleWorkflowService service; | ||||
|     @PostMapping("/submit") | ||||
|     public void submit(@RequestBody Article article) { | ||||
|         service.startProcess(article); | ||||
|     } | ||||
|     @GetMapping("/tasks") | ||||
|     public List<Article> getTasks(@RequestParam String assignee) { | ||||
|         return service.getTasks(assignee); | ||||
|     } | ||||
|     @PostMapping("/review") | ||||
|     public void review(@RequestBody Approval approval) { | ||||
|         service.submitReview(approval); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,24 @@ | ||||
| package com.baeldung.domain; | ||||
| 
 | ||||
| public class Approval { | ||||
| 
 | ||||
|     private String id; | ||||
|     private boolean status; | ||||
| 
 | ||||
|     public String getId() { | ||||
|         return id; | ||||
|     } | ||||
| 
 | ||||
|     public void setId(String id) { | ||||
|         this.id = id; | ||||
|     } | ||||
| 
 | ||||
|     public boolean isStatus() { | ||||
|         return status; | ||||
|     } | ||||
| 
 | ||||
|     public void setStatus(boolean status) { | ||||
|         this.status = status; | ||||
|     } | ||||
| 
 | ||||
| } | ||||
| @ -0,0 +1,52 @@ | ||||
| package com.baeldung.domain; | ||||
| 
 | ||||
| public class Article { | ||||
| 
 | ||||
|     private String id; | ||||
|     private String author; | ||||
|     private String url; | ||||
| 
 | ||||
|     public Article() { | ||||
|     } | ||||
| 
 | ||||
|     public Article(String author, String url) { | ||||
|         this.author = author; | ||||
|         this.url = url; | ||||
|     } | ||||
| 
 | ||||
|     public Article(String id, String author, String url) { | ||||
|         this.id = id; | ||||
|         this.author = author; | ||||
|         this.url = url; | ||||
|     } | ||||
| 
 | ||||
|     public String getId() { | ||||
|         return id; | ||||
|     } | ||||
| 
 | ||||
|     public void setId(String id) { | ||||
|         this.id = id; | ||||
|     } | ||||
| 
 | ||||
|     public String getAuthor() { | ||||
|         return author; | ||||
|     } | ||||
| 
 | ||||
|     public void setAuthor(String author) { | ||||
|         this.author = author; | ||||
|     } | ||||
| 
 | ||||
|     public String getUrl() { | ||||
|         return url; | ||||
|     } | ||||
| 
 | ||||
|     public void setUrl(String url) { | ||||
|         this.url = url; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public String toString() { | ||||
|         return ("[" + this.author + " " + this.url + "]"); | ||||
|     } | ||||
| 
 | ||||
| } | ||||
| @ -0,0 +1,55 @@ | ||||
| package com.baeldung.service; | ||||
| 
 | ||||
| import java.util.HashMap; | ||||
| import java.util.List; | ||||
| import java.util.Map; | ||||
| import java.util.stream.Collectors; | ||||
| 
 | ||||
| import org.flowable.engine.RuntimeService; | ||||
| import org.flowable.engine.TaskService; | ||||
| import org.flowable.task.api.Task; | ||||
| import org.springframework.beans.factory.annotation.Autowired; | ||||
| import org.springframework.stereotype.Service; | ||||
| import org.springframework.transaction.annotation.Transactional; | ||||
| 
 | ||||
| import com.baeldung.domain.Approval; | ||||
| import com.baeldung.domain.Article; | ||||
| 
 | ||||
| @Service | ||||
| public class ArticleWorkflowService { | ||||
|     @Autowired | ||||
|     private RuntimeService runtimeService; | ||||
|     @Autowired | ||||
|     private TaskService taskService; | ||||
| 
 | ||||
|     @Transactional | ||||
|     public void startProcess(Article article) { | ||||
|         Map<String, Object> variables = new HashMap<String, Object>(); | ||||
|         variables.put("author", article.getAuthor()); | ||||
|         variables.put("url", article.getUrl()); | ||||
|         runtimeService.startProcessInstanceByKey("articleReview", variables); | ||||
|     } | ||||
| 
 | ||||
|     @Transactional | ||||
|     public List<Article> getTasks(String assignee) { | ||||
|         List<Task> tasks = taskService.createTaskQuery() | ||||
|           .taskCandidateGroup(assignee) | ||||
|           .list(); | ||||
|          | ||||
|         List<Article> articles = tasks.stream() | ||||
|           .map(task -> { | ||||
|               Map<String, Object> variables = taskService.getVariables(task.getId()); | ||||
|               return new Article( | ||||
|                 task.getId(), (String) variables.get("author"), (String) variables.get("url")); | ||||
|           }) | ||||
|           .collect(Collectors.toList()); | ||||
|         return articles; | ||||
|     } | ||||
| 
 | ||||
|     @Transactional | ||||
|     public void submitReview(Approval approval) { | ||||
|         Map<String, Object> variables = new HashMap<String, Object>(); | ||||
|         variables.put("approved", approval.isStatus()); | ||||
|         taskService.complete(approval.getId(), variables); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,10 @@ | ||||
| package com.baeldung.service; | ||||
| 
 | ||||
| import org.flowable.engine.delegate.DelegateExecution; | ||||
| import org.flowable.engine.delegate.JavaDelegate; | ||||
| 
 | ||||
| public class PublishArticleService implements JavaDelegate { | ||||
|     public void execute(DelegateExecution execution) { | ||||
|         System.out.println("Publishing the approved article."); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,10 @@ | ||||
| package com.baeldung.service; | ||||
| 
 | ||||
| import org.flowable.engine.delegate.DelegateExecution; | ||||
| import org.flowable.engine.delegate.JavaDelegate; | ||||
| 
 | ||||
| public class SendMailService implements JavaDelegate { | ||||
|     public void execute(DelegateExecution execution) { | ||||
|         System.out.println("Sending rejection mail to author."); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1 @@ | ||||
| management.endpoint.flowable.enabled=true | ||||
| @ -0,0 +1,51 @@ | ||||
| <?xml version="1.0" encoding="UTF-8"?> | ||||
| <definitions | ||||
| 	xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" | ||||
| 	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||||
| 	xmlns:xsd="http://www.w3.org/2001/XMLSchema" | ||||
| 	xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" | ||||
| 	xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" | ||||
| 	xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" | ||||
| 	xmlns:flowable="http://flowable.org/bpmn" | ||||
| 	typeLanguage="http://www.w3.org/2001/XMLSchema" | ||||
| 	expressionLanguage="http://www.w3.org/1999/XPath" | ||||
| 	targetNamespace="http://www.flowable.org/processdef"> | ||||
| 	<process id="articleReview" | ||||
| 		name="A simple process for article review." isExecutable="true"> | ||||
| 		<startEvent id="start" /> | ||||
| 		<sequenceFlow sourceRef="start" targetRef="reviewArticle" /> | ||||
| 		<userTask id="reviewArticle" | ||||
| 			name="Review the submitted tutorial" | ||||
| 			flowable:candidateGroups="editors" /> | ||||
| 		<sequenceFlow sourceRef="reviewArticle" | ||||
| 			targetRef="decision" /> | ||||
| 		<exclusiveGateway id="decision" /> | ||||
| 		<sequenceFlow sourceRef="decision" | ||||
| 			targetRef="tutorialApproved"> | ||||
| 			<conditionExpression xsi:type="tFormalExpression"> | ||||
| 		        <![CDATA[ | ||||
| 		          ${approved} | ||||
| 		        ]]> | ||||
| 			</conditionExpression> | ||||
| 		</sequenceFlow> | ||||
| 		<sequenceFlow sourceRef="decision" | ||||
| 			targetRef="tutorialRejected"> | ||||
| 			<conditionExpression xsi:type="tFormalExpression"> | ||||
| 		        <![CDATA[ | ||||
| 		          ${!approved} | ||||
| 		        ]]> | ||||
| 			</conditionExpression> | ||||
| 		</sequenceFlow> | ||||
| 		<serviceTask id="tutorialApproved" | ||||
| 			name="Publish the approved tutorial." | ||||
| 			flowable:class="com.sapient.learning.service.PublishArticleService" /> | ||||
| 		<sequenceFlow sourceRef="tutorialApproved" | ||||
| 			targetRef="end" /> | ||||
| 		<serviceTask id="tutorialRejected" | ||||
| 			name="Send out rejection email" | ||||
| 			flowable:class="com.sapient.learning.service.SendMailService" /> | ||||
| 		<sequenceFlow sourceRef="tutorialRejected" | ||||
| 			targetRef="end" /> | ||||
| 		<endEvent id="end" /> | ||||
| 	</process> | ||||
| </definitions> | ||||
| @ -0,0 +1,40 @@ | ||||
| package com.baeldung.processes; | ||||
| 
 | ||||
| import static org.junit.Assert.assertEquals; | ||||
| 
 | ||||
| import java.util.HashMap; | ||||
| import java.util.Map; | ||||
| 
 | ||||
| import org.flowable.engine.RuntimeService; | ||||
| import org.flowable.engine.TaskService; | ||||
| import org.flowable.engine.test.Deployment; | ||||
| import org.flowable.spring.impl.test.FlowableSpringExtension; | ||||
| import org.flowable.task.api.Task; | ||||
| import org.junit.jupiter.api.Test; | ||||
| import org.junit.jupiter.api.extension.ExtendWith; | ||||
| import org.springframework.beans.factory.annotation.Autowired; | ||||
| import org.springframework.test.context.junit.jupiter.SpringExtension; | ||||
| 
 | ||||
| @ExtendWith(FlowableSpringExtension.class) | ||||
| @ExtendWith(SpringExtension.class) | ||||
| public class ArticleWorkflowUnitTest { | ||||
|     @Autowired | ||||
|     private RuntimeService runtimeService; | ||||
|     @Autowired | ||||
|     private TaskService taskService; | ||||
|     @Test | ||||
|     @Deployment(resources = { "processes/article-workflow.bpmn20.xml" }) | ||||
|     void articleApprovalTest() { | ||||
|         Map<String, Object> variables = new HashMap<String, Object>(); | ||||
|         variables.put("author", "test@baeldung.com"); | ||||
|         variables.put("url", "http://baeldung.com/dummy"); | ||||
|         runtimeService.startProcessInstanceByKey("articleReview", variables); | ||||
|         Task task = taskService.createTaskQuery() | ||||
|             .singleResult(); | ||||
|         assertEquals("Review the submitted tutorial", task.getName()); | ||||
|         variables.put("approved", true); | ||||
|         taskService.complete(task.getId(), variables); | ||||
|         assertEquals(0, runtimeService.createProcessInstanceQuery() | ||||
|             .count()); | ||||
|     } | ||||
| } | ||||
| @ -10,4 +10,5 @@ Module for the articles that are part of the Spring REST E-book: | ||||
| 8. [Http Message Converters with the Spring Framework](http://www.baeldung.com/spring-httpmessageconverter-rest) | ||||
| 9. [ETags for REST with Spring](http://www.baeldung.com/etags-for-rest-with-spring) | ||||
| 10. [Testing REST with multiple MIME types](http://www.baeldung.com/testing-rest-api-with-multiple-media-types) | ||||
| 11. [Testing Web APIs with Postman Collections](https://www.baeldung.com/postman-testing-collections) | ||||
| 11. [Spring Boot Consuming and Producing JSON](https://www.baeldung.com/spring-boot-json) | ||||
| 12. [Testing Web APIs with Postman Collections](https://www.baeldung.com/postman-testing-collections) | ||||
|  | ||||
| @ -0,0 +1,21 @@ | ||||
| package com.baeldung.rest; | ||||
| 
 | ||||
| public class GitHubUser { | ||||
| 
 | ||||
|     private String login; | ||||
| 
 | ||||
|     public GitHubUser() { | ||||
|         super(); | ||||
|     } | ||||
| 
 | ||||
|     // API | ||||
| 
 | ||||
|     public String getLogin() { | ||||
|         return login; | ||||
|     } | ||||
| 
 | ||||
|     public void setLogin(final String login) { | ||||
|         this.login = login; | ||||
|     } | ||||
| 
 | ||||
| } | ||||
| @ -1,4 +1,4 @@ | ||||
| package org.baeldung.rest; | ||||
| package com.baeldung.rest; | ||||
| 
 | ||||
| import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic; | ||||
| import static org.hamcrest.Matchers.equalTo; | ||||
| @ -0,0 +1,21 @@ | ||||
| package com.baeldung.rest; | ||||
| 
 | ||||
| import java.io.IOException; | ||||
| 
 | ||||
| import org.apache.http.HttpResponse; | ||||
| import org.apache.http.util.EntityUtils; | ||||
| 
 | ||||
| import com.fasterxml.jackson.databind.DeserializationFeature; | ||||
| import com.fasterxml.jackson.databind.ObjectMapper; | ||||
| 
 | ||||
| public class RetrieveUtil { | ||||
| 
 | ||||
|     // API | ||||
| 
 | ||||
|     public static <T> T retrieveResourceFromResponse(final HttpResponse response, final Class<T> clazz) throws IOException { | ||||
|         final String jsonFromResponse = EntityUtils.toString(response.getEntity()); | ||||
|         final ObjectMapper mapper = new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); | ||||
|         return mapper.readValue(jsonFromResponse, clazz); | ||||
|     } | ||||
| 
 | ||||
| } | ||||
| @ -6,12 +6,12 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring | ||||
| - [A Guide to Spring in Eclipse STS](http://www.baeldung.com/eclipse-sts-spring) | ||||
| - [The @ServletComponentScan Annotation in Spring Boot](http://www.baeldung.com/spring-servletcomponentscan) | ||||
| - [Intro to Building an Application with Spring Boot](http://www.baeldung.com/intro-to-spring-boot) | ||||
| - [How to Register a Servlet in a Java Web Application](http://www.baeldung.com/register-servlet) | ||||
| - [How to Register a Servlet in Java](http://www.baeldung.com/register-servlet) | ||||
| - [Guide to Spring WebUtils and ServletRequestUtils](http://www.baeldung.com/spring-webutils-servletrequestutils) | ||||
| - [Using Custom Banners in Spring Boot](http://www.baeldung.com/spring-boot-custom-banners) | ||||
| - [Guide to Internationalization in Spring Boot](http://www.baeldung.com/spring-boot-internationalization) | ||||
| - [Create a Custom FailureAnalyzer with Spring Boot](http://www.baeldung.com/spring-boot-failure-analyzer) | ||||
| - [Dynamic DTO Validation Config Retrieved from DB](http://www.baeldung.com/spring-dynamic-dto-validation) | ||||
| - [Dynamic DTO Validation Config Retrieved from the Database](http://www.baeldung.com/spring-dynamic-dto-validation) | ||||
| - [Custom Information in Spring Boot Info Endpoint](http://www.baeldung.com/spring-boot-info-actuator-custom) | ||||
| - [Using @JsonComponent in Spring Boot](http://www.baeldung.com/spring-boot-jsoncomponent) | ||||
| - [Testing in Spring Boot](http://www.baeldung.com/spring-boot-testing) | ||||
| @ -21,7 +21,7 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring | ||||
| - [Getting Started with GraphQL and Spring Boot](http://www.baeldung.com/spring-graphql) | ||||
| - [Guide to Spring Type Conversions](http://www.baeldung.com/spring-type-conversions) | ||||
| - [An Introduction to Kong](http://www.baeldung.com/kong) | ||||
| - [Spring Boot Customize Whitelabel Error Page](http://www.baeldung.com/spring-boot-custom-error-page) | ||||
| - [Spring Boot: Customize Whitelabel Error Page](http://www.baeldung.com/spring-boot-custom-error-page) | ||||
| - [Spring Boot: Configuring a Main Class](http://www.baeldung.com/spring-boot-main-class) | ||||
| - [A Quick Intro to the SpringBootServletInitializer](http://www.baeldung.com/spring-boot-servlet-initializer) | ||||
| - [How to Define a Spring Boot Filter?](http://www.baeldung.com/spring-boot-add-filter) | ||||
|  | ||||
| @ -1,4 +1,4 @@ | ||||
| package org.baeldung; | ||||
| package com.baeldung.spring.cloud.config.client; | ||||
| 
 | ||||
| import org.junit.Test; | ||||
| import org.junit.runner.RunWith; | ||||
| @ -6,12 +6,15 @@ import org.springframework.boot.test.context.SpringBootTest; | ||||
| import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; | ||||
| import org.springframework.test.context.web.WebAppConfiguration; | ||||
| 
 | ||||
| import com.baeldung.spring.cloud.config.client.ConfigClient; | ||||
| 
 | ||||
| /** | ||||
|  *  | ||||
|  * The app needs the server running on port 8888. Can be started with docker | ||||
|  * | ||||
|  */ | ||||
| @RunWith(SpringJUnit4ClassRunner.class) | ||||
| @SpringBootTest(classes = ConfigClient.class) | ||||
| @WebAppConfiguration | ||||
| public class SpringContextIntegrationTest { | ||||
| public class SpringContextLiveTest { | ||||
|     @Test | ||||
|     public void contextLoads() { | ||||
|     } | ||||
| @ -6,16 +6,10 @@ import org.springframework.boot.test.context.SpringBootTest; | ||||
| import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; | ||||
| import org.springframework.test.context.web.WebAppConfiguration; | ||||
| 
 | ||||
| 
 | ||||
| /** | ||||
|  *  | ||||
|  * The context will load successfully with some properties provided by docker | ||||
|  * | ||||
|  */ | ||||
| @RunWith(SpringJUnit4ClassRunner.class) | ||||
| @SpringBootTest(classes = ConfigServer.class) | ||||
| @WebAppConfiguration | ||||
| public class SpringContextLiveTest { | ||||
| public class SpringContextIntegrationTest { | ||||
|     @Test | ||||
|     public void whenSpringContextIsBootstrapped_thenNoExceptions() { | ||||
|     } | ||||
| @ -0,0 +1,2 @@ | ||||
| ### This should be provided by the docker config | ||||
| spring.cloud.config.server.git.uri=classpath:. | ||||
| @ -4,5 +4,6 @@ spring.datasource.maxIdle=5 | ||||
| spring.datasource.minIdle=2 | ||||
| spring.datasource.initialSize=5 | ||||
| spring.datasource.removeAbandoned=true | ||||
| spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect | ||||
| 
 | ||||
| spring.jpa.hibernate.ddl-auto=update | ||||
| @ -1,4 +1,4 @@ | ||||
| package org.baeldung; | ||||
| package com.baeldung.spring.cloud.connectors.heroku; | ||||
| 
 | ||||
| import org.junit.Test; | ||||
| import org.junit.runner.RunWith; | ||||
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