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/README.md b/core-java/README.md
index 231d35aafc..a117d1843d 100644
--- a/core-java/README.md
+++ b/core-java/README.md
@@ -36,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/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/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