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/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-java-8-2/src/test/java/com/baeldung/UnitTest.java b/core-java-8-2/src/test/java/com/baeldung/UnitTest.java
deleted file mode 100644
index 9757901f52..0000000000
--- a/core-java-8-2/src/test/java/com/baeldung/UnitTest.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.baeldung;
-
-import static org.junit.Assert.assertTrue;
-
-import org.junit.Test;
-
-/**
- * Unit test for simple App.
- */
-public class UnitTest {
- /**
- * Stub test
- */
- @Test
- public void givenPreconditions_whenCondition_shouldResult() {
- assertTrue(true);
- }
-}
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-8-2/src/main/java/com/baeldung/anonymous/Book.java b/core-java-lang-oop-2/src/main/java/com/baeldung/anonymous/Book.java
similarity index 100%
rename from core-java-8-2/src/main/java/com/baeldung/anonymous/Book.java
rename to core-java-lang-oop-2/src/main/java/com/baeldung/anonymous/Book.java
diff --git a/core-java-8-2/src/main/java/com/baeldung/anonymous/Main.java b/core-java-lang-oop-2/src/main/java/com/baeldung/anonymous/Main.java
similarity index 100%
rename from core-java-8-2/src/main/java/com/baeldung/anonymous/Main.java
rename to core-java-lang-oop-2/src/main/java/com/baeldung/anonymous/Main.java
diff --git a/core-java-lang-oop-2/src/main/java/com/baeldung/generics/Entry.java b/core-java-lang-oop-2/src/main/java/com/baeldung/generics/Entry.java
new file mode 100644
index 0000000000..07759ca9ba
--- /dev/null
+++ b/core-java-lang-oop-2/src/main/java/com/baeldung/generics/Entry.java
@@ -0,0 +1,38 @@
+package com.baeldung.generics;
+
+import java.io.Serializable;
+
+public class Entry {
+ private String data;
+ private int rank;
+
+ // non-generic constructor
+ public Entry(String data, int rank) {
+ this.data = data;
+ this.rank = rank;
+ }
+
+ // generic constructor
+ public Entry(E element) {
+ this.data = element.toString();
+ this.rank = element.getRank();
+ }
+
+ // getters and setters
+ public String getData() {
+ return data;
+ }
+
+ public void setData(String data) {
+ this.data = data;
+ }
+
+ public int getRank() {
+ return rank;
+ }
+
+ public void setRank(int rank) {
+ this.rank = rank;
+ }
+
+}
diff --git a/core-java-lang-oop-2/src/main/java/com/baeldung/generics/GenericEntry.java b/core-java-lang-oop-2/src/main/java/com/baeldung/generics/GenericEntry.java
new file mode 100644
index 0000000000..27d3a44069
--- /dev/null
+++ b/core-java-lang-oop-2/src/main/java/com/baeldung/generics/GenericEntry.java
@@ -0,0 +1,53 @@
+package com.baeldung.generics;
+
+import java.io.Serializable;
+import java.util.Optional;
+
+public class GenericEntry {
+ private T data;
+ private int rank;
+
+ // non-generic constructor
+ public GenericEntry(int rank) {
+ this.rank = rank;
+ }
+
+ // generic constructor
+ public GenericEntry(T data, int rank) {
+ this.data = data;
+ this.rank = rank;
+ }
+
+ // generic constructor with different type
+ public GenericEntry(E element) {
+ this.data = (T) element;
+ this.rank = element.getRank();
+ }
+
+ // generic constructor with different type and wild card
+ public GenericEntry(Optional extends Rankable> optional) {
+ if (optional.isPresent()) {
+ this.data = (T) optional.get();
+ this.rank = optional.get()
+ .getRank();
+ }
+ }
+
+ // getters and setters
+ public T getData() {
+ return data;
+ }
+
+ public void setData(T data) {
+ this.data = data;
+ }
+
+ public int getRank() {
+ return rank;
+ }
+
+ public void setRank(int rank) {
+ this.rank = rank;
+ }
+
+}
diff --git a/core-java-lang-oop-2/src/main/java/com/baeldung/generics/MapEntry.java b/core-java-lang-oop-2/src/main/java/com/baeldung/generics/MapEntry.java
new file mode 100644
index 0000000000..3d626b2fa5
--- /dev/null
+++ b/core-java-lang-oop-2/src/main/java/com/baeldung/generics/MapEntry.java
@@ -0,0 +1,34 @@
+package com.baeldung.generics;
+
+public class MapEntry {
+ private K key;
+ private V value;
+
+ public MapEntry() {
+ super();
+ }
+
+ // generic constructor with two parameters
+ public MapEntry(K key, V value) {
+ this.key = key;
+ this.value = value;
+ }
+
+ // getters and setters
+ public K getKey() {
+ return key;
+ }
+
+ public void setKey(K key) {
+ this.key = key;
+ }
+
+ public V getValue() {
+ return value;
+ }
+
+ public void setValue(V value) {
+ this.value = value;
+ }
+
+}
diff --git a/core-java-lang-oop-2/src/main/java/com/baeldung/generics/Product.java b/core-java-lang-oop-2/src/main/java/com/baeldung/generics/Product.java
new file mode 100644
index 0000000000..bfc9f63071
--- /dev/null
+++ b/core-java-lang-oop-2/src/main/java/com/baeldung/generics/Product.java
@@ -0,0 +1,50 @@
+package com.baeldung.generics;
+
+import java.io.Serializable;
+
+public class Product implements Rankable, Serializable {
+ private String name;
+ private double price;
+ private int sales;
+
+ public Product(String name, double price) {
+ this.name = name;
+ this.price = price;
+ }
+
+ @Override
+ public int getRank() {
+ return sales;
+ }
+
+ @Override
+ public String toString() {
+ return "Product [name=" + name + ", price=" + price + ", sales=" + sales + "]";
+ }
+
+ // getters and setters
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public double getPrice() {
+ return price;
+ }
+
+ public void setPrice(double price) {
+ this.price = price;
+ }
+
+ public int getSales() {
+ return sales;
+ }
+
+ public void setSales(int sales) {
+ this.sales = sales;
+ }
+
+}
diff --git a/core-java-lang-oop-2/src/main/java/com/baeldung/generics/Rankable.java b/core-java-lang-oop-2/src/main/java/com/baeldung/generics/Rankable.java
new file mode 100644
index 0000000000..72bda67d9d
--- /dev/null
+++ b/core-java-lang-oop-2/src/main/java/com/baeldung/generics/Rankable.java
@@ -0,0 +1,5 @@
+package com.baeldung.generics;
+
+public interface Rankable {
+ public int getRank();
+}
diff --git a/core-java-lang-oop-2/src/test/java/com/baeldung/generics/GenericConstructorUnitTest.java b/core-java-lang-oop-2/src/test/java/com/baeldung/generics/GenericConstructorUnitTest.java
new file mode 100644
index 0000000000..60907bbfd3
--- /dev/null
+++ b/core-java-lang-oop-2/src/test/java/com/baeldung/generics/GenericConstructorUnitTest.java
@@ -0,0 +1,76 @@
+package com.baeldung.generics;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+import java.io.Serializable;
+import java.util.Optional;
+
+import org.junit.Test;
+
+public class GenericConstructorUnitTest {
+
+ @Test
+ public void givenNonGenericConstructor_whenCreateNonGenericEntry_thenOK() {
+ Entry entry = new Entry("sample", 1);
+
+ assertEquals("sample", entry.getData());
+ assertEquals(1, entry.getRank());
+ }
+
+ @Test
+ public void givenGenericConstructor_whenCreateNonGenericEntry_thenOK() {
+ Product product = new Product("milk", 2.5);
+ product.setSales(30);
+ Entry entry = new Entry(product);
+
+ assertEquals(product.toString(), entry.getData());
+ assertEquals(30, entry.getRank());
+ }
+
+ @Test
+ public void givenNonGenericConstructor_whenCreateGenericEntry_thenOK() {
+ GenericEntry entry = new GenericEntry(1);
+
+ assertNull(entry.getData());
+ assertEquals(1, entry.getRank());
+ }
+
+ @Test
+ public void givenGenericConstructor_whenCreateGenericEntry_thenOK() {
+ GenericEntry entry = new GenericEntry("sample", 1);
+
+ assertEquals("sample", entry.getData());
+ assertEquals(1, entry.getRank());
+ }
+
+ @Test
+ public void givenGenericConstructorWithDifferentType_whenCreateGenericEntry_thenOK() {
+ Product product = new Product("milk", 2.5);
+ product.setSales(30);
+ GenericEntry entry = new GenericEntry(product);
+
+ assertEquals(product, entry.getData());
+ assertEquals(30, entry.getRank());
+ }
+
+ @Test
+ public void givenGenericConstructorWithWildCard_whenCreateGenericEntry_thenOK() {
+ Product product = new Product("milk", 2.5);
+ product.setSales(30);
+ Optional optional = Optional.of(product);
+ GenericEntry entry = new GenericEntry(optional);
+
+ assertEquals(product, entry.getData());
+ assertEquals(30, entry.getRank());
+ }
+
+ @Test
+ public void givenGenericConstructor_whenCreateGenericEntryWithTwoTypes_thenOK() {
+ MapEntry entry = new MapEntry("sample", 1);
+
+ assertEquals("sample", entry.getKey());
+ assertEquals(1, entry.getValue()
+ .intValue());
+ }
+}
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-2/src/test/kotlin/com/baeldung/console/ConsoleIOUnitTest.kt b/core-kotlin-2/src/test/kotlin/com/baeldung/console/ConsoleIOUnitTest.kt
new file mode 100644
index 0000000000..c73096fce6
--- /dev/null
+++ b/core-kotlin-2/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-2/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker b/core-kotlin-2/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker
new file mode 100644
index 0000000000..ca6ee9cea8
--- /dev/null
+++ b/core-kotlin-2/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-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..2e21079d7f
--- /dev/null
+++ b/core-kotlin-io/pom.xml
@@ -0,0 +1,78 @@
+
+
+ 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.platform
+ junit-platform-runner
+ ${junit.platform.version}
+ test
+
+
+ org.assertj
+ assertj-core
+ ${assertj.version}
+ test
+
+
+ org.jetbrains.kotlin
+ kotlin-test
+ ${kotlin.version}
+ test
+
+
+
+
+
+
+ org.jetbrains.kotlin
+ kotlin-maven-plugin
+ ${kotlin.version}
+
+
+ compile
+ compile
+
+ compile
+
+
+
+ test-compile
+ test-compile
+
+ test-compile
+
+
+
+
+ 1.8
+
+
+
+
+
+
+ 1.2.71
+ 1.1.1
+ 5.2.0
+ 3.10.0
+
+
+
\ No newline at end of file
diff --git a/core-kotlin-2/src/main/kotlin/com/baeldung/inputstream/InputStreamExtension.kt b/core-kotlin-io/src/main/kotlin/com/baeldung/inputstream/InputStreamExtension.kt
similarity index 100%
rename from core-kotlin-2/src/main/kotlin/com/baeldung/inputstream/InputStreamExtension.kt
rename to core-kotlin-io/src/main/kotlin/com/baeldung/inputstream/InputStreamExtension.kt
diff --git a/core-kotlin-2/src/test/kotlin/com/baeldung/inputstream/InputStreamToStringTest.kt b/core-kotlin-io/src/test/kotlin/com/baeldung/inputstream/InputStreamToStringTest.kt
similarity index 93%
rename from core-kotlin-2/src/test/kotlin/com/baeldung/inputstream/InputStreamToStringTest.kt
rename to core-kotlin-io/src/test/kotlin/com/baeldung/inputstream/InputStreamToStringTest.kt
index 3437ddb68a..d10d23bef0 100644
--- a/core-kotlin-2/src/test/kotlin/com/baeldung/inputstream/InputStreamToStringTest.kt
+++ b/core-kotlin-io/src/test/kotlin/com/baeldung/inputstream/InputStreamToStringTest.kt
@@ -8,7 +8,8 @@ import kotlin.test.assertEquals
class InputStreamToStringTest {
private val fileName = "src/test/resources/inputstream2string.txt"
- private val fileFullContent = "Computer programming can be a hassle\r\n" +
+ 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
@@ -46,7 +47,7 @@ class InputStreamToStringTest {
} finally {
reader.close()
}
- assertEquals(fileFullContent.replace("\r\n", ""), content.toString())
+ assertEquals(fileFullContent.replace(endOfLine, ""), content.toString())
}
diff --git a/core-kotlin-2/src/test/resources/inputstream2string.txt b/core-kotlin-io/src/test/resources/inputstream2string.txt
similarity index 100%
rename from core-kotlin-2/src/test/resources/inputstream2string.txt
rename to core-kotlin-io/src/test/resources/inputstream2string.txt
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/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..d1224359e0
--- /dev/null
+++ b/httpclient-simple/README.md
@@ -0,0 +1,11 @@
+=========
+## 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)
\ No newline at end of file
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/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 c5956068c6..ce98d7e72e 100644
--- a/httpclient/README.md
+++ b/httpclient/README.md
@@ -8,7 +8,6 @@ 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 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)
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 eeb8f1b874..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)
@@ -17,10 +15,8 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring
- [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/Deserialized](http://www.baeldung.com/jackson-field-serializable-deserializable-or-not)
-- [Jackson Annotation Examples](http://www.baeldung.com/jackson-annotations)
- [Working with Tree Model Nodes in Jackson](http://www.baeldung.com/jackson-json-node-tree-model)
- [Jackson vs Gson](http://www.baeldung.com/jackson-vs-gson)
-- [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/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/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/pom.xml b/persistence-modules/pom.xml
index 47c733d8a7..ee55325b20 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
diff --git a/persistence-modules/spring-boot-h2/spring-boot-h2-database/src/main/resources/data.sql b/persistence-modules/spring-boot-h2/spring-boot-h2-database/src/main/resources/data.sql
new file mode 100644
index 0000000000..2d7b446005
--- /dev/null
+++ b/persistence-modules/spring-boot-h2/spring-boot-h2-database/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/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-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/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-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/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/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/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/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/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 d57fa1694e..0de4a36336 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,12 +376,13 @@
cdi
checker-plugin
core-groovy
+ core-groovy-2
-
+
core-java-8
core-java-8-2
- core-java-lambdas
+ core-java-lambdas
core-java-arrays
@@ -404,7 +405,7 @@
core-scala
couchbase
custom-pmd
-
+
dagger
data-structures
ddd
@@ -412,13 +413,13 @@
disruptor
dozer
drools
- dubbo
-
+ dubbo
+
ethereum
-
+
feign
flyway-cdi-extension
-
+
geotools
google-cloud
google-web-toolkit
@@ -432,17 +433,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
@@ -484,7 +487,7 @@
kotlin-libraries
-
+
libraries
libraries-2
@@ -511,8 +514,8 @@
mustache
mybatis
-
-
+
+
optaplanner
orika
osgi
@@ -522,9 +525,9 @@
performance-tests
protobuffer
-
+
persistence-modules
-
+
rabbitmq
ratpack
@@ -536,16 +539,17 @@
rule-engines
rsocket
rxjava
- rxjava-2
+ rxjava-2
software-security/sql-injection-samples
-
+
tensorflow-java
spring-boot-flowable
-
+ spring-security-kerberos
+
-
+
default-second
@@ -579,12 +583,12 @@
parent-spring-5
parent-java
parent-kotlin
-
+
saas
spark-java
-
+
spring-4
-
+
spring-5
spring-5-webflux
spring-5-data-reactive
@@ -595,7 +599,7 @@
spring-5-reactive-security
spring-5-security
spring-5-security-oauth
-
+
spring-activiti
spring-akka
spring-all
@@ -605,7 +609,7 @@
spring-apache-camel
spring-batch
spring-bom
-
+
spring-boot
spring-boot-admin
spring-boot-angular
@@ -615,6 +619,7 @@
spring-boot-camel
spring-boot-client
+ spring-boot-configuration
spring-boot-crud
spring-boot-ctx-fluent
spring-boot-custom-starter
@@ -633,41 +638,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
@@ -679,12 +684,12 @@
spring-mvc-velocity
spring-mvc-webflow
spring-mvc-xml
-
+
spring-protobuf
-
+
spring-quartz
-
+
spring-reactive-kotlin
spring-reactor
spring-remoting
@@ -700,9 +705,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
@@ -730,49 +735,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
@@ -814,6 +820,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
@@ -910,8 +917,9 @@
persistence-modules/spring-data-eclipselink
persistence-modules/spring-data-solr
persistence-modules/spring-hibernate-5
-
+
spring-boot-flowable
+ spring-security-kerberos
@@ -949,10 +957,11 @@
parent-spring-5
parent-java
parent-kotlin
-
+
core-java-concurrency-advanced
core-kotlin
core-kotlin-2
+ core-kotlin-io
jenkins/hello-world
jws
@@ -960,14 +969,15 @@
libraries
persistence-modules/hibernate5
+ persistence-modules/hibernate-mapping
persistence-modules/java-jpa
persistence-modules/java-mongodb
- persistence-modules/jnosql
+ persistence-modules/jnosql
- vaadin
+ vaadin
-
+
integration-lite-first
@@ -1038,8 +1048,9 @@
cdi
checker-plugin
core-groovy
+ core-groovy-2
-
+
core-java-8
core-java-8-2
@@ -1062,7 +1073,7 @@
core-scala
couchbase
custom-pmd
-
+
dagger
data-structures
ddd
@@ -1070,13 +1081,13 @@
disruptor
dozer
drools
- dubbo
-
+ dubbo
+
ethereum
-
+
feign
flyway-cdi-extension
-
+
geotools
google-cloud
google-web-toolkit
@@ -1090,17 +1101,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
@@ -1141,7 +1154,7 @@
kotlin-libraries
-
+
libraries
libraries-data
@@ -1167,8 +1180,8 @@
mustache
mybatis
-
-
+
+
optaplanner
orika
osgi
@@ -1178,9 +1191,9 @@
performance-tests
protobuffer
-
+
persistence-modules
-
+
rabbitmq
ratpack
@@ -1192,8 +1205,8 @@
rule-engines
rsocket
rxjava
- rxjava-2
-
+ rxjava-2
+
@@ -1227,12 +1240,12 @@
parent-spring-5
parent-java
parent-kotlin
-
+
saas
spark-java
-
+
spring-4
-
+
spring-5
spring-5-data-reactive
spring-5-mvc
@@ -1242,7 +1255,7 @@
spring-5-reactive-security
spring-5-security
spring-5-security-oauth
-
+
spring-activiti
spring-akka
spring-all
@@ -1252,7 +1265,7 @@
spring-apache-camel
spring-batch
spring-bom
-
+
spring-boot
spring-boot-admin
spring-boot-angular
@@ -1262,6 +1275,7 @@
spring-boot-camel
spring-boot-client
+ spring-boot-configuration
spring-boot-crud
spring-boot-ctx-fluent
spring-boot-custom-starter
@@ -1278,41 +1292,41 @@
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
@@ -1324,12 +1338,12 @@
spring-mvc-velocity
spring-mvc-webflow
spring-mvc-xml
-
+
spring-protobuf
-
+
spring-quartz
-
+
spring-reactive-kotlin
spring-reactor
spring-remoting
@@ -1342,13 +1356,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
@@ -1375,42 +1389,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
-
+
@@ -1444,8 +1458,8 @@
parent-spring-5
parent-java
parent-kotlin
-
- core-java
+
+ core-java
core-java-concurrency-advanced
core-kotlin
core-kotlin-2
@@ -1458,9 +1472,9 @@
persistence-modules/hibernate5
persistence-modules/java-jpa
persistence-modules/java-mongodb
- persistence-modules/jnosql
+ persistence-modules/jnosql
- vaadin
+ vaadin
@@ -1486,15 +1500,15 @@
false
false
false
-
+
4.12
1.3
2.21.0
-
+
1.7.21
1.1.7
-
+
2.21.0
3.7.0
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-mvc-birt/pom.xml b/spring-boot-mvc-birt/pom.xml
index 05d3f3865a..8f41e8410a 100644
--- a/spring-boot-mvc-birt/pom.xml
+++ b/spring-boot-mvc-birt/pom.xml
@@ -75,7 +75,7 @@
2.1.1.RELEASE
- com.baeldung.springbootmvc.SpringBootMvcApplication
+ com.baeldung.birt.engine.ReportEngineApplication
1.8
1.8
diff --git a/spring-boot-rest/README.md b/spring-boot-rest/README.md
index dc0a573c78..b28192cf62 100644
--- a/spring-boot-rest/README.md
+++ b/spring-boot-rest/README.md
@@ -7,7 +7,7 @@ Module for the articles that are part of the Spring REST E-book:
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.
+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)
@@ -16,4 +16,3 @@ Module for the articles that are part of the Spring REST E-book:
- [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)
-- [An Intro to Spring HATEOAS](http://www.baeldung.com/spring-hateoas-tutorial)
\ No newline at end of file
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-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-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-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/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("