diff --git a/.gitignore b/.gitignore
index 21586748b7..b981a473f6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -19,6 +19,7 @@
.idea/
*.iml
*.iws
+out/
# Mac
.DS_Store
@@ -27,6 +28,9 @@
log/
target/
+# Gradle
+.gradle/
+
spring-openid/src/main/resources/application.properties
.recommenders/
/spring-hibernate4/nbproject/
diff --git a/azure/README.md b/azure/README.md
index c60186e1ce..ae8c443660 100644
--- a/azure/README.md
+++ b/azure/README.md
@@ -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)
diff --git a/blade/README.md b/blade/README.md
index d823de775f..1f2a00ed3f 100644
--- a/blade/README.md
+++ b/blade/README.md
@@ -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`
\ No newline at end of file
+Run Integration Tests with `mvn integration-test`
diff --git a/cloud-foundry-uaa/README.md b/cloud-foundry-uaa/README.md
new file mode 100644
index 0000000000..b2f382cad1
--- /dev/null
+++ b/cloud-foundry-uaa/README.md
@@ -0,0 +1,3 @@
+### Revelant Articles
+
+- [A Quick Guide To Using Cloud Foundry UAA](https://www.baeldung.com/cloud-foundry-uaa)
diff --git a/core-groovy-2/README.md b/core-groovy-2/README.md
new file mode 100644
index 0000000000..f60bdb3cbe
--- /dev/null
+++ b/core-groovy-2/README.md
@@ -0,0 +1,7 @@
+# Groovy
+
+## Relevant articles:
+
+- [String Matching in Groovy](http://www.baeldung.com/)
+- [Groovy def Keyword]
+
diff --git a/core-groovy-2/pom.xml b/core-groovy-2/pom.xml
new file mode 100644
index 0000000000..77de9c8fc8
--- /dev/null
+++ b/core-groovy-2/pom.xml
@@ -0,0 +1,131 @@
+
+
+ 4.0.0
+ core-groovy-2
+ 1.0-SNAPSHOT
+ core-groovy-2
+ jar
+
+
+ com.baeldung
+ parent-modules
+ 1.0.0-SNAPSHOT
+
+
+
+
+ org.codehaus.groovy
+ groovy
+ ${groovy.version}
+
+
+ org.codehaus.groovy
+ groovy-all
+ ${groovy-all.version}
+ pom
+
+
+ org.codehaus.groovy
+ groovy-dateutil
+ ${groovy.version}
+
+
+ org.codehaus.groovy
+ groovy-sql
+ ${groovy-sql.version}
+
+
+ org.junit.platform
+ junit-platform-runner
+ ${junit.platform.version}
+ test
+
+
+ org.hsqldb
+ hsqldb
+ ${hsqldb.version}
+ test
+
+
+ org.spockframework
+ spock-core
+ ${spock-core.version}
+ test
+
+
+
+
+
+
+ org.codehaus.gmavenplus
+ gmavenplus-plugin
+ ${gmavenplus-plugin.version}
+
+
+
+ addSources
+ addTestSources
+ compile
+ compileTests
+
+
+
+
+
+ maven-failsafe-plugin
+ ${maven-failsafe-plugin.version}
+
+
+ org.junit.platform
+ junit-platform-surefire-provider
+ ${junit.platform.version}
+
+
+
+
+ junit5
+
+ integration-test
+ verify
+
+
+
+ **/*Test5.java
+
+
+
+
+
+
+ maven-surefire-plugin
+ 2.20.1
+
+ false
+
+ **/*Test.java
+ **/*Spec.java
+
+
+
+
+
+
+
+
+ central
+ http://jcenter.bintray.com
+
+
+
+
+ 1.0.0
+ 2.5.6
+ 2.5.6
+ 2.5.6
+ 2.4.0
+ 1.1-groovy-2.4
+ 1.6
+
+
+
diff --git a/core-groovy-2/src/test/groovy/com/baeldung/defkeyword/DefUnitTest.groovy b/core-groovy-2/src/test/groovy/com/baeldung/defkeyword/DefUnitTest.groovy
new file mode 100644
index 0000000000..310d97d3fd
--- /dev/null
+++ b/core-groovy-2/src/test/groovy/com/baeldung/defkeyword/DefUnitTest.groovy
@@ -0,0 +1,79 @@
+package com.baeldung.defkeyword
+
+import org.codehaus.groovy.runtime.NullObject
+import org.codehaus.groovy.runtime.typehandling.GroovyCastException
+
+import groovy.transform.TypeChecked
+import groovy.transform.TypeCheckingMode
+
+@TypeChecked
+class DefUnitTest extends GroovyTestCase {
+
+ def id
+ def firstName = "Samwell"
+ def listOfCountries = ['USA', 'UK', 'FRANCE', 'INDIA']
+
+ @TypeChecked(TypeCheckingMode.SKIP)
+ def multiply(x, y) {
+ return x*y
+ }
+
+ @TypeChecked(TypeCheckingMode.SKIP)
+ void testDefVariableDeclaration() {
+
+ def list
+ assert list.getClass() == org.codehaus.groovy.runtime.NullObject
+ assert list.is(null)
+
+ list = [1,2,4]
+ assert list instanceof ArrayList
+ }
+
+ @TypeChecked(TypeCheckingMode.SKIP)
+ void testTypeVariables() {
+ int rate = 200
+ try {
+ rate = [12] //GroovyCastException
+ rate = "nill" //GroovyCastException
+ } catch(GroovyCastException) {
+ println "Cannot assign anything other than integer"
+ }
+ }
+
+ @TypeChecked(TypeCheckingMode.SKIP)
+ void testDefVariableMultipleAssignment() {
+ def rate
+ assert rate == null
+ assert rate.getClass() == org.codehaus.groovy.runtime.NullObject
+
+ rate = 12
+ assert rate instanceof Integer
+
+ rate = "Not Available"
+ assert rate instanceof String
+
+ rate = [1, 4]
+ assert rate instanceof List
+
+ assert divide(12, 3) instanceof BigDecimal
+ assert divide(1, 0) instanceof String
+
+ }
+
+ def divide(int x, int y) {
+ if(y==0) {
+ return "Should not divide by 0"
+ } else {
+ return x/y
+ }
+ }
+
+ def greetMsg() {
+ println "Hello! I am Groovy"
+ }
+
+ void testDefVsType() {
+ def int count
+ assert count instanceof Integer
+ }
+}
\ No newline at end of file
diff --git a/core-groovy-2/src/test/groovy/com/baeldung/strings/StringMatchingSpec.groovy b/core-groovy-2/src/test/groovy/com/baeldung/strings/StringMatchingSpec.groovy
new file mode 100644
index 0000000000..3865bc73fa
--- /dev/null
+++ b/core-groovy-2/src/test/groovy/com/baeldung/strings/StringMatchingSpec.groovy
@@ -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/
+ }
+
+}
diff --git a/core-groovy/README.md b/core-groovy/README.md
index 606a317747..321c37be8d 100644
--- a/core-groovy/README.md
+++ b/core-groovy/README.md
@@ -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)
\ No newline at end of file
diff --git a/core-groovy/src/test/groovy/com/baeldung/strings/StringMatchingSpec.groovy b/core-groovy/src/test/groovy/com/baeldung/strings/StringMatchingSpec.groovy
new file mode 100644
index 0000000000..3865bc73fa
--- /dev/null
+++ b/core-groovy/src/test/groovy/com/baeldung/strings/StringMatchingSpec.groovy
@@ -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/
+ }
+
+}
diff --git a/core-java-11/README.md b/core-java-11/README.md
index b09649f4f1..a4b0e0e59c 100644
--- a/core-java-11/README.md
+++ b/core-java-11/README.md
@@ -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)
diff --git a/core-java-8-2/README.md b/core-java-8-2/README.md
new file mode 100644
index 0000000000..e2b12e8819
--- /dev/null
+++ b/core-java-8-2/README.md
@@ -0,0 +1,6 @@
+=========
+
+## Core Java 8 Cookbooks and Examples (part 2)
+
+### Relevant Articles:
+- [Anonymous Classes in Java](http://www.baeldung.com/)
diff --git a/core-java-8-2/pom.xml b/core-java-8-2/pom.xml
new file mode 100644
index 0000000000..7035f12fb7
--- /dev/null
+++ b/core-java-8-2/pom.xml
@@ -0,0 +1,43 @@
+
+
+ 4.0.0
+ com.baeldung
+ core-java-8-2
+ 0.1.0-SNAPSHOT
+ core-java-8-2
+ jar
+
+
+
+ com.baeldung
+ parent-java
+ 0.0.1-SNAPSHOT
+ ../parent-java
+
+
+
+ UTF-8
+ 1.8
+ 1.8
+
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ ${maven-compiler-plugin.version}
+
+
+ ${maven.compiler.target}
+
+
+
+
+
+
diff --git a/core-java-8/README.md b/core-java-8/README.md
index 99182da390..d11d2debce 100644
--- a/core-java-8/README.md
+++ b/core-java-8/README.md
@@ -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)
diff --git a/core-java-8/src/main/java/com/baeldung/Adder.java b/core-java-8/src/main/java/com/baeldung/Adder.java
deleted file mode 100644
index e3e100f121..0000000000
--- a/core-java-8/src/main/java/com/baeldung/Adder.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package com.baeldung;
-
-import java.util.function.Consumer;
-import java.util.function.Function;
-
-public interface Adder {
-
- String addWithFunction(Function f);
-
- void addWithConsumer(Consumer f);
-
-}
diff --git a/core-java-8/src/main/java/com/baeldung/AdderImpl.java b/core-java-8/src/main/java/com/baeldung/AdderImpl.java
deleted file mode 100644
index 7852934d55..0000000000
--- a/core-java-8/src/main/java/com/baeldung/AdderImpl.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.baeldung;
-
-
-import java.util.function.Consumer;
-import java.util.function.Function;
-
-public class AdderImpl implements Adder {
-
- @Override
- public String addWithFunction(final Function f) {
- return f.apply("Something ");
- }
-
- @Override
- public void addWithConsumer(final Consumer f) {
- }
-
-}
diff --git a/core-java-8/src/main/java/com/baeldung/Bar.java b/core-java-8/src/main/java/com/baeldung/java8/lambda/tips/Bar.java
similarity index 80%
rename from core-java-8/src/main/java/com/baeldung/Bar.java
rename to core-java-8/src/main/java/com/baeldung/java8/lambda/tips/Bar.java
index 6219bddf74..4cf0aa2399 100644
--- a/core-java-8/src/main/java/com/baeldung/Bar.java
+++ b/core-java-8/src/main/java/com/baeldung/java8/lambda/tips/Bar.java
@@ -1,4 +1,4 @@
-package com.baeldung;
+package com.baeldung.java8.lambda.tips;
@FunctionalInterface
diff --git a/core-java-8/src/main/java/com/baeldung/Baz.java b/core-java-8/src/main/java/com/baeldung/java8/lambda/tips/Baz.java
similarity index 80%
rename from core-java-8/src/main/java/com/baeldung/Baz.java
rename to core-java-8/src/main/java/com/baeldung/java8/lambda/tips/Baz.java
index 23180551ac..c7efe14c89 100644
--- a/core-java-8/src/main/java/com/baeldung/Baz.java
+++ b/core-java-8/src/main/java/com/baeldung/java8/lambda/tips/Baz.java
@@ -1,4 +1,4 @@
-package com.baeldung;
+package com.baeldung.java8.lambda.tips;
@FunctionalInterface
diff --git a/core-java-8/src/main/java/com/baeldung/Foo.java b/core-java-8/src/main/java/com/baeldung/java8/lambda/tips/Foo.java
similarity index 75%
rename from core-java-8/src/main/java/com/baeldung/Foo.java
rename to core-java-8/src/main/java/com/baeldung/java8/lambda/tips/Foo.java
index c8223727a1..b63ba61e7e 100644
--- a/core-java-8/src/main/java/com/baeldung/Foo.java
+++ b/core-java-8/src/main/java/com/baeldung/java8/lambda/tips/Foo.java
@@ -1,4 +1,4 @@
-package com.baeldung;
+package com.baeldung.java8.lambda.tips;
@FunctionalInterface
diff --git a/core-java-8/src/main/java/com/baeldung/FooExtended.java b/core-java-8/src/main/java/com/baeldung/java8/lambda/tips/FooExtended.java
similarity index 81%
rename from core-java-8/src/main/java/com/baeldung/FooExtended.java
rename to core-java-8/src/main/java/com/baeldung/java8/lambda/tips/FooExtended.java
index 8c9b21e397..9141cd8eb8 100644
--- a/core-java-8/src/main/java/com/baeldung/FooExtended.java
+++ b/core-java-8/src/main/java/com/baeldung/java8/lambda/tips/FooExtended.java
@@ -1,4 +1,4 @@
-package com.baeldung;
+package com.baeldung.java8.lambda.tips;
@FunctionalInterface
diff --git a/core-java-8/src/main/java/com/baeldung/java8/lambda/tips/Processor.java b/core-java-8/src/main/java/com/baeldung/java8/lambda/tips/Processor.java
new file mode 100644
index 0000000000..7931129cf5
--- /dev/null
+++ b/core-java-8/src/main/java/com/baeldung/java8/lambda/tips/Processor.java
@@ -0,0 +1,12 @@
+package com.baeldung.java8.lambda.tips;
+
+import java.util.concurrent.Callable;
+import java.util.function.Supplier;
+
+public interface Processor {
+
+ String processWithCallable(Callable c) throws Exception;
+
+ String processWithSupplier(Supplier s);
+
+}
diff --git a/core-java-8/src/main/java/com/baeldung/java8/lambda/tips/ProcessorImpl.java b/core-java-8/src/main/java/com/baeldung/java8/lambda/tips/ProcessorImpl.java
new file mode 100644
index 0000000000..cb1b3dcdd2
--- /dev/null
+++ b/core-java-8/src/main/java/com/baeldung/java8/lambda/tips/ProcessorImpl.java
@@ -0,0 +1,20 @@
+package com.baeldung.java8.lambda.tips;
+
+
+import java.util.concurrent.Callable;
+import java.util.function.Consumer;
+import java.util.function.Function;
+import java.util.function.Supplier;
+
+public class ProcessorImpl implements Processor {
+
+ @Override
+ public String processWithCallable(Callable c) throws Exception {
+ return c.call();
+ }
+
+ @Override
+ public String processWithSupplier(Supplier s) {
+ return s.get();
+ }
+}
diff --git a/core-java-8/src/main/java/com/baeldung/UseFoo.java b/core-java-8/src/main/java/com/baeldung/java8/lambda/tips/UseFoo.java
similarity index 95%
rename from core-java-8/src/main/java/com/baeldung/UseFoo.java
rename to core-java-8/src/main/java/com/baeldung/java8/lambda/tips/UseFoo.java
index 950d02062d..a64d8bb920 100644
--- a/core-java-8/src/main/java/com/baeldung/UseFoo.java
+++ b/core-java-8/src/main/java/com/baeldung/java8/lambda/tips/UseFoo.java
@@ -1,4 +1,4 @@
-package com.baeldung;
+package com.baeldung.java8.lambda.tips;
import java.util.function.Function;
diff --git a/core-java-8/src/test/java/com/baeldung/java8/Java8FunctionalInteracesLambdasUnitTest.java b/core-java-8/src/test/java/com/baeldung/java8/lambda/tips/Java8FunctionalInteracesLambdasUnitTest.java
similarity index 93%
rename from core-java-8/src/test/java/com/baeldung/java8/Java8FunctionalInteracesLambdasUnitTest.java
rename to core-java-8/src/test/java/com/baeldung/java8/lambda/tips/Java8FunctionalInteracesLambdasUnitTest.java
index 13ddcc805f..b409f8e37f 100644
--- a/core-java-8/src/test/java/com/baeldung/java8/Java8FunctionalInteracesLambdasUnitTest.java
+++ b/core-java-8/src/test/java/com/baeldung/java8/lambda/tips/Java8FunctionalInteracesLambdasUnitTest.java
@@ -1,8 +1,8 @@
-package com.baeldung.java8;
+package com.baeldung.java8.lambda.tips;
-import com.baeldung.Foo;
-import com.baeldung.FooExtended;
-import com.baeldung.UseFoo;
+import com.baeldung.java8.lambda.tips.Foo;
+import com.baeldung.java8.lambda.tips.FooExtended;
+import com.baeldung.java8.lambda.tips.UseFoo;
import org.junit.Before;
import org.junit.Test;
diff --git a/core-java-8/src/test/java/com/baeldung/reduceIfelse/CalculatorUnitTest.java b/core-java-8/src/test/java/com/baeldung/reduceIfelse/CalculatorUnitTest.java
index fa351930d8..1ff34bee89 100644
--- a/core-java-8/src/test/java/com/baeldung/reduceIfelse/CalculatorUnitTest.java
+++ b/core-java-8/src/test/java/com/baeldung/reduceIfelse/CalculatorUnitTest.java
@@ -29,4 +29,11 @@ public class CalculatorUnitTest {
int result = calculator.calculate(new AddCommand(3, 7));
assertEquals(10, result);
}
+
+ @Test
+ public void whenCalculateUsingFactory_thenReturnCorrectResult() {
+ Calculator calculator = new Calculator();
+ int result = calculator.calculateUsingFactory(3, 4, "add");
+ assertEquals(7, result);
+ }
}
diff --git a/core-java-9/README.md b/core-java-9/README.md
index 2477a38c00..8fdc3f6ee2 100644
--- a/core-java-9/README.md
+++ b/core-java-9/README.md
@@ -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)
+
diff --git a/core-java-collections-map/README.md b/core-java-collections-map/README.md
new file mode 100644
index 0000000000..da02928118
--- /dev/null
+++ b/core-java-collections-map/README.md
@@ -0,0 +1,6 @@
+=========
+
+## Core Java Collections 2
+
+### Relevant Articles:
+- Java - Copying a HashMap
diff --git a/core-java-collections-map/pom.xml b/core-java-collections-map/pom.xml
new file mode 100644
index 0000000000..8c0aef54bf
--- /dev/null
+++ b/core-java-collections-map/pom.xml
@@ -0,0 +1,78 @@
+
+ 4.0.0
+ core-java-collections-map
+ 0.1.0-SNAPSHOT
+ core-java-collections-map
+ jar
+
+
+ com.baeldung
+ parent-java
+ 0.0.1-SNAPSHOT
+ ../parent-java
+
+
+
+
+ org.apache.commons
+ commons-collections4
+ ${commons-collections4.version}
+
+
+ org.apache.commons
+ commons-lang3
+ ${commons-lang3.version}
+
+
+ org.eclipse.collections
+ eclipse-collections
+ ${eclipse.collections.version}
+
+
+ org.assertj
+ assertj-core
+ ${assertj.version}
+ test
+
+
+ org.junit.platform
+ junit-platform-runner
+ ${junit.platform.version}
+ test
+
+
+ org.openjdk.jmh
+ jmh-core
+ ${openjdk.jmh.version}
+
+
+ org.openjdk.jmh
+ jmh-generator-annprocess
+ ${openjdk.jmh.version}
+
+
+ org.apache.commons
+ commons-exec
+ ${commons-exec.version}
+
+
+ org.projectlombok
+ lombok
+ ${lombok.version}
+ provided
+
+
+
+
+ 1.19
+ 1.2.0
+ 3.8.1
+ 4.1
+ 4.01
+ 1.7.0
+ 3.11.1
+ 7.1.0
+ 1.3
+
+
diff --git a/core-java-collections-map/src/main/java/com/baeldung/copyinghashmap/CopyHashMap.java b/core-java-collections-map/src/main/java/com/baeldung/copyinghashmap/CopyHashMap.java
new file mode 100644
index 0000000000..e1649f593c
--- /dev/null
+++ b/core-java-collections-map/src/main/java/com/baeldung/copyinghashmap/CopyHashMap.java
@@ -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 HashMap copyUsingConstructor(HashMap originalMap) {
+ return new HashMap(originalMap);
+ }
+
+ public static HashMap copyUsingClone(HashMap originalMap) {
+ return (HashMap) originalMap.clone();
+ }
+
+ public static HashMap copyUsingPut(HashMap originalMap) {
+ HashMap shallowCopy = new HashMap();
+ Set> entries = originalMap.entrySet();
+ for(Map.Entry mapEntry: entries) {
+ shallowCopy.put(mapEntry.getKey(), mapEntry.getValue());
+ }
+
+ return shallowCopy;
+ }
+
+ public static HashMap copyUsingPutAll(HashMap originalMap) {
+ HashMap shallowCopy = new HashMap();
+ shallowCopy.putAll(originalMap);
+
+ return shallowCopy;
+ }
+
+ public static HashMap copyUsingJava8Stream(HashMap originalMap) {
+ Set> entries = originalMap.entrySet();
+ HashMap shallowCopy = (HashMap) entries
+ .stream()
+ .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
+
+ return shallowCopy;
+ }
+
+ public static HashMap shallowCopy(HashMap originalMap) {
+ return (HashMap) originalMap.clone();
+ }
+
+ public static HashMap deepCopy(HashMap originalMap) {
+ return SerializationUtils.clone(originalMap);
+ }
+
+}
diff --git a/core-java-collections-map/src/test/java/com/baeldung/copyinghashmap/CopyHashMapUnitTest.java b/core-java-collections-map/src/test/java/com/baeldung/copyinghashmap/CopyHashMapUnitTest.java
new file mode 100644
index 0000000000..400696d97a
--- /dev/null
+++ b/core-java-collections-map/src/test/java/com/baeldung/copyinghashmap/CopyHashMapUnitTest.java
@@ -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 map = new HashMap<>();
+ Employee emp1 = new Employee("John");
+ Employee emp2 = new Employee("Norman");
+ map.put("emp1",emp1);
+ map.put("emp2",emp2);
+
+ HashMap shallowCopy = CopyHashMap.shallowCopy(map);
+
+ assertThat(shallowCopy).isNotSameAs(map);
+
+ }
+
+ @Test
+ public void givenHashMap_whenShallowCopyModifyingOriginalObject_thenCopyShouldChange() {
+
+ HashMap map = new HashMap<>();
+ Employee emp1 = new Employee("John");
+ Employee emp2 = new Employee("Norman");
+ map.put("emp1",emp1);
+ map.put("emp2",emp2);
+
+ HashMap shallowCopy = CopyHashMap.shallowCopy(map);
+
+ emp1.setName("Johny");
+
+ assertThat(shallowCopy.get("emp1")).isEqualTo(map.get("emp1"));
+
+ }
+
+ @Test
+ public void givenHashMap_whenDeepCopyModifyingOriginalObject_thenCopyShouldNotChange() {
+
+ HashMap map = new HashMap<>();
+ Employee emp1 = new Employee("John");
+ Employee emp2 = new Employee("Norman");
+ map.put("emp1",emp1);
+ map.put("emp2",emp2);
+ HashMap 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 map = ImmutableMap. builder()
+ .put("emp1",emp1)
+ .put("emp2",emp2)
+ .build();
+ Map shallowCopy = ImmutableMap.copyOf(map);
+
+ assertThat(shallowCopy).isSameAs(map);
+
+ }
+
+}
diff --git a/core-java-collections-map/src/test/java/com/baeldung/copyinghashmap/Employee.java b/core-java-collections-map/src/test/java/com/baeldung/copyinghashmap/Employee.java
new file mode 100644
index 0000000000..b47fdc768e
--- /dev/null
+++ b/core-java-collections-map/src/test/java/com/baeldung/copyinghashmap/Employee.java
@@ -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;
+ }
+
+}
+
+
diff --git a/core-java-collections-set/README.md b/core-java-collections-set/README.md
new file mode 100644
index 0000000000..710484a2e1
--- /dev/null
+++ b/core-java-collections-set/README.md
@@ -0,0 +1,6 @@
+=========
+
+## Core Java Sets Cookbooks and Examples
+
+### Relevant Articles:
+- [Set Operations in Java](http://www.baeldung.com/set-operations-in-java)
diff --git a/core-java-collections-set/pom.xml b/core-java-collections-set/pom.xml
new file mode 100644
index 0000000000..d5f7937645
--- /dev/null
+++ b/core-java-collections-set/pom.xml
@@ -0,0 +1,33 @@
+
+ 4.0.0
+ core-java-collections-set
+ 0.1.0-SNAPSHOT
+ core-java-collections-set
+ jar
+
+
+ com.baeldung
+ parent-java
+ 0.0.1-SNAPSHOT
+ ../parent-java
+
+
+
+
+ com.google.guava
+ guava
+ ${guava.version}
+
+
+ org.apache.commons
+ commons-collections4
+ ${commons-collections4.version}
+
+
+
+
+ 4.3
+ 27.1-jre
+
+
diff --git a/core-java-collections-set/src/test/java/com/baeldung/set/SetOperationsUnitTest.java b/core-java-collections-set/src/test/java/com/baeldung/set/SetOperationsUnitTest.java
new file mode 100644
index 0000000000..7c25585e49
--- /dev/null
+++ b/core-java-collections-set/src/test/java/com/baeldung/set/SetOperationsUnitTest.java
@@ -0,0 +1,93 @@
+package com.baeldung.set;
+
+import static org.junit.Assert.*;
+
+import org.apache.commons.collections4.SetUtils;
+import org.junit.Test;
+
+import com.google.common.collect.Sets;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+public class SetOperationsUnitTest {
+
+ private Set setA = setOf(1,2,3,4);
+ private Set setB = setOf(2,4,6,8);
+
+ private static Set setOf(Integer... values) {
+ return new HashSet(Arrays.asList(values));
+ }
+
+ @Test
+ public void givenTwoSets_WhenWeRetainAll_ThenWeIntersectThem() {
+ Set intersectSet = new HashSet<>(setA);
+ intersectSet.retainAll(setB);
+ assertEquals(setOf(2,4), intersectSet);
+ }
+
+ @Test
+ public void givenTwoSets_WhenWeAddAll_ThenWeUnionThem() {
+ Set unionSet = new HashSet<>(setA);
+ unionSet.addAll(setB);
+ assertEquals(setOf(1,2,3,4,6,8), unionSet);
+ }
+
+ @Test
+ public void givenTwoSets_WhenRemoveAll_ThenWeGetTheDifference() {
+ Set differenceSet = new HashSet<>(setA);
+ differenceSet.removeAll(setB);
+ assertEquals(setOf(1,3), differenceSet);
+ }
+
+ @Test
+ public void givenTwoStreams_WhenWeFilterThem_ThenWeCanGetTheIntersect() {
+ Set intersectSet = setA.stream()
+ .filter(setB::contains)
+ .collect(Collectors.toSet());
+ assertEquals(setOf(2,4), intersectSet);
+ }
+
+ @Test
+ public void givenTwoStreams_WhenWeConcatThem_ThenWeGetTheUnion() {
+ Set unionSet = Stream.concat(setA.stream(), setB.stream())
+ .collect(Collectors.toSet());
+ assertEquals(setOf(1,2,3,4,6,8), unionSet);
+ }
+
+ @Test
+ public void givenTwoStreams_WhenWeFilterThem_ThenWeCanGetTheDifference() {
+ Set differenceSet = setA.stream()
+ .filter(val -> !setB.contains(val))
+ .collect(Collectors.toSet());
+ assertEquals(setOf(1,3), differenceSet);
+ }
+
+ @Test
+ public void givenTwoSets_WhenWeUseApacheCommonsIntersect_ThenWeGetTheIntersect() {
+ Set intersectSet = SetUtils.intersection(setA, setB);
+ assertEquals(setOf(2,4), intersectSet);
+ }
+
+ @Test
+ public void givenTwoSets_WhenWeUseApacheCommonsUnion_ThenWeGetTheUnion() {
+ Set unionSet = SetUtils.union(setA, setB);
+ assertEquals(setOf(1,2,3,4,6,8), unionSet);
+ }
+
+
+ @Test
+ public void givenTwoSets_WhenWeUseGuavaIntersect_ThenWeGetTheIntersect() {
+ Set intersectSet = Sets.intersection(setA, setB);
+ assertEquals(setOf(2,4), intersectSet);
+ }
+
+ @Test
+ public void givenTwoSets_WhenWeUseGuavaUnion_ThenWeGetTheUnion() {
+ Set unionSet = Sets.union(setA, setB);
+ assertEquals(setOf(1,2,3,4,6,8), unionSet);
+ }
+}
diff --git a/core-java-collections/README.md b/core-java-collections/README.md
index 1e504ded65..43f5bfc384 100644
--- a/core-java-collections/README.md
+++ b/core-java-collections/README.md
@@ -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)
diff --git a/core-java-concurrency-advanced/README.md b/core-java-concurrency-advanced/README.md
index f48fd30c73..8e99858693 100644
--- a/core-java-concurrency-advanced/README.md
+++ b/core-java-concurrency-advanced/README.md
@@ -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)
diff --git a/core-java-concurrency-basic/README.md b/core-java-concurrency-basic/README.md
index 7d106095e7..6fa702fbe7 100644
--- a/core-java-concurrency-basic/README.md
+++ b/core-java-concurrency-basic/README.md
@@ -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)
diff --git a/core-java-io/README.md b/core-java-io/README.md
index 05b9165147..9ce39459dd 100644
--- a/core-java-io/README.md
+++ b/core-java-io/README.md
@@ -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)
diff --git a/core-java-io/src/test/java/com/baeldung/filechannel/FileChannelUnitTest.java b/core-java-io/src/test/java/com/baeldung/filechannel/FileChannelUnitTest.java
new file mode 100644
index 0000000000..6964ba80e3
--- /dev/null
+++ b/core-java-io/src/test/java/com/baeldung/filechannel/FileChannelUnitTest.java
@@ -0,0 +1,165 @@
+package com.baeldung.filechannel;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.io.ByteArrayOutputStream;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.nio.ByteBuffer;
+import java.nio.MappedByteBuffer;
+import java.nio.channels.FileChannel;
+import java.nio.channels.FileLock;
+import java.nio.charset.StandardCharsets;
+
+import org.junit.Test;
+
+public class FileChannelUnitTest {
+
+ @Test
+ public void givenFile_whenReadWithFileChannelUsingRandomAccessFile_thenCorrect() throws IOException {
+
+ try (RandomAccessFile reader = new RandomAccessFile("src/test/resources/test_read.in", "r");
+ FileChannel channel = reader.getChannel();
+ ByteArrayOutputStream out = new ByteArrayOutputStream();) {
+
+ int bufferSize = 1024;
+ if (bufferSize > channel.size()) {
+ bufferSize = (int) channel.size();
+ }
+ ByteBuffer buff = ByteBuffer.allocate(bufferSize);
+
+ while (channel.read(buff) > 0) {
+ out.write(buff.array(), 0, buff.position());
+ buff.clear();
+ }
+
+ String fileContent = new String(out.toByteArray(), StandardCharsets.UTF_8);
+
+ assertEquals("Hello world", fileContent);
+ }
+ }
+
+ @Test
+ public void givenFile_whenReadWithFileChannelUsingFileInputStream_thenCorrect() throws IOException {
+
+ try (ByteArrayOutputStream out = new ByteArrayOutputStream();
+ FileInputStream fin = new FileInputStream("src/test/resources/test_read.in");
+ FileChannel channel = fin.getChannel();) {
+
+ int bufferSize = 1024;
+ if (bufferSize > channel.size()) {
+ bufferSize = (int) channel.size();
+ }
+ ByteBuffer buff = ByteBuffer.allocate(bufferSize);
+
+ while (channel.read(buff) > 0) {
+ out.write(buff.array(), 0, buff.position());
+ buff.clear();
+ }
+ String fileContent = new String(out.toByteArray(), StandardCharsets.UTF_8);
+
+ assertEquals("Hello world", fileContent);
+ }
+ }
+
+ @Test
+ public void givenFile_whenReadAFileSectionIntoMemoryWithFileChannel_thenCorrect() throws IOException {
+
+ try (RandomAccessFile reader = new RandomAccessFile("src/test/resources/test_read.in", "r");
+ FileChannel channel = reader.getChannel();
+ ByteArrayOutputStream out = new ByteArrayOutputStream();) {
+
+ MappedByteBuffer buff = channel.map(FileChannel.MapMode.READ_ONLY, 6, 5);
+
+ if (buff.hasRemaining()) {
+ byte[] data = new byte[buff.remaining()];
+ buff.get(data);
+ assertEquals("world", new String(data, StandardCharsets.UTF_8));
+ }
+ }
+ }
+
+ @Test
+ public void whenWriteWithFileChannelUsingRandomAccessFile_thenCorrect() throws IOException {
+ String file = "src/test/resources/test_write_using_filechannel.txt";
+ try (RandomAccessFile writer = new RandomAccessFile(file, "rw");
+ FileChannel channel = writer.getChannel();) {
+ ByteBuffer buff = ByteBuffer.wrap("Hello world".getBytes(StandardCharsets.UTF_8));
+
+ channel.write(buff);
+
+ // now we verify whether the file was written correctly
+ RandomAccessFile reader = new RandomAccessFile(file, "r");
+ assertEquals("Hello world", reader.readLine());
+ reader.close();
+ }
+ }
+
+ @Test
+ public void givenFile_whenWriteAFileUsingLockAFileSectionWithFileChannel_thenCorrect() throws IOException {
+ try (RandomAccessFile reader = new RandomAccessFile("src/test/resources/test_read.in", "rw");
+ FileChannel channel = reader.getChannel();
+ FileLock fileLock = channel.tryLock(6, 5, Boolean.FALSE);) {
+
+ assertNotNull(fileLock);
+ }
+ }
+
+ @Test
+ public void givenFile_whenReadWithFileChannelGetPosition_thenCorrect() throws IOException {
+
+ try (ByteArrayOutputStream out = new ByteArrayOutputStream();
+ RandomAccessFile reader = new RandomAccessFile("src/test/resources/test_read.in", "r");
+ FileChannel channel = reader.getChannel();) {
+
+ int bufferSize = 1024;
+ if (bufferSize > channel.size()) {
+ bufferSize = (int) channel.size();
+ }
+ ByteBuffer buff = ByteBuffer.allocate(bufferSize);
+
+ while (channel.read(buff) > 0) {
+ out.write(buff.array(), 0, buff.position());
+ buff.clear();
+ }
+
+ // the original file is 11 bytes long, so that's where the position pointer should be
+ assertEquals(11, channel.position());
+
+ channel.position(4);
+ assertEquals(4, channel.position());
+ }
+ }
+
+ @Test
+ public void whenGetFileSize_thenCorrect() throws IOException {
+
+ try (RandomAccessFile reader = new RandomAccessFile("src/test/resources/test_read.in", "r");
+ FileChannel channel = reader.getChannel();) {
+
+ // the original file is 11 bytes long, so that's where the position pointer should be
+ assertEquals(11, channel.size());
+ }
+ }
+
+ @Test
+ public void whenTruncateFile_thenCorrect() throws IOException {
+ String input = "this is a test input";
+
+ FileOutputStream fout = new FileOutputStream("src/test/resources/test_truncate.txt");
+ FileChannel channel = fout.getChannel();
+
+ ByteBuffer buff = ByteBuffer.wrap(input.getBytes());
+ channel.write(buff);
+ buff.flip();
+
+ channel = channel.truncate(5);
+ assertEquals(5, channel.size());
+
+ fout.close();
+ channel.close();
+ }
+}
diff --git a/core-java-io/src/test/resources/test_truncate.txt b/core-java-io/src/test/resources/test_truncate.txt
new file mode 100644
index 0000000000..26d3b38cdd
--- /dev/null
+++ b/core-java-io/src/test/resources/test_truncate.txt
@@ -0,0 +1 @@
+this
\ No newline at end of file
diff --git a/core-java-io/src/test/resources/test_write_using_filechannel.txt b/core-java-io/src/test/resources/test_write_using_filechannel.txt
new file mode 100644
index 0000000000..70c379b63f
--- /dev/null
+++ b/core-java-io/src/test/resources/test_write_using_filechannel.txt
@@ -0,0 +1 @@
+Hello world
\ No newline at end of file
diff --git a/core-java-jvm/README.md b/core-java-jvm/README.md
index 529453f3c4..82067ad952 100644
--- a/core-java-jvm/README.md
+++ b/core-java-jvm/README.md
@@ -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)
diff --git a/core-java-lambdas/pom.xml b/core-java-lambdas/pom.xml
new file mode 100644
index 0000000000..25538a3524
--- /dev/null
+++ b/core-java-lambdas/pom.xml
@@ -0,0 +1,19 @@
+
+
+ 4.0.0
+ core-java-lambdas
+ 0.1.0-SNAPSHOT
+ core-java
+ jar
+
+
+ com.baeldung
+ parent-java
+ 0.0.1-SNAPSHOT
+ ../parent-java
+
+
+
+
\ No newline at end of file
diff --git a/core-java-lambdas/src/main/java/com/baeldung/lambdas/LambdaVariables.java b/core-java-lambdas/src/main/java/com/baeldung/lambdas/LambdaVariables.java
new file mode 100644
index 0000000000..5c1201150f
--- /dev/null
+++ b/core-java-lambdas/src/main/java/com/baeldung/lambdas/LambdaVariables.java
@@ -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 incrementer(int start) {
+ return () -> start; // can't modify start parameter inside the lambda
+ }
+
+ Supplier 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;
+ }
+
+}
diff --git a/core-java-lang-oop-2/README.md b/core-java-lang-oop-2/README.md
index e309810ba2..af0aed5af3 100644
--- a/core-java-lang-oop-2/README.md
+++ b/core-java-lang-oop-2/README.md
@@ -3,3 +3,4 @@
## Core Java Lang OOP 2 Cookbooks and Examples
### Relevant Articles:
+- [Generic Constructors in Java](https://www.baeldung.com/java-generic-constructors)
diff --git a/core-java-lang-oop-2/src/main/java/com/baeldung/anonymous/Book.java b/core-java-lang-oop-2/src/main/java/com/baeldung/anonymous/Book.java
new file mode 100644
index 0000000000..964156e8e4
--- /dev/null
+++ b/core-java-lang-oop-2/src/main/java/com/baeldung/anonymous/Book.java
@@ -0,0 +1,15 @@
+package com.baeldung.anonymous;
+
+public class Book {
+
+ final String title;
+
+ public Book(String title) {
+ this.title = title;
+ }
+
+ public String description() {
+ return "Title: " + title;
+ }
+
+}
diff --git a/core-java-lang-oop-2/src/main/java/com/baeldung/anonymous/Main.java b/core-java-lang-oop-2/src/main/java/com/baeldung/anonymous/Main.java
new file mode 100644
index 0000000000..d4eed69567
--- /dev/null
+++ b/core-java-lang-oop-2/src/main/java/com/baeldung/anonymous/Main.java
@@ -0,0 +1,64 @@
+package com.baeldung.anonymous;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Code snippet that illustrates the usage of anonymous classes.
+ *
+ * Note that use of Runnable instances in this example does not demonstrate their
+ * common use.
+ *
+ * @author A. Shcherbakov
+ *
+ */
+public class Main {
+
+ public static void main(String[] args) {
+ final List actions = new ArrayList(2);
+
+ Runnable action = new Runnable() {
+ @Override
+ public void run() {
+ System.out.println("Hello from runnable.");
+ }
+
+ };
+ actions.add(action);
+
+ Book book = new Book("Design Patterns") {
+ @Override
+ public String description() {
+ return "Famous GoF book.";
+ }
+ };
+
+ System.out.println(String.format("Title: %s, description: %s", book.title, book.description()));
+
+ actions.add(new Runnable() {
+ @Override
+ public void run() {
+ System.out.println("Hello from runnable #2.");
+
+ }
+ });
+
+ int count = 1;
+
+ Runnable action2 = new Runnable() {
+ static final int x = 0;
+ // static int y = 0;
+
+ @Override
+ public void run() {
+ System.out.println(String.format("Runnable with captured variables: count = %s, x = %s", count, x));
+ }
+ };
+ actions.add(action2);
+
+ for (Runnable a : actions) {
+ a.run();
+ }
+ }
+
+}
diff --git a/core-java-lang-oop/README.md b/core-java-lang-oop/README.md
index 970a8d44b1..c9ee9a9e94 100644
--- a/core-java-lang-oop/README.md
+++ b/core-java-lang-oop/README.md
@@ -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)
diff --git a/core-java-lang/README.md b/core-java-lang/README.md
index eaedc93eed..e9169a5820 100644
--- a/core-java-lang/README.md
+++ b/core-java-lang/README.md
@@ -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)
diff --git a/core-java-modules/pom.xml b/core-java-modules/pom.xml
new file mode 100644
index 0000000000..ad49cceb9d
--- /dev/null
+++ b/core-java-modules/pom.xml
@@ -0,0 +1,19 @@
+
+
+ 4.0.0
+ core-java-modules
+ core-java-modules
+ pom
+
+
+ parent-modules
+ com.baeldung
+ 1.0.0-SNAPSHOT
+
+
+
+ pre-jpms
+
+
+
\ No newline at end of file
diff --git a/core-java-modules/pre-jpms/pom.xml b/core-java-modules/pre-jpms/pom.xml
new file mode 100644
index 0000000000..169cd21f3e
--- /dev/null
+++ b/core-java-modules/pre-jpms/pom.xml
@@ -0,0 +1,74 @@
+
+ 4.0.0
+ pre-jpms
+ 0.0.1-SNAPSHOT
+ jar
+ pre-jpms
+
+
+ parent-modules
+ com.baeldung
+ 1.0.0-SNAPSHOT
+ ../../
+
+
+
+
+ org.slf4j
+ slf4j-api
+ 1.7.25
+
+
+
+ pre-jpms
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.8.0
+
+
+ 1.8
+
+
+
+ org.apache.maven.plugins
+ maven-dependency-plugin
+ 3.1.1
+
+
+ copy-dependencies
+ package
+
+ copy-dependencies
+
+
+
+ ${project.build.directory}/dependency-jars/
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-jar-plugin
+
+
+
+ com.baeldung.prejpms.App
+ true
+ dependency-jars/
+
+
+
+
+
+
+
+
+ UTF-8
+
+
diff --git a/core-java-modules/pre-jpms/src/main/java/com/baeldung/prejpms/App.java b/core-java-modules/pre-jpms/src/main/java/com/baeldung/prejpms/App.java
new file mode 100644
index 0000000000..1afaae30e4
--- /dev/null
+++ b/core-java-modules/pre-jpms/src/main/java/com/baeldung/prejpms/App.java
@@ -0,0 +1,77 @@
+package com.baeldung.prejpms;
+
+import java.io.StringWriter;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Marshaller;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.sun.crypto.provider.SunJCE;
+
+import sun.misc.BASE64Encoder;
+import sun.reflect.Reflection;
+
+public class App {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(App.class);
+
+ public static void main(String[] args) throws Exception {
+
+ getCrytpographyProviderName();
+ getCallStackClassNames();
+ getXmlFromObject(new Book(100, "Java Modules Architecture"));
+ getBase64EncodedString("Java");
+ }
+
+ private static void getCrytpographyProviderName() {
+ try {
+ LOGGER.info("1. JCE Provider Name: {}\n", new SunJCE().getName());
+ } catch (Throwable e) {
+ LOGGER.error(e.toString());
+ }
+ }
+
+ private static void getCallStackClassNames() {
+ try {
+ StringBuffer sbStack = new StringBuffer();
+ int i = 0;
+ Class> caller = Reflection.getCallerClass(i++);
+ do {
+ sbStack.append(i + ".")
+ .append(caller.getName())
+ .append("\n");
+ caller = Reflection.getCallerClass(i++);
+ } while (caller != null);
+ LOGGER.info("2. Call Stack:\n{}", sbStack);
+ } catch (Throwable e) {
+ LOGGER.error(e.toString());
+ }
+ }
+
+ private static void getXmlFromObject(Book book) {
+ try {
+ Marshaller marshallerObj = JAXBContext.newInstance(Book.class)
+ .createMarshaller();
+ marshallerObj.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
+
+ StringWriter sw = new StringWriter();
+ marshallerObj.marshal(book, sw);
+ LOGGER.info("3. Xml for Book object:\n{}", sw);
+ } catch (Throwable e) {
+ LOGGER.error(e.toString());
+ }
+
+ }
+
+ private static void getBase64EncodedString(String inputString) {
+ try {
+ String encodedString = new BASE64Encoder().encode(inputString.getBytes());
+ LOGGER.info("4. Base Encoded String: {}", encodedString);
+ } catch (Throwable e) {
+ LOGGER.error(e.toString());
+ }
+ }
+}
diff --git a/core-java-modules/pre-jpms/src/main/java/com/baeldung/prejpms/Book.java b/core-java-modules/pre-jpms/src/main/java/com/baeldung/prejpms/Book.java
new file mode 100644
index 0000000000..6780c73738
--- /dev/null
+++ b/core-java-modules/pre-jpms/src/main/java/com/baeldung/prejpms/Book.java
@@ -0,0 +1,37 @@
+package com.baeldung.prejpms;
+
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+@XmlRootElement(name = "book")
+public class Book {
+ private long id;
+ private String name;
+
+ public Book() {
+ }
+
+ public Book(long id, String name) {
+ this.id = id;
+ this.name = name;
+ }
+
+ @XmlAttribute
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ @XmlElement(name = "title")
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public Long getId() {
+ return id;
+ }
+}
diff --git a/core-java-modules/pre-jpms/src/main/resources/logback.xml b/core-java-modules/pre-jpms/src/main/resources/logback.xml
new file mode 100644
index 0000000000..7c5914e58e
--- /dev/null
+++ b/core-java-modules/pre-jpms/src/main/resources/logback.xml
@@ -0,0 +1,10 @@
+
+
+
+ [%level] %msg%n
+
+
+
+
+
+
\ No newline at end of file
diff --git a/core-java-networking/README.md b/core-java-networking/README.md
index e76f28030d..2341520df7 100644
--- a/core-java-networking/README.md
+++ b/core-java-networking/README.md
@@ -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)
\ No newline at end of file
+- [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)
diff --git a/core-java-networking/src/main/java/com/baeldung/networking/cookies/ProxyAcceptCookiePolicy.java b/core-java-networking/src/main/java/com/baeldung/networking/cookies/ProxyAcceptCookiePolicy.java
index 0b5f6d7714..9fbbee8501 100644
--- a/core-java-networking/src/main/java/com/baeldung/networking/cookies/ProxyAcceptCookiePolicy.java
+++ b/core-java-networking/src/main/java/com/baeldung/networking/cookies/ProxyAcceptCookiePolicy.java
@@ -17,8 +17,8 @@ public class ProxyAcceptCookiePolicy implements CookiePolicy {
host = uri.getHost();
}
- if (!HttpCookie.domainMatches(acceptedProxy, host)) {
- return false;
+ if (HttpCookie.domainMatches(acceptedProxy, host)) {
+ return true;
}
return CookiePolicy.ACCEPT_ORIGINAL_SERVER.shouldAccept(uri, cookie);
diff --git a/core-java/README.md b/core-java/README.md
index cbc9251b0b..c2d1b4a06b 100644
--- a/core-java/README.md
+++ b/core-java/README.md
@@ -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)
diff --git a/core-kotlin-2/README.md b/core-kotlin-2/README.md
index 4ac1c2c7bb..6d0b20135d 100644
--- a/core-kotlin-2/README.md
+++ b/core-kotlin-2/README.md
@@ -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)
\ No newline at end of file
diff --git a/core-kotlin-2/build.gradle b/core-kotlin-2/build.gradle
index b058e0ecad..1c52172404 100644
--- a/core-kotlin-2/build.gradle
+++ b/core-kotlin-2/build.gradle
@@ -5,7 +5,7 @@ version '1.0-SNAPSHOT'
buildscript {
- ext.kotlin_version = '1.2.41'
+ ext.kotlin_version = '1.3.30'
repositories {
mavenCentral()
@@ -26,8 +26,6 @@ sourceCompatibility = 1.8
compileKotlin { kotlinOptions.jvmTarget = "1.8" }
compileTestKotlin { kotlinOptions.jvmTarget = "1.8" }
-kotlin { experimental { coroutines "enable" } }
-
repositories {
mavenCentral()
jcenter()
@@ -39,10 +37,22 @@ sourceSets {
srcDirs 'com/baeldung/ktor'
}
}
+}
+test {
+ useJUnitPlatform()
+ testLogging {
+ events "passed", "skipped", "failed"
+ }
}
dependencies {
- compile "ch.qos.logback:logback-classic:1.2.1"
- testCompile group: 'junit', name: 'junit', version: '4.12'
-}
\ No newline at end of file
+ implementation "ch.qos.logback:logback-classic:1.2.1"
+ implementation "org.jetbrains.kotlin:kotlin-stdlib:${kotlin_version}"
+ testImplementation 'org.junit.jupiter:junit-jupiter:5.4.2'
+ testImplementation 'junit:junit:4.12'
+ testImplementation 'org.assertj:assertj-core:3.12.2'
+ testImplementation 'org.mockito:mockito-core:2.27.0'
+ testImplementation "org.jetbrains.kotlin:kotlin-test:${kotlin_version}"
+ testImplementation "org.jetbrains.kotlin:kotlin-test-junit5:${kotlin_version}"
+}
diff --git a/core-kotlin-2/gradle/wrapper/gradle-wrapper.jar b/core-kotlin-2/gradle/wrapper/gradle-wrapper.jar
index 01b8bf6b1f..5c2d1cf016 100644
Binary files a/core-kotlin-2/gradle/wrapper/gradle-wrapper.jar and b/core-kotlin-2/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/core-kotlin-2/gradle/wrapper/gradle-wrapper.properties b/core-kotlin-2/gradle/wrapper/gradle-wrapper.properties
index 933b6473ce..5f1b1201a7 100644
--- a/core-kotlin-2/gradle/wrapper/gradle-wrapper.properties
+++ b/core-kotlin-2/gradle/wrapper/gradle-wrapper.properties
@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-5.4-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-bin.zip
diff --git a/core-kotlin-2/gradlew b/core-kotlin-2/gradlew
index cccdd3d517..b0d6d0ab5d 100644
--- a/core-kotlin-2/gradlew
+++ b/core-kotlin-2/gradlew
@@ -1,5 +1,21 @@
#!/usr/bin/env sh
+#
+# Copyright 2015 the original author or authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
##############################################################################
##
## Gradle start up script for UN*X
@@ -28,7 +44,7 @@ APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
-DEFAULT_JVM_OPTS=""
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
diff --git a/core-kotlin-2/gradlew.bat b/core-kotlin-2/gradlew.bat
index f9553162f1..9991c50326 100644
--- a/core-kotlin-2/gradlew.bat
+++ b/core-kotlin-2/gradlew.bat
@@ -1,3 +1,19 @@
+@rem
+@rem Copyright 2015 the original author or authors.
+@rem
+@rem Licensed under the Apache License, Version 2.0 (the "License");
+@rem you may not use this file except in compliance with the License.
+@rem You may obtain a copy of the License at
+@rem
+@rem http://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing, software
+@rem distributed under the License is distributed on an "AS IS" BASIS,
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem See the License for the specific language governing permissions and
+@rem limitations under the License.
+@rem
+
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@@ -14,7 +30,7 @@ set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
-set DEFAULT_JVM_OPTS=
+set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
diff --git a/core-kotlin-2/pom.xml b/core-kotlin-2/pom.xml
index e329611593..be2f5fa68f 100644
--- a/core-kotlin-2/pom.xml
+++ b/core-kotlin-2/pom.xml
@@ -20,9 +20,21 @@
${kotlin.version}
- org.junit.platform
- junit-platform-runner
- ${junit.platform.version}
+ org.junit.jupiter
+ junit-jupiter
+ ${junit.jupiter.version}
+ test
+
+
+ org.mockito
+ mockito-core
+ ${mockito.version}
+ test
+
+
+ net.bytebuddy
+ byte-buddy
+ ${byte-buddy.version}
test
@@ -37,6 +49,12 @@
${kotlin.version}
test
+
+ org.jetbrains.kotlin
+ kotlin-test-junit5
+ ${kotlin.version}
+ test
+
@@ -69,10 +87,11 @@
- 1.2.71
- 1.1.1
- 5.2.0
+ 1.3.30
+ 5.4.2
+ 2.27.0
+ 1.9.12
3.10.0
-
\ No newline at end of file
+
diff --git a/core-kotlin-io/.gitignore b/core-kotlin-io/.gitignore
new file mode 100644
index 0000000000..f521947850
--- /dev/null
+++ b/core-kotlin-io/.gitignore
@@ -0,0 +1,11 @@
+/bin/
+
+#ignore gradle
+.gradle/
+
+
+#ignore build and generated files
+build/
+node/
+target/
+out/
diff --git a/core-kotlin-io/README.md b/core-kotlin-io/README.md
new file mode 100644
index 0000000000..c085c0653f
--- /dev/null
+++ b/core-kotlin-io/README.md
@@ -0,0 +1,3 @@
+## Relevant articles:
+
+- [InputStream to String in Kotlin](https://www.baeldung.com/kotlin-inputstream-to-string)
diff --git a/core-kotlin-io/pom.xml b/core-kotlin-io/pom.xml
new file mode 100644
index 0000000000..a0b688a223
--- /dev/null
+++ b/core-kotlin-io/pom.xml
@@ -0,0 +1,97 @@
+
+
+ 4.0.0
+ core-kotlin-io
+ core-kotlin-io
+ jar
+
+
+ com.baeldung
+ parent-kotlin
+ 1.0.0-SNAPSHOT
+ ../parent-kotlin
+
+
+
+
+ org.jetbrains.kotlin
+ kotlin-stdlib-jdk8
+ ${kotlin.version}
+
+
+ org.junit.jupiter
+ junit-jupiter
+ ${junit.jupiter.version}
+ test
+
+
+ org.mockito
+ mockito-core
+ ${mockito.version}
+ test
+
+
+ net.bytebuddy
+ byte-buddy
+ ${byte-buddy.version}
+ test
+
+
+ org.assertj
+ assertj-core
+ ${assertj.version}
+ test
+
+
+ org.jetbrains.kotlin
+ kotlin-test
+ ${kotlin.version}
+ test
+
+
+ org.jetbrains.kotlin
+ kotlin-test-junit5
+ ${kotlin.version}
+ test
+
+
+
+
+
+
+ org.jetbrains.kotlin
+ kotlin-maven-plugin
+ ${kotlin.version}
+
+
+ compile
+ compile
+
+ compile
+
+
+
+ test-compile
+ test-compile
+
+ test-compile
+
+
+
+
+ 1.8
+
+
+
+
+
+
+ 1.3.30
+ 5.4.2
+ 2.27.0
+ 1.9.12
+ 3.10.0
+
+
+
diff --git a/core-kotlin-io/src/main/kotlin/com/baeldung/inputstream/InputStreamExtension.kt b/core-kotlin-io/src/main/kotlin/com/baeldung/inputstream/InputStreamExtension.kt
new file mode 100644
index 0000000000..e94a2e84ee
--- /dev/null
+++ b/core-kotlin-io/src/main/kotlin/com/baeldung/inputstream/InputStreamExtension.kt
@@ -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()
+}
+
diff --git a/core-kotlin-io/src/test/kotlin/com/baeldung/console/ConsoleIOUnitTest.kt b/core-kotlin-io/src/test/kotlin/com/baeldung/console/ConsoleIOUnitTest.kt
new file mode 100644
index 0000000000..c73096fce6
--- /dev/null
+++ b/core-kotlin-io/src/test/kotlin/com/baeldung/console/ConsoleIOUnitTest.kt
@@ -0,0 +1,79 @@
+package com.baeldung.console
+
+import org.assertj.core.api.Assertions.assertThat
+import org.junit.jupiter.api.AfterEach
+import org.junit.jupiter.api.Test
+import org.mockito.Mockito.`when`
+import org.mockito.Mockito.mock
+import java.io.BufferedReader
+import java.io.ByteArrayInputStream
+import java.io.ByteArrayOutputStream
+import java.io.Console
+import java.io.InputStreamReader
+import java.io.PrintStream
+import java.util.*
+
+
+class ConsoleIOUnitTest {
+
+ @Test
+ fun givenText_whenPrint_thenPrintText() {
+ val expectedTest = "Hello from Kotlin"
+ val out = ByteArrayOutputStream()
+ System.setOut(PrintStream(out))
+
+ print(expectedTest)
+ out.flush()
+ val printedText = String(out.toByteArray())
+
+ assertThat(printedText).isEqualTo(expectedTest)
+ }
+
+ @Test
+ fun givenInput_whenRead_thenReadText() {
+ val expectedTest = "Hello from Kotlin"
+ val input = ByteArrayInputStream(expectedTest.toByteArray())
+ System.setIn(input)
+
+ val readText = readLine()
+
+ assertThat(readText).isEqualTo(expectedTest)
+ }
+
+ @Test
+ fun givenInput_whenReadWithScanner_thenReadText() {
+ val expectedTest = "Hello from Kotlin"
+ val scanner = Scanner(ByteArrayInputStream(expectedTest.toByteArray()))
+
+ val readText = scanner.nextLine()
+
+ assertThat(readText).isEqualTo(expectedTest)
+ }
+
+ @Test
+ fun givenInput_whenReadWithBufferedReader_thenReadText() {
+ val expectedTest = "Hello from Kotlin"
+ val reader = BufferedReader(InputStreamReader(ByteArrayInputStream(expectedTest.toByteArray())))
+
+ val readText = reader.readLine()
+
+ assertThat(readText).isEqualTo(expectedTest)
+ }
+
+ @Test
+ fun givenInput_whenReadWithConsole_thenReadText() {
+ val expectedTest = "Hello from Kotlin"
+ val console = mock(Console::class.java)
+ `when`(console.readLine()).thenReturn(expectedTest)
+
+ val readText = console.readLine()
+
+ assertThat(readText).isEqualTo(expectedTest)
+ }
+
+ @AfterEach
+ fun resetIO() {
+ System.setOut(System.out)
+ System.setIn(System.`in`)
+ }
+}
\ No newline at end of file
diff --git a/core-kotlin-io/src/test/kotlin/com/baeldung/inputstream/InputStreamToStringTest.kt b/core-kotlin-io/src/test/kotlin/com/baeldung/inputstream/InputStreamToStringTest.kt
new file mode 100644
index 0000000000..d10d23bef0
--- /dev/null
+++ b/core-kotlin-io/src/test/kotlin/com/baeldung/inputstream/InputStreamToStringTest.kt
@@ -0,0 +1,72 @@
+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 endOfLine = System.lineSeparator()
+ private val fileFullContent = "Computer programming can be a hassle$endOfLine" +
+ "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(endOfLine, ""), 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)
+ }
+
+
+}
+
diff --git a/core-kotlin-io/src/test/resources/inputstream2string.txt b/core-kotlin-io/src/test/resources/inputstream2string.txt
new file mode 100644
index 0000000000..40ef9fc5f3
--- /dev/null
+++ b/core-kotlin-io/src/test/resources/inputstream2string.txt
@@ -0,0 +1,2 @@
+Computer programming can be a hassle
+It's like trying to take a defended castle
\ No newline at end of file
diff --git a/core-kotlin-io/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker b/core-kotlin-io/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker
new file mode 100644
index 0000000000..ca6ee9cea8
--- /dev/null
+++ b/core-kotlin-io/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker
@@ -0,0 +1 @@
+mock-maker-inline
\ No newline at end of file
diff --git a/core-kotlin/README.md b/core-kotlin/README.md
index 73a78eccff..3392db9171 100644
--- a/core-kotlin/README.md
+++ b/core-kotlin/README.md
@@ -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)
diff --git a/core-kotlin/src/test/java/com/baeldung/kotlin/StringUtilTest.java b/core-kotlin/src/test/java/com/baeldung/kotlin/StringUtilUnitTest.java
similarity index 94%
rename from core-kotlin/src/test/java/com/baeldung/kotlin/StringUtilTest.java
rename to core-kotlin/src/test/java/com/baeldung/kotlin/StringUtilUnitTest.java
index 3f109b78a2..c7ef18b879 100644
--- a/core-kotlin/src/test/java/com/baeldung/kotlin/StringUtilTest.java
+++ b/core-kotlin/src/test/java/com/baeldung/kotlin/StringUtilUnitTest.java
@@ -7,7 +7,7 @@ import org.junit.Test;
import static com.baeldung.kotlin.Strings.*;
-public class StringUtilTest {
+public class StringUtilUnitTest {
@Test
public void shouldEscapeXmlTagsInString() {
diff --git a/couchbase/README.md b/couchbase/README.md
index 9b76609593..7a99ce4299 100644
--- a/couchbase/README.md
+++ b/couchbase/README.md
@@ -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)
diff --git a/fastUtil/pom.xml b/fastUtil/pom.xml
new file mode 100644
index 0000000000..fcd9020747
--- /dev/null
+++ b/fastUtil/pom.xml
@@ -0,0 +1,44 @@
+
+
+ 4.0.0
+
+ com.baeldung
+ fastUtil
+ 1.0-SNAPSHOT
+
+
+
+
+ it.unimi.dsi
+ fastutil
+ 8.2.2
+
+
+
+ junit
+ junit
+ 4.12
+ test
+
+
+
+ org.openjdk.jmh
+ jmh-core
+ 1.19
+ test
+
+
+ org.openjdk.jmh
+ jmh-generator-annprocess
+ 1.19
+ test
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/fastUtil/src/test/java/com/baeldung/BigArraysUnitTest.java b/fastUtil/src/test/java/com/baeldung/BigArraysUnitTest.java
new file mode 100644
index 0000000000..a794d1a2f6
--- /dev/null
+++ b/fastUtil/src/test/java/com/baeldung/BigArraysUnitTest.java
@@ -0,0 +1,23 @@
+package com.baeldung;
+
+import it.unimi.dsi.fastutil.ints.IntBigArrays;
+import org.junit.Test;
+
+import static junit.framework.Assert.assertEquals;
+
+public class BigArraysUnitTest {
+
+ @Test
+ public void givenValidAray_whenWrapped_checkAccessFromIntBigArraysMethodsCorrect() {
+ int[] oneDArray = new int[] { 2, 1, 5, 2, 1, 7 };
+ int[][] twoDArray = IntBigArrays.wrap(oneDArray.clone());
+
+ int firstIndex = IntBigArrays.get(twoDArray, 0);
+ int lastIndex = IntBigArrays.get(twoDArray, IntBigArrays.length(twoDArray)-1);
+
+ assertEquals(2, firstIndex);
+ assertEquals(7, lastIndex);
+
+ }
+
+}
diff --git a/fastUtil/src/test/java/com/baeldung/FastUtilTypeSpecificBenchmarkUnitTest.java b/fastUtil/src/test/java/com/baeldung/FastUtilTypeSpecificBenchmarkUnitTest.java
new file mode 100644
index 0000000000..2c77989fe5
--- /dev/null
+++ b/fastUtil/src/test/java/com/baeldung/FastUtilTypeSpecificBenchmarkUnitTest.java
@@ -0,0 +1,58 @@
+package com.baeldung;
+
+import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
+import it.unimi.dsi.fastutil.ints.IntSet;
+import org.openjdk.jmh.annotations.*;
+import org.openjdk.jmh.infra.Blackhole;
+import org.openjdk.jmh.runner.Runner;
+import org.openjdk.jmh.runner.RunnerException;
+import org.openjdk.jmh.runner.options.Options;
+import org.openjdk.jmh.runner.options.OptionsBuilder;
+
+import java.util.*;
+import java.util.concurrent.TimeUnit;
+
+@BenchmarkMode(Mode.AverageTime)
+@OutputTimeUnit(TimeUnit.MICROSECONDS)
+@State(Scope.Benchmark)
+public class FastUtilTypeSpecificBenchmarkUnitTest {
+
+ @Param({"100", "1000", "10000", "100000"})
+ public int setSize;
+
+ @Benchmark
+ public IntSet givenFastUtilsIntSetWithInitialSizeSet_whenPopulated_checkTimeTaken() {
+ IntSet intSet = new IntOpenHashSet(setSize);
+ for(int i = 0; i < setSize; i++){
+ intSet.add(i);
+ }
+ return intSet;
+ }
+
+
+ @Benchmark
+ public Set givenCollectionsHashSetWithInitialSizeSet_whenPopulated_checkTimeTaken() {
+ Set intSet = new HashSet(setSize);
+ for(int i = 0; i < setSize; i++){
+ intSet.add(i);
+ }
+ return intSet;
+ }
+
+ public static void main(String... args) throws RunnerException {
+ Options opts = new OptionsBuilder()
+ .include(".*")
+ .warmupIterations(1)
+ .measurementIterations(2)
+ .jvmArgs("-Xms2g", "-Xmx2g")
+ .shouldDoGC(true)
+ .forks(1)
+ .build();
+
+ new Runner(opts).run();
+ }
+
+
+
+
+}
diff --git a/fastUtil/src/test/java/com/baeldung/FastUtilTypeSpecificUnitTest.java b/fastUtil/src/test/java/com/baeldung/FastUtilTypeSpecificUnitTest.java
new file mode 100644
index 0000000000..61295cc6f1
--- /dev/null
+++ b/fastUtil/src/test/java/com/baeldung/FastUtilTypeSpecificUnitTest.java
@@ -0,0 +1,20 @@
+package com.baeldung;
+
+import it.unimi.dsi.fastutil.doubles.Double2DoubleMap;
+import it.unimi.dsi.fastutil.doubles.Double2DoubleOpenHashMap;
+import org.junit.Test;
+
+import static junit.framework.Assert.assertEquals;
+
+
+public class FastUtilTypeSpecificUnitTest {
+
+ @Test
+ public void givenValidDouble2DoubleMap_whenContentsQueried_checkCorrect(){
+ Double2DoubleMap d2dMap = new Double2DoubleOpenHashMap();
+ d2dMap.put(2.0, 5.5);
+ d2dMap.put(3.0, 6.6);
+ assertEquals(5.5, d2dMap.get(2.0));
+ }
+
+}
diff --git a/gson/README.md b/gson/README.md
index fec0506488..268116a2ac 100644
--- a/gson/README.md
+++ b/gson/README.md
@@ -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)
diff --git a/guava-collections-set/.gitignore b/guava-collections-set/.gitignore
new file mode 100644
index 0000000000..83c05e60c8
--- /dev/null
+++ b/guava-collections-set/.gitignore
@@ -0,0 +1,13 @@
+*.class
+
+#folders#
+/target
+/neoDb*
+/data
+/src/main/webapp/WEB-INF/classes
+*/META-INF/*
+
+# Packaged files #
+*.jar
+*.war
+*.ear
\ No newline at end of file
diff --git a/guava-collections-set/pom.xml b/guava-collections-set/pom.xml
new file mode 100644
index 0000000000..46dcae492d
--- /dev/null
+++ b/guava-collections-set/pom.xml
@@ -0,0 +1,37 @@
+
+ 4.0.0
+ com.baeldung
+ guava-collections-set
+ 0.1.0-SNAPSHOT
+ guava-collections-set
+
+
+ com.baeldung
+ parent-java
+ 0.0.1-SNAPSHOT
+ ../parent-java
+
+
+
+
+
+ org.assertj
+ assertj-core
+ ${assertj.version}
+ test
+
+
+
+
+ guava-collections-set
+
+
+
+
+ 27.1-jre
+
+ 3.6.1
+
+
+
diff --git a/guava-collections-set/src/test/java/org/baeldung/guava/GuavaMultiSetUnitTest.java b/guava-collections-set/src/test/java/org/baeldung/guava/GuavaMultiSetUnitTest.java
new file mode 100644
index 0000000000..e74db29881
--- /dev/null
+++ b/guava-collections-set/src/test/java/org/baeldung/guava/GuavaMultiSetUnitTest.java
@@ -0,0 +1,92 @@
+package org.baeldung.guava;
+
+import com.google.common.collect.HashMultiset;
+import com.google.common.collect.Multiset;
+import org.junit.Test;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+public class GuavaMultiSetUnitTest {
+
+ @Test
+ public void givenMultiSet_whenAddingValues_shouldReturnCorrectCount() {
+ Multiset bookStore = HashMultiset.create();
+ bookStore.add("Potter");
+ bookStore.add("Potter");
+ bookStore.add("Potter");
+
+ assertThat(bookStore.contains("Potter")).isTrue();
+ assertThat(bookStore.count("Potter")).isEqualTo(3);
+ }
+
+ @Test
+ public void givenMultiSet_whenRemovingValues_shouldReturnCorrectCount() {
+ Multiset bookStore = HashMultiset.create();
+ bookStore.add("Potter");
+ bookStore.add("Potter");
+
+ bookStore.remove("Potter");
+ assertThat(bookStore.contains("Potter")).isTrue();
+ assertThat(bookStore.count("Potter")).isEqualTo(1);
+ }
+
+ @Test
+ public void givenMultiSet_whenSetCount_shouldReturnCorrectCount() {
+ Multiset bookStore = HashMultiset.create();
+ bookStore.setCount("Potter", 50);
+ assertThat(bookStore.count("Potter")).isEqualTo(50);
+ }
+
+ @Test
+ public void givenMultiSet_whenSettingNegativeCount_shouldThrowException() {
+ Multiset bookStore = HashMultiset.create();
+ assertThatThrownBy(() -> bookStore.setCount("Potter", -1))
+ .isInstanceOf(IllegalArgumentException.class);
+ }
+
+ @Test
+ public void givenMultiSet_whenSettingCountWithEmptySet_shouldBeSuccessful() {
+ Multiset bookStore = HashMultiset.create();
+ assertThat(bookStore.setCount("Potter", 0, 2)).isTrue();
+ }
+
+ @Test
+ public void givenMultiSet_whenSettingCountWithCorrectValue_shouldBeSuccessful() {
+ Multiset bookStore = HashMultiset.create();
+ bookStore.add("Potter");
+ bookStore.add("Potter");
+
+ assertThat(bookStore.setCount("Potter", 2, 52)).isTrue();
+ }
+
+ @Test
+ public void givenMultiSet_whenSettingCountWithIncorrectValue_shouldFail() {
+ Multiset bookStore = HashMultiset.create();
+ bookStore.add("Potter");
+ bookStore.add("Potter");
+
+ assertThat(bookStore.setCount("Potter", 5, 52)).isFalse();
+ }
+
+ @Test
+ public void givenMap_compareMultiSetOperations() {
+ Map bookStore = new HashMap<>();
+ bookStore.put("Potter", 3);
+
+ assertThat(bookStore.containsKey("Potter")).isTrue();
+ assertThat(bookStore.get("Potter")).isEqualTo(3);
+
+ bookStore.put("Potter", 2);
+ assertThat(bookStore.get("Potter")).isEqualTo(2);
+
+ bookStore.put("Potter", null);
+ assertThat(bookStore.containsKey("Potter")).isTrue();
+
+ bookStore.put("Potter", -1);
+ assertThat(bookStore.containsKey("Potter")).isTrue();
+ }
+}
\ No newline at end of file
diff --git a/guava-modules/guava-21/README.md b/guava-modules/guava-21/README.md
index 68c1ac4a8e..4e897325b6 100644
--- a/guava-modules/guava-21/README.md
+++ b/guava-modules/guava-21/README.md
@@ -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)
diff --git a/httpclient-simple/.gitignore b/httpclient-simple/.gitignore
new file mode 100644
index 0000000000..83c05e60c8
--- /dev/null
+++ b/httpclient-simple/.gitignore
@@ -0,0 +1,13 @@
+*.class
+
+#folders#
+/target
+/neoDb*
+/data
+/src/main/webapp/WEB-INF/classes
+*/META-INF/*
+
+# Packaged files #
+*.jar
+*.war
+*.ear
\ No newline at end of file
diff --git a/httpclient-simple/README.md b/httpclient-simple/README.md
new file mode 100644
index 0000000000..96d9e9ec0e
--- /dev/null
+++ b/httpclient-simple/README.md
@@ -0,0 +1,12 @@
+=========
+## HttpClient 4.x Cookbooks and Examples
+
+###The Course
+The "REST With Spring" Classes: http://bit.ly/restwithspring
+
+
+### Relevant Articles:
+
+- [HttpClient 4 – Get the Status Code](http://www.baeldung.com/httpclient-status-code)
+- [HttpClient with SSL](http://www.baeldung.com/httpclient-ssl)
+- [HttpClient Basic Authentication](http://www.baeldung.com/httpclient-4-basic-authentication)
diff --git a/httpclient-simple/pom.xml b/httpclient-simple/pom.xml
new file mode 100644
index 0000000000..f3d00251d7
--- /dev/null
+++ b/httpclient-simple/pom.xml
@@ -0,0 +1,315 @@
+
+ 4.0.0
+ com.baeldung
+ httpclient-simple
+ 0.1-SNAPSHOT
+ httpclient-simple
+ war
+
+
+ com.baeldung
+ parent-spring-5
+ 0.0.1-SNAPSHOT
+ ../parent-spring-5
+
+
+
+
+
+
+
+ org.springframework.security
+ spring-security-web
+ ${spring.version}
+
+
+ org.springframework.security
+ spring-security-config
+ ${spring.version}
+
+
+
+
+
+ org.springframework
+ spring-core
+ ${spring.version}
+
+
+ commons-logging
+ commons-logging
+
+
+
+
+ org.springframework
+ spring-context
+ ${spring.version}
+
+
+ org.springframework
+ spring-jdbc
+ ${spring.version}
+
+
+ org.springframework
+ spring-beans
+ ${spring.version}
+
+
+ org.springframework
+ spring-aop
+ ${spring.version}
+
+
+ org.springframework
+ spring-tx
+ ${spring.version}
+
+
+ org.springframework
+ spring-expression
+ ${spring.version}
+
+
+
+ org.springframework
+ spring-web
+ ${spring.version}
+
+
+ org.springframework
+ spring-webmvc
+ ${spring.version}
+
+
+
+ org.springframework
+ spring-oxm
+ ${spring.version}
+
+
+
+
+
+ com.fasterxml.jackson.core
+ jackson-databind
+ ${jackson.version}
+
+
+
+ org.apache.httpcomponents
+ httpcore
+ ${httpcore.version}
+
+
+ commons-logging
+ commons-logging
+
+
+
+
+
+
+ org.apache.commons
+ commons-lang3
+ ${commons-lang3.version}
+
+
+
+ org.apache.httpcomponents
+ httpclient
+ ${httpclient.version}
+
+
+ commons-logging
+ commons-logging
+
+
+
+
+ org.apache.httpcomponents
+ fluent-hc
+ ${httpclient.version}
+
+
+ commons-logging
+ commons-logging
+
+
+
+
+ org.apache.httpcomponents
+ httpmime
+ ${httpclient.version}
+
+
+ commons-codec
+ commons-codec
+ ${commons-codec.version}
+
+
+ org.apache.httpcomponents
+ httpasyncclient
+ ${httpasyncclient.version}
+
+
+ commons-logging
+ commons-logging
+
+
+
+
+ com.github.tomakehurst
+ wiremock
+ ${wiremock.version}
+ test
+
+
+
+
+
+ javax.servlet
+ javax.servlet-api
+ ${javax.servlet.version}
+ provided
+
+
+
+ javax.servlet
+ jstl
+ ${jstl.version}
+ runtime
+
+
+
+
+
+ com.google.guava
+ guava
+ ${guava.version}
+
+
+
+
+
+ org.springframework
+ spring-test
+ ${spring.version}
+ test
+
+
+
+
+ httpclient-simple
+
+
+ src/main/resources
+ true
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-war-plugin
+ ${maven-war-plugin.version}
+
+
+ org.codehaus.cargo
+ cargo-maven2-plugin
+ ${cargo-maven2-plugin.version}
+
+ true
+
+ jetty8x
+ embedded
+
+
+
+
+
+
+ 8082
+
+
+
+
+
+
+
+
+
+ live
+
+
+
+ org.codehaus.cargo
+ cargo-maven2-plugin
+
+
+ start-server
+ pre-integration-test
+
+ start
+
+
+
+ stop-server
+ post-integration-test
+
+ stop
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+
+
+ integration-test
+
+ test
+
+
+
+ none
+
+
+ **/*LiveTest.java
+
+
+ cargo
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1.2
+ 3.1.0
+
+ 19.0
+ 3.5
+ 1.10
+ 4.1.4
+
+ 2.5.1
+ 4.4.11
+ 4.5.8
+
+ 2.6
+ 1.6.1
+
+
+
\ No newline at end of file
diff --git a/httpclient-simple/src/main/java/org/baeldung/basic/MyBasicAuthenticationEntryPoint.java b/httpclient-simple/src/main/java/org/baeldung/basic/MyBasicAuthenticationEntryPoint.java
new file mode 100644
index 0000000000..6e580e7a22
--- /dev/null
+++ b/httpclient-simple/src/main/java/org/baeldung/basic/MyBasicAuthenticationEntryPoint.java
@@ -0,0 +1,30 @@
+package org.baeldung.basic;
+
+import org.springframework.security.core.AuthenticationException;
+import org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint;
+import org.springframework.stereotype.Component;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.io.PrintWriter;
+
+@Component
+public class MyBasicAuthenticationEntryPoint extends BasicAuthenticationEntryPoint {
+
+ @Override
+ public void commence(final HttpServletRequest request, final HttpServletResponse response, final AuthenticationException authException) throws IOException, ServletException {
+ response.addHeader("WWW-Authenticate", "Basic realm=\"" + getRealmName() + "\"");
+ response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
+ final PrintWriter writer = response.getWriter();
+ writer.println("HTTP Status " + HttpServletResponse.SC_UNAUTHORIZED + " - " + authException.getMessage());
+ }
+
+ @Override
+ public void afterPropertiesSet() throws Exception {
+ setRealmName("Baeldung");
+ super.afterPropertiesSet();
+ }
+
+}
diff --git a/httpclient-simple/src/main/java/org/baeldung/client/HttpComponentsClientHttpRequestFactoryBasicAuth.java b/httpclient-simple/src/main/java/org/baeldung/client/HttpComponentsClientHttpRequestFactoryBasicAuth.java
new file mode 100644
index 0000000000..a2f51d343b
--- /dev/null
+++ b/httpclient-simple/src/main/java/org/baeldung/client/HttpComponentsClientHttpRequestFactoryBasicAuth.java
@@ -0,0 +1,39 @@
+package org.baeldung.client;
+
+import java.net.URI;
+
+import org.apache.http.HttpHost;
+import org.apache.http.client.AuthCache;
+import org.apache.http.client.protocol.HttpClientContext;
+import org.apache.http.impl.auth.BasicScheme;
+import org.apache.http.impl.client.BasicAuthCache;
+import org.apache.http.protocol.BasicHttpContext;
+import org.apache.http.protocol.HttpContext;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
+
+public class HttpComponentsClientHttpRequestFactoryBasicAuth extends HttpComponentsClientHttpRequestFactory {
+
+ HttpHost host;
+
+ public HttpComponentsClientHttpRequestFactoryBasicAuth(HttpHost host) {
+ super();
+ this.host = host;
+ }
+
+ protected HttpContext createHttpContext(HttpMethod httpMethod, URI uri) {
+ return createHttpContext();
+ }
+
+ private HttpContext createHttpContext() {
+
+ AuthCache authCache = new BasicAuthCache();
+
+ BasicScheme basicAuth = new BasicScheme();
+ authCache.put(host, basicAuth);
+
+ BasicHttpContext localcontext = new BasicHttpContext();
+ localcontext.setAttribute(HttpClientContext.AUTH_CACHE, authCache);
+ return localcontext;
+ }
+}
\ No newline at end of file
diff --git a/httpclient-simple/src/main/java/org/baeldung/client/RestTemplateFactory.java b/httpclient-simple/src/main/java/org/baeldung/client/RestTemplateFactory.java
new file mode 100644
index 0000000000..3ed0bc82b7
--- /dev/null
+++ b/httpclient-simple/src/main/java/org/baeldung/client/RestTemplateFactory.java
@@ -0,0 +1,44 @@
+package org.baeldung.client;
+
+import org.apache.http.HttpHost;
+import org.springframework.beans.factory.FactoryBean;
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.http.client.ClientHttpRequestFactory;
+import org.springframework.http.client.support.BasicAuthenticationInterceptor;
+import org.springframework.stereotype.Component;
+import org.springframework.web.client.RestTemplate;
+
+@Component
+public class RestTemplateFactory implements FactoryBean, InitializingBean {
+ private RestTemplate restTemplate;
+
+ public RestTemplateFactory() {
+ super();
+ }
+
+ // API
+
+ @Override
+ public RestTemplate getObject() {
+ return restTemplate;
+ }
+
+ @Override
+ public Class getObjectType() {
+ return RestTemplate.class;
+ }
+
+ @Override
+ public boolean isSingleton() {
+ return true;
+ }
+
+ @Override
+ public void afterPropertiesSet() {
+ HttpHost host = new HttpHost("localhost", 8082, "http");
+ final ClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactoryBasicAuth(host);
+ restTemplate = new RestTemplate(requestFactory);
+ restTemplate.getInterceptors().add(new BasicAuthenticationInterceptor("user1", "user1Pass"));
+ }
+
+}
\ No newline at end of file
diff --git a/httpclient-simple/src/main/java/org/baeldung/client/spring/ClientConfig.java b/httpclient-simple/src/main/java/org/baeldung/client/spring/ClientConfig.java
new file mode 100644
index 0000000000..73e602855c
--- /dev/null
+++ b/httpclient-simple/src/main/java/org/baeldung/client/spring/ClientConfig.java
@@ -0,0 +1,16 @@
+package org.baeldung.client.spring;
+
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+@ComponentScan("org.baeldung.client")
+public class ClientConfig {
+
+ public ClientConfig() {
+ super();
+ }
+
+ // beans
+
+}
\ No newline at end of file
diff --git a/httpclient-simple/src/main/java/org/baeldung/filter/CustomFilter.java b/httpclient-simple/src/main/java/org/baeldung/filter/CustomFilter.java
new file mode 100644
index 0000000000..01e5b0b59d
--- /dev/null
+++ b/httpclient-simple/src/main/java/org/baeldung/filter/CustomFilter.java
@@ -0,0 +1,18 @@
+package org.baeldung.filter;
+
+import org.springframework.web.filter.GenericFilterBean;
+
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import java.io.IOException;
+
+public class CustomFilter extends GenericFilterBean {
+
+ @Override
+ public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
+ chain.doFilter(request, response);
+ }
+
+}
diff --git a/httpclient-simple/src/main/java/org/baeldung/filter/CustomWebSecurityConfigurerAdapter.java b/httpclient-simple/src/main/java/org/baeldung/filter/CustomWebSecurityConfigurerAdapter.java
new file mode 100644
index 0000000000..7ca2a80c52
--- /dev/null
+++ b/httpclient-simple/src/main/java/org/baeldung/filter/CustomWebSecurityConfigurerAdapter.java
@@ -0,0 +1,49 @@
+package org.baeldung.filter;
+
+import org.baeldung.security.RestAuthenticationEntryPoint;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
+import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
+import org.springframework.security.crypto.password.PasswordEncoder;
+import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
+
+@Configuration
+@EnableWebSecurity
+public class CustomWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
+
+ @Autowired private RestAuthenticationEntryPoint authenticationEntryPoint;
+
+ @Autowired
+ public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
+ auth
+ .inMemoryAuthentication()
+ .withUser("user1")
+ .password(passwordEncoder().encode("user1Pass"))
+ .authorities("ROLE_USER");
+ }
+
+ @Override
+ protected void configure(HttpSecurity http) throws Exception {
+ http
+ .authorizeRequests()
+ .antMatchers("/securityNone")
+ .permitAll()
+ .anyRequest()
+ .authenticated()
+ .and()
+ .httpBasic()
+ .authenticationEntryPoint(authenticationEntryPoint);
+
+ http.addFilterAfter(new CustomFilter(), BasicAuthenticationFilter.class);
+ }
+
+ @Bean
+ public PasswordEncoder passwordEncoder() {
+ return new BCryptPasswordEncoder();
+ }
+}
diff --git a/httpclient-simple/src/main/java/org/baeldung/security/MySavedRequestAwareAuthenticationSuccessHandler.java b/httpclient-simple/src/main/java/org/baeldung/security/MySavedRequestAwareAuthenticationSuccessHandler.java
new file mode 100644
index 0000000000..698052fa2b
--- /dev/null
+++ b/httpclient-simple/src/main/java/org/baeldung/security/MySavedRequestAwareAuthenticationSuccessHandler.java
@@ -0,0 +1,48 @@
+package org.baeldung.security;
+
+import java.io.IOException;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.springframework.security.core.Authentication;
+import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler;
+import org.springframework.security.web.savedrequest.HttpSessionRequestCache;
+import org.springframework.security.web.savedrequest.RequestCache;
+import org.springframework.security.web.savedrequest.SavedRequest;
+import org.springframework.util.StringUtils;
+
+public class MySavedRequestAwareAuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler {
+
+ private RequestCache requestCache = new HttpSessionRequestCache();
+
+ @Override
+ public void onAuthenticationSuccess(final HttpServletRequest request, final HttpServletResponse response, final Authentication authentication) throws ServletException, IOException {
+ final SavedRequest savedRequest = requestCache.getRequest(request, response);
+
+ if (savedRequest == null) {
+ super.onAuthenticationSuccess(request, response, authentication);
+
+ return;
+ }
+ final String targetUrlParameter = getTargetUrlParameter();
+ if (isAlwaysUseDefaultTargetUrl() || (targetUrlParameter != null && StringUtils.hasText(request.getParameter(targetUrlParameter)))) {
+ requestCache.removeRequest(request, response);
+ super.onAuthenticationSuccess(request, response, authentication);
+
+ return;
+ }
+
+ clearAuthenticationAttributes(request);
+
+ // Use the DefaultSavedRequest URL
+ // final String targetUrl = savedRequest.getRedirectUrl();
+ // logger.debug("Redirecting to DefaultSavedRequest Url: " + targetUrl);
+ // getRedirectStrategy().sendRedirect(request, response, targetUrl);
+ }
+
+ public void setRequestCache(final RequestCache requestCache) {
+ this.requestCache = requestCache;
+ }
+}
diff --git a/httpclient-simple/src/main/java/org/baeldung/security/RestAuthenticationEntryPoint.java b/httpclient-simple/src/main/java/org/baeldung/security/RestAuthenticationEntryPoint.java
new file mode 100644
index 0000000000..77aa32ff97
--- /dev/null
+++ b/httpclient-simple/src/main/java/org/baeldung/security/RestAuthenticationEntryPoint.java
@@ -0,0 +1,23 @@
+package org.baeldung.security;
+
+import java.io.IOException;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.springframework.security.core.AuthenticationException;
+import org.springframework.security.web.AuthenticationEntryPoint;
+import org.springframework.stereotype.Component;
+
+/**
+ * The Entry Point will not redirect to any sort of Login - it will return the 401
+ */
+@Component
+public final class RestAuthenticationEntryPoint implements AuthenticationEntryPoint {
+
+ @Override
+ public void commence(final HttpServletRequest request, final HttpServletResponse response, final AuthenticationException authException) throws IOException {
+ response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized");
+ }
+
+}
\ No newline at end of file
diff --git a/httpclient-simple/src/main/java/org/baeldung/spring/SecSecurityConfig.java b/httpclient-simple/src/main/java/org/baeldung/spring/SecSecurityConfig.java
new file mode 100644
index 0000000000..4ce80dab9f
--- /dev/null
+++ b/httpclient-simple/src/main/java/org/baeldung/spring/SecSecurityConfig.java
@@ -0,0 +1,16 @@
+package org.baeldung.spring;
+
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.ImportResource;
+
+@Configuration
+@ImportResource({ "classpath:webSecurityConfig.xml" })
+@ComponentScan("org.baeldung.security")
+public class SecSecurityConfig {
+
+ public SecSecurityConfig() {
+ super();
+ }
+
+}
diff --git a/httpclient-simple/src/main/java/org/baeldung/spring/WebConfig.java b/httpclient-simple/src/main/java/org/baeldung/spring/WebConfig.java
new file mode 100644
index 0000000000..5876e1307b
--- /dev/null
+++ b/httpclient-simple/src/main/java/org/baeldung/spring/WebConfig.java
@@ -0,0 +1,30 @@
+package org.baeldung.spring;
+
+import java.util.List;
+
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.http.converter.HttpMessageConverter;
+import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
+import org.springframework.web.servlet.config.annotation.EnableWebMvc;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+@Configuration
+@EnableWebMvc
+@ComponentScan("org.baeldung.web")
+public class WebConfig implements WebMvcConfigurer {
+
+ public WebConfig() {
+ super();
+ }
+
+ // beans
+
+ @Override
+ public void configureMessageConverters(final List> converters) {
+ converters.add(new MappingJackson2HttpMessageConverter());
+ }
+
+ //
+
+}
\ No newline at end of file
diff --git a/httpclient-simple/src/main/java/org/baeldung/web/controller/BarController.java b/httpclient-simple/src/main/java/org/baeldung/web/controller/BarController.java
new file mode 100644
index 0000000000..2bc314baa2
--- /dev/null
+++ b/httpclient-simple/src/main/java/org/baeldung/web/controller/BarController.java
@@ -0,0 +1,31 @@
+package org.baeldung.web.controller;
+
+import org.baeldung.web.dto.Bar;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationEventPublisher;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+@Controller
+@RequestMapping(value = "/bars")
+public class BarController {
+
+ @Autowired
+ private ApplicationEventPublisher eventPublisher;
+
+ public BarController() {
+ super();
+ }
+
+ // API
+
+ @RequestMapping(value = "/{id}", method = RequestMethod.GET)
+ @ResponseBody
+ public Bar findOne(@PathVariable("id") final Long id) {
+ return new Bar();
+ }
+
+}
diff --git a/httpclient-simple/src/main/java/org/baeldung/web/controller/FooController.java b/httpclient-simple/src/main/java/org/baeldung/web/controller/FooController.java
new file mode 100644
index 0000000000..b50edb2dcf
--- /dev/null
+++ b/httpclient-simple/src/main/java/org/baeldung/web/controller/FooController.java
@@ -0,0 +1,33 @@
+package org.baeldung.web.controller;
+
+import org.baeldung.web.dto.Foo;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationEventPublisher;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+@Controller
+@RequestMapping(value = "/foos")
+public class FooController {
+
+ @Autowired
+ private ApplicationEventPublisher eventPublisher;
+
+ public FooController() {
+ super();
+ }
+
+ // API
+
+ @RequestMapping(value = "/{id}", method = RequestMethod.GET)
+ @ResponseBody
+ @PreAuthorize("hasRole('ROLE_USER')")
+ public Foo findOne(@PathVariable("id") final Long id) {
+ return new Foo();
+ }
+
+}
diff --git a/httpclient-simple/src/main/java/org/baeldung/web/dto/Bar.java b/httpclient-simple/src/main/java/org/baeldung/web/dto/Bar.java
new file mode 100644
index 0000000000..d33e39a823
--- /dev/null
+++ b/httpclient-simple/src/main/java/org/baeldung/web/dto/Bar.java
@@ -0,0 +1,14 @@
+package org.baeldung.web.dto;
+
+import java.io.Serializable;
+
+import javax.xml.bind.annotation.XmlRootElement;
+
+@XmlRootElement
+public class Bar implements Serializable {
+
+ public Bar() {
+ super();
+ }
+
+}
diff --git a/httpclient-simple/src/main/java/org/baeldung/web/dto/Foo.java b/httpclient-simple/src/main/java/org/baeldung/web/dto/Foo.java
new file mode 100644
index 0000000000..09c1dac933
--- /dev/null
+++ b/httpclient-simple/src/main/java/org/baeldung/web/dto/Foo.java
@@ -0,0 +1,14 @@
+package org.baeldung.web.dto;
+
+import java.io.Serializable;
+
+import javax.xml.bind.annotation.XmlRootElement;
+
+@XmlRootElement
+public class Foo implements Serializable {
+
+ public Foo() {
+ super();
+ }
+
+}
diff --git a/httpclient-simple/src/main/resources/logback.xml b/httpclient-simple/src/main/resources/logback.xml
new file mode 100644
index 0000000000..56af2d397e
--- /dev/null
+++ b/httpclient-simple/src/main/resources/logback.xml
@@ -0,0 +1,19 @@
+
+
+
+
+ %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/httpclient-simple/src/main/resources/webSecurityConfig.xml b/httpclient-simple/src/main/resources/webSecurityConfig.xml
new file mode 100644
index 0000000000..a93dc841b6
--- /dev/null
+++ b/httpclient-simple/src/main/resources/webSecurityConfig.xml
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/httpclient-simple/src/main/webapp/WEB-INF/api-servlet.xml b/httpclient-simple/src/main/webapp/WEB-INF/api-servlet.xml
new file mode 100644
index 0000000000..1dbff70b83
--- /dev/null
+++ b/httpclient-simple/src/main/webapp/WEB-INF/api-servlet.xml
@@ -0,0 +1,6 @@
+
+
+
+
\ No newline at end of file
diff --git a/httpclient-simple/src/main/webapp/WEB-INF/web.xml b/httpclient-simple/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000000..83b4aeb0a7
--- /dev/null
+++ b/httpclient-simple/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,43 @@
+
+
+
+ Spring Security Custom Application
+
+
+
+ contextClass
+ org.springframework.web.context.support.AnnotationConfigWebApplicationContext
+
+
+ contextConfigLocation
+ org.baeldung.spring
+
+
+
+ org.springframework.web.context.ContextLoaderListener
+
+
+
+
+ api
+ org.springframework.web.servlet.DispatcherServlet
+ 1
+
+
+ api
+ /api/*
+
+
+
+
+ springSecurityFilterChain
+ org.springframework.web.filter.DelegatingFilterProxy
+
+
+ springSecurityFilterChain
+ /*
+
+
+
\ No newline at end of file
diff --git a/spring-security-rest-basic-auth/src/test/java/org/baeldung/client/ClientLiveTest.java b/httpclient-simple/src/test/java/org/baeldung/client/ClientLiveTest.java
similarity index 88%
rename from spring-security-rest-basic-auth/src/test/java/org/baeldung/client/ClientLiveTest.java
rename to httpclient-simple/src/test/java/org/baeldung/client/ClientLiveTest.java
index 2a668f827a..286ee3c900 100644
--- a/spring-security-rest-basic-auth/src/test/java/org/baeldung/client/ClientLiveTest.java
+++ b/httpclient-simple/src/test/java/org/baeldung/client/ClientLiveTest.java
@@ -33,13 +33,13 @@ public class ClientLiveTest {
@Test
public final void whenSecuredRestApiIsConsumed_then200OK() {
- final ResponseEntity responseEntity = secureRestTemplate.exchange("http://localhost:8082/spring-security-rest-basic-auth/api/foos/1", HttpMethod.GET, null, Foo.class);
+ final ResponseEntity responseEntity = secureRestTemplate.exchange("http://localhost:8082/httpclient-simple/api/foos/1", HttpMethod.GET, null, Foo.class);
assertThat(responseEntity.getStatusCode().value(), is(200));
}
@Test(expected = ResourceAccessException.class)
public final void whenHttpsUrlIsConsumed_thenException() {
- final String urlOverHttps = "https://localhost:8443/spring-security-rest-basic-auth/api/bars/1";
+ final String urlOverHttps = "https://localhost:8443/httpclient-simple/api/bars/1";
final ResponseEntity response = new RestTemplate().exchange(urlOverHttps, HttpMethod.GET, null, String.class);
assertThat(response.getStatusCode().value(), equalTo(200));
}
diff --git a/spring-security-rest-basic-auth/src/test/java/org/baeldung/client/RestClientLiveManualTest.java b/httpclient-simple/src/test/java/org/baeldung/client/RestClientLiveManualTest.java
similarity index 63%
rename from spring-security-rest-basic-auth/src/test/java/org/baeldung/client/RestClientLiveManualTest.java
rename to httpclient-simple/src/test/java/org/baeldung/client/RestClientLiveManualTest.java
index 104129b663..53f259c21d 100644
--- a/spring-security-rest-basic-auth/src/test/java/org/baeldung/client/RestClientLiveManualTest.java
+++ b/httpclient-simple/src/test/java/org/baeldung/client/RestClientLiveManualTest.java
@@ -8,19 +8,24 @@ import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.cert.X509Certificate;
-import javax.net.ssl.SSLException;
-import javax.net.ssl.SSLPeerUnverifiedException;
+import javax.net.ssl.SSLContext;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpGet;
+import org.apache.http.config.Registry;
+import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.scheme.Scheme;
+import org.apache.http.conn.socket.ConnectionSocketFactory;
+import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
+import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.impl.client.CloseableHttpClient;
-import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.client.HttpClients;
+import org.apache.http.impl.conn.BasicHttpClientConnectionManager;
+import org.apache.http.ssl.SSLContexts;
import org.junit.Ignore;
import org.junit.Test;
import org.springframework.http.HttpMethod;
@@ -34,14 +39,14 @@ import org.springframework.web.client.RestTemplate;
* */
public class RestClientLiveManualTest {
- final String urlOverHttps = "http://localhost:8082/spring-security-rest-basic-auth/api/bars/1";
+ final String urlOverHttps = "http://localhost:8082/httpclient-simple/api/bars/1";
// tests
// old httpClient will throw UnsupportedOperationException
@Ignore
@Test
- public final void givenAcceptingAllCertificates_whenHttpsUrlIsConsumed_thenException() throws GeneralSecurityException {
+ public final void givenAcceptingAllCertificates_whenHttpsUrlIsConsumed_thenException_1() throws GeneralSecurityException {
final HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory();
final CloseableHttpClient httpClient = (CloseableHttpClient) requestFactory.getHttpClient();
@@ -57,6 +62,29 @@ public class RestClientLiveManualTest {
final ResponseEntity response = new RestTemplate(requestFactory).exchange(urlOverHttps, HttpMethod.GET, null, String.class);
assertThat(response.getStatusCode().value(), equalTo(200));
}
+
+ // new httpClient : 4.4 and above
+ @Test
+ public final void givenAcceptingAllCertificates_whenHttpsUrlIsConsumed_thenException_2() throws GeneralSecurityException {
+
+ final TrustStrategy acceptingTrustStrategy = (cert, authType) -> true;
+ final SSLContext sslContext = SSLContexts.custom().loadTrustMaterial(null, acceptingTrustStrategy).build();
+ final SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext, NoopHostnameVerifier.INSTANCE);
+ final Registry socketFactoryRegistry = RegistryBuilder. create()
+ .register("https", sslsf)
+ .register("http", new PlainConnectionSocketFactory())
+ .build();
+
+ final BasicHttpClientConnectionManager connectionManager = new BasicHttpClientConnectionManager(socketFactoryRegistry);
+ final CloseableHttpClient httpClient = HttpClients.custom()
+ .setSSLSocketFactory(sslsf)
+ .setConnectionManager(connectionManager)
+ .build();
+
+ final HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(httpClient);
+ final ResponseEntity response = new RestTemplate(requestFactory).exchange(urlOverHttps, HttpMethod.GET, null, String.class);
+ assertThat(response.getStatusCode().value(), equalTo(200));
+ }
@Test
public final void givenAcceptingAllCertificatesUsing4_4_whenHttpsUrlIsConsumed_thenCorrect() throws ClientProtocolException, IOException {
diff --git a/httpclient/src/test/java/org/baeldung/httpclient/HttpsClientSslLiveTest.java b/httpclient-simple/src/test/java/org/baeldung/httpclient/HttpsClientSslLiveTest.java
similarity index 82%
rename from httpclient/src/test/java/org/baeldung/httpclient/HttpsClientSslLiveTest.java
rename to httpclient-simple/src/test/java/org/baeldung/httpclient/HttpsClientSslLiveTest.java
index 4eadfe24d5..9e95905c70 100644
--- a/httpclient/src/test/java/org/baeldung/httpclient/HttpsClientSslLiveTest.java
+++ b/httpclient-simple/src/test/java/org/baeldung/httpclient/HttpsClientSslLiveTest.java
@@ -1,32 +1,31 @@
package org.baeldung.httpclient;
-import org.apache.http.HttpResponse;
-import org.apache.http.client.methods.HttpGet;
-import org.apache.http.conn.ClientConnectionManager;
-import org.apache.http.conn.scheme.Scheme;
-import org.apache.http.conn.scheme.SchemeRegistry;
-import org.apache.http.conn.ssl.NoopHostnameVerifier;
-import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
-import org.apache.http.conn.ssl.SSLSocketFactory;
-import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
-import org.apache.http.conn.ssl.TrustStrategy;
-import org.apache.http.impl.client.CloseableHttpClient;
-import org.apache.http.impl.client.DefaultHttpClient;
-import org.apache.http.impl.client.HttpClientBuilder;
-import org.apache.http.impl.client.HttpClients;
-import org.apache.http.impl.conn.PoolingClientConnectionManager;
-import org.apache.http.ssl.SSLContextBuilder;
-import org.apache.http.ssl.SSLContexts;
-import org.junit.Test;
-
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.SSLHandshakeException;
-import java.io.IOException;
-import java.security.GeneralSecurityException;
-
import static org.hamcrest.CoreMatchers.equalTo;
import static org.junit.Assert.assertThat;
+import java.io.IOException;
+import java.security.GeneralSecurityException;
+
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLHandshakeException;
+
+import org.apache.http.HttpResponse;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.config.Registry;
+import org.apache.http.config.RegistryBuilder;
+import org.apache.http.conn.socket.ConnectionSocketFactory;
+import org.apache.http.conn.ssl.NoopHostnameVerifier;
+import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
+import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
+import org.apache.http.conn.ssl.TrustStrategy;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClientBuilder;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
+import org.apache.http.ssl.SSLContextBuilder;
+import org.apache.http.ssl.SSLContexts;
+import org.junit.Test;
+
/**
* This test requires a localhost server over HTTPS
* It should only be manually run, not part of the automated build
@@ -50,16 +49,22 @@ public class HttpsClientSslLiveTest {
.getStatusCode(), equalTo(200));
}
- @SuppressWarnings("deprecation")
@Test
public final void givenHttpClientPre4_3_whenAcceptingAllCertificates_thenCanConsumeHttpsUriWithSelfSignedCertificate() throws IOException, GeneralSecurityException {
final TrustStrategy acceptingTrustStrategy = (certificate, authType) -> true;
- final SSLSocketFactory sf = new SSLSocketFactory(acceptingTrustStrategy, SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
- final SchemeRegistry registry = new SchemeRegistry();
- registry.register(new Scheme("https", 443, sf));
- final ClientConnectionManager ccm = new PoolingClientConnectionManager(registry);
+
+ final SSLContext sslContext = SSLContexts.custom()
+ .loadTrustMaterial(null, acceptingTrustStrategy)
+ .build();
- final CloseableHttpClient httpClient = new DefaultHttpClient(ccm);
+ final SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext, NoopHostnameVerifier.INSTANCE);
+ Registry socketFactoryRegistry = RegistryBuilder. create().register("https", sslsf).build();
+ PoolingHttpClientConnectionManager clientConnectionManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
+
+ final CloseableHttpClient httpClient = HttpClients.custom()
+ .setSSLSocketFactory(sslsf)
+ .setConnectionManager(clientConnectionManager)
+ .build();
final HttpGet getMethod = new HttpGet(HOST_WITH_SSL);
final HttpResponse response = httpClient.execute(getMethod);
@@ -76,10 +81,9 @@ public class HttpsClientSslLiveTest {
.loadTrustMaterial(null, acceptingTrustStrategy)
.build();
- final SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext, SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
+ final SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext, NoopHostnameVerifier.INSTANCE);
final CloseableHttpClient httpClient = HttpClients.custom()
- .setHostnameVerifier(SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER)
.setSSLSocketFactory(sslsf)
.build();
diff --git a/httpclient-simple/src/test/java/org/baeldung/httpclient/ResponseUtil.java b/httpclient-simple/src/test/java/org/baeldung/httpclient/ResponseUtil.java
new file mode 100644
index 0000000000..fd38b95cbe
--- /dev/null
+++ b/httpclient-simple/src/test/java/org/baeldung/httpclient/ResponseUtil.java
@@ -0,0 +1,26 @@
+package org.baeldung.httpclient;
+
+import org.apache.http.HttpEntity;
+import org.apache.http.client.methods.CloseableHttpResponse;
+
+import java.io.IOException;
+
+public final class ResponseUtil {
+ private ResponseUtil() {
+ }
+
+ public static void closeResponse(CloseableHttpResponse response) throws IOException {
+ if (response == null) {
+ return;
+ }
+
+ try {
+ final HttpEntity entity = response.getEntity();
+ if (entity != null) {
+ entity.getContent().close();
+ }
+ } finally {
+ response.close();
+ }
+ }
+}
diff --git a/httpclient/src/test/java/org/baeldung/httpclient/base/HttpClientBasicLiveTest.java b/httpclient-simple/src/test/java/org/baeldung/httpclient/base/HttpClientBasicLiveTest.java
similarity index 100%
rename from httpclient/src/test/java/org/baeldung/httpclient/base/HttpClientBasicLiveTest.java
rename to httpclient-simple/src/test/java/org/baeldung/httpclient/base/HttpClientBasicLiveTest.java
diff --git a/httpclient/src/test/java/org/baeldung/httpclient/sec/HttpClientAuthLiveTest.java b/httpclient-simple/src/test/java/org/baeldung/httpclient/sec/HttpClientAuthLiveTest.java
similarity index 96%
rename from httpclient/src/test/java/org/baeldung/httpclient/sec/HttpClientAuthLiveTest.java
rename to httpclient-simple/src/test/java/org/baeldung/httpclient/sec/HttpClientAuthLiveTest.java
index c9956e5852..96278b481a 100644
--- a/httpclient/src/test/java/org/baeldung/httpclient/sec/HttpClientAuthLiveTest.java
+++ b/httpclient-simple/src/test/java/org/baeldung/httpclient/sec/HttpClientAuthLiveTest.java
@@ -23,19 +23,18 @@ import org.junit.Before;
import org.junit.Test;
import java.io.IOException;
-import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.assertThat;
/*
- * NOTE : Need module spring-security-rest-basic-auth to be running
+ * NOTE : Need module httpclient-simple to be running
*/
public class HttpClientAuthLiveTest {
- private static final String URL_SECURED_BY_BASIC_AUTHENTICATION = "http://localhost:8081/spring-security-rest-basic-auth/api/foos/1";
+ private static final String URL_SECURED_BY_BASIC_AUTHENTICATION = "http://localhost:8082/httpclient-simple/api/foos/1";
private static final String DEFAULT_USER = "user1";
private static final String DEFAULT_PASS = "user1Pass";
@@ -111,7 +110,7 @@ public class HttpClientAuthLiveTest {
}
private HttpContext context() {
- final HttpHost targetHost = new HttpHost("localhost", 8080, "http");
+ final HttpHost targetHost = new HttpHost("localhost", 8082, "http");
final CredentialsProvider credsProvider = new BasicCredentialsProvider();
credsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(DEFAULT_USER, DEFAULT_PASS));
diff --git a/spring-security-rest-basic-auth/src/test/java/org/baeldung/test/LiveTestSuite.java b/httpclient-simple/src/test/java/org/baeldung/test/LiveTestSuite.java
similarity index 100%
rename from spring-security-rest-basic-auth/src/test/java/org/baeldung/test/LiveTestSuite.java
rename to httpclient-simple/src/test/java/org/baeldung/test/LiveTestSuite.java
diff --git a/httpclient-simple/src/test/resources/.gitignore b/httpclient-simple/src/test/resources/.gitignore
new file mode 100644
index 0000000000..83c05e60c8
--- /dev/null
+++ b/httpclient-simple/src/test/resources/.gitignore
@@ -0,0 +1,13 @@
+*.class
+
+#folders#
+/target
+/neoDb*
+/data
+/src/main/webapp/WEB-INF/classes
+*/META-INF/*
+
+# Packaged files #
+*.jar
+*.war
+*.ear
\ No newline at end of file
diff --git a/httpclient/README.md b/httpclient/README.md
index 87fb38706d..cab538be85 100644
--- a/httpclient/README.md
+++ b/httpclient/README.md
@@ -8,13 +8,11 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring
### Relevant Articles:
- [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)
- [Custom HTTP Header with the HttpClient](http://www.baeldung.com/httpclient-custom-http-header)
-- [HttpClient Basic Authentication](http://www.baeldung.com/httpclient-4-basic-authentication)
- [Multipart Upload with HttpClient 4](http://www.baeldung.com/httpclient-multipart-upload)
- [HttpAsyncClient Tutorial](http://www.baeldung.com/httpasyncclient-tutorial)
- [HttpClient 4 Tutorial](http://www.baeldung.com/httpclient-guide)
diff --git a/httpclient/pom.xml b/httpclient/pom.xml
index c9f9808ede..def3a05816 100644
--- a/httpclient/pom.xml
+++ b/httpclient/pom.xml
@@ -122,11 +122,10 @@
19.0
3.5
1.10
- 4.1.2
+ 4.1.4
2.5.1
- 4.4.5
- 4.5.3
+ 4.5.8
1.6.1
diff --git a/httpclient/src/test/java/org/baeldung/httpclient/HttpAsyncClientLiveTest.java b/httpclient/src/test/java/org/baeldung/httpclient/HttpAsyncClientLiveTest.java
index d39697c0a9..47a587885e 100644
--- a/httpclient/src/test/java/org/baeldung/httpclient/HttpAsyncClientLiveTest.java
+++ b/httpclient/src/test/java/org/baeldung/httpclient/HttpAsyncClientLiveTest.java
@@ -4,7 +4,6 @@ import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.assertThat;
import java.io.IOException;
-import java.security.cert.X509Certificate;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
@@ -18,8 +17,7 @@ import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.protocol.HttpClientContext;
-import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
-import org.apache.http.conn.ssl.SSLContexts;
+import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.client.BasicCredentialsProvider;
@@ -31,6 +29,7 @@ import org.apache.http.impl.nio.reactor.DefaultConnectingIOReactor;
import org.apache.http.nio.reactor.ConnectingIOReactor;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.protocol.HttpContext;
+import org.apache.http.ssl.SSLContexts;
import org.junit.Test;
public class HttpAsyncClientLiveTest {
@@ -104,7 +103,7 @@ public class HttpAsyncClientLiveTest {
final TrustStrategy acceptingTrustStrategy = (certificate, authType) -> true;
final SSLContext sslContext = SSLContexts.custom().loadTrustMaterial(null, acceptingTrustStrategy).build();
- final CloseableHttpAsyncClient client = HttpAsyncClients.custom().setSSLHostnameVerifier(SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER).setSSLContext(sslContext).build();
+ final CloseableHttpAsyncClient client = HttpAsyncClients.custom().setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE).setSSLContext(sslContext).build();
client.start();
final HttpGet request = new HttpGet(HOST_WITH_SSL);
diff --git a/httpclient/src/test/java/org/baeldung/httpclient/conn/HttpClientConnectionManagementLiveTest.java b/httpclient/src/test/java/org/baeldung/httpclient/conn/HttpClientConnectionManagementLiveTest.java
index 0f8ebefe6c..cf945098db 100644
--- a/httpclient/src/test/java/org/baeldung/httpclient/conn/HttpClientConnectionManagementLiveTest.java
+++ b/httpclient/src/test/java/org/baeldung/httpclient/conn/HttpClientConnectionManagementLiveTest.java
@@ -327,7 +327,8 @@ public class HttpClientConnectionManagementLiveTest {
// 8.1
public final void whenHttpClientChecksStaleConns_thenNoExceptions() {
poolingConnManager = new PoolingHttpClientConnectionManager();
- client = HttpClients.custom().setDefaultRequestConfig(RequestConfig.custom().setStaleConnectionCheckEnabled(true).build()).setConnectionManager(poolingConnManager).build();
+ poolingConnManager.setValidateAfterInactivity(1000);
+ client = HttpClients.custom().setDefaultRequestConfig(RequestConfig.custom().build()).setConnectionManager(poolingConnManager).build();
}
@Test
diff --git a/jackson-2/pom.xml b/jackson-2/pom.xml
index ddbcb81dcc..6b973dd6f5 100644
--- a/jackson-2/pom.xml
+++ b/jackson-2/pom.xml
@@ -22,6 +22,20 @@
${jackson.version}
+
+
+ com.fasterxml.jackson.dataformat
+ jackson-dataformat-yaml
+ 2.9.8
+
+
+
+
+ com.fasterxml.jackson.datatype
+ jackson-datatype-jsr310
+ 2.9.8
+
+
diff --git a/jackson-2/src/main/java/com/baeldung/jackson/entities/Order.java b/jackson-2/src/main/java/com/baeldung/jackson/entities/Order.java
new file mode 100644
index 0000000000..2075b7879b
--- /dev/null
+++ b/jackson-2/src/main/java/com/baeldung/jackson/entities/Order.java
@@ -0,0 +1,68 @@
+package com.baeldung.jackson.entities;
+
+import java.time.LocalDate;
+import java.util.ArrayList;
+import java.util.List;
+
+public class Order {
+ private String orderNo;
+ private LocalDate date;
+ private String customerName;
+ private List orderLines;
+
+ public Order() {
+
+ }
+
+ public Order(String orderNo, LocalDate date, String customerName, List orderLines) {
+ super();
+ this.orderNo = orderNo;
+ this.date = date;
+ this.customerName = customerName;
+ this.orderLines = orderLines;
+ }
+
+ public String getOrderNo() {
+ return orderNo;
+ }
+
+ public void setOrderNo(String orderNo) {
+ this.orderNo = orderNo;
+ }
+
+ public LocalDate getDate() {
+ return date;
+ }
+
+ public void setDate(LocalDate date) {
+ this.date = date;
+ }
+
+ public String getCustomerName() {
+ return customerName;
+ }
+
+ public void setCustomerName(String customerName) {
+ this.customerName = customerName;
+ }
+
+ public List getOrderLines() {
+ if (orderLines == null) {
+ orderLines = new ArrayList<>();
+ }
+ return orderLines;
+ }
+
+ public void setOrderLines(List orderLines) {
+ if (orderLines == null) {
+ orderLines = new ArrayList<>();
+ }
+ this.orderLines = orderLines;
+ }
+
+ @Override
+ public String toString() {
+ return "Order [orderNo=" + orderNo + ", date=" + date + ", customerName=" + customerName + ", orderLines=" + orderLines + "]";
+ }
+
+}
diff --git a/jackson-2/src/main/java/com/baeldung/jackson/entities/OrderLine.java b/jackson-2/src/main/java/com/baeldung/jackson/entities/OrderLine.java
new file mode 100644
index 0000000000..858d094dd1
--- /dev/null
+++ b/jackson-2/src/main/java/com/baeldung/jackson/entities/OrderLine.java
@@ -0,0 +1,49 @@
+package com.baeldung.jackson.entities;
+
+import java.math.BigDecimal;
+
+public class OrderLine {
+ private String item;
+ private int quantity;
+ private BigDecimal unitPrice;
+
+ public OrderLine() {
+
+ }
+
+ public OrderLine(String item, int quantity, BigDecimal unitPrice) {
+ super();
+ this.item = item;
+ this.quantity = quantity;
+ this.unitPrice = unitPrice;
+ }
+
+ public String getItem() {
+ return item;
+ }
+
+ public void setItem(String item) {
+ this.item = item;
+ }
+
+ public int getQuantity() {
+ return quantity;
+ }
+
+ public void setQuantity(int quantity) {
+ this.quantity = quantity;
+ }
+
+ public BigDecimal getUnitPrice() {
+ return unitPrice;
+ }
+
+ public void setUnitPrice(BigDecimal unitPrice) {
+ this.unitPrice = unitPrice;
+ }
+
+ @Override
+ public String toString() {
+ return "OrderLine [item=" + item + ", quantity=" + quantity + ", unitPrice=" + unitPrice + "]";
+ }
+}
diff --git a/jackson-2/src/main/resources/orderInput.yaml b/jackson-2/src/main/resources/orderInput.yaml
new file mode 100644
index 0000000000..0aaa6186a2
--- /dev/null
+++ b/jackson-2/src/main/resources/orderInput.yaml
@@ -0,0 +1,11 @@
+orderNo: A001
+date: 2019-04-17
+customerName: Customer, Joe
+orderLines:
+ - item: No. 9 Sprockets
+ quantity: 12
+ unitPrice: 1.23
+ - item: Widget (10mm)
+ quantity: 4
+ unitPrice: 3.45
+
\ No newline at end of file
diff --git a/jackson-2/src/test/java/com/baeldung/jackson/yaml/YamlUnitTest.java b/jackson-2/src/test/java/com/baeldung/jackson/yaml/YamlUnitTest.java
new file mode 100644
index 0000000000..3ed84db60e
--- /dev/null
+++ b/jackson-2/src/test/java/com/baeldung/jackson/yaml/YamlUnitTest.java
@@ -0,0 +1,63 @@
+package com.baeldung.jackson.yaml;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.io.File;
+import java.io.IOException;
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import com.baeldung.jackson.entities.Order;
+import com.baeldung.jackson.entities.OrderLine;
+import com.fasterxml.jackson.core.JsonGenerationException;
+import com.fasterxml.jackson.core.JsonParseException;
+import com.fasterxml.jackson.databind.JsonMappingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
+import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
+import com.fasterxml.jackson.dataformat.yaml.YAMLGenerator.Feature;
+
+public class YamlUnitTest {
+ private ObjectMapper mapper;
+
+ @Before
+ public void setup() {
+ mapper = new ObjectMapper(new YAMLFactory().disable(Feature.WRITE_DOC_START_MARKER));
+ mapper.findAndRegisterModules();
+ mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
+ }
+
+ @Test
+ public void givenYamlInput_ObjectCreated() throws JsonParseException, JsonMappingException, IOException {
+ Order order = mapper.readValue(new File("src/main/resources/orderInput.yaml"), Order.class);
+ assertEquals("A001", order.getOrderNo());
+ assertEquals(LocalDate.parse("2019-04-17", DateTimeFormatter.ISO_DATE), order.getDate());
+ assertEquals("Customer, Joe", order.getCustomerName());
+ assertEquals(2, order.getOrderLines()
+ .size());
+ }
+
+ @Test
+ public void givenYamlObject_FileWritten() throws JsonGenerationException, JsonMappingException, IOException {
+ List lines = new ArrayList<>();
+ lines.add(new OrderLine("Copper Wire (200ft)", 1, new BigDecimal(50.67).setScale(2, RoundingMode.HALF_UP)));
+ lines.add(new OrderLine("Washers (1/4\")", 24, new BigDecimal(.15).setScale(2, RoundingMode.HALF_UP)));
+ Order order = new Order(
+ "B-9910",
+ LocalDate.parse("2019-04-18", DateTimeFormatter.ISO_DATE),
+ "Customer, Jane",
+ lines);
+ mapper.writeValue(new File("src/main/resources/orderOutput.yaml"), order);
+
+ File outputYaml = new File("src/main/resources/orderOutput.yaml");
+ assertTrue(outputYaml.exists());
+ }
+}
diff --git a/jackson-simple/.gitignore b/jackson-simple/.gitignore
new file mode 100644
index 0000000000..83c05e60c8
--- /dev/null
+++ b/jackson-simple/.gitignore
@@ -0,0 +1,13 @@
+*.class
+
+#folders#
+/target
+/neoDb*
+/data
+/src/main/webapp/WEB-INF/classes
+*/META-INF/*
+
+# Packaged files #
+*.jar
+*.war
+*.ear
\ No newline at end of file
diff --git a/jackson-simple/README.md b/jackson-simple/README.md
new file mode 100644
index 0000000000..be647e22d5
--- /dev/null
+++ b/jackson-simple/README.md
@@ -0,0 +1,13 @@
+=========
+### Jackson Articles that are also part of the e-book
+
+###The Course
+The "REST With Spring" Classes: http://bit.ly/restwithspring
+
+### Relevant Articles:
+- [Jackson Ignore Properties on Marshalling](http://www.baeldung.com/jackson-ignore-properties-on-serialization)
+- [Jackson Unmarshalling json with Unknown Properties](http://www.baeldung.com/jackson-deserialize-json-unknown-properties)
+- [Jackson Annotation Examples](http://www.baeldung.com/jackson-annotations)
+- [Intro to the Jackson ObjectMapper](http://www.baeldung.com/jackson-object-mapper-tutorial)
+- [Ignore Null Fields with Jackson](http://www.baeldung.com/jackson-ignore-null-fields)
+- [Jackson – Change Name of Field](http://www.baeldung.com/jackson-name-of-property)
diff --git a/jackson-simple/pom.xml b/jackson-simple/pom.xml
new file mode 100644
index 0000000000..5023ad87b6
--- /dev/null
+++ b/jackson-simple/pom.xml
@@ -0,0 +1,131 @@
+
+ 4.0.0
+ jackson-simple
+ 0.1-SNAPSHOT
+ jackson-simple
+
+
+ com.baeldung
+ parent-java
+ 0.0.1-SNAPSHOT
+ ../parent-java
+
+
+
+
+
+ commons-io
+ commons-io
+ ${commons-io.version}
+
+
+
+ com.fasterxml.jackson.dataformat
+ jackson-dataformat-xml
+ ${jackson.version}
+
+
+
+ org.apache.commons
+ commons-collections4
+ ${commons-collections4.version}
+
+
+
+ org.apache.commons
+ commons-lang3
+ ${commons-lang3.version}
+
+
+
+
+
+ com.fasterxml.jackson.core
+ jackson-databind
+ ${jackson.version}
+
+
+
+ com.fasterxml.jackson.datatype
+ jackson-datatype-jsr310
+ ${jackson.version}
+
+
+
+ com.fasterxml.jackson.datatype
+ jackson-datatype-joda
+ ${jackson.version}
+
+
+
+ com.fasterxml.jackson.module
+ jackson-module-jsonSchema
+ ${jackson.version}
+
+
+
+ com.fasterxml.jackson.datatype
+ jackson-datatype-jdk8
+ ${jackson.version}
+
+
+
+ joda-time
+ joda-time
+ ${joda-time.version}
+
+
+
+ com.google.code.gson
+ gson
+ ${gson.version}
+
+
+
+
+
+ io.rest-assured
+ json-schema-validator
+ ${rest-assured.version}
+ test
+
+
+
+ io.rest-assured
+ json-path
+ ${rest-assured.version}
+ test
+
+
+
+ org.assertj
+ assertj-core
+ ${assertj.version}
+ test
+
+
+
+
+ jackson-simple
+
+
+ src/main/resources
+ true
+
+
+
+
+
+
+ 3.8
+ 2.10
+ 2.8.5
+ 4.2
+
+
+ 3.1.1
+ 3.11.0
+
+
+
diff --git a/jackson-simple/src/main/resources/logback.xml b/jackson-simple/src/main/resources/logback.xml
new file mode 100644
index 0000000000..56af2d397e
--- /dev/null
+++ b/jackson-simple/src/main/resources/logback.xml
@@ -0,0 +1,19 @@
+
+
+
+
+ %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/jackson/src/test/java/com/baeldung/jackson/annotation/AliasBean.java b/jackson-simple/src/test/java/com/baeldung/jackson/annotation/AliasBean.java
similarity index 100%
rename from jackson/src/test/java/com/baeldung/jackson/annotation/AliasBean.java
rename to jackson-simple/src/test/java/com/baeldung/jackson/annotation/AliasBean.java
diff --git a/jackson/src/test/java/com/baeldung/jackson/annotation/BeanWithCreator.java b/jackson-simple/src/test/java/com/baeldung/jackson/annotation/BeanWithCreator.java
similarity index 100%
rename from jackson/src/test/java/com/baeldung/jackson/annotation/BeanWithCreator.java
rename to jackson-simple/src/test/java/com/baeldung/jackson/annotation/BeanWithCreator.java
diff --git a/jackson/src/test/java/com/baeldung/jackson/annotation/BeanWithCustomAnnotation.java b/jackson-simple/src/test/java/com/baeldung/jackson/annotation/BeanWithCustomAnnotation.java
similarity index 100%
rename from jackson/src/test/java/com/baeldung/jackson/annotation/BeanWithCustomAnnotation.java
rename to jackson-simple/src/test/java/com/baeldung/jackson/annotation/BeanWithCustomAnnotation.java
diff --git a/jackson/src/test/java/com/baeldung/jackson/annotation/BeanWithFilter.java b/jackson-simple/src/test/java/com/baeldung/jackson/annotation/BeanWithFilter.java
similarity index 100%
rename from jackson/src/test/java/com/baeldung/jackson/annotation/BeanWithFilter.java
rename to jackson-simple/src/test/java/com/baeldung/jackson/annotation/BeanWithFilter.java
diff --git a/jackson/src/test/java/com/baeldung/jackson/annotation/BeanWithGetter.java b/jackson-simple/src/test/java/com/baeldung/jackson/annotation/BeanWithGetter.java
similarity index 100%
rename from jackson/src/test/java/com/baeldung/jackson/annotation/BeanWithGetter.java
rename to jackson-simple/src/test/java/com/baeldung/jackson/annotation/BeanWithGetter.java
diff --git a/jackson/src/test/java/com/baeldung/jackson/annotation/BeanWithIgnore.java b/jackson-simple/src/test/java/com/baeldung/jackson/annotation/BeanWithIgnore.java
similarity index 100%
rename from jackson/src/test/java/com/baeldung/jackson/annotation/BeanWithIgnore.java
rename to jackson-simple/src/test/java/com/baeldung/jackson/annotation/BeanWithIgnore.java
diff --git a/jackson/src/test/java/com/baeldung/jackson/annotation/BeanWithInject.java b/jackson-simple/src/test/java/com/baeldung/jackson/annotation/BeanWithInject.java
similarity index 100%
rename from jackson/src/test/java/com/baeldung/jackson/annotation/BeanWithInject.java
rename to jackson-simple/src/test/java/com/baeldung/jackson/annotation/BeanWithInject.java
diff --git a/jackson/src/test/java/com/baeldung/jackson/annotation/ExtendableBean.java b/jackson-simple/src/test/java/com/baeldung/jackson/annotation/ExtendableBean.java
similarity index 100%
rename from jackson/src/test/java/com/baeldung/jackson/annotation/ExtendableBean.java
rename to jackson-simple/src/test/java/com/baeldung/jackson/annotation/ExtendableBean.java
diff --git a/jackson/src/test/java/com/baeldung/jackson/annotation/MyBean.java b/jackson-simple/src/test/java/com/baeldung/jackson/annotation/MyBean.java
similarity index 100%
rename from jackson/src/test/java/com/baeldung/jackson/annotation/MyBean.java
rename to jackson-simple/src/test/java/com/baeldung/jackson/annotation/MyBean.java
diff --git a/jackson/src/test/java/com/baeldung/jackson/annotation/PrivateBean.java b/jackson-simple/src/test/java/com/baeldung/jackson/annotation/PrivateBean.java
similarity index 100%
rename from jackson/src/test/java/com/baeldung/jackson/annotation/PrivateBean.java
rename to jackson-simple/src/test/java/com/baeldung/jackson/annotation/PrivateBean.java
diff --git a/jackson/src/test/java/com/baeldung/jackson/annotation/RawBean.java b/jackson-simple/src/test/java/com/baeldung/jackson/annotation/RawBean.java
similarity index 100%
rename from jackson/src/test/java/com/baeldung/jackson/annotation/RawBean.java
rename to jackson-simple/src/test/java/com/baeldung/jackson/annotation/RawBean.java
diff --git a/jackson/src/test/java/com/baeldung/jackson/annotation/UnwrappedUser.java b/jackson-simple/src/test/java/com/baeldung/jackson/annotation/UnwrappedUser.java
similarity index 100%
rename from jackson/src/test/java/com/baeldung/jackson/annotation/UnwrappedUser.java
rename to jackson-simple/src/test/java/com/baeldung/jackson/annotation/UnwrappedUser.java
diff --git a/jackson/src/test/java/com/baeldung/jackson/annotation/UserWithIgnoreType.java b/jackson-simple/src/test/java/com/baeldung/jackson/annotation/UserWithIgnoreType.java
similarity index 100%
rename from jackson/src/test/java/com/baeldung/jackson/annotation/UserWithIgnoreType.java
rename to jackson-simple/src/test/java/com/baeldung/jackson/annotation/UserWithIgnoreType.java
diff --git a/jackson/src/test/java/com/baeldung/jackson/annotation/Zoo.java b/jackson-simple/src/test/java/com/baeldung/jackson/annotation/Zoo.java
similarity index 100%
rename from jackson/src/test/java/com/baeldung/jackson/annotation/Zoo.java
rename to jackson-simple/src/test/java/com/baeldung/jackson/annotation/Zoo.java
diff --git a/jackson-simple/src/test/java/com/baeldung/jackson/bidirection/ItemWithIdentity.java b/jackson-simple/src/test/java/com/baeldung/jackson/bidirection/ItemWithIdentity.java
new file mode 100644
index 0000000000..25de4a8f7a
--- /dev/null
+++ b/jackson-simple/src/test/java/com/baeldung/jackson/bidirection/ItemWithIdentity.java
@@ -0,0 +1,21 @@
+package com.baeldung.jackson.bidirection;
+
+import com.fasterxml.jackson.annotation.JsonIdentityInfo;
+import com.fasterxml.jackson.annotation.ObjectIdGenerators;
+
+@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")
+public class ItemWithIdentity {
+ public int id;
+ public String itemName;
+ public UserWithIdentity owner;
+
+ public ItemWithIdentity() {
+ super();
+ }
+
+ public ItemWithIdentity(final int id, final String itemName, final UserWithIdentity owner) {
+ this.id = id;
+ this.itemName = itemName;
+ this.owner = owner;
+ }
+}
diff --git a/jackson-simple/src/test/java/com/baeldung/jackson/bidirection/ItemWithIgnore.java b/jackson-simple/src/test/java/com/baeldung/jackson/bidirection/ItemWithIgnore.java
new file mode 100644
index 0000000000..910ccec174
--- /dev/null
+++ b/jackson-simple/src/test/java/com/baeldung/jackson/bidirection/ItemWithIgnore.java
@@ -0,0 +1,17 @@
+package com.baeldung.jackson.bidirection;
+
+public class ItemWithIgnore {
+ public int id;
+ public String itemName;
+ public UserWithIgnore owner;
+
+ public ItemWithIgnore() {
+ super();
+ }
+
+ public ItemWithIgnore(final int id, final String itemName, final UserWithIgnore owner) {
+ this.id = id;
+ this.itemName = itemName;
+ this.owner = owner;
+ }
+}
diff --git a/jackson-simple/src/test/java/com/baeldung/jackson/bidirection/ItemWithRef.java b/jackson-simple/src/test/java/com/baeldung/jackson/bidirection/ItemWithRef.java
new file mode 100644
index 0000000000..0ca8d721e8
--- /dev/null
+++ b/jackson-simple/src/test/java/com/baeldung/jackson/bidirection/ItemWithRef.java
@@ -0,0 +1,21 @@
+package com.baeldung.jackson.bidirection;
+
+import com.fasterxml.jackson.annotation.JsonManagedReference;
+
+public class ItemWithRef {
+ public int id;
+ public String itemName;
+
+ @JsonManagedReference
+ public UserWithRef owner;
+
+ public ItemWithRef() {
+ super();
+ }
+
+ public ItemWithRef(final int id, final String itemName, final UserWithRef owner) {
+ this.id = id;
+ this.itemName = itemName;
+ this.owner = owner;
+ }
+}
diff --git a/jackson-simple/src/test/java/com/baeldung/jackson/bidirection/UserWithIdentity.java b/jackson-simple/src/test/java/com/baeldung/jackson/bidirection/UserWithIdentity.java
new file mode 100644
index 0000000000..db83a09389
--- /dev/null
+++ b/jackson-simple/src/test/java/com/baeldung/jackson/bidirection/UserWithIdentity.java
@@ -0,0 +1,28 @@
+package com.baeldung.jackson.bidirection;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.fasterxml.jackson.annotation.JsonIdentityInfo;
+import com.fasterxml.jackson.annotation.ObjectIdGenerators;
+
+@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")
+public class UserWithIdentity {
+ public int id;
+ public String name;
+ public List userItems;
+
+ public UserWithIdentity() {
+ super();
+ }
+
+ public UserWithIdentity(final int id, final String name) {
+ this.id = id;
+ this.name = name;
+ userItems = new ArrayList();
+ }
+
+ public void addItem(final ItemWithIdentity item) {
+ userItems.add(item);
+ }
+}
diff --git a/jackson-simple/src/test/java/com/baeldung/jackson/bidirection/UserWithIgnore.java b/jackson-simple/src/test/java/com/baeldung/jackson/bidirection/UserWithIgnore.java
new file mode 100644
index 0000000000..857a373cc5
--- /dev/null
+++ b/jackson-simple/src/test/java/com/baeldung/jackson/bidirection/UserWithIgnore.java
@@ -0,0 +1,28 @@
+package com.baeldung.jackson.bidirection;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+
+public class UserWithIgnore {
+ public int id;
+ public String name;
+
+ @JsonIgnore
+ public List userItems;
+
+ public UserWithIgnore() {
+ super();
+ }
+
+ public UserWithIgnore(final int id, final String name) {
+ this.id = id;
+ this.name = name;
+ userItems = new ArrayList();
+ }
+
+ public void addItem(final ItemWithIgnore item) {
+ userItems.add(item);
+ }
+}
diff --git a/jackson-simple/src/test/java/com/baeldung/jackson/bidirection/UserWithRef.java b/jackson-simple/src/test/java/com/baeldung/jackson/bidirection/UserWithRef.java
new file mode 100644
index 0000000000..3de03fc651
--- /dev/null
+++ b/jackson-simple/src/test/java/com/baeldung/jackson/bidirection/UserWithRef.java
@@ -0,0 +1,28 @@
+package com.baeldung.jackson.bidirection;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.fasterxml.jackson.annotation.JsonBackReference;
+
+public class UserWithRef {
+ public int id;
+ public String name;
+
+ @JsonBackReference
+ public List userItems;
+
+ public UserWithRef() {
+ super();
+ }
+
+ public UserWithRef(final int id, final String name) {
+ this.id = id;
+ this.name = name;
+ userItems = new ArrayList();
+ }
+
+ public void addItem(final ItemWithRef item) {
+ userItems.add(item);
+ }
+}
diff --git a/jackson-simple/src/test/java/com/baeldung/jackson/date/CustomDateDeserializer.java b/jackson-simple/src/test/java/com/baeldung/jackson/date/CustomDateDeserializer.java
new file mode 100644
index 0000000000..90c7d9fbac
--- /dev/null
+++ b/jackson-simple/src/test/java/com/baeldung/jackson/date/CustomDateDeserializer.java
@@ -0,0 +1,36 @@
+package com.baeldung.jackson.date;
+
+import java.io.IOException;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
+
+public class CustomDateDeserializer extends StdDeserializer {
+
+ private static final long serialVersionUID = -5451717385630622729L;
+ private SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyy hh:mm:ss");
+
+ public CustomDateDeserializer() {
+ this(null);
+ }
+
+ public CustomDateDeserializer(final Class> vc) {
+ super(vc);
+ }
+
+ @Override
+ public Date deserialize(final JsonParser jsonparser, final DeserializationContext context) throws IOException, JsonProcessingException {
+ final String date = jsonparser.getText();
+ try {
+ return formatter.parse(date);
+ } catch (final ParseException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+}
diff --git a/jackson-simple/src/test/java/com/baeldung/jackson/date/CustomDateSerializer.java b/jackson-simple/src/test/java/com/baeldung/jackson/date/CustomDateSerializer.java
new file mode 100644
index 0000000000..d840e1940f
--- /dev/null
+++ b/jackson-simple/src/test/java/com/baeldung/jackson/date/CustomDateSerializer.java
@@ -0,0 +1,29 @@
+package com.baeldung.jackson.date;
+
+import java.io.IOException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.SerializerProvider;
+import com.fasterxml.jackson.databind.ser.std.StdSerializer;
+
+public class CustomDateSerializer extends StdSerializer {
+
+ private static final long serialVersionUID = -2894356342227378312L;
+ private SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyy hh:mm:ss");
+
+ public CustomDateSerializer() {
+ this(null);
+ }
+
+ public CustomDateSerializer(final Class t) {
+ super(t);
+ }
+
+ @Override
+ public void serialize(final Date value, final JsonGenerator gen, final SerializerProvider arg2) throws IOException, JsonProcessingException {
+ gen.writeString(formatter.format(value));
+ }
+}
diff --git a/jackson-simple/src/test/java/com/baeldung/jackson/date/EventWithFormat.java b/jackson-simple/src/test/java/com/baeldung/jackson/date/EventWithFormat.java
new file mode 100644
index 0000000000..607e694cef
--- /dev/null
+++ b/jackson-simple/src/test/java/com/baeldung/jackson/date/EventWithFormat.java
@@ -0,0 +1,29 @@
+package com.baeldung.jackson.date;
+
+import java.util.Date;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+
+public class EventWithFormat {
+ public String name;
+
+ @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "dd-MM-yyyy hh:mm:ss")
+ public Date eventDate;
+
+ public EventWithFormat() {
+ super();
+ }
+
+ public EventWithFormat(final String name, final Date eventDate) {
+ this.name = name;
+ this.eventDate = eventDate;
+ }
+
+ public Date getEventDate() {
+ return eventDate;
+ }
+
+ public String getName() {
+ return name;
+ }
+}
diff --git a/jackson-simple/src/test/java/com/baeldung/jackson/date/EventWithSerializer.java b/jackson-simple/src/test/java/com/baeldung/jackson/date/EventWithSerializer.java
new file mode 100644
index 0000000000..c359b5c846
--- /dev/null
+++ b/jackson-simple/src/test/java/com/baeldung/jackson/date/EventWithSerializer.java
@@ -0,0 +1,31 @@
+package com.baeldung.jackson.date;
+
+import java.util.Date;
+
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+
+public class EventWithSerializer {
+ public String name;
+
+ @JsonDeserialize(using = CustomDateDeserializer.class)
+ @JsonSerialize(using = CustomDateSerializer.class)
+ public Date eventDate;
+
+ public EventWithSerializer() {
+ super();
+ }
+
+ public EventWithSerializer(final String name, final Date eventDate) {
+ this.name = name;
+ this.eventDate = eventDate;
+ }
+
+ public Date getEventDate() {
+ return eventDate;
+ }
+
+ public String getName() {
+ return name;
+ }
+}
diff --git a/jackson-simple/src/test/java/com/baeldung/jackson/deserialization/ItemDeserializerOnClass.java b/jackson-simple/src/test/java/com/baeldung/jackson/deserialization/ItemDeserializerOnClass.java
new file mode 100644
index 0000000000..eaba9a7173
--- /dev/null
+++ b/jackson-simple/src/test/java/com/baeldung/jackson/deserialization/ItemDeserializerOnClass.java
@@ -0,0 +1,41 @@
+package com.baeldung.jackson.deserialization;
+
+import java.io.IOException;
+
+import com.baeldung.jackson.dtos.ItemWithSerializer;
+import com.baeldung.jackson.dtos.User;
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
+import com.fasterxml.jackson.databind.node.IntNode;
+
+public class ItemDeserializerOnClass extends StdDeserializer {
+
+ private static final long serialVersionUID = 5579141241817332594L;
+
+ public ItemDeserializerOnClass() {
+ this(null);
+ }
+
+ public ItemDeserializerOnClass(final Class> vc) {
+ super(vc);
+ }
+
+ /**
+ * {"id":1,"itemNr":"theItem","owner":2}
+ */
+ @Override
+ public ItemWithSerializer deserialize(final JsonParser jp, final DeserializationContext ctxt) throws IOException, JsonProcessingException {
+ final JsonNode node = jp.getCodec()
+ .readTree(jp);
+ final int id = (Integer) ((IntNode) node.get("id")).numberValue();
+ final String itemName = node.get("itemName")
+ .asText();
+ final int userId = (Integer) ((IntNode) node.get("owner")).numberValue();
+
+ return new ItemWithSerializer(id, itemName, new User(userId, null));
+ }
+
+}
\ No newline at end of file
diff --git a/jackson-simple/src/test/java/com/baeldung/jackson/dtos/Item.java b/jackson-simple/src/test/java/com/baeldung/jackson/dtos/Item.java
new file mode 100644
index 0000000000..6fce2bc88e
--- /dev/null
+++ b/jackson-simple/src/test/java/com/baeldung/jackson/dtos/Item.java
@@ -0,0 +1,32 @@
+package com.baeldung.jackson.dtos;
+
+public class Item {
+ public int id;
+ public String itemName;
+ public User owner;
+
+ public Item() {
+ super();
+ }
+
+ public Item(final int id, final String itemName, final User owner) {
+ this.id = id;
+ this.itemName = itemName;
+ this.owner = owner;
+ }
+
+ // API
+
+ public int getId() {
+ return id;
+ }
+
+ public String getItemName() {
+ return itemName;
+ }
+
+ public User getOwner() {
+ return owner;
+ }
+
+}
\ No newline at end of file
diff --git a/jackson-simple/src/test/java/com/baeldung/jackson/dtos/ItemWithSerializer.java b/jackson-simple/src/test/java/com/baeldung/jackson/dtos/ItemWithSerializer.java
new file mode 100644
index 0000000000..aea9aa770d
--- /dev/null
+++ b/jackson-simple/src/test/java/com/baeldung/jackson/dtos/ItemWithSerializer.java
@@ -0,0 +1,36 @@
+package com.baeldung.jackson.dtos;
+
+import com.baeldung.jackson.deserialization.ItemDeserializerOnClass;
+import com.baeldung.jackson.serialization.ItemSerializerOnClass;
+
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+
+@JsonSerialize(using = ItemSerializerOnClass.class)
+@JsonDeserialize(using = ItemDeserializerOnClass.class)
+public class ItemWithSerializer {
+ public final int id;
+ public final String itemName;
+ public final User owner;
+
+ public ItemWithSerializer(final int id, final String itemName, final User owner) {
+ this.id = id;
+ this.itemName = itemName;
+ this.owner = owner;
+ }
+
+ // API
+
+ public int getId() {
+ return id;
+ }
+
+ public String getItemName() {
+ return itemName;
+ }
+
+ public User getOwner() {
+ return owner;
+ }
+
+}
\ No newline at end of file
diff --git a/jackson-simple/src/test/java/com/baeldung/jackson/dtos/MyDto.java b/jackson-simple/src/test/java/com/baeldung/jackson/dtos/MyDto.java
new file mode 100644
index 0000000000..49cf07baea
--- /dev/null
+++ b/jackson-simple/src/test/java/com/baeldung/jackson/dtos/MyDto.java
@@ -0,0 +1,54 @@
+package com.baeldung.jackson.dtos;
+
+public class MyDto {
+
+ private String stringValue;
+ private int intValue;
+ private boolean booleanValue;
+
+ public MyDto() {
+ super();
+ }
+
+ public MyDto(final String stringValue, final int intValue, final boolean booleanValue) {
+ super();
+
+ this.stringValue = stringValue;
+ this.intValue = intValue;
+ this.booleanValue = booleanValue;
+ }
+
+ // API
+
+ public String getStringValue() {
+ return stringValue;
+ }
+
+ public void setStringValue(final String stringValue) {
+ this.stringValue = stringValue;
+ }
+
+ public int getIntValue() {
+ return intValue;
+ }
+
+ public void setIntValue(final int intValue) {
+ this.intValue = intValue;
+ }
+
+ public boolean isBooleanValue() {
+ return booleanValue;
+ }
+
+ public void setBooleanValue(final boolean booleanValue) {
+ this.booleanValue = booleanValue;
+ }
+
+ //
+
+ @Override
+ public String toString() {
+ return "MyDto [stringValue=" + stringValue + ", intValue=" + intValue + ", booleanValue=" + booleanValue + "]";
+ }
+
+}
diff --git a/jackson/src/test/java/com/baeldung/jackson/dtos/MyDtoFieldNameChanged.java b/jackson-simple/src/test/java/com/baeldung/jackson/dtos/MyDtoFieldNameChanged.java
similarity index 100%
rename from jackson/src/test/java/com/baeldung/jackson/dtos/MyDtoFieldNameChanged.java
rename to jackson-simple/src/test/java/com/baeldung/jackson/dtos/MyDtoFieldNameChanged.java
diff --git a/jackson/src/test/java/com/baeldung/jackson/dtos/MyDtoIncludeNonDefault.java b/jackson-simple/src/test/java/com/baeldung/jackson/dtos/MyDtoIncludeNonDefault.java
similarity index 100%
rename from jackson/src/test/java/com/baeldung/jackson/dtos/MyDtoIncludeNonDefault.java
rename to jackson-simple/src/test/java/com/baeldung/jackson/dtos/MyDtoIncludeNonDefault.java
diff --git a/jackson/src/test/java/com/baeldung/jackson/dtos/MyDtoNoAccessors.java b/jackson-simple/src/test/java/com/baeldung/jackson/dtos/MyDtoNoAccessors.java
similarity index 100%
rename from jackson/src/test/java/com/baeldung/jackson/dtos/MyDtoNoAccessors.java
rename to jackson-simple/src/test/java/com/baeldung/jackson/dtos/MyDtoNoAccessors.java
diff --git a/jackson/src/test/java/com/baeldung/jackson/dtos/MyDtoNoAccessorsAndFieldVisibility.java b/jackson-simple/src/test/java/com/baeldung/jackson/dtos/MyDtoNoAccessorsAndFieldVisibility.java
similarity index 100%
rename from jackson/src/test/java/com/baeldung/jackson/dtos/MyDtoNoAccessorsAndFieldVisibility.java
rename to jackson-simple/src/test/java/com/baeldung/jackson/dtos/MyDtoNoAccessorsAndFieldVisibility.java
diff --git a/jackson/src/test/java/com/baeldung/jackson/dtos/MyDtoWithFilter.java b/jackson-simple/src/test/java/com/baeldung/jackson/dtos/MyDtoWithFilter.java
similarity index 100%
rename from jackson/src/test/java/com/baeldung/jackson/dtos/MyDtoWithFilter.java
rename to jackson-simple/src/test/java/com/baeldung/jackson/dtos/MyDtoWithFilter.java
diff --git a/jackson/src/test/java/com/baeldung/jackson/dtos/MyDtoWithSpecialField.java b/jackson-simple/src/test/java/com/baeldung/jackson/dtos/MyDtoWithSpecialField.java
similarity index 100%
rename from jackson/src/test/java/com/baeldung/jackson/dtos/MyDtoWithSpecialField.java
rename to jackson-simple/src/test/java/com/baeldung/jackson/dtos/MyDtoWithSpecialField.java
diff --git a/jackson/src/test/java/com/baeldung/jackson/dtos/MyMixInForIgnoreType.java b/jackson-simple/src/test/java/com/baeldung/jackson/dtos/MyMixInForIgnoreType.java
similarity index 100%
rename from jackson/src/test/java/com/baeldung/jackson/dtos/MyMixInForIgnoreType.java
rename to jackson-simple/src/test/java/com/baeldung/jackson/dtos/MyMixInForIgnoreType.java
diff --git a/jackson-simple/src/test/java/com/baeldung/jackson/dtos/User.java b/jackson-simple/src/test/java/com/baeldung/jackson/dtos/User.java
new file mode 100644
index 0000000000..2418e8070d
--- /dev/null
+++ b/jackson-simple/src/test/java/com/baeldung/jackson/dtos/User.java
@@ -0,0 +1,26 @@
+package com.baeldung.jackson.dtos;
+
+public class User {
+ public int id;
+ public String name;
+
+ public User() {
+ super();
+ }
+
+ public User(final int id, final String name) {
+ this.id = id;
+ this.name = name;
+ }
+
+ // API
+
+ public int getId() {
+ return id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+}
\ No newline at end of file
diff --git a/jackson/src/test/java/com/baeldung/jackson/dtos/ignore/MyDtoIgnoreField.java b/jackson-simple/src/test/java/com/baeldung/jackson/dtos/ignore/MyDtoIgnoreField.java
similarity index 100%
rename from jackson/src/test/java/com/baeldung/jackson/dtos/ignore/MyDtoIgnoreField.java
rename to jackson-simple/src/test/java/com/baeldung/jackson/dtos/ignore/MyDtoIgnoreField.java
diff --git a/jackson/src/test/java/com/baeldung/jackson/dtos/ignore/MyDtoIgnoreFieldByName.java b/jackson-simple/src/test/java/com/baeldung/jackson/dtos/ignore/MyDtoIgnoreFieldByName.java
similarity index 100%
rename from jackson/src/test/java/com/baeldung/jackson/dtos/ignore/MyDtoIgnoreFieldByName.java
rename to jackson-simple/src/test/java/com/baeldung/jackson/dtos/ignore/MyDtoIgnoreFieldByName.java
diff --git a/jackson/src/test/java/com/baeldung/jackson/dtos/ignore/MyDtoIgnoreNull.java b/jackson-simple/src/test/java/com/baeldung/jackson/dtos/ignore/MyDtoIgnoreNull.java
similarity index 100%
rename from jackson/src/test/java/com/baeldung/jackson/dtos/ignore/MyDtoIgnoreNull.java
rename to jackson-simple/src/test/java/com/baeldung/jackson/dtos/ignore/MyDtoIgnoreNull.java
diff --git a/jackson-simple/src/test/java/com/baeldung/jackson/dtos/withEnum/DistanceEnumWithValue.java b/jackson-simple/src/test/java/com/baeldung/jackson/dtos/withEnum/DistanceEnumWithValue.java
new file mode 100644
index 0000000000..69c476d8a5
--- /dev/null
+++ b/jackson-simple/src/test/java/com/baeldung/jackson/dtos/withEnum/DistanceEnumWithValue.java
@@ -0,0 +1,29 @@
+package com.baeldung.jackson.dtos.withEnum;
+
+import com.fasterxml.jackson.annotation.JsonValue;
+
+public enum DistanceEnumWithValue {
+ KILOMETER("km", 1000), MILE("miles", 1609.34), METER("meters", 1), INCH("inches", 0.0254), CENTIMETER("cm", 0.01), MILLIMETER("mm", 0.001);
+
+ private String unit;
+ private final double meters;
+
+ private DistanceEnumWithValue(String unit, double meters) {
+ this.unit = unit;
+ this.meters = meters;
+ }
+
+ @JsonValue
+ public double getMeters() {
+ return meters;
+ }
+
+ public String getUnit() {
+ return unit;
+ }
+
+ public void setUnit(String unit) {
+ this.unit = unit;
+ }
+
+}
\ No newline at end of file
diff --git a/jackson-simple/src/test/java/com/baeldung/jackson/exception/UserWithRoot.java b/jackson-simple/src/test/java/com/baeldung/jackson/exception/UserWithRoot.java
new file mode 100644
index 0000000000..d879c16e6a
--- /dev/null
+++ b/jackson-simple/src/test/java/com/baeldung/jackson/exception/UserWithRoot.java
@@ -0,0 +1,18 @@
+package com.baeldung.jackson.exception;
+
+import com.fasterxml.jackson.annotation.JsonRootName;
+
+@JsonRootName(value = "user")
+public class UserWithRoot {
+ public int id;
+ public String name;
+
+ public UserWithRoot() {
+ super();
+ }
+
+ public UserWithRoot(final int id, final String name) {
+ this.id = id;
+ this.name = name;
+ }
+}
diff --git a/jackson/src/test/java/com/baeldung/jackson/exception/UserWithRootNamespace.java b/jackson-simple/src/test/java/com/baeldung/jackson/exception/UserWithRootNamespace.java
similarity index 100%
rename from jackson/src/test/java/com/baeldung/jackson/exception/UserWithRootNamespace.java
rename to jackson-simple/src/test/java/com/baeldung/jackson/exception/UserWithRootNamespace.java
diff --git a/jackson-simple/src/test/java/com/baeldung/jackson/jsonview/Item.java b/jackson-simple/src/test/java/com/baeldung/jackson/jsonview/Item.java
new file mode 100644
index 0000000000..26d20d4847
--- /dev/null
+++ b/jackson-simple/src/test/java/com/baeldung/jackson/jsonview/Item.java
@@ -0,0 +1,36 @@
+package com.baeldung.jackson.jsonview;
+
+import com.fasterxml.jackson.annotation.JsonView;
+
+public class Item {
+ @JsonView(Views.Public.class)
+ public int id;
+
+ @JsonView(Views.Public.class)
+ public String itemName;
+
+ @JsonView(Views.Internal.class)
+ public String ownerName;
+
+ public Item() {
+ super();
+ }
+
+ public Item(final int id, final String itemName, final String ownerName) {
+ this.id = id;
+ this.itemName = itemName;
+ this.ownerName = ownerName;
+ }
+
+ public int getId() {
+ return id;
+ }
+
+ public String getItemName() {
+ return itemName;
+ }
+
+ public String getOwnerName() {
+ return ownerName;
+ }
+}
diff --git a/jackson-simple/src/test/java/com/baeldung/jackson/jsonview/Views.java b/jackson-simple/src/test/java/com/baeldung/jackson/jsonview/Views.java
new file mode 100644
index 0000000000..65950b7f9f
--- /dev/null
+++ b/jackson-simple/src/test/java/com/baeldung/jackson/jsonview/Views.java
@@ -0,0 +1,9 @@
+package com.baeldung.jackson.jsonview;
+
+public class Views {
+ public static class Public {
+ }
+
+ public static class Internal extends Public {
+ }
+}
diff --git a/jackson/src/test/java/com/baeldung/jackson/objectmapper/CustomCarDeserializer.java b/jackson-simple/src/test/java/com/baeldung/jackson/objectmapper/CustomCarDeserializer.java
similarity index 100%
rename from jackson/src/test/java/com/baeldung/jackson/objectmapper/CustomCarDeserializer.java
rename to jackson-simple/src/test/java/com/baeldung/jackson/objectmapper/CustomCarDeserializer.java
diff --git a/jackson/src/test/java/com/baeldung/jackson/objectmapper/CustomCarSerializer.java b/jackson-simple/src/test/java/com/baeldung/jackson/objectmapper/CustomCarSerializer.java
similarity index 100%
rename from jackson/src/test/java/com/baeldung/jackson/objectmapper/CustomCarSerializer.java
rename to jackson-simple/src/test/java/com/baeldung/jackson/objectmapper/CustomCarSerializer.java
diff --git a/jackson/src/test/java/com/baeldung/jackson/objectmapper/JavaReadWriteJsonExampleUnitTest.java b/jackson-simple/src/test/java/com/baeldung/jackson/objectmapper/JavaReadWriteJsonExampleUnitTest.java
similarity index 100%
rename from jackson/src/test/java/com/baeldung/jackson/objectmapper/JavaReadWriteJsonExampleUnitTest.java
rename to jackson-simple/src/test/java/com/baeldung/jackson/objectmapper/JavaReadWriteJsonExampleUnitTest.java
diff --git a/jackson/src/test/java/com/baeldung/jackson/objectmapper/SerializationDeserializationFeatureUnitTest.java b/jackson-simple/src/test/java/com/baeldung/jackson/objectmapper/SerializationDeserializationFeatureUnitTest.java
similarity index 100%
rename from jackson/src/test/java/com/baeldung/jackson/objectmapper/SerializationDeserializationFeatureUnitTest.java
rename to jackson-simple/src/test/java/com/baeldung/jackson/objectmapper/SerializationDeserializationFeatureUnitTest.java
diff --git a/jackson/src/test/java/com/baeldung/jackson/objectmapper/dto/Car.java b/jackson-simple/src/test/java/com/baeldung/jackson/objectmapper/dto/Car.java
similarity index 100%
rename from jackson/src/test/java/com/baeldung/jackson/objectmapper/dto/Car.java
rename to jackson-simple/src/test/java/com/baeldung/jackson/objectmapper/dto/Car.java
diff --git a/jackson/src/test/java/com/baeldung/jackson/objectmapper/dto/Request.java b/jackson-simple/src/test/java/com/baeldung/jackson/objectmapper/dto/Request.java
similarity index 100%
rename from jackson/src/test/java/com/baeldung/jackson/objectmapper/dto/Request.java
rename to jackson-simple/src/test/java/com/baeldung/jackson/objectmapper/dto/Request.java
diff --git a/jackson/src/test/java/com/baeldung/jackson/serialization/ItemSerializer.java b/jackson-simple/src/test/java/com/baeldung/jackson/serialization/ItemSerializer.java
similarity index 100%
rename from jackson/src/test/java/com/baeldung/jackson/serialization/ItemSerializer.java
rename to jackson-simple/src/test/java/com/baeldung/jackson/serialization/ItemSerializer.java
diff --git a/jackson-simple/src/test/java/com/baeldung/jackson/serialization/ItemSerializerOnClass.java b/jackson-simple/src/test/java/com/baeldung/jackson/serialization/ItemSerializerOnClass.java
new file mode 100644
index 0000000000..1fdf44e17c
--- /dev/null
+++ b/jackson-simple/src/test/java/com/baeldung/jackson/serialization/ItemSerializerOnClass.java
@@ -0,0 +1,32 @@
+package com.baeldung.jackson.serialization;
+
+import java.io.IOException;
+
+import com.baeldung.jackson.dtos.ItemWithSerializer;
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.SerializerProvider;
+import com.fasterxml.jackson.databind.ser.std.StdSerializer;
+
+public class ItemSerializerOnClass extends StdSerializer {
+
+ private static final long serialVersionUID = -1760959597313610409L;
+
+ public ItemSerializerOnClass() {
+ this(null);
+ }
+
+ public ItemSerializerOnClass(final Class t) {
+ super(t);
+ }
+
+ @Override
+ public final void serialize(final ItemWithSerializer value, final JsonGenerator jgen, final SerializerProvider provider) throws IOException, JsonProcessingException {
+ jgen.writeStartObject();
+ jgen.writeNumberField("id", value.id);
+ jgen.writeStringField("itemName", value.itemName);
+ jgen.writeNumberField("owner", value.owner.id);
+ jgen.writeEndObject();
+ }
+
+}
\ No newline at end of file
diff --git a/jackson/src/test/java/com/baeldung/jackson/serialization/MyDtoNullKeySerializer.java b/jackson-simple/src/test/java/com/baeldung/jackson/serialization/MyDtoNullKeySerializer.java
similarity index 100%
rename from jackson/src/test/java/com/baeldung/jackson/serialization/MyDtoNullKeySerializer.java
rename to jackson-simple/src/test/java/com/baeldung/jackson/serialization/MyDtoNullKeySerializer.java
diff --git a/jackson/src/test/java/com/baeldung/jackson/test/JacksonAnnotationUnitTest.java b/jackson-simple/src/test/java/com/baeldung/jackson/test/JacksonAnnotationUnitTest.java
similarity index 100%
rename from jackson/src/test/java/com/baeldung/jackson/test/JacksonAnnotationUnitTest.java
rename to jackson-simple/src/test/java/com/baeldung/jackson/test/JacksonAnnotationUnitTest.java
diff --git a/jackson/src/test/java/com/baeldung/jackson/test/JacksonSerializationIgnoreUnitTest.java b/jackson-simple/src/test/java/com/baeldung/jackson/test/JacksonSerializationIgnoreUnitTest.java
similarity index 100%
rename from jackson/src/test/java/com/baeldung/jackson/test/JacksonSerializationIgnoreUnitTest.java
rename to jackson-simple/src/test/java/com/baeldung/jackson/test/JacksonSerializationIgnoreUnitTest.java
diff --git a/jackson/src/test/java/com/baeldung/jackson/test/JacksonSerializationUnitTest.java b/jackson-simple/src/test/java/com/baeldung/jackson/test/JacksonSerializationUnitTest.java
similarity index 100%
rename from jackson/src/test/java/com/baeldung/jackson/test/JacksonSerializationUnitTest.java
rename to jackson-simple/src/test/java/com/baeldung/jackson/test/JacksonSerializationUnitTest.java
diff --git a/jackson-simple/src/test/resources/.gitignore b/jackson-simple/src/test/resources/.gitignore
new file mode 100644
index 0000000000..83c05e60c8
--- /dev/null
+++ b/jackson-simple/src/test/resources/.gitignore
@@ -0,0 +1,13 @@
+*.class
+
+#folders#
+/target
+/neoDb*
+/data
+/src/main/webapp/WEB-INF/classes
+*/META-INF/*
+
+# Packaged files #
+*.jar
+*.war
+*.ear
\ No newline at end of file
diff --git a/jackson/README.md b/jackson/README.md
index e9cf6f212c..794ddc04d9 100644
--- a/jackson/README.md
+++ b/jackson/README.md
@@ -6,9 +6,7 @@
The "REST With Spring" Classes: http://bit.ly/restwithspring
### Relevant Articles:
-- [Jackson Ignore Properties on Marshalling](http://www.baeldung.com/jackson-ignore-properties-on-serialization)
- [Jackson – Unmarshall to Collection/Array](http://www.baeldung.com/jackson-collection-array)
-- [Jackson Unmarshalling json with Unknown Properties](http://www.baeldung.com/jackson-deserialize-json-unknown-properties)
- [Jackson – Custom Serializer](http://www.baeldung.com/jackson-custom-serialization)
- [Getting Started with Custom Deserialization in Jackson](http://www.baeldung.com/jackson-deserialization)
- [Jackson Exceptions – Problems and Solutions](http://www.baeldung.com/jackson-exception)
@@ -16,11 +14,9 @@ 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 Annotation Examples](http://www.baeldung.com/jackson-annotations)
+- [Jackson – Decide What Fields Get Serialized/Deserialized](http://www.baeldung.com/jackson-field-serializable-deserializable-or-not)
- [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)
-- [Intro to the Jackson ObjectMapper](http://www.baeldung.com/jackson-object-mapper-tutorial)
- [XML Serialization and Deserialization with Jackson](http://www.baeldung.com/jackson-xml-serialization-and-deserialization)
- [More Jackson Annotations](http://www.baeldung.com/jackson-advanced-annotations)
- [Inheritance with Jackson](http://www.baeldung.com/jackson-inheritance)
@@ -31,9 +27,7 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring
- [Jackson – JsonMappingException (No serializer found for class)](http://www.baeldung.com/jackson-jsonmappingexception)
- [How To Serialize Enums as JSON Objects with Jackson](http://www.baeldung.com/jackson-serialize-enums)
- [Jackson – Marshall String to JsonNode](http://www.baeldung.com/jackson-json-to-jsonnode)
-- [Ignore Null Fields with Jackson](http://www.baeldung.com/jackson-ignore-null-fields)
- [Jackson – Unmarshall to Collection/Array](http://www.baeldung.com/jackson-collection-array)
-- [Jackson – Change Name of Field](http://www.baeldung.com/jackson-name-of-property)
- [Serialize Only Fields that meet a Custom Criteria with Jackson](http://www.baeldung.com/jackson-serialize-field-custom-criteria)
- [Mapping Nested Values with Jackson](http://www.baeldung.com/jackson-nested-values)
- [Convert XML to JSON Using Jackson](https://www.baeldung.com/jackson-convert-xml-json)
diff --git a/jackson/src/test/java/com/baeldung/jackson/test/UnitTestSuite.java b/jackson/src/test/java/com/baeldung/jackson/test/UnitTestSuite.java
index 6be2f29baa..e783c67f5b 100644
--- a/jackson/src/test/java/com/baeldung/jackson/test/UnitTestSuite.java
+++ b/jackson/src/test/java/com/baeldung/jackson/test/UnitTestSuite.java
@@ -12,8 +12,6 @@ import org.junit.runners.Suite;
,JacksonDeserializationUnitTest.class
,JacksonDeserializationUnitTest.class
,JacksonPrettyPrintUnitTest.class
- ,JacksonSerializationIgnoreUnitTest.class
- ,JacksonSerializationUnitTest.class
,SandboxUnitTest.class
,JacksonFieldUnitTest.class
}) // @formatter:on
diff --git a/java-collections-maps-2/README.md b/java-collections-maps-2/README.md
new file mode 100644
index 0000000000..8bcafccfe8
--- /dev/null
+++ b/java-collections-maps-2/README.md
@@ -0,0 +1,2 @@
+## Relevant Articles:
+- [Map of Primitives in Java](https://www.baeldung.com/java-map-primitives)
diff --git a/java-dates-2/README.md b/java-dates-2/README.md
new file mode 100644
index 0000000000..a6b5c8e574
--- /dev/null
+++ b/java-dates-2/README.md
@@ -0,0 +1,2 @@
+## Relevant Articles:
+- [Converting Between LocalDate and XMLGregorianCalendar](https://www.baeldung.com/java-localdate-to-xmlgregoriancalendar)
diff --git a/java-math/.gitignore b/java-math/.gitignore
new file mode 100644
index 0000000000..30b2b7442c
--- /dev/null
+++ b/java-math/.gitignore
@@ -0,0 +1,4 @@
+/target/
+.settings/
+.classpath
+.project
\ No newline at end of file
diff --git a/java-math/README.md b/java-math/README.md
new file mode 100644
index 0000000000..d821348204
--- /dev/null
+++ b/java-math/README.md
@@ -0,0 +1,10 @@
+## Relevant articles:
+
+- [Calculate Factorial in Java](https://www.baeldung.com/java-calculate-factorial)
+- [Generate Combinations in Java](https://www.baeldung.com/java-combinations-algorithm)
+- [Check If Two Rectangles Overlap In Java](https://www.baeldung.com/java-check-if-two-rectangles-overlap)
+- [Calculate the Distance Between Two Points in Java](https://www.baeldung.com/java-distance-between-two-points)
+- [Find the Intersection of Two Lines in Java](https://www.baeldung.com/java-intersection-of-two-lines)
+- [Round Up to the Nearest Hundred](https://www.baeldung.com/java-round-up-nearest-hundred)
+- [Calculate Percentage in Java](https://www.baeldung.com/java-calculate-percentage)
+- [Convert Latitude and Longitude to a 2D Point in Java](https://www.baeldung.com/java-convert-latitude-longitude)
\ No newline at end of file
diff --git a/java-math/pom.xml b/java-math/pom.xml
new file mode 100644
index 0000000000..159d053df3
--- /dev/null
+++ b/java-math/pom.xml
@@ -0,0 +1,68 @@
+
+ 4.0.0
+ java-math
+ 0.0.1-SNAPSHOT
+ java-math
+
+
+ com.baeldung
+ parent-modules
+ 1.0.0-SNAPSHOT
+
+
+
+
+ org.apache.commons
+ commons-math3
+ ${commons-math3.version}
+
+
+ com.google.guava
+ guava
+ ${guava.version}
+
+
+ commons-codec
+ commons-codec
+ ${commons-codec.version}
+
+
+ org.projectlombok
+ lombok
+ ${lombok.version}
+ provided
+
+
+ org.assertj
+ assertj-core
+ ${org.assertj.core.version}
+ test
+
+
+ com.github.dpaukov
+ combinatoricslib3
+ 3.3.0
+
+
+
+
+
+
+
+ org.codehaus.mojo
+ exec-maven-plugin
+ ${exec-maven-plugin.version}
+
+
+
+
+
+
+ 3.6.1
+ 3.9.0
+ 1.11
+ 27.0.1-jre
+
+
+
\ No newline at end of file
diff --git a/algorithms-miscellaneous-1/src/main/java/com/baeldung/algorithms/combination/ApacheCommonsCombinationGenerator.java b/java-math/src/main/java/com/baeldung/algorithms/combination/ApacheCommonsCombinationGenerator.java
similarity index 100%
rename from algorithms-miscellaneous-1/src/main/java/com/baeldung/algorithms/combination/ApacheCommonsCombinationGenerator.java
rename to java-math/src/main/java/com/baeldung/algorithms/combination/ApacheCommonsCombinationGenerator.java
diff --git a/algorithms-miscellaneous-1/src/main/java/com/baeldung/algorithms/combination/CombinatoricsLibCombinationGenerator.java b/java-math/src/main/java/com/baeldung/algorithms/combination/CombinatoricsLibCombinationGenerator.java
similarity index 100%
rename from algorithms-miscellaneous-1/src/main/java/com/baeldung/algorithms/combination/CombinatoricsLibCombinationGenerator.java
rename to java-math/src/main/java/com/baeldung/algorithms/combination/CombinatoricsLibCombinationGenerator.java
diff --git a/algorithms-miscellaneous-1/src/main/java/com/baeldung/algorithms/combination/GuavaCombinationsGenerator.java b/java-math/src/main/java/com/baeldung/algorithms/combination/GuavaCombinationsGenerator.java
similarity index 100%
rename from algorithms-miscellaneous-1/src/main/java/com/baeldung/algorithms/combination/GuavaCombinationsGenerator.java
rename to java-math/src/main/java/com/baeldung/algorithms/combination/GuavaCombinationsGenerator.java
diff --git a/algorithms-miscellaneous-1/src/main/java/com/baeldung/algorithms/combination/IterativeCombinationGenerator.java b/java-math/src/main/java/com/baeldung/algorithms/combination/IterativeCombinationGenerator.java
similarity index 100%
rename from algorithms-miscellaneous-1/src/main/java/com/baeldung/algorithms/combination/IterativeCombinationGenerator.java
rename to java-math/src/main/java/com/baeldung/algorithms/combination/IterativeCombinationGenerator.java
diff --git a/algorithms-miscellaneous-1/src/main/java/com/baeldung/algorithms/combination/SelectionRecursiveCombinationGenerator.java b/java-math/src/main/java/com/baeldung/algorithms/combination/SelectionRecursiveCombinationGenerator.java
similarity index 100%
rename from algorithms-miscellaneous-1/src/main/java/com/baeldung/algorithms/combination/SelectionRecursiveCombinationGenerator.java
rename to java-math/src/main/java/com/baeldung/algorithms/combination/SelectionRecursiveCombinationGenerator.java
diff --git a/algorithms-miscellaneous-1/src/main/java/com/baeldung/algorithms/combination/SetRecursiveCombinationGenerator.java b/java-math/src/main/java/com/baeldung/algorithms/combination/SetRecursiveCombinationGenerator.java
similarity index 100%
rename from algorithms-miscellaneous-1/src/main/java/com/baeldung/algorithms/combination/SetRecursiveCombinationGenerator.java
rename to java-math/src/main/java/com/baeldung/algorithms/combination/SetRecursiveCombinationGenerator.java
diff --git a/algorithms-miscellaneous-2/src/main/java/com/baeldung/algorithms/distancebetweenpoints/DistanceBetweenPointsService.java b/java-math/src/main/java/com/baeldung/algorithms/distancebetweenpoints/DistanceBetweenPointsService.java
similarity index 100%
rename from algorithms-miscellaneous-2/src/main/java/com/baeldung/algorithms/distancebetweenpoints/DistanceBetweenPointsService.java
rename to java-math/src/main/java/com/baeldung/algorithms/distancebetweenpoints/DistanceBetweenPointsService.java
diff --git a/algorithms-miscellaneous-1/src/main/java/com/baeldung/algorithms/factorial/Factorial.java b/java-math/src/main/java/com/baeldung/algorithms/factorial/Factorial.java
similarity index 100%
rename from algorithms-miscellaneous-1/src/main/java/com/baeldung/algorithms/factorial/Factorial.java
rename to java-math/src/main/java/com/baeldung/algorithms/factorial/Factorial.java
diff --git a/algorithms-miscellaneous-1/src/main/java/com/baeldung/algorithms/linesintersection/LinesIntersectionService.java b/java-math/src/main/java/com/baeldung/algorithms/linesintersection/LinesIntersectionService.java
similarity index 100%
rename from algorithms-miscellaneous-1/src/main/java/com/baeldung/algorithms/linesintersection/LinesIntersectionService.java
rename to java-math/src/main/java/com/baeldung/algorithms/linesintersection/LinesIntersectionService.java
diff --git a/algorithms-miscellaneous-2/src/main/java/com/baeldung/algorithms/mercator/EllipticalMercator.java b/java-math/src/main/java/com/baeldung/algorithms/mercator/EllipticalMercator.java
similarity index 100%
rename from algorithms-miscellaneous-2/src/main/java/com/baeldung/algorithms/mercator/EllipticalMercator.java
rename to java-math/src/main/java/com/baeldung/algorithms/mercator/EllipticalMercator.java
diff --git a/algorithms-miscellaneous-2/src/main/java/com/baeldung/algorithms/mercator/Mercator.java b/java-math/src/main/java/com/baeldung/algorithms/mercator/Mercator.java
similarity index 100%
rename from algorithms-miscellaneous-2/src/main/java/com/baeldung/algorithms/mercator/Mercator.java
rename to java-math/src/main/java/com/baeldung/algorithms/mercator/Mercator.java
diff --git a/algorithms-miscellaneous-2/src/main/java/com/baeldung/algorithms/mercator/SphericalMercator.java b/java-math/src/main/java/com/baeldung/algorithms/mercator/SphericalMercator.java
similarity index 100%
rename from algorithms-miscellaneous-2/src/main/java/com/baeldung/algorithms/mercator/SphericalMercator.java
rename to java-math/src/main/java/com/baeldung/algorithms/mercator/SphericalMercator.java
diff --git a/java-numbers/src/main/java/com/baeldung/percentage/PercentageCalculator.java b/java-math/src/main/java/com/baeldung/algorithms/percentage/PercentageCalculator.java
similarity index 93%
rename from java-numbers/src/main/java/com/baeldung/percentage/PercentageCalculator.java
rename to java-math/src/main/java/com/baeldung/algorithms/percentage/PercentageCalculator.java
index e74de2cc67..f69b23146e 100644
--- a/java-numbers/src/main/java/com/baeldung/percentage/PercentageCalculator.java
+++ b/java-math/src/main/java/com/baeldung/algorithms/percentage/PercentageCalculator.java
@@ -1,4 +1,4 @@
-package com.baeldung.percentage;
+package com.baeldung.algorithms.percentage;
import java.util.Scanner;
diff --git a/algorithms-miscellaneous-2/src/main/java/com/baeldung/algorithms/rectanglesoverlap/Point.java b/java-math/src/main/java/com/baeldung/algorithms/rectanglesoverlap/Point.java
similarity index 100%
rename from algorithms-miscellaneous-2/src/main/java/com/baeldung/algorithms/rectanglesoverlap/Point.java
rename to java-math/src/main/java/com/baeldung/algorithms/rectanglesoverlap/Point.java
diff --git a/algorithms-miscellaneous-2/src/main/java/com/baeldung/algorithms/rectanglesoverlap/Rectangle.java b/java-math/src/main/java/com/baeldung/algorithms/rectanglesoverlap/Rectangle.java
similarity index 100%
rename from algorithms-miscellaneous-2/src/main/java/com/baeldung/algorithms/rectanglesoverlap/Rectangle.java
rename to java-math/src/main/java/com/baeldung/algorithms/rectanglesoverlap/Rectangle.java
diff --git a/algorithms-miscellaneous-2/src/main/java/com/baeldung/algorithms/roundedup/RoundUpToHundred.java b/java-math/src/main/java/com/baeldung/algorithms/roundedup/RoundUpToHundred.java
similarity index 100%
rename from algorithms-miscellaneous-2/src/main/java/com/baeldung/algorithms/roundedup/RoundUpToHundred.java
rename to java-math/src/main/java/com/baeldung/algorithms/roundedup/RoundUpToHundred.java
diff --git a/spring-cloud/spring-cloud-kubernetes-2/client-service/src/main/resources/logback.xml b/java-math/src/main/resources/logback.xml
similarity index 100%
rename from spring-cloud/spring-cloud-kubernetes-2/client-service/src/main/resources/logback.xml
rename to java-math/src/main/resources/logback.xml
diff --git a/algorithms-miscellaneous-1/src/test/java/com/baeldung/algorithms/combination/CombinationUnitTest.java b/java-math/src/test/java/com/baeldung/algorithms/combination/CombinationUnitTest.java
similarity index 100%
rename from algorithms-miscellaneous-1/src/test/java/com/baeldung/algorithms/combination/CombinationUnitTest.java
rename to java-math/src/test/java/com/baeldung/algorithms/combination/CombinationUnitTest.java
diff --git a/algorithms-miscellaneous-2/src/test/java/com/baeldung/algorithms/distancebetweenpoints/DistanceBetweenPointsServiceUnitTest.java b/java-math/src/test/java/com/baeldung/algorithms/distancebetweenpoints/DistanceBetweenPointsServiceUnitTest.java
similarity index 93%
rename from algorithms-miscellaneous-2/src/test/java/com/baeldung/algorithms/distancebetweenpoints/DistanceBetweenPointsServiceUnitTest.java
rename to java-math/src/test/java/com/baeldung/algorithms/distancebetweenpoints/DistanceBetweenPointsServiceUnitTest.java
index 785afdbb2b..784681a807 100644
--- a/algorithms-miscellaneous-2/src/test/java/com/baeldung/algorithms/distancebetweenpoints/DistanceBetweenPointsServiceUnitTest.java
+++ b/java-math/src/test/java/com/baeldung/algorithms/distancebetweenpoints/DistanceBetweenPointsServiceUnitTest.java
@@ -2,8 +2,6 @@ package com.baeldung.algorithms.distancebetweenpoints;
import org.junit.Test;
-import com.baeldung.algorithms.distancebetweenpoints.DistanceBetweenPointsService;
-
import static org.junit.Assert.assertEquals;
public class DistanceBetweenPointsServiceUnitTest {
diff --git a/algorithms-miscellaneous-1/src/test/java/com/baeldung/algorithms/factorial/FactorialUnitTest.java b/java-math/src/test/java/com/baeldung/algorithms/factorial/FactorialUnitTest.java
similarity index 100%
rename from algorithms-miscellaneous-1/src/test/java/com/baeldung/algorithms/factorial/FactorialUnitTest.java
rename to java-math/src/test/java/com/baeldung/algorithms/factorial/FactorialUnitTest.java
diff --git a/algorithms-miscellaneous-1/src/test/java/com/baeldung/algorithms/linesintersection/LinesIntersectionServiceUnitTest.java b/java-math/src/test/java/com/baeldung/algorithms/linesintersection/LinesIntersectionServiceUnitTest.java
similarity index 100%
rename from algorithms-miscellaneous-1/src/test/java/com/baeldung/algorithms/linesintersection/LinesIntersectionServiceUnitTest.java
rename to java-math/src/test/java/com/baeldung/algorithms/linesintersection/LinesIntersectionServiceUnitTest.java
diff --git a/algorithms-miscellaneous-2/src/test/java/com/baeldung/algorithms/mercator/EllipticalMercatorUnitTest.java b/java-math/src/test/java/com/baeldung/algorithms/mercator/EllipticalMercatorUnitTest.java
similarity index 100%
rename from algorithms-miscellaneous-2/src/test/java/com/baeldung/algorithms/mercator/EllipticalMercatorUnitTest.java
rename to java-math/src/test/java/com/baeldung/algorithms/mercator/EllipticalMercatorUnitTest.java
diff --git a/algorithms-miscellaneous-2/src/test/java/com/baeldung/algorithms/mercator/SphericalMercatorUnitTest.java b/java-math/src/test/java/com/baeldung/algorithms/mercator/SphericalMercatorUnitTest.java
similarity index 100%
rename from algorithms-miscellaneous-2/src/test/java/com/baeldung/algorithms/mercator/SphericalMercatorUnitTest.java
rename to java-math/src/test/java/com/baeldung/algorithms/mercator/SphericalMercatorUnitTest.java
diff --git a/java-numbers/src/test/java/com/baeldung/percentage/PercentageCalculatorUnitTest.java b/java-math/src/test/java/com/baeldung/algorithms/percentage/PercentageCalculatorUnitTest.java
similarity index 95%
rename from java-numbers/src/test/java/com/baeldung/percentage/PercentageCalculatorUnitTest.java
rename to java-math/src/test/java/com/baeldung/algorithms/percentage/PercentageCalculatorUnitTest.java
index 202d4f8112..e49acc0c4b 100644
--- a/java-numbers/src/test/java/com/baeldung/percentage/PercentageCalculatorUnitTest.java
+++ b/java-math/src/test/java/com/baeldung/algorithms/percentage/PercentageCalculatorUnitTest.java
@@ -1,4 +1,4 @@
-package com.baeldung.percentage;
+package com.baeldung.algorithms.percentage;
import org.junit.Assert;
import org.junit.Test;
diff --git a/algorithms-miscellaneous-2/src/test/java/com/baeldung/algorithms/rectanglesoverlap/RectangleUnitTest.java b/java-math/src/test/java/com/baeldung/algorithms/rectanglesoverlap/RectangleUnitTest.java
similarity index 93%
rename from algorithms-miscellaneous-2/src/test/java/com/baeldung/algorithms/rectanglesoverlap/RectangleUnitTest.java
rename to java-math/src/test/java/com/baeldung/algorithms/rectanglesoverlap/RectangleUnitTest.java
index 6707b34477..e4bb614b48 100644
--- a/algorithms-miscellaneous-2/src/test/java/com/baeldung/algorithms/rectanglesoverlap/RectangleUnitTest.java
+++ b/java-math/src/test/java/com/baeldung/algorithms/rectanglesoverlap/RectangleUnitTest.java
@@ -4,9 +4,6 @@ import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertFalse;
import org.junit.Test;
-import com.baeldung.algorithms.rectanglesoverlap.Point;
-import com.baeldung.algorithms.rectanglesoverlap.Rectangle;
-
public class RectangleUnitTest {
@Test
diff --git a/algorithms-miscellaneous-2/src/test/java/com/baeldung/algorithms/roundedup/RoundUpToHundredUnitTest.java b/java-math/src/test/java/com/baeldung/algorithms/roundedup/RoundUpToHundredUnitTest.java
similarity index 100%
rename from algorithms-miscellaneous-2/src/test/java/com/baeldung/algorithms/roundedup/RoundUpToHundredUnitTest.java
rename to java-math/src/test/java/com/baeldung/algorithms/roundedup/RoundUpToHundredUnitTest.java
diff --git a/java-streams/README.md b/java-streams/README.md
index e294e5aee1..0c9588c47e 100644
--- a/java-streams/README.md
+++ b/java-streams/README.md
@@ -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)
diff --git a/kotlin-libraries/README.md b/kotlin-libraries/README.md
index 5e2526e64e..94359193b6 100644
--- a/kotlin-libraries/README.md
+++ b/kotlin-libraries/README.md
@@ -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)
\ No newline at end of file
diff --git a/libraries2/pom.xml b/libraries-2/pom.xml
similarity index 100%
rename from libraries2/pom.xml
rename to libraries-2/pom.xml
diff --git a/libraries2/src/main/java/com/baeldung/jbpm/WorkflowProcessMain.java b/libraries-2/src/main/java/com/baeldung/jbpm/WorkflowProcessMain.java
similarity index 100%
rename from libraries2/src/main/java/com/baeldung/jbpm/WorkflowProcessMain.java
rename to libraries-2/src/main/java/com/baeldung/jbpm/WorkflowProcessMain.java
diff --git a/libraries2/src/main/java/com/baeldung/jbpm/engine/WorkflowEngine.java b/libraries-2/src/main/java/com/baeldung/jbpm/engine/WorkflowEngine.java
similarity index 100%
rename from libraries2/src/main/java/com/baeldung/jbpm/engine/WorkflowEngine.java
rename to libraries-2/src/main/java/com/baeldung/jbpm/engine/WorkflowEngine.java
diff --git a/libraries2/src/main/java/com/baeldung/jbpm/engine/WorkflowEngineImpl.java b/libraries-2/src/main/java/com/baeldung/jbpm/engine/WorkflowEngineImpl.java
similarity index 100%
rename from libraries2/src/main/java/com/baeldung/jbpm/engine/WorkflowEngineImpl.java
rename to libraries-2/src/main/java/com/baeldung/jbpm/engine/WorkflowEngineImpl.java
diff --git a/libraries2/src/main/resources/META-INF/kmodule.xml b/libraries-2/src/main/resources/META-INF/kmodule.xml
similarity index 100%
rename from libraries2/src/main/resources/META-INF/kmodule.xml
rename to libraries-2/src/main/resources/META-INF/kmodule.xml
diff --git a/libraries2/src/main/resources/com/baeldung/process/helloworld.bpmn b/libraries-2/src/main/resources/com/baeldung/process/helloworld.bpmn
similarity index 100%
rename from libraries2/src/main/resources/com/baeldung/process/helloworld.bpmn
rename to libraries-2/src/main/resources/com/baeldung/process/helloworld.bpmn
diff --git a/libraries2/src/test/java/com/baeldung/jbpm/WorkflowEngineIntegrationTest.java b/libraries-2/src/test/java/com/baeldung/jbpm/WorkflowEngineIntegrationTest.java
similarity index 100%
rename from libraries2/src/test/java/com/baeldung/jbpm/WorkflowEngineIntegrationTest.java
rename to libraries-2/src/test/java/com/baeldung/jbpm/WorkflowEngineIntegrationTest.java
diff --git a/libraries-apache-commons/src/main/java/com/baeldung/commons/beanutils/CourseService.java b/libraries-apache-commons/src/main/java/com/baeldung/commons/beanutils/CourseService.java
index 538fa3accb..2c7644fd64 100644
--- a/libraries-apache-commons/src/main/java/com/baeldung/commons/beanutils/CourseService.java
+++ b/libraries-apache-commons/src/main/java/com/baeldung/commons/beanutils/CourseService.java
@@ -29,6 +29,6 @@ public class CourseService {
}
public static void copyProperties(Course course, CourseEntity courseEntity) throws IllegalAccessException, InvocationTargetException {
- BeanUtils.copyProperties(course, courseEntity);
+ BeanUtils.copyProperties(courseEntity, course);
}
}
diff --git a/libraries-apache-commons/src/test/java/com/baeldung/commons/beanutils/CourseServiceUnitTest.java b/libraries-apache-commons/src/test/java/com/baeldung/commons/beanutils/CourseServiceUnitTest.java
index 833d91b2c4..224ee8404c 100644
--- a/libraries-apache-commons/src/test/java/com/baeldung/commons/beanutils/CourseServiceUnitTest.java
+++ b/libraries-apache-commons/src/test/java/com/baeldung/commons/beanutils/CourseServiceUnitTest.java
@@ -44,6 +44,8 @@ public class CourseServiceUnitTest {
CourseEntity courseEntity = new CourseEntity();
CourseService.copyProperties(course, courseEntity);
+ Assert.assertNotNull(course.getName());
+ Assert.assertNotNull(courseEntity.getName());
Assert.assertEquals(course.getName(), courseEntity.getName());
Assert.assertEquals(course.getCodes(), courseEntity.getCodes());
Assert.assertNull(courseEntity.getStudent("ST-1"));
diff --git a/libraries-security/pom.xml b/libraries-security/pom.xml
index 9f125361ba..17d57fe203 100644
--- a/libraries-security/pom.xml
+++ b/libraries-security/pom.xml
@@ -32,6 +32,12 @@
${scribejava.version}
+
+ com.google.crypto.tink
+ tink
+ ${tink.version}
+
+
junit
junit
@@ -55,6 +61,7 @@
5.6.0
2.3.3.RELEASE
1.3.1
+ 1.2.2
1.2.2
diff --git a/libraries-security/src/test/java/com/baeldung/tink/TinkUnitTest.java b/libraries-security/src/test/java/com/baeldung/tink/TinkUnitTest.java
new file mode 100644
index 0000000000..b98c698016
--- /dev/null
+++ b/libraries-security/src/test/java/com/baeldung/tink/TinkUnitTest.java
@@ -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));
+ }
+}
+
+
diff --git a/libraries-server/README.md b/libraries-server/README.md
index 75c12fd61a..dc6bcd0716 100644
--- a/libraries-server/README.md
+++ b/libraries-server/README.md
@@ -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)
diff --git a/libraries/README.md b/libraries/README.md
index 57f22631f1..f6a39daef1 100644
--- a/libraries/README.md
+++ b/libraries/README.md
@@ -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)
diff --git a/logging-modules/README.md b/logging-modules/README.md
index 0f12d7eb22..17405847b1 100644
--- a/logging-modules/README.md
+++ b/logging-modules/README.md
@@ -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)
diff --git a/logging-modules/log4j2/README.md b/logging-modules/log4j2/README.md
index 2cf6f9768f..dd326bc7a1 100644
--- a/logging-modules/log4j2/README.md
+++ b/logging-modules/log4j2/README.md
@@ -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)
diff --git a/logging-modules/logback/README.md b/logging-modules/logback/README.md
index e69de29bb2..df55492b69 100644
--- a/logging-modules/logback/README.md
+++ b/logging-modules/logback/README.md
@@ -0,0 +1,3 @@
+### Relevant Articles:
+
+- [Get Log Output in JSON](https://www.baeldung.com/java-log-json-output)
diff --git a/maven-java-11/multimodule-maven-project/daomodule/pom.xml b/maven-java-11/multimodule-maven-project/daomodule/pom.xml
new file mode 100644
index 0000000000..de9be656d4
--- /dev/null
+++ b/maven-java-11/multimodule-maven-project/daomodule/pom.xml
@@ -0,0 +1,14 @@
+
+
+ 4.0.0
+
+ com.baeldung.multimodule-maven-project
+ multimodule-maven-project
+ 1.0
+
+ com.baeldung.daomodule
+ daomodule
+ jar
+ 1.0
+ daomodule
+
diff --git a/maven-java-11/multimodule-maven-project/daomodule/src/main/java/com/baeldung/dao/Dao.java b/maven-java-11/multimodule-maven-project/daomodule/src/main/java/com/baeldung/dao/Dao.java
new file mode 100644
index 0000000000..f86ae8abb3
--- /dev/null
+++ b/maven-java-11/multimodule-maven-project/daomodule/src/main/java/com/baeldung/dao/Dao.java
@@ -0,0 +1,12 @@
+package com.baeldung.dao;
+
+import java.util.List;
+import java.util.Optional;
+
+public interface Dao {
+
+ Optional findById(int id);
+
+ List findAll();
+
+}
diff --git a/maven-java-11/multimodule-maven-project/daomodule/src/main/java/module-info.java b/maven-java-11/multimodule-maven-project/daomodule/src/main/java/module-info.java
new file mode 100644
index 0000000000..072d7ad007
--- /dev/null
+++ b/maven-java-11/multimodule-maven-project/daomodule/src/main/java/module-info.java
@@ -0,0 +1,3 @@
+module com.baeldung.dao {
+ exports com.baeldung.dao;
+}
diff --git a/maven-java-11/multimodule-maven-project/entitiymodule/pom.xml b/maven-java-11/multimodule-maven-project/entitiymodule/pom.xml
new file mode 100644
index 0000000000..8e700e62b5
--- /dev/null
+++ b/maven-java-11/multimodule-maven-project/entitiymodule/pom.xml
@@ -0,0 +1,18 @@
+
+
+ 4.0.0
+
+ com.baeldung.multimodule-maven-project
+ multimodule-maven-project
+ 1.0
+
+ com.baeldung.entitymodule
+ entitymodule
+ jar
+ 1.0
+ entitymodule
+
+ 11
+ 11
+
+
diff --git a/maven-java-11/multimodule-maven-project/entitiymodule/src/main/java/com/baeldung/entity/User.java b/maven-java-11/multimodule-maven-project/entitiymodule/src/main/java/com/baeldung/entity/User.java
new file mode 100644
index 0000000000..22022a2e6d
--- /dev/null
+++ b/maven-java-11/multimodule-maven-project/entitiymodule/src/main/java/com/baeldung/entity/User.java
@@ -0,0 +1,19 @@
+package com.baeldung.entity;
+
+public class User {
+
+ private final String name;
+
+ public User(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public String toString() {
+ return "User{" + "name=" + name + '}';
+ }
+}
diff --git a/maven-java-11/multimodule-maven-project/entitiymodule/src/main/java/module-info.java b/maven-java-11/multimodule-maven-project/entitiymodule/src/main/java/module-info.java
new file mode 100644
index 0000000000..67a3097352
--- /dev/null
+++ b/maven-java-11/multimodule-maven-project/entitiymodule/src/main/java/module-info.java
@@ -0,0 +1,3 @@
+module com.baeldung.entity {
+ exports com.baeldung.entity;
+}
diff --git a/maven-java-11/multimodule-maven-project/mainppmodule/pom.xml b/maven-java-11/multimodule-maven-project/mainppmodule/pom.xml
new file mode 100644
index 0000000000..d2c94527f1
--- /dev/null
+++ b/maven-java-11/multimodule-maven-project/mainppmodule/pom.xml
@@ -0,0 +1,32 @@
+
+
+ 4.0.0
+
+ com.baeldung.multimodule-maven-project
+ multimodule-maven-project
+ 1.0
+
+ com.baeldung.mainappmodule
+ mainappmodule
+ 1.0
+ jar
+ mainappmodule
+
+
+
+ com.baeldung.entitymodule
+ entitymodule
+ 1.0
+
+
+ com.baeldung.daomodule
+ daomodule
+ 1.0
+
+
+ com.baeldung.userdaomodule
+ userdaomodule
+ 1.0
+
+
+
diff --git a/maven-java-11/multimodule-maven-project/mainppmodule/src/main/java/com/baeldung/mainapp/Application.java b/maven-java-11/multimodule-maven-project/mainppmodule/src/main/java/com/baeldung/mainapp/Application.java
new file mode 100644
index 0000000000..0c0df7461b
--- /dev/null
+++ b/maven-java-11/multimodule-maven-project/mainppmodule/src/main/java/com/baeldung/mainapp/Application.java
@@ -0,0 +1,19 @@
+package com.baeldung.mainapp;
+
+import com.baeldung.dao.Dao;
+import com.baeldung.entity.User;
+import com.baeldung.userdao.UserDao;
+import java.util.HashMap;
+import java.util.Map;
+
+public class Application {
+
+ public static void main(String[] args) {
+ Map users = new HashMap<>();
+ users.put(1, new User("Julie"));
+ users.put(2, new User("David"));
+ Dao userDao = new UserDao(users);
+ userDao.findAll().forEach(System.out::println);
+ }
+
+}
diff --git a/maven-java-11/multimodule-maven-project/mainppmodule/src/main/java/module-info.java b/maven-java-11/multimodule-maven-project/mainppmodule/src/main/java/module-info.java
new file mode 100644
index 0000000000..c688fcf7de
--- /dev/null
+++ b/maven-java-11/multimodule-maven-project/mainppmodule/src/main/java/module-info.java
@@ -0,0 +1,6 @@
+module com.baeldung.mainapp {
+ requires com.baeldung.entity;
+ requires com.baeldung.userdao;
+ requires com.baeldung.dao;
+ uses com.baeldung.dao.Dao;
+}
diff --git a/maven-java-11/multimodule-maven-project/pom.xml b/maven-java-11/multimodule-maven-project/pom.xml
new file mode 100644
index 0000000000..f22541738c
--- /dev/null
+++ b/maven-java-11/multimodule-maven-project/pom.xml
@@ -0,0 +1,58 @@
+
+
+ 4.0.0
+ com.baeldung.multimodule-maven-project
+ multimodule-maven-project
+ 1.0
+ pom
+ multimodule-maven-project
+
+ com.baeldung.maven-java-11
+ maven-java-11
+ 1.0
+
+
+
+
+
+ junit
+ junit
+ 4.12
+ test
+
+
+ org.assertj
+ assertj-core
+ 3.12.2
+ test
+
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.8.0
+
+
+ 11
+
+
+
+
+
+
+
+ entitymodule
+ daomodule
+ userdaomodule
+ mainappmodule
+
+
+
+ UTF-8
+
+
diff --git a/maven-java-11/multimodule-maven-project/userdaomodule/pom.xml b/maven-java-11/multimodule-maven-project/userdaomodule/pom.xml
new file mode 100644
index 0000000000..b4fe7f0398
--- /dev/null
+++ b/maven-java-11/multimodule-maven-project/userdaomodule/pom.xml
@@ -0,0 +1,31 @@
+
+
+ 4.0.0
+
+ com.baeldung.multimodule-maven-project
+ multimodule-maven-project
+ 1.0
+
+ com.baeldung.userdaomodule
+ userdaomodule
+ 1.0
+ jar
+ userdaomodule
+
+
+ com.baeldung.entitymodule
+ entitymodule
+ 1.0
+
+
+ com.baeldung.daomodule
+ daomodule
+ 1.0
+
+
+ junit
+ junit
+ test
+
+
+
diff --git a/maven-java-11/multimodule-maven-project/userdaomodule/src/main/java/com/baeldung/userdao/UserDao.java b/maven-java-11/multimodule-maven-project/userdaomodule/src/main/java/com/baeldung/userdao/UserDao.java
new file mode 100644
index 0000000000..1f1ea38a60
--- /dev/null
+++ b/maven-java-11/multimodule-maven-project/userdaomodule/src/main/java/com/baeldung/userdao/UserDao.java
@@ -0,0 +1,32 @@
+package com.baeldung.userdao;
+
+import com.baeldung.dao.Dao;
+import com.baeldung.entity.User;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+public class UserDao implements Dao {
+
+ private final Map users;
+
+ public UserDao() {
+ users = new HashMap<>();
+ }
+
+ public UserDao(Map users) {
+ this.users = users;
+ }
+
+ @Override
+ public List findAll() {
+ return new ArrayList<>(users.values());
+ }
+
+ @Override
+ public Optional findById(int id) {
+ return Optional.ofNullable(users.get(id));
+ }
+}
\ No newline at end of file
diff --git a/maven-java-11/multimodule-maven-project/userdaomodule/src/main/java/module-info.java b/maven-java-11/multimodule-maven-project/userdaomodule/src/main/java/module-info.java
new file mode 100644
index 0000000000..f1cb217e23
--- /dev/null
+++ b/maven-java-11/multimodule-maven-project/userdaomodule/src/main/java/module-info.java
@@ -0,0 +1,6 @@
+module com.baeldung.userdao {
+ requires com.baeldung.entity;
+ requires com.baeldung.dao;
+ provides com.baeldung.dao.Dao with com.baeldung.userdao.UserDao;
+ exports com.baeldung.userdao;
+}
diff --git a/maven-java-11/multimodule-maven-project/userdaomodule/src/test/java/com/baeldung/userdao/test/UserDaoUnitTest.java b/maven-java-11/multimodule-maven-project/userdaomodule/src/test/java/com/baeldung/userdao/test/UserDaoUnitTest.java
new file mode 100644
index 0000000000..191d17ff32
--- /dev/null
+++ b/maven-java-11/multimodule-maven-project/userdaomodule/src/test/java/com/baeldung/userdao/test/UserDaoUnitTest.java
@@ -0,0 +1,36 @@
+package com.baeldung.userdao.test;
+
+import com.baeldung.dao.Dao;
+import com.baeldung.entity.User;
+import com.baeldung.userdao.UserDao;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import static org.junit.Assert.*;
+import static org.hamcrest.CoreMatchers.*;
+import org.junit.Before;
+import org.junit.Test;
+
+public class UserDaoUnitTest {
+
+ private Dao userDao;
+
+ @Before
+ public void setUpUserDaoInstance() {
+ Map users = new HashMap<>();
+ users.put(1, new User("Julie"));
+ users.put(2, new User("David"));
+ userDao = new UserDao(users);
+ }
+
+ @Test
+ public void givenUserDaoIntance_whenCalledFindById_thenCorrect() {
+ assertThat(userDao.findById(1), isA(Optional.class));
+ }
+
+ @Test
+ public void givenUserDaoIntance_whenCalledFindAll_thenCorrect() {
+ assertThat(userDao.findAll(), isA(List.class));
+ }
+}
diff --git a/maven-java-11/pom.xml b/maven-java-11/pom.xml
new file mode 100644
index 0000000000..4342fa740f
--- /dev/null
+++ b/maven-java-11/pom.xml
@@ -0,0 +1,22 @@
+
+
+ 4.0.0
+ com.baeldung.maven-java-11
+ maven-java-11
+ 1.0
+ pom
+ maven-java-11
+
+ parent-modules
+ com.baeldung
+ 1.0.0-SNAPSHOT
+
+
+ multimodule-maven-project
+
+
+ UTF-8
+ 11
+ 11
+
+
diff --git a/parent-kotlin/pom.xml b/parent-kotlin/pom.xml
index 7a3a8b10ca..86ab45ecb1 100644
--- a/parent-kotlin/pom.xml
+++ b/parent-kotlin/pom.xml
@@ -202,10 +202,10 @@
- 1.3.10
+ 1.3.30
1.0.0
0.9.5
- 3.11.0
- 1.2.0
+ 3.12.0
+ 1.3.2
diff --git a/patterns/README.md b/patterns/README.md
index b3ece5e52b..f627251aa4 100644
--- a/patterns/README.md
+++ b/patterns/README.md
@@ -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)
diff --git a/patterns/design-patterns-2/README.md b/patterns/design-patterns-2/README.md
new file mode 100644
index 0000000000..c2a75d4680
--- /dev/null
+++ b/patterns/design-patterns-2/README.md
@@ -0,0 +1,3 @@
+### Relevant Articles
+
+- [The Mediator Pattern in Java](https://www.baeldung.com/java-mediator-pattern)
diff --git a/patterns/design-patterns/README.md b/patterns/design-patterns/README.md
index c43ea48505..605fdc0d6e 100644
--- a/patterns/design-patterns/README.md
+++ b/patterns/design-patterns/README.md
@@ -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)
diff --git a/patterns/principles/solid/README.md b/patterns/principles/solid/README.md
index e2d72ecd28..ddd2f78b7e 100644
--- a/patterns/principles/solid/README.md
+++ b/patterns/principles/solid/README.md
@@ -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)
diff --git a/persistence-modules/README.md b/persistence-modules/README.md
index 87dc9522fd..2fbaf25f2f 100644
--- a/persistence-modules/README.md
+++ b/persistence-modules/README.md
@@ -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)
diff --git a/persistence-modules/core-java-persistence/pom.xml b/persistence-modules/core-java-persistence/pom.xml
index a777eeb73f..2ad2083fec 100644
--- a/persistence-modules/core-java-persistence/pom.xml
+++ b/persistence-modules/core-java-persistence/pom.xml
@@ -6,15 +6,21 @@
0.1.0-SNAPSHOT
core-java-persistence
jar
-
+
com.baeldung
parent-java
0.0.1-SNAPSHOT
../../parent-java
-
+
+
+ org.postgresql
+ postgresql
+ ${postgresql.version}
+ test
+
org.assertj
assertj-core
@@ -52,7 +58,7 @@
${springframework.boot.spring-boot-starter.version}
-
+
core-java-persistence
@@ -62,8 +68,10 @@
-
+
+ 42.2.5.jre7
+ 8.0.15
3.10.0
1.4.197
2.4.0
@@ -72,5 +80,5 @@
1.5.8.RELEASE
4.3.4.RELEASE
-
+
\ No newline at end of file
diff --git a/persistence-modules/core-java-persistence/src/main/java/com/baeldung/jdbc/joins/ArticleWithAuthor.java b/persistence-modules/core-java-persistence/src/main/java/com/baeldung/jdbc/joins/ArticleWithAuthor.java
new file mode 100644
index 0000000000..5ce196ee47
--- /dev/null
+++ b/persistence-modules/core-java-persistence/src/main/java/com/baeldung/jdbc/joins/ArticleWithAuthor.java
@@ -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;
+ }
+
+}
diff --git a/persistence-modules/core-java-persistence/src/main/java/com/baeldung/jdbc/joins/ArticleWithAuthorDAO.java b/persistence-modules/core-java-persistence/src/main/java/com/baeldung/jdbc/joins/ArticleWithAuthorDAO.java
new file mode 100644
index 0000000000..55f03d99ec
--- /dev/null
+++ b/persistence-modules/core-java-persistence/src/main/java/com/baeldung/jdbc/joins/ArticleWithAuthorDAO.java
@@ -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 articleInnerJoinAuthor() {
+ String query = String.format(QUERY_TEMPLATE, "INNER JOIN");
+ return executeQuery(query);
+ }
+
+ List articleLeftJoinAuthor() {
+ String query = String.format(QUERY_TEMPLATE, "LEFT JOIN");
+ return executeQuery(query);
+ }
+
+ List articleRightJoinAuthor() {
+ String query = String.format(QUERY_TEMPLATE, "RIGHT JOIN");
+ return executeQuery(query);
+ }
+
+ List articleFullJoinAuthor() {
+ String query = String.format(QUERY_TEMPLATE, "FULL JOIN");
+ return executeQuery(query);
+ }
+
+ private List 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 mapToList(ResultSet resultSet) throws SQLException {
+ List 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;
+ }
+}
diff --git a/persistence-modules/core-java-persistence/src/test/java/com/baeldung/jdbc/joins/ArticleWithAuthorDAOIntegrationTest.java b/persistence-modules/core-java-persistence/src/test/java/com/baeldung/jdbc/joins/ArticleWithAuthorDAOIntegrationTest.java
new file mode 100644
index 0000000000..5c20b6bf1e
--- /dev/null
+++ b/persistence-modules/core-java-persistence/src/test/java/com/baeldung/jdbc/joins/ArticleWithAuthorDAOIntegrationTest.java
@@ -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 articleWithAuthorList = articleWithAuthorDAO.articleInnerJoinAuthor();
+
+ assertThat(articleWithAuthorList).hasSize(4);
+ assertThat(articleWithAuthorList).noneMatch(row -> row.getAuthorFirstName() == null || row.getTitle() == null);
+ }
+
+ @Test
+ public void whenQueryWithLeftJoin_thenShouldReturnProperRows() {
+ List articleWithAuthorList = articleWithAuthorDAO.articleLeftJoinAuthor();
+
+ assertThat(articleWithAuthorList).hasSize(5);
+ assertThat(articleWithAuthorList).anyMatch(row -> row.getAuthorFirstName() == null);
+ }
+
+ @Test
+ public void whenQueryWithRightJoin_thenShouldReturnProperRows() {
+ List articleWithAuthorList = articleWithAuthorDAO.articleRightJoinAuthor();
+
+ assertThat(articleWithAuthorList).hasSize(5);
+ assertThat(articleWithAuthorList).anyMatch(row -> row.getTitle() == null);
+ }
+
+ @Test
+ public void whenQueryWithFullJoin_thenShouldReturnProperRows() {
+ List 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);
+ }
+}
diff --git a/persistence-modules/hibernate-mapping/pom.xml b/persistence-modules/hibernate-mapping/pom.xml
new file mode 100644
index 0000000000..11caf67bf1
--- /dev/null
+++ b/persistence-modules/hibernate-mapping/pom.xml
@@ -0,0 +1,52 @@
+
+
+
+
+ com.baeldung
+ parent-modules
+ 1.0.0-SNAPSHOT
+ ../../
+
+
+ hibernate-mapping
+ 1.0.0-SNAPSHOT
+ 4.0.0
+
+
+
+ org.hibernate
+ hibernate-core
+ ${hibernate.version}
+
+
+ org.assertj
+ assertj-core
+ ${assertj-core.version}
+ test
+
+
+ com.h2database
+ h2
+ ${h2database.version}
+
+
+
+
+ hibernate-mapping
+
+
+ src/test/resources
+ true
+
+
+
+
+
+ 5.3.7.Final
+ 1.4.196
+ 3.8.0
+
+
+
\ No newline at end of file
diff --git a/persistence-modules/hibernate-mapping/src/main/java/com/baeldung/hibernate/HibernateUtil.java b/persistence-modules/hibernate-mapping/src/main/java/com/baeldung/hibernate/HibernateUtil.java
new file mode 100644
index 0000000000..7411edd225
--- /dev/null
+++ b/persistence-modules/hibernate-mapping/src/main/java/com/baeldung/hibernate/HibernateUtil.java
@@ -0,0 +1,64 @@
+package com.baeldung.hibernate;
+
+import org.hibernate.SessionFactory;
+import org.hibernate.boot.Metadata;
+import org.hibernate.boot.MetadataSources;
+import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
+import org.hibernate.service.ServiceRegistry;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.net.URL;
+import java.util.Properties;
+
+public class HibernateUtil {
+ private static SessionFactory sessionFactory;
+
+ private HibernateUtil() {
+ }
+
+ public static SessionFactory getSessionFactory(Strategy strategy) {
+ if (sessionFactory == null) {
+ sessionFactory = buildSessionFactory(strategy);
+ }
+ return sessionFactory;
+ }
+
+ private static SessionFactory buildSessionFactory(Strategy strategy) {
+ try {
+ ServiceRegistry serviceRegistry = configureServiceRegistry();
+
+ MetadataSources metadataSources = new MetadataSources(serviceRegistry);
+
+ for (Class> entityClass : strategy.getEntityClasses()) {
+ metadataSources.addAnnotatedClass(entityClass);
+ }
+
+ Metadata metadata = metadataSources.getMetadataBuilder()
+ .build();
+
+ return metadata.getSessionFactoryBuilder()
+ .build();
+ } catch (IOException ex) {
+ throw new ExceptionInInitializerError(ex);
+ }
+ }
+
+
+ private static ServiceRegistry configureServiceRegistry() throws IOException {
+ Properties properties = getProperties();
+ return new StandardServiceRegistryBuilder().applySettings(properties)
+ .build();
+ }
+
+ private static Properties getProperties() throws IOException {
+ Properties properties = new Properties();
+ URL propertiesURL = Thread.currentThread()
+ .getContextClassLoader()
+ .getResource("hibernate.properties");
+ try (FileInputStream inputStream = new FileInputStream(propertiesURL.getFile())) {
+ properties.load(inputStream);
+ }
+ return properties;
+ }
+}
diff --git a/persistence-modules/hibernate-mapping/src/main/java/com/baeldung/hibernate/Strategy.java b/persistence-modules/hibernate-mapping/src/main/java/com/baeldung/hibernate/Strategy.java
new file mode 100644
index 0000000000..75f10ed583
--- /dev/null
+++ b/persistence-modules/hibernate-mapping/src/main/java/com/baeldung/hibernate/Strategy.java
@@ -0,0 +1,31 @@
+package com.baeldung.hibernate;
+
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+public enum Strategy {
+ //See that the classes belongs to different packages
+ MAP_KEY_COLUMN_BASED(Collections.singletonList(com.baeldung.hibernate.persistmaps.mapkeycolumn.Order.class)),
+ MAP_KEY_BASED(Arrays.asList(com.baeldung.hibernate.persistmaps.mapkey.Item.class,
+ com.baeldung.hibernate.persistmaps.mapkey.Order.class)),
+ MAP_KEY_JOIN_COLUMN_BASED(Arrays.asList(com.baeldung.hibernate.persistmaps.mapkeyjoincolumn.Seller.class,
+ com.baeldung.hibernate.persistmaps.mapkeyjoincolumn.Item.class,
+ com.baeldung.hibernate.persistmaps.mapkeyjoincolumn.Order.class)),
+ MAP_KEY_ENUMERATED_BASED(Arrays.asList(com.baeldung.hibernate.persistmaps.mapkeyenumerated.Order.class,
+ com.baeldung.hibernate.persistmaps.mapkey.Item.class)),
+ MAP_KEY_TEMPORAL_BASED(Arrays.asList(com.baeldung.hibernate.persistmaps.mapkeytemporal.Order.class,
+ com.baeldung.hibernate.persistmaps.mapkey.Item.class));
+
+
+ private List> entityClasses;
+
+ Strategy(List> entityClasses) {
+ this.entityClasses = entityClasses;
+ }
+
+ public List> getEntityClasses() {
+ return entityClasses;
+ }
+}
diff --git a/persistence-modules/hibernate-mapping/src/main/java/com/baeldung/hibernate/persistmaps/ItemType.java b/persistence-modules/hibernate-mapping/src/main/java/com/baeldung/hibernate/persistmaps/ItemType.java
new file mode 100644
index 0000000000..b7f3cef9a2
--- /dev/null
+++ b/persistence-modules/hibernate-mapping/src/main/java/com/baeldung/hibernate/persistmaps/ItemType.java
@@ -0,0 +1,6 @@
+package com.baeldung.hibernate.persistmaps;
+
+public enum ItemType {
+ JEANS,
+ TSHIRTS
+}
diff --git a/persistence-modules/hibernate-mapping/src/main/java/com/baeldung/hibernate/persistmaps/mapkey/Item.java b/persistence-modules/hibernate-mapping/src/main/java/com/baeldung/hibernate/persistmaps/mapkey/Item.java
new file mode 100644
index 0000000000..385ffe93ea
--- /dev/null
+++ b/persistence-modules/hibernate-mapping/src/main/java/com/baeldung/hibernate/persistmaps/mapkey/Item.java
@@ -0,0 +1,95 @@
+package com.baeldung.hibernate.persistmaps.mapkey;
+
+import com.baeldung.hibernate.persistmaps.ItemType;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.EnumType;
+import javax.persistence.Enumerated;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.Table;
+import javax.persistence.Temporal;
+import javax.persistence.TemporalType;
+import java.util.Date;
+import java.util.Objects;
+
+@Entity
+@Table(name = "item")
+public class Item {
+ @Id
+ @GeneratedValue
+ @Column(name = "id")
+ private int id;
+
+ @Column(name = "name")
+ private String itemName;
+
+ @Column(name = "price")
+ private double itemPrice;
+
+ @Enumerated(EnumType.STRING)
+ @Column(name = "item_type")
+ private ItemType itemType;
+
+ @Temporal(TemporalType.TIMESTAMP)
+ @Column(name = "created_on")
+ private Date createdOn;
+
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ public String getItemName() {
+ return itemName;
+ }
+
+ public void setItemName(String itemName) {
+ this.itemName = itemName;
+ }
+
+ public double getItemPrice() {
+ return itemPrice;
+ }
+
+ public void setItemPrice(double itemPrice) {
+ this.itemPrice = itemPrice;
+ }
+
+ public ItemType getItemType() {
+ return itemType;
+ }
+
+ public void setItemType(ItemType itemType) {
+ this.itemType = itemType;
+ }
+
+ public Date getCreatedOn() {
+ return createdOn;
+ }
+
+ public void setCreatedOn(Date createdOn) {
+ this.createdOn = createdOn;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ Item item = (Item) o;
+ return id == item.id &&
+ Double.compare(item.itemPrice, itemPrice) == 0 &&
+ Objects.equals(itemName, item.itemName) &&
+ itemType == item.itemType &&
+ Objects.equals(createdOn, item.createdOn);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(id, itemName, itemPrice, itemType, createdOn);
+ }
+}
diff --git a/persistence-modules/hibernate-mapping/src/main/java/com/baeldung/hibernate/persistmaps/mapkey/Order.java b/persistence-modules/hibernate-mapping/src/main/java/com/baeldung/hibernate/persistmaps/mapkey/Order.java
new file mode 100644
index 0000000000..8409cacd6b
--- /dev/null
+++ b/persistence-modules/hibernate-mapping/src/main/java/com/baeldung/hibernate/persistmaps/mapkey/Order.java
@@ -0,0 +1,44 @@
+package com.baeldung.hibernate.persistmaps.mapkey;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.JoinTable;
+import javax.persistence.MapKey;
+import javax.persistence.OneToMany;
+import javax.persistence.Table;
+import java.util.Map;
+
+@Entity
+@Table(name = "orders")
+public class Order {
+ @Id
+ @GeneratedValue
+ @Column(name = "id")
+ private int id;
+
+ @OneToMany(cascade = CascadeType.ALL)
+ @JoinTable(name = "order_item_mapping", joinColumns = {@JoinColumn(name = "order_id", referencedColumnName = "id")},
+ inverseJoinColumns = {@JoinColumn(name = "item_id", referencedColumnName = "id")})
+ @MapKey(name = "itemName")
+ private Map itemMap;
+
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ public Map getItemMap() {
+ return itemMap;
+ }
+
+ public void setItemMap(Map itemMap) {
+ this.itemMap = itemMap;
+ }
+}
\ No newline at end of file
diff --git a/persistence-modules/hibernate-mapping/src/main/java/com/baeldung/hibernate/persistmaps/mapkeycolumn/Order.java b/persistence-modules/hibernate-mapping/src/main/java/com/baeldung/hibernate/persistmaps/mapkeycolumn/Order.java
new file mode 100644
index 0000000000..fa092060da
--- /dev/null
+++ b/persistence-modules/hibernate-mapping/src/main/java/com/baeldung/hibernate/persistmaps/mapkeycolumn/Order.java
@@ -0,0 +1,43 @@
+package com.baeldung.hibernate.persistmaps.mapkeycolumn;
+
+import javax.persistence.CollectionTable;
+import javax.persistence.Column;
+import javax.persistence.ElementCollection;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.MapKeyColumn;
+import javax.persistence.Table;
+import java.util.Map;
+
+@Entity
+@Table(name = "orders")
+public class Order {
+ @Id
+ @GeneratedValue
+ @Column(name = "id")
+ private int id;
+
+ @ElementCollection
+ @CollectionTable(name = "order_item_mapping", joinColumns = {@JoinColumn(name = "order_id", referencedColumnName = "id")})
+ @MapKeyColumn(name = "item_name")
+ @Column(name = "price")
+ private Map itemPriceMap;
+
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ public Map getItemPriceMap() {
+ return itemPriceMap;
+ }
+
+ public void setItemPriceMap(Map itemPriceMap) {
+ this.itemPriceMap = itemPriceMap;
+ }
+}
\ No newline at end of file
diff --git a/persistence-modules/hibernate-mapping/src/main/java/com/baeldung/hibernate/persistmaps/mapkeyenumerated/Order.java b/persistence-modules/hibernate-mapping/src/main/java/com/baeldung/hibernate/persistmaps/mapkeyenumerated/Order.java
new file mode 100644
index 0000000000..e1f62599b8
--- /dev/null
+++ b/persistence-modules/hibernate-mapping/src/main/java/com/baeldung/hibernate/persistmaps/mapkeyenumerated/Order.java
@@ -0,0 +1,48 @@
+package com.baeldung.hibernate.persistmaps.mapkeyenumerated;
+
+import com.baeldung.hibernate.persistmaps.ItemType;
+import com.baeldung.hibernate.persistmaps.mapkey.Item;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.EnumType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.JoinTable;
+import javax.persistence.MapKeyEnumerated;
+import javax.persistence.OneToMany;
+import javax.persistence.Table;
+import java.util.Map;
+
+@Entity
+@Table(name = "orders")
+public class Order {
+ @Id
+ @GeneratedValue
+ @Column(name = "id")
+ private int id;
+
+ @OneToMany(cascade = CascadeType.ALL)
+ @JoinTable(name = "order_item_mapping", joinColumns = {@JoinColumn(name = "order_id", referencedColumnName = "id")},
+ inverseJoinColumns = {@JoinColumn(name = "item_id", referencedColumnName = "id")})
+ @MapKeyEnumerated(EnumType.STRING)
+ private Map itemMap;
+
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ public Map getItemMap() {
+ return itemMap;
+ }
+
+ public void setItemMap(Map itemMap) {
+ this.itemMap = itemMap;
+ }
+}
diff --git a/persistence-modules/hibernate-mapping/src/main/java/com/baeldung/hibernate/persistmaps/mapkeyjoincolumn/Item.java b/persistence-modules/hibernate-mapping/src/main/java/com/baeldung/hibernate/persistmaps/mapkeyjoincolumn/Item.java
new file mode 100644
index 0000000000..97bbd5b539
--- /dev/null
+++ b/persistence-modules/hibernate-mapping/src/main/java/com/baeldung/hibernate/persistmaps/mapkeyjoincolumn/Item.java
@@ -0,0 +1,112 @@
+package com.baeldung.hibernate.persistmaps.mapkeyjoincolumn;
+
+import com.baeldung.hibernate.persistmaps.ItemType;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.EnumType;
+import javax.persistence.Enumerated;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+import javax.persistence.Temporal;
+import javax.persistence.TemporalType;
+import java.util.Date;
+import java.util.Objects;
+
+@Entity
+@Table(name = "item")
+public class Item {
+ @Id
+ @GeneratedValue
+ @Column(name = "id")
+ private int id;
+
+ @Column(name = "name")
+ private String itemName;
+
+ @Column(name = "price")
+ private double itemPrice;
+
+ @Column(name = "item_type")
+ @Enumerated(EnumType.STRING)
+ private ItemType itemType;
+
+ @Temporal(TemporalType.TIMESTAMP)
+ @Column(name = "created_on")
+ private Date createdOn;
+
+ @ManyToOne(cascade = CascadeType.ALL)
+ @JoinColumn(name = "seller_id")
+ private Seller seller;
+
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ public String getItemName() {
+ return itemName;
+ }
+
+ public void setItemName(String itemName) {
+ this.itemName = itemName;
+ }
+
+ public double getItemPrice() {
+ return itemPrice;
+ }
+
+ public void setItemPrice(double itemPrice) {
+ this.itemPrice = itemPrice;
+ }
+
+ public ItemType getItemType() {
+ return itemType;
+ }
+
+ public void setItemType(ItemType itemType) {
+ this.itemType = itemType;
+ }
+
+ public Date getCreatedOn() {
+ return createdOn;
+ }
+
+ public void setCreatedOn(Date createdOn) {
+ this.createdOn = createdOn;
+ }
+
+ public Seller getSeller() {
+ return seller;
+ }
+
+ public void setSeller(Seller seller) {
+ this.seller = seller;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ Item item = (Item) o;
+ return id == item.id &&
+ Double.compare(item.itemPrice, itemPrice) == 0 &&
+ Objects.equals(itemName, item.itemName) &&
+ itemType == item.itemType &&
+ Objects.equals(createdOn, item.createdOn) &&
+ Objects.equals(seller, item.seller);
+ }
+
+ @Override
+ public int hashCode() {
+
+ return Objects.hash(id, itemName, itemPrice, itemType, createdOn, seller);
+ }
+}
diff --git a/persistence-modules/hibernate-mapping/src/main/java/com/baeldung/hibernate/persistmaps/mapkeyjoincolumn/Order.java b/persistence-modules/hibernate-mapping/src/main/java/com/baeldung/hibernate/persistmaps/mapkeyjoincolumn/Order.java
new file mode 100644
index 0000000000..d680d84501
--- /dev/null
+++ b/persistence-modules/hibernate-mapping/src/main/java/com/baeldung/hibernate/persistmaps/mapkeyjoincolumn/Order.java
@@ -0,0 +1,44 @@
+package com.baeldung.hibernate.persistmaps.mapkeyjoincolumn;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.JoinTable;
+import javax.persistence.MapKeyJoinColumn;
+import javax.persistence.OneToMany;
+import javax.persistence.Table;
+import java.util.Map;
+
+@Entity
+@Table(name = "orders")
+public class Order {
+ @Id
+ @GeneratedValue
+ @Column(name = "id")
+ private int id;
+
+ @OneToMany(cascade = CascadeType.ALL)
+ @JoinTable(name = "order_item_mapping", joinColumns = {@JoinColumn(name = "order_id", referencedColumnName = "id")},
+ inverseJoinColumns = {@JoinColumn(name = "item_id", referencedColumnName = "id")})
+ @MapKeyJoinColumn(name = "seller_id")
+ private Map sellerItemMap;
+
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ public Map getSellerItemMap() {
+ return sellerItemMap;
+ }
+
+ public void setSellerItemMap(Map sellerItemMap) {
+ this.sellerItemMap = sellerItemMap;
+ }
+}
\ No newline at end of file
diff --git a/persistence-modules/hibernate-mapping/src/main/java/com/baeldung/hibernate/persistmaps/mapkeyjoincolumn/Seller.java b/persistence-modules/hibernate-mapping/src/main/java/com/baeldung/hibernate/persistmaps/mapkeyjoincolumn/Seller.java
new file mode 100644
index 0000000000..15b08e9fe6
--- /dev/null
+++ b/persistence-modules/hibernate-mapping/src/main/java/com/baeldung/hibernate/persistmaps/mapkeyjoincolumn/Seller.java
@@ -0,0 +1,51 @@
+package com.baeldung.hibernate.persistmaps.mapkeyjoincolumn;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.Table;
+import java.util.Objects;
+
+@Entity
+@Table(name = "seller")
+public class Seller {
+
+ @Id
+ @GeneratedValue
+ @Column(name = "id")
+ private int id;
+
+ @Column(name = "name")
+ private String sellerName;
+
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ public String getSellerName() {
+ return sellerName;
+ }
+
+ public void setSellerName(String sellerName) {
+ this.sellerName = sellerName;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ Seller seller = (Seller) o;
+ return Objects.equals(sellerName, seller.sellerName);
+ }
+
+ @Override
+ public int hashCode() {
+
+ return Objects.hash(sellerName);
+ }
+}
diff --git a/persistence-modules/hibernate-mapping/src/main/java/com/baeldung/hibernate/persistmaps/mapkeytemporal/Order.java b/persistence-modules/hibernate-mapping/src/main/java/com/baeldung/hibernate/persistmaps/mapkeytemporal/Order.java
new file mode 100644
index 0000000000..be602c1e9f
--- /dev/null
+++ b/persistence-modules/hibernate-mapping/src/main/java/com/baeldung/hibernate/persistmaps/mapkeytemporal/Order.java
@@ -0,0 +1,48 @@
+package com.baeldung.hibernate.persistmaps.mapkeytemporal;
+
+import com.baeldung.hibernate.persistmaps.mapkey.Item;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.JoinTable;
+import javax.persistence.MapKeyTemporal;
+import javax.persistence.OneToMany;
+import javax.persistence.Table;
+import javax.persistence.TemporalType;
+import java.util.Date;
+import java.util.Map;
+
+@Entity
+@Table(name = "orders")
+public class Order {
+ @Id
+ @GeneratedValue
+ @Column(name = "id")
+ private int id;
+
+ @OneToMany(cascade = CascadeType.ALL)
+ @JoinTable(name = "order_item_mapping", joinColumns = {@JoinColumn(name = "order_id", referencedColumnName = "id")},
+ inverseJoinColumns = {@JoinColumn(name = "item_id", referencedColumnName = "id")})
+ @MapKeyTemporal(TemporalType.TIMESTAMP)
+ private Map itemMap;
+
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ public Map getItemMap() {
+ return itemMap;
+ }
+
+ public void setItemMap(Map itemMap) {
+ this.itemMap = itemMap;
+ }
+}
diff --git a/persistence-modules/hibernate-mapping/src/main/resources/logback.xml b/persistence-modules/hibernate-mapping/src/main/resources/logback.xml
new file mode 100644
index 0000000000..26beb6d5b4
--- /dev/null
+++ b/persistence-modules/hibernate-mapping/src/main/resources/logback.xml
@@ -0,0 +1,13 @@
+
+
+
+
+ %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/persistence-modules/hibernate-mapping/src/test/java/com/baeldung/hibernate/persistmaps/MapKeyColumnIntegrationTest.java b/persistence-modules/hibernate-mapping/src/test/java/com/baeldung/hibernate/persistmaps/MapKeyColumnIntegrationTest.java
new file mode 100644
index 0000000000..acd77ee382
--- /dev/null
+++ b/persistence-modules/hibernate-mapping/src/test/java/com/baeldung/hibernate/persistmaps/MapKeyColumnIntegrationTest.java
@@ -0,0 +1,79 @@
+package com.baeldung.hibernate.persistmaps;
+
+import com.baeldung.hibernate.HibernateUtil;
+import com.baeldung.hibernate.Strategy;
+import com.baeldung.hibernate.persistmaps.mapkeycolumn.Order;
+import org.hibernate.Session;
+import org.hibernate.SessionFactory;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+public class MapKeyColumnIntegrationTest {
+ private static SessionFactory sessionFactory;
+
+ private Session session;
+
+ @BeforeClass
+ public static void beforeTests() {
+ sessionFactory = HibernateUtil.getSessionFactory(Strategy.MAP_KEY_COLUMN_BASED);
+ }
+
+ @Before
+ public void setUp() {
+ session = sessionFactory.openSession();
+ session.beginTransaction();
+ }
+
+ @Test
+ public void givenData_whenInsertUsingMapKeyColumn_thenPersistMap() {
+ Map itemPriceMap = new HashMap<>();
+ itemPriceMap.put("Wrangler Jeans", 150.0);
+ itemPriceMap.put("Lee Jeans", 180.0);
+
+
+ Order order = new Order();
+ order.setItemPriceMap(itemPriceMap);
+
+ session.persist(order);
+ session.getTransaction().commit();
+
+ assertInsertedData();
+ }
+
+ private void assertInsertedData() {
+ @SuppressWarnings("unchecked")
+ List orderList = session.createQuery("FROM Order").list();
+
+ assertNotNull(orderList);
+ assertEquals(1, orderList.size());
+
+ Order order = orderList.get(0);
+
+ Map itemPriceMap = order.getItemPriceMap();
+ assertNotNull(itemPriceMap);
+ assertEquals(itemPriceMap.size(), 2);
+ assertEquals((Double) 150.0, itemPriceMap.get("Wrangler Jeans"));
+ assertEquals((Double) 180.0, itemPriceMap.get("Lee Jeans"));
+
+ }
+
+ @After
+ public void tearDown() {
+ session.close();
+ }
+
+ @AfterClass
+ public static void afterTests() {
+ sessionFactory.close();
+ }
+}
diff --git a/persistence-modules/hibernate-mapping/src/test/java/com/baeldung/hibernate/persistmaps/MapKeyEnumeratedIntegrationTest.java b/persistence-modules/hibernate-mapping/src/test/java/com/baeldung/hibernate/persistmaps/MapKeyEnumeratedIntegrationTest.java
new file mode 100644
index 0000000000..221aa7b1d7
--- /dev/null
+++ b/persistence-modules/hibernate-mapping/src/test/java/com/baeldung/hibernate/persistmaps/MapKeyEnumeratedIntegrationTest.java
@@ -0,0 +1,95 @@
+package com.baeldung.hibernate.persistmaps;
+
+import com.baeldung.hibernate.HibernateUtil;
+import com.baeldung.hibernate.Strategy;
+import com.baeldung.hibernate.persistmaps.mapkey.Item;
+import com.baeldung.hibernate.persistmaps.mapkeyenumerated.Order;
+import org.hibernate.Session;
+import org.hibernate.SessionFactory;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import java.time.Instant;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+public class MapKeyEnumeratedIntegrationTest {
+ private static SessionFactory sessionFactory;
+
+ private Session session;
+
+ @BeforeClass
+ public static void beforeTests() {
+ sessionFactory = HibernateUtil.getSessionFactory(Strategy.MAP_KEY_ENUMERATED_BASED);
+ }
+
+ @Before
+ public void setUp() {
+ session = sessionFactory.openSession();
+ session.beginTransaction();
+ }
+
+ @Test
+ public void givenData_whenInsertUsingMapKeyEnumerated_thenPersistMap() {
+ Item item1 = new Item();
+ item1.setItemName("Wrangler Jeans");
+ item1.setItemPrice(150.0);
+ item1.setItemType(ItemType.JEANS);
+ item1.setCreatedOn(Date.from(Instant.ofEpochSecond(1554926573)));
+
+
+ Item item2 = new Item();
+ item2.setItemName("Armani Tshirts");
+ item2.setItemPrice(180.0);
+ item2.setItemType(ItemType.TSHIRTS);
+ item2.setCreatedOn(Date.from(Instant.ofEpochSecond(1554890573)));
+
+ Map itemMap = new HashMap<>();
+ itemMap.put(item1.getItemType(), item1);
+ itemMap.put(item2.getItemType(), item2);
+
+ Order order = new Order();
+ order.setItemMap(itemMap);
+
+ session.persist(order);
+ session.getTransaction().commit();
+
+ assertInsertedData(item1, item2);
+ }
+
+ private void assertInsertedData(Item expectedItem1, Item expectedItem2) {
+ @SuppressWarnings("unchecked")
+ List orderList = session.createQuery("FROM Order").list();
+
+ assertNotNull(orderList);
+ assertEquals(1, orderList.size());
+
+ Order order = orderList.get(0);
+
+ Map itemMap = order.getItemMap();
+ assertNotNull(itemMap);
+ assertEquals(2, itemMap.size());
+ assertEquals(expectedItem1, itemMap.get(ItemType.JEANS));
+ assertEquals(expectedItem2, itemMap.get(ItemType.TSHIRTS));
+
+ }
+
+ @After
+ public void tearDown() {
+ session.close();
+ }
+
+ @AfterClass
+ public static void afterTests() {
+ sessionFactory.close();
+ }
+}
+
diff --git a/persistence-modules/hibernate-mapping/src/test/java/com/baeldung/hibernate/persistmaps/MapKeyIntegrationTest.java b/persistence-modules/hibernate-mapping/src/test/java/com/baeldung/hibernate/persistmaps/MapKeyIntegrationTest.java
new file mode 100644
index 0000000000..b500deb78e
--- /dev/null
+++ b/persistence-modules/hibernate-mapping/src/test/java/com/baeldung/hibernate/persistmaps/MapKeyIntegrationTest.java
@@ -0,0 +1,95 @@
+package com.baeldung.hibernate.persistmaps;
+
+import com.baeldung.hibernate.HibernateUtil;
+import com.baeldung.hibernate.Strategy;
+import com.baeldung.hibernate.persistmaps.mapkey.Item;
+import com.baeldung.hibernate.persistmaps.mapkey.Order;
+import org.hibernate.Session;
+import org.hibernate.SessionFactory;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import java.time.Instant;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+public class MapKeyIntegrationTest {
+ private static SessionFactory sessionFactory;
+
+ private Session session;
+
+ @BeforeClass
+ public static void beforeTests() {
+ sessionFactory = HibernateUtil.getSessionFactory(Strategy.MAP_KEY_BASED);
+ }
+
+ @Before
+ public void setUp() {
+ session = sessionFactory.openSession();
+ session.beginTransaction();
+ }
+
+ @Test
+ public void givenData_whenInsertUsingMapKey_thenPersistMap() {
+ Item item1 = new Item();
+ item1.setItemName("Wrangler Jeans");
+ item1.setItemPrice(150.0);
+ item1.setItemType(ItemType.JEANS);
+ item1.setCreatedOn(Date.from(Instant.ofEpochSecond(1554926573)));
+
+
+ Item item2 = new Item();
+ item2.setItemName("Armani Tshirts");
+ item2.setItemPrice(180.0);
+ item2.setItemType(ItemType.TSHIRTS);
+ item2.setCreatedOn(Date.from(Instant.ofEpochSecond(1554890573)));
+
+ Map itemMap = new HashMap<>();
+ itemMap.put(item1.getItemName(), item1);
+ itemMap.put(item2.getItemName(), item2);
+
+ Order order = new Order();
+ order.setItemMap(itemMap);
+
+ session.persist(order);
+ session.getTransaction().commit();
+
+ assertInsertedData(item1, item2);
+ }
+
+ private void assertInsertedData(Item expectedItem1, Item expectedItem2) {
+ @SuppressWarnings("unchecked")
+ List orderList = session.createQuery("FROM Order").list();
+
+ assertNotNull(orderList);
+ assertEquals(1, orderList.size());
+
+ Order order = orderList.get(0);
+
+ Map itemMap = order.getItemMap();
+ assertNotNull(itemMap);
+ assertEquals(2, itemMap.size());
+ assertEquals(expectedItem1, itemMap.get("Wrangler Jeans"));
+ assertEquals(expectedItem2, itemMap.get("Armani Tshirts"));
+
+ }
+
+ @After
+ public void tearDown() {
+ session.close();
+ }
+
+ @AfterClass
+ public static void afterTests() {
+ sessionFactory.close();
+ }
+}
+
diff --git a/persistence-modules/hibernate-mapping/src/test/java/com/baeldung/hibernate/persistmaps/MapKeyJoinColumnIntegrationTest.java b/persistence-modules/hibernate-mapping/src/test/java/com/baeldung/hibernate/persistmaps/MapKeyJoinColumnIntegrationTest.java
new file mode 100644
index 0000000000..88b22f5c99
--- /dev/null
+++ b/persistence-modules/hibernate-mapping/src/test/java/com/baeldung/hibernate/persistmaps/MapKeyJoinColumnIntegrationTest.java
@@ -0,0 +1,105 @@
+package com.baeldung.hibernate.persistmaps;
+
+import com.baeldung.hibernate.HibernateUtil;
+import com.baeldung.hibernate.Strategy;
+import com.baeldung.hibernate.persistmaps.mapkeyjoincolumn.Item;
+import com.baeldung.hibernate.persistmaps.mapkeyjoincolumn.Order;
+import com.baeldung.hibernate.persistmaps.mapkeyjoincolumn.Seller;
+import org.hibernate.Session;
+import org.hibernate.SessionFactory;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import java.time.Instant;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+public class MapKeyJoinColumnIntegrationTest {
+ private static SessionFactory sessionFactory;
+
+ private Session session;
+
+ @BeforeClass
+ public static void beforeTests() {
+ sessionFactory = HibernateUtil.getSessionFactory(Strategy.MAP_KEY_JOIN_COLUMN_BASED);
+ }
+
+ @Before
+ public void setUp() {
+ session = sessionFactory.openSession();
+ session.beginTransaction();
+ }
+
+ @Test
+ public void givenData_whenInsertUsingMapKeyJoinColumn_thenPersistMap() {
+ Seller seller1 = new Seller();
+ seller1.setSellerName("Walmart");
+
+ Item item1 = new Item();
+ item1.setItemName("Wrangler Jeans");
+ item1.setItemPrice(150.0);
+ item1.setItemType(ItemType.JEANS);
+ item1.setCreatedOn(Date.from(Instant.ofEpochSecond(1554926573)));
+ item1.setSeller(seller1);
+
+
+ Seller seller2 = new Seller();
+ seller2.setSellerName("Amazon");
+
+ Item item2 = new Item();
+ item2.setItemName("Armani Tshirts");
+ item2.setItemPrice(180.0);
+ item2.setItemType(ItemType.TSHIRTS);
+ item2.setCreatedOn(Date.from(Instant.ofEpochSecond(1554890573)));
+ item2.setSeller(seller2);
+
+ Map itemSellerMap = new HashMap<>();
+ itemSellerMap.put(seller1, item1);
+ itemSellerMap.put(seller2, item2);
+
+ Order order = new Order();
+ order.setSellerItemMap(itemSellerMap);
+
+
+ session.persist(order);
+ session.getTransaction().commit();
+
+ assertInsertedData(seller1, item1, seller2, item2);
+ }
+
+ private void assertInsertedData(Seller seller1, Item expectedItem1, Seller seller2, Item expectedItem2) {
+ @SuppressWarnings("unchecked")
+ List orderList = session.createQuery("FROM Order").list();
+
+ assertNotNull(orderList);
+ assertEquals(1, orderList.size());
+
+ Order order = orderList.get(0);
+
+ Map sellerItemMap = order.getSellerItemMap();
+ assertNotNull(sellerItemMap);
+ assertEquals(2, sellerItemMap.size());
+ assertEquals(expectedItem1, sellerItemMap.get(seller1));
+ assertEquals(expectedItem2, sellerItemMap.get(seller2));
+
+ }
+
+ @After
+ public void tearDown() {
+ session.close();
+ }
+
+ @AfterClass
+ public static void afterTests() {
+ sessionFactory.close();
+ }
+}
+
diff --git a/persistence-modules/hibernate-mapping/src/test/java/com/baeldung/hibernate/persistmaps/MapKeyTemporalIntegrationTest.java b/persistence-modules/hibernate-mapping/src/test/java/com/baeldung/hibernate/persistmaps/MapKeyTemporalIntegrationTest.java
new file mode 100644
index 0000000000..7117cad22f
--- /dev/null
+++ b/persistence-modules/hibernate-mapping/src/test/java/com/baeldung/hibernate/persistmaps/MapKeyTemporalIntegrationTest.java
@@ -0,0 +1,96 @@
+package com.baeldung.hibernate.persistmaps;
+
+import com.baeldung.hibernate.HibernateUtil;
+import com.baeldung.hibernate.Strategy;
+import com.baeldung.hibernate.persistmaps.mapkey.Item;
+import com.baeldung.hibernate.persistmaps.mapkeytemporal.Order;
+import org.hibernate.Session;
+import org.hibernate.SessionFactory;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import java.time.Instant;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+public class MapKeyTemporalIntegrationTest {
+ private static SessionFactory sessionFactory;
+
+ private Session session;
+
+ @BeforeClass
+ public static void beforeTests() {
+ sessionFactory = HibernateUtil.getSessionFactory(Strategy.MAP_KEY_TEMPORAL_BASED);
+ }
+
+ @Before
+ public void setUp() {
+ session = sessionFactory.openSession();
+ session.beginTransaction();
+ }
+
+ @Test
+ public void givenData_whenInsertUsingMapKeyEnumerated_thenPersistMap() {
+ Date item1CreatedOn = Date.from(Instant.ofEpochSecond(1554926573));
+ Item item1 = new Item();
+ item1.setItemName("Wrangler Jeans");
+ item1.setItemPrice(150.0);
+ item1.setItemType(ItemType.JEANS);
+ item1.setCreatedOn(item1CreatedOn);
+
+
+ Date item2CreatedOn = Date.from(Instant.ofEpochSecond(1554890573));
+ Item item2 = new Item();
+ item2.setItemName("Armani Tshirts");
+ item2.setItemPrice(180.0);
+ item2.setItemType(ItemType.TSHIRTS);
+ item2.setCreatedOn(item2CreatedOn);
+
+ Map itemMap = new HashMap<>();
+ itemMap.put(item1CreatedOn, item1);
+ itemMap.put(item2CreatedOn, item2);
+
+ Order order = new Order();
+ order.setItemMap(itemMap);
+
+ session.persist(order);
+ session.getTransaction().commit();
+
+ assertInsertedData(item1CreatedOn, item1, item2CreatedOn, item2);
+ }
+
+ private void assertInsertedData(Date item1CreatedOn, Item expectedItem1, Date item2CreatedOn, Item expectedItem2) {
+ @SuppressWarnings("unchecked")
+ List orderList = session.createQuery("FROM Order").list();
+
+ assertNotNull(orderList);
+ assertEquals(1, orderList.size());
+
+ Order order = orderList.get(0);
+
+ Map itemMap = order.getItemMap();
+ assertNotNull(itemMap);
+ assertEquals(2, itemMap.size());
+ assertEquals(expectedItem1, itemMap.get(item1CreatedOn));
+ assertEquals(expectedItem2, itemMap.get(item2CreatedOn));
+
+ }
+
+ @After
+ public void tearDown() {
+ session.close();
+ }
+
+ @AfterClass
+ public static void afterTests() {
+ sessionFactory.close();
+ }
+}
diff --git a/persistence-modules/hibernate-mapping/src/test/resources/hibernate.properties b/persistence-modules/hibernate-mapping/src/test/resources/hibernate.properties
new file mode 100644
index 0000000000..c22da2496b
--- /dev/null
+++ b/persistence-modules/hibernate-mapping/src/test/resources/hibernate.properties
@@ -0,0 +1,10 @@
+hibernate.connection.driver_class=org.h2.Driver
+hibernate.connection.url=jdbc:h2:mem:mydb1;DB_CLOSE_DELAY=-1
+hibernate.connection.username=sa
+hibernate.connection.autocommit=true
+jdbc.password=
+
+hibernate.dialect=org.hibernate.dialect.H2Dialect
+hibernate.show_sql=true
+hibernate.hbm2ddl.auto=create-drop
+
diff --git a/persistence-modules/hibernate5/README.md b/persistence-modules/hibernate5/README.md
index a37720a428..68008bc8fe 100644
--- a/persistence-modules/hibernate5/README.md
+++ b/persistence-modules/hibernate5/README.md
@@ -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)
diff --git a/persistence-modules/java-jpa/README.md b/persistence-modules/java-jpa/README.md
index 2424999fb3..5be1015942 100644
--- a/persistence-modules/java-jpa/README.md
+++ b/persistence-modules/java-jpa/README.md
@@ -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)
diff --git a/persistence-modules/java-mongodb/pom.xml b/persistence-modules/java-mongodb/pom.xml
index 9658ef567f..0f5efedb96 100644
--- a/persistence-modules/java-mongodb/pom.xml
+++ b/persistence-modules/java-mongodb/pom.xml
@@ -35,8 +35,8 @@
1.8
1.8
- 3.4.1
+ 3.10.1
1.11
-
\ No newline at end of file
+
diff --git a/persistence-modules/java-mongodb/src/main/java/com/baeldung/MongoBsonExample.java b/persistence-modules/java-mongodb/src/main/java/com/baeldung/MongoBsonExample.java
new file mode 100644
index 0000000000..0ad3dfae30
--- /dev/null
+++ b/persistence-modules/java-mongodb/src/main/java/com/baeldung/MongoBsonExample.java
@@ -0,0 +1,79 @@
+package com.baeldung;
+
+import com.mongodb.client.MongoClient;
+import com.mongodb.client.MongoClients;
+import com.mongodb.client.MongoCollection;
+import com.mongodb.client.MongoDatabase;
+import org.bson.Document;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+public class MongoBsonExample
+{
+ public static void main(String[] args)
+ {
+ //
+ // 4.1 Connect to cluster (default is localhost:27017)
+ //
+
+ MongoClient mongoClient = MongoClients.create();
+ MongoDatabase database = mongoClient.getDatabase("myDB");
+ MongoCollection collection = database.getCollection("employees");
+
+ //
+ // 4.2 Insert new document
+ //
+
+ Document employee = new Document()
+ .append("first_name", "Joe")
+ .append("last_name", "Smith")
+ .append("title", "Java Developer")
+ .append("years_of_service", 3)
+ .append("skills", Arrays.asList("java", "spring", "mongodb"))
+ .append("manager", new Document()
+ .append("first_name", "Sally")
+ .append("last_name", "Johanson"));
+ collection.insertOne(employee);
+
+ //
+ // 4.3 Find documents
+ //
+
+
+ Document query = new Document("last_name", "Smith");
+ List results = new ArrayList<>();
+ collection.find(query).into(results);
+
+ query =
+ new Document("$or", Arrays.asList(
+ new Document("last_name", "Smith"),
+ new Document("first_name", "Joe")));
+ results = new ArrayList<>();
+ collection.find(query).into(results);
+
+ //
+ // 4.4 Update document
+ //
+
+ query = new Document(
+ "skills",
+ new Document(
+ "$elemMatch",
+ new Document("$eq", "spring")));
+ Document update = new Document(
+ "$push",
+ new Document("skills", "security"));
+ collection.updateMany(query, update);
+
+ //
+ // 4.5 Delete documents
+ //
+
+ query = new Document(
+ "years_of_service",
+ new Document("$lt", 0));
+ collection.deleteMany(query);
+ }
+}
diff --git a/persistence-modules/pom.xml b/persistence-modules/pom.xml
index 47c733d8a7..67a5c36fed 100644
--- a/persistence-modules/pom.xml
+++ b/persistence-modules/pom.xml
@@ -22,6 +22,7 @@
hbase
hibernate5
hibernate-ogm
+ hibernate-mapping
influxdb
java-cassandra
java-cockroachdb
@@ -34,7 +35,7 @@
querydsl
redis
solr
- spring-boot-h2/spring-boot-h2-database
+ spring-boot-persistence-h2
spring-boot-persistence
spring-boot-persistence-mongodb
spring-data-cassandra
diff --git a/persistence-modules/spring-boot-h2/spring-boot-h2-database/.gitignore b/persistence-modules/spring-boot-persistence-h2/.gitignore
similarity index 100%
rename from persistence-modules/spring-boot-h2/spring-boot-h2-database/.gitignore
rename to persistence-modules/spring-boot-persistence-h2/.gitignore
diff --git a/persistence-modules/spring-boot-h2/README.md b/persistence-modules/spring-boot-persistence-h2/README.md
similarity index 67%
rename from persistence-modules/spring-boot-h2/README.md
rename to persistence-modules/spring-boot-persistence-h2/README.md
index af5f395440..377b7c8939 100644
--- a/persistence-modules/spring-boot-h2/README.md
+++ b/persistence-modules/spring-boot-persistence-h2/README.md
@@ -1,2 +1,3 @@
### Relevant Articles:
- [Access the Same In-Memory H2 Database in Multiple Spring Boot Applications](https://www.baeldung.com/spring-boot-access-h2-database-multiple-apps)
+- [Spring Boot With H2 Database](https://www.baeldung.com/spring-boot-h2-database)
\ No newline at end of file
diff --git a/persistence-modules/spring-boot-h2/spring-boot-h2-database/pom.xml b/persistence-modules/spring-boot-persistence-h2/pom.xml
similarity index 97%
rename from persistence-modules/spring-boot-h2/spring-boot-h2-database/pom.xml
rename to persistence-modules/spring-boot-persistence-h2/pom.xml
index 882b88b535..4c8073ddb4 100644
--- a/persistence-modules/spring-boot-h2/spring-boot-h2-database/pom.xml
+++ b/persistence-modules/spring-boot-persistence-h2/pom.xml
@@ -14,7 +14,7 @@
parent-boot-2
com.baeldung
0.0.1-SNAPSHOT
- ../../../parent-boot-2
+ ../../parent-boot-2
diff --git a/persistence-modules/spring-boot-h2/spring-boot-h2-database/src/main/java/com/baeldung/h2db/auto/configuration/AutoConfigurationDemo.java b/persistence-modules/spring-boot-persistence-h2/src/main/java/com/baeldung/h2db/auto/configuration/AutoConfigurationDemo.java
similarity index 100%
rename from persistence-modules/spring-boot-h2/spring-boot-h2-database/src/main/java/com/baeldung/h2db/auto/configuration/AutoConfigurationDemo.java
rename to persistence-modules/spring-boot-persistence-h2/src/main/java/com/baeldung/h2db/auto/configuration/AutoConfigurationDemo.java
diff --git a/persistence-modules/spring-boot-h2/spring-boot-h2-database/src/main/java/com/baeldung/h2db/demo/client/ClientSpringBootApp.java b/persistence-modules/spring-boot-persistence-h2/src/main/java/com/baeldung/h2db/demo/client/ClientSpringBootApp.java
similarity index 100%
rename from persistence-modules/spring-boot-h2/spring-boot-h2-database/src/main/java/com/baeldung/h2db/demo/client/ClientSpringBootApp.java
rename to persistence-modules/spring-boot-persistence-h2/src/main/java/com/baeldung/h2db/demo/client/ClientSpringBootApp.java
diff --git a/persistence-modules/spring-boot-h2/spring-boot-h2-database/src/main/java/com/baeldung/h2db/demo/server/SpringBootApp.java b/persistence-modules/spring-boot-persistence-h2/src/main/java/com/baeldung/h2db/demo/server/SpringBootApp.java
similarity index 100%
rename from persistence-modules/spring-boot-h2/spring-boot-h2-database/src/main/java/com/baeldung/h2db/demo/server/SpringBootApp.java
rename to persistence-modules/spring-boot-persistence-h2/src/main/java/com/baeldung/h2db/demo/server/SpringBootApp.java
diff --git a/persistence-modules/spring-boot-persistence-h2/src/main/java/com/baeldung/h2db/springboot/SpringBootH2Application.java b/persistence-modules/spring-boot-persistence-h2/src/main/java/com/baeldung/h2db/springboot/SpringBootH2Application.java
new file mode 100644
index 0000000000..378093cfa9
--- /dev/null
+++ b/persistence-modules/spring-boot-persistence-h2/src/main/java/com/baeldung/h2db/springboot/SpringBootH2Application.java
@@ -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);
+ }
+}
diff --git a/persistence-modules/spring-boot-persistence-h2/src/main/java/com/baeldung/h2db/springboot/daos/UserRepository.java b/persistence-modules/spring-boot-persistence-h2/src/main/java/com/baeldung/h2db/springboot/daos/UserRepository.java
new file mode 100644
index 0000000000..35e496e910
--- /dev/null
+++ b/persistence-modules/spring-boot-persistence-h2/src/main/java/com/baeldung/h2db/springboot/daos/UserRepository.java
@@ -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 {
+}
diff --git a/persistence-modules/spring-boot-persistence-h2/src/main/java/com/baeldung/h2db/springboot/models/User.java b/persistence-modules/spring-boot-persistence-h2/src/main/java/com/baeldung/h2db/springboot/models/User.java
new file mode 100644
index 0000000000..fa3c01c035
--- /dev/null
+++ b/persistence-modules/spring-boot-persistence-h2/src/main/java/com/baeldung/h2db/springboot/models/User.java
@@ -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 + '\'' +
+ '}';
+ }
+}
diff --git a/persistence-modules/spring-boot-h2/spring-boot-h2-database/src/main/resources/application.properties b/persistence-modules/spring-boot-persistence-h2/src/main/resources/application.properties
similarity index 84%
rename from persistence-modules/spring-boot-h2/spring-boot-h2-database/src/main/resources/application.properties
rename to persistence-modules/spring-boot-persistence-h2/src/main/resources/application.properties
index 5e425a3550..109b389b58 100644
--- a/persistence-modules/spring-boot-h2/spring-boot-h2-database/src/main/resources/application.properties
+++ b/persistence-modules/spring-boot-persistence-h2/src/main/resources/application.properties
@@ -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
\ No newline at end of file
diff --git a/persistence-modules/spring-boot-persistence-h2/src/main/resources/data.sql b/persistence-modules/spring-boot-persistence-h2/src/main/resources/data.sql
new file mode 100644
index 0000000000..2d7b446005
--- /dev/null
+++ b/persistence-modules/spring-boot-persistence-h2/src/main/resources/data.sql
@@ -0,0 +1,13 @@
+DROP TABLE IF EXISTS billionaires;
+
+CREATE TABLE billionaires (
+ id INT AUTO_INCREMENT PRIMARY KEY,
+ first_name VARCHAR(250) NOT NULL,
+ last_name VARCHAR(250) NOT NULL,
+ career VARCHAR(250) DEFAULT NULL
+);
+
+INSERT INTO billionaires (first_name, last_name, career) VALUES
+('Aliko', 'Dangote', 'Billionaire Industrialist'),
+('Bill', 'Gates', 'Billionaire Tech Entrepreneur'),
+('Folrunsho', 'Alakija', 'Billionaire Oil Magnate');
\ No newline at end of file
diff --git a/persistence-modules/spring-boot-persistence-h2/src/test/java/com/baeldung/SpringBootH2IntegrationTest.java b/persistence-modules/spring-boot-persistence-h2/src/test/java/com/baeldung/SpringBootH2IntegrationTest.java
new file mode 100644
index 0000000000..aecc63c599
--- /dev/null
+++ b/persistence-modules/spring-boot-persistence-h2/src/test/java/com/baeldung/SpringBootH2IntegrationTest.java
@@ -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 users = (List) 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) userRepository.findAll()).isEmpty());
+ }
+
+}
diff --git a/persistence-modules/spring-boot-h2/spring-boot-h2-database/src/test/java/com/baeldung/SpringContextIntegrationTest.java b/persistence-modules/spring-boot-persistence-h2/src/test/java/com/baeldung/SpringContextIntegrationTest.java
similarity index 100%
rename from persistence-modules/spring-boot-h2/spring-boot-h2-database/src/test/java/com/baeldung/SpringContextIntegrationTest.java
rename to persistence-modules/spring-boot-persistence-h2/src/test/java/com/baeldung/SpringContextIntegrationTest.java
diff --git a/persistence-modules/spring-boot-persistence/README.MD b/persistence-modules/spring-boot-persistence/README.MD
index ee7c2e298e..709f505ea9 100644
--- a/persistence-modules/spring-boot-persistence/README.MD
+++ b/persistence-modules/spring-boot-persistence/README.MD
@@ -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)
diff --git a/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/boot/config/H2JpaConfig.java b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/boot/config/H2JpaConfig.java
index 547a905d91..c5c77be56f 100644
--- a/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/boot/config/H2JpaConfig.java
+++ b/persistence-modules/spring-boot-persistence/src/main/java/com/baeldung/boot/config/H2JpaConfig.java
@@ -1,13 +1,9 @@
package com.baeldung.boot.config;
-import java.util.Properties;
-
-import javax.persistence.EntityManagerFactory;
-import javax.sql.DataSource;
-
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Profile;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
@@ -17,10 +13,17 @@ import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.annotation.EnableTransactionManagement;
+import javax.persistence.EntityManagerFactory;
+import javax.sql.DataSource;
+import java.util.Properties;
+
@Configuration
@EnableJpaRepositories(basePackages = { "com.baeldung.boot.repository", "com.baeldung.repository" })
@PropertySource("classpath:persistence-generic-entity.properties")
@EnableTransactionManagement
+@Profile("default") //only required to allow H2JpaConfig and H2TestProfileJPAConfig to coexist in same project
+ //this demo project is showcasing several ways to achieve the same end, and class-level
+ //Profile annotations are only necessary because the different techniques are sharing a project
public class H2JpaConfig {
@Autowired
diff --git a/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/SpringBootProfileIntegrationTest.java b/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/SpringBootProfileIntegrationTest.java
index 0227458987..d7bb44e133 100644
--- a/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/SpringBootProfileIntegrationTest.java
+++ b/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/SpringBootProfileIntegrationTest.java
@@ -1,8 +1,9 @@
package com.baeldung;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-
+import com.baeldung.boot.Application;
+import com.baeldung.boot.domain.GenericEntity;
+import com.baeldung.boot.repository.GenericEntityRepository;
+import com.baeldung.config.H2TestProfileJPAConfig;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
@@ -10,13 +11,11 @@ import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit4.SpringRunner;
-import com.baeldung.boot.Application;
-import com.baeldung.boot.config.H2JpaConfig;
-import com.baeldung.boot.domain.GenericEntity;
-import com.baeldung.boot.repository.GenericEntityRepository;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
@RunWith(SpringRunner.class)
-@SpringBootTest(classes = { Application.class, H2JpaConfig.class })
+@SpringBootTest(classes = { Application.class, H2TestProfileJPAConfig.class })
@ActiveProfiles("test")
public class SpringBootProfileIntegrationTest {
@Autowired
diff --git a/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/config/H2TestProfileJPAConfig.java b/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/config/H2TestProfileJPAConfig.java
index e0678bcf47..f73000a10e 100644
--- a/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/config/H2TestProfileJPAConfig.java
+++ b/persistence-modules/spring-boot-persistence/src/test/java/com/baeldung/config/H2TestProfileJPAConfig.java
@@ -1,10 +1,5 @@
package com.baeldung.config;
-import java.util.Properties;
-
-import javax.persistence.EntityManagerFactory;
-import javax.sql.DataSource;
-
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@@ -17,9 +12,16 @@ import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.annotation.EnableTransactionManagement;
+import javax.persistence.EntityManagerFactory;
+import javax.sql.DataSource;
+import java.util.Properties;
+
@Configuration
@EnableJpaRepositories(basePackages = { "com.baeldung.repository", "com.baeldung.boot.repository" })
@EnableTransactionManagement
+@Profile("test") //only required to allow H2JpaConfig and H2TestProfileJPAConfig to coexist in same project
+ //this demo project is showcasing several ways to achieve the same end, and class-level
+ //Profile annotations are only necessary because the different techniques are sharing a project
public class H2TestProfileJPAConfig {
@Autowired
diff --git a/persistence-modules/spring-data-couchbase-2/README.md b/persistence-modules/spring-data-couchbase-2/README.md
index 2b6a1faddf..3145fc653a 100644
--- a/persistence-modules/spring-data-couchbase-2/README.md
+++ b/persistence-modules/spring-data-couchbase-2/README.md
@@ -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
diff --git a/persistence-modules/spring-data-jpa-2/README.md b/persistence-modules/spring-data-jpa-2/README.md
index 295a434d17..41381ab82a 100644
--- a/persistence-modules/spring-data-jpa-2/README.md
+++ b/persistence-modules/spring-data-jpa-2/README.md
@@ -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)
diff --git a/persistence-modules/spring-data-jpa-2/pom.xml b/persistence-modules/spring-data-jpa-2/pom.xml
index 8e46112659..251007ba6d 100644
--- a/persistence-modules/spring-data-jpa-2/pom.xml
+++ b/persistence-modules/spring-data-jpa-2/pom.xml
@@ -1,12 +1,13 @@
+ 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">
4.0.0
- com.baeldung
+
+ com.baeldung
spring-data-jpa-2
- spring-data-jpa
-
+ spring-data-jpa
+
parent-boot-2
com.baeldung
@@ -19,12 +20,22 @@
org.springframework.boot
spring-boot-starter-data-jpa
-
+
com.h2database
h2
-
+
+
+ com.fasterxml.jackson.core
+ jackson-databind
+
+
+
+ org.springframework
+ spring-oxm
+
+
\ No newline at end of file
diff --git a/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/config/JpaPopulators.java b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/config/JpaPopulators.java
new file mode 100644
index 0000000000..24348d31c5
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/config/JpaPopulators.java
@@ -0,0 +1,35 @@
+package com.baeldung.config;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.core.io.Resource;
+import org.springframework.data.repository.init.Jackson2RepositoryPopulatorFactoryBean;
+import org.springframework.data.repository.init.UnmarshallerRepositoryPopulatorFactoryBean;
+import org.springframework.oxm.jaxb.Jaxb2Marshaller;
+
+import com.baeldung.entity.Fruit;
+
+@Configuration
+public class JpaPopulators {
+
+ @Bean
+ public Jackson2RepositoryPopulatorFactoryBean getRespositoryPopulator() throws Exception {
+ Jackson2RepositoryPopulatorFactoryBean factory = new Jackson2RepositoryPopulatorFactoryBean();
+ factory.setResources(new Resource[] { new ClassPathResource("fruit-data.json") });
+ return factory;
+ }
+
+ @Bean
+ public UnmarshallerRepositoryPopulatorFactoryBean repositoryPopulator() {
+
+ Jaxb2Marshaller unmarshaller = new Jaxb2Marshaller();
+ unmarshaller.setClassesToBeBound(Fruit.class);
+
+ UnmarshallerRepositoryPopulatorFactoryBean factory = new UnmarshallerRepositoryPopulatorFactoryBean();
+ factory.setUnmarshaller(unmarshaller);
+ factory.setResources(new Resource[] { new ClassPathResource("apple-fruit-data.xml"), new ClassPathResource("guava-fruit-data.xml") });
+ return factory;
+ }
+
+}
diff --git a/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/datajpadelete/entity/Book.java b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/datajpadelete/entity/Book.java
new file mode 100644
index 0000000000..deac24548a
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/datajpadelete/entity/Book.java
@@ -0,0 +1,51 @@
+package com.baeldung.datajpadelete.entity;
+
+import javax.persistence.*;
+
+@Entity
+public class Book {
+
+ @Id
+ @GeneratedValue
+ private Long id;
+ private String title;
+
+ @ManyToOne
+ private Category category;
+
+ public Book() {
+ }
+
+ public Book(String title) {
+ this.title = title;
+ }
+
+ public Book(String title, Category category) {
+ this.title = title;
+ this.category = category;
+ }
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public void setTitle(String title) {
+ this.title = title;
+ }
+
+ public Category getCategory() {
+ return category;
+ }
+
+ public void setCategory(Category category) {
+ this.category = category;
+ }
+}
\ No newline at end of file
diff --git a/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/datajpadelete/entity/Category.java b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/datajpadelete/entity/Category.java
new file mode 100644
index 0000000000..16f1a4157f
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/datajpadelete/entity/Category.java
@@ -0,0 +1,60 @@
+package com.baeldung.datajpadelete.entity;
+
+import javax.persistence.*;
+import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+@Entity
+public class Category {
+
+ @Id
+ @GeneratedValue
+ private Long id;
+ private String name;
+
+ @OneToMany(mappedBy = "category", cascade = CascadeType.ALL, orphanRemoval = true)
+ private List books;
+
+ public Category() {
+ }
+
+ public Category(String name) {
+ this.name = name;
+ }
+
+ public Category(String name, Book... books) {
+ this.name = name;
+ this.books = Stream.of(books).collect(Collectors.toList());
+ this.books.forEach(x -> x.setCategory(this));
+ }
+
+ public Category(String name, List books) {
+ this.name = name;
+ this.books = books;
+ }
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public List getBooks() {
+ return books;
+ }
+
+ public void setBooks(List books) {
+ this.books = books;
+ }
+}
diff --git a/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/datajpadelete/repository/BookRepository.java b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/datajpadelete/repository/BookRepository.java
new file mode 100644
index 0000000000..5d0f45f127
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/datajpadelete/repository/BookRepository.java
@@ -0,0 +1,19 @@
+package com.baeldung.datajpadelete.repository;
+
+import com.baeldung.datajpadelete.entity.Book;
+import org.springframework.data.jpa.repository.Modifying;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.CrudRepository;
+import org.springframework.data.repository.query.Param;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface BookRepository extends CrudRepository {
+
+ long deleteByTitle(String title);
+
+ @Modifying
+ @Query("delete from Book b where b.title=:title")
+ void deleteBooks(@Param("title") String title);
+
+}
\ No newline at end of file
diff --git a/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/datajpadelete/repository/CategoryRepository.java b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/datajpadelete/repository/CategoryRepository.java
new file mode 100644
index 0000000000..6fe7058a78
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/datajpadelete/repository/CategoryRepository.java
@@ -0,0 +1,9 @@
+package com.baeldung.datajpadelete.repository;
+
+import com.baeldung.datajpadelete.entity.Category;
+import org.springframework.data.repository.CrudRepository;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface CategoryRepository extends CrudRepository {
+}
diff --git a/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/embeddable/model/Company.java b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/embeddable/model/Company.java
new file mode 100644
index 0000000000..203cff1e35
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/embeddable/model/Company.java
@@ -0,0 +1,71 @@
+package com.baeldung.embeddable.model;
+
+import javax.persistence.AttributeOverride;
+import javax.persistence.AttributeOverrides;
+import javax.persistence.Column;
+import javax.persistence.Embedded;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+
+@Entity
+public class Company {
+
+ @Id
+ @GeneratedValue
+ private Integer id;
+
+ private String name;
+
+ private String address;
+
+ private String phone;
+
+ @Embedded
+ @AttributeOverrides(value = {
+ @AttributeOverride( name = "firstName", column = @Column(name = "contact_first_name")),
+ @AttributeOverride( name = "lastName", column = @Column(name = "contact_last_name")),
+ @AttributeOverride( name = "phone", column = @Column(name = "contact_phone"))
+ })
+ private ContactPerson contactPerson;
+
+ public Integer getId() {
+ return id;
+ }
+
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getAddress() {
+ return address;
+ }
+
+ public void setAddress(String address) {
+ this.address = address;
+ }
+
+ public String getPhone() {
+ return phone;
+ }
+
+ public void setPhone(String phone) {
+ this.phone = phone;
+ }
+
+ public ContactPerson getContactPerson() {
+ return contactPerson;
+ }
+
+ public void setContactPerson(ContactPerson contactPerson) {
+ this.contactPerson = contactPerson;
+ }
+}
diff --git a/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/embeddable/model/ContactPerson.java b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/embeddable/model/ContactPerson.java
new file mode 100644
index 0000000000..561da80878
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/embeddable/model/ContactPerson.java
@@ -0,0 +1,38 @@
+package com.baeldung.embeddable.model;
+
+import javax.persistence.Embeddable;
+
+@Embeddable
+public class ContactPerson {
+
+ private String firstName;
+
+ private String lastName;
+
+ private String phone;
+
+ 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;
+ }
+
+ public String getPhone() {
+ return phone;
+ }
+
+ public void setPhone(String phone) {
+ this.phone = phone;
+ }
+
+}
diff --git a/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/embeddable/repositories/CompanyRepository.java b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/embeddable/repositories/CompanyRepository.java
new file mode 100644
index 0000000000..f456b15652
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/embeddable/repositories/CompanyRepository.java
@@ -0,0 +1,18 @@
+package com.baeldung.embeddable.repositories;
+
+import com.baeldung.embeddable.model.Company;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Query;
+
+import java.util.List;
+
+public interface CompanyRepository extends JpaRepository {
+
+ List findByContactPersonFirstName(String firstName);
+
+ @Query("SELECT C FROM Company C WHERE C.contactPerson.firstName = ?1")
+ List findByContactPersonFirstNameWithJPQL(String firstName);
+
+ @Query(value = "SELECT * FROM company WHERE contact_first_name = ?1", nativeQuery = true)
+ List findByContactPersonFirstNameWithNativeQuery(String firstName);
+}
diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/customer/Customer.java b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/entity/Customer.java
similarity index 95%
rename from persistence-modules/spring-data-jpa/src/main/java/com/baeldung/customer/Customer.java
rename to persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/entity/Customer.java
index ed922c3075..efcae73853 100644
--- a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/customer/Customer.java
+++ b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/entity/Customer.java
@@ -1,4 +1,4 @@
-package com.baeldung.customer;
+package com.baeldung.entity;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
diff --git a/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/entity/Fruit.java b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/entity/Fruit.java
index f82022e67e..d45ac33db8 100644
--- a/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/entity/Fruit.java
+++ b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/entity/Fruit.java
@@ -2,7 +2,9 @@ package com.baeldung.entity;
import javax.persistence.Entity;
import javax.persistence.Id;
+import javax.xml.bind.annotation.XmlRootElement;
+@XmlRootElement
@Entity
public class Fruit {
diff --git a/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/joins/model/Department.java b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/joins/model/Department.java
new file mode 100644
index 0000000000..439f7532f5
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/joins/model/Department.java
@@ -0,0 +1,45 @@
+package com.baeldung.joins.model;
+
+import java.util.List;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.OneToMany;
+
+@Entity
+public class Department {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.AUTO)
+ private long id;
+
+ private String name;
+
+ @OneToMany(mappedBy = "department")
+ private List employees;
+
+ public long getId() {
+ return id;
+ }
+
+ public void setId(long id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public List getEmployees() {
+ return employees;
+ }
+
+ public void setEmployees(List employees) {
+ this.employees = employees;
+ }
+}
diff --git a/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/joins/model/Employee.java b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/joins/model/Employee.java
new file mode 100644
index 0000000000..277274e61c
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/joins/model/Employee.java
@@ -0,0 +1,69 @@
+package com.baeldung.joins.model;
+
+import java.util.List;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.ManyToOne;
+import javax.persistence.OneToMany;
+import javax.persistence.Table;
+
+@Entity
+@Table(name = "joins_employee")
+public class Employee {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ private long id;
+
+ private String name;
+
+ private int age;
+
+ @ManyToOne
+ private Department department;
+
+ @OneToMany(mappedBy = "employee")
+ private List phones;
+
+ public long getId() {
+ return id;
+ }
+
+ public void setId(long id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public int getAge() {
+ return age;
+ }
+
+ public void setAge(int age) {
+ this.age = age;
+ }
+
+ public Department getDepartment() {
+ return department;
+ }
+
+ public void setDepartment(Department department) {
+ this.department = department;
+ }
+
+ public List getPhones() {
+ return phones;
+ }
+
+ public void setPhones(List phones) {
+ this.phones = phones;
+ }
+}
diff --git a/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/joins/model/Phone.java b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/joins/model/Phone.java
new file mode 100644
index 0000000000..41382915b1
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/joins/model/Phone.java
@@ -0,0 +1,44 @@
+package com.baeldung.joins.model;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.ManyToOne;
+
+@Entity
+public class Phone {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ private long id;
+
+ private String number;
+
+ @ManyToOne
+ private Employee employee;
+
+ public long getId() {
+ return id;
+ }
+
+ public void setId(long id) {
+ this.id = id;
+ }
+
+ public String getNumber() {
+ return number;
+ }
+
+ public void setNumber(String number) {
+ this.number = number;
+ }
+
+ public Employee getEmployee() {
+ return employee;
+ }
+
+ public void setEmployee(Employee employee) {
+ this.employee = employee;
+ }
+}
diff --git a/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/projection/model/Address.java b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/projection/model/Address.java
new file mode 100644
index 0000000000..0c5a3eac60
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/projection/model/Address.java
@@ -0,0 +1,57 @@
+package com.baeldung.projection.model;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.OneToOne;
+
+@Entity
+public class Address {
+ @Id
+ private Long id;
+ @OneToOne
+ private Person person;
+ private String state;
+ private String city;
+ private String street;
+ private String zipCode;
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public String getState() {
+ return state;
+ }
+
+ public void setState(String state) {
+ this.state = state;
+ }
+
+ public String getCity() {
+ return city;
+ }
+
+ public void setCity(String city) {
+ this.city = city;
+ }
+
+ public String getStreet() {
+ return street;
+ }
+
+ public void setStreet(String street) {
+ this.street = street;
+ }
+
+ public String getZipCode() {
+ return zipCode;
+ }
+
+ public void setZipCode(String zipCode) {
+ this.zipCode = zipCode;
+ }
+}
diff --git a/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/projection/model/Person.java b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/projection/model/Person.java
new file mode 100644
index 0000000000..d18bd1c72d
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/projection/model/Person.java
@@ -0,0 +1,47 @@
+package com.baeldung.projection.model;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.OneToOne;
+
+@Entity
+public class Person {
+ @Id
+ private Long id;
+ private String firstName;
+ private String lastName;
+ @OneToOne(mappedBy = "person")
+ private Address address;
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long 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;
+ }
+
+ public Address getAddress() {
+ return address;
+ }
+
+ public void setAddress(Address address) {
+ this.address = address;
+ }
+}
diff --git a/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/projection/repository/AddressRepository.java b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/projection/repository/AddressRepository.java
new file mode 100644
index 0000000000..c1053f4867
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/projection/repository/AddressRepository.java
@@ -0,0 +1,11 @@
+package com.baeldung.projection.repository;
+
+import com.baeldung.projection.view.AddressView;
+import com.baeldung.projection.model.Address;
+import org.springframework.data.repository.Repository;
+
+import java.util.List;
+
+public interface AddressRepository extends Repository {
+ List getAddressByState(String state);
+}
diff --git a/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/projection/repository/PersonRepository.java b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/projection/repository/PersonRepository.java
new file mode 100644
index 0000000000..64bc7471e6
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/projection/repository/PersonRepository.java
@@ -0,0 +1,14 @@
+package com.baeldung.projection.repository;
+
+import com.baeldung.projection.model.Person;
+import com.baeldung.projection.view.PersonDto;
+import com.baeldung.projection.view.PersonView;
+import org.springframework.data.repository.Repository;
+
+public interface PersonRepository extends Repository {
+ PersonView findByLastName(String lastName);
+
+ PersonDto findByFirstName(String firstName);
+
+ T findByLastName(String lastName, Class type);
+}
diff --git a/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/projection/view/AddressView.java b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/projection/view/AddressView.java
new file mode 100644
index 0000000000..7a24a1e9b9
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/projection/view/AddressView.java
@@ -0,0 +1,7 @@
+package com.baeldung.projection.view;
+
+public interface AddressView {
+ String getZipCode();
+
+ PersonView getPerson();
+}
diff --git a/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/projection/view/PersonDto.java b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/projection/view/PersonDto.java
new file mode 100644
index 0000000000..1fd924450b
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/projection/view/PersonDto.java
@@ -0,0 +1,34 @@
+package com.baeldung.projection.view;
+
+import java.util.Objects;
+
+public class PersonDto {
+ private final String firstName;
+ private final String lastName;
+
+ public PersonDto(String firstName, String lastName) {
+ this.firstName = firstName;
+ this.lastName = lastName;
+ }
+
+ public String getFirstName() {
+ return firstName;
+ }
+
+ public String getLastName() {
+ return lastName;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ PersonDto personDto = (PersonDto) o;
+ return Objects.equals(firstName, personDto.firstName) && Objects.equals(lastName, personDto.lastName);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(firstName, lastName);
+ }
+}
diff --git a/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/projection/view/PersonView.java b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/projection/view/PersonView.java
new file mode 100644
index 0000000000..36777ec26f
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/projection/view/PersonView.java
@@ -0,0 +1,12 @@
+package com.baeldung.projection.view;
+
+import org.springframework.beans.factory.annotation.Value;
+
+public interface PersonView {
+ String getFirstName();
+
+ String getLastName();
+
+ @Value("#{target.firstName + ' ' + target.lastName}")
+ String getFullName();
+}
diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/customer/CustomerRepository.java b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/repository/CustomerRepository.java
similarity index 89%
rename from persistence-modules/spring-data-jpa/src/main/java/com/baeldung/customer/CustomerRepository.java
rename to persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/repository/CustomerRepository.java
index c354ccbb58..65b22bbd84 100644
--- a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/customer/CustomerRepository.java
+++ b/persistence-modules/spring-data-jpa-2/src/main/java/com/baeldung/repository/CustomerRepository.java
@@ -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;
diff --git a/persistence-modules/spring-data-jpa-2/src/main/resources/apple-fruit-data.xml b/persistence-modules/spring-data-jpa-2/src/main/resources/apple-fruit-data.xml
new file mode 100644
index 0000000000..d87ae28f1e
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-2/src/main/resources/apple-fruit-data.xml
@@ -0,0 +1,7 @@
+
+
+
+ 1
+ apple
+ red
+
diff --git a/persistence-modules/spring-data-jpa-2/src/main/resources/application-joins.properties b/persistence-modules/spring-data-jpa-2/src/main/resources/application-joins.properties
new file mode 100644
index 0000000000..fe2270293b
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-2/src/main/resources/application-joins.properties
@@ -0,0 +1 @@
+spring.datasource.data=classpath:db/import_joins.sql
diff --git a/persistence-modules/spring-data-jpa-2/src/main/resources/db/import_joins.sql b/persistence-modules/spring-data-jpa-2/src/main/resources/db/import_joins.sql
new file mode 100644
index 0000000000..e4772d6ff2
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-2/src/main/resources/db/import_joins.sql
@@ -0,0 +1,13 @@
+INSERT INTO department (id, name) VALUES (1, 'Infra');
+INSERT INTO department (id, name) VALUES (2, 'Accounting');
+INSERT INTO department (id, name) VALUES (3, 'Management');
+
+INSERT INTO joins_employee (id, name, age, department_id) VALUES (1, 'Baeldung', '35', 1);
+INSERT INTO joins_employee (id, name, age, department_id) VALUES (2, 'John', '35', 2);
+INSERT INTO joins_employee (id, name, age, department_id) VALUES (3, 'Jane', '35', 2);
+
+INSERT INTO phone (id, number, employee_id) VALUES (1, '111', 1);
+INSERT INTO phone (id, number, employee_id) VALUES (2, '222', 1);
+INSERT INTO phone (id, number, employee_id) VALUES (3, '333', 1);
+
+COMMIT;
diff --git a/persistence-modules/spring-data-jpa-2/src/main/resources/fruit-data.json b/persistence-modules/spring-data-jpa-2/src/main/resources/fruit-data.json
new file mode 100644
index 0000000000..6dc44e2586
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-2/src/main/resources/fruit-data.json
@@ -0,0 +1,14 @@
+[
+ {
+ "_class": "com.baeldung.entity.Fruit",
+ "name": "apple",
+ "color": "red",
+ "id": 1
+ },
+ {
+ "_class": "com.baeldung.entity.Fruit",
+ "name": "guava",
+ "color": "green",
+ "id": 2
+ }
+]
\ No newline at end of file
diff --git a/persistence-modules/spring-data-jpa-2/src/main/resources/guava-fruit-data.xml b/persistence-modules/spring-data-jpa-2/src/main/resources/guava-fruit-data.xml
new file mode 100644
index 0000000000..ffd75bb4bb
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-2/src/main/resources/guava-fruit-data.xml
@@ -0,0 +1,7 @@
+
+
+
+ 2
+ guava
+ green
+
diff --git a/persistence-modules/spring-data-jpa-2/src/test/java/com/baeldung/datajpadelete/DeleteFromRepositoryUnitTest.java b/persistence-modules/spring-data-jpa-2/src/test/java/com/baeldung/datajpadelete/DeleteFromRepositoryUnitTest.java
new file mode 100644
index 0000000000..9e7e516735
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-2/src/test/java/com/baeldung/datajpadelete/DeleteFromRepositoryUnitTest.java
@@ -0,0 +1,72 @@
+package com.baeldung.datajpadelete;
+
+import com.baeldung.Application;
+import com.baeldung.datajpadelete.entity.Book;
+import com.baeldung.datajpadelete.repository.BookRepository;
+import org.junit.After;
+import org.junit.Before;
+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 org.springframework.transaction.annotation.Transactional;
+
+import java.util.Arrays;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = {Application.class})
+public class DeleteFromRepositoryUnitTest {
+
+ @Autowired
+ private BookRepository repository;
+
+ Book book1;
+ Book book2;
+
+ @Before
+ public void setup() {
+ book1 = new Book("The Hobbit");
+ book2 = new Book("All Quiet on the Western Front");
+
+ repository.saveAll(Arrays.asList(book1, book2));
+ }
+
+ @After
+ public void teardown() {
+ repository.deleteAll();
+ }
+
+ @Test
+ public void whenDeleteByIdFromRepository_thenDeletingShouldBeSuccessful() {
+ repository.deleteById(book1.getId());
+
+ assertThat(repository.count() == 1).isTrue();
+ }
+
+ @Test
+ public void whenDeleteAllFromRepository_thenRepositoryShouldBeEmpty() {
+ repository.deleteAll();
+
+ assertThat(repository.count() == 0).isTrue();
+ }
+
+ @Test
+ @Transactional
+ public void whenDeleteFromDerivedQuery_thenDeletingShouldBeSuccessful() {
+ repository.deleteByTitle("The Hobbit");
+
+ assertThat(repository.count() == 1).isTrue();
+ }
+
+ @Test
+ @Transactional
+ public void whenDeleteFromCustomQuery_thenDeletingShouldBeSuccessful() {
+ repository.deleteBooks("The Hobbit");
+
+ assertThat(repository.count() == 1).isTrue();
+ }
+
+}
\ No newline at end of file
diff --git a/persistence-modules/spring-data-jpa-2/src/test/java/com/baeldung/datajpadelete/DeleteInRelationshipsUnitTest.java b/persistence-modules/spring-data-jpa-2/src/test/java/com/baeldung/datajpadelete/DeleteInRelationshipsUnitTest.java
new file mode 100644
index 0000000000..56de8749b2
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-2/src/test/java/com/baeldung/datajpadelete/DeleteInRelationshipsUnitTest.java
@@ -0,0 +1,60 @@
+package com.baeldung.datajpadelete;
+
+import com.baeldung.Application;
+import com.baeldung.datajpadelete.entity.Book;
+import com.baeldung.datajpadelete.entity.Category;
+import com.baeldung.datajpadelete.repository.BookRepository;
+import com.baeldung.datajpadelete.repository.CategoryRepository;
+import org.junit.After;
+import org.junit.Before;
+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 static org.assertj.core.api.Assertions.assertThat;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = {Application.class})
+public class DeleteInRelationshipsUnitTest {
+
+ @Autowired
+ private BookRepository bookRepository;
+
+ @Autowired
+ private CategoryRepository categoryRepository;
+
+ @Before
+ public void setup() {
+ Book book1 = new Book("The Hobbit");
+ Category category1 = new Category("Cat1", book1);
+ categoryRepository.save(category1);
+
+ Book book2 = new Book("All Quiet on the Western Front");
+ Category category2 = new Category("Cat2", book2);
+ categoryRepository.save(category2);
+ }
+
+ @After
+ public void teardown() {
+ bookRepository.deleteAll();
+ categoryRepository.deleteAll();
+ }
+
+ @Test
+ public void whenDeletingCategories_thenBooksShouldAlsoBeDeleted() {
+ categoryRepository.deleteAll();
+
+ assertThat(bookRepository.count() == 0).isTrue();
+ assertThat(categoryRepository.count() == 0).isTrue();
+ }
+
+ @Test
+ public void whenDeletingBooks_thenCategoriesShouldAlsoBeDeleted() {
+ bookRepository.deleteAll();
+
+ assertThat(bookRepository.count() == 0).isTrue();
+ assertThat(categoryRepository.count() == 2).isTrue();
+ }
+}
\ No newline at end of file
diff --git a/persistence-modules/spring-data-jpa-2/src/test/java/com/baeldung/embeddable/EmbeddableIntegrationTest.java b/persistence-modules/spring-data-jpa-2/src/test/java/com/baeldung/embeddable/EmbeddableIntegrationTest.java
new file mode 100644
index 0000000000..b4c365a2d9
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-2/src/test/java/com/baeldung/embeddable/EmbeddableIntegrationTest.java
@@ -0,0 +1,125 @@
+package com.baeldung.embeddable;
+
+import com.baeldung.Application;
+import com.baeldung.embeddable.model.Company;
+import com.baeldung.embeddable.model.ContactPerson;
+import com.baeldung.embeddable.repositories.CompanyRepository;
+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 org.springframework.transaction.annotation.Transactional;
+
+import java.util.List;
+
+import static org.junit.Assert.assertEquals;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = {Application.class})
+public class EmbeddableIntegrationTest {
+
+ @Autowired
+ private CompanyRepository companyRepository;
+
+ @Test
+ @Transactional
+ public void whenInsertingCompany_thenEmbeddedContactPersonDetailsAreMapped() {
+ ContactPerson contactPerson = new ContactPerson();
+ contactPerson.setFirstName("First");
+ contactPerson.setLastName("Last");
+ contactPerson.setPhone("123-456-789");
+
+ Company company = new Company();
+ company.setName("Company");
+ company.setAddress("1st street");
+ company.setPhone("987-654-321");
+ company.setContactPerson(contactPerson);
+
+ companyRepository.save(company);
+
+ Company result = companyRepository.getOne(company.getId());
+
+ assertEquals("Company", result.getName());
+ assertEquals("1st street", result.getAddress());
+ assertEquals("987-654-321", result.getPhone());
+ assertEquals("First", result.getContactPerson().getFirstName());
+ assertEquals("Last", result.getContactPerson().getLastName());
+ assertEquals("123-456-789", result.getContactPerson().getPhone());
+ }
+
+ @Test
+ @Transactional
+ public void whenFindingCompanyByContactPersonAttribute_thenCompanyIsReturnedProperly() {
+ ContactPerson contactPerson = new ContactPerson();
+ contactPerson.setFirstName("Name");
+ contactPerson.setLastName("Last");
+ contactPerson.setPhone("123-456-789");
+
+ Company company = new Company();
+ company.setName("Company");
+ company.setAddress("1st street");
+ company.setPhone("987-654-321");
+ company.setContactPerson(contactPerson);
+
+ companyRepository.save(company);
+
+ List result = companyRepository.findByContactPersonFirstName("Name");
+
+ assertEquals(1, result.size());
+
+ result = companyRepository.findByContactPersonFirstName("FirstName");
+
+ assertEquals(0, result.size());
+ }
+
+ @Test
+ @Transactional
+ public void whenFindingCompanyByContactPersonAttributeWithJPQL_thenCompanyIsReturnedProperly() {
+ ContactPerson contactPerson = new ContactPerson();
+ contactPerson.setFirstName("@QueryName");
+ contactPerson.setLastName("Last");
+ contactPerson.setPhone("123-456-789");
+
+ Company company = new Company();
+ company.setName("Company");
+ company.setAddress("1st street");
+ company.setPhone("987-654-321");
+ company.setContactPerson(contactPerson);
+
+ companyRepository.save(company);
+
+ List result = companyRepository.findByContactPersonFirstNameWithJPQL("@QueryName");
+
+ assertEquals(1, result.size());
+
+ result = companyRepository.findByContactPersonFirstNameWithJPQL("FirstName");
+
+ assertEquals(0, result.size());
+ }
+
+ @Test
+ @Transactional
+ public void whenFindingCompanyByContactPersonAttributeWithNativeQuery_thenCompanyIsReturnedProperly() {
+ ContactPerson contactPerson = new ContactPerson();
+ contactPerson.setFirstName("NativeQueryName");
+ contactPerson.setLastName("Last");
+ contactPerson.setPhone("123-456-789");
+
+ Company company = new Company();
+ company.setName("Company");
+ company.setAddress("1st street");
+ company.setPhone("987-654-321");
+ company.setContactPerson(contactPerson);
+
+ companyRepository.save(company);
+
+ List result = companyRepository.findByContactPersonFirstNameWithNativeQuery("NativeQueryName");
+
+ assertEquals(1, result.size());
+
+ result = companyRepository.findByContactPersonFirstNameWithNativeQuery("FirstName");
+
+ assertEquals(0, result.size());
+ }
+}
diff --git a/persistence-modules/spring-data-jpa-2/src/test/java/com/baeldung/joins/JpaJoinsIntegrationTest.java b/persistence-modules/spring-data-jpa-2/src/test/java/com/baeldung/joins/JpaJoinsIntegrationTest.java
new file mode 100644
index 0000000000..9b0d23f3e4
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-2/src/test/java/com/baeldung/joins/JpaJoinsIntegrationTest.java
@@ -0,0 +1,142 @@
+package com.baeldung.joins;
+
+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;
+import javax.persistence.TypedQuery;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
+import org.springframework.test.context.ActiveProfiles;
+import org.springframework.test.context.junit4.SpringRunner;
+
+@RunWith(SpringRunner.class)
+@DataJpaTest
+@ActiveProfiles("joins")
+public class JpaJoinsIntegrationTest {
+
+ @PersistenceContext
+ private EntityManager entityManager;
+
+ @Test
+ public void whenPathExpressionIsUsedForSingleValuedAssociation_thenCreatesImplicitInnerJoin() {
+ TypedQuery query = entityManager.createQuery("SELECT e.department FROM Employee e", Department.class);
+
+ List resultList = query.getResultList();
+
+ assertThat(resultList).hasSize(3);
+ assertThat(resultList).extracting("name")
+ .containsOnly("Infra", "Accounting", "Accounting");
+ }
+
+ @Test
+ public void whenJoinKeywordIsUsed_thenCreatesExplicitInnerJoin() {
+ TypedQuery query = entityManager.createQuery("SELECT d FROM Employee e JOIN e.department d", Department.class);
+
+ List resultList = query.getResultList();
+
+ assertThat(resultList).hasSize(3);
+ assertThat(resultList).extracting("name")
+ .containsOnly("Infra", "Accounting", "Accounting");
+ }
+
+ @Test
+ public void whenInnerJoinKeywordIsUsed_thenCreatesExplicitInnerJoin() {
+ TypedQuery query = entityManager.createQuery("SELECT d FROM Employee e INNER JOIN e.department d", Department.class);
+
+ List resultList = query.getResultList();
+
+ assertThat(resultList).hasSize(3);
+ assertThat(resultList).extracting("name")
+ .containsOnly("Infra", "Accounting", "Accounting");
+ }
+
+ @Test
+ public void whenEntitiesAreListedInFromAndMatchedInWhere_ThenCreatesJoin() {
+ TypedQuery query = entityManager.createQuery("SELECT d FROM Employee e, Department d WHERE e.department = d", Department.class);
+
+ List resultList = query.getResultList();
+
+ assertThat(resultList).hasSize(3);
+ assertThat(resultList).extracting("name")
+ .containsOnly("Infra", "Accounting", "Accounting");
+ }
+
+ @Test
+ public void whenEntitiesAreListedInFrom_ThenCreatesCartesianProduct() {
+ TypedQuery query = entityManager.createQuery("SELECT d FROM Employee e, Department d", Department.class);
+
+ List resultList = query.getResultList();
+
+ assertThat(resultList).hasSize(9);
+ assertThat(resultList).extracting("name")
+ .containsOnly("Infra", "Accounting", "Management", "Infra", "Accounting", "Management", "Infra", "Accounting", "Management");
+ }
+
+ @Test
+ public void whenCollectionValuedAssociationIsJoined_ThenCanSelect() {
+ TypedQuery query = entityManager.createQuery("SELECT ph FROM Employee e JOIN e.phones ph WHERE ph LIKE '1%'", Phone.class);
+
+ List resultList = query.getResultList();
+
+ assertThat(resultList).hasSize(1);
+ }
+
+ @Test
+ public void whenMultipleEntitiesAreListedWithJoin_ThenCreatesMultipleJoins() {
+ TypedQuery query = entityManager.createQuery("SELECT ph FROM Employee e JOIN e.department d JOIN e.phones ph WHERE d.name IS NOT NULL", Phone.class);
+
+ List resultList = query.getResultList();
+
+ assertThat(resultList).hasSize(3);
+ assertThat(resultList).extracting("number")
+ .containsOnly("111", "222", "333");
+ }
+
+ @Test
+ public void whenLeftKeywordIsSpecified_thenCreatesOuterJoinAndIncludesNonMatched() {
+ TypedQuery query = entityManager.createQuery("SELECT DISTINCT d FROM Department d LEFT JOIN d.employees e", Department.class);
+
+ List resultList = query.getResultList();
+
+ assertThat(resultList).hasSize(3);
+ assertThat(resultList).extracting("name")
+ .containsOnly("Infra", "Accounting", "Management");
+ }
+
+ @Test
+ public void whenFetchKeywordIsSpecified_ThenCreatesFetchJoin() {
+ TypedQuery query = entityManager.createQuery("SELECT d FROM Department d JOIN FETCH d.employees", Department.class);
+
+ List resultList = query.getResultList();
+
+ assertThat(resultList).hasSize(3);
+ assertThat(resultList).extracting("name")
+ .containsOnly("Infra", "Accounting", "Accounting");
+ }
+
+ @Test
+ public void whenLeftAndFetchKeywordsAreSpecified_ThenCreatesOuterFetchJoin() {
+ TypedQuery query = entityManager.createQuery("SELECT d FROM Department d LEFT JOIN FETCH d.employees", Department.class);
+
+ List resultList = query.getResultList();
+
+ assertThat(resultList).hasSize(4);
+ assertThat(resultList).extracting("name")
+ .containsOnly("Infra", "Accounting", "Accounting", "Management");
+ }
+
+ @Test
+ public void whenCollectionValuedAssociationIsSpecifiedInSelect_ThenReturnsCollections() {
+ TypedQuery query = entityManager.createQuery("SELECT e.phones FROM Employee e", Collection.class);
+
+ List resultList = query.getResultList();
+
+ assertThat(resultList).extracting("number").containsOnly("111", "222", "333");
+ }
+}
diff --git a/persistence-modules/spring-data-jpa-2/src/test/java/com/baeldung/projection/JpaProjectionIntegrationTest.java b/persistence-modules/spring-data-jpa-2/src/test/java/com/baeldung/projection/JpaProjectionIntegrationTest.java
new file mode 100644
index 0000000000..96eaf4ed07
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-2/src/test/java/com/baeldung/projection/JpaProjectionIntegrationTest.java
@@ -0,0 +1,63 @@
+package com.baeldung.projection;
+
+import com.baeldung.projection.model.Person;
+import com.baeldung.projection.repository.AddressRepository;
+import com.baeldung.projection.repository.PersonRepository;
+import com.baeldung.projection.view.AddressView;
+import com.baeldung.projection.view.PersonDto;
+import com.baeldung.projection.view.PersonView;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
+import org.springframework.test.context.jdbc.Sql;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.springframework.test.context.jdbc.Sql.ExecutionPhase.AFTER_TEST_METHOD;
+
+@DataJpaTest
+@RunWith(SpringRunner.class)
+@Sql(scripts = "/projection-insert-data.sql")
+@Sql(scripts = "/projection-clean-up-data.sql", executionPhase = AFTER_TEST_METHOD)
+public class JpaProjectionIntegrationTest {
+ @Autowired
+ private AddressRepository addressRepository;
+
+ @Autowired
+ private PersonRepository personRepository;
+
+ @Test
+ public void whenUsingClosedProjections_thenViewWithRequiredPropertiesIsReturned() {
+ AddressView addressView = addressRepository.getAddressByState("CA").get(0);
+ assertThat(addressView.getZipCode()).isEqualTo("90001");
+
+ PersonView personView = addressView.getPerson();
+ assertThat(personView.getFirstName()).isEqualTo("John");
+ assertThat(personView.getLastName()).isEqualTo("Doe");
+ }
+
+ @Test
+ public void whenUsingOpenProjections_thenViewWithRequiredPropertiesIsReturned() {
+ PersonView personView = personRepository.findByLastName("Doe");
+ assertThat(personView.getFullName()).isEqualTo("John Doe");
+ }
+
+ @Test
+ public void whenUsingClassBasedProjections_thenDtoWithRequiredPropertiesIsReturned() {
+ PersonDto personDto = personRepository.findByFirstName("John");
+ assertThat(personDto.getFirstName()).isEqualTo("John");
+ assertThat(personDto.getLastName()).isEqualTo("Doe");
+ }
+
+ @Test
+ public void whenUsingDynamicProjections_thenObjectWithRequiredPropertiesIsReturned() {
+ Person person = personRepository.findByLastName("Doe", Person.class);
+ PersonView personView = personRepository.findByLastName("Doe", PersonView.class);
+ PersonDto personDto = personRepository.findByLastName("Doe", PersonDto.class);
+
+ assertThat(person.getFirstName()).isEqualTo("John");
+ assertThat(personView.getFirstName()).isEqualTo("John");
+ assertThat(personDto.getFirstName()).isEqualTo("John");
+ }
+}
diff --git a/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/customer/CustomerRepositoryIntegrationTest.java b/persistence-modules/spring-data-jpa-2/src/test/java/com/baeldung/repository/CustomerRepositoryIntegrationTest.java
similarity index 83%
rename from persistence-modules/spring-data-jpa/src/test/java/com/baeldung/customer/CustomerRepositoryIntegrationTest.java
rename to persistence-modules/spring-data-jpa-2/src/test/java/com/baeldung/repository/CustomerRepositoryIntegrationTest.java
index c3bd821f52..5d6457ce30 100644
--- a/persistence-modules/spring-data-jpa/src/test/java/com/baeldung/customer/CustomerRepositoryIntegrationTest.java
+++ b/persistence-modules/spring-data-jpa-2/src/test/java/com/baeldung/repository/CustomerRepositoryIntegrationTest.java
@@ -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 {
diff --git a/persistence-modules/spring-data-jpa-2/src/test/java/com/baeldung/repository/FruitPopulatorTest.java b/persistence-modules/spring-data-jpa-2/src/test/java/com/baeldung/repository/FruitPopulatorTest.java
new file mode 100644
index 0000000000..29ef52dcef
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-2/src/test/java/com/baeldung/repository/FruitPopulatorTest.java
@@ -0,0 +1,38 @@
+package com.baeldung.repository;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.List;
+
+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 com.baeldung.entity.Fruit;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest
+public class FruitPopulatorTest {
+
+ @Autowired
+ private FruitRepository fruitRepository;
+
+ @Test
+ public void givenFruitJsonPopulatorThenShouldInsertRecordOnStart() {
+
+ List fruits = fruitRepository.findAll();
+ assertEquals("record count is not matching", 2, fruits.size());
+
+ fruits.forEach(fruit -> {
+ if (1 == fruit.getId()) {
+ assertEquals("apple", fruit.getName());
+ assertEquals("red", fruit.getColor());
+ } else if (2 == fruit.getId()) {
+ assertEquals("guava", fruit.getName());
+ assertEquals("green", fruit.getColor());
+ }
+ });
+ }
+}
diff --git a/persistence-modules/spring-data-jpa-2/src/test/resources/projection-clean-up-data.sql b/persistence-modules/spring-data-jpa-2/src/test/resources/projection-clean-up-data.sql
new file mode 100644
index 0000000000..d34f6f0636
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-2/src/test/resources/projection-clean-up-data.sql
@@ -0,0 +1,2 @@
+DELETE FROM address;
+DELETE FROM person;
\ No newline at end of file
diff --git a/persistence-modules/spring-data-jpa-2/src/test/resources/projection-insert-data.sql b/persistence-modules/spring-data-jpa-2/src/test/resources/projection-insert-data.sql
new file mode 100644
index 0000000000..544dcc4b88
--- /dev/null
+++ b/persistence-modules/spring-data-jpa-2/src/test/resources/projection-insert-data.sql
@@ -0,0 +1,2 @@
+INSERT INTO person(id,first_name,last_name) VALUES (1,'John','Doe');
+INSERT INTO address(id,person_id,state,city,street,zip_code) VALUES (1,1,'CA', 'Los Angeles', 'Standford Ave', '90001');
\ No newline at end of file
diff --git a/persistence-modules/spring-data-jpa/README.md b/persistence-modules/spring-data-jpa/README.md
index 48c3180262..4e390c2faf 100644
--- a/persistence-modules/spring-data-jpa/README.md
+++ b/persistence-modules/spring-data-jpa/README.md
@@ -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)
diff --git a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/passenger/PassengerRepository.java b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/passenger/PassengerRepository.java
index b2d145899e..6c6c145942 100644
--- a/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/passenger/PassengerRepository.java
+++ b/persistence-modules/spring-data-jpa/src/main/java/com/baeldung/passenger/PassengerRepository.java
@@ -9,6 +9,8 @@ interface PassengerRepository extends JpaRepository, CustomPass
Passenger findFirstByOrderBySeatNumberAsc();
+ Passenger findTopByOrderBySeatNumberAsc();
+
List findByOrderBySeatNumberAsc();
List findByLastNameOrderBySeatNumberAsc(String lastName);
diff --git a/pom.xml b/pom.xml
index e74c5cd670..64710a39a6 100644
--- a/pom.xml
+++ b/pom.xml
@@ -9,7 +9,7 @@
1.0.0-SNAPSHOT
parent-modules
pom
-
+
lombok-custom
@@ -233,7 +233,7 @@
${maven-war-plugin.version}
-
+
com.vackosar.gitflowincrementalbuilder
@@ -376,15 +376,20 @@
cdi
checker-plugin
core-groovy
+ core-groovy-2
-
+
core-java-8
+ core-java-8-2
+ core-java-lambdas
core-java-arrays
core-java-collections
+ core-java-collections-map
core-java-collections-list
+ core-java-collections-set
core-java-concurrency-basic
core-java-concurrency-collections
core-java-io
@@ -393,6 +398,7 @@
core-java-lang
core-java-lang-oop
core-java-lang-oop-2
+ core-java-modules
core-java-networking
core-java-perf
core-java-sun
@@ -401,7 +407,7 @@
core-scala
couchbase
custom-pmd
-
+
dagger
data-structures
ddd
@@ -409,13 +415,13 @@
disruptor
dozer
drools
- dubbo
-
+ dubbo
+
ethereum
-
+
feign
flyway-cdi-extension
-
+
geotools
google-cloud
google-web-toolkit
@@ -429,17 +435,19 @@
guava-modules
guice
-
+
hazelcast
helidon
httpclient
+ httpclient-simple
hystrix
-
+
image-processing
immutables
jackson
jackson-2
+ jackson-simple
java-collections-conversions
java-collections-maps
java-collections-maps-2
@@ -481,10 +489,10 @@
kotlin-libraries
-
+
libraries
- libraries2
+ libraries-2
libraries-data
libraries-apache-commons
libraries-security
@@ -508,8 +516,8 @@
mustache
mybatis
-
-
+
+
optaplanner
orika
osgi
@@ -519,9 +527,9 @@
performance-tests
protobuffer
-
+
persistence-modules
-
+
rabbitmq
ratpack
@@ -533,15 +541,17 @@
rule-engines
rsocket
rxjava
- rxjava-2
+ rxjava-2
software-security/sql-injection-samples
-
+
tensorflow-java
-
+ spring-boot-flowable
+ spring-security-kerberos
+
-
+
default-second
@@ -575,14 +585,15 @@
parent-spring-5
parent-java
parent-kotlin
-
+
saas
spark-java
-
+
spring-4
-
+
spring-5
spring-5-webflux
+ spring-5-data-reactive
spring-5-mvc
spring-5-reactive
spring-5-reactive-client
@@ -590,16 +601,17 @@
spring-5-reactive-security
spring-5-security
spring-5-security-oauth
-
+
spring-activiti
spring-akka
spring-all
spring-amqp
+ spring-amqp-simple
spring-aop
spring-apache-camel
spring-batch
spring-bom
-
+
spring-boot
spring-boot-admin
spring-boot-angular
@@ -609,6 +621,7 @@
spring-boot-camel
spring-boot-client
+ spring-boot-configuration
spring-boot-crud
spring-boot-ctx-fluent
spring-boot-custom-starter
@@ -618,6 +631,7 @@
spring-boot-keycloak
spring-boot-logging-log4j2
spring-boot-mvc
+ spring-boot-mvc-birt
spring-boot-ops
spring-boot-rest
spring-boot-data
@@ -626,41 +640,41 @@
spring-boot-testing
spring-boot-vue
spring-boot-libraries
-
+
spring-cloud
spring-cloud-bus
spring-cloud-data-flow
-
+
spring-core
spring-cucumber
-
+
spring-data-rest
spring-data-rest-querydsl
spring-dispatcher-servlet
spring-drools
-
+
spring-ehcache
spring-ejb
spring-exceptions
-
+
spring-freemarker
-
+
spring-groovy
-
+
spring-integration
-
+
spring-jenkins-pipeline
spring-jersey
spring-jinq
spring-jms
spring-jooq
-
+
spring-kafka
spring-katharsis
-
+
spring-ldap
-
+
spring-mobile
spring-mockito
spring-mvc-forms-jsp
@@ -672,12 +686,12 @@
spring-mvc-velocity
spring-mvc-webflow
spring-mvc-xml
-
+
spring-protobuf
-
+
spring-quartz
-
+
spring-reactive-kotlin
spring-reactor
spring-remoting
@@ -693,9 +707,9 @@
spring-security-acl
spring-security-angular/server
spring-security-cache-control
-
+
spring-security-client
-
+
spring-security-core
spring-security-mvc-boot
spring-security-mvc-custom
@@ -723,48 +737,50 @@
spring-state-machine
spring-static-resources
spring-swagger-codegen
-
+
spring-thymeleaf
-
+
spring-userservice
-
+
spring-vault
spring-vertx
-
+
spring-webflux-amqp
-
+
spring-zuul
-
+
static-analysis
stripe
structurizr
struts-2
-
+
testing-modules
-
+
twilio
Twitter4J
-
+
undertow
-
+
vavr
vertx
vertx-and-rxjava
video-tutorials
vraptor
-
+
wicket
-
+
xml
xmlunit-2
xstream
-
+
tensorflow-java
-
+ spring-boot-flowable
+ spring-security-kerberos
+
-
+
spring-context
@@ -806,6 +822,7 @@
spring-boot-bootstrap
spring-boot-camel
spring-boot-client
+ spring-boot-configuration
spring-boot-custom-starter
greeter-spring-boot-autoconfigure
greeter-spring-boot-sample-app
@@ -902,6 +919,9 @@
persistence-modules/spring-data-eclipselink
persistence-modules/spring-data-solr
persistence-modules/spring-hibernate-5
+
+ spring-boot-flowable
+ spring-security-kerberos
@@ -939,10 +959,11 @@
parent-spring-5
parent-java
parent-kotlin
-
+
core-java-concurrency-advanced
core-kotlin
core-kotlin-2
+ core-kotlin-io
jenkins/hello-world
jws
@@ -950,17 +971,15 @@
libraries
persistence-modules/hibernate5
+ persistence-modules/hibernate-mapping
persistence-modules/java-jpa
persistence-modules/java-mongodb
- persistence-modules/jnosql
+ persistence-modules/jnosql
- spring-5-data-reactive
- spring-amqp-simple
-
- vaadin
+ vaadin
-
+
integration-lite-first
@@ -1031,14 +1050,18 @@
cdi
checker-plugin
core-groovy
+ core-groovy-2
-
+
core-java-8
+ core-java-8-2
core-java-arrays
core-java-collections
+ core-java-collections-map
core-java-collections-list
+ core-java-collections-set
core-java-concurrency-basic
core-java-concurrency-collections
core-java-io
@@ -1047,13 +1070,14 @@
core-java-lang
core-java-lang-oop
core-java-lang-oop-2
+ core-java-modules
core-java-networking
core-java-perf
core-java-sun
core-scala
couchbase
custom-pmd
-
+
dagger
data-structures
ddd
@@ -1061,13 +1085,13 @@
disruptor
dozer
drools
- dubbo
-
+ dubbo
+
ethereum
-
+
feign
flyway-cdi-extension
-
+
geotools
google-cloud
google-web-toolkit
@@ -1081,17 +1105,19 @@
guava-modules
guice
-
+
hazelcast
helidon
httpclient
+ httpclient-simple
hystrix
-
+
image-processing
immutables
jackson
jackson-2
+ jackson-simple
java-collections-conversions
java-collections-maps
java-collections-maps-2
@@ -1132,7 +1158,7 @@
kotlin-libraries
-
+
libraries
libraries-data
@@ -1146,6 +1172,7 @@
mapstruct
maven
+ maven-java-11
maven-archetype
maven-polyglot/maven-polyglot-json-extension
@@ -1158,8 +1185,8 @@
mustache
mybatis
-
-
+
+
optaplanner
orika
osgi
@@ -1169,9 +1196,9 @@
performance-tests
protobuffer
-
+
persistence-modules
-
+
rabbitmq
ratpack
@@ -1183,8 +1210,8 @@
rule-engines
rsocket
rxjava
- rxjava-2
-
+ rxjava-2
+
@@ -1218,13 +1245,14 @@
parent-spring-5
parent-java
parent-kotlin
-
+
saas
spark-java
-
+
spring-4
-
+
spring-5
+ spring-5-data-reactive
spring-5-mvc
spring-5-reactive
spring-5-reactive-client
@@ -1232,16 +1260,17 @@
spring-5-reactive-security
spring-5-security
spring-5-security-oauth
-
+
spring-activiti
spring-akka
spring-all
spring-amqp
+ spring-amqp-simple
spring-aop
spring-apache-camel
spring-batch
spring-bom
-
+
spring-boot
spring-boot-admin
spring-boot-angular
@@ -1251,6 +1280,7 @@
spring-boot-camel
spring-boot-client
+ spring-boot-configuration
spring-boot-crud
spring-boot-ctx-fluent
spring-boot-custom-starter
@@ -1260,47 +1290,48 @@
spring-boot-keycloak
spring-boot-logging-log4j2
spring-boot-mvc
+ spring-boot-mvc-birt
spring-boot-ops
spring-boot-rest
spring-boot-data
spring-boot-property-exp
spring-boot-security
spring-boot-vue
-
+
spring-cloud
spring-cloud-bus
spring-cloud-data-flow
-
+
spring-core
spring-cucumber
-
+
spring-data-rest
spring-data-rest-querydsl
spring-dispatcher-servlet
spring-drools
-
- spring-ehcache
+
+ spring-ehcache
spring-ejb
spring-exceptions
-
+
spring-freemarker
-
+
spring-groovy
-
+
spring-integration
-
+
spring-jenkins-pipeline
spring-jersey
spring-jinq
spring-jms
spring-jooq
-
+
spring-kafka
spring-katharsis
-
+
spring-ldap
-
+
spring-mobile
spring-mockito
spring-mvc-forms-jsp
@@ -1312,12 +1343,12 @@
spring-mvc-velocity
spring-mvc-webflow
spring-mvc-xml
-
+
spring-protobuf
-
+
spring-quartz
-
+
spring-reactive-kotlin
spring-reactor
spring-remoting
@@ -1330,13 +1361,13 @@
spring-rest-simple
spring-resttemplate
spring-roo
-
+
spring-security-acl
spring-security-angular/server
spring-security-cache-control
-
+
spring-security-client
-
+
spring-security-core
spring-security-mvc-boot
spring-security-mvc-custom
@@ -1363,42 +1394,42 @@
spring-state-machine
spring-static-resources
spring-swagger-codegen
-
+
spring-thymeleaf
-
+
spring-userservice
-
+
spring-vault
spring-vertx
-
+
spring-webflux-amqp
-
+
spring-zuul
-
+
static-analysis
stripe
structurizr
struts-2
-
+
testing-modules
-
+
twilio
Twitter4J
-
+
undertow
-
+
vavr
vertx
vertx-and-rxjava
video-tutorials
vraptor
-
+
wicket
-
+
xml
xmlunit-2
xstream
-
+
@@ -1432,8 +1463,8 @@
parent-spring-5
parent-java
parent-kotlin
-
- core-java
+
+ core-java
core-java-concurrency-advanced
core-kotlin
core-kotlin-2
@@ -1446,12 +1477,9 @@
persistence-modules/hibernate5
persistence-modules/java-jpa
persistence-modules/java-mongodb
- persistence-modules/jnosql
+ persistence-modules/jnosql
- spring-5-data-reactive
- spring-amqp-simple
-
- vaadin
+ vaadin
@@ -1472,20 +1500,21 @@
UTF-8
UTF-8
- refs/remotes/origin/master
- true
+ refs/remotes/origin/master
+ true
+ false
false
false
false
-
+
4.12
1.3
2.21.0
-
+
1.7.21
1.1.7
-
+
2.21.0
3.7.0
@@ -1514,7 +1543,7 @@
0.3.1
2.5.1
0.0.1
- 3.4
+ 3.8
2.3
3.8
diff --git a/rxjava-2/README.md b/rxjava-2/README.md
index d0bdeec684..4182f3fa00 100644
--- a/rxjava-2/README.md
+++ b/rxjava-2/README.md
@@ -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)
diff --git a/spring-5-data-reactive/src/test/java/com/baeldung/reactive/repository/AccountCrudRepositoryIntegrationTest.java b/spring-5-data-reactive/src/test/java/com/baeldung/reactive/repository/AccountCrudRepositoryManualTest.java
similarity index 97%
rename from spring-5-data-reactive/src/test/java/com/baeldung/reactive/repository/AccountCrudRepositoryIntegrationTest.java
rename to spring-5-data-reactive/src/test/java/com/baeldung/reactive/repository/AccountCrudRepositoryManualTest.java
index f425826dce..d4b1d0eeda 100644
--- a/spring-5-data-reactive/src/test/java/com/baeldung/reactive/repository/AccountCrudRepositoryIntegrationTest.java
+++ b/spring-5-data-reactive/src/test/java/com/baeldung/reactive/repository/AccountCrudRepositoryManualTest.java
@@ -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;
diff --git a/spring-5-data-reactive/src/test/java/com/baeldung/reactive/repository/AccountMongoRepositoryIntegrationTest.java b/spring-5-data-reactive/src/test/java/com/baeldung/reactive/repository/AccountMongoRepositoryManualTest.java
similarity index 97%
rename from spring-5-data-reactive/src/test/java/com/baeldung/reactive/repository/AccountMongoRepositoryIntegrationTest.java
rename to spring-5-data-reactive/src/test/java/com/baeldung/reactive/repository/AccountMongoRepositoryManualTest.java
index bfa6a789b2..2ca075aa5e 100644
--- a/spring-5-data-reactive/src/test/java/com/baeldung/reactive/repository/AccountMongoRepositoryIntegrationTest.java
+++ b/spring-5-data-reactive/src/test/java/com/baeldung/reactive/repository/AccountMongoRepositoryManualTest.java
@@ -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;
diff --git a/spring-5-data-reactive/src/test/java/com/baeldung/reactive/repository/AccountRxJavaRepositoryIntegrationTest.java b/spring-5-data-reactive/src/test/java/com/baeldung/reactive/repository/AccountRxJavaRepositoryManualTest.java
similarity index 97%
rename from spring-5-data-reactive/src/test/java/com/baeldung/reactive/repository/AccountRxJavaRepositoryIntegrationTest.java
rename to spring-5-data-reactive/src/test/java/com/baeldung/reactive/repository/AccountRxJavaRepositoryManualTest.java
index e9b3eb1c40..d91acd24e2 100644
--- a/spring-5-data-reactive/src/test/java/com/baeldung/reactive/repository/AccountRxJavaRepositoryIntegrationTest.java
+++ b/spring-5-data-reactive/src/test/java/com/baeldung/reactive/repository/AccountRxJavaRepositoryManualTest.java
@@ -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;
diff --git a/spring-5-data-reactive/src/test/java/com/baeldung/reactive/template/AccountTemplateOperationsIntegrationTest.java b/spring-5-data-reactive/src/test/java/com/baeldung/reactive/template/AccountTemplateOperationsManualTest.java
similarity index 97%
rename from spring-5-data-reactive/src/test/java/com/baeldung/reactive/template/AccountTemplateOperationsIntegrationTest.java
rename to spring-5-data-reactive/src/test/java/com/baeldung/reactive/template/AccountTemplateOperationsManualTest.java
index 373da0e393..5fa0e39317 100644
--- a/spring-5-data-reactive/src/test/java/com/baeldung/reactive/template/AccountTemplateOperationsIntegrationTest.java
+++ b/spring-5-data-reactive/src/test/java/com/baeldung/reactive/template/AccountTemplateOperationsManualTest.java
@@ -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;
diff --git a/spring-5-security-oauth/README.md b/spring-5-security-oauth/README.md
index 5a444d4784..a5cec370c7 100644
--- a/spring-5-security-oauth/README.md
+++ b/spring-5-security-oauth/README.md
@@ -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)
diff --git a/spring-5-security-oauth/src/main/java/com/baeldung/cognito/CognitoWebConfiguration.java b/spring-5-security-oauth/src/main/java/com/baeldung/cognito/CognitoWebConfiguration.java
new file mode 100644
index 0000000000..ae03e0a802
--- /dev/null
+++ b/spring-5-security-oauth/src/main/java/com/baeldung/cognito/CognitoWebConfiguration.java
@@ -0,0 +1,16 @@
+package com.baeldung.cognito;
+
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.PropertySource;
+import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+@Configuration
+@PropertySource("cognito/application_cognito.yml")
+public class CognitoWebConfiguration implements WebMvcConfigurer {
+
+ @Override
+ public void addViewControllers(ViewControllerRegistry registry) {
+ registry.addViewController("/").setViewName("home");
+ }
+}
diff --git a/spring-5-security-oauth/src/main/java/com/baeldung/cognito/SpringCognitoApplication.java b/spring-5-security-oauth/src/main/java/com/baeldung/cognito/SpringCognitoApplication.java
new file mode 100644
index 0000000000..7f7b751cd9
--- /dev/null
+++ b/spring-5-security-oauth/src/main/java/com/baeldung/cognito/SpringCognitoApplication.java
@@ -0,0 +1,14 @@
+package com.baeldung.cognito;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.PropertySource;
+
+@SpringBootApplication
+@PropertySource("cognito/application_cognito.yml")
+public class SpringCognitoApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(SpringCognitoApplication.class, args);
+ }
+}
diff --git a/spring-5-security-oauth/src/main/resources/cognito/application_cognito.yml b/spring-5-security-oauth/src/main/resources/cognito/application_cognito.yml
new file mode 100644
index 0000000000..0a28dbccb4
--- /dev/null
+++ b/spring-5-security-oauth/src/main/resources/cognito/application_cognito.yml
@@ -0,0 +1,15 @@
+spring:
+ security:
+ oauth2:
+ client:
+ registration:
+ cognito:
+ client-id: clientId
+ client-secret: clientSecret
+ scope: openid
+ redirectUriTemplate: "http://localhost:8080/login/oauth2/code/cognito"
+ clientName: cognito-client-name
+ provider:
+ cognito:
+ issuerUri: https://cognito-idp.{region}.amazonaws.com/{poolId}
+ usernameAttribute: cognito:username
diff --git a/spring-5-security-oauth/src/main/resources/cognito/home.html b/spring-5-security-oauth/src/main/resources/cognito/home.html
new file mode 100644
index 0000000000..f0bd9e52a8
--- /dev/null
+++ b/spring-5-security-oauth/src/main/resources/cognito/home.html
@@ -0,0 +1,32 @@
+
+
+
+
+
+ OAuth2 Cognito Demo
+
+
+
+
+
+
+
+
+
OAuth2 Spring Security Cognito Demo
+
+
+
+
+
+
+
+
+
diff --git a/spring-5-security-oauth/src/main/resources/cognito/style.css b/spring-5-security-oauth/src/main/resources/cognito/style.css
new file mode 100644
index 0000000000..45190d6d70
--- /dev/null
+++ b/spring-5-security-oauth/src/main/resources/cognito/style.css
@@ -0,0 +1,9 @@
+.login {
+ background-color: #7289da;
+ color: #fff;
+}
+
+.login:hover {
+ background-color: #697ec4;
+ color: #fff;
+}
diff --git a/spring-5-webflux/README.md b/spring-5-webflux/README.md
new file mode 100644
index 0000000000..84c3d5a4ca
--- /dev/null
+++ b/spring-5-webflux/README.md
@@ -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)
diff --git a/spring-all/README.md b/spring-all/README.md
index a111d2e542..b0805e5477 100644
--- a/spring-all/README.md
+++ b/spring-all/README.md
@@ -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)
diff --git a/spring-batch/README.md b/spring-batch/README.md
index 737e7e13f5..ddd830cd47 100644
--- a/spring-batch/README.md
+++ b/spring-batch/README.md
@@ -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)
diff --git a/spring-boot-configuration/.gitignore b/spring-boot-configuration/.gitignore
new file mode 100644
index 0000000000..153c9335eb
--- /dev/null
+++ b/spring-boot-configuration/.gitignore
@@ -0,0 +1,29 @@
+HELP.md
+/target/
+!.mvn/wrapper/maven-wrapper.jar
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+/build/
+
+### VS Code ###
+.vscode/
diff --git a/spring-boot-configuration/README.MD b/spring-boot-configuration/README.MD
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/spring-boot-configuration/pom.xml b/spring-boot-configuration/pom.xml
new file mode 100644
index 0000000000..2ecef7bb02
--- /dev/null
+++ b/spring-boot-configuration/pom.xml
@@ -0,0 +1,41 @@
+
+
+ 4.0.0
+
+
+ parent-boot-2
+ com.baeldung
+ 0.0.1-SNAPSHOT
+ ../parent-boot-2
+
+
+ com.baeldung
+ spring-boot-configuration
+ 0.0.1-SNAPSHOT
+ spring-boot-configuration
+ Demo project for Spring Boot configuration
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
diff --git a/spring-boot-configuration/src/main/java/com/baeldung/springbootconfiguration/SpringBootConfigurationApplication.java b/spring-boot-configuration/src/main/java/com/baeldung/springbootconfiguration/SpringBootConfigurationApplication.java
new file mode 100644
index 0000000000..b4f5681475
--- /dev/null
+++ b/spring-boot-configuration/src/main/java/com/baeldung/springbootconfiguration/SpringBootConfigurationApplication.java
@@ -0,0 +1,13 @@
+package com.baeldung.springbootconfiguration;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class SpringBootConfigurationApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(SpringBootConfigurationApplication.class, args);
+ }
+
+}
diff --git a/spring-boot-configuration/src/main/resources/application-tomcat.properties b/spring-boot-configuration/src/main/resources/application-tomcat.properties
new file mode 100644
index 0000000000..d7c1ba9ac3
--- /dev/null
+++ b/spring-boot-configuration/src/main/resources/application-tomcat.properties
@@ -0,0 +1,23 @@
+# server configuration
+server.port=80
+server.address=127.0.0.1
+
+## Error handling configuration
+server.error.whitelabel.enabled=true
+server.error.path=/user-error
+server.error.include-exception=true
+server.error.include-stacktrace=always
+
+## Server connections configuration
+server.tomcat.max-threads=200
+server.connection-timeout=5s
+server.max-http-header-size=8KB
+server.tomcat.max-swallow-size=2MB
+server.tomcat.max-http-post-size=2MB
+
+## Access logs configuration
+server.tomcat.accesslog.enabled=true
+server.tomcat.accesslog.directory=logs
+server.tomcat.accesslog.file-date-format=yyyy-MM-dd
+server.tomcat.accesslog.prefix=access_log
+server.tomcat.accesslog.suffix=.log
diff --git a/spring-boot-configuration/src/main/resources/application.properties b/spring-boot-configuration/src/main/resources/application.properties
new file mode 100644
index 0000000000..8b13789179
--- /dev/null
+++ b/spring-boot-configuration/src/main/resources/application.properties
@@ -0,0 +1 @@
+
diff --git a/spring-boot-configuration/src/test/java/com/baeldung/springbootconfiguration/SpringContextIntegrationTest.java b/spring-boot-configuration/src/test/java/com/baeldung/springbootconfiguration/SpringContextIntegrationTest.java
new file mode 100644
index 0000000000..d6b2b50a2f
--- /dev/null
+++ b/spring-boot-configuration/src/test/java/com/baeldung/springbootconfiguration/SpringContextIntegrationTest.java
@@ -0,0 +1,16 @@
+package com.baeldung.springbootconfiguration;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest
+public class SpringContextIntegrationTest {
+
+ @Test
+ public void contextLoads() {
+ }
+
+}
diff --git a/spring-boot-data/README.md b/spring-boot-data/README.md
index 21f7303c48..d93b8c3e93 100644
--- a/spring-boot-data/README.md
+++ b/spring-boot-data/README.md
@@ -1,2 +1,2 @@
### Relevant Articles:
-- [Formatting JSON Dates in Spring ](https://www.baeldung.com/spring-boot-formatting-json-dates)
\ No newline at end of file
+- [Formatting JSON Dates in Spring Boot](https://www.baeldung.com/spring-boot-formatting-json-dates)
diff --git a/spring-boot-exceptions/pass-exception-to-client-json-spring-boot/.gitignore b/spring-boot-exceptions/pass-exception-to-client-json-spring-boot/.gitignore
new file mode 100644
index 0000000000..153c9335eb
--- /dev/null
+++ b/spring-boot-exceptions/pass-exception-to-client-json-spring-boot/.gitignore
@@ -0,0 +1,29 @@
+HELP.md
+/target/
+!.mvn/wrapper/maven-wrapper.jar
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+/build/
+
+### VS Code ###
+.vscode/
diff --git a/spring-boot-exceptions/pass-exception-to-client-json-spring-boot/pom.xml b/spring-boot-exceptions/pass-exception-to-client-json-spring-boot/pom.xml
new file mode 100644
index 0000000000..8237955aef
--- /dev/null
+++ b/spring-boot-exceptions/pass-exception-to-client-json-spring-boot/pom.xml
@@ -0,0 +1,43 @@
+
+
+ 4.0.0
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.1.4.RELEASE
+
+
+ com.baeldung
+ pass-exception-to-client-json-spring-boot
+ 0.0.4-SNAPSHOT
+ pass-exception-to-client-json-spring-boot
+ Baeldung article code on how to pass exceptions to client in JSON format using Spring Boot
+
+
+ 1.8
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
diff --git a/spring-boot-exceptions/pass-exception-to-client-json-spring-boot/src/main/java/com/baeldung/passexceptiontoclientjsonspringboot/CustomException.java b/spring-boot-exceptions/pass-exception-to-client-json-spring-boot/src/main/java/com/baeldung/passexceptiontoclientjsonspringboot/CustomException.java
new file mode 100644
index 0000000000..56fe80cd9a
--- /dev/null
+++ b/spring-boot-exceptions/pass-exception-to-client-json-spring-boot/src/main/java/com/baeldung/passexceptiontoclientjsonspringboot/CustomException.java
@@ -0,0 +1,11 @@
+package com.baeldung.passexceptiontoclientjsonspringboot;
+
+public class CustomException extends RuntimeException {
+
+ private static final long serialVersionUID = 1L;
+
+ public CustomException() {
+ super("Custom exception message.");
+ }
+
+}
\ No newline at end of file
diff --git a/spring-boot-exceptions/pass-exception-to-client-json-spring-boot/src/main/java/com/baeldung/passexceptiontoclientjsonspringboot/ErrorHandler.java b/spring-boot-exceptions/pass-exception-to-client-json-spring-boot/src/main/java/com/baeldung/passexceptiontoclientjsonspringboot/ErrorHandler.java
new file mode 100644
index 0000000000..b39d2811dd
--- /dev/null
+++ b/spring-boot-exceptions/pass-exception-to-client-json-spring-boot/src/main/java/com/baeldung/passexceptiontoclientjsonspringboot/ErrorHandler.java
@@ -0,0 +1,19 @@
+package com.baeldung.passexceptiontoclientjsonspringboot;
+
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.annotation.ControllerAdvice;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.bind.annotation.ResponseStatus;
+
+@ControllerAdvice
+@ResponseBody
+public class ErrorHandler {
+
+ @ExceptionHandler(CustomException.class)
+ @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
+ public CustomException handleCustomException(CustomException ce) {
+ return ce;
+ }
+
+}
\ No newline at end of file
diff --git a/spring-boot-exceptions/pass-exception-to-client-json-spring-boot/src/main/java/com/baeldung/passexceptiontoclientjsonspringboot/MainController.java b/spring-boot-exceptions/pass-exception-to-client-json-spring-boot/src/main/java/com/baeldung/passexceptiontoclientjsonspringboot/MainController.java
new file mode 100644
index 0000000000..82c0c022a8
--- /dev/null
+++ b/spring-boot-exceptions/pass-exception-to-client-json-spring-boot/src/main/java/com/baeldung/passexceptiontoclientjsonspringboot/MainController.java
@@ -0,0 +1,14 @@
+package com.baeldung.passexceptiontoclientjsonspringboot;
+
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.GetMapping;
+
+@Controller
+public class MainController {
+
+ @GetMapping("/")
+ public void index() throws CustomException {
+ throw new CustomException();
+ }
+
+}
\ No newline at end of file
diff --git a/spring-boot-exceptions/pass-exception-to-client-json-spring-boot/src/main/java/com/baeldung/passexceptiontoclientjsonspringboot/PassExceptionToClientJsonSpringBootApplication.java b/spring-boot-exceptions/pass-exception-to-client-json-spring-boot/src/main/java/com/baeldung/passexceptiontoclientjsonspringboot/PassExceptionToClientJsonSpringBootApplication.java
new file mode 100644
index 0000000000..77833c28fd
--- /dev/null
+++ b/spring-boot-exceptions/pass-exception-to-client-json-spring-boot/src/main/java/com/baeldung/passexceptiontoclientjsonspringboot/PassExceptionToClientJsonSpringBootApplication.java
@@ -0,0 +1,13 @@
+package com.baeldung.passexceptiontoclientjsonspringboot;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class PassExceptionToClientJsonSpringBootApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(PassExceptionToClientJsonSpringBootApplication.class, args);
+ }
+
+}
\ No newline at end of file
diff --git a/spring-boot-exceptions/pass-exception-to-client-json-spring-boot/src/main/resources/application.properties b/spring-boot-exceptions/pass-exception-to-client-json-spring-boot/src/main/resources/application.properties
new file mode 100644
index 0000000000..8b13789179
--- /dev/null
+++ b/spring-boot-exceptions/pass-exception-to-client-json-spring-boot/src/main/resources/application.properties
@@ -0,0 +1 @@
+
diff --git a/spring-boot-exceptions/pass-exception-to-client-json-spring-boot/src/main/resources/static/.gitignore b/spring-boot-exceptions/pass-exception-to-client-json-spring-boot/src/main/resources/static/.gitignore
new file mode 100644
index 0000000000..5e7d2734cf
--- /dev/null
+++ b/spring-boot-exceptions/pass-exception-to-client-json-spring-boot/src/main/resources/static/.gitignore
@@ -0,0 +1,4 @@
+# Ignore everything in this directory
+*
+# Except this file
+!.gitignore
diff --git a/spring-boot-exceptions/pass-exception-to-client-json-spring-boot/src/main/resources/templates/.gitignore b/spring-boot-exceptions/pass-exception-to-client-json-spring-boot/src/main/resources/templates/.gitignore
new file mode 100644
index 0000000000..5e7d2734cf
--- /dev/null
+++ b/spring-boot-exceptions/pass-exception-to-client-json-spring-boot/src/main/resources/templates/.gitignore
@@ -0,0 +1,4 @@
+# Ignore everything in this directory
+*
+# Except this file
+!.gitignore
diff --git a/spring-boot-exceptions/pass-exception-to-client-json-spring-boot/src/test/java/com/baeldung/passexceptiontoclientjsonspringboot/MainControllerIntegrationTest.java b/spring-boot-exceptions/pass-exception-to-client-json-spring-boot/src/test/java/com/baeldung/passexceptiontoclientjsonspringboot/MainControllerIntegrationTest.java
new file mode 100644
index 0000000000..a615dc5096
--- /dev/null
+++ b/spring-boot-exceptions/pass-exception-to-client-json-spring-boot/src/test/java/com/baeldung/passexceptiontoclientjsonspringboot/MainControllerIntegrationTest.java
@@ -0,0 +1,16 @@
+package com.baeldung.passexceptiontoclientjsonspringboot;
+
+import org.junit.Test;
+
+public class MainControllerIntegrationTest {
+
+ @Test(expected = CustomException.class)
+ public void givenIndex_thenCustomException() throws CustomException {
+
+ MainController mainController = new MainController();
+
+ mainController.index();
+
+ }
+
+}
\ No newline at end of file
diff --git a/spring-boot-exceptions/pass-exception-to-client-json-spring-boot/src/test/java/com/baeldung/passexceptiontoclientjsonspringboot/PassExceptionToClientJsonSpringBootApplicationTests.java b/spring-boot-exceptions/pass-exception-to-client-json-spring-boot/src/test/java/com/baeldung/passexceptiontoclientjsonspringboot/PassExceptionToClientJsonSpringBootApplicationTests.java
new file mode 100644
index 0000000000..5e35c21f4c
--- /dev/null
+++ b/spring-boot-exceptions/pass-exception-to-client-json-spring-boot/src/test/java/com/baeldung/passexceptiontoclientjsonspringboot/PassExceptionToClientJsonSpringBootApplicationTests.java
@@ -0,0 +1,16 @@
+package com.baeldung.passexceptiontoclientjsonspringboot;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest
+public class PassExceptionToClientJsonSpringBootApplicationTests {
+
+ @Test
+ public void contextLoads() {
+ }
+
+}
diff --git a/spring-boot-flowable/README.md b/spring-boot-flowable/README.md
new file mode 100644
index 0000000000..8fb90d953b
--- /dev/null
+++ b/spring-boot-flowable/README.md
@@ -0,0 +1,3 @@
+### Relevant articles
+
+- [Introduction to Flowable](http://www.baeldung.com/flowable)
diff --git a/spring-boot-flowable/pom.xml b/spring-boot-flowable/pom.xml
new file mode 100644
index 0000000000..f9531a1e6a
--- /dev/null
+++ b/spring-boot-flowable/pom.xml
@@ -0,0 +1,58 @@
+
+
+ 4.0.0
+ spring-boot-flowable
+ war
+ spring-boot-flowable
+ Spring Boot Flowable Module
+
+ parent-boot-2
+ com.baeldung
+ 0.0.1-SNAPSHOT
+ ../parent-boot-2
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ com.h2database
+ h2
+ runtime
+
+
+ org.flowable
+ flowable-spring-boot-starter-rest
+ ${flowable.version}
+
+
+ org.flowable
+ flowable-spring-boot-starter-actuator
+ ${flowable.version}
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+ org.junit.jupiter
+ junit-jupiter-engine
+ test
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+ 6.4.1
+
+
\ No newline at end of file
diff --git a/spring-boot-flowable/src/main/java/com/baeldung/Application.java b/spring-boot-flowable/src/main/java/com/baeldung/Application.java
new file mode 100644
index 0000000000..37dbe7dab8
--- /dev/null
+++ b/spring-boot-flowable/src/main/java/com/baeldung/Application.java
@@ -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);
+ }
+
+}
diff --git a/spring-boot-flowable/src/main/java/com/baeldung/controller/ArticleWorkflowController.java b/spring-boot-flowable/src/main/java/com/baeldung/controller/ArticleWorkflowController.java
new file mode 100644
index 0000000000..3087d30af4
--- /dev/null
+++ b/spring-boot-flowable/src/main/java/com/baeldung/controller/ArticleWorkflowController.java
@@ -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 getTasks(@RequestParam String assignee) {
+ return service.getTasks(assignee);
+ }
+ @PostMapping("/review")
+ public void review(@RequestBody Approval approval) {
+ service.submitReview(approval);
+ }
+}
\ No newline at end of file
diff --git a/spring-boot-flowable/src/main/java/com/baeldung/domain/Approval.java b/spring-boot-flowable/src/main/java/com/baeldung/domain/Approval.java
new file mode 100644
index 0000000000..b0c9c99437
--- /dev/null
+++ b/spring-boot-flowable/src/main/java/com/baeldung/domain/Approval.java
@@ -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;
+ }
+
+}
diff --git a/spring-boot-flowable/src/main/java/com/baeldung/domain/Article.java b/spring-boot-flowable/src/main/java/com/baeldung/domain/Article.java
new file mode 100644
index 0000000000..efa2eb431e
--- /dev/null
+++ b/spring-boot-flowable/src/main/java/com/baeldung/domain/Article.java
@@ -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 + "]");
+ }
+
+}
diff --git a/spring-boot-flowable/src/main/java/com/baeldung/service/ArticleWorkflowService.java b/spring-boot-flowable/src/main/java/com/baeldung/service/ArticleWorkflowService.java
new file mode 100644
index 0000000000..b1e2a92354
--- /dev/null
+++ b/spring-boot-flowable/src/main/java/com/baeldung/service/ArticleWorkflowService.java
@@ -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 variables = new HashMap();
+ variables.put("author", article.getAuthor());
+ variables.put("url", article.getUrl());
+ runtimeService.startProcessInstanceByKey("articleReview", variables);
+ }
+
+ @Transactional
+ public List getTasks(String assignee) {
+ List tasks = taskService.createTaskQuery()
+ .taskCandidateGroup(assignee)
+ .list();
+
+ List articles = tasks.stream()
+ .map(task -> {
+ Map 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 variables = new HashMap();
+ variables.put("approved", approval.isStatus());
+ taskService.complete(approval.getId(), variables);
+ }
+}
\ No newline at end of file
diff --git a/spring-boot-flowable/src/main/java/com/baeldung/service/PublishArticleService.java b/spring-boot-flowable/src/main/java/com/baeldung/service/PublishArticleService.java
new file mode 100644
index 0000000000..b43f1dccdb
--- /dev/null
+++ b/spring-boot-flowable/src/main/java/com/baeldung/service/PublishArticleService.java
@@ -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.");
+ }
+}
diff --git a/spring-boot-flowable/src/main/java/com/baeldung/service/SendMailService.java b/spring-boot-flowable/src/main/java/com/baeldung/service/SendMailService.java
new file mode 100644
index 0000000000..f80b16748f
--- /dev/null
+++ b/spring-boot-flowable/src/main/java/com/baeldung/service/SendMailService.java
@@ -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.");
+ }
+}
diff --git a/spring-boot-flowable/src/main/resources/application.properties b/spring-boot-flowable/src/main/resources/application.properties
new file mode 100644
index 0000000000..c3afcaa0b5
--- /dev/null
+++ b/spring-boot-flowable/src/main/resources/application.properties
@@ -0,0 +1 @@
+management.endpoint.flowable.enabled=true
\ No newline at end of file
diff --git a/spring-boot-flowable/src/main/resources/processes/article-workflow.bpmn20.xml b/spring-boot-flowable/src/main/resources/processes/article-workflow.bpmn20.xml
new file mode 100644
index 0000000000..6bf210dcee
--- /dev/null
+++ b/spring-boot-flowable/src/main/resources/processes/article-workflow.bpmn20.xml
@@ -0,0 +1,51 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-boot-flowable/src/test/java/com/baeldung/processes/ArticleWorkflowUnitTest.java b/spring-boot-flowable/src/test/java/com/baeldung/processes/ArticleWorkflowUnitTest.java
new file mode 100644
index 0000000000..ef5453623a
--- /dev/null
+++ b/spring-boot-flowable/src/test/java/com/baeldung/processes/ArticleWorkflowUnitTest.java
@@ -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 variables = new HashMap();
+ 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());
+ }
+}
\ No newline at end of file
diff --git a/spring-boot-mvc-birt/README.md b/spring-boot-mvc-birt/README.md
new file mode 100644
index 0000000000..9fe3d94e2a
--- /dev/null
+++ b/spring-boot-mvc-birt/README.md
@@ -0,0 +1,3 @@
+### Relevant Articles
+
+- [BIRT Reporting with Spring Boot](https://www.baeldung.com/birt-reports-spring-boot)
diff --git a/spring-boot-mvc-birt/pom.xml b/spring-boot-mvc-birt/pom.xml
new file mode 100644
index 0000000000..8f41e8410a
--- /dev/null
+++ b/spring-boot-mvc-birt/pom.xml
@@ -0,0 +1,83 @@
+
+
+ 4.0.0
+ com.baeldung
+ spring-boot-mvc-birt
+ spring-boot-mvc-birt
+ 0.0.1-SNAPSHOT
+ jar
+ Module For Spring Boot Integration with BIRT
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.1.1.RELEASE
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ org.springframework.boot
+ spring-boot-starter-logging
+
+
+ ch.qos.logback
+ logback-classic
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+ com.innoventsolutions.birt.runtime
+ org.eclipse.birt.runtime_4.8.0-20180626
+ 4.8.0
+
+
+
+ log4j
+ log4j
+ 1.2.17
+
+
+
+ org.projectlombok
+ lombok
+ 1.18.6
+ provided
+
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
+ 2.1.1.RELEASE
+ com.baeldung.birt.engine.ReportEngineApplication
+ 1.8
+ 1.8
+
+
+
diff --git a/spring-boot-mvc-birt/reports/csv_data_report.rptdesign b/spring-boot-mvc-birt/reports/csv_data_report.rptdesign
new file mode 100644
index 0000000000..f390c5e69b
--- /dev/null
+++ b/spring-boot-mvc-birt/reports/csv_data_report.rptdesign
@@ -0,0 +1,2032 @@
+
+
+ Eclipse BIRT Designer Version 4.7.0.v201706222054
+ new_report
+
+
+ queryText
+ 5
+
+
+ HOME
+ 4
+
+
+ URI
+ 4
+
+
+ DELIMTYPE
+ 4
+
+
+ CHARSET
+ 4
+
+
+ INCLCOLUMNNAME
+ 4
+
+
+ INCLTYPELINE
+ 4
+
+
+ TRAILNULLCOLS
+ 4
+
+
+ OdaConnProfileName
+ 4
+
+
+ OdaConnProfileStorePath
+ 4
+
+
+ in
+ /templates/blank_report.gif
+ ltr
+ 96
+
+
+ reports/data.csv
+ COMMA
+ UTF-8
+ YES
+ NO
+ NO
+
+
+
+
+ nulls lowest
+
+
+ Student
+ dimension
+ Student
+
+
+ Math
+ measure
+ Math
+
+
+ Geography
+ measure
+ Geography
+
+
+ History
+ measure
+ History
+
+
+
+
+
+
+ 1
+ Student
+ string
+
+
+ 2
+ Math
+ integer
+
+
+ 3
+ Geography
+ integer
+
+
+ 4
+ History
+ integer
+
+
+
+ Data Source
+
+
+ 1
+ Student
+ Student
+ string
+ 12
+
+
+ 2
+ Math
+ Math
+ integer
+ 12
+
+
+ 3
+ Geography
+ Geography
+ integer
+ 12
+
+
+ 4
+ History
+ History
+ integer
+ 12
+
+
+
+
+
+ 2.0
+
+
+
+
+
+
+ Studen
+ 1
+
+ 12
+ -1
+ -1
+ Unknown
+
+
+ Studen
+
+
+
+
+
+
+ Math
+ 2
+
+ 12
+ -1
+ -1
+ Unknown
+
+
+ Math
+
+
+
+
+
+
+ Geography
+ 3
+
+ 12
+ -1
+ -1
+ Unknown
+
+
+ Geography
+
+
+
+
+
+
+ History
+ 4
+
+ 12
+ -1
+ -1
+ Unknown
+
+
+ History
+
+
+
+
+
+
+
+]]>
+
+
+
+
+
+
+
+
+
+
+
+ 7.947916666666667in
+
+ 2.15625in
+
+
+
+
+ 2
+ 1
+
+
+ 2.6.1
+ Bar Chart
+ Side-by-side
+
+
+
+ 0.0
+ 0.0
+ 0.0
+ 0.0
+
+
+ 3.0
+ 3.0
+ 3.0
+ 3.0
+
+ -1
+ -1
+ -1
+ -1
+
+
+ 1
+
+ 255
+ 0
+ 0
+ 0
+
+ false
+
+ true
+
+
+
+
+ 0.0
+ 0.0
+ 0.0
+ 0.0
+
+
+ 3.0
+ 3.0
+ 3.0
+ 3.0
+
+ -1
+ -1
+ -1
+ -1
+
+
+ 1
+
+ 255
+ 0
+ 0
+ 0
+
+ false
+
+ true
+ 5
+ 5
+
+
+
+ 0
+
+ 255
+ 0
+ 0
+ 0
+
+ false
+
+
+ 0.0
+ 0.0
+ 0.0
+ 0.0
+
+
+
+
+
+ 0.0
+ 0.0
+ 0.0
+ 0.0
+
+
+ 3.0
+ 3.0
+ 3.0
+ 3.0
+
+ -1
+ -1
+ -1
+ -1
+
+
+ 1
+
+ 255
+ 0
+ 0
+ 0
+
+ false
+
+ true
+
+
+
+ 0
+
+ 255
+ 0
+ 0
+ 0
+
+ false
+
+
+ 2.0
+ 2.0
+ 2.0
+ 2.0
+
+
+
+
+
+
+
+
+ Vertical
+ Top_Bottom
+
+
+ 1
+
+ 255
+ 0
+ 0
+ 0
+
+ true
+
+ Right
+ Series
+
+
+
+
+
+
+
+
+ 0
+ 255
+ 255
+ 255
+
+
+
+ 1
+
+ 255
+ 0
+ 0
+ 0
+
+ false
+
+
+ 0.0
+ 2.0
+ 0.0
+ 3.0
+
+ false
+
+ Above
+ false
+
+
+ 0.0
+ 0.0
+ 572.25
+ 286.125
+
+
+ 3.0
+ 3.0
+ 3.0
+ 3.0
+
+ -1
+ -1
+ -1
+ -1
+
+
+ 1
+
+ 255
+ 0
+ 0
+ 0
+
+ false
+
+ true
+
+ Two_Dimensional
+ Points
+ 10.0
+
+ enable.area.alt
+ false
+
+
+
+ A, B, C
+
+
+ 5,4,12
+ 0
+
+
+ 10.0,8.0,24.0
+ 1
+
+
+ 15.0,12.0,36.0
+ 2
+
+
+
+ ToggleSerieVisibility
+
+
+
+ This chart contains no data.
+
+
+ Center
+ Center
+
+
+
+
+ 64
+ 127
+ 127
+ 127
+
+
+
+ 128
+ 127
+ 127
+ 127
+
+ true
+
+
+ 10.0
+ 10.0
+ 10.0
+ 10.0
+
+ false
+
+
+ Text
+
+
+ X-Axis Title
+
+ 14.0
+ true
+
+ Center
+ Center
+
+
+
+
+ 0
+ 255
+ 255
+ 255
+
+
+
+ 1
+
+ 255
+ 0
+ 0
+ 0
+
+
+
+ 0.0
+ 2.0
+ 0.0
+ 3.0
+
+ false
+
+ Below
+
+ Linear
+
+
+ Y-Axis Title
+
+ 14.0
+ true
+
+ Center
+ Center
+
+
+
+
+ 0
+ 255
+ 255
+ 255
+
+
+
+ 1
+
+ 255
+ 0
+ 0
+ 0
+
+
+
+ 0.0
+ 2.0
+ 0.0
+ 3.0
+
+ false
+
+ Left
+
+
+
+
+ Numeric
+
+
+
+
+ 255
+ 80
+ 166
+ 218
+
+
+ 255
+ 242
+ 88
+ 106
+
+
+ 255
+ 232
+ 172
+ 57
+
+
+ 255
+ 128
+ 255
+ 128
+
+
+ 255
+ 64
+ 128
+ 128
+
+
+ 255
+ 128
+ 128
+ 192
+
+
+ 255
+ 170
+ 85
+ 85
+
+
+ 255
+ 128
+ 128
+ 0
+
+
+ 255
+ 192
+ 192
+ 192
+
+
+ 255
+ 255
+ 255
+ 128
+
+
+ 255
+ 128
+ 192
+ 128
+
+
+ 255
+ 7
+ 146
+ 94
+
+
+ 255
+ 0
+ 128
+ 255
+
+
+ 255
+ 255
+ 128
+ 192
+
+
+ 255
+ 0
+ 255
+ 255
+
+
+ 255
+ 255
+ 128
+ 128
+
+
+ 255
+ 0
+ 128
+ 192
+
+
+ 255
+ 255
+ 0
+ 255
+
+
+ 255
+ 128
+ 64
+ 64
+
+
+ 255
+ 255
+ 128
+ 64
+
+
+ 255
+ 80
+ 240
+ 120
+
+
+ 255
+ 0
+ 64
+ 128
+
+
+ 255
+ 128
+ 0
+ 64
+
+
+ 255
+ 255
+ 0
+ 128
+
+
+ 255
+ 128
+ 128
+ 64
+
+
+ 255
+ 128
+ 128
+ 128
+
+
+ 255
+ 255
+ 128
+ 255
+
+
+ 255
+ 0
+ 64
+ 0
+
+
+ 255
+ 0
+ 0
+ 0
+
+
+ 255
+ 255
+ 255
+ 255
+
+
+ 255
+ 255
+ 128
+ 0
+
+
+
+ true
+
+
+ row["Geography"]
+
+ Text
+ Sum
+
+
+ Geo
+
+
+ Orthogonal_Value
+
+ ,
+
+ Outside
+ false
+
+ onmouseover
+
+ Show_Tooltip
+
+
+ 200
+
+
+
+ Rectangle
+
+
+ Text
+ Sum
+
+
+
+
+
+
+ Numeric
+
+
+
+
+ 255
+ 242
+ 88
+ 106
+
+
+ 255
+ 232
+ 172
+ 57
+
+
+ 255
+ 128
+ 255
+ 128
+
+
+ 255
+ 64
+ 128
+ 128
+
+
+ 255
+ 128
+ 128
+ 192
+
+
+ 255
+ 170
+ 85
+ 85
+
+
+ 255
+ 128
+ 128
+ 0
+
+
+ 255
+ 192
+ 192
+ 192
+
+
+ 255
+ 255
+ 255
+ 128
+
+
+ 255
+ 128
+ 192
+ 128
+
+
+ 255
+ 7
+ 146
+ 94
+
+
+ 255
+ 0
+ 128
+ 255
+
+
+ 255
+ 255
+ 128
+ 192
+
+
+ 255
+ 0
+ 255
+ 255
+
+
+ 255
+ 255
+ 128
+ 128
+
+
+ 255
+ 0
+ 128
+ 192
+
+
+ 255
+ 255
+ 0
+ 255
+
+
+ 255
+ 128
+ 64
+ 64
+
+
+ 255
+ 255
+ 128
+ 64
+
+
+ 255
+ 80
+ 240
+ 120
+
+
+ 255
+ 0
+ 64
+ 128
+
+
+ 255
+ 128
+ 0
+ 64
+
+
+ 255
+ 255
+ 0
+ 128
+
+
+ 255
+ 128
+ 128
+ 64
+
+
+ 255
+ 128
+ 128
+ 128
+
+
+ 255
+ 255
+ 128
+ 255
+
+
+ 255
+ 0
+ 64
+ 0
+
+
+ 255
+ 0
+ 0
+ 0
+
+
+ 255
+ 255
+ 255
+ 255
+
+
+ 255
+ 255
+ 128
+ 0
+
+
+ 255
+ 80
+ 166
+ 218
+
+
+
+ true
+
+
+ row["History"]
+
+ false
+ Text
+ Sum
+
+
+ History
+
+
+ Orthogonal_Value
+
+ ,
+
+ Outside
+ false
+
+ onmouseover
+
+ Show_Tooltip
+
+
+ 200
+
+
+
+ Rectangle
+
+
+ Text
+ Sum
+
+
+
+
+
+
+ Numeric
+
+
+
+
+ 255
+ 232
+ 172
+ 57
+
+
+ 255
+ 128
+ 255
+ 128
+
+
+ 255
+ 64
+ 128
+ 128
+
+
+ 255
+ 128
+ 128
+ 192
+
+
+ 255
+ 170
+ 85
+ 85
+
+
+ 255
+ 128
+ 128
+ 0
+
+
+ 255
+ 192
+ 192
+ 192
+
+
+ 255
+ 255
+ 255
+ 128
+
+
+ 255
+ 128
+ 192
+ 128
+
+
+ 255
+ 7
+ 146
+ 94
+
+
+ 255
+ 0
+ 128
+ 255
+
+
+ 255
+ 255
+ 128
+ 192
+
+
+ 255
+ 0
+ 255
+ 255
+
+
+ 255
+ 255
+ 128
+ 128
+
+
+ 255
+ 0
+ 128
+ 192
+
+
+ 255
+ 255
+ 0
+ 255
+
+
+ 255
+ 128
+ 64
+ 64
+
+
+ 255
+ 255
+ 128
+ 64
+
+
+ 255
+ 80
+ 240
+ 120
+
+
+ 255
+ 0
+ 64
+ 128
+
+
+ 255
+ 128
+ 0
+ 64
+
+
+ 255
+ 255
+ 0
+ 128
+
+
+ 255
+ 128
+ 128
+ 64
+
+
+ 255
+ 128
+ 128
+ 128
+
+
+ 255
+ 255
+ 128
+ 255
+
+
+ 255
+ 0
+ 64
+ 0
+
+
+ 255
+ 0
+ 0
+ 0
+
+
+ 255
+ 255
+ 255
+ 255
+
+
+ 255
+ 255
+ 128
+ 0
+
+
+ 255
+ 80
+ 166
+ 218
+
+
+ 255
+ 242
+ 88
+ 106
+
+
+
+ true
+
+
+ row["Math"]
+
+ false
+ Text
+ Sum
+
+
+ Math
+
+
+ Orthogonal_Value
+
+ ,
+
+ Outside
+ false
+
+ onmouseover
+
+ Show_Tooltip
+
+
+ 200
+
+
+
+ Rectangle
+
+
+ Text
+ Sum
+
+
+ Vertical
+
+
+ 1
+
+ 255
+ 0
+ 0
+ 0
+
+ true
+
+
+ Left
+
+
+
+ 1
+
+ 255
+ 196
+ 196
+ 196
+
+ false
+
+ Across
+
+
+ 1
+
+ 255
+ 196
+ 196
+ 196
+
+ true
+
+
+
+
+
+ 1
+
+ 255
+ 225
+ 225
+ 225
+
+ false
+
+ Across
+
+
+ 1
+
+ 255
+ 225
+ 225
+ 225
+
+ false
+
+
+
+ 5
+
+
+ Min
+
+ 0.0
+
+
+ true
+ false
+
+
+
+
+
+
+
+ 255
+ 80
+ 166
+ 218
+
+
+ 255
+ 242
+ 88
+ 106
+
+
+ 255
+ 232
+ 172
+ 57
+
+
+ 255
+ 128
+ 255
+ 128
+
+
+ 255
+ 64
+ 128
+ 128
+
+
+ 255
+ 128
+ 128
+ 192
+
+
+ 255
+ 170
+ 85
+ 85
+
+
+ 255
+ 128
+ 128
+ 0
+
+
+ 255
+ 192
+ 192
+ 192
+
+
+ 255
+ 255
+ 255
+ 128
+
+
+ 255
+ 128
+ 192
+ 128
+
+
+ 255
+ 7
+ 146
+ 94
+
+
+ 255
+ 0
+ 128
+ 255
+
+
+ 255
+ 255
+ 128
+ 192
+
+
+ 255
+ 0
+ 255
+ 255
+
+
+ 255
+ 255
+ 128
+ 128
+
+
+ 255
+ 0
+ 128
+ 192
+
+
+ 255
+ 255
+ 0
+ 255
+
+
+ 255
+ 128
+ 64
+ 64
+
+
+ 255
+ 255
+ 128
+ 64
+
+
+ 255
+ 80
+ 240
+ 120
+
+
+ 255
+ 0
+ 64
+ 128
+
+
+ 255
+ 128
+ 0
+ 64
+
+
+ 255
+ 255
+ 0
+ 128
+
+
+ 255
+ 128
+ 128
+ 64
+
+
+ 255
+ 128
+ 128
+ 128
+
+
+ 255
+ 255
+ 128
+ 255
+
+
+ 255
+ 0
+ 64
+ 0
+
+
+ 255
+ 0
+ 0
+ 0
+
+
+ 255
+ 255
+ 255
+ 255
+
+
+ 255
+ 255
+ 128
+ 0
+
+
+
+ true
+
+
+ row["Student"]
+
+
+
+
+ Orthogonal_Value
+
+ ,
+
+ Outside
+ false
+
+
+ true
+ Text
+ Sum
+
+
+ Horizontal
+
+
+ 1
+
+ 255
+ 0
+ 0
+ 0
+
+ true
+
+
+ Below
+
+
+
+ 1
+
+ 255
+ 196
+ 196
+ 196
+
+ false
+
+ Across
+
+
+ 1
+
+ 255
+ 196
+ 196
+ 196
+
+ true
+
+
+
+
+
+ 1
+
+ 255
+ 225
+ 225
+ 225
+
+ false
+
+ Across
+
+
+ 1
+
+ 255
+ 225
+ 225
+ 225
+
+ false
+
+
+
+ 5
+
+
+ Min
+
+ 0.0
+
+
+ true
+ true
+ false
+
+ Vertical
+ 50.0
+
+
+ -20.0
+ 45.0
+ 0.0
+ None
+
+
+
+]]>
+ SVG
+ true
+ 286.125pt
+ 572.25pt
+ Data Set
+
+
+ Student
+ Student
+ dataSetRow["Student"]
+ string
+
+
+ Math
+ Math
+ dataSetRow["Math"]
+ integer
+
+
+ Geography
+ Geography
+ dataSetRow["Geography"]
+ integer
+
+
+ History
+ History
+ dataSetRow["History"]
+ integer
+
+
+
+ |
+
+
+
+ 2
+ 1
+
+ Data Set
+
+
+ Student
+ Student
+ dataSetRow["Student"]
+ string
+
+
+ Math
+ Math
+ dataSetRow["Math"]
+ integer
+
+
+ Geography
+ Geography
+ dataSetRow["Geography"]
+ integer
+
+
+ History
+ History
+ dataSetRow["History"]
+ integer
+
+
+
+
+
+
+
+
+
+
+ |
+
+
+ |
+
+
+ |
+
+
+ |
+
+
+
+
+
+
+ Student
+
+ |
+
+
+ Math
+
+ |
+
+
+ Geography
+
+ |
+
+
+ History
+
+ |
+
+
+
+
+ |
+
+
+
+
diff --git a/spring-boot-mvc-birt/reports/data.csv b/spring-boot-mvc-birt/reports/data.csv
new file mode 100644
index 0000000000..d05e58415e
--- /dev/null
+++ b/spring-boot-mvc-birt/reports/data.csv
@@ -0,0 +1,4 @@
+Student, Math, Geography, History
+Bill, 10,3,8
+Tom, 5,6,5
+Anne, 7, 4,9
\ No newline at end of file
diff --git a/spring-boot-mvc-birt/reports/static_report.rptdesign b/spring-boot-mvc-birt/reports/static_report.rptdesign
new file mode 100644
index 0000000000..d96ff76856
--- /dev/null
+++ b/spring-boot-mvc-birt/reports/static_report.rptdesign
@@ -0,0 +1,27 @@
+
+
+ Sample Report
+
+
+
+
+
+ 100%
+
+
+
+
+
+ url
+ "https://www.baeldung.com/wp-content/themes/baeldung/favicon/favicon-96x96.png"
+
+ |
+
+
+ |
+
+
+
+
diff --git a/spring-boot-mvc-birt/src/main/java/com/baeldung/birt/designer/ReportDesignApplication.java b/spring-boot-mvc-birt/src/main/java/com/baeldung/birt/designer/ReportDesignApplication.java
new file mode 100644
index 0000000000..f1e1619a58
--- /dev/null
+++ b/spring-boot-mvc-birt/src/main/java/com/baeldung/birt/designer/ReportDesignApplication.java
@@ -0,0 +1,93 @@
+package com.baeldung.birt.designer;
+
+import com.ibm.icu.util.ULocale;
+import org.apache.log4j.Logger;
+import org.eclipse.birt.core.exception.BirtException;
+import org.eclipse.birt.core.framework.Platform;
+import org.eclipse.birt.report.model.api.*;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.CommandLineRunner;
+import org.springframework.boot.WebApplicationType;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.builder.SpringApplicationBuilder;
+
+import java.io.File;
+import java.io.IOException;
+
+@SpringBootApplication
+public class ReportDesignApplication implements CommandLineRunner {
+
+ private static final Logger log = Logger.getLogger(ReportDesignApplication.class);
+
+ @Value("${reports.relative.path}")
+ private String REPORTS_FOLDER;
+
+ public static void main(String[] args) {
+ new SpringApplicationBuilder(ReportDesignApplication.class).web(WebApplicationType.NONE).build().run(args);
+ }
+
+ @Override public void run(String... args) throws Exception {
+ buildReport();
+ }
+
+ private void buildReport() throws IOException, BirtException {
+ final DesignConfig config = new DesignConfig();
+
+ final IDesignEngine engine;
+ try {
+ Platform.startup(config);
+ IDesignEngineFactory factory = (IDesignEngineFactory) Platform
+ .createFactoryObject(IDesignEngineFactory.EXTENSION_DESIGN_ENGINE_FACTORY);
+ engine = factory.createDesignEngine(config);
+
+ } catch (Exception ex) {
+ log.error("Exception during creation of DesignEngine", ex);
+ throw ex;
+ }
+
+ SessionHandle session = engine.newSessionHandle(ULocale.ENGLISH);
+
+ ReportDesignHandle design = session.createDesign();
+ design.setTitle("Sample Report");
+
+ // The element factory creates instances of the various BIRT elements.
+ ElementFactory factory = design.getElementFactory();
+
+ // Create a simple master page that describes how the report will
+ // appear when printed.
+ //
+ // Note: The report will fail to load in the BIRT designer
+ // unless you create a master page.
+
+ DesignElementHandle element = factory.newSimpleMasterPage("Page Master"); //$NON-NLS-1$
+ design.getMasterPages().add(element);
+
+ // Create a grid
+ GridHandle grid = factory.newGridItem(null, 2 /* cols */, 1 /* row */);
+ design.getBody().add(grid);
+ grid.setWidth("100%");
+
+ RowHandle row0 = (RowHandle) grid.getRows().get(0);
+
+ // Create an image and add it to the first cell.
+ ImageHandle image = factory.newImage(null);
+ CellHandle cell = (CellHandle) row0.getCells().get(0);
+ cell.getContent().add(image);
+ image.setURL("\"https://www.baeldung.com/wp-content/themes/baeldung/favicon/favicon-96x96.png\"");
+
+ // Create a label and add it to the second cell.
+ LabelHandle label = factory.newLabel(null);
+ cell = (CellHandle) row0.getCells().get(1);
+ cell.getContent().add(label);
+ label.setText("Hello, Baeldung world!");
+
+ // Save the design and close it.
+ File report = new File(REPORTS_FOLDER);
+ report.mkdirs();
+
+ design.saveAs(new File(report, "static_report.rptdesign").getAbsolutePath());
+ design.close();
+ log.info("Report generated");
+ }
+
+}
diff --git a/spring-boot-mvc-birt/src/main/java/com/baeldung/birt/engine/ReportEngineApplication.java b/spring-boot-mvc-birt/src/main/java/com/baeldung/birt/engine/ReportEngineApplication.java
new file mode 100644
index 0000000000..6d72017c9d
--- /dev/null
+++ b/spring-boot-mvc-birt/src/main/java/com/baeldung/birt/engine/ReportEngineApplication.java
@@ -0,0 +1,29 @@
+package com.baeldung.birt.engine;
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.web.servlet.config.annotation.EnableWebMvc;
+import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+@SpringBootApplication
+@EnableWebMvc
+public class ReportEngineApplication implements WebMvcConfigurer {
+ @Value("${reports.relative.path}")
+ private String reportsPath;
+ @Value("${images.relative.path}")
+ private String imagesPath;
+
+ public static void main(final String[] args) {
+ SpringApplication.run(ReportEngineApplication.class, args);
+ }
+
+ @Override
+ public void addResourceHandlers(ResourceHandlerRegistry registry) {
+ registry
+ .addResourceHandler(reportsPath + imagesPath + "/**")
+ .addResourceLocations("file:///" + System.getProperty("user.dir") + "/" + reportsPath + imagesPath);
+ }
+
+}
\ No newline at end of file
diff --git a/spring-boot-mvc-birt/src/main/java/com/baeldung/birt/engine/controller/BirtReportController.java b/spring-boot-mvc-birt/src/main/java/com/baeldung/birt/engine/controller/BirtReportController.java
new file mode 100644
index 0000000000..e2405d02ec
--- /dev/null
+++ b/spring-boot-mvc-birt/src/main/java/com/baeldung/birt/engine/controller/BirtReportController.java
@@ -0,0 +1,51 @@
+package com.baeldung.birt.engine.controller;
+
+import com.baeldung.birt.engine.dto.OutputType;
+import com.baeldung.birt.engine.dto.Report;
+import com.baeldung.birt.engine.service.BirtReportService;
+import org.apache.log4j.Logger;
+import org.eclipse.birt.report.engine.api.EngineException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.util.List;
+
+@Controller
+public class BirtReportController {
+ private static final Logger log = Logger.getLogger(BirtReportController.class);
+
+ @Autowired
+ private BirtReportService reportService;
+
+ @RequestMapping(produces = "application/json", method = RequestMethod.GET, value = "/report")
+ @ResponseBody
+ public List listReports() {
+ return reportService.getReports();
+ }
+
+ @RequestMapping(produces = "application/json", method = RequestMethod.GET, value = "/report/reload")
+ @ResponseBody
+ public ResponseEntity reloadReports(HttpServletResponse response) {
+ try {
+ log.info("Reloading reports");
+ reportService.loadReports();
+ } catch (EngineException e) {
+ log.error("There was an error reloading the reports in memory: ", e);
+ return ResponseEntity.status(HttpServletResponse.SC_INTERNAL_SERVER_ERROR).build();
+ }
+ return ResponseEntity.ok().build();
+ }
+
+ @RequestMapping(method = RequestMethod.GET, value = "/report/{name}")
+ @ResponseBody
+ public void generateFullReport(HttpServletResponse response, HttpServletRequest request,
+ @PathVariable("name") String name, @RequestParam("output") String output) {
+ log.info("Generating full report: " + name + "; format: " + output);
+ OutputType format = OutputType.from(output);
+ reportService.generateMainReport(name, format, response, request);
+ }
+}
diff --git a/spring-boot-mvc-birt/src/main/java/com/baeldung/birt/engine/dto/OutputType.java b/spring-boot-mvc-birt/src/main/java/com/baeldung/birt/engine/dto/OutputType.java
new file mode 100644
index 0000000000..3180a347ba
--- /dev/null
+++ b/spring-boot-mvc-birt/src/main/java/com/baeldung/birt/engine/dto/OutputType.java
@@ -0,0 +1,21 @@
+package com.baeldung.birt.engine.dto;
+
+import org.eclipse.birt.report.engine.api.IRenderOption;
+
+public enum OutputType {
+ HTML(IRenderOption.OUTPUT_FORMAT_HTML),
+ PDF(IRenderOption.OUTPUT_FORMAT_PDF),
+ INVALID("invalid");
+
+ String val;
+ OutputType(String val) {
+ this.val = val;
+ }
+
+ public static OutputType from(String text) {
+ for (OutputType output : values()) {
+ if(output.val.equalsIgnoreCase(text)) return output;
+ }
+ return INVALID;
+ }
+}
diff --git a/spring-boot-mvc-birt/src/main/java/com/baeldung/birt/engine/dto/Report.java b/spring-boot-mvc-birt/src/main/java/com/baeldung/birt/engine/dto/Report.java
new file mode 100644
index 0000000000..a2d2444b80
--- /dev/null
+++ b/spring-boot-mvc-birt/src/main/java/com/baeldung/birt/engine/dto/Report.java
@@ -0,0 +1,37 @@
+package com.baeldung.birt.engine.dto;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.List;
+
+/**
+ * Report DTO class
+ */
+@Data
+@NoArgsConstructor
+public class Report {
+ private String title;
+ private String name;
+ private List parameters;
+
+ public Report(String title, String name) {
+ this.title = title;
+ this.name = name;
+ }
+
+ @Data
+ @NoArgsConstructor
+ @AllArgsConstructor
+ public static class Parameter {
+ private String title;
+ private String name;
+ private ParameterType type;
+
+ }
+
+ public enum ParameterType {
+ INT, STRING
+ }
+}
diff --git a/spring-boot-mvc-birt/src/main/java/com/baeldung/birt/engine/service/BirtReportService.java b/spring-boot-mvc-birt/src/main/java/com/baeldung/birt/engine/service/BirtReportService.java
new file mode 100644
index 0000000000..540bbbb530
--- /dev/null
+++ b/spring-boot-mvc-birt/src/main/java/com/baeldung/birt/engine/service/BirtReportService.java
@@ -0,0 +1,168 @@
+package com.baeldung.birt.engine.service;
+
+import com.baeldung.birt.engine.dto.OutputType;
+import com.baeldung.birt.engine.dto.Report;
+import org.eclipse.birt.core.exception.BirtException;
+import org.eclipse.birt.core.framework.Platform;
+import org.eclipse.birt.report.engine.api.*;
+import org.springframework.beans.factory.DisposableBean;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+import org.springframework.core.io.ResourceLoader;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.PostConstruct;
+import javax.servlet.ServletContext;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.File;
+import java.util.*;
+
+@Service
+public class BirtReportService implements ApplicationContextAware, DisposableBean {
+ @Value("${reports.relative.path}")
+ private String reportsPath;
+ @Value("${images.relative.path}")
+ private String imagesPath;
+
+ private HTMLServerImageHandler htmlImageHandler = new HTMLServerImageHandler();
+
+ @Autowired
+ private ResourceLoader resourceLoader;
+ @Autowired
+ private ServletContext servletContext;
+
+ private IReportEngine birtEngine;
+ private ApplicationContext context;
+ private String imageFolder;
+
+ private Map reports = new HashMap<>();
+
+ @SuppressWarnings("unchecked")
+ @PostConstruct
+ protected void initialize() throws BirtException {
+ EngineConfig config = new EngineConfig();
+ config.getAppContext().put("spring", this.context);
+ Platform.startup(config);
+ IReportEngineFactory factory = (IReportEngineFactory) Platform
+ .createFactoryObject(IReportEngineFactory.EXTENSION_REPORT_ENGINE_FACTORY);
+ birtEngine = factory.createReportEngine(config);
+ imageFolder = System.getProperty("user.dir") + File.separatorChar + reportsPath + imagesPath;
+ loadReports();
+ }
+
+ @Override
+ public void setApplicationContext(ApplicationContext context) {
+ this.context = context;
+ }
+
+ /**
+ * Load report files to memory
+ *
+ */
+ public void loadReports() throws EngineException {
+ File folder = new File(reportsPath);
+ for (String file : Objects.requireNonNull(folder.list())) {
+ if (!file.endsWith(".rptdesign")) {
+ continue;
+ }
+
+ reports.put(file.replace(".rptdesign", ""),
+ birtEngine.openReportDesign(folder.getAbsolutePath() + File.separator + file));
+
+ }
+ }
+
+ public List getReports() {
+ List response = new ArrayList<>();
+ for (Map.Entry entry : reports.entrySet()) {
+ IReportRunnable report = reports.get(entry.getKey());
+ IGetParameterDefinitionTask task = birtEngine.createGetParameterDefinitionTask(report);
+ Report reportItem = new Report(report.getDesignHandle().getProperty("title").toString(), entry.getKey());
+ for (Object h : task.getParameterDefns(false)) {
+ IParameterDefn def = (IParameterDefn) h;
+ reportItem.getParameters()
+ .add(new Report.Parameter(def.getPromptText(), def.getName(), getParameterType(def)));
+ }
+ response.add(reportItem);
+ }
+ return response;
+ }
+
+ private Report.ParameterType getParameterType(IParameterDefn param) {
+ if (IParameterDefn.TYPE_INTEGER == param.getDataType()) {
+ return Report.ParameterType.INT;
+ }
+ return Report.ParameterType.STRING;
+ }
+
+ public void generateMainReport(String reportName, OutputType output, HttpServletResponse response, HttpServletRequest request) {
+ switch (output) {
+ case HTML:
+ generateHTMLReport(reports.get(reportName), response, request);
+ break;
+ case PDF:
+ generatePDFReport(reports.get(reportName), response, request);
+ break;
+ default:
+ throw new IllegalArgumentException("Output type not recognized:" + output);
+ }
+ }
+
+ /**
+ * Generate a report as HTML
+ */
+ @SuppressWarnings("unchecked")
+ private void generateHTMLReport(IReportRunnable report, HttpServletResponse response, HttpServletRequest request) {
+ IRunAndRenderTask runAndRenderTask = birtEngine.createRunAndRenderTask(report);
+ response.setContentType(birtEngine.getMIMEType("html"));
+ IRenderOption options = new RenderOption();
+ HTMLRenderOption htmlOptions = new HTMLRenderOption(options);
+ htmlOptions.setOutputFormat("html");
+ htmlOptions.setBaseImageURL("/" + reportsPath + imagesPath);
+ htmlOptions.setImageDirectory(imageFolder);
+ htmlOptions.setImageHandler(htmlImageHandler);
+ runAndRenderTask.setRenderOption(htmlOptions);
+ runAndRenderTask.getAppContext().put(EngineConstants.APPCONTEXT_BIRT_VIEWER_HTTPSERVET_REQUEST, request);
+
+ try {
+ htmlOptions.setOutputStream(response.getOutputStream());
+ runAndRenderTask.run();
+ } catch (Exception e) {
+ throw new RuntimeException(e.getMessage(), e);
+ } finally {
+ runAndRenderTask.close();
+ }
+ }
+
+ /**
+ * Generate a report as PDF
+ */
+ @SuppressWarnings("unchecked")
+ private void generatePDFReport(IReportRunnable report, HttpServletResponse response, HttpServletRequest request) {
+ IRunAndRenderTask runAndRenderTask = birtEngine.createRunAndRenderTask(report);
+ response.setContentType(birtEngine.getMIMEType("pdf"));
+ IRenderOption options = new RenderOption();
+ PDFRenderOption pdfRenderOption = new PDFRenderOption(options);
+ pdfRenderOption.setOutputFormat("pdf");
+ runAndRenderTask.setRenderOption(pdfRenderOption);
+ runAndRenderTask.getAppContext().put(EngineConstants.APPCONTEXT_PDF_RENDER_CONTEXT, request);
+
+ try {
+ pdfRenderOption.setOutputStream(response.getOutputStream());
+ runAndRenderTask.run();
+ } catch (Exception e) {
+ throw new RuntimeException(e.getMessage(), e);
+ } finally {
+ runAndRenderTask.close();
+ }
+ }
+
+ @Override
+ public void destroy() {
+ birtEngine.destroy();
+ Platform.shutdown();
+ }
+}
diff --git a/spring-boot-mvc-birt/src/main/resources/application.properties b/spring-boot-mvc-birt/src/main/resources/application.properties
new file mode 100644
index 0000000000..5b015c70b1
--- /dev/null
+++ b/spring-boot-mvc-birt/src/main/resources/application.properties
@@ -0,0 +1,2 @@
+reports.relative.path=reports/
+images.relative.path=images/
\ No newline at end of file
diff --git a/spring-boot-rest/README.md b/spring-boot-rest/README.md
index af372077f0..b28192cf62 100644
--- a/spring-boot-rest/README.md
+++ b/spring-boot-rest/README.md
@@ -1,13 +1,18 @@
Module for the articles that are part of the Spring REST E-book:
1. [Bootstrap a Web Application with Spring 5](https://www.baeldung.com/bootstraping-a-web-application-with-spring-and-java-based-configuration)
-2. [Error Handling for REST with Spring](http://www.baeldung.com/exception-handling-for-rest-with-spring)
-3. [REST Pagination in Spring](http://www.baeldung.com/rest-api-pagination-in-spring)
-4. [Build a REST API with Spring and Java Config](http://www.baeldung.com/building-a-restful-web-service-with-spring-and-java-based-configuration)
-5. [HATEOAS for a Spring REST Service](http://www.baeldung.com/rest-api-discoverability-with-spring)
-6. [REST API Discoverability and HATEOAS](http://www.baeldung.com/restful-web-service-discoverability)
-7. [Versioning a REST API](http://www.baeldung.com/rest-versioning)
-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)
+2. [Build a REST API with Spring and Java Config](http://www.baeldung.com/building-a-restful-web-service-with-spring-and-java-based-configuration)
+3. [Http Message Converters with the Spring Framework](http://www.baeldung.com/spring-httpmessageconverter-rest)
+4. [Spring’s RequestBody and ResponseBody Annotations](https://www.baeldung.com/spring-request-response-body)
+5. [Entity To DTO Conversion for a Spring REST API](https://www.baeldung.com/entity-to-and-from-dto-for-a-java-spring-application)
+6. [Error Handling for REST with Spring](http://www.baeldung.com/exception-handling-for-rest-with-spring)
+7. [REST API Discoverability and HATEOAS](http://www.baeldung.com/restful-web-service-discoverability)
+8. [An Intro to Spring HATEOAS](http://www.baeldung.com/spring-hateoas-tutorial)
+9. [REST Pagination in Spring](http://www.baeldung.com/rest-api-pagination-in-spring)
+10. [Test a REST API with Java](http://www.baeldung.com/integration-testing-a-rest-api)
+
+- [HATEOAS for a Spring REST Service](http://www.baeldung.com/rest-api-discoverability-with-spring)
+- [Versioning a REST API](http://www.baeldung.com/rest-versioning)
+- [ETags for REST with Spring](http://www.baeldung.com/etags-for-rest-with-spring)
+- [Testing REST with multiple MIME types](http://www.baeldung.com/testing-rest-api-with-multiple-media-types)
+- [Testing Web APIs with Postman Collections](https://www.baeldung.com/postman-testing-collections)
diff --git a/spring-boot-rest/pom.xml b/spring-boot-rest/pom.xml
index decaccd148..598b589ea0 100644
--- a/spring-boot-rest/pom.xml
+++ b/spring-boot-rest/pom.xml
@@ -44,6 +44,12 @@
org.springframework.boot
spring-boot-starter-data-jpa
+
+
+
+ org.springframework.boot
+ spring-boot-starter-hateoas
+
@@ -63,6 +69,11 @@
htmlunit
test
+
+ org.modelmapper
+ modelmapper
+ ${modelmapper.version}
+
@@ -78,5 +89,6 @@
com.baeldung.SpringBootRestApplication
27.0.1-jre
1.4.11.1
+ 2.3.3
diff --git a/spring-boot-rest/src/main/java/com/baeldung/SpringBootRestApplication.java b/spring-boot-rest/src/main/java/com/baeldung/SpringBootRestApplication.java
index 62aae7619d..1c0d0d19e8 100644
--- a/spring-boot-rest/src/main/java/com/baeldung/SpringBootRestApplication.java
+++ b/spring-boot-rest/src/main/java/com/baeldung/SpringBootRestApplication.java
@@ -1,7 +1,9 @@
package com.baeldung;
+import org.modelmapper.ModelMapper;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.Bean;
@SpringBootApplication
public class SpringBootRestApplication {
@@ -9,5 +11,10 @@ public class SpringBootRestApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootRestApplication.class, args);
}
+
+ @Bean
+ public ModelMapper modelMapper() {
+ return new ModelMapper();
+ }
}
diff --git a/spring-boot/src/main/java/com/baeldung/modelmapper/controller/PostRestController.java b/spring-boot-rest/src/main/java/com/baeldung/modelmapper/controller/PostRestController.java
similarity index 99%
rename from spring-boot/src/main/java/com/baeldung/modelmapper/controller/PostRestController.java
rename to spring-boot-rest/src/main/java/com/baeldung/modelmapper/controller/PostRestController.java
index c0cbca5220..68c17975d4 100644
--- a/spring-boot/src/main/java/com/baeldung/modelmapper/controller/PostRestController.java
+++ b/spring-boot-rest/src/main/java/com/baeldung/modelmapper/controller/PostRestController.java
@@ -21,6 +21,7 @@ import com.baeldung.modelmapper.service.IPostService;
import com.baeldung.modelmapper.service.IUserService;
@Controller
+@RequestMapping("/posts")
public class PostRestController {
@Autowired
diff --git a/spring-boot/src/main/java/com/baeldung/modelmapper/dto/PostDto.java b/spring-boot-rest/src/main/java/com/baeldung/modelmapper/dto/PostDto.java
similarity index 100%
rename from spring-boot/src/main/java/com/baeldung/modelmapper/dto/PostDto.java
rename to spring-boot-rest/src/main/java/com/baeldung/modelmapper/dto/PostDto.java
diff --git a/spring-boot/src/main/java/com/baeldung/modelmapper/dto/UserDto.java b/spring-boot-rest/src/main/java/com/baeldung/modelmapper/dto/UserDto.java
similarity index 100%
rename from spring-boot/src/main/java/com/baeldung/modelmapper/dto/UserDto.java
rename to spring-boot-rest/src/main/java/com/baeldung/modelmapper/dto/UserDto.java
diff --git a/spring-boot/src/main/java/com/baeldung/modelmapper/model/Post.java b/spring-boot-rest/src/main/java/com/baeldung/modelmapper/model/Post.java
similarity index 100%
rename from spring-boot/src/main/java/com/baeldung/modelmapper/model/Post.java
rename to spring-boot-rest/src/main/java/com/baeldung/modelmapper/model/Post.java
diff --git a/spring-boot/src/main/java/com/baeldung/modelmapper/model/Preference.java b/spring-boot-rest/src/main/java/com/baeldung/modelmapper/model/Preference.java
similarity index 100%
rename from spring-boot/src/main/java/com/baeldung/modelmapper/model/Preference.java
rename to spring-boot-rest/src/main/java/com/baeldung/modelmapper/model/Preference.java
diff --git a/spring-boot/src/main/java/com/baeldung/modelmapper/model/User.java b/spring-boot-rest/src/main/java/com/baeldung/modelmapper/model/User.java
similarity index 100%
rename from spring-boot/src/main/java/com/baeldung/modelmapper/model/User.java
rename to spring-boot-rest/src/main/java/com/baeldung/modelmapper/model/User.java
diff --git a/spring-boot/src/main/java/com/baeldung/modelmapper/repository/PostRepository.java b/spring-boot-rest/src/main/java/com/baeldung/modelmapper/repository/PostRepository.java
similarity index 100%
rename from spring-boot/src/main/java/com/baeldung/modelmapper/repository/PostRepository.java
rename to spring-boot-rest/src/main/java/com/baeldung/modelmapper/repository/PostRepository.java
diff --git a/spring-boot/src/main/java/com/baeldung/modelmapper/service/IPostService.java b/spring-boot-rest/src/main/java/com/baeldung/modelmapper/service/IPostService.java
similarity index 100%
rename from spring-boot/src/main/java/com/baeldung/modelmapper/service/IPostService.java
rename to spring-boot-rest/src/main/java/com/baeldung/modelmapper/service/IPostService.java
diff --git a/spring-boot/src/main/java/com/baeldung/modelmapper/service/IUserService.java b/spring-boot-rest/src/main/java/com/baeldung/modelmapper/service/IUserService.java
similarity index 100%
rename from spring-boot/src/main/java/com/baeldung/modelmapper/service/IUserService.java
rename to spring-boot-rest/src/main/java/com/baeldung/modelmapper/service/IUserService.java
diff --git a/spring-boot/src/main/java/com/baeldung/modelmapper/service/PostService.java b/spring-boot-rest/src/main/java/com/baeldung/modelmapper/service/PostService.java
similarity index 100%
rename from spring-boot/src/main/java/com/baeldung/modelmapper/service/PostService.java
rename to spring-boot-rest/src/main/java/com/baeldung/modelmapper/service/PostService.java
diff --git a/spring-boot/src/main/java/com/baeldung/modelmapper/service/UserService.java b/spring-boot-rest/src/main/java/com/baeldung/modelmapper/service/UserService.java
similarity index 100%
rename from spring-boot/src/main/java/com/baeldung/modelmapper/service/UserService.java
rename to spring-boot-rest/src/main/java/com/baeldung/modelmapper/service/UserService.java
diff --git a/spring-security-rest/src/main/java/org/baeldung/persistence/model/Customer.java b/spring-boot-rest/src/main/java/com/baeldung/persistence/model/Customer.java
similarity index 97%
rename from spring-security-rest/src/main/java/org/baeldung/persistence/model/Customer.java
rename to spring-boot-rest/src/main/java/com/baeldung/persistence/model/Customer.java
index b302ec057a..10da2e10f0 100644
--- a/spring-security-rest/src/main/java/org/baeldung/persistence/model/Customer.java
+++ b/spring-boot-rest/src/main/java/com/baeldung/persistence/model/Customer.java
@@ -1,4 +1,4 @@
-package org.baeldung.persistence.model;
+package com.baeldung.persistence.model;
import java.util.Map;
diff --git a/spring-security-rest/src/main/java/org/baeldung/persistence/model/Order.java b/spring-boot-rest/src/main/java/com/baeldung/persistence/model/Order.java
similarity index 96%
rename from spring-security-rest/src/main/java/org/baeldung/persistence/model/Order.java
rename to spring-boot-rest/src/main/java/com/baeldung/persistence/model/Order.java
index ca551423e8..7aea9bce5c 100644
--- a/spring-security-rest/src/main/java/org/baeldung/persistence/model/Order.java
+++ b/spring-boot-rest/src/main/java/com/baeldung/persistence/model/Order.java
@@ -1,4 +1,4 @@
-package org.baeldung.persistence.model;
+package com.baeldung.persistence.model;
import org.springframework.hateoas.ResourceSupport;
diff --git a/spring-security-rest/src/main/java/org/baeldung/web/service/CustomerService.java b/spring-boot-rest/src/main/java/com/baeldung/services/CustomerService.java
similarity index 64%
rename from spring-security-rest/src/main/java/org/baeldung/web/service/CustomerService.java
rename to spring-boot-rest/src/main/java/com/baeldung/services/CustomerService.java
index da016af2d5..a5e95e693b 100644
--- a/spring-security-rest/src/main/java/org/baeldung/web/service/CustomerService.java
+++ b/spring-boot-rest/src/main/java/com/baeldung/services/CustomerService.java
@@ -1,8 +1,8 @@
-package org.baeldung.web.service;
+package com.baeldung.services;
import java.util.List;
-import org.baeldung.persistence.model.Customer;
+import com.baeldung.persistence.model.Customer;
public interface CustomerService {
diff --git a/spring-security-rest/src/main/java/org/baeldung/web/service/CustomerServiceImpl.java b/spring-boot-rest/src/main/java/com/baeldung/services/CustomerServiceImpl.java
similarity index 92%
rename from spring-security-rest/src/main/java/org/baeldung/web/service/CustomerServiceImpl.java
rename to spring-boot-rest/src/main/java/com/baeldung/services/CustomerServiceImpl.java
index e179de2554..58030483ec 100644
--- a/spring-security-rest/src/main/java/org/baeldung/web/service/CustomerServiceImpl.java
+++ b/spring-boot-rest/src/main/java/com/baeldung/services/CustomerServiceImpl.java
@@ -1,12 +1,13 @@
-package org.baeldung.web.service;
+package com.baeldung.services;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
-import org.baeldung.persistence.model.Customer;
import org.springframework.stereotype.Service;
+import com.baeldung.persistence.model.Customer;
+
@Service
public class CustomerServiceImpl implements CustomerService {
diff --git a/spring-rest/src/main/java/com/baeldung/services/ExampleService.java b/spring-boot-rest/src/main/java/com/baeldung/services/ExampleService.java
similarity index 100%
rename from spring-rest/src/main/java/com/baeldung/services/ExampleService.java
rename to spring-boot-rest/src/main/java/com/baeldung/services/ExampleService.java
diff --git a/spring-security-rest/src/main/java/org/baeldung/web/service/OrderService.java b/spring-boot-rest/src/main/java/com/baeldung/services/OrderService.java
similarity index 70%
rename from spring-security-rest/src/main/java/org/baeldung/web/service/OrderService.java
rename to spring-boot-rest/src/main/java/com/baeldung/services/OrderService.java
index 9a23488c50..775701e042 100644
--- a/spring-security-rest/src/main/java/org/baeldung/web/service/OrderService.java
+++ b/spring-boot-rest/src/main/java/com/baeldung/services/OrderService.java
@@ -1,8 +1,8 @@
-package org.baeldung.web.service;
+package com.baeldung.services;
import java.util.List;
-import org.baeldung.persistence.model.Order;
+import com.baeldung.persistence.model.Order;
public interface OrderService {
diff --git a/spring-security-rest/src/main/java/org/baeldung/web/service/OrderServiceImpl.java b/spring-boot-rest/src/main/java/com/baeldung/services/OrderServiceImpl.java
similarity index 93%
rename from spring-security-rest/src/main/java/org/baeldung/web/service/OrderServiceImpl.java
rename to spring-boot-rest/src/main/java/com/baeldung/services/OrderServiceImpl.java
index 0a6d4708a1..fffdf88969 100644
--- a/spring-security-rest/src/main/java/org/baeldung/web/service/OrderServiceImpl.java
+++ b/spring-boot-rest/src/main/java/com/baeldung/services/OrderServiceImpl.java
@@ -1,14 +1,15 @@
-package org.baeldung.web.service;
+package com.baeldung.services;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import org.baeldung.persistence.model.Customer;
-import org.baeldung.persistence.model.Order;
import org.springframework.stereotype.Service;
+import com.baeldung.persistence.model.Customer;
+import com.baeldung.persistence.model.Order;
+
@Service
public class OrderServiceImpl implements OrderService {
diff --git a/spring-boot-rest/src/main/java/com/baeldung/spring/PersistenceConfig.java b/spring-boot-rest/src/main/java/com/baeldung/spring/PersistenceConfig.java
index 5179c66978..2e967751ad 100644
--- a/spring-boot-rest/src/main/java/com/baeldung/spring/PersistenceConfig.java
+++ b/spring-boot-rest/src/main/java/com/baeldung/spring/PersistenceConfig.java
@@ -24,8 +24,8 @@ import com.google.common.base.Preconditions;
@Configuration
@EnableTransactionManagement
@PropertySource({ "classpath:persistence-${envTarget:h2}.properties" })
-@ComponentScan({ "com.baeldung.persistence" })
-@EnableJpaRepositories(basePackages = "com.baeldung.persistence.dao")
+@ComponentScan(basePackages = { "com.baeldung.persistence", "com.baeldung.modelmapper" })
+@EnableJpaRepositories(basePackages = {"com.baeldung.persistence.dao", "com.baeldung.modelmapper.repository"})
public class PersistenceConfig {
@Autowired
@@ -39,7 +39,7 @@ public class PersistenceConfig {
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
final LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(dataSource());
- em.setPackagesToScan(new String[] { "com.baeldung.persistence.model" });
+ em.setPackagesToScan(new String[] { "com.baeldung.persistence.model", "com.baeldung.modelmapper.model" });
final HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
// vendorAdapter.set
diff --git a/spring-boot-rest/src/main/java/com/baeldung/transfer/LoginForm.java b/spring-boot-rest/src/main/java/com/baeldung/transfer/LoginForm.java
new file mode 100644
index 0000000000..caafcdb500
--- /dev/null
+++ b/spring-boot-rest/src/main/java/com/baeldung/transfer/LoginForm.java
@@ -0,0 +1,31 @@
+package com.baeldung.transfer;
+
+public class LoginForm {
+ private String username;
+ private String password;
+
+ public LoginForm() {
+ }
+
+ public LoginForm(String username, String password) {
+ super();
+ this.username = username;
+ this.password = password;
+ }
+
+ public String getUsername() {
+ return username;
+ }
+
+ public void setUsername(String username) {
+ this.username = username;
+ }
+
+ public String getPassword() {
+ return password;
+ }
+
+ public void setPassword(String password) {
+ this.password = password;
+ }
+}
\ No newline at end of file
diff --git a/spring-rest/src/main/java/com/baeldung/transfer/ResponseTransfer.java b/spring-boot-rest/src/main/java/com/baeldung/transfer/ResponseTransfer.java
similarity index 100%
rename from spring-rest/src/main/java/com/baeldung/transfer/ResponseTransfer.java
rename to spring-boot-rest/src/main/java/com/baeldung/transfer/ResponseTransfer.java
diff --git a/spring-security-rest/src/main/java/org/baeldung/web/controller/CustomerController.java b/spring-boot-rest/src/main/java/com/baeldung/web/controller/CustomerController.java
similarity index 64%
rename from spring-security-rest/src/main/java/org/baeldung/web/controller/CustomerController.java
rename to spring-boot-rest/src/main/java/com/baeldung/web/controller/CustomerController.java
index e1db105d18..91aa9f2144 100644
--- a/spring-security-rest/src/main/java/org/baeldung/web/controller/CustomerController.java
+++ b/spring-boot-rest/src/main/java/com/baeldung/web/controller/CustomerController.java
@@ -1,24 +1,25 @@
-package org.baeldung.web.controller;
+package com.baeldung.web.controller;
import static org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo;
import static org.springframework.hateoas.mvc.ControllerLinkBuilder.methodOn;
import java.util.List;
-import org.baeldung.persistence.model.Customer;
-import org.baeldung.persistence.model.Order;
-import org.baeldung.web.service.CustomerService;
-import org.baeldung.web.service.OrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.hateoas.Link;
import org.springframework.hateoas.Resources;
import org.springframework.hateoas.config.EnableHypermediaSupport;
import org.springframework.hateoas.config.EnableHypermediaSupport.HypermediaType;
+import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
+import com.baeldung.persistence.model.Customer;
+import com.baeldung.persistence.model.Order;
+import com.baeldung.services.CustomerService;
+import com.baeldung.services.OrderService;
+
@RestController
@RequestMapping(value = "/customers")
@EnableHypermediaSupport(type = HypermediaType.HAL)
@@ -29,45 +30,49 @@ public class CustomerController {
@Autowired
private OrderService orderService;
- @RequestMapping(value = "/{customerId}", method = RequestMethod.GET)
+ @GetMapping("/{customerId}")
public Customer getCustomerById(@PathVariable final String customerId) {
return customerService.getCustomerDetail(customerId);
}
- @RequestMapping(value = "/{customerId}/{orderId}", method = RequestMethod.GET)
+ @GetMapping("/{customerId}/{orderId}")
public Order getOrderById(@PathVariable final String customerId, @PathVariable final String orderId) {
return orderService.getOrderByIdForCustomer(customerId, orderId);
}
- @RequestMapping(value = "/{customerId}/orders", method = RequestMethod.GET , produces = {"application/hal+json"})
+ @GetMapping(value = "/{customerId}/orders", produces = { "application/hal+json" })
public Resources getOrdersForCustomer(@PathVariable final String customerId) {
final List orders = orderService.getAllOrdersForCustomer(customerId);
for (final Order order : orders) {
- final Link selfLink = linkTo(methodOn(CustomerController.class).getOrderById(customerId, order.getOrderId())).withSelfRel();
+ final Link selfLink = linkTo(
+ methodOn(CustomerController.class).getOrderById(customerId, order.getOrderId())).withSelfRel();
order.add(selfLink);
}
-
- Link link =linkTo(methodOn(CustomerController.class).getOrdersForCustomer(customerId)).withSelfRel();
- Resources result = new Resources<>(orders,link);
+
+ Link link = linkTo(methodOn(CustomerController.class).getOrdersForCustomer(customerId)).withSelfRel();
+ Resources result = new Resources<>(orders, link);
return result;
}
- @RequestMapping(method = RequestMethod.GET, produces = {"application/hal+json"})
+ @GetMapping(produces = { "application/hal+json" })
public Resources getAllCustomers() {
final List allCustomers = customerService.allCustomers();
-
+
for (final Customer customer : allCustomers) {
String customerId = customer.getCustomerId();
- Link selfLink = linkTo(CustomerController.class).slash(customerId).withSelfRel();
+ Link selfLink = linkTo(CustomerController.class).slash(customerId)
+ .withSelfRel();
customer.add(selfLink);
- if (orderService.getAllOrdersForCustomer(customerId).size() > 0) {
- final Link ordersLink = linkTo(methodOn(CustomerController.class).getOrdersForCustomer(customerId)).withRel("allOrders");
+ if (orderService.getAllOrdersForCustomer(customerId)
+ .size() > 0) {
+ final Link ordersLink = linkTo(methodOn(CustomerController.class).getOrdersForCustomer(customerId))
+ .withRel("allOrders");
customer.add(ordersLink);
}
}
-
- Link link =linkTo(CustomerController.class).withSelfRel();
- Resources result = new Resources<>(allCustomers,link);
+
+ Link link = linkTo(CustomerController.class).withSelfRel();
+ Resources result = new Resources<>(allCustomers, link);
return result;
}
diff --git a/spring-rest/src/main/java/com/baeldung/controllers/ExamplePostController.java b/spring-boot-rest/src/main/java/com/baeldung/web/controller/ExamplePostController.java
similarity index 97%
rename from spring-rest/src/main/java/com/baeldung/controllers/ExamplePostController.java
rename to spring-boot-rest/src/main/java/com/baeldung/web/controller/ExamplePostController.java
index 93f96756b4..1519d95d4d 100644
--- a/spring-rest/src/main/java/com/baeldung/controllers/ExamplePostController.java
+++ b/spring-boot-rest/src/main/java/com/baeldung/web/controller/ExamplePostController.java
@@ -1,4 +1,4 @@
-package com.baeldung.controllers;
+package com.baeldung.web.controller;
import com.baeldung.services.ExampleService;
import com.baeldung.transfer.ResponseTransfer;
diff --git a/spring-boot-rest/src/test/java/com/baeldung/SpringContextIntegrationTest.java b/spring-boot-rest/src/test/java/com/baeldung/SpringContextIntegrationTest.java
index 25fbc4cc02..3db1ecb462 100644
--- a/spring-boot-rest/src/test/java/com/baeldung/SpringContextIntegrationTest.java
+++ b/spring-boot-rest/src/test/java/com/baeldung/SpringContextIntegrationTest.java
@@ -6,7 +6,7 @@ import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
-@SpringBootTest
+@SpringBootTest(classes = {SpringBootRestApplication.class})
public class SpringContextIntegrationTest {
@Test
diff --git a/spring-rest/src/test/java/com/baeldung/controllers/ExamplePostControllerRequestIntegrationTest.java b/spring-boot-rest/src/test/java/com/baeldung/controllers/ExamplePostControllerRequestIntegrationTest.java
similarity index 92%
rename from spring-rest/src/test/java/com/baeldung/controllers/ExamplePostControllerRequestIntegrationTest.java
rename to spring-boot-rest/src/test/java/com/baeldung/controllers/ExamplePostControllerRequestIntegrationTest.java
index 94b8bf40e7..fc533072c8 100644
--- a/spring-rest/src/test/java/com/baeldung/controllers/ExamplePostControllerRequestIntegrationTest.java
+++ b/spring-boot-rest/src/test/java/com/baeldung/controllers/ExamplePostControllerRequestIntegrationTest.java
@@ -1,8 +1,10 @@
package com.baeldung.controllers;
-import com.baeldung.sampleapp.config.MainApplication;
-import com.baeldung.services.ExampleService;
-import com.baeldung.transfer.LoginForm;
+import static org.mockito.Mockito.when;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
+import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -14,13 +16,13 @@ import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
-import static org.mockito.Mockito.when;
-import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
-import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
-import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+import com.baeldung.SpringBootRestApplication;
+import com.baeldung.services.ExampleService;
+import com.baeldung.transfer.LoginForm;
+import com.baeldung.web.controller.ExamplePostController;
@RunWith(SpringRunner.class)
-@SpringBootTest(classes = MainApplication.class)
+@SpringBootTest(classes = SpringBootRestApplication.class)
public class ExamplePostControllerRequestIntegrationTest {
MockMvc mockMvc;
diff --git a/spring-rest/src/test/java/com/baeldung/controllers/ExamplePostControllerResponseIntegrationTest.java b/spring-boot-rest/src/test/java/com/baeldung/controllers/ExamplePostControllerResponseIntegrationTest.java
similarity index 92%
rename from spring-rest/src/test/java/com/baeldung/controllers/ExamplePostControllerResponseIntegrationTest.java
rename to spring-boot-rest/src/test/java/com/baeldung/controllers/ExamplePostControllerResponseIntegrationTest.java
index 5743ad450b..cbe21b1d90 100644
--- a/spring-rest/src/test/java/com/baeldung/controllers/ExamplePostControllerResponseIntegrationTest.java
+++ b/spring-boot-rest/src/test/java/com/baeldung/controllers/ExamplePostControllerResponseIntegrationTest.java
@@ -1,8 +1,11 @@
package com.baeldung.controllers;
-import com.baeldung.sampleapp.config.MainApplication;
-import com.baeldung.services.ExampleService;
-import com.baeldung.transfer.LoginForm;
+import static org.mockito.Mockito.when;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
+import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -11,18 +14,16 @@ import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
-
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
-import static org.mockito.Mockito.when;
-import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
-import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
-import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
-import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+import com.baeldung.SpringBootRestApplication;
+import com.baeldung.services.ExampleService;
+import com.baeldung.transfer.LoginForm;
+import com.baeldung.web.controller.ExamplePostController;
@RunWith(SpringRunner.class)
-@SpringBootTest(classes = MainApplication.class)
+@SpringBootTest(classes = SpringBootRestApplication.class)
public class ExamplePostControllerResponseIntegrationTest {
MockMvc mockMvc;
diff --git a/spring-boot/src/test/java/com/baeldung/modelmapper/PostDtoUnitTest.java b/spring-boot-rest/src/test/java/com/baeldung/modelmapper/PostDtoUnitTest.java
similarity index 100%
rename from spring-boot/src/test/java/com/baeldung/modelmapper/PostDtoUnitTest.java
rename to spring-boot-rest/src/test/java/com/baeldung/modelmapper/PostDtoUnitTest.java
diff --git a/spring-boot-rest/src/test/java/com/baeldung/rest/GitHubUser.java b/spring-boot-rest/src/test/java/com/baeldung/rest/GitHubUser.java
new file mode 100644
index 0000000000..da5085ab12
--- /dev/null
+++ b/spring-boot-rest/src/test/java/com/baeldung/rest/GitHubUser.java
@@ -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;
+ }
+
+}
diff --git a/testing-modules/rest-testing/src/test/java/org/baeldung/rest/GithubBasicLiveTest.java b/spring-boot-rest/src/test/java/com/baeldung/rest/GithubBasicLiveTest.java
similarity index 98%
rename from testing-modules/rest-testing/src/test/java/org/baeldung/rest/GithubBasicLiveTest.java
rename to spring-boot-rest/src/test/java/com/baeldung/rest/GithubBasicLiveTest.java
index acac82c8f4..3082b34421 100644
--- a/testing-modules/rest-testing/src/test/java/org/baeldung/rest/GithubBasicLiveTest.java
+++ b/spring-boot-rest/src/test/java/com/baeldung/rest/GithubBasicLiveTest.java
@@ -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;
diff --git a/spring-boot-rest/src/test/java/com/baeldung/rest/RetrieveUtil.java b/spring-boot-rest/src/test/java/com/baeldung/rest/RetrieveUtil.java
new file mode 100644
index 0000000000..0ec36bc3ae
--- /dev/null
+++ b/spring-boot-rest/src/test/java/com/baeldung/rest/RetrieveUtil.java
@@ -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 retrieveResourceFromResponse(final HttpResponse response, final Class 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);
+ }
+
+}
diff --git a/spring-boot-rest/src/test/java/com/baeldung/springhateoas/CustomerControllerIntegrationTest.java b/spring-boot-rest/src/test/java/com/baeldung/springhateoas/CustomerControllerIntegrationTest.java
new file mode 100644
index 0000000000..b08da6d2cd
--- /dev/null
+++ b/spring-boot-rest/src/test/java/com/baeldung/springhateoas/CustomerControllerIntegrationTest.java
@@ -0,0 +1,98 @@
+package com.baeldung.springhateoas;
+
+import static org.hamcrest.Matchers.is;
+import static org.mockito.BDDMockito.given;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
+import org.springframework.boot.test.mock.mockito.MockBean;
+import org.springframework.hateoas.MediaTypes;
+import org.springframework.test.context.junit4.SpringRunner;
+import org.springframework.test.web.servlet.MockMvc;
+
+import com.baeldung.persistence.model.Customer;
+import com.baeldung.persistence.model.Order;
+import com.baeldung.services.CustomerService;
+import com.baeldung.services.OrderService;
+import com.baeldung.web.controller.CustomerController;
+
+@RunWith(SpringRunner.class)
+@WebMvcTest(CustomerController.class)
+public class CustomerControllerIntegrationTest {
+
+ @Autowired
+ private MockMvc mvc;
+
+ @MockBean
+ private CustomerService customerService;
+
+ @MockBean
+ private OrderService orderService;
+
+ private static final String DEFAULT_CUSTOMER_ID = "customer1";
+ private static final String DEFAULT_ORDER_ID = "order1";
+
+ @Test
+ public void givenExistingCustomer_whenCustomerRequested_thenResourceRetrieved() throws Exception {
+ given(this.customerService.getCustomerDetail(DEFAULT_CUSTOMER_ID))
+ .willReturn(new Customer(DEFAULT_CUSTOMER_ID, "customerJohn", "companyOne"));
+
+ this.mvc.perform(get("/customers/" + DEFAULT_CUSTOMER_ID))
+ .andExpect(status().isOk())
+ .andExpect(jsonPath("$._links").doesNotExist())
+ .andExpect(jsonPath("$.customerId", is(DEFAULT_CUSTOMER_ID)));
+ }
+
+ @Test
+ public void givenExistingOrder_whenOrderRequested_thenResourceRetrieved() throws Exception {
+ given(this.orderService.getOrderByIdForCustomer(DEFAULT_CUSTOMER_ID, DEFAULT_ORDER_ID))
+ .willReturn(new Order(DEFAULT_ORDER_ID, 1., 1));
+
+ this.mvc.perform(get("/customers/" + DEFAULT_CUSTOMER_ID + "/" + DEFAULT_ORDER_ID))
+ .andExpect(status().isOk())
+ .andExpect(jsonPath("$._links").doesNotExist())
+ .andExpect(jsonPath("$.orderId", is(DEFAULT_ORDER_ID)));
+ }
+
+ @Test
+ public void givenExistingCustomerWithOrders_whenOrdersRequested_thenHalResourceRetrieved() throws Exception {
+ Order order1 = new Order(DEFAULT_ORDER_ID, 1., 1);
+ List orders = Collections.singletonList(order1);
+ given(this.orderService.getAllOrdersForCustomer(DEFAULT_CUSTOMER_ID)).willReturn(orders);
+
+ this.mvc.perform(get("/customers/" + DEFAULT_CUSTOMER_ID + "/orders").accept(MediaTypes.HAL_JSON_VALUE))
+ .andExpect(status().isOk())
+ .andExpect(jsonPath("$._embedded.orderList[0]._links.self.href",
+ is("http://localhost/customers/customer1/order1")))
+ .andExpect(jsonPath("$._links.self.href", is("http://localhost/customers/customer1/orders")));
+ }
+
+ @Test
+ public void givenExistingCustomer_whenAllCustomersRequested_thenHalResourceRetrieved() throws Exception {
+ // customers
+ Customer retrievedCustomer = new Customer(DEFAULT_CUSTOMER_ID, "customerJohn", "companyOne");
+ List customers = Collections.singletonList(retrievedCustomer);
+ given(this.customerService.allCustomers()).willReturn(customers);
+ // orders
+ Order order1 = new Order(DEFAULT_ORDER_ID, 1., 1);
+ List orders = Collections.singletonList(order1);
+ given(this.orderService.getAllOrdersForCustomer(DEFAULT_CUSTOMER_ID)).willReturn(orders);
+
+ this.mvc.perform(get("/customers/").accept(MediaTypes.HAL_JSON_VALUE))
+ .andExpect(status().isOk())
+ .andExpect(
+ jsonPath("$._embedded.customerList[0]._links.self.href", is("http://localhost/customers/customer1")))
+ .andExpect(jsonPath("$._embedded.customerList[0]._links.allOrders.href",
+ is("http://localhost/customers/customer1/orders")))
+ .andExpect(jsonPath("$._links.self.href", is("http://localhost/customers")));
+ }
+
+}
diff --git a/spring-boot-testing/src/main/java/com/baeldung/component/OtherComponent.java b/spring-boot-testing/src/main/java/com/baeldung/component/OtherComponent.java
new file mode 100644
index 0000000000..97f001a9e5
--- /dev/null
+++ b/spring-boot-testing/src/main/java/com/baeldung/component/OtherComponent.java
@@ -0,0 +1,19 @@
+package com.baeldung.component;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+
+@Component
+public class OtherComponent {
+
+ private static final Logger LOG = LoggerFactory.getLogger(OtherComponent.class);
+
+ public void processData() {
+ LOG.trace("This is a TRACE log from another package");
+ LOG.debug("This is a DEBUG log from another package");
+ LOG.info("This is an INFO log from another package");
+ LOG.error("This is an ERROR log from another package");
+ }
+
+}
diff --git a/spring-boot-testing/src/main/java/com/baeldung/testloglevel/TestLogLevelApplication.java b/spring-boot-testing/src/main/java/com/baeldung/testloglevel/TestLogLevelApplication.java
new file mode 100644
index 0000000000..ed8218c6a3
--- /dev/null
+++ b/spring-boot-testing/src/main/java/com/baeldung/testloglevel/TestLogLevelApplication.java
@@ -0,0 +1,15 @@
+package com.baeldung.testloglevel;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+import com.baeldung.boot.Application;
+
+@SpringBootApplication(scanBasePackages = {"com.baeldung.testloglevel", "com.baeldung.component"})
+public class TestLogLevelApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Application.class, args);
+ }
+
+}
diff --git a/spring-boot-testing/src/main/java/com/baeldung/testloglevel/TestLogLevelController.java b/spring-boot-testing/src/main/java/com/baeldung/testloglevel/TestLogLevelController.java
new file mode 100644
index 0000000000..22078562b4
--- /dev/null
+++ b/spring-boot-testing/src/main/java/com/baeldung/testloglevel/TestLogLevelController.java
@@ -0,0 +1,31 @@
+package com.baeldung.testloglevel;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.baeldung.component.OtherComponent;
+
+@RestController
+public class TestLogLevelController {
+
+ private static final Logger LOG = LoggerFactory.getLogger(TestLogLevelController.class);
+
+ @Autowired
+ private OtherComponent otherComponent;
+
+ @GetMapping("/testLogLevel")
+ public String testLogLevel() {
+ LOG.trace("This is a TRACE log");
+ LOG.debug("This is a DEBUG log");
+ LOG.info("This is an INFO log");
+ LOG.error("This is an ERROR log");
+
+ otherComponent.processData();
+
+ return "Added some log output to console...";
+ }
+
+}
diff --git a/spring-boot-testing/src/test/java/com/baeldung/testloglevel/LogbackMultiProfileTestLogLevelIntegrationTest.java b/spring-boot-testing/src/test/java/com/baeldung/testloglevel/LogbackMultiProfileTestLogLevelIntegrationTest.java
new file mode 100644
index 0000000000..7a1eb4adbe
--- /dev/null
+++ b/spring-boot-testing/src/test/java/com/baeldung/testloglevel/LogbackMultiProfileTestLogLevelIntegrationTest.java
@@ -0,0 +1,70 @@
+package com.baeldung.testloglevel;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
+import org.springframework.boot.test.rule.OutputCapture;
+import org.springframework.boot.test.web.client.TestRestTemplate;
+import org.springframework.http.ResponseEntity;
+import org.springframework.test.context.ActiveProfiles;
+import org.springframework.test.context.junit4.SpringRunner;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT, classes = TestLogLevelApplication.class)
+@EnableAutoConfiguration(exclude = SecurityAutoConfiguration.class)
+@ActiveProfiles("logback-test2")
+public class LogbackMultiProfileTestLogLevelIntegrationTest {
+
+ @Autowired
+ private TestRestTemplate restTemplate;
+
+ @Rule
+ public OutputCapture outputCapture = new OutputCapture();
+
+ private String baseUrl = "/testLogLevel";
+
+ @Test
+ public void givenErrorRootLevelAndTraceLevelForOurPackage_whenCall_thenPrintTraceLogsForOurPackage() {
+ ResponseEntity response = restTemplate.getForEntity(baseUrl, String.class);
+
+ assertThat(response.getStatusCode().value()).isEqualTo(200);
+ assertThatOutputContainsLogForOurPackage("TRACE");
+ }
+
+ @Test
+ public void givenErrorRootLevelAndTraceLevelForOurPackage_whenCall_thenNoTraceLogsForOtherPackages() {
+ ResponseEntity response = restTemplate.getForEntity(baseUrl, String.class);
+
+ assertThat(response.getStatusCode().value()).isEqualTo(200);
+ assertThatOutputDoesntContainLogForOtherPackages("TRACE");
+ }
+
+ @Test
+ public void givenErrorRootLevelAndTraceLevelForOurPackage_whenCall_thenPrintErrorLogs() {
+ ResponseEntity response = restTemplate.getForEntity(baseUrl, String.class);
+
+ assertThat(response.getStatusCode().value()).isEqualTo(200);
+ assertThatOutputContainsLogForOurPackage("ERROR");
+ assertThatOutputContainsLogForOtherPackages("ERROR");
+ }
+
+ private void assertThatOutputContainsLogForOurPackage(String level) {
+ assertThat(outputCapture.toString()).containsPattern("TestLogLevelController.*" + level + ".*");
+ }
+
+ private void assertThatOutputDoesntContainLogForOtherPackages(String level) {
+ assertThat(outputCapture.toString().replaceAll("(?m)^.*TestLogLevelController.*$", "")).doesNotContain(level);
+ }
+
+ private void assertThatOutputContainsLogForOtherPackages(String level) {
+ assertThat(outputCapture.toString().replaceAll("(?m)^.*TestLogLevelController.*$", "")).contains(level);
+ }
+
+}
diff --git a/spring-boot-testing/src/test/java/com/baeldung/testloglevel/LogbackTestLogLevelIntegrationTest.java b/spring-boot-testing/src/test/java/com/baeldung/testloglevel/LogbackTestLogLevelIntegrationTest.java
new file mode 100644
index 0000000000..af3bafdc2e
--- /dev/null
+++ b/spring-boot-testing/src/test/java/com/baeldung/testloglevel/LogbackTestLogLevelIntegrationTest.java
@@ -0,0 +1,70 @@
+package com.baeldung.testloglevel;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
+import org.springframework.boot.test.rule.OutputCapture;
+import org.springframework.boot.test.web.client.TestRestTemplate;
+import org.springframework.http.ResponseEntity;
+import org.springframework.test.context.ActiveProfiles;
+import org.springframework.test.context.junit4.SpringRunner;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT, classes = TestLogLevelApplication.class)
+@EnableAutoConfiguration(exclude = SecurityAutoConfiguration.class)
+@ActiveProfiles("logback-test")
+public class LogbackTestLogLevelIntegrationTest {
+
+ @Autowired
+ private TestRestTemplate restTemplate;
+
+ @Rule
+ public OutputCapture outputCapture = new OutputCapture();
+
+ private String baseUrl = "/testLogLevel";
+
+ @Test
+ public void givenErrorRootLevelAndDebugLevelForOurPackage_whenCall_thenPrintDebugLogsForOurPackage() {
+ ResponseEntity response = restTemplate.getForEntity(baseUrl, String.class);
+
+ assertThat(response.getStatusCode().value()).isEqualTo(200);
+ assertThatOutputContainsLogForOurPackage("DEBUG");
+ }
+
+ @Test
+ public void givenErrorRootLevelAndDebugLevelForOurPackage_whenCall_thenNoDebugLogsForOtherPackages() {
+ ResponseEntity response = restTemplate.getForEntity(baseUrl, String.class);
+
+ assertThat(response.getStatusCode().value()).isEqualTo(200);
+ assertThatOutputDoesntContainLogForOtherPackages("DEBUG");
+ }
+
+ @Test
+ public void givenErrorRootLevelAndDebugLevelForOurPackage_whenCall_thenPrintErrorLogs() {
+ ResponseEntity response = restTemplate.getForEntity(baseUrl, String.class);
+
+ assertThat(response.getStatusCode().value()).isEqualTo(200);
+ assertThatOutputContainsLogForOurPackage("ERROR");
+ assertThatOutputContainsLogForOtherPackages("ERROR");
+ }
+
+ private void assertThatOutputContainsLogForOurPackage(String level) {
+ assertThat(outputCapture.toString()).containsPattern("TestLogLevelController.*" + level + ".*");
+ }
+
+ private void assertThatOutputDoesntContainLogForOtherPackages(String level) {
+ assertThat(outputCapture.toString().replaceAll("(?m)^.*TestLogLevelController.*$", "")).doesNotContain(level);
+ }
+
+ private void assertThatOutputContainsLogForOtherPackages(String level) {
+ assertThat(outputCapture.toString().replaceAll("(?m)^.*TestLogLevelController.*$", "")).contains(level);
+ }
+
+}
diff --git a/spring-boot-testing/src/test/java/com/baeldung/testloglevel/TestLogLevelWithProfileIntegrationTest.java b/spring-boot-testing/src/test/java/com/baeldung/testloglevel/TestLogLevelWithProfileIntegrationTest.java
new file mode 100644
index 0000000000..5609ce6c01
--- /dev/null
+++ b/spring-boot-testing/src/test/java/com/baeldung/testloglevel/TestLogLevelWithProfileIntegrationTest.java
@@ -0,0 +1,70 @@
+package com.baeldung.testloglevel;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
+import org.springframework.boot.test.rule.OutputCapture;
+import org.springframework.boot.test.web.client.TestRestTemplate;
+import org.springframework.http.ResponseEntity;
+import org.springframework.test.context.ActiveProfiles;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT, classes = TestLogLevelApplication.class)
+@EnableAutoConfiguration(exclude = SecurityAutoConfiguration.class)
+@ActiveProfiles("logging-test")
+public class TestLogLevelWithProfileIntegrationTest {
+
+ @Autowired
+ private TestRestTemplate restTemplate;
+
+ @Rule
+ public OutputCapture outputCapture = new OutputCapture();
+
+ private String baseUrl = "/testLogLevel";
+
+ @Test
+ public void givenInfoRootLevelAndDebugLevelForOurPackage_whenCall_thenPrintDebugLogsForOurPackage() {
+ ResponseEntity response = restTemplate.getForEntity(baseUrl, String.class);
+
+ assertThat(response.getStatusCode().value()).isEqualTo(200);
+ assertThatOutputContainsLogForOurPackage("DEBUG");
+ }
+
+ @Test
+ public void givenInfoRootLevelAndDebugLevelForOurPackage_whenCall_thenNoDebugLogsForOtherPackages() {
+ ResponseEntity response = restTemplate.getForEntity(baseUrl, String.class);
+
+ assertThat(response.getStatusCode().value()).isEqualTo(200);
+ assertThatOutputDoesntContainLogForOtherPackages("DEBUG");
+ }
+
+ @Test
+ public void givenInfoRootLevelAndDebugLevelForOurPackage_whenCall_thenPrintInfoLogs() {
+ ResponseEntity response = restTemplate.getForEntity(baseUrl, String.class);
+
+ assertThat(response.getStatusCode().value()).isEqualTo(200);
+ assertThatOutputContainsLogForOurPackage("INFO");
+ assertThatOutputContainsLogForOtherPackages("INFO");
+ }
+
+ private void assertThatOutputContainsLogForOurPackage(String level) {
+ assertThat(outputCapture.toString()).containsPattern("TestLogLevelController.*" + level + ".*");
+ }
+
+ private void assertThatOutputDoesntContainLogForOtherPackages(String level) {
+ assertThat(outputCapture.toString().replaceAll("(?m)^.*TestLogLevelController.*$", "")).doesNotContain(level);
+ }
+
+ private void assertThatOutputContainsLogForOtherPackages(String level) {
+ assertThat(outputCapture.toString().replaceAll("(?m)^.*TestLogLevelController.*$", "")).contains(level);
+ }
+
+}
diff --git a/spring-boot-testing/src/test/resources/application-logback-test.properties b/spring-boot-testing/src/test/resources/application-logback-test.properties
new file mode 100644
index 0000000000..587302fa01
--- /dev/null
+++ b/spring-boot-testing/src/test/resources/application-logback-test.properties
@@ -0,0 +1 @@
+logging.config=classpath:logback-test.xml
diff --git a/spring-boot-testing/src/test/resources/application-logback-test2.properties b/spring-boot-testing/src/test/resources/application-logback-test2.properties
new file mode 100644
index 0000000000..aeed46e3ca
--- /dev/null
+++ b/spring-boot-testing/src/test/resources/application-logback-test2.properties
@@ -0,0 +1 @@
+logging.config=classpath:logback-multiprofile.xml
\ No newline at end of file
diff --git a/spring-boot-testing/src/test/resources/application-logging-test.properties b/spring-boot-testing/src/test/resources/application-logging-test.properties
new file mode 100644
index 0000000000..b5adb4cc11
--- /dev/null
+++ b/spring-boot-testing/src/test/resources/application-logging-test.properties
@@ -0,0 +1,2 @@
+logging.level.com.baeldung.testloglevel=DEBUG
+logging.level.root=INFO
\ No newline at end of file
diff --git a/spring-boot-testing/src/test/resources/logback-multiprofile.xml b/spring-boot-testing/src/test/resources/logback-multiprofile.xml
new file mode 100644
index 0000000000..be790234f2
--- /dev/null
+++ b/spring-boot-testing/src/test/resources/logback-multiprofile.xml
@@ -0,0 +1,18 @@
+
+
+
+
+ %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/spring-boot-testing/src/test/resources/logback-test.xml b/spring-boot-testing/src/test/resources/logback-test.xml
new file mode 100644
index 0000000000..0528aa88f3
--- /dev/null
+++ b/spring-boot-testing/src/test/resources/logback-test.xml
@@ -0,0 +1,13 @@
+
+
+
+
+ %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
+
+
+
+
+
+
+
+
diff --git a/spring-boot/README.MD b/spring-boot/README.MD
index 7d270c9c25..c0392d38de 100644
--- a/spring-boot/README.MD
+++ b/spring-boot/README.MD
@@ -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)
@@ -35,5 +35,4 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring
- [Display Auto-Configuration Report in Spring Boot](https://www.baeldung.com/spring-boot-auto-configuration-report)
- [Injecting Git Information Into Spring](https://www.baeldung.com/spring-git-information)
- [Validation in Spring Boot](https://www.baeldung.com/spring-boot-bean-validation)
-- [Entity To DTO Conversion for a Spring REST API](https://www.baeldung.com/entity-to-and-from-dto-for-a-java-spring-application)
- [Guide to Creating and Running a Jar File in Java](https://www.baeldung.com/java-create-jar)
diff --git a/spring-boot/pom.xml b/spring-boot/pom.xml
index ed2d8259df..401e0289e8 100644
--- a/spring-boot/pom.xml
+++ b/spring-boot/pom.xml
@@ -153,12 +153,6 @@
javax.validation
validation-api
-
-
- org.modelmapper
- modelmapper
- ${modelmapper.version}
-
@@ -256,7 +250,6 @@
5.2.4
18.0
2.2.4
- 2.3.2
diff --git a/spring-boot/src/main/java/com/baeldung/modelmapper/PostApplication.java b/spring-boot/src/main/java/com/baeldung/modelmapper/PostApplication.java
deleted file mode 100644
index 7684c43648..0000000000
--- a/spring-boot/src/main/java/com/baeldung/modelmapper/PostApplication.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package com.baeldung.modelmapper;
-
-import org.modelmapper.ModelMapper;
-import org.springframework.boot.SpringApplication;
-import org.springframework.boot.autoconfigure.SpringBootApplication;
-import org.springframework.context.annotation.Bean;
-
-@SpringBootApplication
-public class PostApplication {
-
- public static void main(String[] args) {
- SpringApplication.run(PostApplication.class, args);
- }
-
- @Bean
- public ModelMapper modelMapper() {
- return new ModelMapper();
- }
-
-}
diff --git a/spring-boot/src/main/java/org/baeldung/properties/ConfigProperties.java b/spring-boot/src/main/java/org/baeldung/properties/ConfigProperties.java
index 3698d8ef30..1a3c985fe4 100644
--- a/spring-boot/src/main/java/org/baeldung/properties/ConfigProperties.java
+++ b/spring-boot/src/main/java/org/baeldung/properties/ConfigProperties.java
@@ -9,6 +9,7 @@ import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Pattern;
import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.validation.annotation.Validated;
@@ -80,4 +81,10 @@ public class ConfigProperties {
public void setCredentials(Credentials credentials) {
this.credentials = credentials;
}
+
+ @Bean
+ @ConfigurationProperties(prefix = "item")
+ public Item item(){
+ return new Item();
+ }
}
diff --git a/spring-boot/src/main/java/org/baeldung/properties/Item.java b/spring-boot/src/main/java/org/baeldung/properties/Item.java
new file mode 100644
index 0000000000..0314654ada
--- /dev/null
+++ b/spring-boot/src/main/java/org/baeldung/properties/Item.java
@@ -0,0 +1,31 @@
+package org.baeldung.properties;
+
+public class Item {
+
+ private String name;
+ private int size;
+
+ public Item() {
+ }
+
+ public Item(String name, int size) {
+ this.name = name;
+ this.size = size;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public int getSize() {
+ return size;
+ }
+
+ public void setSize(int size) {
+ this.size = size;
+ }
+}
diff --git a/spring-boot/src/main/resources/configprops.properties b/spring-boot/src/main/resources/configprops.properties
index 2dad11f9cc..424b3632f9 100644
--- a/spring-boot/src/main/resources/configprops.properties
+++ b/spring-boot/src/main/resources/configprops.properties
@@ -17,4 +17,8 @@ mail.credentials.username=john
mail.credentials.password=password
mail.credentials.authMethod=SHA1
+#Bean method properties
+item.name=Item name
+item.size=42
+
diff --git a/spring-boot/src/test/java/org/baeldung/properties/ConfigPropertiesIntegrationTest.java b/spring-boot/src/test/java/org/baeldung/properties/ConfigPropertiesIntegrationTest.java
index 4ba6bf29d8..f864fd4f8c 100644
--- a/spring-boot/src/test/java/org/baeldung/properties/ConfigPropertiesIntegrationTest.java
+++ b/spring-boot/src/test/java/org/baeldung/properties/ConfigPropertiesIntegrationTest.java
@@ -53,4 +53,11 @@ public class ConfigPropertiesIntegrationTest {
Assert.assertEquals("Incorrectly bound object property, username", "john", credentials.getUsername());
Assert.assertEquals("Incorrectly bound object property, password", "password", credentials.getPassword());
}
+
+ @Test
+ public void whenBeanMethodAnnotatedThenPropertiesCorrectlyBound(){
+ Item item = properties.item();
+ Assert.assertEquals("Incorrectly bound object property, item.name","Test item name", item.getName());
+ Assert.assertEquals("Incorrectly bound object property, item.size", 21, item.getSize());
+ }
}
diff --git a/spring-boot/src/test/resources/configprops-test.properties b/spring-boot/src/test/resources/configprops-test.properties
index 697771ae6e..ea11f2159e 100644
--- a/spring-boot/src/test/resources/configprops-test.properties
+++ b/spring-boot/src/test/resources/configprops-test.properties
@@ -17,3 +17,6 @@ mail.credentials.username=john
mail.credentials.password=password
mail.credentials.authMethod=SHA1
+#Bean method properties
+item.name=Test item name
+item.size=21
diff --git a/spring-cloud/pom.xml b/spring-cloud/pom.xml
index bf70e0284c..baf86a4386 100644
--- a/spring-cloud/pom.xml
+++ b/spring-cloud/pom.xml
@@ -32,7 +32,6 @@
spring-cloud-zuul-eureka-integration
spring-cloud-contract
spring-cloud-kubernetes
- spring-cloud-kubernetes-2
spring-cloud-archaius
spring-cloud-functions
spring-cloud-vault
diff --git a/spring-cloud/spring-cloud-archaius/basic-config/src/test/java/com/baeldung/spring/cloud/archaius/basic/ArchaiusBasicConfigurationIntegrationTest.java b/spring-cloud/spring-cloud-archaius/basic-config/src/test/java/com/baeldung/spring/cloud/archaius/basic/ArchaiusBasicConfigurationIntegrationTest.java
index 2948606c0b..d49a8dfa7e 100644
--- a/spring-cloud/spring-cloud-archaius/basic-config/src/test/java/com/baeldung/spring/cloud/archaius/basic/ArchaiusBasicConfigurationIntegrationTest.java
+++ b/spring-cloud/spring-cloud-archaius/basic-config/src/test/java/com/baeldung/spring/cloud/archaius/basic/ArchaiusBasicConfigurationIntegrationTest.java
@@ -5,21 +5,18 @@ import static org.assertj.core.api.Assertions.assertThat;
import java.util.Collections;
import org.junit.Test;
-import org.junit.jupiter.api.extension.ExtendWith;
-import org.junit.platform.runner.JUnitPlatform;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.util.TestPropertyValues;
import org.springframework.cloud.context.environment.EnvironmentChangeEvent;
import org.springframework.context.ConfigurableApplicationContext;
-import org.springframework.test.context.junit.jupiter.SpringExtension;
+import org.springframework.test.context.junit4.SpringRunner;
import com.netflix.config.DynamicPropertyFactory;
import com.netflix.config.DynamicStringProperty;
-@RunWith(JUnitPlatform.class)
-@ExtendWith(SpringExtension.class)
+@RunWith(SpringRunner.class)
@SpringBootTest
public class ArchaiusBasicConfigurationIntegrationTest {
diff --git a/spring-cloud/spring-cloud-archaius/dynamodb-config/src/test/java/com/baeldung/spring/cloud/archaius/dynamosources/SpringContextLiveTest.java b/spring-cloud/spring-cloud-archaius/dynamodb-config/src/test/java/com/baeldung/spring/cloud/archaius/dynamosources/SpringContextLiveTest.java
new file mode 100644
index 0000000000..a1a6c46c60
--- /dev/null
+++ b/spring-cloud/spring-cloud-archaius/dynamodb-config/src/test/java/com/baeldung/spring/cloud/archaius/dynamosources/SpringContextLiveTest.java
@@ -0,0 +1,20 @@
+package com.baeldung.spring.cloud.archaius.dynamosources;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+
+/**
+ * To run this Live Test we need to:
+ * * start a dynamodb instance locally on port 8000(e.g. with the following command `docker run -p 8000:8000 --name bael-dynamodb amazon/dynamodb-local`)
+ *
+ */
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = DynamoSourcesApplication.class)
+public class SpringContextLiveTest {
+
+ @Test
+ public void whenSpringContextIsBootstrapped_thenNoExceptions() {
+ }
+}
\ No newline at end of file
diff --git a/spring-cloud/spring-cloud-archaius/jdbc-config/src/test/java/com/baeldung/spring/cloud/archaius/jdbconfig/SpringContextIntegrationTest.java b/spring-cloud/spring-cloud-archaius/jdbc-config/src/test/java/com/baeldung/spring/cloud/archaius/jdbconfig/SpringContextIntegrationTest.java
new file mode 100644
index 0000000000..b3cd01e684
--- /dev/null
+++ b/spring-cloud/spring-cloud-archaius/jdbc-config/src/test/java/com/baeldung/spring/cloud/archaius/jdbconfig/SpringContextIntegrationTest.java
@@ -0,0 +1,15 @@
+package com.baeldung.spring.cloud.archaius.jdbconfig;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = JdbcSourcesApplication.class)
+public class SpringContextIntegrationTest {
+
+ @Test
+ public void whenSpringContextIsBootstrapped_thenNoExceptions() {
+ }
+}
\ No newline at end of file
diff --git a/spring-cloud/spring-cloud-archaius/zookeeper-config/src/test/java/com/baeldung/spring/cloud/archaius/zookeeperconfig/SpringContextLiveTest.java b/spring-cloud/spring-cloud-archaius/zookeeper-config/src/test/java/com/baeldung/spring/cloud/archaius/zookeeperconfig/SpringContextLiveTest.java
new file mode 100644
index 0000000000..a827b8e27d
--- /dev/null
+++ b/spring-cloud/spring-cloud-archaius/zookeeper-config/src/test/java/com/baeldung/spring/cloud/archaius/zookeeperconfig/SpringContextLiveTest.java
@@ -0,0 +1,20 @@
+package com.baeldung.spring.cloud.archaius.zookeeperconfig;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+
+/**
+ * This Live tTest requires:
+ * * A Zookeeper instance running locally on port 2181 (e.g. using `docker run --name bael-zookeeper -p 2181:2181 --restart always zookeeper`)
+ *
+ */
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = ZookeeperConfigApplication.class)
+public class SpringContextLiveTest {
+
+ @Test
+ public void whenSpringContextIsBootstrapped_thenNoExceptions() {
+ }
+}
\ No newline at end of file
diff --git a/spring-cloud/spring-cloud-aws/README.md b/spring-cloud/spring-cloud-aws/README.md
index 36d0c7080e..3b7b4dbcd7 100644
--- a/spring-cloud/spring-cloud-aws/README.md
+++ b/spring-cloud/spring-cloud-aws/README.md
@@ -8,7 +8,7 @@
#### Running the Integration Tests
-To run the Integration Tests, we need to have an AWS account and have API keys generated for programmatic access. Edit
+To run the Live Tests, we need to have an AWS account and have API keys generated for programmatic access. Edit
the `application.properties` file to add the following properties:
```
diff --git a/spring-cloud/spring-cloud-aws/src/test/java/com/baeldung/spring/cloud/aws/SpringContextLiveTest.java b/spring-cloud/spring-cloud-aws/src/test/java/com/baeldung/spring/cloud/aws/SpringContextLiveTest.java
new file mode 100644
index 0000000000..90ad9c518c
--- /dev/null
+++ b/spring-cloud/spring-cloud-aws/src/test/java/com/baeldung/spring/cloud/aws/SpringContextLiveTest.java
@@ -0,0 +1,22 @@
+package com.baeldung.spring.cloud.aws;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+
+/**
+ *
+ * To run this Live Test, we need to have an AWS account and have API keys generated for programmatic access.
+ *
+ * Check the README file in this module for more information.
+ *
+ */
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = SpringCloudAwsApplication.class)
+public class SpringContextLiveTest {
+
+ @Test
+ public void whenSpringContextIsBootstrapped_thenNoExceptions() {
+ }
+}
diff --git a/spring-cloud/spring-cloud-aws/src/test/java/com/baeldung/spring/cloud/aws/ec2/EC2MetadataIntegrationTest.java b/spring-cloud/spring-cloud-aws/src/test/java/com/baeldung/spring/cloud/aws/ec2/EC2MetadataLiveTest.java
similarity index 86%
rename from spring-cloud/spring-cloud-aws/src/test/java/com/baeldung/spring/cloud/aws/ec2/EC2MetadataIntegrationTest.java
rename to spring-cloud/spring-cloud-aws/src/test/java/com/baeldung/spring/cloud/aws/ec2/EC2MetadataLiveTest.java
index 1e75134194..853777ed25 100644
--- a/spring-cloud/spring-cloud-aws/src/test/java/com/baeldung/spring/cloud/aws/ec2/EC2MetadataIntegrationTest.java
+++ b/spring-cloud/spring-cloud-aws/src/test/java/com/baeldung/spring/cloud/aws/ec2/EC2MetadataLiveTest.java
@@ -16,12 +16,19 @@ import org.springframework.test.context.junit4.SpringRunner;
import com.amazonaws.regions.Regions;
import com.amazonaws.services.ec2.AmazonEC2;
+/**
+ *
+ * To run this Live Test, we need to have an AWS account and have API keys generated for programmatic access.
+ *
+ * Check the README file in this module for more information.
+ *
+ */
@SpringBootTest
@RunWith(SpringRunner.class)
@TestPropertySource("classpath:application-test.properties")
-public class EC2MetadataIntegrationTest {
+public class EC2MetadataLiveTest {
- private static final Logger logger = LoggerFactory.getLogger(EC2MetadataIntegrationTest.class);
+ private static final Logger logger = LoggerFactory.getLogger(EC2MetadataLiveTest.class);
private boolean serverEc2;
diff --git a/spring-cloud/spring-cloud-aws/src/test/java/com/baeldung/spring/cloud/aws/rds/SpringCloudRDSIntegrationTest.java b/spring-cloud/spring-cloud-aws/src/test/java/com/baeldung/spring/cloud/aws/rds/SpringCloudRDSLiveTest.java
similarity index 85%
rename from spring-cloud/spring-cloud-aws/src/test/java/com/baeldung/spring/cloud/aws/rds/SpringCloudRDSIntegrationTest.java
rename to spring-cloud/spring-cloud-aws/src/test/java/com/baeldung/spring/cloud/aws/rds/SpringCloudRDSLiveTest.java
index 9e163d6dc4..e7004c6b9f 100644
--- a/spring-cloud/spring-cloud-aws/src/test/java/com/baeldung/spring/cloud/aws/rds/SpringCloudRDSIntegrationTest.java
+++ b/spring-cloud/spring-cloud-aws/src/test/java/com/baeldung/spring/cloud/aws/rds/SpringCloudRDSLiveTest.java
@@ -14,9 +14,16 @@ import java.sql.Statement;
import static org.assertj.core.api.Assertions.assertThat;
+/**
+ *
+ * To run this Live Test, we need to have an AWS account and have API keys generated for programmatic access.
+ *
+ * Check the README file in this module for more information.
+ *
+ */
@SpringBootTest
@RunWith(SpringRunner.class)
-public class SpringCloudRDSIntegrationTest {
+public class SpringCloudRDSLiveTest {
@Autowired
DataSource dataSource;
diff --git a/spring-cloud/spring-cloud-aws/src/test/java/com/baeldung/spring/cloud/aws/s3/SpringCloudS3IntegrationTest.java b/spring-cloud/spring-cloud-aws/src/test/java/com/baeldung/spring/cloud/aws/s3/SpringCloudS3LiveTest.java
similarity index 94%
rename from spring-cloud/spring-cloud-aws/src/test/java/com/baeldung/spring/cloud/aws/s3/SpringCloudS3IntegrationTest.java
rename to spring-cloud/spring-cloud-aws/src/test/java/com/baeldung/spring/cloud/aws/s3/SpringCloudS3LiveTest.java
index a866287dec..dff3a06fe0 100644
--- a/spring-cloud/spring-cloud-aws/src/test/java/com/baeldung/spring/cloud/aws/s3/SpringCloudS3IntegrationTest.java
+++ b/spring-cloud/spring-cloud-aws/src/test/java/com/baeldung/spring/cloud/aws/s3/SpringCloudS3LiveTest.java
@@ -23,10 +23,17 @@ import java.util.UUID;
import static org.assertj.core.api.Assertions.assertThat;
+/**
+ *
+ * To run this Live Test, we need to have an AWS account and have API keys generated for programmatic access.
+ *
+ * Check the README file in this module for more information.
+ *
+ */
@SpringBootTest
@RunWith(SpringRunner.class)
@TestPropertySource("classpath:application-test.properties")
-public class SpringCloudS3IntegrationTest {
+public class SpringCloudS3LiveTest {
@Autowired
private SpringCloudS3 springCloudS3;
diff --git a/spring-cloud/spring-cloud-aws/src/test/java/com/baeldung/spring/cloud/aws/sns/SpringCloudSNSIntegrationTest.java b/spring-cloud/spring-cloud-aws/src/test/java/com/baeldung/spring/cloud/aws/sns/SpringCloudSNSLiveTest.java
similarity index 88%
rename from spring-cloud/spring-cloud-aws/src/test/java/com/baeldung/spring/cloud/aws/sns/SpringCloudSNSIntegrationTest.java
rename to spring-cloud/spring-cloud-aws/src/test/java/com/baeldung/spring/cloud/aws/sns/SpringCloudSNSLiveTest.java
index e1f23d5c76..b773520089 100644
--- a/spring-cloud/spring-cloud-aws/src/test/java/com/baeldung/spring/cloud/aws/sns/SpringCloudSNSIntegrationTest.java
+++ b/spring-cloud/spring-cloud-aws/src/test/java/com/baeldung/spring/cloud/aws/sns/SpringCloudSNSLiveTest.java
@@ -16,10 +16,17 @@ import com.amazonaws.services.sns.model.CreateTopicResult;
import com.baeldung.spring.cloud.aws.SpringCloudAwsTestUtil;
import com.baeldung.spring.cloud.aws.sqs.Greeting;
+/**
+ *
+ * To run this Live Test, we need to have an AWS account and have API keys generated for programmatic access.
+ *
+ * Check the README file in this module for more information.
+ *
+ */
@SpringBootTest
@RunWith(SpringRunner.class)
@TestPropertySource("classpath:application-test.properties")
-public class SpringCloudSNSIntegrationTest {
+public class SpringCloudSNSLiveTest {
@Autowired
private SNSMessageSender snsMessageSender;
diff --git a/spring-cloud/spring-cloud-aws/src/test/java/com/baeldung/spring/cloud/aws/sqs/SpringCloudSQSIntegrationTest.java b/spring-cloud/spring-cloud-aws/src/test/java/com/baeldung/spring/cloud/aws/sqs/SpringCloudSQSLiveTest.java
similarity index 95%
rename from spring-cloud/spring-cloud-aws/src/test/java/com/baeldung/spring/cloud/aws/sqs/SpringCloudSQSIntegrationTest.java
rename to spring-cloud/spring-cloud-aws/src/test/java/com/baeldung/spring/cloud/aws/sqs/SpringCloudSQSLiveTest.java
index 76d2fd7c0d..24917e52f1 100644
--- a/spring-cloud/spring-cloud-aws/src/test/java/com/baeldung/spring/cloud/aws/sqs/SpringCloudSQSIntegrationTest.java
+++ b/spring-cloud/spring-cloud-aws/src/test/java/com/baeldung/spring/cloud/aws/sqs/SpringCloudSQSLiveTest.java
@@ -26,12 +26,19 @@ import java.util.concurrent.CountDownLatch;
import static org.assertj.core.api.Assertions.assertThat;
+/**
+ *
+ * To run this Live Test, we need to have an AWS account and have API keys generated for programmatic access.
+ *
+ * Check the README file in this module for more information.
+ *
+ */
@SpringBootTest
@RunWith(SpringRunner.class)
@TestPropertySource("classpath:application-test.properties")
-public class SpringCloudSQSIntegrationTest {
+public class SpringCloudSQSLiveTest {
- private static final Logger logger = LoggerFactory.getLogger(SpringCloudSQSIntegrationTest.class);
+ private static final Logger logger = LoggerFactory.getLogger(SpringCloudSQSLiveTest.class);
@Autowired
@Lazy
diff --git a/spring-cloud/spring-cloud-bootstrap/README.MD b/spring-cloud/spring-cloud-bootstrap/README.MD
index 5185200469..7a3a94c8e3 100644
--- a/spring-cloud/spring-cloud-bootstrap/README.MD
+++ b/spring-cloud/spring-cloud-bootstrap/README.MD
@@ -6,7 +6,7 @@
- [Spring Cloud – Adding Angular 4](http://www.baeldung.com/spring-cloud-angular)
- To run the project:
- - copy the appliction-config folder to c:\Users\{username}\ on Windows or /Users/{username}/ on *nix. Then open a git bash terminal in application-config and run:
+ - copy the appliction-config folder to c:\Users\{username}\ on Windows or /home/{username}/ on *nix. Then open a git bash terminal in application-config and run:
- git init
- git add .
- git commit -m "First commit"
diff --git a/spring-cloud/spring-cloud-bootstrap/discovery/src/test/java/org/baeldung/SpringContextIntegrationTest.java b/spring-cloud/spring-cloud-bootstrap/discovery/src/test/java/org/baeldung/SpringContextLiveTest.java
similarity index 70%
rename from spring-cloud/spring-cloud-bootstrap/discovery/src/test/java/org/baeldung/SpringContextIntegrationTest.java
rename to spring-cloud/spring-cloud-bootstrap/discovery/src/test/java/org/baeldung/SpringContextLiveTest.java
index 1e2db33395..e4e2e95e04 100644
--- a/spring-cloud/spring-cloud-bootstrap/discovery/src/test/java/org/baeldung/SpringContextIntegrationTest.java
+++ b/spring-cloud/spring-cloud-bootstrap/discovery/src/test/java/org/baeldung/SpringContextLiveTest.java
@@ -7,9 +7,15 @@ import org.springframework.test.context.junit4.SpringRunner;
import com.baeldung.spring.cloud.bootstrap.discovery.DiscoveryApplication;
+/**
+ *
+ * This Live Test requires:
+ * * A Redis instance running in port 6379 (e.g. using `docker run --name some-redis -p 6379:6379 -d redis`)
+ *
+ */
@RunWith(SpringRunner.class)
@SpringBootTest(classes = DiscoveryApplication.class)
-public class SpringContextIntegrationTest {
+public class SpringContextLiveTest {
@Test
public void whenSpringContextIsBootstrapped_thenNoExceptions() {
diff --git a/spring-cloud/spring-cloud-bootstrap/gateway/pom.xml b/spring-cloud/spring-cloud-bootstrap/gateway/pom.xml
index 2efa926e3a..4f9c60a26a 100644
--- a/spring-cloud/spring-cloud-bootstrap/gateway/pom.xml
+++ b/spring-cloud/spring-cloud-bootstrap/gateway/pom.xml
@@ -98,6 +98,6 @@
- Brixton.SR7
+ Dalston.RELEASE
\ No newline at end of file
diff --git a/spring-cloud/spring-cloud-bootstrap/gateway/src/main/java/com/baeldung/spring/cloud/bootstrap/gateway/GatewayApplication.java b/spring-cloud/spring-cloud-bootstrap/gateway/src/main/java/com/baeldung/spring/cloud/bootstrap/gateway/GatewayApplication.java
index 10ed66bfd4..79785a3f20 100644
--- a/spring-cloud/spring-cloud-bootstrap/gateway/src/main/java/com/baeldung/spring/cloud/bootstrap/gateway/GatewayApplication.java
+++ b/spring-cloud/spring-cloud-bootstrap/gateway/src/main/java/com/baeldung/spring/cloud/bootstrap/gateway/GatewayApplication.java
@@ -71,7 +71,7 @@ public class GatewayApplication {
InstanceInfo instance = eurekaClient.getNextServerFromEureka("zipkin", false);
if (!(baseUrl != null && instance.getHomePageUrl().equals(baseUrl))) {
baseUrl = instance.getHomePageUrl();
- delegate = new HttpZipkinSpanReporter(baseUrl, zipkinProperties.getFlushInterval(), zipkinProperties.getCompression().isEnabled(), spanMetricReporter);
+ delegate = new HttpZipkinSpanReporter(new RestTemplate(), baseUrl, zipkinProperties.getFlushInterval(), spanMetricReporter);
if (!span.name.matches(skipPattern)) delegate.report(span);
}
if (!span.name.matches(skipPattern)) delegate.report(span);
diff --git a/spring-cloud/spring-cloud-bootstrap/gateway/src/test/java/org/baeldung/SpringContextIntegrationTest.java b/spring-cloud/spring-cloud-bootstrap/gateway/src/test/java/org/baeldung/SpringContextLiveTest.java
similarity index 70%
rename from spring-cloud/spring-cloud-bootstrap/gateway/src/test/java/org/baeldung/SpringContextIntegrationTest.java
rename to spring-cloud/spring-cloud-bootstrap/gateway/src/test/java/org/baeldung/SpringContextLiveTest.java
index ef3bb5ef95..e0342cf82c 100644
--- a/spring-cloud/spring-cloud-bootstrap/gateway/src/test/java/org/baeldung/SpringContextIntegrationTest.java
+++ b/spring-cloud/spring-cloud-bootstrap/gateway/src/test/java/org/baeldung/SpringContextLiveTest.java
@@ -7,9 +7,15 @@ import org.springframework.test.context.junit4.SpringRunner;
import com.baeldung.spring.cloud.bootstrap.gateway.GatewayApplication;
+/**
+ *
+ * This Live Test requires:
+ * * A Redis instance running in port 6379 (e.g. using `docker run --name some-redis -p 6379:6379 -d redis`)
+ *
+ */
@RunWith(SpringRunner.class)
@SpringBootTest(classes = GatewayApplication.class)
-public class SpringContextIntegrationTest {
+public class SpringContextLiveTest {
@Test
public void whenSpringContextIsBootstrapped_thenNoExceptions() {
diff --git a/spring-cloud/spring-cloud-bootstrap/gateway/src/test/resources/bootstrap.properties b/spring-cloud/spring-cloud-bootstrap/gateway/src/test/resources/bootstrap.properties
new file mode 100644
index 0000000000..c76df21ff1
--- /dev/null
+++ b/spring-cloud/spring-cloud-bootstrap/gateway/src/test/resources/bootstrap.properties
@@ -0,0 +1,2 @@
+# This property would be provided by the config service in a real-case scenario
+spring.sleuth.web.skipPattern=(^cleanup.|.+favicon.)
\ No newline at end of file
diff --git a/spring-cloud/spring-cloud-bootstrap/svc-book/pom.xml b/spring-cloud/spring-cloud-bootstrap/svc-book/pom.xml
index eb855a91e3..a88b77dda0 100644
--- a/spring-cloud/spring-cloud-bootstrap/svc-book/pom.xml
+++ b/spring-cloud/spring-cloud-bootstrap/svc-book/pom.xml
@@ -72,7 +72,7 @@
- Brixton.SR7
+ Dalston.RELEASE
\ No newline at end of file
diff --git a/spring-cloud/spring-cloud-bootstrap/svc-book/src/main/java/com/baeldung/spring/cloud/bootstrap/svcbook/BookServiceApplication.java b/spring-cloud/spring-cloud-bootstrap/svc-book/src/main/java/com/baeldung/spring/cloud/bootstrap/svcbook/BookServiceApplication.java
index 3d55a59dbc..91fd23e32d 100644
--- a/spring-cloud/spring-cloud-bootstrap/svc-book/src/main/java/com/baeldung/spring/cloud/bootstrap/svcbook/BookServiceApplication.java
+++ b/spring-cloud/spring-cloud-bootstrap/svc-book/src/main/java/com/baeldung/spring/cloud/bootstrap/svcbook/BookServiceApplication.java
@@ -12,6 +12,8 @@ import org.springframework.cloud.sleuth.zipkin.HttpZipkinSpanReporter;
import org.springframework.cloud.sleuth.zipkin.ZipkinProperties;
import org.springframework.cloud.sleuth.zipkin.ZipkinSpanReporter;
import org.springframework.context.annotation.Bean;
+import org.springframework.web.client.RestTemplate;
+
import zipkin.Span;
@SpringBootApplication
@@ -42,7 +44,7 @@ public class BookServiceApplication {
InstanceInfo instance = eurekaClient.getNextServerFromEureka("zipkin", false);
if (!(baseUrl != null && instance.getHomePageUrl().equals(baseUrl))) {
baseUrl = instance.getHomePageUrl();
- delegate = new HttpZipkinSpanReporter(baseUrl, zipkinProperties.getFlushInterval(), zipkinProperties.getCompression().isEnabled(), spanMetricReporter);
+ delegate = new HttpZipkinSpanReporter(new RestTemplate(), baseUrl, zipkinProperties.getFlushInterval(), spanMetricReporter);
if (!span.name.matches(skipPattern)) delegate.report(span);
}
}
diff --git a/spring-cloud/spring-cloud-bootstrap/svc-book/src/test/java/org/baeldung/SpringContextIntegrationTest.java b/spring-cloud/spring-cloud-bootstrap/svc-book/src/test/java/org/baeldung/SpringContextLiveTest.java
similarity index 70%
rename from spring-cloud/spring-cloud-bootstrap/svc-book/src/test/java/org/baeldung/SpringContextIntegrationTest.java
rename to spring-cloud/spring-cloud-bootstrap/svc-book/src/test/java/org/baeldung/SpringContextLiveTest.java
index 0ffc2410e3..2e437aa3f7 100644
--- a/spring-cloud/spring-cloud-bootstrap/svc-book/src/test/java/org/baeldung/SpringContextIntegrationTest.java
+++ b/spring-cloud/spring-cloud-bootstrap/svc-book/src/test/java/org/baeldung/SpringContextLiveTest.java
@@ -7,9 +7,15 @@ import org.springframework.test.context.junit4.SpringRunner;
import com.baeldung.spring.cloud.bootstrap.svcbook.BookServiceApplication;
+/**
+ *
+ * This Live Test requires:
+ * * A Redis instance running in port 6379 (e.g. using `docker run --name some-redis -p 6379:6379 -d redis`)
+ *
+ */
@RunWith(SpringRunner.class)
@SpringBootTest(classes = BookServiceApplication.class)
-public class SpringContextIntegrationTest {
+public class SpringContextLiveTest {
@Test
public void whenSpringContextIsBootstrapped_thenNoExceptions() {
diff --git a/spring-cloud/spring-cloud-bootstrap/svc-book/src/test/resources/bootstrap.properties b/spring-cloud/spring-cloud-bootstrap/svc-book/src/test/resources/bootstrap.properties
new file mode 100644
index 0000000000..c76df21ff1
--- /dev/null
+++ b/spring-cloud/spring-cloud-bootstrap/svc-book/src/test/resources/bootstrap.properties
@@ -0,0 +1,2 @@
+# This property would be provided by the config service in a real-case scenario
+spring.sleuth.web.skipPattern=(^cleanup.|.+favicon.)
\ No newline at end of file
diff --git a/spring-cloud/spring-cloud-bootstrap/svc-rating/pom.xml b/spring-cloud/spring-cloud-bootstrap/svc-rating/pom.xml
index 7c1e93bad1..f0b19922d8 100644
--- a/spring-cloud/spring-cloud-bootstrap/svc-rating/pom.xml
+++ b/spring-cloud/spring-cloud-bootstrap/svc-rating/pom.xml
@@ -81,7 +81,7 @@
- Brixton.SR7
+ Dalston.RELEASE
\ No newline at end of file
diff --git a/spring-cloud/spring-cloud-bootstrap/svc-rating/src/main/java/com/baeldung/spring/cloud/bootstrap/svcrating/RatingServiceApplication.java b/spring-cloud/spring-cloud-bootstrap/svc-rating/src/main/java/com/baeldung/spring/cloud/bootstrap/svcrating/RatingServiceApplication.java
index 31ca69c139..8dacbaa79d 100644
--- a/spring-cloud/spring-cloud-bootstrap/svc-rating/src/main/java/com/baeldung/spring/cloud/bootstrap/svcrating/RatingServiceApplication.java
+++ b/spring-cloud/spring-cloud-bootstrap/svc-rating/src/main/java/com/baeldung/spring/cloud/bootstrap/svcrating/RatingServiceApplication.java
@@ -16,6 +16,7 @@ import org.springframework.context.annotation.Primary;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.transaction.annotation.EnableTransactionManagement;
+import org.springframework.web.client.RestTemplate;
import com.netflix.appinfo.InstanceInfo;
import com.netflix.discovery.EurekaClient;
@@ -52,7 +53,7 @@ public class RatingServiceApplication {
InstanceInfo instance = eurekaClient.getNextServerFromEureka("zipkin", false);
if (!(baseUrl != null && instance.getHomePageUrl().equals(baseUrl))) {
baseUrl = instance.getHomePageUrl();
- delegate = new HttpZipkinSpanReporter(baseUrl, zipkinProperties.getFlushInterval(), zipkinProperties.getCompression().isEnabled(), spanMetricReporter);
+ delegate = new HttpZipkinSpanReporter(new RestTemplate(), baseUrl, zipkinProperties.getFlushInterval(), spanMetricReporter);
if (!span.name.matches(skipPattern)) delegate.report(span);
}
if (!span.name.matches(skipPattern)) delegate.report(span);
diff --git a/spring-cloud/spring-cloud-bootstrap/svc-rating/src/test/java/org/baeldung/SpringContextIntegrationTest.java b/spring-cloud/spring-cloud-bootstrap/svc-rating/src/test/java/org/baeldung/SpringContextLiveTest.java
similarity index 70%
rename from spring-cloud/spring-cloud-bootstrap/svc-rating/src/test/java/org/baeldung/SpringContextIntegrationTest.java
rename to spring-cloud/spring-cloud-bootstrap/svc-rating/src/test/java/org/baeldung/SpringContextLiveTest.java
index 3589666f17..e2921f0308 100644
--- a/spring-cloud/spring-cloud-bootstrap/svc-rating/src/test/java/org/baeldung/SpringContextIntegrationTest.java
+++ b/spring-cloud/spring-cloud-bootstrap/svc-rating/src/test/java/org/baeldung/SpringContextLiveTest.java
@@ -7,9 +7,16 @@ import org.springframework.test.context.junit4.SpringRunner;
import com.baeldung.spring.cloud.bootstrap.svcrating.RatingServiceApplication;
+
+/**
+ *
+ * This Live Test requires:
+ * * A Redis instance running in port 6379 (e.g. using `docker run --name some-redis -p 6379:6379 -d redis`)
+ *
+ */
@RunWith(SpringRunner.class)
@SpringBootTest(classes = RatingServiceApplication.class)
-public class SpringContextIntegrationTest {
+public class SpringContextLiveTest {
@Test
public void whenSpringContextIsBootstrapped_thenNoExceptions() {
diff --git a/spring-cloud/spring-cloud-bootstrap/svc-rating/src/test/resources/bootstrap.properties b/spring-cloud/spring-cloud-bootstrap/svc-rating/src/test/resources/bootstrap.properties
new file mode 100644
index 0000000000..c76df21ff1
--- /dev/null
+++ b/spring-cloud/spring-cloud-bootstrap/svc-rating/src/test/resources/bootstrap.properties
@@ -0,0 +1,2 @@
+# This property would be provided by the config service in a real-case scenario
+spring.sleuth.web.skipPattern=(^cleanup.|.+favicon.)
\ No newline at end of file
diff --git a/spring-cloud/spring-cloud-config/client/src/test/java/org/baeldung/SpringContextIntegrationTest.java b/spring-cloud/spring-cloud-config/client/src/test/java/com/baeldung/spring/cloud/config/client/SpringContextLiveTest.java
similarity index 69%
rename from spring-cloud/spring-cloud-config/client/src/test/java/org/baeldung/SpringContextIntegrationTest.java
rename to spring-cloud/spring-cloud-config/client/src/test/java/com/baeldung/spring/cloud/config/client/SpringContextLiveTest.java
index d727772cf9..3fb43b169d 100644
--- a/spring-cloud/spring-cloud-config/client/src/test/java/org/baeldung/SpringContextIntegrationTest.java
+++ b/spring-cloud/spring-cloud-config/client/src/test/java/com/baeldung/spring/cloud/config/client/SpringContextLiveTest.java
@@ -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() {
}
diff --git a/spring-cloud/spring-cloud-config/server/src/test/java/com/baeldung/spring/cloud/config/server/SpringContextLiveTest.java b/spring-cloud/spring-cloud-config/server/src/test/java/com/baeldung/spring/cloud/config/server/SpringContextIntegrationTest.java
similarity index 79%
rename from spring-cloud/spring-cloud-config/server/src/test/java/com/baeldung/spring/cloud/config/server/SpringContextLiveTest.java
rename to spring-cloud/spring-cloud-config/server/src/test/java/com/baeldung/spring/cloud/config/server/SpringContextIntegrationTest.java
index 793b4abb6c..b2c6ef85ea 100644
--- a/spring-cloud/spring-cloud-config/server/src/test/java/com/baeldung/spring/cloud/config/server/SpringContextLiveTest.java
+++ b/spring-cloud/spring-cloud-config/server/src/test/java/com/baeldung/spring/cloud/config/server/SpringContextIntegrationTest.java
@@ -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() {
}
diff --git a/spring-cloud/spring-cloud-config/server/src/test/resources/application.properties b/spring-cloud/spring-cloud-config/server/src/test/resources/application.properties
new file mode 100644
index 0000000000..67cc81ff67
--- /dev/null
+++ b/spring-cloud/spring-cloud-config/server/src/test/resources/application.properties
@@ -0,0 +1,2 @@
+### This should be provided by the docker config
+spring.cloud.config.server.git.uri=classpath:.
diff --git a/spring-cloud/spring-cloud-connectors-heroku/src/main/resources/application.properties b/spring-cloud/spring-cloud-connectors-heroku/src/main/resources/application.properties
index d2f1c89dc5..571f325824 100644
--- a/spring-cloud/spring-cloud-connectors-heroku/src/main/resources/application.properties
+++ b/spring-cloud/spring-cloud-connectors-heroku/src/main/resources/application.properties
@@ -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
\ No newline at end of file
diff --git a/spring-cloud/spring-cloud-connectors-heroku/src/test/java/org/baeldung/SpringContextIntegrationTest.java b/spring-cloud/spring-cloud-connectors-heroku/src/test/java/com/baeldung/spring/cloud/connectors/heroku/SpringContextIntegrationTest.java
similarity index 90%
rename from spring-cloud/spring-cloud-connectors-heroku/src/test/java/org/baeldung/SpringContextIntegrationTest.java
rename to spring-cloud/spring-cloud-connectors-heroku/src/test/java/com/baeldung/spring/cloud/connectors/heroku/SpringContextIntegrationTest.java
index a705f18bc6..dca4c25c71 100644
--- a/spring-cloud/spring-cloud-connectors-heroku/src/test/java/org/baeldung/SpringContextIntegrationTest.java
+++ b/spring-cloud/spring-cloud-connectors-heroku/src/test/java/com/baeldung/spring/cloud/connectors/heroku/SpringContextIntegrationTest.java
@@ -1,4 +1,4 @@
-package org.baeldung;
+package com.baeldung.spring.cloud.connectors.heroku;
import org.junit.Test;
import org.junit.runner.RunWith;
diff --git a/spring-cloud/spring-cloud-connectors-heroku/src/test/resources/application.properties b/spring-cloud/spring-cloud-connectors-heroku/src/test/resources/application.properties
new file mode 100644
index 0000000000..7b139ae07d
--- /dev/null
+++ b/spring-cloud/spring-cloud-connectors-heroku/src/test/resources/application.properties
@@ -0,0 +1,2 @@
+spring.jpa.hibernate.ddl-auto=create
+spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect
\ No newline at end of file
diff --git a/spring-cloud/spring-cloud-consul/src/test/java/org/baeldung/SpringContextIntegrationTest.java b/spring-cloud/spring-cloud-consul/src/test/java/com/baeldung/spring/cloud/consul/SpringContextLiveTest.java
similarity index 74%
rename from spring-cloud/spring-cloud-consul/src/test/java/org/baeldung/SpringContextIntegrationTest.java
rename to spring-cloud/spring-cloud-consul/src/test/java/com/baeldung/spring/cloud/consul/SpringContextLiveTest.java
index 6290ccc03e..7c87add43e 100644
--- a/spring-cloud/spring-cloud-consul/src/test/java/org/baeldung/SpringContextIntegrationTest.java
+++ b/spring-cloud/spring-cloud-consul/src/test/java/com/baeldung/spring/cloud/consul/SpringContextLiveTest.java
@@ -1,4 +1,4 @@
-package org.baeldung;
+package com.baeldung.spring.cloud.consul;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -9,10 +9,18 @@ import com.baeldung.spring.cloud.consul.discovery.DiscoveryClientApplication;
import com.baeldung.spring.cloud.consul.health.ServiceDiscoveryApplication;
import com.baeldung.spring.cloud.consul.properties.DistributedPropertiesApplication;
+
+/**
+ *
+ * This Live test requires:
+ * * a Consul instance running on port 8500
+ * * Consul configured with particular properties (e.g. 'my.prop')
+ *
+ */
@RunWith(SpringRunner.class)
@SpringBootTest(classes = { DiscoveryClientApplication.class, ServiceDiscoveryApplication.class,
DistributedPropertiesApplication.class })
-public class SpringContextIntegrationTest {
+public class SpringContextLiveTest {
@Test
public void whenSpringContextIsBootstrapped_thenNoExceptions() {
diff --git a/spring-cloud/spring-cloud-functions/src/test/java/com/baeldung/spring/cloudfunction/aws/SpringContextIntegrationTest.java b/spring-cloud/spring-cloud-functions/src/test/java/com/baeldung/spring/cloudfunction/aws/SpringContextIntegrationTest.java
new file mode 100644
index 0000000000..beee84246d
--- /dev/null
+++ b/spring-cloud/spring-cloud-functions/src/test/java/com/baeldung/spring/cloudfunction/aws/SpringContextIntegrationTest.java
@@ -0,0 +1,15 @@
+package com.baeldung.spring.cloudfunction.aws;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = CloudFunctionAwsApplication.class)
+public class SpringContextIntegrationTest {
+
+ @Test
+ public void whenSpringContextIsBootstrapped_thenNoExceptions() {
+ }
+}
\ No newline at end of file
diff --git a/spring-cloud/spring-cloud-kubernetes-2/pom.xml b/spring-cloud/spring-cloud-kubernetes-2/pom.xml
deleted file mode 100644
index c5681e8e7d..0000000000
--- a/spring-cloud/spring-cloud-kubernetes-2/pom.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-
-
- 4.0.0
- com.baeldung.spring.cloud
- spring-cloud-kubernetes-2
- 1.0-SNAPSHOT
- spring-cloud-kubernetes-2
- pom
-
-
- client-service
- travel-agency-service
-
-
-
-
-
- org.springframework.boot
- spring-boot-dependencies
- ${spring-boot.version}
- pom
- import
-
-
-
-
-
- 2.0.6.RELEASE
-
-
-
diff --git a/spring-cloud/spring-cloud-kubernetes-2/travel-agency-service/travel-agency-config.yaml b/spring-cloud/spring-cloud-kubernetes-2/travel-agency-service/travel-agency-config.yaml
deleted file mode 100644
index 93a67e3777..0000000000
--- a/spring-cloud/spring-cloud-kubernetes-2/travel-agency-service/travel-agency-config.yaml
+++ /dev/null
@@ -1,8 +0,0 @@
-apiVersion: v1
-kind: Secret
-metadata:
- name: travel-agency-service
-data:
- application.properties: |-
- bean.message=Testing reload ! Message from backend is: %s
Services : %s
-
diff --git a/spring-cloud/spring-cloud-kubernetes-2/client-service/.gitignore b/spring-cloud/spring-cloud-kubernetes/client-service/.gitignore
similarity index 100%
rename from spring-cloud/spring-cloud-kubernetes-2/client-service/.gitignore
rename to spring-cloud/spring-cloud-kubernetes/client-service/.gitignore
diff --git a/spring-cloud/spring-cloud-kubernetes-2/client-service/Dockerfile b/spring-cloud/spring-cloud-kubernetes/client-service/Dockerfile
similarity index 100%
rename from spring-cloud/spring-cloud-kubernetes-2/client-service/Dockerfile
rename to spring-cloud/spring-cloud-kubernetes/client-service/Dockerfile
diff --git a/spring-cloud/spring-cloud-kubernetes-2/client-service/client-config.yaml b/spring-cloud/spring-cloud-kubernetes/client-service/client-config.yaml
similarity index 100%
rename from spring-cloud/spring-cloud-kubernetes-2/client-service/client-config.yaml
rename to spring-cloud/spring-cloud-kubernetes/client-service/client-config.yaml
diff --git a/spring-cloud/spring-cloud-kubernetes-2/client-service/client-service-deployment.yaml b/spring-cloud/spring-cloud-kubernetes/client-service/client-service-deployment.yaml
similarity index 100%
rename from spring-cloud/spring-cloud-kubernetes-2/client-service/client-service-deployment.yaml
rename to spring-cloud/spring-cloud-kubernetes/client-service/client-service-deployment.yaml
diff --git a/spring-cloud/spring-cloud-kubernetes-2/client-service/pom.xml b/spring-cloud/spring-cloud-kubernetes/client-service/pom.xml
similarity index 97%
rename from spring-cloud/spring-cloud-kubernetes-2/client-service/pom.xml
rename to spring-cloud/spring-cloud-kubernetes/client-service/pom.xml
index 718e445e0c..a4de796ee3 100644
--- a/spring-cloud/spring-cloud-kubernetes-2/client-service/pom.xml
+++ b/spring-cloud/spring-cloud-kubernetes/client-service/pom.xml
@@ -3,12 +3,12 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0
client-service
- client-service
+ client-service
1.0-SNAPSHOT
com.baeldung.spring.cloud
- spring-cloud-kubernetes-2
+ spring-cloud-kubernetes
1.0-SNAPSHOT
diff --git a/spring-cloud/spring-cloud-kubernetes-2/client-service/src/main/java/com/baeldung/spring/cloud/kubernetes/client/Application.java b/spring-cloud/spring-cloud-kubernetes/client-service/src/main/java/com/baeldung/spring/cloud/kubernetes/client/Application.java
similarity index 100%
rename from spring-cloud/spring-cloud-kubernetes-2/client-service/src/main/java/com/baeldung/spring/cloud/kubernetes/client/Application.java
rename to spring-cloud/spring-cloud-kubernetes/client-service/src/main/java/com/baeldung/spring/cloud/kubernetes/client/Application.java
diff --git a/spring-cloud/spring-cloud-kubernetes-2/client-service/src/main/java/com/baeldung/spring/cloud/kubernetes/client/ClientConfig.java b/spring-cloud/spring-cloud-kubernetes/client-service/src/main/java/com/baeldung/spring/cloud/kubernetes/client/ClientConfig.java
similarity index 100%
rename from spring-cloud/spring-cloud-kubernetes-2/client-service/src/main/java/com/baeldung/spring/cloud/kubernetes/client/ClientConfig.java
rename to spring-cloud/spring-cloud-kubernetes/client-service/src/main/java/com/baeldung/spring/cloud/kubernetes/client/ClientConfig.java
diff --git a/spring-cloud/spring-cloud-kubernetes-2/client-service/src/main/java/com/baeldung/spring/cloud/kubernetes/client/ClientController.java b/spring-cloud/spring-cloud-kubernetes/client-service/src/main/java/com/baeldung/spring/cloud/kubernetes/client/ClientController.java
similarity index 100%
rename from spring-cloud/spring-cloud-kubernetes-2/client-service/src/main/java/com/baeldung/spring/cloud/kubernetes/client/ClientController.java
rename to spring-cloud/spring-cloud-kubernetes/client-service/src/main/java/com/baeldung/spring/cloud/kubernetes/client/ClientController.java
diff --git a/spring-cloud/spring-cloud-kubernetes-2/client-service/src/main/java/com/baeldung/spring/cloud/kubernetes/client/RibbonConfiguration.java b/spring-cloud/spring-cloud-kubernetes/client-service/src/main/java/com/baeldung/spring/cloud/kubernetes/client/RibbonConfiguration.java
similarity index 100%
rename from spring-cloud/spring-cloud-kubernetes-2/client-service/src/main/java/com/baeldung/spring/cloud/kubernetes/client/RibbonConfiguration.java
rename to spring-cloud/spring-cloud-kubernetes/client-service/src/main/java/com/baeldung/spring/cloud/kubernetes/client/RibbonConfiguration.java
diff --git a/spring-cloud/spring-cloud-kubernetes-2/client-service/src/main/java/com/baeldung/spring/cloud/kubernetes/client/TravelAgencyService.java b/spring-cloud/spring-cloud-kubernetes/client-service/src/main/java/com/baeldung/spring/cloud/kubernetes/client/TravelAgencyService.java
similarity index 100%
rename from spring-cloud/spring-cloud-kubernetes-2/client-service/src/main/java/com/baeldung/spring/cloud/kubernetes/client/TravelAgencyService.java
rename to spring-cloud/spring-cloud-kubernetes/client-service/src/main/java/com/baeldung/spring/cloud/kubernetes/client/TravelAgencyService.java
diff --git a/spring-cloud/spring-cloud-kubernetes-2/client-service/src/main/resources/application.yaml b/spring-cloud/spring-cloud-kubernetes/client-service/src/main/resources/application.yaml
similarity index 100%
rename from spring-cloud/spring-cloud-kubernetes-2/client-service/src/main/resources/application.yaml
rename to spring-cloud/spring-cloud-kubernetes/client-service/src/main/resources/application.yaml
diff --git a/spring-cloud/spring-cloud-kubernetes/client-service/src/main/resources/logback.xml b/spring-cloud/spring-cloud-kubernetes/client-service/src/main/resources/logback.xml
new file mode 100644
index 0000000000..7d900d8ea8
--- /dev/null
+++ b/spring-cloud/spring-cloud-kubernetes/client-service/src/main/resources/logback.xml
@@ -0,0 +1,13 @@
+
+
+
+
+ %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-cloud/spring-cloud-kubernetes-2/client-service/src/test/java/org/baeldung/SpringContextIntegrationTest.java b/spring-cloud/spring-cloud-kubernetes/client-service/src/test/java/org/baeldung/SpringContextIntegrationTest.java
similarity index 100%
rename from spring-cloud/spring-cloud-kubernetes-2/client-service/src/test/java/org/baeldung/SpringContextIntegrationTest.java
rename to spring-cloud/spring-cloud-kubernetes/client-service/src/test/java/org/baeldung/SpringContextIntegrationTest.java
diff --git a/spring-cloud/spring-cloud-kubernetes-2/deployment-all.sh b/spring-cloud/spring-cloud-kubernetes/deployment-travel-client.sh
similarity index 72%
rename from spring-cloud/spring-cloud-kubernetes-2/deployment-all.sh
rename to spring-cloud/spring-cloud-kubernetes/deployment-travel-client.sh
index 9c088b7422..90f92f31a6 100755
--- a/spring-cloud/spring-cloud-kubernetes-2/deployment-all.sh
+++ b/spring-cloud/spring-cloud-kubernetes/deployment-travel-client.sh
@@ -1,9 +1,9 @@
-### build the repository
-mvn clean install
-
### set docker env
eval $(minikube docker-env)
+### build the repository
+#mvn clean install
+
### build the docker images on minikube
cd travel-agency-service
docker build -t travel-agency-service .
@@ -12,11 +12,11 @@ docker build -t client-service .
cd ..
### secret and mongodb
-kubectl delete -f secret.yaml
-kubectl delete -f mongo-deployment.yaml
+kubectl delete -f travel-agency-service/secret.yaml
+kubectl delete -f travel-agency-service/mongo-deployment.yaml
-kubectl create -f secret.yaml
-kubectl create -f mongo-deployment.yaml
+kubectl create -f travel-agency-service/secret.yaml
+kubectl create -f travel-agency-service/mongo-deployment.yaml
### travel-agency-service
kubectl delete -f travel-agency-service/travel-agency-deployment.yaml
@@ -31,4 +31,4 @@ kubectl create -f client-service/client-config.yaml
kubectl create -f client-service/client-service-deployment.yaml
# Check that the pods are running
-kubectl get pods
\ No newline at end of file
+kubectl get pods
diff --git a/spring-cloud/spring-cloud-kubernetes/pom.xml b/spring-cloud/spring-cloud-kubernetes/pom.xml
index b3c59b7127..a9563fc582 100644
--- a/spring-cloud/spring-cloud-kubernetes/pom.xml
+++ b/spring-cloud/spring-cloud-kubernetes/pom.xml
@@ -20,6 +20,8 @@
demo-backend
liveness-example
readiness-example
+ client-service
+ travel-agency-service
\ No newline at end of file
diff --git a/spring-cloud/spring-cloud-kubernetes-2/travel-agency-service/Dockerfile b/spring-cloud/spring-cloud-kubernetes/travel-agency-service/Dockerfile
similarity index 100%
rename from spring-cloud/spring-cloud-kubernetes-2/travel-agency-service/Dockerfile
rename to spring-cloud/spring-cloud-kubernetes/travel-agency-service/Dockerfile
diff --git a/spring-cloud/spring-cloud-kubernetes-2/mongo-deployment.yaml b/spring-cloud/spring-cloud-kubernetes/travel-agency-service/mongo-deployment.yaml
similarity index 100%
rename from spring-cloud/spring-cloud-kubernetes-2/mongo-deployment.yaml
rename to spring-cloud/spring-cloud-kubernetes/travel-agency-service/mongo-deployment.yaml
diff --git a/spring-cloud/spring-cloud-kubernetes-2/travel-agency-service/pom.xml b/spring-cloud/spring-cloud-kubernetes/travel-agency-service/pom.xml
similarity index 97%
rename from spring-cloud/spring-cloud-kubernetes-2/travel-agency-service/pom.xml
rename to spring-cloud/spring-cloud-kubernetes/travel-agency-service/pom.xml
index fd5aa5f9d6..19eea2612c 100755
--- a/spring-cloud/spring-cloud-kubernetes-2/travel-agency-service/pom.xml
+++ b/spring-cloud/spring-cloud-kubernetes/travel-agency-service/pom.xml
@@ -6,7 +6,7 @@
com.baeldung.spring.cloud
- spring-cloud-kubernetes-2
+ spring-cloud-kubernetes
1.0-SNAPSHOT
diff --git a/spring-cloud/spring-cloud-kubernetes-2/secret.yaml b/spring-cloud/spring-cloud-kubernetes/travel-agency-service/secret.yaml
similarity index 100%
rename from spring-cloud/spring-cloud-kubernetes-2/secret.yaml
rename to spring-cloud/spring-cloud-kubernetes/travel-agency-service/secret.yaml
diff --git a/spring-cloud/spring-cloud-kubernetes-2/travel-agency-service/src/main/java/com/baeldung/spring/cloud/kubernetes/travelagency/Application.java b/spring-cloud/spring-cloud-kubernetes/travel-agency-service/src/main/java/com/baeldung/spring/cloud/kubernetes/travelagency/Application.java
similarity index 100%
rename from spring-cloud/spring-cloud-kubernetes-2/travel-agency-service/src/main/java/com/baeldung/spring/cloud/kubernetes/travelagency/Application.java
rename to spring-cloud/spring-cloud-kubernetes/travel-agency-service/src/main/java/com/baeldung/spring/cloud/kubernetes/travelagency/Application.java
diff --git a/spring-cloud/spring-cloud-kubernetes-2/travel-agency-service/src/main/java/com/baeldung/spring/cloud/kubernetes/travelagency/controller/TravelAgencyController.java b/spring-cloud/spring-cloud-kubernetes/travel-agency-service/src/main/java/com/baeldung/spring/cloud/kubernetes/travelagency/controller/TravelAgencyController.java
similarity index 100%
rename from spring-cloud/spring-cloud-kubernetes-2/travel-agency-service/src/main/java/com/baeldung/spring/cloud/kubernetes/travelagency/controller/TravelAgencyController.java
rename to spring-cloud/spring-cloud-kubernetes/travel-agency-service/src/main/java/com/baeldung/spring/cloud/kubernetes/travelagency/controller/TravelAgencyController.java
diff --git a/spring-cloud/spring-cloud-kubernetes-2/travel-agency-service/src/main/java/com/baeldung/spring/cloud/kubernetes/travelagency/model/TravelDeal.java b/spring-cloud/spring-cloud-kubernetes/travel-agency-service/src/main/java/com/baeldung/spring/cloud/kubernetes/travelagency/model/TravelDeal.java
similarity index 100%
rename from spring-cloud/spring-cloud-kubernetes-2/travel-agency-service/src/main/java/com/baeldung/spring/cloud/kubernetes/travelagency/model/TravelDeal.java
rename to spring-cloud/spring-cloud-kubernetes/travel-agency-service/src/main/java/com/baeldung/spring/cloud/kubernetes/travelagency/model/TravelDeal.java
diff --git a/spring-cloud/spring-cloud-kubernetes-2/travel-agency-service/src/main/java/com/baeldung/spring/cloud/kubernetes/travelagency/repository/TravelDealRepository.java b/spring-cloud/spring-cloud-kubernetes/travel-agency-service/src/main/java/com/baeldung/spring/cloud/kubernetes/travelagency/repository/TravelDealRepository.java
similarity index 100%
rename from spring-cloud/spring-cloud-kubernetes-2/travel-agency-service/src/main/java/com/baeldung/spring/cloud/kubernetes/travelagency/repository/TravelDealRepository.java
rename to spring-cloud/spring-cloud-kubernetes/travel-agency-service/src/main/java/com/baeldung/spring/cloud/kubernetes/travelagency/repository/TravelDealRepository.java
diff --git a/spring-cloud/spring-cloud-kubernetes-2/travel-agency-service/src/main/resources/application.properties b/spring-cloud/spring-cloud-kubernetes/travel-agency-service/src/main/resources/application.properties
similarity index 100%
rename from spring-cloud/spring-cloud-kubernetes-2/travel-agency-service/src/main/resources/application.properties
rename to spring-cloud/spring-cloud-kubernetes/travel-agency-service/src/main/resources/application.properties
diff --git a/spring-cloud/spring-cloud-kubernetes-2/travel-agency-service/src/main/resources/logback-spring.xml b/spring-cloud/spring-cloud-kubernetes/travel-agency-service/src/main/resources/logback-spring.xml
similarity index 100%
rename from spring-cloud/spring-cloud-kubernetes-2/travel-agency-service/src/main/resources/logback-spring.xml
rename to spring-cloud/spring-cloud-kubernetes/travel-agency-service/src/main/resources/logback-spring.xml
diff --git a/spring-cloud/spring-cloud-kubernetes-2/travel-agency-service/src/main/resources/logback.xml b/spring-cloud/spring-cloud-kubernetes/travel-agency-service/src/main/resources/logback.xml
similarity index 100%
rename from spring-cloud/spring-cloud-kubernetes-2/travel-agency-service/src/main/resources/logback.xml
rename to spring-cloud/spring-cloud-kubernetes/travel-agency-service/src/main/resources/logback.xml
diff --git a/spring-cloud/spring-cloud-kubernetes/travel-agency-service/src/test/java/com/baeldung/spring/cloud/kubernetes/travelagency/SpringContextIntegrationTest.java b/spring-cloud/spring-cloud-kubernetes/travel-agency-service/src/test/java/com/baeldung/spring/cloud/kubernetes/travelagency/SpringContextIntegrationTest.java
new file mode 100644
index 0000000000..2f901d39f6
--- /dev/null
+++ b/spring-cloud/spring-cloud-kubernetes/travel-agency-service/src/test/java/com/baeldung/spring/cloud/kubernetes/travelagency/SpringContextIntegrationTest.java
@@ -0,0 +1,16 @@
+package com.baeldung.spring.cloud.kubernetes.travelagency;
+
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = Application.class)
+public class SpringContextIntegrationTest {
+
+ @Test
+ public void whenSpringContextIsBootstrapped_thenNoExceptions() {
+ }
+}
\ No newline at end of file
diff --git a/spring-cloud/spring-cloud-kubernetes-2/travel-agency-service/travel-agency-deployment.yaml b/spring-cloud/spring-cloud-kubernetes/travel-agency-service/travel-agency-deployment.yaml
similarity index 100%
rename from spring-cloud/spring-cloud-kubernetes-2/travel-agency-service/travel-agency-deployment.yaml
rename to spring-cloud/spring-cloud-kubernetes/travel-agency-service/travel-agency-deployment.yaml
diff --git a/spring-cloud/spring-cloud-rest/spring-cloud-rest-books-api/src/test/java/org/baeldung/SpringContextIntegrationTest.java b/spring-cloud/spring-cloud-openfeign/src/test/java/com/baeldung/cloud/openfeign/SpringContextIntegrationTest.java
similarity index 77%
rename from spring-cloud/spring-cloud-rest/spring-cloud-rest-books-api/src/test/java/org/baeldung/SpringContextIntegrationTest.java
rename to spring-cloud/spring-cloud-openfeign/src/test/java/com/baeldung/cloud/openfeign/SpringContextIntegrationTest.java
index 24e758ff82..77d294093c 100644
--- a/spring-cloud/spring-cloud-rest/spring-cloud-rest-books-api/src/test/java/org/baeldung/SpringContextIntegrationTest.java
+++ b/spring-cloud/spring-cloud-openfeign/src/test/java/com/baeldung/cloud/openfeign/SpringContextIntegrationTest.java
@@ -1,4 +1,5 @@
-package org.baeldung;
+package com.baeldung.cloud.openfeign;
+
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -6,10 +7,10 @@ import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
-@SpringBootTest(classes = BooksApiApplication.class)
+@SpringBootTest(classes = ExampleApplication.class)
public class SpringContextIntegrationTest {
-
+
@Test
public void whenSpringContextIsBootstrapped_thenNoExceptions() {
}
-}
+}
\ No newline at end of file
diff --git a/spring-cloud/spring-cloud-rest/spring-cloud-rest-books-api/src/test/java/org/baeldung/SpringContextLiveTest.java b/spring-cloud/spring-cloud-rest/spring-cloud-rest-books-api/src/test/java/org/baeldung/SpringContextLiveTest.java
new file mode 100644
index 0000000000..eb56c16c6a
--- /dev/null
+++ b/spring-cloud/spring-cloud-rest/spring-cloud-rest-books-api/src/test/java/org/baeldung/SpringContextLiveTest.java
@@ -0,0 +1,21 @@
+package org.baeldung;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+
+/**
+ *
+ * This Live Test requires:
+ * * A Redis instance running in port 6379 (e.g. using `docker run --name some-redis -p 6379:6379 -d redis`)
+ *
+ */
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = BooksApiApplication.class)
+public class SpringContextLiveTest {
+
+ @Test
+ public void whenSpringContextIsBootstrapped_thenNoExceptions() {
+ }
+}
diff --git a/spring-cloud/spring-cloud-rest/spring-cloud-rest-discovery-server/src/test/java/org/baeldung/SpringContextLiveTest.java b/spring-cloud/spring-cloud-rest/spring-cloud-rest-discovery-server/src/test/java/org/baeldung/SpringContextLiveTest.java
new file mode 100644
index 0000000000..01266a3bda
--- /dev/null
+++ b/spring-cloud/spring-cloud-rest/spring-cloud-rest-discovery-server/src/test/java/org/baeldung/SpringContextLiveTest.java
@@ -0,0 +1,21 @@
+package org.baeldung;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+
+/**
+ *
+ * This Live Test requires:
+ * * A Redis instance running in port 6379 (e.g. using `docker run --name some-redis -p 6379:6379 -d redis`)
+ *
+ */
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = SpringCloudRestServerApplication.class)
+public class SpringContextLiveTest {
+
+ @Test
+ public void whenSpringContextIsBootstrapped_thenNoExceptions() {
+ }
+}
diff --git a/spring-cloud/spring-cloud-rest/spring-cloud-rest-reviews-api/src/test/java/org/baeldung/SpringContextLiveTest.java b/spring-cloud/spring-cloud-rest/spring-cloud-rest-reviews-api/src/test/java/org/baeldung/SpringContextLiveTest.java
new file mode 100644
index 0000000000..070abd246f
--- /dev/null
+++ b/spring-cloud/spring-cloud-rest/spring-cloud-rest-reviews-api/src/test/java/org/baeldung/SpringContextLiveTest.java
@@ -0,0 +1,21 @@
+package org.baeldung;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+
+/**
+ *
+ * This Live Test requires:
+ * * A Redis instance running in port 6379 (e.g. using `docker run --name some-redis -p 6379:6379 -d redis`)
+ *
+ */
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = BookReviewsApiApplication.class)
+public class SpringContextLiveTest {
+
+ @Test
+ public void whenSpringContextIsBootstrapped_thenNoExceptions() {
+ }
+}
diff --git a/spring-cloud/spring-cloud-rest/spring-cloud-rest-reviews-api/src/test/java/org/baeldung/SpringContextIntegrationTest.java b/spring-cloud/spring-cloud-stream-starters/twitterhdfs/src/test/java/com/baeldung/twitterhdfs/aggregate/SpringContextIntegrationTest.java
similarity index 79%
rename from spring-cloud/spring-cloud-rest/spring-cloud-rest-reviews-api/src/test/java/org/baeldung/SpringContextIntegrationTest.java
rename to spring-cloud/spring-cloud-stream-starters/twitterhdfs/src/test/java/com/baeldung/twitterhdfs/aggregate/SpringContextIntegrationTest.java
index 07d7db0505..b5cef1b5ed 100644
--- a/spring-cloud/spring-cloud-rest/spring-cloud-rest-reviews-api/src/test/java/org/baeldung/SpringContextIntegrationTest.java
+++ b/spring-cloud/spring-cloud-stream-starters/twitterhdfs/src/test/java/com/baeldung/twitterhdfs/aggregate/SpringContextIntegrationTest.java
@@ -1,4 +1,4 @@
-package org.baeldung;
+package com.baeldung.twitterhdfs.aggregate;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -6,7 +6,7 @@ import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
-@SpringBootTest(classes = BookReviewsApiApplication.class)
+@SpringBootTest(classes = AggregateApp.class)
public class SpringContextIntegrationTest {
@Test
diff --git a/spring-cloud/spring-cloud-stream-starters/twitterhdfs/src/test/java/org/baeldung/SpringContextIntegrationTest.java b/spring-cloud/spring-cloud-stream-starters/twitterhdfs/src/test/java/org/baeldung/SpringContextIntegrationTest.java
deleted file mode 100644
index 3d370e7b48..0000000000
--- a/spring-cloud/spring-cloud-stream-starters/twitterhdfs/src/test/java/org/baeldung/SpringContextIntegrationTest.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package org.baeldung;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.test.context.junit4.SpringRunner;
-
-import com.baeldung.twitterhdfs.aggregate.AggregateApp;
-import com.baeldung.twitterhdfs.processor.ProcessorApp;
-import com.baeldung.twitterhdfs.sink.SinkApp;
-import com.baeldung.twitterhdfs.source.SourceApp;
-
-@RunWith(SpringRunner.class)
-@SpringBootTest(classes = {AggregateApp.class, ProcessorApp.class, SinkApp.class, SourceApp.class})
-public class SpringContextIntegrationTest {
-
- @Test
- public void whenSpringContextIsBootstrapped_thenNoExceptions() {
- }
-}
diff --git a/spring-cloud/spring-cloud-task/springcloudtaskbatch/src/main/resources/application.yml b/spring-cloud/spring-cloud-task/springcloudtaskbatch/src/main/resources/application.yml
index 1187c12fe7..71275793ec 100644
--- a/spring-cloud/spring-cloud-task/springcloudtaskbatch/src/main/resources/application.yml
+++ b/spring-cloud/spring-cloud-task/springcloudtaskbatch/src/main/resources/application.yml
@@ -3,11 +3,11 @@ logging:
org:
springframework:
cloud:
- task=DEBUG
+ task: DEBUG
spring:
application:
- name=helloWorld
+ name: helloWorld
datasource:
url: jdbc:mysql://localhost:3306/springcloud?useSSL=false
username: root
diff --git a/spring-cloud/spring-cloud-task/springcloudtaskbatch/src/test/java/org/baeldung/SpringContextIntegrationTest.java b/spring-cloud/spring-cloud-task/springcloudtaskbatch/src/test/java/org/baeldung/SpringContextIntegrationTest.java
deleted file mode 100644
index 4b5aff2db8..0000000000
--- a/spring-cloud/spring-cloud-task/springcloudtaskbatch/src/test/java/org/baeldung/SpringContextIntegrationTest.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package org.baeldung;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.springframework.test.context.ContextConfiguration;
-import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
-
-import com.baeldung.task.JobConfiguration;
-
-@RunWith(SpringJUnit4ClassRunner.class)
-@ContextConfiguration(classes = JobConfiguration.class)
-public class SpringContextIntegrationTest {
-
- @Test
- public void whenSpringContextIsBootstrapped_thenNoExceptions() {
- }
-}
diff --git a/spring-cloud/spring-cloud-task/springcloudtaskbatch/src/test/java/org/baeldung/SpringContextLiveTest.java b/spring-cloud/spring-cloud-task/springcloudtaskbatch/src/test/java/org/baeldung/SpringContextLiveTest.java
new file mode 100644
index 0000000000..ddbcbf65ea
--- /dev/null
+++ b/spring-cloud/spring-cloud-task/springcloudtaskbatch/src/test/java/org/baeldung/SpringContextLiveTest.java
@@ -0,0 +1,29 @@
+package org.baeldung;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.test.context.ConfigFileApplicationContextInitializer;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+import com.baeldung.task.JobConfiguration;
+import com.baeldung.task.TaskDemo;
+
+/**
+ * This Live Test requires:
+ * * a MySql instance running, that allows a root user with no password, and with a database named
+ *
+ * (e.g. with the following command `docker run -p 3306:3306 --name bael-mysql -e MYSQL_ALLOW_EMPTY_PASSWORD=true -e MYSQL_DATABASE=springcloud mysql:latest`)
+ *
+ */
+@RunWith(SpringJUnit4ClassRunner.class)
+@SpringBootApplication
+@ContextConfiguration(classes = { JobConfiguration.class, TaskDemo.class }, initializers = {
+ ConfigFileApplicationContextInitializer.class })
+public class SpringContextLiveTest {
+
+ @Test
+ public void whenSpringContextIsBootstrapped_thenNoExceptions() {
+ }
+}
diff --git a/spring-cloud/spring-cloud-rest/spring-cloud-rest-discovery-server/src/test/java/org/baeldung/SpringContextIntegrationTest.java b/spring-cloud/spring-cloud-vault/src/test/java/org/baeldung/spring/cloud/vaultsample/SpringContextIntegrationTest.java
similarity index 76%
rename from spring-cloud/spring-cloud-rest/spring-cloud-rest-discovery-server/src/test/java/org/baeldung/SpringContextIntegrationTest.java
rename to spring-cloud/spring-cloud-vault/src/test/java/org/baeldung/spring/cloud/vaultsample/SpringContextIntegrationTest.java
index e22359a016..e1eb2f8e24 100644
--- a/spring-cloud/spring-cloud-rest/spring-cloud-rest-discovery-server/src/test/java/org/baeldung/SpringContextIntegrationTest.java
+++ b/spring-cloud/spring-cloud-vault/src/test/java/org/baeldung/spring/cloud/vaultsample/SpringContextIntegrationTest.java
@@ -1,4 +1,4 @@
-package org.baeldung;
+package org.baeldung.spring.cloud.vaultsample;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -6,10 +6,10 @@ import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
-@SpringBootTest(classes = SpringCloudRestServerApplication.class)
+@SpringBootTest(classes = VaultSampleApplication.class)
public class SpringContextIntegrationTest {
@Test
public void whenSpringContextIsBootstrapped_thenNoExceptions() {
}
-}
+}
\ No newline at end of file
diff --git a/spring-cloud/spring-cloud-zookeeper/HelloWorld/pom.xml b/spring-cloud/spring-cloud-zookeeper/HelloWorld/pom.xml
index 262b059544..0da0f7503e 100644
--- a/spring-cloud/spring-cloud-zookeeper/HelloWorld/pom.xml
+++ b/spring-cloud/spring-cloud-zookeeper/HelloWorld/pom.xml
@@ -34,6 +34,12 @@
+
+ org.springframework.boot
+ spring-boot-starter-test
+ ${spring-boot.version}
+ test
+
diff --git a/spring-cloud/spring-cloud-aws/src/test/java/com/baeldung/spring/cloud/aws/SpringContextIntegrationTest.java b/spring-cloud/spring-cloud-zookeeper/HelloWorld/src/test/java/com/baeldung/spring/cloud/helloworld/SpringContextIntegrationTest.java
similarity index 76%
rename from spring-cloud/spring-cloud-aws/src/test/java/com/baeldung/spring/cloud/aws/SpringContextIntegrationTest.java
rename to spring-cloud/spring-cloud-zookeeper/HelloWorld/src/test/java/com/baeldung/spring/cloud/helloworld/SpringContextIntegrationTest.java
index e0026ce441..2770649aa3 100644
--- a/spring-cloud/spring-cloud-aws/src/test/java/com/baeldung/spring/cloud/aws/SpringContextIntegrationTest.java
+++ b/spring-cloud/spring-cloud-zookeeper/HelloWorld/src/test/java/com/baeldung/spring/cloud/helloworld/SpringContextIntegrationTest.java
@@ -1,4 +1,5 @@
-package com.baeldung.spring.cloud.aws;
+package com.baeldung.spring.cloud.helloworld;
+
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -6,10 +7,10 @@ import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
-@SpringBootTest(classes = SpringCloudAwsApplication.class)
+@SpringBootTest(classes = HelloWorldApplication.class)
public class SpringContextIntegrationTest {
-
+
@Test
public void whenSpringContextIsBootstrapped_thenNoExceptions() {
}
-}
+}
\ No newline at end of file
diff --git a/spring-cloud/spring-cloud-zookeeper/README.md b/spring-cloud/spring-cloud-zookeeper/README.md
index a639833452..a49a448833 100644
--- a/spring-cloud/spring-cloud-zookeeper/README.md
+++ b/spring-cloud/spring-cloud-zookeeper/README.md
@@ -1,2 +1,2 @@
### Relevant Articles:
-- [An Introduction to Spring Cloud Zookeeper](http://www.baeldung.com/spring-cloud-zookeeper)
+- [An Intro to Spring Cloud Zookeeper](http://www.baeldung.com/spring-cloud-zookeeper)
diff --git a/spring-cloud/spring-cloud-bootstrap/discovery/java/org/baeldung/SpringContextIntegrationTest.java b/spring-cloud/spring-cloud-zuul/src/test/java/com/baeldung/spring/cloud/zuulratelimitdemo/controller/SpringContextIntegrationTest.java
similarity index 62%
rename from spring-cloud/spring-cloud-bootstrap/discovery/java/org/baeldung/SpringContextIntegrationTest.java
rename to spring-cloud/spring-cloud-zuul/src/test/java/com/baeldung/spring/cloud/zuulratelimitdemo/controller/SpringContextIntegrationTest.java
index 6016788eab..dbcdbdd434 100644
--- a/spring-cloud/spring-cloud-bootstrap/discovery/java/org/baeldung/SpringContextIntegrationTest.java
+++ b/spring-cloud/spring-cloud-zuul/src/test/java/com/baeldung/spring/cloud/zuulratelimitdemo/controller/SpringContextIntegrationTest.java
@@ -1,17 +1,17 @@
-package org.baeldung;
+package com.baeldung.spring.cloud.zuulratelimitdemo.controller;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
-import com.baeldung.spring.cloud.bootstrap.config.ConfigApplication;
+import com.baeldung.spring.cloud.zuulratelimitdemo.ZuulRatelimitDemoApplication;
@RunWith(SpringRunner.class)
-@SpringBootTest(classes = ConfigApplication.class)
+@SpringBootTest(classes = ZuulRatelimitDemoApplication.class)
public class SpringContextIntegrationTest {
@Test
public void whenSpringContextIsBootstrapped_thenNoExceptions() {
}
-}
+}
\ No newline at end of file
diff --git a/spring-core/pom.xml b/spring-core/pom.xml
index d348d742e7..814addecdd 100644
--- a/spring-core/pom.xml
+++ b/spring-core/pom.xml
@@ -10,9 +10,9 @@
com.baeldung
- parent-spring-4
+ parent-spring-5
0.0.1-SNAPSHOT
- ../parent-spring-4
+ ../parent-spring-5
diff --git a/spring-data-rest/README.md b/spring-data-rest/README.md
index 1624a3abfd..abbacb69cc 100644
--- a/spring-data-rest/README.md
+++ b/spring-data-rest/README.md
@@ -22,3 +22,4 @@ To view the running application, visit [http://localhost:8080](http://localhost:
- [Spring Data REST Events with @RepositoryEventHandler](http://www.baeldung.com/spring-data-rest-events)
- [Customizing HTTP Endpoints in Spring Data REST](https://www.baeldung.com/spring-data-rest-customize-http-endpoints)
- [Spring Boot with SQLite](https://www.baeldung.com/spring-boot-sqlite)
+- [Spring Data Web Support](https://www.baeldung.com/spring-data-web-support)
diff --git a/spring-data-rest/pom.xml b/spring-data-rest/pom.xml
index e563a6a3b5..525c88c9d8 100644
--- a/spring-data-rest/pom.xml
+++ b/spring-data-rest/pom.xml
@@ -1,9 +1,8 @@
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0
spring-data-rest
-
1.0
spring-data-rest
jar
@@ -21,6 +20,10 @@
org.springframework.boot
spring-boot-starter
+
+ org.springframework.boot
+ spring-boot-starter-web
+
org.springframework.boot
spring-boot-starter-data-rest
@@ -30,12 +33,21 @@
spring-boot-starter-data-jpa
- com.h2database
- h2
+ org.springframework.boot
+ spring-boot-autoconfigure
org.springframework.boot
- spring-boot-autoconfigure
+ spring-boot-starter-test
+ test
+
+
+ com.querydsl
+ querydsl-apt
+
+
+ com.querydsl
+ querydsl-jpa
org.xerial
@@ -45,9 +57,33 @@
${project.artifactId}
+
+
+ com.mysema.maven
+ maven-apt-plugin
+ 1.0
+
+
+ generate-sources
+
+ process
+
+
+ target/generated-sources
+ com.querydsl.apt.jpa.JPAAnnotationProcessor
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+ UTF-8
com.baeldung.SpringDataRestApplication
diff --git a/spring-data-rest/src/main/java/com/baeldung/springdatawebsupport/application/Application.java b/spring-data-rest/src/main/java/com/baeldung/springdatawebsupport/application/Application.java
new file mode 100644
index 0000000000..fe2f996d37
--- /dev/null
+++ b/spring-data-rest/src/main/java/com/baeldung/springdatawebsupport/application/Application.java
@@ -0,0 +1,28 @@
+package com.baeldung.springdatawebsupport.application;
+
+import com.baeldung.springdatawebsupport.application.entities.User;
+import com.baeldung.springdatawebsupport.application.repositories.UserRepository;
+import java.util.stream.Stream;
+import org.springframework.boot.CommandLineRunner;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.Bean;
+
+@SpringBootApplication
+public class Application {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Application.class, args);
+ }
+
+ @Bean
+ CommandLineRunner initialize(UserRepository userRepository) {
+ return args -> {
+ Stream.of("John", "Robert", "Nataly", "Helen", "Mary").forEach(name -> {
+ User user = new User(name);
+ userRepository.save(user);
+ });
+ userRepository.findAll().forEach(System.out::println);
+ };
+ }
+}
diff --git a/spring-data-rest/src/main/java/com/baeldung/springdatawebsupport/application/controllers/UserController.java b/spring-data-rest/src/main/java/com/baeldung/springdatawebsupport/application/controllers/UserController.java
new file mode 100644
index 0000000000..8258c3b7aa
--- /dev/null
+++ b/spring-data-rest/src/main/java/com/baeldung/springdatawebsupport/application/controllers/UserController.java
@@ -0,0 +1,47 @@
+package com.baeldung.springdatawebsupport.application.controllers;
+
+import com.baeldung.springdatawebsupport.application.entities.User;
+import com.baeldung.springdatawebsupport.application.repositories.UserRepository;
+import com.querydsl.core.types.Predicate;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.PageRequest;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.domain.Sort;
+import org.springframework.data.querydsl.binding.QuerydslPredicate;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+public class UserController {
+
+ private final UserRepository userRepository;
+
+ @Autowired
+ public UserController(UserRepository userRepository) {
+ this.userRepository = userRepository;
+ }
+
+ @GetMapping("/users/{id}")
+ public User findUserById(@PathVariable("id") User user) {
+ return user;
+ }
+
+ @GetMapping("/users")
+ public Page findAllUsers(Pageable pageable) {
+ return userRepository.findAll(pageable);
+ }
+
+ @GetMapping("/sortedusers")
+ public Page findAllUsersSortedByName() {
+ Pageable pageable = PageRequest.of(0, 5, Sort.by("name"));
+ return userRepository.findAll(pageable);
+ }
+
+ @GetMapping("/filteredusers")
+ public Iterable getUsersByQuerydslPredicate(@QuerydslPredicate(root = User.class) Predicate predicate) {
+ return userRepository.findAll(predicate);
+ }
+}
diff --git a/spring-data-rest/src/main/java/com/baeldung/springdatawebsupport/application/entities/User.java b/spring-data-rest/src/main/java/com/baeldung/springdatawebsupport/application/entities/User.java
new file mode 100644
index 0000000000..e9aaeb119a
--- /dev/null
+++ b/spring-data-rest/src/main/java/com/baeldung/springdatawebsupport/application/entities/User.java
@@ -0,0 +1,38 @@
+package com.baeldung.springdatawebsupport.application.entities;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+@Entity
+@Table(name = "users")
+public class User {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.AUTO)
+ private long id;
+ private final String name;
+
+ public User() {
+ this.name = "";
+ }
+
+ public User(String name) {
+ this.name = name;
+ }
+
+ public long getId() {
+ return id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public String toString() {
+ return "User{" + "id=" + id + ", name=" + name + '}';
+ }
+}
diff --git a/spring-data-rest/src/main/java/com/baeldung/springdatawebsupport/application/repositories/UserRepository.java b/spring-data-rest/src/main/java/com/baeldung/springdatawebsupport/application/repositories/UserRepository.java
new file mode 100644
index 0000000000..41d7ed9d98
--- /dev/null
+++ b/spring-data-rest/src/main/java/com/baeldung/springdatawebsupport/application/repositories/UserRepository.java
@@ -0,0 +1,14 @@
+package com.baeldung.springdatawebsupport.application.repositories;
+
+import com.baeldung.springdatawebsupport.application.entities.User;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.querydsl.QuerydslPredicateExecutor;
+import org.springframework.data.repository.PagingAndSortingRepository;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface UserRepository extends PagingAndSortingRepository,
+ QuerydslPredicateExecutor {
+
+}
diff --git a/spring-data-rest/src/test/java/com/baeldung/springdatawebsupport/application/test/UserControllerIntegrationTest.java b/spring-data-rest/src/test/java/com/baeldung/springdatawebsupport/application/test/UserControllerIntegrationTest.java
new file mode 100644
index 0000000000..db522b1413
--- /dev/null
+++ b/spring-data-rest/src/test/java/com/baeldung/springdatawebsupport/application/test/UserControllerIntegrationTest.java
@@ -0,0 +1,74 @@
+package com.baeldung.springdatawebsupport.application.test;
+
+import com.baeldung.springdatawebsupport.application.controllers.UserController;
+import static org.assertj.core.api.Assertions.assertThat;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.http.MediaType;
+import org.springframework.test.context.junit4.SpringRunner;
+import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
+import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest
+@AutoConfigureMockMvc
+public class UserControllerIntegrationTest {
+
+ @Autowired
+ private UserController userController;
+
+ @Autowired
+ private MockMvc mockMvc;
+
+ @Test
+ public void whenUserControllerInjected_thenNotNull() throws Exception {
+ assertThat(userController).isNotNull();
+ }
+
+ @Test
+ public void whenGetRequestToUsersEndPointWithIdPathVariable_thenCorrectResponse() throws Exception {
+ mockMvc.perform(MockMvcRequestBuilders.get("/users/{id}", "1")
+ .contentType(MediaType.APPLICATION_JSON_UTF8))
+ .andExpect(MockMvcResultMatchers.status().isOk())
+ .andExpect(MockMvcResultMatchers.jsonPath("$.id").value("1"));
+ }
+
+ @Test
+ public void whenGetRequestToUsersEndPoint_thenCorrectResponse() throws Exception {
+ mockMvc.perform(MockMvcRequestBuilders.get("/users")
+ .contentType(MediaType.APPLICATION_JSON_UTF8))
+ .andExpect(MockMvcResultMatchers.status().isOk())
+ .andExpect(MockMvcResultMatchers.jsonPath("$['pageable']['paged']").value("true"));
+
+ }
+
+ @Test
+ public void whenGetRequestToUserEndPointWithNameRequestParameter_thenCorrectResponse() throws Exception {
+ mockMvc.perform(MockMvcRequestBuilders.get("/user")
+ .param("name", "John")
+ .contentType(MediaType.APPLICATION_JSON_UTF8))
+ .andExpect(MockMvcResultMatchers.status().isOk())
+ .andExpect(MockMvcResultMatchers.jsonPath("$['content'][0].['name']").value("John"));
+ }
+
+ @Test
+ public void whenGetRequestToSorteredUsersEndPoint_thenCorrectResponse() throws Exception {
+ mockMvc.perform(MockMvcRequestBuilders.get("/sortedusers")
+ .contentType(MediaType.APPLICATION_JSON_UTF8))
+ .andExpect(MockMvcResultMatchers.status().isOk())
+ .andExpect(MockMvcResultMatchers.jsonPath("$['sort']['sorted']").value("true"));
+ }
+
+ @Test
+ public void whenGetRequestToFilteredUsersEndPoint_thenCorrectResponse() throws Exception {
+ mockMvc.perform(MockMvcRequestBuilders.get("/filteredusers")
+ .param("name", "John")
+ .contentType(MediaType.APPLICATION_JSON_UTF8))
+ .andExpect(MockMvcResultMatchers.status().isOk())
+ .andExpect(MockMvcResultMatchers.jsonPath("$[0].name").value("John"));
+ }
+}
diff --git a/spring-mvc-java/README.md b/spring-mvc-java/README.md
index 497b0f4c1f..3deeb21afc 100644
--- a/spring-mvc-java/README.md
+++ b/spring-mvc-java/README.md
@@ -19,7 +19,7 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring
- [Introduction to HtmlUnit](http://www.baeldung.com/htmlunit)
- [Spring @RequestMapping New Shortcut Annotations](http://www.baeldung.com/spring-new-requestmapping-shortcuts)
- [Guide to Spring Handler Mappings](http://www.baeldung.com/spring-handler-mappings)
-- [Uploading and Displaying Excel Files with Spring MVC](http://www.baeldung.com/spring-mvc-excel-files)
+- [Upload and Display Excel Files with Spring MVC](http://www.baeldung.com/spring-mvc-excel-files)
- [Spring MVC Custom Validation](http://www.baeldung.com/spring-mvc-custom-validator)
- [web.xml vs Initializer with Spring](http://www.baeldung.com/spring-xml-vs-java-config)
- [The HttpMediaTypeNotAcceptableException in Spring MVC](http://www.baeldung.com/spring-httpmediatypenotacceptable)
@@ -31,3 +31,4 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring
- [Using Spring @ResponseStatus to Set HTTP Status Code](http://www.baeldung.com/spring-response-status)
- [Spring MVC Tutorial](https://www.baeldung.com/spring-mvc-tutorial)
- [Working with Date Parameters in Spring](https://www.baeldung.com/spring-date-parameters)
+- [A Java Web Application Without a web.xml](https://www.baeldung.com/java-web-app-without-web-xml)
diff --git a/spring-mvc-xml/README.md b/spring-mvc-xml/README.md
index dbc6125424..216517f52d 100644
--- a/spring-mvc-xml/README.md
+++ b/spring-mvc-xml/README.md
@@ -14,3 +14,4 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring
- [Guide to JavaServer Pages (JSP)](http://www.baeldung.com/jsp)
- [Exploring SpringMVC’s Form Tag Library](http://www.baeldung.com/spring-mvc-form-tags)
- [web.xml vs Initializer with Spring](http://www.baeldung.com/spring-xml-vs-java-config)
+- [A Java Web Application Without a web.xml](https://www.baeldung.com/java-web-app-without-web-xml)
diff --git a/spring-rest-shell/README.md b/spring-rest-shell/README.md
index 901d9a51ee..b250f06a4b 100644
--- a/spring-rest-shell/README.md
+++ b/spring-rest-shell/README.md
@@ -2,4 +2,4 @@
### Relevant Articles
-- [Spring REST Shell](http://www.baeldung.com/spring-rest-shell)
\ No newline at end of file
+- [Introduction to Spring REST Shell](http://www.baeldung.com/spring-rest-shell)
diff --git a/spring-rest/README.md b/spring-rest/README.md
index 9a2c1fd96c..6d3aac3eb8 100644
--- a/spring-rest/README.md
+++ b/spring-rest/README.md
@@ -20,5 +20,4 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring
- [Using the Spring RestTemplate Interceptor](http://www.baeldung.com/spring-rest-template-interceptor)
- [Get and Post Lists of Objects with RestTemplate](http://www.baeldung.com/spring-rest-template-list)
- [How to Set a Header on a Response with Spring 5](http://www.baeldung.com/spring-response-header)
-- [Spring’s RequestBody and ResponseBody Annotations](https://www.baeldung.com/spring-request-response-body)
- [Uploading MultipartFile with Spring RestTemplate](http://www.baeldung.com/spring-rest-template-multipart-upload)
diff --git a/spring-resttemplate/src/main/java/org/baeldung/resttemplate/web/controller/PersonAPI.java b/spring-resttemplate/src/main/java/org/baeldung/resttemplate/web/controller/PersonAPI.java
new file mode 100644
index 0000000000..b1b56ec2f3
--- /dev/null
+++ b/spring-resttemplate/src/main/java/org/baeldung/resttemplate/web/controller/PersonAPI.java
@@ -0,0 +1,38 @@
+package org.baeldung.resttemplate.web.controller;
+
+import javax.servlet.http.HttpServletResponse;
+
+import org.baeldung.resttemplate.web.dto.Person;
+import org.baeldung.resttemplate.web.service.PersonService;
+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.RestController;
+import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
+
+@RestController
+public class PersonAPI {
+
+ @Autowired
+ private PersonService personService;
+
+ @GetMapping("/")
+ public String home() {
+ return "Spring boot is working!";
+ }
+
+ @PostMapping(value = "/createPerson", consumes = "application/json", produces = "application/json")
+ public Person createPerson(@RequestBody Person person) {
+ return personService.saveUpdatePerson(person);
+ }
+
+ @PostMapping(value = "/updatePerson", consumes = "application/json", produces = "application/json")
+ public Person updatePerson(@RequestBody Person person, HttpServletResponse response) {
+ response.setHeader("Location", ServletUriComponentsBuilder.fromCurrentContextPath()
+ .path("/findPerson/" + person.getId())
+ .toUriString());
+ return personService.saveUpdatePerson(person);
+ }
+
+}
\ No newline at end of file
diff --git a/spring-resttemplate/src/main/java/org/baeldung/resttemplate/web/dto/Person.java b/spring-resttemplate/src/main/java/org/baeldung/resttemplate/web/dto/Person.java
new file mode 100644
index 0000000000..4b7679638f
--- /dev/null
+++ b/spring-resttemplate/src/main/java/org/baeldung/resttemplate/web/dto/Person.java
@@ -0,0 +1,32 @@
+package org.baeldung.resttemplate.web.dto;
+
+public class Person {
+ private Integer id;
+ private String name;
+
+ public Person() {
+
+ }
+
+ public Person(Integer id, String name) {
+ this.id = id;
+ this.name = name;
+ }
+
+ public Integer getId() {
+ return id;
+ }
+
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+}
diff --git a/spring-resttemplate/src/main/java/org/baeldung/resttemplate/web/service/PersonService.java b/spring-resttemplate/src/main/java/org/baeldung/resttemplate/web/service/PersonService.java
new file mode 100644
index 0000000000..c5ad39e101
--- /dev/null
+++ b/spring-resttemplate/src/main/java/org/baeldung/resttemplate/web/service/PersonService.java
@@ -0,0 +1,10 @@
+package org.baeldung.resttemplate.web.service;
+
+import org.baeldung.resttemplate.web.dto.Person;
+
+public interface PersonService {
+
+ public Person saveUpdatePerson(Person person);
+
+ public Person findPersonById(Integer id);
+}
\ No newline at end of file
diff --git a/spring-resttemplate/src/main/java/org/baeldung/resttemplate/web/service/PersonServiceImpl.java b/spring-resttemplate/src/main/java/org/baeldung/resttemplate/web/service/PersonServiceImpl.java
new file mode 100644
index 0000000000..658e0fade0
--- /dev/null
+++ b/spring-resttemplate/src/main/java/org/baeldung/resttemplate/web/service/PersonServiceImpl.java
@@ -0,0 +1,19 @@
+package org.baeldung.resttemplate.web.service;
+
+import org.baeldung.resttemplate.web.dto.Person;
+import org.springframework.stereotype.Component;
+
+@Component
+public class PersonServiceImpl implements PersonService {
+
+ @Override
+ public Person saveUpdatePerson(Person person) {
+ return person;
+ }
+
+ @Override
+ public Person findPersonById(Integer id) {
+ return new Person(id, "John");
+ }
+
+}
diff --git a/spring-resttemplate/src/test/java/org/baeldung/resttemplate/PersonAPILiveTest.java b/spring-resttemplate/src/test/java/org/baeldung/resttemplate/PersonAPILiveTest.java
new file mode 100644
index 0000000000..de18f6db09
--- /dev/null
+++ b/spring-resttemplate/src/test/java/org/baeldung/resttemplate/PersonAPILiveTest.java
@@ -0,0 +1,96 @@
+package org.baeldung.resttemplate;
+
+import static org.junit.Assert.assertNotNull;
+
+import java.io.IOException;
+import java.net.URI;
+
+import org.baeldung.resttemplate.web.dto.Person;
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.test.context.junit4.SpringRunner;
+import org.springframework.web.client.RestTemplate;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = RestTemplateConfigurationApplication.class)
+public class PersonAPILiveTest {
+
+ private static String createPersonUrl;
+ private static String updatePersonUrl;
+
+ private static RestTemplate restTemplate;
+
+ private static HttpHeaders headers;
+
+ private final ObjectMapper objectMapper = new ObjectMapper();
+
+ private static JSONObject personJsonObject;
+
+ @BeforeClass
+ public static void runBeforeAllTestMethods() throws JSONException {
+ createPersonUrl = "http://localhost:8082/spring-rest/createPerson";
+ updatePersonUrl = "http://localhost:8082/spring-rest/updatePerson";
+
+ restTemplate = new RestTemplate();
+
+ headers = new HttpHeaders();
+ headers.setContentType(MediaType.APPLICATION_JSON);
+ personJsonObject = new JSONObject();
+ personJsonObject.put("id", 1);
+ personJsonObject.put("name", "John");
+ }
+
+ @Test
+ public void givenDataIsJson_whenDataIsPostedByPostForObject_thenResponseBodyIsNotNull() throws IOException {
+ HttpEntity request = new HttpEntity(personJsonObject.toString(), headers);
+ String personResultAsJsonStr = restTemplate.postForObject(createPersonUrl, request, String.class);
+ JsonNode root = objectMapper.readTree(personResultAsJsonStr);
+
+ Person person = restTemplate.postForObject(createPersonUrl, request, Person.class);
+
+ assertNotNull(personResultAsJsonStr);
+ assertNotNull(root);
+ assertNotNull(root.path("name")
+ .asText());
+
+ assertNotNull(person);
+ assertNotNull(person.getName());
+ }
+
+ @Test
+ public void givenDataIsJson_whenDataIsPostedByPostForEntity_thenResponseBodyIsNotNull() throws IOException {
+ HttpEntity request = new HttpEntity(personJsonObject.toString(), headers);
+ ResponseEntity responseEntityStr = restTemplate.postForEntity(createPersonUrl, request, String.class);
+ JsonNode root = objectMapper.readTree(responseEntityStr.getBody());
+
+ ResponseEntity responseEntityPerson = restTemplate.postForEntity(createPersonUrl, request, Person.class);
+
+ assertNotNull(responseEntityStr.getBody());
+ assertNotNull(root.path("name")
+ .asText());
+
+ assertNotNull(responseEntityPerson.getBody());
+ assertNotNull(responseEntityPerson.getBody()
+ .getName());
+ }
+
+ @Test
+ public void givenDataIsJson_whenDataIsPostedByPostForLocation_thenResponseBodyIsTheLocationHeader() throws JsonProcessingException {
+ HttpEntity request = new HttpEntity(personJsonObject.toString(), headers);
+ URI locationHeader = restTemplate.postForLocation(updatePersonUrl, request);
+
+ assertNotNull(locationHeader);
+ }
+}
\ No newline at end of file
diff --git a/spring-security-kerberos/README.md b/spring-security-kerberos/README.md
new file mode 100644
index 0000000000..0338c2058c
--- /dev/null
+++ b/spring-security-kerberos/README.md
@@ -0,0 +1,10 @@
+## @PreFilter and @PostFilter annotations
+
+### Build the Project ###
+
+```
+mvn clean install
+```
+
+### Relevant Articles:
+- [Spring Security – Kerberos](http://www.baeldung.com/xxxxxx)
diff --git a/spring-security-kerberos/pom.xml b/spring-security-kerberos/pom.xml
new file mode 100644
index 0000000000..35c4ba4926
--- /dev/null
+++ b/spring-security-kerberos/pom.xml
@@ -0,0 +1,61 @@
+
+ 4.0.0
+ com.baeldung
+ spring-security-kerberos
+ 0.1-SNAPSHOT
+ spring-security-kerberos
+ war
+
+ parent-boot-1
+ com.baeldung
+ 0.0.1-SNAPSHOT
+ ../parent-boot-1
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.boot
+ spring-boot-starter-security
+
+
+
+ org.springframework.security.kerberos
+ spring-security-kerberos-core
+ 1.0.1.RELEASE
+
+
+ org.springframework.security.kerberos
+ spring-security-kerberos-web
+ 1.0.1.RELEASE
+
+
+ org.springframework.security.kerberos
+ spring-security-kerberos-client
+ 1.0.1.RELEASE
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+ org.springframework.security
+ spring-security-test
+ test
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-war-plugin
+
+
+
+
diff --git a/spring-security-kerberos/src/main/java/org/baeldung/Application.java b/spring-security-kerberos/src/main/java/org/baeldung/Application.java
new file mode 100644
index 0000000000..39c2b51356
--- /dev/null
+++ b/spring-security-kerberos/src/main/java/org/baeldung/Application.java
@@ -0,0 +1,13 @@
+package org.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);
+ }
+
+}
diff --git a/spring-security-kerberos/src/main/java/org/baeldung/config/WebSecurityConfig.java b/spring-security-kerberos/src/main/java/org/baeldung/config/WebSecurityConfig.java
new file mode 100644
index 0000000000..49a1cf0a8e
--- /dev/null
+++ b/spring-security-kerberos/src/main/java/org/baeldung/config/WebSecurityConfig.java
@@ -0,0 +1,87 @@
+package org.baeldung.config;
+
+import org.baeldung.security.DummyUserDetailsService;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.io.FileSystemResource;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
+import org.springframework.security.kerberos.authentication.KerberosAuthenticationProvider;
+import org.springframework.security.kerberos.authentication.KerberosServiceAuthenticationProvider;
+import org.springframework.security.kerberos.authentication.sun.SunJaasKerberosClient;
+import org.springframework.security.kerberos.authentication.sun.SunJaasKerberosTicketValidator;
+import org.springframework.security.kerberos.web.authentication.SpnegoAuthenticationProcessingFilter;
+import org.springframework.security.kerberos.web.authentication.SpnegoEntryPoint;
+import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
+
+@Configuration
+public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
+
+ @Override
+ protected void configure(HttpSecurity http) throws Exception {
+ http.authorizeRequests()
+ .anyRequest()
+ .authenticated()
+ .and()
+ .addFilterBefore(spnegoAuthenticationProcessingFilter(authenticationManagerBean()), BasicAuthenticationFilter.class);
+ }
+
+ @Override
+ @Bean
+ public AuthenticationManager authenticationManagerBean() throws Exception {
+ return super.authenticationManagerBean();
+ }
+
+ @Override
+ protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+ auth.authenticationProvider(kerberosAuthenticationProvider())
+ .authenticationProvider(kerberosServiceAuthenticationProvider());
+ }
+
+ @Bean
+ public KerberosAuthenticationProvider kerberosAuthenticationProvider() {
+ KerberosAuthenticationProvider provider = new KerberosAuthenticationProvider();
+ SunJaasKerberosClient client = new SunJaasKerberosClient();
+ client.setDebug(true);
+ provider.setKerberosClient(client);
+ provider.setUserDetailsService(dummyUserDetailsService());
+ return provider;
+ }
+
+ @Bean
+ public SpnegoEntryPoint spnegoEntryPoint() {
+ return new SpnegoEntryPoint("/login");
+ }
+
+ @Bean
+ public SpnegoAuthenticationProcessingFilter spnegoAuthenticationProcessingFilter(AuthenticationManager authenticationManager) {
+ SpnegoAuthenticationProcessingFilter filter = new SpnegoAuthenticationProcessingFilter();
+ filter.setAuthenticationManager(authenticationManager);
+ return filter;
+ }
+
+ @Bean
+ public KerberosServiceAuthenticationProvider kerberosServiceAuthenticationProvider() {
+ KerberosServiceAuthenticationProvider provider = new KerberosServiceAuthenticationProvider();
+ provider.setTicketValidator(sunJaasKerberosTicketValidator());
+ provider.setUserDetailsService(dummyUserDetailsService());
+ return provider;
+ }
+
+ @Bean
+ public SunJaasKerberosTicketValidator sunJaasKerberosTicketValidator() {
+ SunJaasKerberosTicketValidator ticketValidator = new SunJaasKerberosTicketValidator();
+ ticketValidator.setServicePrincipal("HTTP/demo.kerberos.bealdung.com@baeldung.com");
+ ticketValidator.setKeyTabLocation(new FileSystemResource("baeldung.keytab"));
+ ticketValidator.setDebug(true);
+ return ticketValidator;
+ }
+
+ @Bean
+ public DummyUserDetailsService dummyUserDetailsService() {
+ return new DummyUserDetailsService();
+ }
+
+}
\ No newline at end of file
diff --git a/spring-security-kerberos/src/main/java/org/baeldung/security/DummyUserDetailsService.java b/spring-security-kerberos/src/main/java/org/baeldung/security/DummyUserDetailsService.java
new file mode 100644
index 0000000000..10d71fca8f
--- /dev/null
+++ b/spring-security-kerberos/src/main/java/org/baeldung/security/DummyUserDetailsService.java
@@ -0,0 +1,16 @@
+package org.baeldung.security;
+
+import org.springframework.security.core.authority.AuthorityUtils;
+import org.springframework.security.core.userdetails.User;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.core.userdetails.UserDetailsService;
+import org.springframework.security.core.userdetails.UsernameNotFoundException;
+
+public class DummyUserDetailsService implements UserDetailsService {
+
+ @Override
+ public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
+ return new User(username, "notUsed", true, true, true, true, AuthorityUtils.createAuthorityList("ROLE_USER"));
+ }
+
+}
\ No newline at end of file
diff --git a/spring-security-mvc-ldap/README.md b/spring-security-mvc-ldap/README.md
index ac080c138d..6f03143183 100644
--- a/spring-security-mvc-ldap/README.md
+++ b/spring-security-mvc-ldap/README.md
@@ -5,7 +5,7 @@
The "Learn Spring Security" Classes: http://github.learnspringsecurity.com
### Relevant Article:
-- [Spring Security - security none, filters none, access permitAll](http://www.baeldung.com/security-none-filters-none-access-permitAll)
+- [Spring Security – security none, filters none, access permitAll](http://www.baeldung.com/security-none-filters-none-access-permitAll)
- [Intro to Spring Security LDAP](http://www.baeldung.com/spring-security-ldap)
### Notes
diff --git a/spring-security-mvc-login/README.md b/spring-security-mvc-login/README.md
index c19cbc87a5..983d949cb8 100644
--- a/spring-security-mvc-login/README.md
+++ b/spring-security-mvc-login/README.md
@@ -10,7 +10,7 @@ The "Learn Spring Security" Classes: http://github.learnspringsecurity.com
- [Spring Security Logout](http://www.baeldung.com/spring-security-logout)
- [Spring Security Expressions – hasRole Example](http://www.baeldung.com/spring-security-expressions-basic)
- [Spring HTTP/HTTPS Channel Security](http://www.baeldung.com/spring-channel-security-https)
-- [Spring Security - Customize the 403 Forbidden/Access Denied Page](http://www.baeldung.com/spring-security-custom-access-denied-page)
+- [Spring Security – Customize the 403 Forbidden/Access Denied Page](http://www.baeldung.com/spring-security-custom-access-denied-page)
- [Spring Security – Redirect to the Previous URL After Login](http://www.baeldung.com/spring-security-redirect-login)
- [Spring Security Custom AuthenticationFailureHandler](http://www.baeldung.com/spring-security-custom-authentication-failure-handler)
diff --git a/spring-security-mvc-persisted-remember-me/README.md b/spring-security-mvc-persisted-remember-me/README.md
index e505537be1..db2ae890f9 100644
--- a/spring-security-mvc-persisted-remember-me/README.md
+++ b/spring-security-mvc-persisted-remember-me/README.md
@@ -6,7 +6,7 @@
The "Learn Spring Security" Classes: http://github.learnspringsecurity.com
### Relevant Articles:
-- [Spring Security Persisted Remember Me](http://www.baeldung.com/spring-security-persistent-remember-me)
+- [Spring Security – Persistent Remember Me](http://www.baeldung.com/spring-security-persistent-remember-me)
### Build the Project
```
diff --git a/spring-security-rest-basic-auth/README.md b/spring-security-rest-basic-auth/README.md
index 30da3afbcf..0a48a747c2 100644
--- a/spring-security-rest-basic-auth/README.md
+++ b/spring-security-rest-basic-auth/README.md
@@ -8,6 +8,5 @@ The "Learn Spring Security" Classes: http://github.learnspringsecurity.com
### Relevant Articles:
- [Basic Authentication with the RestTemplate](http://www.baeldung.com/how-to-use-resttemplate-with-basic-authentication-in-spring)
- [HttpClient Timeout](http://www.baeldung.com/httpclient-timeout)
-- [HttpClient with SSL](http://www.baeldung.com/httpclient-ssl)
- [A Custom Filter in the Spring Security Filter Chain](http://www.baeldung.com/spring-security-custom-filter)
- [Spring Security Basic Authentication](http://www.baeldung.com/spring-security-basic-authentication)
diff --git a/spring-security-rest-basic-auth/pom.xml b/spring-security-rest-basic-auth/pom.xml
index ca5c4c38e6..3c7f8eaa2b 100644
--- a/spring-security-rest-basic-auth/pom.xml
+++ b/spring-security-rest-basic-auth/pom.xml
@@ -272,8 +272,8 @@
- 4.4.5
- 4.5.3
+ 4.4.11
+ 4.5.8
1.2
diff --git a/spring-security-rest/README.md b/spring-security-rest/README.md
index f71eead9ae..f450a514b2 100644
--- a/spring-security-rest/README.md
+++ b/spring-security-rest/README.md
@@ -11,7 +11,6 @@ The "Learn Spring Security" Classes: http://github.learnspringsecurity.com
- [Spring REST Service Security](http://www.baeldung.com/2011/10/31/securing-a-restful-web-service-with-spring-security-3-1-part-3/)
- [Setting Up Swagger 2 with a Spring REST API](http://www.baeldung.com/swagger-2-documentation-for-spring-rest-api)
- [Custom Error Message Handling for REST API](http://www.baeldung.com/global-error-handler-in-a-spring-rest-api)
-- [An Intro to Spring HATEOAS](http://www.baeldung.com/spring-hateoas-tutorial)
- [Spring Security Context Propagation with @Async](http://www.baeldung.com/spring-security-async-principal-propagation)
- [Servlet 3 Async Support with Spring MVC and Spring Security](http://www.baeldung.com/spring-mvc-async-security)
- [Intro to Spring Security Expressions](http://www.baeldung.com/spring-security-expressions)
diff --git a/spring-security-rest/pom.xml b/spring-security-rest/pom.xml
index 24f1c5807a..b6039ce9d3 100644
--- a/spring-security-rest/pom.xml
+++ b/spring-security-rest/pom.xml
@@ -84,13 +84,6 @@
${spring.version}
-
-
- org.springframework.hateoas
- spring-hateoas
- ${org.springframework.hateoas.version}
-
-
@@ -273,9 +266,6 @@
-
- 0.25.0.RELEASE
-
3.1.0
1.1.0.Final
diff --git a/spring-security-sso/README.md b/spring-security-sso/README.md
index 11b5f011d5..d0c1b2f7cf 100644
--- a/spring-security-sso/README.md
+++ b/spring-security-sso/README.md
@@ -1,2 +1,2 @@
### Relevant Articles:
-- [Simple Single Sign On with Spring Security OAuth2](http://www.baeldung.com/sso-spring-security-oauth2)
+- [Simple Single Sign-On with Spring Security OAuth2](http://www.baeldung.com/sso-spring-security-oauth2)
diff --git a/spring-security-sso/spring-security-sso-kerberos/src/main/java/kerberos/client/KerberosClientApp.java b/spring-security-sso/spring-security-sso-kerberos/src/main/java/kerberos/client/KerberosClientApp.java
index a353961854..9fb86e7658 100644
--- a/spring-security-sso/spring-security-sso-kerberos/src/main/java/kerberos/client/KerberosClientApp.java
+++ b/spring-security-sso/spring-security-sso-kerberos/src/main/java/kerberos/client/KerberosClientApp.java
@@ -12,6 +12,8 @@ class KerberosClientApp {
System.setProperty("java.security.krb5.conf",
Paths.get(".\\krb-test-workdir\\krb5.conf").normalize().toAbsolutePath().toString());
System.setProperty("sun.security.krb5.debug", "true");
+ // disable usage of local kerberos ticket cache
+ System.setProperty("http.use.global.creds", "false");
}
public static void main(String[] args) {
diff --git a/spring-security-sso/spring-security-sso-kerberos/src/main/java/kerberos/client/SampleService.java b/spring-security-sso/spring-security-sso-kerberos/src/main/java/kerberos/client/SampleClient.java
similarity index 87%
rename from spring-security-sso/spring-security-sso-kerberos/src/main/java/kerberos/client/SampleService.java
rename to spring-security-sso/spring-security-sso-kerberos/src/main/java/kerberos/client/SampleClient.java
index 4145cf0c1a..745193e3b0 100644
--- a/spring-security-sso/spring-security-sso-kerberos/src/main/java/kerberos/client/SampleService.java
+++ b/spring-security-sso/spring-security-sso-kerberos/src/main/java/kerberos/client/SampleClient.java
@@ -5,14 +5,14 @@ import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
@Service
-class SampleService {
+class SampleClient {
@Value("${app.access-url}")
private String endpoint;
private RestTemplate restTemplate;
- public SampleService(RestTemplate restTemplate) {
+ public SampleClient(RestTemplate restTemplate) {
this.restTemplate = restTemplate;
}
diff --git a/spring-security-sso/spring-security-sso-kerberos/src/test/java/kerberos/client/SampleServiceManualTest.java b/spring-security-sso/spring-security-sso-kerberos/src/test/java/kerberos/client/SampleClientManualTest.java
similarity index 59%
rename from spring-security-sso/spring-security-sso-kerberos/src/test/java/kerberos/client/SampleServiceManualTest.java
rename to spring-security-sso/spring-security-sso-kerberos/src/test/java/kerberos/client/SampleClientManualTest.java
index d0d9f0ae4b..fdb1b12531 100644
--- a/spring-security-sso/spring-security-sso-kerberos/src/test/java/kerberos/client/SampleServiceManualTest.java
+++ b/spring-security-sso/spring-security-sso-kerberos/src/test/java/kerberos/client/SampleClientManualTest.java
@@ -1,6 +1,5 @@
package kerberos.client;
-import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
@@ -10,7 +9,6 @@ import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;
import static org.junit.Assert.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
/**
@@ -23,21 +21,19 @@ import static org.junit.jupiter.api.Assertions.assertThrows;
*/
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
-@FixMethodOrder
-public class SampleServiceManualTest {
+public class SampleClientManualTest {
@Autowired
- private SampleService sampleService;
+ private SampleClient sampleClient;
@Test
- public void a_givenKerberizedRestTemplate_whenServiceCall_thenSuccess() {
- assertNotNull(sampleService);
- assertEquals("data from kerberized server", sampleService.getData());
+ public void givenKerberizedRestTemplate_whenServiceCall_thenSuccess() {
+ assertEquals("data from kerberized server", sampleClient.getData());
}
@Test
- public void b_givenRestTemplate_whenServiceCall_thenFail() {
- sampleService.setRestTemplate(new RestTemplate());
- assertThrows(RestClientException.class, sampleService::getData);
+ public void givenRestTemplate_whenServiceCall_thenFail() {
+ sampleClient.setRestTemplate(new RestTemplate());
+ assertThrows(RestClientException.class, sampleClient::getData);
}
}
\ No newline at end of file
diff --git a/spring-thymeleaf/README.md b/spring-thymeleaf/README.md
index f9e7dd90a7..b6824003db 100644
--- a/spring-thymeleaf/README.md
+++ b/spring-thymeleaf/README.md
@@ -8,7 +8,7 @@
- [Thymeleaf: Custom Layout Dialect](http://www.baeldung.com/thymeleaf-spring-layouts)
- [Spring and Thymeleaf 3: Expressions](http://www.baeldung.com/spring-thymeleaf-3-expressions)
- [Spring MVC + Thymeleaf 3.0: New Features](http://www.baeldung.com/spring-thymeleaf-3)
-- [How to Work with Dates in Thymeleaef](http://www.baeldung.com/dates-in-thymeleaf)
+- [How to Work with Dates in Thymeleaf](http://www.baeldung.com/dates-in-thymeleaf)
- [How to Create an Executable JAR with Maven](http://www.baeldung.com/executable-jar-with-maven)
- [Working with Boolean in Thymeleaf](http://www.baeldung.com/thymeleaf-boolean)
- [Working with Fragments in Thymeleaf](http://www.baeldung.com/spring-thymeleaf-fragments)
diff --git a/tensorflow-java/README.md b/tensorflow-java/README.md
index aa9e9e56b9..f826375ac1 100644
--- a/tensorflow-java/README.md
+++ b/tensorflow-java/README.md
@@ -1,3 +1,3 @@
## Relevant articles:
-- [TensorFlow for Java](https://www.baeldung.com/tensorflow-java)
+- [Introduction to Tensorflow for Java](https://www.baeldung.com/tensorflow-java)
diff --git a/testing-modules/groovy-spock/README.md b/testing-modules/groovy-spock/README.md
index a98df27172..e61c56d470 100644
--- a/testing-modules/groovy-spock/README.md
+++ b/testing-modules/groovy-spock/README.md
@@ -2,3 +2,4 @@
- [Introduction to Testing with Spock and Groovy](http://www.baeldung.com/groovy-spock)
- [Difference Between Stub, Mock, and Spy in the Spock Framework](https://www.baeldung.com/spock-stub-mock-spy)
+- [Guide to Spock Extensions](https://www.baeldung.com/spock-extensions)
diff --git a/testing-modules/groovy-spock/pom.xml b/testing-modules/groovy-spock/pom.xml
index d6097af208..35d8f5034f 100644
--- a/testing-modules/groovy-spock/pom.xml
+++ b/testing-modules/groovy-spock/pom.xml
@@ -48,7 +48,7 @@
- 1.3-RC1-groovy-2.4
+ 1.3-groovy-2.4
2.4.7
1.5
diff --git a/testing-modules/groovy-spock/src/test/groovy/extensions/IgnoreIfTest.groovy b/testing-modules/groovy-spock/src/test/groovy/extensions/IgnoreIfTest.groovy
index 91da2ff1ec..9010481220 100644
--- a/testing-modules/groovy-spock/src/test/groovy/extensions/IgnoreIfTest.groovy
+++ b/testing-modules/groovy-spock/src/test/groovy/extensions/IgnoreIfTest.groovy
@@ -7,6 +7,16 @@ import spock.lang.Specification
class IgnoreIfTest extends Specification {
@IgnoreIf({System.getProperty("os.name").contains("windows")})
- def "I won't run on windows"() { }
+ def "I won't run on windows"() {
+ expect:
+ true
+ }
+
+ @IgnoreIf({ os.isWindows() })
+ def "I'm using Spock helper classes to run only on windows"() {
+ expect:
+ true
+ }
+
}
diff --git a/testing-modules/groovy-spock/src/test/resources/SpockConfig.groovy b/testing-modules/groovy-spock/src/test/resources/SpockConfig.groovy
index ed94e61cbf..4b017aeefc 100644
--- a/testing-modules/groovy-spock/src/test/resources/SpockConfig.groovy
+++ b/testing-modules/groovy-spock/src/test/resources/SpockConfig.groovy
@@ -2,7 +2,10 @@ import extensions.TimeoutTest
import spock.lang.Issue
runner {
- filterStackTrace true
+
+ if (System.getenv("FILTER_STACKTRACE") == null) {
+ filterStackTrace false
+ }
report {
issueNamePrefix 'Bug '
diff --git a/testing-modules/junit-5/README.md b/testing-modules/junit-5/README.md
index d686396a1d..aafdd75e81 100644
--- a/testing-modules/junit-5/README.md
+++ b/testing-modules/junit-5/README.md
@@ -6,7 +6,7 @@
- [A Guide to JUnit 5 Extensions](http://www.baeldung.com/junit-5-extensions)
- [Inject Parameters into JUnit Jupiter Unit Tests](http://www.baeldung.com/junit-5-parameters)
- [Mockito and JUnit 5 – Using ExtendWith](http://www.baeldung.com/mockito-junit-5-extension)
-- [JUnit 5 – @RunWith](http://www.baeldung.com/junit-5-runwith)
+- [JUnit 5 @RunWith](http://www.baeldung.com/junit-5-runwith)
- [JUnit 5 @Test Annotation](http://www.baeldung.com/junit-5-test-annotation)
- [Assert an Exception is Thrown in JUnit 4 and 5](http://www.baeldung.com/junit-assert-exception)
- [@Before vs @BeforeClass vs @BeforeEach vs @BeforeAll](http://www.baeldung.com/junit-before-beforeclass-beforeeach-beforeall)
diff --git a/testing-modules/rest-assured/README.md b/testing-modules/rest-assured/README.md
index de15515f9d..d44fd08335 100644
--- a/testing-modules/rest-assured/README.md
+++ b/testing-modules/rest-assured/README.md
@@ -1,3 +1,4 @@
###Relevant Articles:
- [A Guide to REST-assured](http://www.baeldung.com/rest-assured-tutorial)
- [REST-assured Support for Spring MockMvc](https://www.baeldung.com/spring-mock-mvc-rest-assured)
+- [Getting and Verifying Response Data with REST-assured](https://www.baeldung.com/rest-assured-response)
diff --git a/testing-modules/rest-assured/pom.xml b/testing-modules/rest-assured/pom.xml
index cd342ccd11..c528a34e21 100644
--- a/testing-modules/rest-assured/pom.xml
+++ b/testing-modules/rest-assured/pom.xml
@@ -162,6 +162,11 @@
commons-collections
${commons-collections.version}
+
+
+ org.springframework.boot
+ spring-boot-starter-security
+
@@ -179,6 +184,12 @@
json-schema-validator
test
+
+ com.github.scribejava
+ scribejava-apis
+ ${scribejava.version}
+ test
+
@@ -211,6 +222,8 @@
3.0.1
3.0.1
+
+ 2.5.3
diff --git a/testing-modules/rest-assured/src/test/java/com/baeldung/restassured/authentication/BasicAuthenticationLiveTest.java b/testing-modules/rest-assured/src/test/java/com/baeldung/restassured/authentication/BasicAuthenticationLiveTest.java
new file mode 100644
index 0000000000..aff765dfa3
--- /dev/null
+++ b/testing-modules/rest-assured/src/test/java/com/baeldung/restassured/authentication/BasicAuthenticationLiveTest.java
@@ -0,0 +1,38 @@
+package com.baeldung.restassured.authentication;
+
+import static io.restassured.RestAssured.get;
+import static io.restassured.RestAssured.given;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.http.HttpStatus;
+
+/**
+ * For this Live Test we need:
+ * * a running instance of the service located in the spring-security-rest-basic-auth module.
+ * @see spring-security-rest-basic-auth module
+ *
+ */
+public class BasicAuthenticationLiveTest {
+
+ private static final String USER = "user1";
+ private static final String PASSWORD = "user1Pass";
+ private static final String SVC_URL = "http://localhost:8080/spring-security-rest-basic-auth/api/foos/1";
+
+ @Test
+ public void givenNoAuthentication_whenRequestSecuredResource_thenUnauthorizedResponse() {
+ get(SVC_URL).then()
+ .assertThat()
+ .statusCode(HttpStatus.UNAUTHORIZED.value());
+ }
+
+ @Test
+ public void givenBasicAuthentication_whenRequestSecuredResource_thenResourceRetrieved() {
+ given().auth()
+ .basic(USER, PASSWORD)
+ .when()
+ .get(SVC_URL)
+ .then()
+ .assertThat()
+ .statusCode(HttpStatus.OK.value());
+ }
+}
diff --git a/testing-modules/rest-assured/src/test/java/com/baeldung/restassured/authentication/BasicPreemtiveAuthenticationLiveTest.java b/testing-modules/rest-assured/src/test/java/com/baeldung/restassured/authentication/BasicPreemtiveAuthenticationLiveTest.java
new file mode 100644
index 0000000000..02138f22e3
--- /dev/null
+++ b/testing-modules/rest-assured/src/test/java/com/baeldung/restassured/authentication/BasicPreemtiveAuthenticationLiveTest.java
@@ -0,0 +1,56 @@
+package com.baeldung.restassured.authentication;
+
+import static io.restassured.RestAssured.get;
+import static io.restassured.RestAssured.given;
+import static org.hamcrest.Matchers.containsString;
+import static org.hamcrest.Matchers.is;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.http.HttpStatus;
+
+/**
+ * For this Live Test we need:
+ * * a running instance of the service located in the spring-boot-admin/spring-boot-admin-server module.
+ * @see spring-boot-admin/spring-boot-admin-server module
+ *
+ */
+public class BasicPreemtiveAuthenticationLiveTest {
+
+ private static final String USER = "admin";
+ private static final String PASSWORD = "admin";
+ private static final String SVC_URL = "http://localhost:8080/api/applications/";
+
+ @Test
+ public void givenNoAuthentication_whenRequestSecuredResource_thenUnauthorizedResponse() {
+ get(SVC_URL).then()
+ .assertThat()
+ .statusCode(HttpStatus.OK.value())
+ .content(containsString("