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)
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
=========
|
||||
|
||||
## Core Java Collections 2
|
||||
|
||||
### Relevant Articles:
|
||||
- Java - Copying a HashMap
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -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)
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
## Relevant Articles:
|
||||
- [Map of Primitives in Java](https://www.baeldung.com/java-map-primitives)
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
### Relevant articles
|
||||
|
||||
- [Introduction to Flowable](http://www.baeldung.com/flowable)
|
|
@ -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…
Reference in New Issue