diff --git a/README.md b/README.md
index d20968b455..adb17ca7e5 100644
--- a/README.md
+++ b/README.md
@@ -2,41 +2,22 @@
The "REST with Spring" Classes
==============================
-Here's the Master Class of REST With Spring (price changes permanently next Friday):
-**[>> THE REST WITH SPRING MASTER CLASS](http://www.baeldung.com/rest-with-spring-course?utm_source=github&utm_medium=social&utm_content=tutorials&utm_campaign=rws#master-class)**
+Here's the Master Class of REST With Spring (along with the newly announced Boot 2 material):
+**[>> THE REST WITH SPRING - MASTER CLASS](http://www.baeldung.com/rest-with-spring-course?utm_source=github&utm_medium=social&utm_content=tutorials&utm_campaign=rws#master-class)**
And here's the Master Class of Learn Spring Security:
-**[>> LEARN SPRING SECURITY MASTER CLASS](http://www.baeldung.com/learn-spring-security-course?utm_source=github&utm_medium=social&utm_content=tutorials&utm_campaign=lss#master-class)**
+**[>> LEARN SPRING SECURITY - MASTER CLASS](http://www.baeldung.com/learn-spring-security-course?utm_source=github&utm_medium=social&utm_content=tutorials&utm_campaign=lss#master-class)**
-Spring Tutorials
+Java and Spring Tutorials
================
-This project is **a collection of small and focused tutorials** each covering a single and well defined area of development.
-Most of the tutorial projects are focused on the `Spring Framework` (and `Spring Security`).
+This project is **a collection of small and focused tutorials** - each covering a single and well defined area of development in the Java ecosystem.
+A strong focus of these is, of course, the Spring Framework - Spring, Spring Boot and Spring Securiyt.
In additional to Spring, the following technologies are in focus: `core Java`, `Jackson`, `HttpClient`, `Guava`.
+
Building the project
====================
To do the full build, do: `mvn install -Pdefault -Dgib.enabled=false`
-
-
-Working with the code in Eclipse
-================================
-Any IDE can be used to work with the projects, but if you're using Eclipse, consider the following.
-
-- import the included **formatter** in Eclipse:
-`https://github.com/eugenp/tutorials/tree/master/eclipse`
-
-
-CI - Jenkins
-================================
-This tutorials project is being built **[>> HERE](https://rest-security.ci.cloudbees.com/job/tutorials-unit/)**
-
-### Relevant Articles:
-================================
-
-- [Apache Maven Standard Directory Layout](http://www.baeldung.com/maven-directory-structure)
-- [Apache Maven Tutorial](http://www.baeldung.com/maven)
-- [Designing a User Friendly Java Library](http://www.baeldung.com/design-a-user-friendly-java-library)
diff --git a/algorithms/src/main/java/com/baeldung/algorithms/kthlargest/FindKthLargest.java b/algorithms/src/main/java/com/baeldung/algorithms/kthlargest/FindKthLargest.java
index 822abdae02..7054979ada 100644
--- a/algorithms/src/main/java/com/baeldung/algorithms/kthlargest/FindKthLargest.java
+++ b/algorithms/src/main/java/com/baeldung/algorithms/kthlargest/FindKthLargest.java
@@ -98,7 +98,7 @@ public class FindKthLargest {
private int randomPartition(Integer arr[], int left, int right) {
int n = right - left + 1;
- int pivot = (int) (Math.random()) % n;
+ int pivot = (int) (Math.random() * n);
swap(arr, left + pivot, right);
return partition(arr, left, right);
}
diff --git a/core-java-8/src/test/java/com/baeldung/java8/Java8SortUnitTest.java b/core-java-8/src/test/java/com/baeldung/java8/Java8SortUnitTest.java
index f371c0d7da..71ec5b147f 100644
--- a/core-java-8/src/test/java/com/baeldung/java8/Java8SortUnitTest.java
+++ b/core-java-8/src/test/java/com/baeldung/java8/Java8SortUnitTest.java
@@ -1,16 +1,18 @@
package com.baeldung.java8;
-import com.baeldung.java8.entity.Human;
-import com.google.common.collect.Lists;
-import com.google.common.primitives.Ints;
-import org.junit.Assert;
-import org.junit.Test;
+import static org.hamcrest.Matchers.equalTo;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
+import java.util.stream.Collectors;
-import static org.hamcrest.Matchers.equalTo;
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.baeldung.java8.entity.Human;
+import com.google.common.collect.Lists;
+import com.google.common.primitives.Ints;
public class Java8SortUnitTest {
@@ -111,5 +113,22 @@ public class Java8SortUnitTest {
humans.sort(Comparator.comparing(Human::getName));
Assert.assertThat(humans.get(0), equalTo(new Human("Jack", 12)));
}
+
+ @Test
+ public final void givenStreamNaturalOrdering_whenSortingEntitiesByName_thenCorrectlySorted() {
+ final List letters = Lists.newArrayList("B", "A", "C");
+
+ final List sortedLetters = letters.stream().sorted().collect(Collectors.toList());
+ Assert.assertThat(sortedLetters.get(0), equalTo("A"));
+ }
+ @Test
+ public final void givenStreamCustomOrdering_whenSortingEntitiesByName_thenCorrectlySorted() {
+
+ final List humans = Lists.newArrayList(new Human("Sarah", 10), new Human("Jack", 12));
+ final Comparator nameComparator = (h1, h2) -> h1.getName().compareTo(h2.getName());
+
+ final List sortedHumans = humans.stream().sorted(nameComparator).collect(Collectors.toList());
+ Assert.assertThat(sortedHumans.get(0), equalTo(new Human("Jack", 12)));
+ }
}
diff --git a/core-java-collections/README.md b/core-java-collections/README.md
index ca275d7c09..d9d768961c 100644
--- a/core-java-collections/README.md
+++ b/core-java-collections/README.md
@@ -48,6 +48,7 @@
- [Thread Safe LIFO Data Structure Implementations](https://www.baeldung.com/java-lifo-thread-safe)
- [Collections.emptyList() vs. New List Instance](https://www.baeldung.com/java-collections-emptylist-new-list)
- [Initialize a HashMap in Java](https://www.baeldung.com/java-initialize-hashmap)
+- [Differences Between Collection.clear() and Collection.removeAll()](https://www.baeldung.com/java-collection-clear-vs-removeall)
- [Performance of contains() in a HashSet vs ArrayList](https://www.baeldung.com/java-hashset-arraylist-contains-performance)
- [Get the Key for a Value from a Java Map](https://www.baeldung.com/java-map-key-from-value)
- [Time Complexity of Java Collections](https://www.baeldung.com/java-collections-complexity)
diff --git a/core-java-collections/pom.xml b/core-java-collections/pom.xml
index d0c3c25beb..06b79fff22 100644
--- a/core-java-collections/pom.xml
+++ b/core-java-collections/pom.xml
@@ -68,6 +68,11 @@
commons-exec
1.3
+
+ one.util
+ streamex
+ 0.6.5
+
diff --git a/core-java-collections/src/main/java/com/baeldung/map/java_8/MergeMaps.java b/core-java-collections/src/main/java/com/baeldung/map/java_8/MergeMaps.java
new file mode 100644
index 0000000000..052cfb8bad
--- /dev/null
+++ b/core-java-collections/src/main/java/com/baeldung/map/java_8/MergeMaps.java
@@ -0,0 +1,105 @@
+package com.baeldung.map.java_8;
+
+import com.baeldung.sort.Employee;
+import one.util.streamex.EntryStream;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+public class MergeMaps {
+
+ private static Map map1 = new HashMap<>();
+ private static Map map2 = new HashMap<>();
+
+ public static void main(String[] args) {
+
+ initialize();
+
+ mergeFunction();
+
+ streamConcat();
+
+ streamOf();
+
+ streamEx();
+
+ streamMerge();
+ }
+
+ private static void streamMerge() {
+
+ Map map3 = map2.entrySet()
+ .stream()
+ .collect(
+ Collectors.toMap(
+ Map.Entry::getKey,
+ Map.Entry::getValue,
+ (v1, v2) -> new Employee(v1.getId(), v2.getName()),
+ () -> new HashMap<>(map1)
+ )
+ );
+
+ System.out.println(map3);
+ }
+
+ private static void streamEx() {
+ Map map3 = EntryStream.of(map1)
+ .append(EntryStream.of(map2))
+ .toMap((e1, e2) -> e1);
+
+ System.out.println(map3);
+
+ }
+
+ private static void streamOf() {
+ Map map3 = Stream.of(map1, map2)
+ .flatMap(map -> map.entrySet().stream())
+ .collect(
+ Collectors.toMap(
+ Map.Entry::getKey,
+ Map.Entry::getValue,
+ (v1, v2) -> new Employee(v1.getId(), v2.getName())
+ )
+ );
+
+ map3.entrySet().forEach(System.out::println);
+ }
+
+ private static void streamConcat() {
+ Map result = Stream.concat(map1.entrySet().stream(), map2.entrySet().stream()).collect(Collectors.toMap(
+ Map.Entry::getKey,
+ Map.Entry::getValue,
+ (value1, value2) -> new Employee(value2.getId(), value1.getName())
+ ));
+
+ result.entrySet().forEach(System.out::println);
+ }
+
+ private static void mergeFunction() {
+ Map map3 = new HashMap<>(map1);
+
+ map2.forEach(
+ (key, value) -> map3.merge(key, value, (v1, v2) ->
+ new Employee(v1.getId(), v2.getName()))
+ );
+
+ map3.entrySet().forEach(System.out::println);
+ }
+
+
+ private static void initialize() {
+ Employee employee1 = new Employee(1L, "Henry");
+ map1.put(employee1.getName(), employee1);
+ Employee employee2 = new Employee(22L, "Annie");
+ map1.put(employee2.getName(), employee2);
+ Employee employee3 = new Employee(8L, "John");
+ map1.put(employee3.getName(), employee3);
+
+ Employee employee4 = new Employee(2L, "George");
+ map2.put(employee4.getName(), employee4);
+ Employee employee5 = new Employee(3L, "Henry");
+ map2.put(employee5.getName(), employee5);
+ }
+
+}
diff --git a/core-java-collections/src/test/java/com/baeldung/java/map/KeyCheckTest.java b/core-java-collections/src/test/java/com/baeldung/java/map/KeyCheckTest.java
new file mode 100644
index 0000000000..024b2973d2
--- /dev/null
+++ b/core-java-collections/src/test/java/com/baeldung/java/map/KeyCheckTest.java
@@ -0,0 +1,44 @@
+package com.baeldung.java.map;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.collections4.MultiMap;
+import org.apache.commons.collections4.MultiMapUtils;
+import org.apache.commons.collections4.MultiValuedMap;
+import org.apache.commons.collections4.map.MultiValueMap;
+import org.apache.commons.collections4.multimap.ArrayListValuedHashMap;
+import org.apache.commons.collections4.multimap.HashSetValuedHashMap;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.ArrayListMultimap;
+import com.google.common.collect.LinkedHashMultimap;
+import com.google.common.collect.Multimap;
+import com.google.common.collect.TreeMultimap;
+
+
+public class KeyCheckTest {
+
+ @Test
+ public void whenKeyIsPresent_thenContainsKeyReturnsTrue() {
+ Map map = Collections.singletonMap("key", "value");
+
+ assertTrue(map.containsKey("key"));
+ assertFalse(map.containsKey("missing"));
+ }
+
+ @Test
+ public void whenKeyHasNullValue_thenGetStillWorks() {
+ Map map = Collections.singletonMap("nothing", null);
+
+ assertTrue(map.containsKey("nothing"));
+ assertNull(map.get("nothing"));
+ }
+}
\ No newline at end of file
diff --git a/core-java-io/src/main/java/com/baeldung/stream/OutputStreamExamples.java b/core-java-io/src/main/java/com/baeldung/stream/OutputStreamExamples.java
new file mode 100644
index 0000000000..c7168c5b26
--- /dev/null
+++ b/core-java-io/src/main/java/com/baeldung/stream/OutputStreamExamples.java
@@ -0,0 +1,48 @@
+package com.baeldung.stream;
+
+import java.io.BufferedOutputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+
+public class OutputStreamExamples {
+
+ public void fileOutputStreamByteSequence(String file, String data) throws IOException {
+ byte[] bytes = data.getBytes();
+ try (OutputStream out = new FileOutputStream(file)) {
+ out.write(bytes);
+ }
+ }
+
+ public void fileOutputStreamByteSubSequence(String file, String data) throws IOException {
+ byte[] bytes = data.getBytes();
+ try (OutputStream out = new FileOutputStream(file)) {
+ out.write(bytes, 6, 5);
+ }
+ }
+
+ public void fileOutputStreamByteSingle(String file, String data) throws IOException {
+ byte[] bytes = data.getBytes();
+ try (OutputStream out = new FileOutputStream(file)) {
+ out.write(bytes[6]);
+ }
+ }
+
+ public void bufferedOutputStream(String file, String... data) throws IOException {
+ try (BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(file))) {
+ for (String s : data) {
+ out.write(s.getBytes());
+ out.write(" ".getBytes());
+ }
+ }
+ }
+
+ public void outputStreamWriter(String file, String data) throws IOException {
+ try (OutputStream out = new FileOutputStream(file); Writer writer = new OutputStreamWriter(out, "UTF-8")) {
+ writer.write(data);
+ }
+ }
+
+}
diff --git a/core-java-io/src/test/java/com/baeldung/stream/OutputStreamExamplesTest.java b/core-java-io/src/test/java/com/baeldung/stream/OutputStreamExamplesTest.java
new file mode 100644
index 0000000000..4ae1ce9aa7
--- /dev/null
+++ b/core-java-io/src/test/java/com/baeldung/stream/OutputStreamExamplesTest.java
@@ -0,0 +1,76 @@
+package com.baeldung.stream;
+
+import static org.junit.Assert.assertTrue;
+
+import java.io.File;
+import java.io.IOException;
+
+import org.junit.Before;
+import org.junit.Test;
+
+public class OutputStreamExamplesTest {
+
+ StringBuilder filePath = new StringBuilder();
+
+ @Before
+ public void init() {
+ filePath.append("src");
+ filePath.append(File.separator);
+ filePath.append("test");
+ filePath.append(File.separator);
+ filePath.append("resources");
+ filePath.append(File.separator);
+ filePath.append("output_file.txt");
+ }
+
+ @Test
+ public void givenOutputStream_whenWriteSingleByteCalled_thenOutputCreated() throws IOException {
+
+ final File file = new File(filePath.toString());
+ OutputStreamExamples examples = new OutputStreamExamples();
+ examples.fileOutputStreamByteSingle(filePath.toString(), "Hello World!");
+ assertTrue(file.exists());
+ file.delete();
+ }
+
+ @Test
+ public void givenOutputStream_whenWriteByteSequenceCalled_thenOutputCreated() throws IOException {
+
+ final File file = new File(filePath.toString());
+ OutputStreamExamples examples = new OutputStreamExamples();
+ examples.fileOutputStreamByteSequence(filePath.toString(), "Hello World!");
+ assertTrue(file.exists());
+ file.delete();
+ }
+
+ @Test
+ public void givenOutputStream_whenWriteByteSubSequenceCalled_thenOutputCreated() throws IOException {
+
+ final File file = new File(filePath.toString());
+ OutputStreamExamples examples = new OutputStreamExamples();
+ examples.fileOutputStreamByteSubSequence(filePath.toString(), "Hello World!");
+ assertTrue(file.exists());
+ file.delete();
+ }
+
+ @Test
+ public void givenBufferedOutputStream_whenCalled_thenOutputCreated() throws IOException {
+
+ final File file = new File(filePath.toString());
+ OutputStreamExamples examples = new OutputStreamExamples();
+ examples.bufferedOutputStream(filePath.toString(), "Hello", "World!");
+ assertTrue(file.exists());
+ file.delete();
+ }
+
+ @Test
+ public void givenOutputStreamWriter_whenCalled_thenOutputCreated() throws IOException {
+
+ final File file = new File(filePath.toString());
+ OutputStreamExamples examples = new OutputStreamExamples();
+ examples.outputStreamWriter(filePath.toString(), "Hello World!");
+ assertTrue(file.exists());
+ file.delete();
+ }
+
+}
diff --git a/core-java/README.md b/core-java/README.md
index fbfcb1117c..a117d1843d 100644
--- a/core-java/README.md
+++ b/core-java/README.md
@@ -25,7 +25,6 @@
- [The Traveling Salesman Problem in Java](http://www.baeldung.com/java-simulated-annealing-for-traveling-salesman)
- [How to Create an Executable JAR with Maven](http://www.baeldung.com/executable-jar-with-maven)
- [How to Design a Genetic Algorithm in Java](http://www.baeldung.com/java-genetic-algorithm)
-- [Spring Security – Cache Control Headers](http://www.baeldung.com/spring-security-cache-control-headers)
- [Basic Introduction to JMX](http://www.baeldung.com/java-management-extensions)
- [AWS Lambda With Java](http://www.baeldung.com/java-aws-lambda)
- [Introduction to Nashorn](http://www.baeldung.com/java-nashorn)
@@ -37,7 +36,6 @@
- [Guide to sun.misc.Unsafe](http://www.baeldung.com/java-unsafe)
- [How to Perform a Simple HTTP Request in Java](http://www.baeldung.com/java-http-request)
- [Call Methods at Runtime Using Java Reflection](http://www.baeldung.com/java-method-reflection)
-- [Guide to UUID in JAVA](http://www.baeldung.com/guide-to-uuid-in-java)
- [How to Add a Single Element to a Stream](http://www.baeldung.com/java-stream-append-prepend)
- [Iterating Over Enum Values in Java](http://www.baeldung.com/java-enum-iteration)
- [Kotlin Java Interoperability](http://www.baeldung.com/kotlin-java-interoperability)
diff --git a/core-kotlin/src/test/kotlin/com/baeldung/kotlin/StructuralJumpUnitTest.kt b/core-kotlin/src/test/kotlin/com/baeldung/kotlin/StructuralJumpUnitTest.kt
new file mode 100644
index 0000000000..436dc9e2ba
--- /dev/null
+++ b/core-kotlin/src/test/kotlin/com/baeldung/kotlin/StructuralJumpUnitTest.kt
@@ -0,0 +1,121 @@
+package com.baeldung.kotlin
+
+import org.junit.Test
+import kotlin.test.assertEquals
+import kotlin.test.assertFalse
+
+class StructuralJumpUnitTest {
+
+ @Test
+ fun givenLoop_whenBreak_thenComplete() {
+ var value = ""
+ for (i in "hello_world") {
+ if (i == '_')
+ break
+ value += i.toString()
+ }
+ assertEquals("hello", value)
+ }
+ @Test
+ fun givenLoop_whenBreakWithLabel_thenComplete() {
+ var value = ""
+ outer_loop@ for (i in 'a'..'d') {
+ for (j in 1..3) {
+ value += "" + i + j
+ if (i == 'b' && j == 1)
+ break@outer_loop
+ }
+ }
+ assertEquals("a1a2a3b1", value)
+ }
+
+ @Test
+ fun givenLoop_whenContinue_thenComplete() {
+ var result = ""
+ for (i in "hello_world") {
+ if (i == '_')
+ continue
+ result += i
+ }
+ assertEquals("helloworld", result)
+ }
+ @Test
+ fun givenLoop_whenContinueWithLabel_thenComplete() {
+ var result = ""
+ outer_loop@ for (i in 'a'..'c') {
+ for (j in 1..3) {
+ if (i == 'b')
+ continue@outer_loop
+ result += "" + i + j
+ }
+ }
+ assertEquals("a1a2a3c1c2c3", result)
+ }
+
+ @Test
+ fun givenLambda_whenReturn_thenComplete() {
+ var result = returnInLambda();
+ assertEquals("hello", result)
+ }
+
+ private fun returnInLambda(): String {
+ var result = ""
+ "hello_world".forEach {
+ // non-local return directly to the caller
+ if (it == '_') return result
+ result += it.toString()
+ }
+ //this line won't be reached
+ return result;
+ }
+
+ @Test
+ fun givenLambda_whenReturnWithExplicitLabel_thenComplete() {
+ var result = ""
+ "hello_world".forEach lit@{
+ if (it == '_') {
+ // local return to the caller of the lambda, i.e. the forEach loop
+ return@lit
+ }
+ result += it.toString()
+ }
+ assertEquals("helloworld", result)
+ }
+
+ @Test
+ fun givenLambda_whenReturnWithImplicitLabel_thenComplete() {
+ var result = ""
+ "hello_world".forEach {
+ if (it == '_') {
+ // local return to the caller of the lambda, i.e. the forEach loop
+ return@forEach
+ }
+ result += it.toString()
+ }
+ assertEquals("helloworld", result)
+ }
+
+ @Test
+ fun givenAnonymousFunction_return_thenComplete() {
+ var result = ""
+ "hello_world".forEach(fun(element) {
+ // local return to the caller of the anonymous fun, i.e. the forEach loop
+ if (element == '_') return
+ result += element.toString()
+ })
+ assertEquals("helloworld", result)
+ }
+
+ @Test
+ fun givenAnonymousFunction_returnToLabel_thenComplete() {
+ var result = ""
+ run loop@{
+ "hello_world".forEach {
+ // non-local return from the lambda passed to run
+ if (it == '_') return@loop
+ result += it.toString()
+ }
+ }
+ assertEquals("hello", result)
+ }
+}
diff --git a/hibernate5/README.md b/hibernate5/README.md
index b67ab7115f..b90f885c78 100644
--- a/hibernate5/README.md
+++ b/hibernate5/README.md
@@ -14,4 +14,5 @@
- [Bootstrapping JPA Programmatically in Java](http://www.baeldung.com/java-bootstrap-jpa)
- [Optimistic Locking in JPA](http://www.baeldung.com/jpa-optimistic-locking)
- [Hibernate Entity Lifecycle](https://www.baeldung.com/hibernate-entity-lifecycle)
+- [Mapping A Hibernate Query to a Custom Class](https://www.baeldung.com/hibernate-query-to-custom-class)
- [@JoinColumn Annotation Explained](https://www.baeldung.com/jpa-join-column)
diff --git a/hibernate5/src/main/java/com/baeldung/hibernate/namingstrategy/CustomPhysicalNamingStrategy.java b/hibernate5/src/main/java/com/baeldung/hibernate/namingstrategy/CustomPhysicalNamingStrategy.java
new file mode 100644
index 0000000000..74bcb9e411
--- /dev/null
+++ b/hibernate5/src/main/java/com/baeldung/hibernate/namingstrategy/CustomPhysicalNamingStrategy.java
@@ -0,0 +1,47 @@
+package com.baeldung.hibernate.namingstrategy;
+
+import org.hibernate.boot.model.naming.Identifier;
+import org.hibernate.boot.model.naming.PhysicalNamingStrategy;
+import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
+
+public class CustomPhysicalNamingStrategy implements PhysicalNamingStrategy {
+
+ @Override
+ public Identifier toPhysicalCatalogName(final Identifier identifier, final JdbcEnvironment jdbcEnv) {
+ return convertToSnakeCase(identifier);
+ }
+
+ @Override
+ public Identifier toPhysicalColumnName(final Identifier identifier, final JdbcEnvironment jdbcEnv) {
+ return convertToSnakeCase(identifier);
+ }
+
+ @Override
+ public Identifier toPhysicalSchemaName(final Identifier identifier, final JdbcEnvironment jdbcEnv) {
+ return convertToSnakeCase(identifier);
+ }
+
+ @Override
+ public Identifier toPhysicalSequenceName(final Identifier identifier, final JdbcEnvironment jdbcEnv) {
+ return convertToSnakeCase(identifier);
+ }
+
+ @Override
+ public Identifier toPhysicalTableName(final Identifier identifier, final JdbcEnvironment jdbcEnv) {
+ return convertToSnakeCase(identifier);
+ }
+
+ private Identifier convertToSnakeCase(final Identifier identifier) {
+ if (identifier == null) {
+ return identifier;
+ }
+
+ final String regex = "([a-z])([A-Z])";
+ final String replacement = "$1_$2";
+ final String newName = identifier.getText()
+ .replaceAll(regex, replacement)
+ .toLowerCase();
+ return Identifier.toIdentifier(newName);
+ }
+
+}
diff --git a/hibernate5/src/main/java/com/baeldung/hibernate/namingstrategy/Customer.java b/hibernate5/src/main/java/com/baeldung/hibernate/namingstrategy/Customer.java
new file mode 100644
index 0000000000..b3fb3b32b6
--- /dev/null
+++ b/hibernate5/src/main/java/com/baeldung/hibernate/namingstrategy/Customer.java
@@ -0,0 +1,56 @@
+package com.baeldung.hibernate.namingstrategy;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+@Entity
+@Table(name = "Customers")
+public class Customer {
+
+ @Id
+ @GeneratedValue
+ private Long id;
+
+ private String firstName;
+
+ private String lastName;
+
+ @Column(name = "email")
+ private String emailAddress;
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public String getFirstName() {
+ return firstName;
+ }
+
+ public void setFirstName(String firstName) {
+ this.firstName = firstName;
+ }
+
+ public String getLastName() {
+ return lastName;
+ }
+
+ public void setLastName(String lastName) {
+ this.lastName = lastName;
+ }
+
+ public String getEmailAddress() {
+ return emailAddress;
+ }
+
+ public void setEmailAddress(String emailAddress) {
+ this.emailAddress = emailAddress;
+ }
+
+}
diff --git a/hibernate5/src/test/java/com/baeldung/hibernate/namingstrategy/NamingStrategyLiveTest.java b/hibernate5/src/test/java/com/baeldung/hibernate/namingstrategy/NamingStrategyLiveTest.java
new file mode 100644
index 0000000000..0d6aed3370
--- /dev/null
+++ b/hibernate5/src/test/java/com/baeldung/hibernate/namingstrategy/NamingStrategyLiveTest.java
@@ -0,0 +1,75 @@
+package com.baeldung.hibernate.namingstrategy;
+
+import static org.junit.Assert.fail;
+
+import java.io.IOException;
+import java.util.Properties;
+
+import org.hibernate.HibernateException;
+import org.hibernate.Session;
+import org.hibernate.SessionFactory;
+import org.hibernate.boot.MetadataSources;
+import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
+import org.hibernate.cfg.Configuration;
+import org.hibernate.service.ServiceRegistry;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+public class NamingStrategyLiveTest {
+
+ private Session session;
+
+ @Before
+ public void init() {
+ try {
+ Configuration configuration = new Configuration();
+
+ Properties properties = new Properties();
+ properties.load(Thread.currentThread()
+ .getContextClassLoader()
+ .getResourceAsStream("hibernate-namingstrategy.properties"));
+
+ configuration.setProperties(properties);
+
+ ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties())
+ .build();
+ MetadataSources metadataSources = new MetadataSources(serviceRegistry);
+ metadataSources.addAnnotatedClass(Customer.class);
+
+ SessionFactory factory = metadataSources.buildMetadata()
+ .buildSessionFactory();
+
+ session = factory.openSession();
+ } catch (HibernateException | IOException e) {
+ fail("Failed to initiate Hibernate Session [Exception:" + e.toString() + "]");
+ }
+ }
+
+ @After
+ public void close() {
+ if (session != null)
+ session.close();
+ }
+
+ @Test
+ public void testCustomPhysicalNamingStrategy() {
+
+ Customer customer = new Customer();
+ customer.setFirstName("first name");
+ customer.setLastName("last name");
+ customer.setEmailAddress("customer@example.com");
+
+ session.beginTransaction();
+
+ Long id = (Long) session.save(customer);
+
+ session.flush();
+ session.clear();
+
+ Object[] result = (Object[]) session.createNativeQuery("select c.first_name, c.last_name, c.email from customers c where c.id = :id")
+ .setParameter("id", id)
+ .getSingleResult();
+
+ }
+}
diff --git a/hibernate5/src/test/resources/hibernate-namingstrategy.properties b/hibernate5/src/test/resources/hibernate-namingstrategy.properties
new file mode 100644
index 0000000000..f75a35bdfe
--- /dev/null
+++ b/hibernate5/src/test/resources/hibernate-namingstrategy.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.dialect=org.hibernate.dialect.H2Dialect
+
+hibernate.show_sql=true
+hibernate.hbm2ddl.auto=create-drop
+
+hibernate.physical_naming_strategy=com.baeldung.hibernate.namingstrategy.CustomPhysicalNamingStrategy
+hibernate.implicit_naming_strategy=org.hibernate.boot.model.naming.ImplicitNamingStrategyJpaCompliantImpl
\ No newline at end of file
diff --git a/jackson/pom.xml b/jackson/pom.xml
index 9592e11961..e941ababc5 100644
--- a/jackson/pom.xml
+++ b/jackson/pom.xml
@@ -118,7 +118,7 @@
- 2.9.6
+ 2.9.7
3.8
2.10
diff --git a/jackson/src/main/java/com/baeldung/jackson/xmlToJson/Color.java b/jackson/src/main/java/com/baeldung/jackson/xmlToJson/Color.java
new file mode 100644
index 0000000000..19dabb30b0
--- /dev/null
+++ b/jackson/src/main/java/com/baeldung/jackson/xmlToJson/Color.java
@@ -0,0 +1,5 @@
+package com.baeldung.jackson.xmlToJson;
+
+public enum Color {
+ PINK, BLUE, YELLOW, RED;
+}
diff --git a/jackson/src/main/java/com/baeldung/jackson/xmlToJson/Flower.java b/jackson/src/main/java/com/baeldung/jackson/xmlToJson/Flower.java
new file mode 100644
index 0000000000..0b1ee1b16a
--- /dev/null
+++ b/jackson/src/main/java/com/baeldung/jackson/xmlToJson/Flower.java
@@ -0,0 +1,42 @@
+package com.baeldung.jackson.xmlToJson;
+
+public class Flower {
+
+ private String name;
+
+ private Color color;
+
+ private Integer petals;
+
+ public Flower() { }
+
+ public Flower(String name, Color color, Integer petals) {
+ this.name = name;
+ this.color = color;
+ this.petals = petals;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public Color getColor() {
+ return color;
+ }
+
+ public void setColor(Color color) {
+ this.color = color;
+ }
+
+ public Integer getPetals() {
+ return petals;
+ }
+
+ public void setPetals(Integer petals) {
+ this.petals = petals;
+ }
+}
diff --git a/jackson/src/test/java/com/baeldung/jackson/xmlToJson/XmlToJsonUnitTest.java b/jackson/src/test/java/com/baeldung/jackson/xmlToJson/XmlToJsonUnitTest.java
new file mode 100644
index 0000000000..295bb9d6e8
--- /dev/null
+++ b/jackson/src/test/java/com/baeldung/jackson/xmlToJson/XmlToJsonUnitTest.java
@@ -0,0 +1,56 @@
+package com.baeldung.jackson.xmlToJson;
+
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.dataformat.xml.XmlMapper;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+import java.io.IOException;
+
+public class XmlToJsonUnitTest {
+
+ @Test
+ public void givenAnXML_whenUseDataBidingToConvertToJSON_thenReturnDataOK() {
+ String flowerXML = "PoppyRED9";
+
+ try {
+ XmlMapper xmlMapper = new XmlMapper();
+ Flower poppy = xmlMapper.readValue(flowerXML, Flower.class);
+
+ assertEquals(poppy.getName(), "Poppy");
+ assertEquals(poppy.getColor(), Color.RED);
+ assertEquals(poppy.getPetals(), new Integer(9));
+
+ ObjectMapper mapper = new ObjectMapper();
+ String json = mapper.writeValueAsString(poppy);
+
+ assertEquals(json, "{\"name\":\"Poppy\",\"color\":\"RED\",\"petals\":9}");
+ System.out.println(json);
+ } catch(IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Test
+ public void givenAnXML_whenUseATreeConvertToJSON_thenReturnDataOK() {
+ String flowerXML = "PoppyRED9";
+
+ try {
+ XmlMapper xmlMapper = new XmlMapper();
+ JsonNode node = xmlMapper.readTree(flowerXML.getBytes());
+
+ ObjectMapper jsonMapper = new ObjectMapper();
+ String json = jsonMapper.writeValueAsString(node);
+
+ System.out.println(json);
+
+ assertEquals(json, "{\"name\":\"Poppy\",\"color\":\"RED\",\"petals\":\"9\"}");
+ } catch(IOException e) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/java-numbers/src/test/java/com/baeldung/maths/MathSinUnitTest.java b/java-numbers/src/test/java/com/baeldung/maths/MathSinUnitTest.java
new file mode 100644
index 0000000000..111b2f4465
--- /dev/null
+++ b/java-numbers/src/test/java/com/baeldung/maths/MathSinUnitTest.java
@@ -0,0 +1,20 @@
+package com.baeldung.maths;
+
+import static org.junit.Assert.assertTrue;
+
+import org.junit.jupiter.api.Test;
+
+public class MathSinUnitTest {
+
+ @Test
+ public void givenAnAngleInDegrees_whenUsingToRadians_thenResultIsInRadians() {
+ double angleInDegrees = 30;
+ double sinForDegrees = Math.sin(Math.toRadians(angleInDegrees)); // 0.5
+
+ double thirtyDegreesInRadians = 1/6 * Math.PI;
+ double sinForRadians = Math.sin(thirtyDegreesInRadians); // 0.5
+
+ assertTrue(sinForDegrees == sinForRadians);
+ }
+
+}
diff --git a/java-strings/README.md b/java-strings/README.md
index 7d8ec16bcc..8bb07be221 100644
--- a/java-strings/README.md
+++ b/java-strings/README.md
@@ -28,6 +28,7 @@
- [Java Check a String for Lowercase/Uppercase Letter, Special Character and Digit](https://www.baeldung.com/java-lowercase-uppercase-special-character-digit-regex)
- [Convert java.util.Date to String](https://www.baeldung.com/java-util-date-to-string)
- [String Not Empty Test Assertions in Java](https://www.baeldung.com/java-assert-string-not-empty)
+- [Get Substring from String in Java](https://www.baeldung.com/java-substring)
- [Converting a Stack Trace to a String in Java](https://www.baeldung.com/java-stacktrace-to-string)
- [Sorting a String Alphabetically in Java](https://www.baeldung.com/java-sort-string-alphabetically)
- [Remove Emojis from a Java String](https://www.baeldung.com/java-string-remove-emojis)
diff --git a/jersey/README.md b/jersey/README.md
index 1a7b541e92..c548a79c6d 100644
--- a/jersey/README.md
+++ b/jersey/README.md
@@ -1,3 +1,4 @@
- [Jersey Filters and Interceptors](http://www.baeldung.com/jersey-filters-interceptors)
- [Jersey MVC Support](https://www.baeldung.com/jersey-mvc)
+- [Bean Validation in Jersey](https://www.baeldung.com/jersey-bean-validation)
- [Set a Response Body in JAX-RS](https://www.baeldung.com/jax-rs-response)
diff --git a/libraries-data/README.md b/libraries-data/README.md
index 652ae0e04c..63ee5f9947 100644
--- a/libraries-data/README.md
+++ b/libraries-data/README.md
@@ -11,3 +11,4 @@
- [Apache Ignite with Spring Data](http://www.baeldung.com/apache-ignite-spring-data)
- [Guide to JMapper](https://www.baeldung.com/jmapper)
- [A Guide to Apache Crunch](https://www.baeldung.com/apache-crunch)
+- [Building a Data Pipeline with Flink and Kafka](https://www.baeldung.com/kafka-flink-data-pipeline)
diff --git a/maven-polyglot/README.md b/maven-polyglot/README.md
new file mode 100644
index 0000000000..589315efd1
--- /dev/null
+++ b/maven-polyglot/README.md
@@ -0,0 +1,3 @@
+To run the maven-polyglot-json-app successfully, you first have to build the maven-polyglot-json-extension module using: mvn clean install.
+
+Related Articles:
diff --git a/maven-polyglot/maven-polyglot-json-app/.mvn/extensions.xml b/maven-polyglot/maven-polyglot-json-app/.mvn/extensions.xml
new file mode 100644
index 0000000000..c06b76e1b2
--- /dev/null
+++ b/maven-polyglot/maven-polyglot-json-app/.mvn/extensions.xml
@@ -0,0 +1,8 @@
+
+
+
+ com.baeldung.maven.polyglot
+ maven-polyglot-json-extension
+ 1.0-SNAPSHOT
+
+
\ No newline at end of file
diff --git a/maven-polyglot/maven-polyglot-json-app/pom.json b/maven-polyglot/maven-polyglot-json-app/pom.json
new file mode 100644
index 0000000000..abd58f3127
--- /dev/null
+++ b/maven-polyglot/maven-polyglot-json-app/pom.json
@@ -0,0 +1,34 @@
+{
+ "modelVersion": "4.0.0",
+ "groupId": "com.baeldung.maven.polyglot",
+ "artifactId": "maven-polyglot-json-app",
+ "version": "1.0-SNAPSHOT",
+ "name": "Json Maven Polyglot",
+ "parent": {
+ "groupId": "org.springframework.boot",
+ "artifactId": "spring-boot-starter-parent",
+ "version": "2.0.5.RELEASE",
+ "relativePath": null
+ },
+ "properties": {
+ "project.build.sourceEncoding": "UTF-8",
+ "project.reporting.outputEncoding": "UTF-8",
+ "maven.compiler.source": "1.8",
+ "maven.compiler.target": "1.8",
+ "java.version": "1.8"
+ },
+ "dependencies": [
+ {
+ "groupId": "org.springframework.boot",
+ "artifactId": "spring-boot-starter-web"
+ }
+ ],
+ "build": {
+ "plugins": [
+ {
+ "groupId": "org.springframework.boot",
+ "artifactId": "spring-boot-maven-plugin"
+ }
+ ]
+ }
+}
\ No newline at end of file
diff --git a/maven-polyglot/maven-polyglot-json-app/src/main/java/com/baeldung/maven/polyglot/MavenPolyglotApplication.java b/maven-polyglot/maven-polyglot-json-app/src/main/java/com/baeldung/maven/polyglot/MavenPolyglotApplication.java
new file mode 100644
index 0000000000..d03116889f
--- /dev/null
+++ b/maven-polyglot/maven-polyglot-json-app/src/main/java/com/baeldung/maven/polyglot/MavenPolyglotApplication.java
@@ -0,0 +1,19 @@
+package com.baeldung.maven.polyglot;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.bind.annotation.GetMapping;
+
+@RestController
+@SpringBootApplication
+public class MavenPolyglotApplication {
+ public static void main(String[] args) {
+ SpringApplication.run(MavenPolyglotApplication.class, args);
+ }
+
+ @GetMapping("/")
+ public String home(){
+ return "Hello JSON Maven Model !";
+ }
+}
diff --git a/maven-polyglot/maven-polyglot-json-app/src/main/resources/model.json b/maven-polyglot/maven-polyglot-json-app/src/main/resources/model.json
new file mode 100644
index 0000000000..f006582c12
--- /dev/null
+++ b/maven-polyglot/maven-polyglot-json-app/src/main/resources/model.json
@@ -0,0 +1,109 @@
+{
+ "modules": [],
+ "distributionManagement": null,
+ "properties": {
+ "project.reporting.outputEncoding": "UTF-8",
+ "java.version": "1.8",
+ "maven.compiler.source": "1.8",
+ "project.build.sourceEncoding": "UTF-8",
+ "maven.compiler.target": "1.8"
+ },
+ "dependencyManagement": null,
+ "dependencies": [
+ {
+ "groupId": "org.springframework.boot",
+ "artifactId": "spring-boot-starter-web",
+ "version": null,
+ "type": "jar",
+ "classifier": null,
+ "scope": null,
+ "systemPath": null,
+ "exclusions": [],
+ "optional": null,
+ "managementKey": "org.springframework.boot:spring-boot-starter-web:jar"
+ }
+ ],
+ "repositories": [],
+ "pluginRepositories": [],
+ "reports": null,
+ "reporting": null,
+ "modelVersion": "4.0.0",
+ "parent": {
+ "groupId": "org.springframework.boot",
+ "artifactId": "spring-boot-starter-parent",
+ "version": "2.0.5.RELEASE",
+ "relativePath": "",
+ "id": "org.springframework.boot:spring-boot-starter-parent:pom:2.0.5.RELEASE"
+ },
+ "groupId": "com.demo.polyglot",
+ "artifactId": "maven-polyglot-app",
+ "version": "1.0.1",
+ "packaging": "jar",
+ "name": "Json Maven Polyglot",
+ "description": null,
+ "url": null,
+ "inceptionYear": null,
+ "organization": null,
+ "licenses": [],
+ "developers": [],
+ "contributors": [],
+ "mailingLists": [],
+ "prerequisites": null,
+ "scm": null,
+ "issueManagement": null,
+ "ciManagement": null,
+ "build": {
+ "plugins": [
+ {
+ "inherited": null,
+ "configuration": null,
+ "inheritanceApplied": true,
+ "groupId": "org.liquibase",
+ "artifactId": "liquibase-maven-plugin",
+ "version": "3.0.5",
+ "extensions": null,
+ "executions": [],
+ "dependencies": [],
+ "goals": null,
+ "key": "org.liquibase:liquibase-maven-plugin",
+ "id": "org.liquibase:liquibase-maven-plugin:3.0.5",
+ "executionsAsMap": {}
+ }
+ ],
+ "pluginManagement": null,
+ "defaultGoal": null,
+ "resources": [],
+ "testResources": [],
+ "directory": null,
+ "finalName": null,
+ "filters": [],
+ "sourceDirectory": null,
+ "scriptSourceDirectory": null,
+ "testSourceDirectory": null,
+ "outputDirectory": null,
+ "testOutputDirectory": null,
+ "extensions": [],
+ "pluginsAsMap": {
+ "org.liquibase:liquibase-maven-plugin": {
+ "inherited": null,
+ "configuration": null,
+ "inheritanceApplied": true,
+ "groupId": "org.liquibase",
+ "artifactId": "liquibase-maven-plugin",
+ "version": "3.0.5",
+ "extensions": null,
+ "executions": [],
+ "dependencies": [],
+ "goals": null,
+ "key": "org.liquibase:liquibase-maven-plugin",
+ "id": "org.liquibase:liquibase-maven-plugin:3.0.5",
+ "executionsAsMap": {}
+ }
+ }
+ },
+ "profiles": [],
+ "modelEncoding": "UTF-8",
+ "pomFile": null,
+ "id": "com.demo.polyglot:maven-polyglot-app:jar:1.0.1",
+ "projectDirectory": null
+}
diff --git a/maven-polyglot/maven-polyglot-json-extension/pom.xml b/maven-polyglot/maven-polyglot-json-extension/pom.xml
new file mode 100644
index 0000000000..d5c5b7ab55
--- /dev/null
+++ b/maven-polyglot/maven-polyglot-json-extension/pom.xml
@@ -0,0 +1,47 @@
+
+
+ 4.0.0
+
+ com.baeldung.maven.polyglot
+ maven-polyglot-json-extension
+ 1.0-SNAPSHOT
+
+
+ 1.8
+ 1.8
+
+
+
+
+ org.apache.maven
+ maven-core
+ 3.5.4
+ provided
+
+
+ com.fasterxml.jackson.core
+ jackson-databind
+ 2.9.6
+
+
+
+
+
+
+ org.codehaus.plexus
+ plexus-component-metadata
+ 1.7.1
+
+
+
+ generate-metadata
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/maven-polyglot/maven-polyglot-json-extension/src/main/java/com/demo/polyglot/CustomModelProcessor.java b/maven-polyglot/maven-polyglot-json-extension/src/main/java/com/demo/polyglot/CustomModelProcessor.java
new file mode 100644
index 0000000000..a1756192e9
--- /dev/null
+++ b/maven-polyglot/maven-polyglot-json-extension/src/main/java/com/demo/polyglot/CustomModelProcessor.java
@@ -0,0 +1,62 @@
+package com.demo.polyglot;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.apache.maven.model.Model;
+import org.apache.maven.model.building.FileModelSource;
+import org.apache.maven.model.building.ModelProcessor;
+import org.apache.maven.model.io.ModelParseException;
+import org.apache.maven.model.io.ModelReader;
+import org.codehaus.plexus.component.annotations.Component;
+import org.codehaus.plexus.component.annotations.Requirement;
+import org.codehaus.plexus.util.ReaderFactory;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+import java.util.Map;
+
+@Component(role = ModelProcessor.class)
+public class CustomModelProcessor implements ModelProcessor {
+
+ private static final String XML_POM = "pom.xml";
+ private static final String JSON_POM = "pom.json";
+ private static final String JSON_EXT = ".json";
+
+ ObjectMapper objectMapper = new ObjectMapper();
+
+ @Requirement
+ private ModelReader modelReader;
+
+ @Override
+ public File locatePom(File projectDirectory) {
+ File pomFile = new File(projectDirectory, JSON_POM);
+ if (!pomFile.exists()) {
+ pomFile = new File(projectDirectory, XML_POM);
+ }
+ return pomFile;
+ }
+
+ @Override
+ public Model read(InputStream input, Map options) throws IOException, ModelParseException {
+ try (final Reader in = ReaderFactory.newPlatformReader(input)) {
+ return read(in, options);
+ }
+ }
+
+ @Override
+ public Model read(Reader reader, Map options) throws IOException, ModelParseException {
+ FileModelSource source = (options != null) ? (FileModelSource) options.get(SOURCE) : null;
+ if (source != null && source.getLocation().endsWith(JSON_EXT)) {
+ Model model = objectMapper.readValue(reader, Model.class);
+ return model;
+ }
+ //It's a normal maven project with a pom.xml file
+ return modelReader.read(reader, options);
+ }
+
+ @Override
+ public Model read(File input, Map options) throws IOException, ModelParseException {
+ return null;
+ }
+}
\ No newline at end of file
diff --git a/maven-polyglot/maven-polyglot-yml-app/.mvn/extensions.xml b/maven-polyglot/maven-polyglot-yml-app/.mvn/extensions.xml
new file mode 100644
index 0000000000..cfc6275681
--- /dev/null
+++ b/maven-polyglot/maven-polyglot-yml-app/.mvn/extensions.xml
@@ -0,0 +1,8 @@
+
+
+
+ io.takari.polyglot
+ polyglot-yaml
+ 0.3.1
+
+
\ No newline at end of file
diff --git a/maven-polyglot/maven-polyglot-yml-app/pom.yml b/maven-polyglot/maven-polyglot-yml-app/pom.yml
new file mode 100644
index 0000000000..445e2eec3b
--- /dev/null
+++ b/maven-polyglot/maven-polyglot-yml-app/pom.yml
@@ -0,0 +1,7 @@
+modelVersion: 4.0.0
+groupId: com.baeldung.maven.polyglot
+artifactId: maven-polyglot-yml-app
+version: 1.0-SNAPSHOT
+name: 'YAML Demo'
+
+properties: {maven.compiler.source: 1.8, maven.compiler.target: 1.8}
\ No newline at end of file
diff --git a/maven-polyglot/maven-polyglot-yml-app/src/main/java/com/baeldung/maven/polyglot/YamlDemoApplication.java b/maven-polyglot/maven-polyglot-yml-app/src/main/java/com/baeldung/maven/polyglot/YamlDemoApplication.java
new file mode 100644
index 0000000000..2142c7f9b8
--- /dev/null
+++ b/maven-polyglot/maven-polyglot-yml-app/src/main/java/com/baeldung/maven/polyglot/YamlDemoApplication.java
@@ -0,0 +1,7 @@
+package com.baeldung.maven.polyglot;
+
+public class YamlDemoApplication {
+ public static void main(String[] args) {
+ System.out.println("Hello Maven Polyglot YAML !");
+ }
+}
diff --git a/maven-polyglot/maven-polyglot-yml-app/src/main/resources/model.json b/maven-polyglot/maven-polyglot-yml-app/src/main/resources/model.json
new file mode 100644
index 0000000000..f006582c12
--- /dev/null
+++ b/maven-polyglot/maven-polyglot-yml-app/src/main/resources/model.json
@@ -0,0 +1,109 @@
+{
+ "modules": [],
+ "distributionManagement": null,
+ "properties": {
+ "project.reporting.outputEncoding": "UTF-8",
+ "java.version": "1.8",
+ "maven.compiler.source": "1.8",
+ "project.build.sourceEncoding": "UTF-8",
+ "maven.compiler.target": "1.8"
+ },
+ "dependencyManagement": null,
+ "dependencies": [
+ {
+ "groupId": "org.springframework.boot",
+ "artifactId": "spring-boot-starter-web",
+ "version": null,
+ "type": "jar",
+ "classifier": null,
+ "scope": null,
+ "systemPath": null,
+ "exclusions": [],
+ "optional": null,
+ "managementKey": "org.springframework.boot:spring-boot-starter-web:jar"
+ }
+ ],
+ "repositories": [],
+ "pluginRepositories": [],
+ "reports": null,
+ "reporting": null,
+ "modelVersion": "4.0.0",
+ "parent": {
+ "groupId": "org.springframework.boot",
+ "artifactId": "spring-boot-starter-parent",
+ "version": "2.0.5.RELEASE",
+ "relativePath": "",
+ "id": "org.springframework.boot:spring-boot-starter-parent:pom:2.0.5.RELEASE"
+ },
+ "groupId": "com.demo.polyglot",
+ "artifactId": "maven-polyglot-app",
+ "version": "1.0.1",
+ "packaging": "jar",
+ "name": "Json Maven Polyglot",
+ "description": null,
+ "url": null,
+ "inceptionYear": null,
+ "organization": null,
+ "licenses": [],
+ "developers": [],
+ "contributors": [],
+ "mailingLists": [],
+ "prerequisites": null,
+ "scm": null,
+ "issueManagement": null,
+ "ciManagement": null,
+ "build": {
+ "plugins": [
+ {
+ "inherited": null,
+ "configuration": null,
+ "inheritanceApplied": true,
+ "groupId": "org.liquibase",
+ "artifactId": "liquibase-maven-plugin",
+ "version": "3.0.5",
+ "extensions": null,
+ "executions": [],
+ "dependencies": [],
+ "goals": null,
+ "key": "org.liquibase:liquibase-maven-plugin",
+ "id": "org.liquibase:liquibase-maven-plugin:3.0.5",
+ "executionsAsMap": {}
+ }
+ ],
+ "pluginManagement": null,
+ "defaultGoal": null,
+ "resources": [],
+ "testResources": [],
+ "directory": null,
+ "finalName": null,
+ "filters": [],
+ "sourceDirectory": null,
+ "scriptSourceDirectory": null,
+ "testSourceDirectory": null,
+ "outputDirectory": null,
+ "testOutputDirectory": null,
+ "extensions": [],
+ "pluginsAsMap": {
+ "org.liquibase:liquibase-maven-plugin": {
+ "inherited": null,
+ "configuration": null,
+ "inheritanceApplied": true,
+ "groupId": "org.liquibase",
+ "artifactId": "liquibase-maven-plugin",
+ "version": "3.0.5",
+ "extensions": null,
+ "executions": [],
+ "dependencies": [],
+ "goals": null,
+ "key": "org.liquibase:liquibase-maven-plugin",
+ "id": "org.liquibase:liquibase-maven-plugin:3.0.5",
+ "executionsAsMap": {}
+ }
+ }
+ },
+ "profiles": [],
+ "modelEncoding": "UTF-8",
+ "pomFile": null,
+ "id": "com.demo.polyglot:maven-polyglot-app:jar:1.0.1",
+ "projectDirectory": null
+}
diff --git a/pom.xml b/pom.xml
index ef34881cef..a499aac7ee 100644
--- a/pom.xml
+++ b/pom.xml
@@ -551,18 +551,6 @@
spring-security-rest
spring-security-sso
spring-security-x509
- spring-session
- spring-sleuth
- spring-social-login
- spring-spel
- spring-state-machine
- spring-thymeleaf
- spring-userservice
- spring-zuul
- spring-remoting
- spring-reactor
- spring-vertx
- spring-jinq
@@ -601,6 +589,18 @@
parent-java
parent-kotlin
+ spring-session
+ spring-sleuth
+ spring-social-login
+ spring-spel
+ spring-state-machine
+ spring-thymeleaf
+ spring-userservice
+ spring-zuul
+ spring-remoting
+ spring-reactor
+ spring-vertx
+ spring-jinq
spring-rest-embedded-tomcat
testing-modules/testing
testing-modules/testng
diff --git a/spring-cloud-data-flow/etl/README.MD b/spring-cloud-data-flow/etl/README.MD
new file mode 100644
index 0000000000..0cbb460b01
--- /dev/null
+++ b/spring-cloud-data-flow/etl/README.MD
@@ -0,0 +1,9 @@
+# Overview
+This is an example of a ETL stream pipeline, mixing a starter application with custom transform and sink.
+
+# Applications
+JDBC Source - Application Starter distributed by default
+
+customer-transform - Custom application to transform the data
+
+customer-mongodb-sink - Custom application to sink the data
diff --git a/spring-cloud-data-flow/etl/customer-mongodb-sink/pom.xml b/spring-cloud-data-flow/etl/customer-mongodb-sink/pom.xml
new file mode 100644
index 0000000000..468d8e17d0
--- /dev/null
+++ b/spring-cloud-data-flow/etl/customer-mongodb-sink/pom.xml
@@ -0,0 +1,75 @@
+
+
+ 4.0.0
+
+ com.customer
+ customer-mongodb-sink
+ jar
+
+ customer-mongodb-sink
+ Example ETL Load Project
+
+
+ parent-boot-2
+ com.baeldung
+ 0.0.1-SNAPSHOT
+ ../../../parent-boot-2
+
+
+
+ UTF-8
+ UTF-8
+ 1.8
+ Finchley.SR1
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-stream
+
+
+ org.springframework.cloud
+ spring-cloud-stream-binder-rabbit
+
+
+ org.springframework.boot
+ spring-boot-starter-data-mongodb
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+ org.springframework.cloud
+ spring-cloud-stream-test-support
+ test
+
+
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-dependencies
+ ${spring-cloud.version}
+ pom
+ import
+
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
+
diff --git a/spring-cloud-data-flow/etl/customer-mongodb-sink/src/main/java/com/customer/customermongodbsink/Customer.java b/spring-cloud-data-flow/etl/customer-mongodb-sink/src/main/java/com/customer/customermongodbsink/Customer.java
new file mode 100644
index 0000000000..cf44aec5b7
--- /dev/null
+++ b/spring-cloud-data-flow/etl/customer-mongodb-sink/src/main/java/com/customer/customermongodbsink/Customer.java
@@ -0,0 +1,27 @@
+package com.customer.customermongodbsink;
+
+import org.springframework.data.mongodb.core.mapping.Document;
+
+@Document(collection = "customer")
+public class Customer {
+
+ private Long id;
+ private String name;
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+}
\ No newline at end of file
diff --git a/spring-cloud-data-flow/etl/customer-mongodb-sink/src/main/java/com/customer/customermongodbsink/CustomerListener.java b/spring-cloud-data-flow/etl/customer-mongodb-sink/src/main/java/com/customer/customermongodbsink/CustomerListener.java
new file mode 100644
index 0000000000..c841daea8a
--- /dev/null
+++ b/spring-cloud-data-flow/etl/customer-mongodb-sink/src/main/java/com/customer/customermongodbsink/CustomerListener.java
@@ -0,0 +1,18 @@
+package com.customer.customermongodbsink;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.cloud.stream.annotation.EnableBinding;
+import org.springframework.cloud.stream.annotation.StreamListener;
+import org.springframework.cloud.stream.messaging.Sink;
+
+@EnableBinding(Sink.class)
+public class CustomerListener {
+
+ @Autowired
+ private CustomerRepository repository;
+
+ @StreamListener(Sink.INPUT)
+ public void save(Customer customer) {
+ repository.save(customer);
+ }
+}
diff --git a/spring-cloud-data-flow/etl/customer-mongodb-sink/src/main/java/com/customer/customermongodbsink/CustomerMongodbSinkApplication.java b/spring-cloud-data-flow/etl/customer-mongodb-sink/src/main/java/com/customer/customermongodbsink/CustomerMongodbSinkApplication.java
new file mode 100644
index 0000000000..2ef311457e
--- /dev/null
+++ b/spring-cloud-data-flow/etl/customer-mongodb-sink/src/main/java/com/customer/customermongodbsink/CustomerMongodbSinkApplication.java
@@ -0,0 +1,12 @@
+package com.customer.customermongodbsink;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class CustomerMongodbSinkApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(CustomerMongodbSinkApplication.class, args);
+ }
+}
diff --git a/spring-cloud-data-flow/etl/customer-mongodb-sink/src/main/java/com/customer/customermongodbsink/CustomerRepository.java b/spring-cloud-data-flow/etl/customer-mongodb-sink/src/main/java/com/customer/customermongodbsink/CustomerRepository.java
new file mode 100644
index 0000000000..f921ff51cf
--- /dev/null
+++ b/spring-cloud-data-flow/etl/customer-mongodb-sink/src/main/java/com/customer/customermongodbsink/CustomerRepository.java
@@ -0,0 +1,9 @@
+package com.customer.customermongodbsink;
+
+import org.springframework.data.mongodb.repository.MongoRepository;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface CustomerRepository extends MongoRepository {
+
+}
\ No newline at end of file
diff --git a/spring-cloud-data-flow/etl/customer-mongodb-sink/src/main/resources/application.properties b/spring-cloud-data-flow/etl/customer-mongodb-sink/src/main/resources/application.properties
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/spring-cloud-data-flow/etl/customer-transform/pom.xml b/spring-cloud-data-flow/etl/customer-transform/pom.xml
new file mode 100644
index 0000000000..bc4b648907
--- /dev/null
+++ b/spring-cloud-data-flow/etl/customer-transform/pom.xml
@@ -0,0 +1,68 @@
+
+
+ 4.0.0
+
+ com.customer
+ customer-transform
+ 0.0.1-SNAPSHOT
+ jar
+
+ customer-transform
+ Example transform ETL step
+
+
+ parent-boot-2
+ com.baeldung
+ 0.0.1-SNAPSHOT
+ ../../../parent-boot-2
+
+
+
+ UTF-8
+ UTF-8
+ 1.8
+ Finchley.SR1
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-stream-binder-rabbit
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+ org.springframework.cloud
+ spring-cloud-stream-test-support
+ test
+
+
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-dependencies
+ ${spring-cloud.version}
+ pom
+ import
+
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
+
diff --git a/spring-cloud-data-flow/etl/customer-transform/src/main/java/com/customer/customertransform/Customer.java b/spring-cloud-data-flow/etl/customer-transform/src/main/java/com/customer/customertransform/Customer.java
new file mode 100644
index 0000000000..f0e4d79388
--- /dev/null
+++ b/spring-cloud-data-flow/etl/customer-transform/src/main/java/com/customer/customertransform/Customer.java
@@ -0,0 +1,29 @@
+package com.customer.customertransform;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public class Customer {
+
+ private Long id;
+
+ private String name;
+
+ @JsonProperty("customer_name")
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ @JsonProperty("name")
+ public String getName() {
+ return name;
+ }
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+}
\ No newline at end of file
diff --git a/spring-cloud-data-flow/etl/customer-transform/src/main/java/com/customer/customertransform/CustomerProcessorConfiguration.java b/spring-cloud-data-flow/etl/customer-transform/src/main/java/com/customer/customertransform/CustomerProcessorConfiguration.java
new file mode 100644
index 0000000000..c99fcf55be
--- /dev/null
+++ b/spring-cloud-data-flow/etl/customer-transform/src/main/java/com/customer/customertransform/CustomerProcessorConfiguration.java
@@ -0,0 +1,16 @@
+package com.customer.customertransform;
+
+
+import org.springframework.cloud.stream.annotation.EnableBinding;
+import org.springframework.cloud.stream.messaging.Processor;
+import org.springframework.integration.annotation.Transformer;
+
+@EnableBinding(Processor.class)
+public class CustomerProcessorConfiguration {
+
+ @Transformer(inputChannel = Processor.INPUT, outputChannel = Processor.OUTPUT)
+ public Customer convertToPojo(Customer payload) {
+
+ return payload;
+ }
+}
\ No newline at end of file
diff --git a/spring-cloud-data-flow/etl/customer-transform/src/main/java/com/customer/customertransform/CustomerTransformApplication.java b/spring-cloud-data-flow/etl/customer-transform/src/main/java/com/customer/customertransform/CustomerTransformApplication.java
new file mode 100644
index 0000000000..8781f4da54
--- /dev/null
+++ b/spring-cloud-data-flow/etl/customer-transform/src/main/java/com/customer/customertransform/CustomerTransformApplication.java
@@ -0,0 +1,12 @@
+package com.customer.customertransform;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class CustomerTransformApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(CustomerTransformApplication.class, args);
+ }
+}
diff --git a/spring-cloud-data-flow/etl/customer-transform/src/main/resources/application.properties b/spring-cloud-data-flow/etl/customer-transform/src/main/resources/application.properties
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/spring-cloud-data-flow/etl/pom.xml b/spring-cloud-data-flow/etl/pom.xml
new file mode 100644
index 0000000000..2b904f6e0d
--- /dev/null
+++ b/spring-cloud-data-flow/etl/pom.xml
@@ -0,0 +1,20 @@
+
+ 4.0.0
+ org.baeldung.spring.cloud
+ etl-spring-cloud-data-flow
+ 0.0.1-SNAPSHOT
+ pom
+
+
+ org.baeldung.spring.cloud
+ spring-cloud-data-flow
+ 0.0.1-SNAPSHOT
+
+
+
+ customer-mongodb-sink
+ customer-transform
+
+
+
diff --git a/spring-cloud-data-flow/pom.xml b/spring-cloud-data-flow/pom.xml
index 5f24aa2cbd..5a007f3c7d 100644
--- a/spring-cloud-data-flow/pom.xml
+++ b/spring-cloud-data-flow/pom.xml
@@ -19,6 +19,7 @@
time-processor
log-sink
batch-job
+ etl
diff --git a/spring-data-mongodb/pom.xml b/spring-data-mongodb/pom.xml
index 332245adc8..ad70d987bb 100644
--- a/spring-data-mongodb/pom.xml
+++ b/spring-data-mongodb/pom.xml
@@ -8,9 +8,9 @@
com.baeldung
- parent-spring-4
+ parent-spring-5
0.0.1-SNAPSHOT
- ../parent-spring-4
+ ../parent-spring-5
@@ -19,6 +19,28 @@
spring-data-mongodb
${org.springframework.data.version}
+
+
+ org.springframework.data
+ spring-data-releasetrain
+ Lovelace-M3
+ pom
+ import
+
+
+
+ org.mongodb
+ mongodb-driver-reactivestreams
+ ${mongodb-reactivestreams.version}
+
+
+
+ io.projectreactor
+ reactor-test
+ ${projectreactor.version}
+ test
+
+
org.springframework
spring-core
@@ -48,6 +70,17 @@
+
+
+ spring-milestones
+ Spring Milestones
+ https://repo.spring.io/milestone
+
+ false
+
+
+
+
@@ -70,10 +103,12 @@
- 1.10.4.RELEASE
- 2.9.0
+ 2.1.0.RELEASE
4.1.4
1.1.3
+ 5.1.0.RELEASE
+ 1.9.2
+ 3.2.0.RELEASE
diff --git a/spring-data-mongodb/src/main/java/com/baeldung/config/MongoConfig.java b/spring-data-mongodb/src/main/java/com/baeldung/config/MongoConfig.java
index 551a9142a6..f1048fa145 100644
--- a/spring-data-mongodb/src/main/java/com/baeldung/config/MongoConfig.java
+++ b/spring-data-mongodb/src/main/java/com/baeldung/config/MongoConfig.java
@@ -1,21 +1,23 @@
package com.baeldung.config;
-import com.mongodb.Mongo;
-import com.mongodb.MongoClient;
-import com.baeldung.converter.UserWriterConverter;
-import com.baeldung.event.CascadeSaveMongoEventListener;
-import com.baeldung.event.UserCascadeSaveMongoEventListener;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.core.convert.converter.Converter;
-import org.springframework.data.mongodb.config.AbstractMongoConfiguration;
-import org.springframework.data.mongodb.core.convert.CustomConversions;
-import org.springframework.data.mongodb.gridfs.GridFsTemplate;
-import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;
-
import java.util.ArrayList;
import java.util.List;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.convert.converter.Converter;
+import org.springframework.data.mongodb.MongoDbFactory;
+import org.springframework.data.mongodb.MongoTransactionManager;
+import org.springframework.data.mongodb.config.AbstractMongoConfiguration;
+import org.springframework.data.mongodb.core.convert.MongoCustomConversions;
+import org.springframework.data.mongodb.gridfs.GridFsTemplate;
+import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;
+
+import com.baeldung.converter.UserWriterConverter;
+import com.baeldung.event.CascadeSaveMongoEventListener;
+import com.baeldung.event.UserCascadeSaveMongoEventListener;
+import com.mongodb.MongoClient;
+
@Configuration
@EnableMongoRepositories(basePackages = "com.baeldung.repository")
public class MongoConfig extends AbstractMongoConfiguration {
@@ -28,7 +30,7 @@ public class MongoConfig extends AbstractMongoConfiguration {
}
@Override
- public Mongo mongo() throws Exception {
+ public MongoClient mongoClient() {
return new MongoClient("127.0.0.1", 27017);
}
@@ -48,13 +50,19 @@ public class MongoConfig extends AbstractMongoConfiguration {
}
@Override
- public CustomConversions customConversions() {
+ public MongoCustomConversions customConversions() {
converters.add(new UserWriterConverter());
- return new CustomConversions(converters);
+ return new MongoCustomConversions(converters);
}
@Bean
public GridFsTemplate gridFsTemplate() throws Exception {
return new GridFsTemplate(mongoDbFactory(), mappingMongoConverter());
}
+
+ @Bean
+ MongoTransactionManager transactionManager(MongoDbFactory dbFactory) {
+ return new MongoTransactionManager(dbFactory);
+ }
+
}
diff --git a/spring-data-mongodb/src/main/java/com/baeldung/config/MongoReactiveConfig.java b/spring-data-mongodb/src/main/java/com/baeldung/config/MongoReactiveConfig.java
new file mode 100644
index 0000000000..b4042b5550
--- /dev/null
+++ b/spring-data-mongodb/src/main/java/com/baeldung/config/MongoReactiveConfig.java
@@ -0,0 +1,23 @@
+package com.baeldung.config;
+
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.mongodb.config.AbstractReactiveMongoConfiguration;
+import org.springframework.data.mongodb.repository.config.EnableReactiveMongoRepositories;
+
+import com.mongodb.reactivestreams.client.MongoClient;
+import com.mongodb.reactivestreams.client.MongoClients;
+
+@Configuration
+@EnableReactiveMongoRepositories(basePackages = "com.baeldung.reactive.repository")
+public class MongoReactiveConfig extends AbstractReactiveMongoConfiguration {
+
+ @Override
+ public MongoClient reactiveMongoClient() {
+ return MongoClients.create();
+ }
+
+ @Override
+ protected String getDatabaseName() {
+ return "reactive";
+ }
+}
diff --git a/spring-data-mongodb/src/main/java/com/baeldung/config/SimpleMongoConfig.java b/spring-data-mongodb/src/main/java/com/baeldung/config/SimpleMongoConfig.java
index 95f192811f..c3ddad5a82 100644
--- a/spring-data-mongodb/src/main/java/com/baeldung/config/SimpleMongoConfig.java
+++ b/spring-data-mongodb/src/main/java/com/baeldung/config/SimpleMongoConfig.java
@@ -1,18 +1,18 @@
package com.baeldung.config;
-import com.mongodb.Mongo;
-import com.mongodb.MongoClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;
+import com.mongodb.MongoClient;
+
@Configuration
@EnableMongoRepositories(basePackages = "com.baeldung.repository")
public class SimpleMongoConfig {
@Bean
- public Mongo mongo() throws Exception {
+ public MongoClient mongo() throws Exception {
return new MongoClient("localhost");
}
diff --git a/spring-data-mongodb/src/main/java/com/baeldung/reactive/repository/UserRepository.java b/spring-data-mongodb/src/main/java/com/baeldung/reactive/repository/UserRepository.java
new file mode 100644
index 0000000000..7e754aa680
--- /dev/null
+++ b/spring-data-mongodb/src/main/java/com/baeldung/reactive/repository/UserRepository.java
@@ -0,0 +1,9 @@
+package com.baeldung.reactive.repository;
+
+import org.springframework.data.mongodb.repository.ReactiveMongoRepository;
+
+import com.baeldung.model.User;
+
+
+public interface UserRepository extends ReactiveMongoRepository {
+}
diff --git a/spring-data-mongodb/src/main/java/com/baeldung/repository/UserRepository.java b/spring-data-mongodb/src/main/java/com/baeldung/repository/UserRepository.java
index e9dc0f5c95..4c69d7f9c6 100644
--- a/spring-data-mongodb/src/main/java/com/baeldung/repository/UserRepository.java
+++ b/spring-data-mongodb/src/main/java/com/baeldung/repository/UserRepository.java
@@ -1,13 +1,14 @@
package com.baeldung.repository;
-import com.baeldung.model.User;
-import org.springframework.data.mongodb.repository.MongoRepository;
-import org.springframework.data.mongodb.repository.Query;
-import org.springframework.data.querydsl.QueryDslPredicateExecutor;
-
import java.util.List;
-public interface UserRepository extends MongoRepository, QueryDslPredicateExecutor {
+import org.springframework.data.mongodb.repository.MongoRepository;
+import org.springframework.data.mongodb.repository.Query;
+import org.springframework.data.querydsl.QuerydslPredicateExecutor;
+
+import com.baeldung.model.User;
+
+public interface UserRepository extends MongoRepository, QuerydslPredicateExecutor {
@Query("{ 'name' : ?0 }")
List findUsersByName(String name);
diff --git a/spring-data-mongodb/src/main/resources/mongoConfig.xml b/spring-data-mongodb/src/main/resources/mongoConfig.xml
index 2b32863fb6..324f7f60c2 100644
--- a/spring-data-mongodb/src/main/resources/mongoConfig.xml
+++ b/spring-data-mongodb/src/main/resources/mongoConfig.xml
@@ -3,17 +3,17 @@
xmlns:p="http://www.springframework.org/schema/p" xmlns:mongo="http://www.springframework.org/schema/data/mongo"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
- http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
+ http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/data/mongo
- http://www.springframework.org/schema/data/mongo/spring-mongo-1.0.xsd
+ http://www.springframework.org/schema/data/mongo/spring-mongo.xsd
http://www.springframework.org/schema/context
- http://www.springframework.org/schema/context/spring-context-3.2.xsd"
+ http://www.springframework.org/schema/context/spring-context.xsd"
>
-
+
-
+
@@ -27,12 +27,12 @@
-
+
-
+
-
+
diff --git a/spring-data-mongodb/src/test/java/com/baeldung/aggregation/ZipsAggregationLiveTest.java b/spring-data-mongodb/src/test/java/com/baeldung/aggregation/ZipsAggregationLiveTest.java
index a4bea45fcf..1da50d7cb4 100644
--- a/spring-data-mongodb/src/test/java/com/baeldung/aggregation/ZipsAggregationLiveTest.java
+++ b/spring-data-mongodb/src/test/java/com/baeldung/aggregation/ZipsAggregationLiveTest.java
@@ -1,12 +1,24 @@
package com.baeldung.aggregation;
-import com.mongodb.DB;
-import com.mongodb.DBCollection;
-import com.mongodb.DBObject;
-import com.mongodb.MongoClient;
-import com.mongodb.util.JSON;
-import com.baeldung.aggregation.model.StatePopulation;
-import com.baeldung.config.MongoConfig;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.springframework.data.mongodb.core.aggregation.Aggregation.group;
+import static org.springframework.data.mongodb.core.aggregation.Aggregation.limit;
+import static org.springframework.data.mongodb.core.aggregation.Aggregation.match;
+import static org.springframework.data.mongodb.core.aggregation.Aggregation.newAggregation;
+import static org.springframework.data.mongodb.core.aggregation.Aggregation.project;
+import static org.springframework.data.mongodb.core.aggregation.Aggregation.sort;
+
+import java.io.BufferedReader;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.StreamSupport;
+
+import org.bson.Document;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
@@ -26,23 +38,11 @@ import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
-import java.io.BufferedReader;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.stream.Collectors;
-import java.util.stream.StreamSupport;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-import static org.springframework.data.mongodb.core.aggregation.Aggregation.group;
-import static org.springframework.data.mongodb.core.aggregation.Aggregation.limit;
-import static org.springframework.data.mongodb.core.aggregation.Aggregation.match;
-import static org.springframework.data.mongodb.core.aggregation.Aggregation.newAggregation;
-import static org.springframework.data.mongodb.core.aggregation.Aggregation.project;
-import static org.springframework.data.mongodb.core.aggregation.Aggregation.sort;
+import com.baeldung.aggregation.model.StatePopulation;
+import com.baeldung.config.MongoConfig;
+import com.mongodb.MongoClient;
+import com.mongodb.client.MongoCollection;
+import com.mongodb.client.MongoDatabase;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = MongoConfig.class)
@@ -56,23 +56,22 @@ public class ZipsAggregationLiveTest {
@BeforeClass
public static void setupTests() throws Exception {
client = new MongoClient();
- DB testDB = client.getDB("test");
- DBCollection zipsCollection = testDB.getCollection("zips");
+ MongoDatabase testDB = client.getDatabase("test");
+ MongoCollection zipsCollection = testDB.getCollection("zips");
zipsCollection.drop();
InputStream zipsJsonStream = ZipsAggregationLiveTest.class.getResourceAsStream("/zips.json");
BufferedReader reader = new BufferedReader(new InputStreamReader(zipsJsonStream));
reader.lines()
- .forEach(line -> zipsCollection.insert((DBObject) JSON.parse(line)));
+ .forEach(line -> zipsCollection.insertOne(Document.parse(line)));
reader.close();
-
}
@AfterClass
public static void tearDown() throws Exception {
client = new MongoClient();
- DB testDB = client.getDB("test");
- DBCollection zipsCollection = testDB.getCollection("zips");
+ MongoDatabase testDB = client.getDatabase("test");
+ MongoCollection zipsCollection = testDB.getCollection("zips");
zipsCollection.drop();
client.close();
}
@@ -140,13 +139,13 @@ public class ZipsAggregationLiveTest {
Aggregation aggregation = newAggregation(sumZips, sortByCount, groupFirstAndLast);
- AggregationResults result = mongoTemplate.aggregate(aggregation, "zips", DBObject.class);
- DBObject dbObject = result.getUniqueMappedResult();
+ AggregationResults result = mongoTemplate.aggregate(aggregation, "zips", Document.class);
+ Document document = result.getUniqueMappedResult();
- assertEquals("DC", dbObject.get("minZipState"));
- assertEquals(24, dbObject.get("minZipCount"));
- assertEquals("TX", dbObject.get("maxZipState"));
- assertEquals(1671, dbObject.get("maxZipCount"));
+ assertEquals("DC", document.get("minZipState"));
+ assertEquals(24, document.get("minZipCount"));
+ assertEquals("TX", document.get("maxZipState"));
+ assertEquals(1671, document.get("maxZipCount"));
}
}
diff --git a/spring-data-mongodb/src/test/java/com/baeldung/gridfs/GridFSLiveTest.java b/spring-data-mongodb/src/test/java/com/baeldung/gridfs/GridFSLiveTest.java
index 02485e8517..3a88a1e654 100644
--- a/spring-data-mongodb/src/test/java/com/baeldung/gridfs/GridFSLiveTest.java
+++ b/spring-data-mongodb/src/test/java/com/baeldung/gridfs/GridFSLiveTest.java
@@ -1,8 +1,19 @@
package com.baeldung.gridfs;
-import com.mongodb.BasicDBObject;
-import com.mongodb.DBObject;
-import com.mongodb.gridfs.GridFSDBFile;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.Matchers.nullValue;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThat;
+
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.bson.types.ObjectId;
import org.junit.After;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -16,18 +27,9 @@ import org.springframework.data.mongodb.gridfs.GridFsTemplate;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.List;
-
-import static org.hamcrest.CoreMatchers.is;
-import static org.hamcrest.Matchers.nullValue;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertThat;
+import com.mongodb.BasicDBObject;
+import com.mongodb.DBObject;
+import com.mongodb.client.gridfs.model.GridFSFile;
@ContextConfiguration("file:src/main/resources/mongoConfig.xml")
@RunWith(SpringJUnit4ClassRunner.class)
@@ -40,8 +42,9 @@ public class GridFSLiveTest {
@After
public void tearDown() {
- List fileList = gridFsTemplate.find(null);
- for (GridFSDBFile file : fileList) {
+ List fileList = new ArrayList();
+ gridFsTemplate.find(new Query()).into(fileList);
+ for (GridFSFile file : fileList) {
gridFsTemplate.delete(new Query(Criteria.where("filename").is(file.getFilename())));
}
}
@@ -54,7 +57,7 @@ public class GridFSLiveTest {
String id = "";
try {
inputStream = new FileInputStream("src/main/resources/test.png");
- id = gridFsTemplate.store(inputStream, "test.png", "image/png", metaData).getId().toString();
+ id = gridFsTemplate.store(inputStream, "test.png", "image/png", metaData).toString();
} catch (FileNotFoundException ex) {
logger.error("File not found", ex);
} finally {
@@ -75,10 +78,10 @@ public class GridFSLiveTest {
DBObject metaData = new BasicDBObject();
metaData.put("user", "alex");
InputStream inputStream = null;
- String id = "";
+ ObjectId id = null;
try {
inputStream = new FileInputStream("src/main/resources/test.png");
- id = gridFsTemplate.store(inputStream, "test.png", "image/png", metaData).getId().toString();
+ id = gridFsTemplate.store(inputStream, "test.png", "image/png", metaData);
} catch (FileNotFoundException ex) {
logger.error("File not found", ex);
} finally {
@@ -91,22 +94,22 @@ public class GridFSLiveTest {
}
}
- GridFSDBFile gridFSDBFile = gridFsTemplate.findOne(new Query(Criteria.where("_id").is(id)));
+ GridFSFile gridFSFile = gridFsTemplate.findOne(new Query(Criteria.where("_id").is(id)));
- assertNotNull(gridFSDBFile);
- assertNotNull(gridFSDBFile.getInputStream());
- assertThat(gridFSDBFile.numChunks(), is(1));
- assertThat(gridFSDBFile.containsField("filename"), is(true));
- assertThat(gridFSDBFile.get("filename"), is("test.png"));
- assertThat(gridFSDBFile.getId(), is(id));
- assertThat(gridFSDBFile.keySet().size(), is(9));
- assertNotNull(gridFSDBFile.getMD5());
- assertNotNull(gridFSDBFile.getUploadDate());
- assertNull(gridFSDBFile.getAliases());
- assertNotNull(gridFSDBFile.getChunkSize());
- assertThat(gridFSDBFile.getContentType(), is("image/png"));
- assertThat(gridFSDBFile.getFilename(), is("test.png"));
- assertThat(gridFSDBFile.getMetaData().get("user"), is("alex"));
+ assertNotNull(gridFSFile);
+// assertNotNull(gridFSFile.getInputStream());
+// assertThat(gridFSFile.numChunks(), is(1));
+// assertThat(gridFSFile.containsField("filename"), is(true));
+ assertThat(gridFSFile.getFilename(), is("test.png"));
+ assertThat(gridFSFile.getObjectId(), is(id));
+// assertThat(gridFSFile.keySet().size(), is(9));
+// assertNotNull(gridFSFile.getMD5());
+ assertNotNull(gridFSFile.getUploadDate());
+// assertNull(gridFSFile.getAliases());
+ assertNotNull(gridFSFile.getChunkSize());
+ assertThat(gridFSFile.getMetadata().get("_contentType"), is("image/png"));
+ assertThat(gridFSFile.getFilename(), is("test.png"));
+ assertThat(gridFSFile.getMetadata().get("user"), is("alex"));
}
@Test
@@ -133,10 +136,11 @@ public class GridFSLiveTest {
}
}
- List gridFSDBFiles = gridFsTemplate.find(null);
+ List gridFSFiles = new ArrayList();
+ gridFsTemplate.find(new Query()).into(gridFSFiles);
- assertNotNull(gridFSDBFiles);
- assertThat(gridFSDBFiles.size(), is(2));
+ assertNotNull(gridFSFiles);
+ assertThat(gridFSFiles.size(), is(2));
}
@Test
@@ -163,10 +167,11 @@ public class GridFSLiveTest {
}
}
- List gridFSDBFiles = gridFsTemplate.find(new Query(Criteria.where("metadata.user").is("alex")));
+ List gridFSFiles = new ArrayList();
+ gridFsTemplate.find(new Query(Criteria.where("metadata.user").is("alex"))).into(gridFSFiles);
- assertNotNull(gridFSDBFiles);
- assertThat(gridFSDBFiles.size(), is(1));
+ assertNotNull(gridFSFiles);
+ assertThat(gridFSFiles.size(), is(1));
}
@Test
@@ -177,7 +182,7 @@ public class GridFSLiveTest {
String id = "";
try {
inputStream = new FileInputStream("src/main/resources/test.png");
- id = gridFsTemplate.store(inputStream, "test.png", "image/png", metaData).getId().toString();
+ id = gridFsTemplate.store(inputStream, "test.png", "image/png", metaData).toString();
} catch (FileNotFoundException ex) {
logger.error("File not found", ex);
} finally {
@@ -200,10 +205,9 @@ public class GridFSLiveTest {
DBObject metaData = new BasicDBObject();
metaData.put("user", "alex");
InputStream inputStream = null;
- String id = "";
try {
inputStream = new FileInputStream("src/main/resources/test.png");
- id = gridFsTemplate.store(inputStream, "test.png", "image/png", metaData).getId().toString();
+ gridFsTemplate.store(inputStream, "test.png", "image/png", metaData).toString();
} catch (FileNotFoundException ex) {
logger.error("File not found", ex);
} finally {
diff --git a/spring-data-mongodb/src/test/java/com/baeldung/mongotemplate/DocumentQueryLiveTest.java b/spring-data-mongodb/src/test/java/com/baeldung/mongotemplate/DocumentQueryLiveTest.java
index 7a61f9f98a..d05bde0f1b 100644
--- a/spring-data-mongodb/src/test/java/com/baeldung/mongotemplate/DocumentQueryLiveTest.java
+++ b/spring-data-mongodb/src/test/java/com/baeldung/mongotemplate/DocumentQueryLiveTest.java
@@ -1,8 +1,11 @@
package com.baeldung.mongotemplate;
-import com.baeldung.config.MongoConfig;
-import com.baeldung.model.EmailAddress;
-import com.baeldung.model.User;
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
+import java.util.Iterator;
+import java.util.List;
+
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@@ -17,11 +20,9 @@ import org.springframework.data.mongodb.core.query.Query;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
-import java.util.Iterator;
-import java.util.List;
-
-import static org.hamcrest.CoreMatchers.is;
-import static org.junit.Assert.assertThat;
+import com.baeldung.config.MongoConfig;
+import com.baeldung.model.EmailAddress;
+import com.baeldung.model.User;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = MongoConfig.class)
@@ -152,7 +153,7 @@ public class DocumentQueryLiveTest {
user.setAge(35);
mongoTemplate.insert(user);
- final Pageable pageableRequest = new PageRequest(0, 2);
+ final Pageable pageableRequest = PageRequest.of(0, 2);
Query query = new Query();
query.with(pageableRequest);
diff --git a/spring-data-mongodb/src/test/java/com/baeldung/mongotemplate/MongoTemplateQueryLiveTest.java b/spring-data-mongodb/src/test/java/com/baeldung/mongotemplate/MongoTemplateQueryLiveTest.java
index ee1d4f4760..fc78921b75 100644
--- a/spring-data-mongodb/src/test/java/com/baeldung/mongotemplate/MongoTemplateQueryLiveTest.java
+++ b/spring-data-mongodb/src/test/java/com/baeldung/mongotemplate/MongoTemplateQueryLiveTest.java
@@ -1,8 +1,11 @@
package com.baeldung.mongotemplate;
-import com.baeldung.config.MongoConfig;
-import com.baeldung.model.EmailAddress;
-import com.baeldung.model.User;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.Matchers.nullValue;
+import static org.junit.Assert.assertThat;
+
+import java.util.List;
+
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@@ -20,11 +23,9 @@ import org.springframework.data.mongodb.core.query.Query;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
-import java.util.List;
-
-import static org.hamcrest.CoreMatchers.is;
-import static org.hamcrest.Matchers.nullValue;
-import static org.junit.Assert.assertThat;
+import com.baeldung.config.MongoConfig;
+import com.baeldung.model.EmailAddress;
+import com.baeldung.model.User;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = MongoConfig.class)
@@ -104,7 +105,7 @@ public class MongoTemplateQueryLiveTest {
user.setAge(35);
mongoTemplate.insert(user);
- final Pageable pageableRequest = new PageRequest(0, 2);
+ final Pageable pageableRequest = PageRequest.of(0, 2);
Query query = new Query();
query.with(pageableRequest);
diff --git a/spring-data-mongodb/src/test/java/com/baeldung/repository/UserRepositoryLiveTest.java b/spring-data-mongodb/src/test/java/com/baeldung/repository/UserRepositoryLiveTest.java
index da4e91baec..901610e42d 100644
--- a/spring-data-mongodb/src/test/java/com/baeldung/repository/UserRepositoryLiveTest.java
+++ b/spring-data-mongodb/src/test/java/com/baeldung/repository/UserRepositoryLiveTest.java
@@ -5,8 +5,6 @@ import static org.junit.Assert.assertThat;
import java.util.List;
-import com.baeldung.config.MongoConfig;
-import com.baeldung.model.User;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@@ -22,6 +20,9 @@ import org.springframework.data.mongodb.core.query.Query;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import com.baeldung.config.MongoConfig;
+import com.baeldung.model.User;
+
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = MongoConfig.class)
public class UserRepositoryLiveTest {
@@ -72,8 +73,7 @@ public class UserRepositoryLiveTest {
user.setName("Jim");
userRepository.save(user);
-
- assertThat(mongoOps.findAll(User.class).size(), is(2));
+ assertThat(mongoOps.findAll(User.class).size(), is(1));
}
@Test
@@ -94,7 +94,7 @@ public class UserRepositoryLiveTest {
mongoOps.insert(user);
user = mongoOps.findOne(Query.query(Criteria.where("name").is("Chris")), User.class);
- final User foundUser = userRepository.findOne(user.getId());
+ final User foundUser = userRepository.findById(user.getId()).get();
assertThat(user.getName(), is(foundUser.getName()));
}
@@ -106,7 +106,7 @@ public class UserRepositoryLiveTest {
mongoOps.insert(user);
user = mongoOps.findOne(Query.query(Criteria.where("name").is("Harris")), User.class);
- final boolean isExists = userRepository.exists(user.getId());
+ final boolean isExists = userRepository.existsById(user.getId());
assertThat(isExists, is(true));
}
@@ -138,7 +138,7 @@ public class UserRepositoryLiveTest {
user.setName("Adam");
mongoOps.insert(user);
- final Pageable pageableRequest = new PageRequest(0, 1);
+ final Pageable pageableRequest = PageRequest.of(0, 1);
final Page page = userRepository.findAll(pageableRequest);
List users = page.getContent();
diff --git a/spring-data-mongodb/src/test/java/com/baeldung/transaction/MongoTransactionReactiveIntegrationTest.java b/spring-data-mongodb/src/test/java/com/baeldung/transaction/MongoTransactionReactiveIntegrationTest.java
new file mode 100644
index 0000000000..43aa865e91
--- /dev/null
+++ b/spring-data-mongodb/src/test/java/com/baeldung/transaction/MongoTransactionReactiveIntegrationTest.java
@@ -0,0 +1,47 @@
+package com.baeldung.transaction;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.mongodb.core.ReactiveMongoOperations;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+import com.baeldung.config.MongoReactiveConfig;
+import com.baeldung.model.User;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(classes = MongoReactiveConfig.class)
+public class MongoTransactionReactiveIntegrationTest {
+
+ @Autowired
+ private ReactiveMongoOperations reactiveOps;
+
+ @Before
+ public void testSetup() {
+ if (!reactiveOps.collectionExists(User.class)
+ .block()) {
+ reactiveOps.createCollection(User.class);
+ }
+ }
+
+ @After
+ public void tearDown() {
+ System.out.println(reactiveOps.findAll(User.class)
+ .count()
+ .block());
+ reactiveOps.dropCollection(User.class);
+ }
+
+ @Test
+ public void whenPerformTransaction_thenSuccess() {
+ User user1 = new User("Jane", 23);
+ User user2 = new User("John", 34);
+ reactiveOps.inTransaction()
+ .execute(action -> action.insert(user1)
+ .then(action.insert(user2)));
+ }
+
+}
diff --git a/spring-data-mongodb/src/test/java/com/baeldung/transaction/MongoTransactionTemplateIntegrationTest.java b/spring-data-mongodb/src/test/java/com/baeldung/transaction/MongoTransactionTemplateIntegrationTest.java
new file mode 100644
index 0000000000..1dbe724d87
--- /dev/null
+++ b/spring-data-mongodb/src/test/java/com/baeldung/transaction/MongoTransactionTemplateIntegrationTest.java
@@ -0,0 +1,68 @@
+package com.baeldung.transaction;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
+import java.util.List;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.mongodb.MongoTransactionManager;
+import org.springframework.data.mongodb.SessionSynchronization;
+import org.springframework.data.mongodb.core.MongoTemplate;
+import org.springframework.data.mongodb.core.query.Criteria;
+import org.springframework.data.mongodb.core.query.Query;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.transaction.TransactionStatus;
+import org.springframework.transaction.support.TransactionCallbackWithoutResult;
+import org.springframework.transaction.support.TransactionTemplate;
+
+import com.baeldung.config.MongoConfig;
+import com.baeldung.model.User;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(classes = MongoConfig.class)
+public class MongoTransactionTemplateIntegrationTest {
+
+ @Autowired
+ private MongoTemplate mongoTemplate;
+
+ @Autowired
+ private MongoTransactionManager mongoTransactionManager;
+
+ @Before
+ public void testSetup() {
+ if (!mongoTemplate.collectionExists(User.class)) {
+ mongoTemplate.createCollection(User.class);
+ }
+ }
+
+ @After
+ public void tearDown() {
+ mongoTemplate.dropCollection(User.class);
+ }
+
+ @Test
+ public void givenTransactionTemplate_whenPerformTransaction_thenSuccess() {
+ mongoTemplate.setSessionSynchronization(SessionSynchronization.ALWAYS);
+ TransactionTemplate transactionTemplate = new TransactionTemplate(mongoTransactionManager);
+ transactionTemplate.execute(new TransactionCallbackWithoutResult() {
+ @Override
+ protected void doInTransactionWithoutResult(TransactionStatus status) {
+ mongoTemplate.insert(new User("Kim", 20));
+ mongoTemplate.insert(new User("Jack", 45));
+ };
+ });
+
+ Query query = new Query().addCriteria(Criteria.where("name")
+ .is("Jack"));
+ List users = mongoTemplate.find(query, User.class);
+
+ assertThat(users.size(), is(1));
+ }
+
+}
diff --git a/spring-data-mongodb/src/test/java/com/baeldung/transaction/MongoTransactionalIntegrationTest.java b/spring-data-mongodb/src/test/java/com/baeldung/transaction/MongoTransactionalIntegrationTest.java
new file mode 100644
index 0000000000..4d747789a0
--- /dev/null
+++ b/spring-data-mongodb/src/test/java/com/baeldung/transaction/MongoTransactionalIntegrationTest.java
@@ -0,0 +1,90 @@
+package com.baeldung.transaction;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+
+import java.util.List;
+
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.MethodSorters;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.mongodb.MongoTransactionException;
+import org.springframework.data.mongodb.core.MongoTemplate;
+import org.springframework.data.mongodb.core.query.Criteria;
+import org.springframework.data.mongodb.core.query.Query;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.transaction.annotation.Transactional;
+
+import com.baeldung.config.MongoConfig;
+import com.baeldung.model.User;
+import com.baeldung.repository.UserRepository;
+import com.mongodb.MongoCommandException;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(classes = MongoConfig.class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class MongoTransactionalIntegrationTest {
+
+ @Autowired
+ private MongoTemplate mongoTemplate;
+
+ @Autowired
+ private UserRepository userRepository;
+
+ @Test
+ @Transactional
+ public void whenPerformMongoTransaction_thenSuccess() {
+ userRepository.save(new User("John", 30));
+ userRepository.save(new User("Ringo", 35));
+ Query query = new Query().addCriteria(Criteria.where("name")
+ .is("John"));
+ List users = mongoTemplate.find(query, User.class);
+
+ assertThat(users.size(), is(1));
+ }
+
+ @Test(expected = MongoTransactionException.class)
+ @Transactional
+ public void whenListCollectionDuringMongoTransaction_thenException() {
+ if (mongoTemplate.collectionExists(User.class)) {
+ mongoTemplate.save(new User("John", 30));
+ mongoTemplate.save(new User("Ringo", 35));
+ }
+ }
+
+ @Test(expected = MongoCommandException.class)
+ @Transactional
+ public void whenCountDuringMongoTransaction_thenException() {
+ userRepository.save(new User("John", 30));
+ userRepository.save(new User("Ringo", 35));
+ userRepository.count();
+ }
+
+ @Test
+ @Transactional
+ public void whenQueryDuringMongoTransaction_thenSuccess() {
+ userRepository.save(new User("Jane", 20));
+ userRepository.save(new User("Nick", 33));
+ List users = mongoTemplate.find(new Query(), User.class);
+
+ assertTrue(users.size() > 1);
+ }
+
+ // ==== Using test instead of before and after due to @transactional doesn't allow list collection
+
+ @Test
+ public void setup() {
+ if (!mongoTemplate.collectionExists(User.class)) {
+ mongoTemplate.createCollection(User.class);
+ }
+ }
+
+ @Test
+ public void ztearDown() {
+ mongoTemplate.dropCollection(User.class);
+ }
+}