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