Merge branch 'eugenmaster'

This commit is contained in:
Marcos Lopez Gonzalez 2019-04-15 14:37:42 +02:00
commit 352e7ca9db
133 changed files with 1779 additions and 156 deletions

View File

@ -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)

View File

@ -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`

View File

@ -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)

View File

@ -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/
}
}

View File

@ -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)

View File

@ -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 8s 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)

View File

@ -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)

View File

@ -0,0 +1,6 @@
=========
## Core Java Collections 2
### Relevant Articles:
- Java - Copying a HashMap

View File

@ -0,0 +1,78 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>core-java-collections-map</artifactId>
<version>0.1.0-SNAPSHOT</version>
<name>core-java-collections-map</name>
<packaging>jar</packaging>
<parent>
<groupId>com.baeldung</groupId>
<artifactId>parent-java</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../parent-java</relativePath>
</parent>
<dependencies>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
<version>${commons-collections4.version}</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>${commons-lang3.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.collections</groupId>
<artifactId>eclipse-collections</artifactId>
<version>${eclipse.collections.version}</version>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<version>${assertj.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-runner</artifactId>
<version>${junit.platform.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-core</artifactId>
<version>${openjdk.jmh.version}</version>
</dependency>
<dependency>
<groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-generator-annprocess</artifactId>
<version>${openjdk.jmh.version}</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-exec</artifactId>
<version>${commons-exec.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>
<properties>
<openjdk.jmh.version>1.19</openjdk.jmh.version>
<junit.platform.version>1.2.0</junit.platform.version>
<commons-lang3.version>3.8.1</commons-lang3.version>
<commons-collections4.version>4.1</commons-collections4.version>
<collections-generic.version>4.01</collections-generic.version>
<avaitility.version>1.7.0</avaitility.version>
<assertj.version>3.11.1</assertj.version>
<eclipse.collections.version>7.1.0</eclipse.collections.version>
<commons-exec.version>1.3</commons-exec.version>
</properties>
</project>

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -3,4 +3,4 @@
## Core Java JVM Cookbooks and Examples
### Relevant Articles:
- [Method Inlining in the JVM](http://www.baeldung.com/method-inlining-in-the-jvm/)
- [Method Inlining in the JVM](https://www.baeldung.com/jvm-method-inlining)

19
core-java-lambdas/pom.xml Normal file
View File

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>core-java-lambdas</artifactId>
<version>0.1.0-SNAPSHOT</version>
<name>core-java</name>
<packaging>jar</packaging>
<parent>
<groupId>com.baeldung</groupId>
<artifactId>parent-java</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../parent-java</relativePath>
</parent>
</project>

View File

@ -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;
}
}

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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()
}

View File

@ -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)
}
}

View File

@ -0,0 +1,2 @@
Computer programming can be a hassle
It's like trying to take a defended castle

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -0,0 +1,2 @@
## Relevant Articles:
- [Map of Primitives in Java](https://www.baeldung.com/java-map-primitives)

2
java-dates-2/README.md Normal file
View File

@ -0,0 +1,2 @@
## Relevant Articles:
- [Converting Between LocalDate and XMLGregorianCalendar](https://www.baeldung.com/java-localdate-to-xmlgregoriancalendar)

View File

@ -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)

View File

@ -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)

View File

@ -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>

View File

@ -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));
}
}

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -0,0 +1,3 @@
### Relevant Articles:
- [Get Log Output in JSON](https://www.baeldung.com/java-log-json-output)

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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>

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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)

View File

@ -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)

View File

@ -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);
}
}

View File

@ -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> {
}

View File

@ -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 + '\'' +
'}';
}
}

View File

@ -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

View File

@ -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());
}
}

View File

@ -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)

View File

@ -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

View File

@ -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)

View File

@ -1,4 +1,4 @@
package com.baeldung.customer;
package com.baeldung.entity;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;

View File

@ -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;

View File

@ -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");
}
}

View File

@ -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 {

View File

@ -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
View File

@ -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>

View File

@ -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)

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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)

View File

@ -0,0 +1,4 @@
## Relevant articles:
- [Spring Boot Reactor Netty Configuration](https://www.baeldung.com/spring-boot-reactor-netty)
- [How to Return 404 with Spring WebFlux](https://www.baeldung.com/spring-webflux-404)

View File

@ -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)
- [Whats 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)

View File

@ -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)

View File

@ -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)

View File

@ -0,0 +1,3 @@
### Relevant articles
- [Introduction to Flowable](http://www.baeldung.com/flowable)

View File

@ -0,0 +1,58 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>spring-boot-flowable</artifactId>
<packaging>war</packaging>
<name>spring-boot-flowable</name>
<description>Spring Boot Flowable Module</description>
<parent>
<artifactId>parent-boot-2</artifactId>
<groupId>com.baeldung</groupId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../parent-boot-2</relativePath>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.flowable</groupId>
<artifactId>flowable-spring-boot-starter-rest</artifactId>
<version>${flowable.version}</version>
</dependency>
<dependency>
<groupId>org.flowable</groupId>
<artifactId>flowable-spring-boot-starter-actuator</artifactId>
<version>${flowable.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<properties>
<flowable.version>6.4.1</flowable.version>
</properties>
</project>

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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 + "]");
}
}

View File

@ -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);
}
}

View File

@ -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.");
}
}

View File

@ -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.");
}
}

View File

@ -0,0 +1 @@
management.endpoint.flowable.enabled=true

View File

@ -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>

View File

@ -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());
}
}

View File

@ -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)

View File

@ -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;
}
}

View File

@ -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;

View File

@ -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);
}
}

View File

@ -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)

View File

@ -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() {
}

View File

@ -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() {
}

View File

@ -0,0 +1,2 @@
### This should be provided by the docker config
spring.cloud.config.server.git.uri=classpath:.

View File

@ -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

Some files were not shown because too many files have changed in this diff Show More