diff --git a/.gitignore b/.gitignore
index 0e71421ee7..5be11c71ff 100644
--- a/.gitignore
+++ b/.gitignore
@@ -19,6 +19,7 @@
.idea/
*.iml
*.iws
+out/
# Mac
.DS_Store
@@ -27,6 +28,9 @@
log/
target/
+# Gradle
+.gradle/
+
spring-openid/src/main/resources/application.properties
.recommenders/
/spring-hibernate4/nbproject/
@@ -66,3 +70,12 @@ jmeter/src/main/resources/*-JMeter.csv
**/nb-configuration.xml
core-scala/.cache-main
core-scala/.cache-tests
+
+
+persistence-modules/hibernate5/transaction.log
+apache-avro/src/main/java/com/baeldung/avro/model/
+jta/transaction-logs/
+software-security/sql-injection-samples/derby.log
+spring-soap/src/main/java/com/baeldung/springsoap/gen/
+/report-*.json
+transaction.log
\ No newline at end of file
diff --git a/JGit/pom.xml b/JGit/pom.xml
index 176d55d321..deae1e45e3 100644
--- a/JGit/pom.xml
+++ b/JGit/pom.xml
@@ -5,9 +5,9 @@
com.baeldungJGit1.0-SNAPSHOT
+ JGitjarhttp://maven.apache.org
- JGitcom.baeldung
diff --git a/README.md b/README.md
index f3fe5e3bf0..1030cbb09c 100644
--- a/README.md
+++ b/README.md
@@ -14,23 +14,28 @@ Java and Spring Tutorials
================
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.
+A strong focus of these is, of course, the Spring Framework - Spring, Spring Boot and Spring Security.
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`
+To do the full build, do: `mvn clean install`
Building a single module
====================
-To build a specific module run the command: `mvn clean install -Dgib.enabled=false` in the module directory
+To build a specific module run the command: `mvn clean install` in the module directory
Running a Spring Boot module
====================
-To run a Spring Boot module run the command: `mvn spring-boot:run -Dgib.enabled=false` in the module directory
+To run a Spring Boot module run the command: `mvn spring-boot:run` in the module directory
+
+#Running Tests
+
+The command `mvn clean install` will run the unit tests in a module.
+To run the integration tests, use the command `mvn clean install -Pintegration-lite-first`
diff --git a/Twitter4J/pom.xml b/Twitter4J/pom.xml
index 982c1adc23..b82b9f6778 100644
--- a/Twitter4J/pom.xml
+++ b/Twitter4J/pom.xml
@@ -2,8 +2,8 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
4.0.0Twitter4J
- jarTwitter4J
+ jarcom.baeldung
diff --git a/akka-http/README.md b/akka-http/README.md
new file mode 100644
index 0000000000..3831b5079f
--- /dev/null
+++ b/akka-http/README.md
@@ -0,0 +1,3 @@
+## Relevant articles:
+
+- [Introduction to Akka HTTP](https://www.baeldung.com/akka-http)
diff --git a/akka-http/pom.xml b/akka-http/pom.xml
new file mode 100644
index 0000000000..6d73f2f2e6
--- /dev/null
+++ b/akka-http/pom.xml
@@ -0,0 +1,47 @@
+
+
+
+ 4.0.0
+ akka-http
+ akka-http
+
+
+ parent-modules
+ com.baeldung
+ 1.0.0-SNAPSHOT
+
+
+
+
+ com.typesafe.akka
+ akka-http_2.12
+ ${akka.http.version}
+
+
+ com.typesafe.akka
+ akka-stream_2.12
+ ${akka.stream.version}
+
+
+ com.typesafe.akka
+ akka-http-jackson_2.12
+ ${akka.http.version}
+
+
+ com.typesafe.akka
+ akka-http-testkit_2.12
+ ${akka.http.version}
+ test
+
+
+
+
+ UTF-8
+ UTF-8
+ 10.0.11
+ 2.5.11
+
+
diff --git a/akka-http/src/main/java/com/baeldung/akkahttp/User.java b/akka-http/src/main/java/com/baeldung/akkahttp/User.java
new file mode 100644
index 0000000000..43c21eca62
--- /dev/null
+++ b/akka-http/src/main/java/com/baeldung/akkahttp/User.java
@@ -0,0 +1,26 @@
+package com.baeldung.akkahttp;
+
+public class User {
+
+ private final Long id;
+
+ private final String name;
+
+ public User() {
+ this.name = "";
+ this.id = null;
+ }
+
+ public User(Long id, String name) {
+ this.name = name;
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public Long getId() {
+ return id;
+ }
+}
\ No newline at end of file
diff --git a/akka-http/src/main/java/com/baeldung/akkahttp/UserActor.java b/akka-http/src/main/java/com/baeldung/akkahttp/UserActor.java
new file mode 100644
index 0000000000..431014a88b
--- /dev/null
+++ b/akka-http/src/main/java/com/baeldung/akkahttp/UserActor.java
@@ -0,0 +1,41 @@
+package com.baeldung.akkahttp;
+
+import akka.actor.AbstractActor;
+import akka.actor.Props;
+import akka.japi.pf.FI;
+import com.baeldung.akkahttp.UserMessages.ActionPerformed;
+import com.baeldung.akkahttp.UserMessages.CreateUserMessage;
+import com.baeldung.akkahttp.UserMessages.GetUserMessage;
+
+
+class UserActor extends AbstractActor {
+
+ private UserService userService = new UserService();
+
+ static Props props() {
+ return Props.create(UserActor.class);
+ }
+
+ @Override
+ public Receive createReceive() {
+ return receiveBuilder()
+ .match(CreateUserMessage.class, handleCreateUser())
+ .match(GetUserMessage.class, handleGetUser())
+ .build();
+ }
+
+ private FI.UnitApply handleCreateUser() {
+ return createUserMessageMessage -> {
+ userService.createUser(createUserMessageMessage.getUser());
+ sender().tell(new ActionPerformed(String.format("User %s created.", createUserMessageMessage.getUser()
+ .getName())), getSelf());
+ };
+ }
+
+ private FI.UnitApply handleGetUser() {
+ return getUserMessageMessage -> {
+ sender().tell(userService.getUser(getUserMessageMessage.getUserId()), getSelf());
+ };
+ }
+
+}
diff --git a/akka-http/src/main/java/com/baeldung/akkahttp/UserMessages.java b/akka-http/src/main/java/com/baeldung/akkahttp/UserMessages.java
new file mode 100644
index 0000000000..995b92bcb0
--- /dev/null
+++ b/akka-http/src/main/java/com/baeldung/akkahttp/UserMessages.java
@@ -0,0 +1,49 @@
+package com.baeldung.akkahttp;
+
+import java.io.Serializable;
+
+public interface UserMessages {
+
+ class ActionPerformed implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ private final String description;
+
+ public ActionPerformed(String description) {
+ this.description = description;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+ }
+
+ class CreateUserMessage implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+ private final User user;
+
+ public CreateUserMessage(User user) {
+ this.user = user;
+ }
+
+ public User getUser() {
+ return user;
+ }
+ }
+
+ class GetUserMessage implements Serializable {
+ private static final long serialVersionUID = 1L;
+ private final Long userId;
+
+ public GetUserMessage(Long userId) {
+ this.userId = userId;
+ }
+
+ public Long getUserId() {
+ return userId;
+ }
+ }
+
+}
diff --git a/akka-http/src/main/java/com/baeldung/akkahttp/UserServer.java b/akka-http/src/main/java/com/baeldung/akkahttp/UserServer.java
new file mode 100644
index 0000000000..0c1dbd1f60
--- /dev/null
+++ b/akka-http/src/main/java/com/baeldung/akkahttp/UserServer.java
@@ -0,0 +1,70 @@
+package com.baeldung.akkahttp;
+
+import java.util.Optional;
+import java.util.concurrent.CompletionStage;
+import java.util.concurrent.TimeUnit;
+
+import akka.actor.ActorRef;
+import akka.actor.ActorSystem;
+import akka.http.javadsl.marshallers.jackson.Jackson;
+import akka.http.javadsl.model.StatusCodes;
+import akka.http.javadsl.server.HttpApp;
+import akka.http.javadsl.server.Route;
+import akka.pattern.PatternsCS;
+import akka.util.Timeout;
+import com.baeldung.akkahttp.UserMessages.ActionPerformed;
+import com.baeldung.akkahttp.UserMessages.CreateUserMessage;
+import com.baeldung.akkahttp.UserMessages.GetUserMessage;
+import scala.concurrent.duration.Duration;
+import static akka.http.javadsl.server.PathMatchers.*;
+
+class UserServer extends HttpApp {
+
+ private final ActorRef userActor;
+
+ Timeout timeout = new Timeout(Duration.create(5, TimeUnit.SECONDS));
+
+ UserServer(ActorRef userActor) {
+ this.userActor = userActor;
+ }
+
+ @Override
+ public Route routes() {
+ return path("users", this::postUser)
+ .orElse(path(segment("users").slash(longSegment()), id ->
+ route(getUser(id))));
+ }
+
+ private Route getUser(Long id) {
+ return get(() -> {
+ CompletionStage> user = PatternsCS.ask(userActor, new GetUserMessage(id), timeout)
+ .thenApply(obj -> (Optional) obj);
+
+ return onSuccess(() -> user, performed -> {
+ if (performed.isPresent())
+ return complete(StatusCodes.OK, performed.get(), Jackson.marshaller());
+ else
+ return complete(StatusCodes.NOT_FOUND);
+ });
+ });
+ }
+
+ private Route postUser() {
+ return route(post(() -> entity(Jackson.unmarshaller(User.class), user -> {
+ CompletionStage userCreated = PatternsCS.ask(userActor, new CreateUserMessage(user), timeout)
+ .thenApply(obj -> (ActionPerformed) obj);
+
+ return onSuccess(() -> userCreated, performed -> {
+ return complete(StatusCodes.CREATED, performed, Jackson.marshaller());
+ });
+ })));
+ }
+
+ public static void main(String[] args) throws Exception {
+ ActorSystem system = ActorSystem.create("userServer");
+ ActorRef userActor = system.actorOf(UserActor.props(), "userActor");
+ UserServer server = new UserServer(userActor);
+ server.startServer("localhost", 8080, system);
+ }
+
+}
diff --git a/akka-http/src/main/java/com/baeldung/akkahttp/UserService.java b/akka-http/src/main/java/com/baeldung/akkahttp/UserService.java
new file mode 100644
index 0000000000..50dc1e1b28
--- /dev/null
+++ b/akka-http/src/main/java/com/baeldung/akkahttp/UserService.java
@@ -0,0 +1,35 @@
+package com.baeldung.akkahttp;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+
+public class UserService {
+
+ private final static List users = new ArrayList<>();
+
+ static {
+ users.add(new User(1l, "Alice"));
+ users.add(new User(2l, "Bob"));
+ users.add(new User(3l, "Chris"));
+ users.add(new User(4l, "Dick"));
+ users.add(new User(5l, "Eve"));
+ users.add(new User(6l, "Finn"));
+ }
+
+ public Optional getUser(Long id) {
+ return users.stream()
+ .filter(user -> user.getId()
+ .equals(id))
+ .findFirst();
+ }
+
+ public void createUser(User user) {
+ users.add(user);
+ }
+
+ public List getUsers(){
+ return users;
+ }
+
+}
diff --git a/akka-http/src/test/java/com/baeldung/akkahttp/UserServerUnitTest.java b/akka-http/src/test/java/com/baeldung/akkahttp/UserServerUnitTest.java
new file mode 100644
index 0000000000..1170a2d761
--- /dev/null
+++ b/akka-http/src/test/java/com/baeldung/akkahttp/UserServerUnitTest.java
@@ -0,0 +1,50 @@
+package com.baeldung.akkahttp;
+
+import akka.actor.ActorRef;
+import akka.actor.ActorSystem;
+import akka.http.javadsl.model.ContentTypes;
+import akka.http.javadsl.model.HttpEntities;
+import akka.http.javadsl.model.HttpRequest;
+import akka.http.javadsl.testkit.JUnitRouteTest;
+import akka.http.javadsl.testkit.TestRoute;
+import org.junit.Test;
+
+public class UserServerUnitTest extends JUnitRouteTest {
+
+ ActorSystem system = ActorSystem.create("helloAkkaHttpServer");
+
+ ActorRef userActorRef = system.actorOf(UserActor.props(), "userActor");
+
+ TestRoute appRoute = testRoute(new UserServer(userActorRef).routes());
+
+ @Test
+ public void whenRequest_thenActorResponds() {
+
+ appRoute.run(HttpRequest.GET("/users/1"))
+ .assertEntity(alice())
+ .assertStatusCode(200);
+
+ appRoute.run(HttpRequest.GET("/users/42"))
+ .assertStatusCode(404);
+
+ appRoute.run(HttpRequest.DELETE("/users/1"))
+ .assertStatusCode(200);
+
+ appRoute.run(HttpRequest.DELETE("/users/42"))
+ .assertStatusCode(200);
+
+ appRoute.run(HttpRequest.POST("/users")
+ .withEntity(HttpEntities.create(ContentTypes.APPLICATION_JSON, zaphod())))
+ .assertStatusCode(201);
+
+ }
+
+ private String alice() {
+ return "{\"id\":1,\"name\":\"Alice\"}";
+ }
+
+ private String zaphod() {
+ return "{\"id\":42,\"name\":\"Zaphod\"}";
+ }
+
+}
diff --git a/akka-streams/pom.xml b/akka-streams/pom.xml
index a885753ce2..7719bb7351 100644
--- a/akka-streams/pom.xml
+++ b/akka-streams/pom.xml
@@ -14,18 +14,19 @@
com.typesafe.akka
- akka-stream_2.11
+ akka-stream_${scala.version}${akkastreams.version}com.typesafe.akka
- akka-stream-testkit_2.11
+ akka-stream-testkit_${scala.version}${akkastreams.version}2.5.2
+ 2.11
\ No newline at end of file
diff --git a/algorithms-genetic/pom.xml b/algorithms-genetic/pom.xml
index fc6d36dac1..56f6a31525 100644
--- a/algorithms-genetic/pom.xml
+++ b/algorithms-genetic/pom.xml
@@ -54,7 +54,6 @@
- 1.16.123.6.13.7.03.9.0
diff --git a/algorithms-miscellaneous-1/README.md b/algorithms-miscellaneous-1/README.md
index a04874c4d2..479c2792f6 100644
--- a/algorithms-miscellaneous-1/README.md
+++ b/algorithms-miscellaneous-1/README.md
@@ -10,4 +10,9 @@
- [Multi-Swarm Optimization Algorithm in Java](http://www.baeldung.com/java-multi-swarm-algorithm)
- [String Search Algorithms for Large Texts](http://www.baeldung.com/java-full-text-search-algorithms)
- [Check If a String Contains All The Letters of The Alphabet](https://www.baeldung.com/java-string-contains-all-letters)
-- [Find the Middle Element of a Linked List](http://www.baeldung.com/java-linked-list-middle-element)
\ No newline at end of file
+- [Find the Middle Element of a Linked List](http://www.baeldung.com/java-linked-list-middle-element)
+- [Calculate Factorial in Java](https://www.baeldung.com/java-calculate-factorial)
+- [Find Substrings That Are Palindromes in Java](https://www.baeldung.com/java-palindrome-substrings)
+- [Find the Longest Substring without Repeating Characters](https://www.baeldung.com/java-longest-substring-without-repeated-characters)
+- [Permutations of an Array in Java](https://www.baeldung.com/java-array-permutations)
+- [Generate Combinations in Java](https://www.baeldung.com/java-combinations-algorithm)
diff --git a/algorithms-miscellaneous-1/pom.xml b/algorithms-miscellaneous-1/pom.xml
index 5006670dd9..affa66f147 100644
--- a/algorithms-miscellaneous-1/pom.xml
+++ b/algorithms-miscellaneous-1/pom.xml
@@ -39,6 +39,11 @@
${org.assertj.core.version}test
+
+ com.github.dpaukov
+ combinatoricslib3
+ ${combinatoricslib3.version}
+
@@ -74,11 +79,11 @@
- 1.16.123.6.13.9.01.11
- 25.1-jre
+ 27.0.1-jre
+ 3.3.0
\ No newline at end of file
diff --git a/algorithms-miscellaneous-1/src/main/java/com/baeldung/algorithms/permutation/Permutation.java b/algorithms-miscellaneous-1/src/main/java/com/baeldung/algorithms/permutation/Permutation.java
new file mode 100644
index 0000000000..7fedd78ffb
--- /dev/null
+++ b/algorithms-miscellaneous-1/src/main/java/com/baeldung/algorithms/permutation/Permutation.java
@@ -0,0 +1,123 @@
+package com.baeldung.algorithms.permutation;
+
+import java.util.Arrays;
+import java.util.Collections;
+
+public class Permutation {
+
+ public static void printAllRecursive(T[] elements, char delimiter) {
+ printAllRecursive(elements.length, elements, delimiter);
+ }
+
+ public static void printAllRecursive(int n, T[] elements, char delimiter) {
+
+ if(n == 1) {
+ printArray(elements, delimiter);
+ } else {
+ for(int i = 0; i < n-1; i++) {
+ printAllRecursive(n - 1, elements, delimiter);
+ if(n % 2 == 0) {
+ swap(elements, i, n-1);
+ } else {
+ swap(elements, 0, n-1);
+ }
+ }
+ printAllRecursive(n - 1, elements, delimiter);
+ }
+ }
+
+ public static void printAllIterative(int n, T[] elements, char delimiter) {
+
+ int[] indexes = new int[n];
+ for (int i = 0; i < n; i++) {
+ indexes[i] = 0;
+ }
+
+ printArray(elements, delimiter);
+
+ int i = 0;
+ while (i < n) {
+ if (indexes[i] < i) {
+ swap(elements, i % 2 == 0 ? 0: indexes[i], i);
+ printArray(elements, delimiter);
+ indexes[i]++;
+ i = 0;
+ }
+ else {
+ indexes[i] = 0;
+ i++;
+ }
+ }
+ }
+
+ public static > void printAllOrdered(T[] elements, char delimiter) {
+
+ Arrays.sort(elements);
+ boolean hasNext = true;
+
+ while(hasNext) {
+ printArray(elements, delimiter);
+ int k = 0, l = 0;
+ hasNext = false;
+ for (int i = elements.length - 1; i > 0; i--) {
+ if (elements[i].compareTo(elements[i - 1]) > 0) {
+ k = i - 1;
+ hasNext = true;
+ break;
+ }
+ }
+
+ for (int i = elements.length - 1; i > k; i--) {
+ if (elements[i].compareTo(elements[k]) > 0) {
+ l = i;
+ break;
+ }
+ }
+
+ swap(elements, k, l);
+ Collections.reverse(Arrays.asList(elements).subList(k + 1, elements.length));
+ }
+ }
+
+ public static void printRandom(T[] elements, char delimiter) {
+
+ Collections.shuffle(Arrays.asList(elements));
+ printArray(elements, delimiter);
+ }
+
+ private static void swap(T[] elements, int a, int b) {
+
+ T tmp = elements[a];
+ elements[a] = elements[b];
+ elements[b] = tmp;
+ }
+
+ private static void printArray(T[] elements, char delimiter) {
+
+ String delimiterSpace = delimiter + " ";
+ for(int i = 0; i < elements.length; i++) {
+ System.out.print(elements[i] + delimiterSpace);
+ }
+ System.out.print('\n');
+ }
+
+ public static void main(String[] argv) {
+
+ Integer[] elements = {1,2,3,4};
+
+ System.out.println("Rec:");
+ printAllRecursive(elements, ';');
+
+ System.out.println("Iter:");
+ printAllIterative(elements.length, elements, ';');
+
+ System.out.println("Orderes:");
+ printAllOrdered(elements, ';');
+
+ System.out.println("Random:");
+ printRandom(elements, ';');
+
+ System.out.println("Random:");
+ printRandom(elements, ';');
+ }
+}
diff --git a/algorithms-miscellaneous-2/README.md b/algorithms-miscellaneous-2/README.md
index d693a44f66..462644dddb 100644
--- a/algorithms-miscellaneous-2/README.md
+++ b/algorithms-miscellaneous-2/README.md
@@ -8,9 +8,6 @@
- [Create a Sudoku Solver in Java](http://www.baeldung.com/java-sudoku)
- [Displaying Money Amounts in Words](http://www.baeldung.com/java-money-into-words)
- [A Collaborative Filtering Recommendation System in Java](http://www.baeldung.com/java-collaborative-filtering-recommendations)
-- [Converting Between Roman and Arabic Numerals in Java](http://www.baeldung.com/java-convert-roman-arabic)
-- [Practical Java Examples of the Big O Notation](http://www.baeldung.com/java-algorithm-complexity)
-- [An Introduction to the Theory of Big-O Notation](http://www.baeldung.com/big-o-notation)
- [Check If Two Rectangles Overlap In Java](https://www.baeldung.com/java-check-if-two-rectangles-overlap)
- [Calculate the Distance Between Two Points in Java](https://www.baeldung.com/java-distance-between-two-points)
- [Find the Intersection of Two Lines in Java](https://www.baeldung.com/java-intersection-of-two-lines)
@@ -18,3 +15,5 @@
- [Calculate Percentage in Java](https://www.baeldung.com/java-calculate-percentage)
- [Converting Between Byte Arrays and Hexadecimal Strings in Java](https://www.baeldung.com/java-byte-arrays-hex-strings)
- [Convert Latitude and Longitude to a 2D Point in Java](https://www.baeldung.com/java-convert-latitude-longitude)
+- [Reversing a Binary Tree in Java](https://www.baeldung.com/java-reversing-a-binary-tree)
+- [Find If Two Numbers Are Relatively Prime in Java](https://www.baeldung.com/java-two-relatively-prime-numbers)
diff --git a/algorithms-miscellaneous-2/pom.xml b/algorithms-miscellaneous-2/pom.xml
index 5461f4ebe1..e85dd456a3 100644
--- a/algorithms-miscellaneous-2/pom.xml
+++ b/algorithms-miscellaneous-2/pom.xml
@@ -68,7 +68,7 @@
org.codehaus.mojocobertura-maven-plugin
- 2.7
+ ${cobertura-maven-plugin.version}
@@ -84,13 +84,13 @@
- 1.16.123.6.11.0.11.0.11.0.13.9.01.11
+ 2.7
\ No newline at end of file
diff --git a/algorithms-miscellaneous-2/src/main/java/com/baeldung/algorithms/relativelyprime/RelativelyPrime.java b/algorithms-miscellaneous-2/src/main/java/com/baeldung/algorithms/relativelyprime/RelativelyPrime.java
new file mode 100644
index 0000000000..fbea87be30
--- /dev/null
+++ b/algorithms-miscellaneous-2/src/main/java/com/baeldung/algorithms/relativelyprime/RelativelyPrime.java
@@ -0,0 +1,45 @@
+package com.baeldung.algorithms.relativelyprime;
+
+import java.math.BigInteger;
+
+class RelativelyPrime {
+
+ static boolean iterativeRelativelyPrime(int a, int b) {
+ return iterativeGCD(a, b) == 1;
+ }
+
+ static boolean recursiveRelativelyPrime(int a, int b) {
+ return recursiveGCD(a, b) == 1;
+ }
+
+ static boolean bigIntegerRelativelyPrime(int a, int b) {
+ return BigInteger.valueOf(a).gcd(BigInteger.valueOf(b)).equals(BigInteger.ONE);
+ }
+
+ private static int iterativeGCD(int a, int b) {
+ int tmp;
+ while (b != 0) {
+ if (a < b) {
+ tmp = a;
+ a = b;
+ b = tmp;
+ }
+ tmp = b;
+ b = a % b;
+ a = tmp;
+ }
+ return a;
+ }
+
+ private static int recursiveGCD(int a, int b) {
+ if (b == 0) {
+ return a;
+ }
+ if (a < b) {
+ return recursiveGCD(b, a);
+ }
+ return recursiveGCD(b, a % b);
+ }
+
+
+}
diff --git a/algorithms-miscellaneous-2/src/main/java/com/baeldung/algorithms/reversingtree/TreeNode.java b/algorithms-miscellaneous-2/src/main/java/com/baeldung/algorithms/reversingtree/TreeNode.java
new file mode 100644
index 0000000000..a6ec2277e5
--- /dev/null
+++ b/algorithms-miscellaneous-2/src/main/java/com/baeldung/algorithms/reversingtree/TreeNode.java
@@ -0,0 +1,42 @@
+package com.baeldung.algorithms.reversingtree;
+
+public class TreeNode {
+
+ private int value;
+ private TreeNode rightChild;
+ private TreeNode leftChild;
+
+ public int getValue() {
+ return value;
+ }
+
+ public void setValue(int value) {
+ this.value = value;
+ }
+
+ public TreeNode getRightChild() {
+ return rightChild;
+ }
+
+ public void setRightChild(TreeNode rightChild) {
+ this.rightChild = rightChild;
+ }
+
+ public TreeNode getLeftChild() {
+ return leftChild;
+ }
+
+ public void setLeftChild(TreeNode leftChild) {
+ this.leftChild = leftChild;
+ }
+
+ public TreeNode(int value, TreeNode leftChild, TreeNode rightChild) {
+ this.value = value;
+ this.rightChild = rightChild;
+ this.leftChild = leftChild;
+ }
+
+ public TreeNode(int value) {
+ this.value = value;
+ }
+}
diff --git a/algorithms-miscellaneous-2/src/main/java/com/baeldung/algorithms/reversingtree/TreeReverser.java b/algorithms-miscellaneous-2/src/main/java/com/baeldung/algorithms/reversingtree/TreeReverser.java
new file mode 100644
index 0000000000..162119d390
--- /dev/null
+++ b/algorithms-miscellaneous-2/src/main/java/com/baeldung/algorithms/reversingtree/TreeReverser.java
@@ -0,0 +1,53 @@
+package com.baeldung.algorithms.reversingtree;
+
+import java.util.LinkedList;
+
+public class TreeReverser {
+
+ public void reverseRecursive(TreeNode treeNode) {
+ if (treeNode == null) {
+ return;
+ }
+
+ TreeNode temp = treeNode.getLeftChild();
+ treeNode.setLeftChild(treeNode.getRightChild());
+ treeNode.setRightChild(temp);
+
+ reverseRecursive(treeNode.getLeftChild());
+ reverseRecursive(treeNode.getRightChild());
+ }
+
+ public void reverseIterative(TreeNode treeNode) {
+ LinkedList queue = new LinkedList();
+
+ if (treeNode != null) {
+ queue.add(treeNode);
+ }
+
+ while (!queue.isEmpty()) {
+
+ TreeNode node = queue.poll();
+ if (node.getLeftChild() != null)
+ queue.add(node.getLeftChild());
+ if (node.getRightChild() != null)
+ queue.add(node.getRightChild());
+
+ TreeNode temp = node.getLeftChild();
+ node.setLeftChild(node.getRightChild());
+ node.setRightChild(temp);
+ }
+ }
+
+ public String toString(TreeNode root) {
+ if (root == null) {
+ return "";
+ }
+
+ StringBuffer buffer = new StringBuffer(String.valueOf(root.getValue())).append(" ");
+
+ buffer.append(toString(root.getLeftChild()));
+ buffer.append(toString(root.getRightChild()));
+
+ return buffer.toString();
+ }
+}
diff --git a/algorithms-miscellaneous-2/src/test/java/com/baeldung/algorithms/relativelyprime/RelativelyPrimeUnitTest.java b/algorithms-miscellaneous-2/src/test/java/com/baeldung/algorithms/relativelyprime/RelativelyPrimeUnitTest.java
new file mode 100644
index 0000000000..84bb2620af
--- /dev/null
+++ b/algorithms-miscellaneous-2/src/test/java/com/baeldung/algorithms/relativelyprime/RelativelyPrimeUnitTest.java
@@ -0,0 +1,51 @@
+package com.baeldung.algorithms.relativelyprime;
+
+import org.junit.Test;
+
+import static com.baeldung.algorithms.relativelyprime.RelativelyPrime.*;
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class RelativelyPrimeUnitTest {
+
+ @Test
+ public void givenNonRelativelyPrimeNumbers_whenCheckingIteratively_shouldReturnFalse() {
+
+ boolean result = iterativeRelativelyPrime(45, 35);
+ assertThat(result).isFalse();
+ }
+
+ @Test
+ public void givenRelativelyPrimeNumbers_whenCheckingIteratively_shouldReturnTrue() {
+
+ boolean result = iterativeRelativelyPrime(500, 501);
+ assertThat(result).isTrue();
+ }
+
+ @Test
+ public void givenNonRelativelyPrimeNumbers_whenCheckingRecursively_shouldReturnFalse() {
+
+ boolean result = recursiveRelativelyPrime(45, 35);
+ assertThat(result).isFalse();
+ }
+
+ @Test
+ public void givenRelativelyPrimeNumbers_whenCheckingRecursively_shouldReturnTrue() {
+
+ boolean result = recursiveRelativelyPrime(500, 501);
+ assertThat(result).isTrue();
+ }
+
+ @Test
+ public void givenNonRelativelyPrimeNumbers_whenCheckingUsingBigIntegers_shouldReturnFalse() {
+
+ boolean result = bigIntegerRelativelyPrime(45, 35);
+ assertThat(result).isFalse();
+ }
+
+ @Test
+ public void givenRelativelyPrimeNumbers_whenCheckingBigIntegers_shouldReturnTrue() {
+
+ boolean result = bigIntegerRelativelyPrime(500, 501);
+ assertThat(result).isTrue();
+ }
+}
diff --git a/algorithms-miscellaneous-2/src/test/java/com/baeldung/algorithms/reversingtree/TreeReverserUnitTest.java b/algorithms-miscellaneous-2/src/test/java/com/baeldung/algorithms/reversingtree/TreeReverserUnitTest.java
new file mode 100644
index 0000000000..44fac57361
--- /dev/null
+++ b/algorithms-miscellaneous-2/src/test/java/com/baeldung/algorithms/reversingtree/TreeReverserUnitTest.java
@@ -0,0 +1,47 @@
+package com.baeldung.algorithms.reversingtree;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import org.junit.jupiter.api.Test;
+
+public class TreeReverserUnitTest {
+
+ @Test
+ public void givenTreeWhenReversingRecursivelyThenReversed() {
+ TreeReverser reverser = new TreeReverser();
+
+ TreeNode treeNode = createBinaryTree();
+
+ reverser.reverseRecursive(treeNode);
+
+ assertEquals("4 7 9 6 2 3 1", reverser.toString(treeNode)
+ .trim());
+ }
+
+ @Test
+ public void givenTreeWhenReversingIterativelyThenReversed() {
+ TreeReverser reverser = new TreeReverser();
+
+ TreeNode treeNode = createBinaryTree();
+
+ reverser.reverseIterative(treeNode);
+
+ assertEquals("4 7 9 6 2 3 1", reverser.toString(treeNode)
+ .trim());
+ }
+
+ private TreeNode createBinaryTree() {
+
+ TreeNode leaf1 = new TreeNode(1);
+ TreeNode leaf2 = new TreeNode(3);
+ TreeNode leaf3 = new TreeNode(6);
+ TreeNode leaf4 = new TreeNode(9);
+
+ TreeNode nodeRight = new TreeNode(7, leaf3, leaf4);
+ TreeNode nodeLeft = new TreeNode(2, leaf1, leaf2);
+
+ TreeNode root = new TreeNode(4, nodeLeft, nodeRight);
+
+ return root;
+ }
+}
diff --git a/algorithms-miscellaneous-2/src/test/resources/graph.png b/algorithms-miscellaneous-2/src/test/resources/graph.png
index 56995b8dd9..7165a51782 100644
Binary files a/algorithms-miscellaneous-2/src/test/resources/graph.png and b/algorithms-miscellaneous-2/src/test/resources/graph.png differ
diff --git a/algorithms-miscellaneous-3/.gitignore b/algorithms-miscellaneous-3/.gitignore
new file mode 100644
index 0000000000..30b2b7442c
--- /dev/null
+++ b/algorithms-miscellaneous-3/.gitignore
@@ -0,0 +1,4 @@
+/target/
+.settings/
+.classpath
+.project
\ No newline at end of file
diff --git a/algorithms-miscellaneous-3/README.md b/algorithms-miscellaneous-3/README.md
new file mode 100644
index 0000000000..71541cd2b3
--- /dev/null
+++ b/algorithms-miscellaneous-3/README.md
@@ -0,0 +1,9 @@
+## Relevant articles:
+
+- [Java Two Pointer Technique](https://www.baeldung.com/java-two-pointer-technique)
+- [Implementing Simple State Machines with Java Enums](https://www.baeldung.com/java-enum-simple-state-machine)
+- [Converting Between Roman and Arabic Numerals in Java](http://www.baeldung.com/java-convert-roman-arabic)
+- [Practical Java Examples of the Big O Notation](http://www.baeldung.com/java-algorithm-complexity)
+- [Checking If a List Is Sorted in Java](https://www.baeldung.com/java-check-if-list-sorted)
+- [Checking if a Java Graph has a Cycle](https://www.baeldung.com/java-graph-has-a-cycle)
+- [A Guide to the Folding Technique](https://www.baeldung.com/folding-hashing-technique)
diff --git a/algorithms-miscellaneous-3/pom.xml b/algorithms-miscellaneous-3/pom.xml
new file mode 100644
index 0000000000..3cebdd09ac
--- /dev/null
+++ b/algorithms-miscellaneous-3/pom.xml
@@ -0,0 +1,52 @@
+
+ 4.0.0
+ algorithms-miscellaneous-3
+ 0.0.1-SNAPSHOT
+ algorithms-miscellaneous-3
+
+
+ com.baeldung
+ parent-modules
+ 1.0.0-SNAPSHOT
+
+
+
+
+ org.assertj
+ assertj-core
+ ${org.assertj.core.version}
+ test
+
+
+
+ org.apache.commons
+ commons-collections4
+ ${commons-collections4.version}
+
+
+
+ com.google.guava
+ guava
+ ${guava.version}
+
+
+
+
+
+
+
+ org.codehaus.mojo
+ exec-maven-plugin
+ ${exec-maven-plugin.version}
+
+
+
+
+
+
+ 3.9.0
+ 4.3
+ 28.0-jre
+
+
\ No newline at end of file
diff --git a/algorithms-miscellaneous-3/src/main/java/com/baeldung/algorithms/checksortedlist/Employee.java b/algorithms-miscellaneous-3/src/main/java/com/baeldung/algorithms/checksortedlist/Employee.java
new file mode 100644
index 0000000000..796932728b
--- /dev/null
+++ b/algorithms-miscellaneous-3/src/main/java/com/baeldung/algorithms/checksortedlist/Employee.java
@@ -0,0 +1,34 @@
+package com.baeldung.algorithms.checksortedlist;
+
+public class Employee {
+
+ long id;
+
+ String name;
+
+ public Employee() {
+ }
+
+ public Employee(long id, String name) {
+ super();
+ this.id = id;
+ this.name = 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;
+ }
+
+}
diff --git a/algorithms-miscellaneous-3/src/main/java/com/baeldung/algorithms/checksortedlist/SortedListChecker.java b/algorithms-miscellaneous-3/src/main/java/com/baeldung/algorithms/checksortedlist/SortedListChecker.java
new file mode 100644
index 0000000000..ab6eb6bc14
--- /dev/null
+++ b/algorithms-miscellaneous-3/src/main/java/com/baeldung/algorithms/checksortedlist/SortedListChecker.java
@@ -0,0 +1,87 @@
+package com.baeldung.algorithms.checksortedlist;
+
+import static org.apache.commons.collections4.CollectionUtils.isEmpty;
+
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.List;
+
+import com.google.common.collect.Comparators;
+import com.google.common.collect.Ordering;;
+
+public class SortedListChecker {
+
+ private SortedListChecker() {
+ throw new AssertionError();
+ }
+
+ public static boolean checkIfSortedUsingIterativeApproach(List listOfStrings) {
+ if (isEmpty(listOfStrings) || listOfStrings.size() == 1) {
+ return true;
+ }
+
+ Iterator iter = listOfStrings.iterator();
+ String current, previous = iter.next();
+ while (iter.hasNext()) {
+ current = iter.next();
+ if (previous.compareTo(current) > 0) {
+ return false;
+ }
+ previous = current;
+ }
+ return true;
+ }
+
+ public static boolean checkIfSortedUsingIterativeApproach(List employees, Comparator employeeComparator) {
+ if (isEmpty(employees) || employees.size() == 1) {
+ return true;
+ }
+
+ Iterator iter = employees.iterator();
+ Employee current, previous = iter.next();
+ while (iter.hasNext()) {
+ current = iter.next();
+ if (employeeComparator.compare(previous, current) > 0) {
+ return false;
+ }
+ previous = current;
+ }
+ return true;
+ }
+
+ public static boolean checkIfSortedUsingRecursion(List listOfStrings) {
+ return isSortedRecursive(listOfStrings, listOfStrings.size());
+ }
+
+ public static boolean isSortedRecursive(List listOfStrings, int index) {
+ if (index < 2) {
+ return true;
+ } else if (listOfStrings.get(index - 2)
+ .compareTo(listOfStrings.get(index - 1)) > 0) {
+ return false;
+ } else {
+ return isSortedRecursive(listOfStrings, index - 1);
+ }
+ }
+
+ public static boolean checkIfSortedUsingOrderingClass(List listOfStrings) {
+ return Ordering. natural()
+ .isOrdered(listOfStrings);
+ }
+
+ public static boolean checkIfSortedUsingOrderingClass(List employees, Comparator employeeComparator) {
+ return Ordering.from(employeeComparator)
+ .isOrdered(employees);
+ }
+
+ public static boolean checkIfSortedUsingOrderingClassHandlingNull(List listOfStrings) {
+ return Ordering. natural()
+ .nullsLast()
+ .isOrdered(listOfStrings);
+ }
+
+ public static boolean checkIfSortedUsingComparators(List listOfStrings) {
+ return Comparators.isInOrder(listOfStrings, Comparator. naturalOrder());
+ }
+
+}
diff --git a/algorithms-miscellaneous-3/src/main/java/com/baeldung/algorithms/enumstatemachine/LeaveRequestState.java b/algorithms-miscellaneous-3/src/main/java/com/baeldung/algorithms/enumstatemachine/LeaveRequestState.java
new file mode 100644
index 0000000000..5153c2e18e
--- /dev/null
+++ b/algorithms-miscellaneous-3/src/main/java/com/baeldung/algorithms/enumstatemachine/LeaveRequestState.java
@@ -0,0 +1,46 @@
+package com.baeldung.algorithms.enumstatemachine;
+
+public enum LeaveRequestState {
+
+ Submitted {
+ @Override
+ public LeaveRequestState nextState() {
+ System.out.println("Starting the Leave Request and sending to Team Leader for approval.");
+ return Escalated;
+ }
+
+ @Override
+ public String responsiblePerson() {
+ return "Employee";
+ }
+ },
+ Escalated {
+ @Override
+ public LeaveRequestState nextState() {
+ System.out.println("Reviewing the Leave Request and escalating to Department Manager.");
+ return Approved;
+ }
+
+ @Override
+ public String responsiblePerson() {
+ return "Team Leader";
+ }
+ },
+ Approved {
+ @Override
+ public LeaveRequestState nextState() {
+ System.out.println("Approving the Leave Request.");
+ return this;
+ }
+
+ @Override
+ public String responsiblePerson() {
+ return "Department Manager";
+ }
+ };
+
+ public abstract String responsiblePerson();
+
+ public abstract LeaveRequestState nextState();
+
+}
diff --git a/algorithms-miscellaneous-3/src/main/java/com/baeldung/algorithms/graphcycledetection/domain/Graph.java b/algorithms-miscellaneous-3/src/main/java/com/baeldung/algorithms/graphcycledetection/domain/Graph.java
new file mode 100644
index 0000000000..c77173b288
--- /dev/null
+++ b/algorithms-miscellaneous-3/src/main/java/com/baeldung/algorithms/graphcycledetection/domain/Graph.java
@@ -0,0 +1,51 @@
+package com.baeldung.algorithms.graphcycledetection.domain;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class Graph {
+
+ private List vertices;
+
+ public Graph() {
+ this.vertices = new ArrayList<>();
+ }
+
+ public Graph(List vertices) {
+ this.vertices = vertices;
+ }
+
+ public void addVertex(Vertex vertex) {
+ this.vertices.add(vertex);
+ }
+
+ public void addEdge(Vertex from, Vertex to) {
+ from.addNeighbour(to);
+ }
+
+ public boolean hasCycle() {
+ for (Vertex vertex : vertices) {
+ if (!vertex.isVisited() && hasCycle(vertex)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public boolean hasCycle(Vertex sourceVertex) {
+ sourceVertex.setBeingVisited(true);
+
+ for (Vertex neighbour : sourceVertex.getAdjacencyList()) {
+ if (neighbour.isBeingVisited()) {
+ // backward edge exists
+ return true;
+ } else if (!neighbour.isVisited() && hasCycle(neighbour)) {
+ return true;
+ }
+ }
+
+ sourceVertex.setBeingVisited(false);
+ sourceVertex.setVisited(true);
+ return false;
+ }
+}
diff --git a/algorithms-miscellaneous-3/src/main/java/com/baeldung/algorithms/graphcycledetection/domain/Vertex.java b/algorithms-miscellaneous-3/src/main/java/com/baeldung/algorithms/graphcycledetection/domain/Vertex.java
new file mode 100644
index 0000000000..398cdf0d9c
--- /dev/null
+++ b/algorithms-miscellaneous-3/src/main/java/com/baeldung/algorithms/graphcycledetection/domain/Vertex.java
@@ -0,0 +1,56 @@
+package com.baeldung.algorithms.graphcycledetection.domain;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class Vertex {
+
+ private String label;
+
+ private boolean visited;
+
+ private boolean beingVisited;
+
+ private List adjacencyList;
+
+ public Vertex(String label) {
+ this.label = label;
+ this.adjacencyList = new ArrayList<>();
+ }
+
+ public String getLabel() {
+ return label;
+ }
+
+ public void setLabel(String label) {
+ this.label = label;
+ }
+
+ public boolean isVisited() {
+ return visited;
+ }
+
+ public void setVisited(boolean visited) {
+ this.visited = visited;
+ }
+
+ public boolean isBeingVisited() {
+ return beingVisited;
+ }
+
+ public void setBeingVisited(boolean beingVisited) {
+ this.beingVisited = beingVisited;
+ }
+
+ public List getAdjacencyList() {
+ return adjacencyList;
+ }
+
+ public void setAdjacencyList(List adjacencyList) {
+ this.adjacencyList = adjacencyList;
+ }
+
+ public void addNeighbour(Vertex adjacent) {
+ this.adjacencyList.add(adjacent);
+ }
+}
diff --git a/algorithms-miscellaneous-2/src/main/java/com/baeldung/algorithms/romannumerals/RomanArabicConverter.java b/algorithms-miscellaneous-3/src/main/java/com/baeldung/algorithms/romannumerals/RomanArabicConverter.java
similarity index 100%
rename from algorithms-miscellaneous-2/src/main/java/com/baeldung/algorithms/romannumerals/RomanArabicConverter.java
rename to algorithms-miscellaneous-3/src/main/java/com/baeldung/algorithms/romannumerals/RomanArabicConverter.java
diff --git a/algorithms-miscellaneous-2/src/main/java/com/baeldung/algorithms/romannumerals/RomanNumeral.java b/algorithms-miscellaneous-3/src/main/java/com/baeldung/algorithms/romannumerals/RomanNumeral.java
similarity index 100%
rename from algorithms-miscellaneous-2/src/main/java/com/baeldung/algorithms/romannumerals/RomanNumeral.java
rename to algorithms-miscellaneous-3/src/main/java/com/baeldung/algorithms/romannumerals/RomanNumeral.java
diff --git a/algorithms-miscellaneous-3/src/main/java/com/baeldung/algorithms/twopointertechnique/LinkedListFindMiddle.java b/algorithms-miscellaneous-3/src/main/java/com/baeldung/algorithms/twopointertechnique/LinkedListFindMiddle.java
new file mode 100644
index 0000000000..a7031f4fba
--- /dev/null
+++ b/algorithms-miscellaneous-3/src/main/java/com/baeldung/algorithms/twopointertechnique/LinkedListFindMiddle.java
@@ -0,0 +1,16 @@
+package com.baeldung.algorithms.twopointertechnique;
+
+public class LinkedListFindMiddle {
+
+ public T findMiddle(MyNode head) {
+ MyNode slowPointer = head;
+ MyNode fastPointer = head;
+
+ while (fastPointer.next != null && fastPointer.next.next != null) {
+ fastPointer = fastPointer.next.next;
+ slowPointer = slowPointer.next;
+ }
+ return slowPointer.data;
+ }
+
+}
diff --git a/algorithms-miscellaneous-3/src/main/java/com/baeldung/algorithms/twopointertechnique/MyNode.java b/algorithms-miscellaneous-3/src/main/java/com/baeldung/algorithms/twopointertechnique/MyNode.java
new file mode 100644
index 0000000000..7d93f03ef9
--- /dev/null
+++ b/algorithms-miscellaneous-3/src/main/java/com/baeldung/algorithms/twopointertechnique/MyNode.java
@@ -0,0 +1,20 @@
+package com.baeldung.algorithms.twopointertechnique;
+
+public class MyNode {
+ MyNode next;
+ E data;
+
+ public MyNode(E value) {
+ data = value;
+ next = null;
+ }
+
+ public MyNode(E value, MyNode n) {
+ data = value;
+ next = n;
+ }
+
+ public void setNext(MyNode n) {
+ next = n;
+ }
+}
diff --git a/algorithms-miscellaneous-3/src/main/java/com/baeldung/algorithms/twopointertechnique/RotateArray.java b/algorithms-miscellaneous-3/src/main/java/com/baeldung/algorithms/twopointertechnique/RotateArray.java
new file mode 100644
index 0000000000..b4e3698c01
--- /dev/null
+++ b/algorithms-miscellaneous-3/src/main/java/com/baeldung/algorithms/twopointertechnique/RotateArray.java
@@ -0,0 +1,22 @@
+package com.baeldung.algorithms.twopointertechnique;
+
+public class RotateArray {
+
+ public void rotate(int[] input, int step) {
+ step %= input.length;
+ reverse(input, 0, input.length - 1);
+ reverse(input, 0, step - 1);
+ reverse(input, step, input.length - 1);
+ }
+
+ private void reverse(int[] input, int start, int end) {
+ while (start < end) {
+ int temp = input[start];
+ input[start] = input[end];
+ input[end] = temp;
+ start++;
+ end--;
+ }
+ }
+
+}
diff --git a/algorithms-miscellaneous-3/src/main/java/com/baeldung/algorithms/twopointertechnique/TwoSum.java b/algorithms-miscellaneous-3/src/main/java/com/baeldung/algorithms/twopointertechnique/TwoSum.java
new file mode 100644
index 0000000000..14eceaa1bd
--- /dev/null
+++ b/algorithms-miscellaneous-3/src/main/java/com/baeldung/algorithms/twopointertechnique/TwoSum.java
@@ -0,0 +1,38 @@
+package com.baeldung.algorithms.twopointertechnique;
+
+public class TwoSum {
+
+ public boolean twoSum(int[] input, int targetValue) {
+
+ int pointerOne = 0;
+ int pointerTwo = input.length - 1;
+
+ while (pointerOne < pointerTwo) {
+ int sum = input[pointerOne] + input[pointerTwo];
+
+ if (sum == targetValue) {
+ return true;
+ } else if (sum < targetValue) {
+ pointerOne++;
+ } else {
+ pointerTwo--;
+ }
+ }
+
+ return false;
+ }
+
+ public boolean twoSumSlow(int[] input, int targetValue) {
+
+ for (int i = 0; i < input.length; i++) {
+ for (int j = 1; j < input.length; j++) {
+ if (input[i] + input[j] == targetValue) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+}
diff --git a/algorithms-miscellaneous-3/src/main/java/com/baeldung/folding/FoldingHash.java b/algorithms-miscellaneous-3/src/main/java/com/baeldung/folding/FoldingHash.java
new file mode 100644
index 0000000000..0ea128c1d9
--- /dev/null
+++ b/algorithms-miscellaneous-3/src/main/java/com/baeldung/folding/FoldingHash.java
@@ -0,0 +1,78 @@
+package com.baeldung.folding;
+
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+
+/**
+ * Calculate a hash value for the strings using the folding technique.
+ *
+ * The implementation serves only to the illustration purposes and is far
+ * from being the most efficient.
+ *
+ * @author A.Shcherbakov
+ *
+ */
+public class FoldingHash {
+
+ /**
+ * Calculate the hash value of a given string.
+ *
+ * @param str Assume it is not null
+ * @param groupSize the group size in the folding technique
+ * @param maxValue defines a max value that the hash may acquire (exclusive)
+ * @return integer value from 0 (inclusive) to maxValue (exclusive)
+ */
+ public int hash(String str, int groupSize, int maxValue) {
+ final int[] codes = this.toAsciiCodes(str);
+ return IntStream.range(0, str.length())
+ .filter(i -> i % groupSize == 0)
+ .mapToObj(i -> extract(codes, i, groupSize))
+ .map(block -> concatenate(block))
+ .reduce(0, (a, b) -> (a + b) % maxValue);
+ }
+
+ /**
+ * Returns a new array of given length whose elements are take from
+ * the original one starting from the offset.
+ *
+ * If the original array has not enough elements, the returning array will contain
+ * element from the offset till the end of the original array.
+ *
+ * @param numbers original array. Assume it is not null.
+ * @param offset index of the element to start from. Assume it is less than the size of the array
+ * @param length max size of the resulting array
+ * @return
+ */
+ public int[] extract(int[] numbers, int offset, int length) {
+ final int defect = numbers.length - (offset + length);
+ final int s = defect < 0 ? length + defect : length;
+ int[] result = new int[s];
+ for (int index = 0; index < s; index++) {
+ result[index] = numbers[index + offset];
+ }
+ return result;
+ }
+
+ /**
+ * Concatenate the numbers into a single number as if they were strings.
+ * Assume that the procedure does not suffer from the overflow.
+ * @param numbers integers to concatenate
+ * @return
+ */
+ public int concatenate(int[] numbers) {
+ final String merged = IntStream.of(numbers)
+ .mapToObj(number -> "" + number)
+ .collect(Collectors.joining());
+ return Integer.parseInt(merged, 10);
+ }
+
+ /**
+ * Convert the string into its characters' ASCII codes.
+ * @param str input string
+ * @return
+ */
+ private int[] toAsciiCodes(String str) {
+ return str.chars()
+ .toArray();
+ }
+}
diff --git a/algorithms-miscellaneous-3/src/main/java/com/baeldung/folding/Main.java b/algorithms-miscellaneous-3/src/main/java/com/baeldung/folding/Main.java
new file mode 100644
index 0000000000..3b055a0dbe
--- /dev/null
+++ b/algorithms-miscellaneous-3/src/main/java/com/baeldung/folding/Main.java
@@ -0,0 +1,17 @@
+package com.baeldung.folding;
+
+/**
+ * Code snippet for article "A Guide to the Folding Technique".
+ *
+ * @author A.Shcherbakov
+ *
+ */
+public class Main {
+
+ public static void main(String... arg) {
+ FoldingHash hasher = new FoldingHash();
+ final String str = "Java language";
+ System.out.println(hasher.hash(str, 2, 100_000));
+ System.out.println(hasher.hash(str, 3, 1_000));
+ }
+}
diff --git a/core-java-10/src/main/resources/logback.xml b/algorithms-miscellaneous-3/src/main/resources/logback.xml
similarity index 100%
rename from core-java-10/src/main/resources/logback.xml
rename to algorithms-miscellaneous-3/src/main/resources/logback.xml
diff --git a/algorithms-miscellaneous-2/src/test/java/com/baeldung/algorithms/analysis/AnalysisRunnerLiveTest.java b/algorithms-miscellaneous-3/src/test/java/com/baeldung/algorithms/analysis/AnalysisRunnerLiveTest.java
similarity index 100%
rename from algorithms-miscellaneous-2/src/test/java/com/baeldung/algorithms/analysis/AnalysisRunnerLiveTest.java
rename to algorithms-miscellaneous-3/src/test/java/com/baeldung/algorithms/analysis/AnalysisRunnerLiveTest.java
diff --git a/algorithms-miscellaneous-3/src/test/java/com/baeldung/algorithms/checksortedlist/SortedListCheckerUnitTest.java b/algorithms-miscellaneous-3/src/test/java/com/baeldung/algorithms/checksortedlist/SortedListCheckerUnitTest.java
new file mode 100644
index 0000000000..44c4388e6c
--- /dev/null
+++ b/algorithms-miscellaneous-3/src/test/java/com/baeldung/algorithms/checksortedlist/SortedListCheckerUnitTest.java
@@ -0,0 +1,106 @@
+package com.baeldung.algorithms.checksortedlist;
+
+import static com.baeldung.algorithms.checksortedlist.SortedListChecker.checkIfSortedUsingComparators;
+import static com.baeldung.algorithms.checksortedlist.SortedListChecker.checkIfSortedUsingIterativeApproach;
+import static com.baeldung.algorithms.checksortedlist.SortedListChecker.checkIfSortedUsingOrderingClass;
+import static com.baeldung.algorithms.checksortedlist.SortedListChecker.checkIfSortedUsingRecursion;
+import static java.util.Arrays.asList;
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+import org.junit.Before;
+import org.junit.Test;
+
+public class SortedListCheckerUnitTest {
+
+ private List sortedListOfString;
+ private List unsortedListOfString;
+ private List singletonList;
+
+ private List employeesSortedByName;
+ private List employeesNotSortedByName;
+
+ @Before
+ public void setUp() {
+ sortedListOfString = asList("Canada", "HK", "LA", "NJ", "NY");
+ unsortedListOfString = asList("LA", "HK", "NJ", "NY", "Canada");
+ singletonList = Collections.singletonList("NY");
+
+ employeesSortedByName = asList(new Employee(1L, "John"), new Employee(2L, "Kevin"), new Employee(3L, "Mike"));
+ employeesNotSortedByName = asList(new Employee(1L, "Kevin"), new Employee(2L, "John"), new Employee(3L, "Mike"));
+ }
+
+ @Test
+ public void givenSortedList_whenUsingIterativeApproach_thenReturnTrue() {
+ assertThat(checkIfSortedUsingIterativeApproach(sortedListOfString)).isTrue();
+ }
+
+ @Test
+ public void givenSingleElementList_whenUsingIterativeApproach_thenReturnTrue() {
+ assertThat(checkIfSortedUsingIterativeApproach(singletonList)).isTrue();
+ }
+
+ @Test
+ public void givenUnsortedList_whenUsingIterativeApproach_thenReturnFalse() {
+ assertThat(checkIfSortedUsingIterativeApproach(unsortedListOfString)).isFalse();
+ }
+
+ @Test
+ public void givenSortedListOfEmployees_whenUsingIterativeApproach_thenReturnTrue() {
+ assertThat(checkIfSortedUsingIterativeApproach(employeesSortedByName, Comparator.comparing(Employee::getName))).isTrue();
+ }
+
+ @Test
+ public void givenUnsortedListOfEmployees_whenUsingIterativeApproach_thenReturnFalse() {
+ assertThat(checkIfSortedUsingIterativeApproach(employeesNotSortedByName, Comparator.comparing(Employee::getName))).isFalse();
+ }
+
+ @Test
+ public void givenSortedList_whenUsingRecursion_thenReturnTrue() {
+ assertThat(checkIfSortedUsingRecursion(sortedListOfString)).isTrue();
+ }
+
+ @Test
+ public void givenSingleElementList_whenUsingRecursion_thenReturnTrue() {
+ assertThat(checkIfSortedUsingRecursion(singletonList)).isTrue();
+ }
+
+ @Test
+ public void givenUnsortedList_whenUsingRecursion_thenReturnFalse() {
+ assertThat(checkIfSortedUsingRecursion(unsortedListOfString)).isFalse();
+ }
+
+ @Test
+ public void givenSortedList_whenUsingGuavaOrdering_thenReturnTrue() {
+ assertThat(checkIfSortedUsingOrderingClass(sortedListOfString)).isTrue();
+ }
+
+ @Test
+ public void givenUnsortedList_whenUsingGuavaOrdering_thenReturnFalse() {
+ assertThat(checkIfSortedUsingOrderingClass(unsortedListOfString)).isFalse();
+ }
+
+ @Test
+ public void givenSortedListOfEmployees_whenUsingGuavaOrdering_thenReturnTrue() {
+ assertThat(checkIfSortedUsingOrderingClass(employeesSortedByName, Comparator.comparing(Employee::getName))).isTrue();
+ }
+
+ @Test
+ public void givenUnsortedListOfEmployees_whenUsingGuavaOrdering_thenReturnFalse() {
+ assertThat(checkIfSortedUsingOrderingClass(employeesNotSortedByName, Comparator.comparing(Employee::getName))).isFalse();
+ }
+
+ @Test
+ public void givenSortedList_whenUsingGuavaComparators_thenReturnTrue() {
+ assertThat(checkIfSortedUsingComparators(sortedListOfString)).isTrue();
+ }
+
+ @Test
+ public void givenUnsortedList_whenUsingGuavaComparators_thenReturnFalse() {
+ assertThat(checkIfSortedUsingComparators(unsortedListOfString)).isFalse();
+ }
+
+}
diff --git a/algorithms-miscellaneous-3/src/test/java/com/baeldung/algorithms/enumstatemachine/LeaveRequestStateUnitTest.java b/algorithms-miscellaneous-3/src/test/java/com/baeldung/algorithms/enumstatemachine/LeaveRequestStateUnitTest.java
new file mode 100644
index 0000000000..61ed6b3aec
--- /dev/null
+++ b/algorithms-miscellaneous-3/src/test/java/com/baeldung/algorithms/enumstatemachine/LeaveRequestStateUnitTest.java
@@ -0,0 +1,37 @@
+package com.baeldung.algorithms.enumstatemachine;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+
+public class LeaveRequestStateUnitTest {
+
+ @Test
+ public void givenLeaveRequest_whenStateEscalated_thenResponsibleIsTeamLeader() {
+ LeaveRequestState state = LeaveRequestState.Escalated;
+
+ assertEquals(state.responsiblePerson(), "Team Leader");
+ }
+
+
+ @Test
+ public void givenLeaveRequest_whenStateApproved_thenResponsibleIsDepartmentManager() {
+ LeaveRequestState state = LeaveRequestState.Approved;
+
+ assertEquals(state.responsiblePerson(), "Department Manager");
+ }
+
+ @Test
+ public void givenLeaveRequest_whenNextStateIsCalled_thenStateIsChanged() {
+ LeaveRequestState state = LeaveRequestState.Submitted;
+
+ state = state.nextState();
+ assertEquals(state, LeaveRequestState.Escalated);
+
+ state = state.nextState();
+ assertEquals(state, LeaveRequestState.Approved);
+
+ state = state.nextState();
+ assertEquals(state, LeaveRequestState.Approved);
+ }
+}
diff --git a/algorithms-miscellaneous-3/src/test/java/com/baeldung/algorithms/graphcycledetection/GraphCycleDetectionUnitTest.java b/algorithms-miscellaneous-3/src/test/java/com/baeldung/algorithms/graphcycledetection/GraphCycleDetectionUnitTest.java
new file mode 100644
index 0000000000..8d464d7b97
--- /dev/null
+++ b/algorithms-miscellaneous-3/src/test/java/com/baeldung/algorithms/graphcycledetection/GraphCycleDetectionUnitTest.java
@@ -0,0 +1,56 @@
+package com.baeldung.algorithms.graphcycledetection;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+
+import com.baeldung.algorithms.graphcycledetection.domain.Graph;
+import com.baeldung.algorithms.graphcycledetection.domain.Vertex;
+
+public class GraphCycleDetectionUnitTest {
+
+ @Test
+ public void givenGraph_whenCycleExists_thenReturnTrue() {
+
+ Vertex vertexA = new Vertex("A");
+ Vertex vertexB = new Vertex("B");
+ Vertex vertexC = new Vertex("C");
+ Vertex vertexD = new Vertex("D");
+
+ Graph graph = new Graph();
+ graph.addVertex(vertexA);
+ graph.addVertex(vertexB);
+ graph.addVertex(vertexC);
+ graph.addVertex(vertexD);
+
+ graph.addEdge(vertexA, vertexB);
+ graph.addEdge(vertexB, vertexC);
+ graph.addEdge(vertexC, vertexA);
+ graph.addEdge(vertexD, vertexC);
+
+ assertTrue(graph.hasCycle());
+ }
+
+ @Test
+ public void givenGraph_whenNoCycleExists_thenReturnFalse() {
+
+ Vertex vertexA = new Vertex("A");
+ Vertex vertexB = new Vertex("B");
+ Vertex vertexC = new Vertex("C");
+ Vertex vertexD = new Vertex("D");
+
+ Graph graph = new Graph();
+ graph.addVertex(vertexA);
+ graph.addVertex(vertexB);
+ graph.addVertex(vertexC);
+ graph.addVertex(vertexD);
+
+ graph.addEdge(vertexA, vertexB);
+ graph.addEdge(vertexB, vertexC);
+ graph.addEdge(vertexA, vertexC);
+ graph.addEdge(vertexD, vertexC);
+
+ assertFalse(graph.hasCycle());
+ }
+}
diff --git a/algorithms-miscellaneous-2/src/test/java/com/baeldung/algorithms/romannumerals/RomanArabicConverterUnitTest.java b/algorithms-miscellaneous-3/src/test/java/com/baeldung/algorithms/romannumerals/RomanArabicConverterUnitTest.java
similarity index 100%
rename from algorithms-miscellaneous-2/src/test/java/com/baeldung/algorithms/romannumerals/RomanArabicConverterUnitTest.java
rename to algorithms-miscellaneous-3/src/test/java/com/baeldung/algorithms/romannumerals/RomanArabicConverterUnitTest.java
diff --git a/algorithms-miscellaneous-3/src/test/java/com/baeldung/algorithms/twopointertechnique/LinkedListFindMiddleUnitTest.java b/algorithms-miscellaneous-3/src/test/java/com/baeldung/algorithms/twopointertechnique/LinkedListFindMiddleUnitTest.java
new file mode 100644
index 0000000000..422a53fa3e
--- /dev/null
+++ b/algorithms-miscellaneous-3/src/test/java/com/baeldung/algorithms/twopointertechnique/LinkedListFindMiddleUnitTest.java
@@ -0,0 +1,37 @@
+package com.baeldung.algorithms.twopointertechnique;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import org.junit.Test;
+
+public class LinkedListFindMiddleUnitTest {
+
+ LinkedListFindMiddle linkedListFindMiddle = new LinkedListFindMiddle();
+
+ @Test
+ public void givenLinkedListOfMyNodes_whenLinkedListFindMiddle_thenCorrect() {
+
+ MyNode head = createNodesList(8);
+
+ assertThat(linkedListFindMiddle.findMiddle(head)).isEqualTo("4");
+
+ head = createNodesList(9);
+
+ assertThat(linkedListFindMiddle.findMiddle(head)).isEqualTo("5");
+ }
+
+ private static MyNode createNodesList(int n) {
+
+ MyNode head = new MyNode("1");
+ MyNode current = head;
+
+ for (int i = 2; i <= n; i++) {
+ MyNode newNode = new MyNode(String.valueOf(i));
+ current.setNext(newNode);
+ current = newNode;
+ }
+
+ return head;
+ }
+
+}
diff --git a/algorithms-miscellaneous-3/src/test/java/com/baeldung/algorithms/twopointertechnique/RotateArrayUnitTest.java b/algorithms-miscellaneous-3/src/test/java/com/baeldung/algorithms/twopointertechnique/RotateArrayUnitTest.java
new file mode 100644
index 0000000000..da227ae751
--- /dev/null
+++ b/algorithms-miscellaneous-3/src/test/java/com/baeldung/algorithms/twopointertechnique/RotateArrayUnitTest.java
@@ -0,0 +1,26 @@
+package com.baeldung.algorithms.twopointertechnique;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import org.junit.Test;
+
+public class RotateArrayUnitTest {
+
+ private RotateArray rotateArray = new RotateArray();
+
+ private int[] inputArray;
+
+ private int step;
+
+ @Test
+ public void givenAnArrayOfIntegers_whenRotateKsteps_thenCorrect() {
+
+ inputArray = new int[] { 1, 2, 3, 4, 5, 6, 7 };
+ step = 4;
+
+ rotateArray.rotate(inputArray, step);
+
+ assertThat(inputArray).containsExactly(new int[] { 4, 5, 6, 7, 1, 2, 3 });
+ }
+
+}
diff --git a/algorithms-miscellaneous-3/src/test/java/com/baeldung/algorithms/twopointertechnique/TwoSumUnitTest.java b/algorithms-miscellaneous-3/src/test/java/com/baeldung/algorithms/twopointertechnique/TwoSumUnitTest.java
new file mode 100644
index 0000000000..aa76f8e1cf
--- /dev/null
+++ b/algorithms-miscellaneous-3/src/test/java/com/baeldung/algorithms/twopointertechnique/TwoSumUnitTest.java
@@ -0,0 +1,56 @@
+package com.baeldung.algorithms.twopointertechnique;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+
+public class TwoSumUnitTest {
+
+ private TwoSum twoSum = new TwoSum();
+
+ private int[] sortedArray;
+
+ private int targetValue;
+
+ @Test
+ public void givenASortedArrayOfIntegers_whenTwoSumSlow_thenPairExists() {
+
+ sortedArray = new int[] { 0, 1, 2, 3, 4, 5, 5, 6, 7, 8, 9, 9 };
+
+ targetValue = 12;
+
+ assertTrue(twoSum.twoSumSlow(sortedArray, targetValue));
+ }
+
+ @Test
+ public void givenASortedArrayOfIntegers_whenTwoSumSlow_thenPairDoesNotExists() {
+
+ sortedArray = new int[] { 0, 1, 2, 3, 4, 5, 5, 6, 7, 8, 9, 9 };
+
+ targetValue = 20;
+
+ assertFalse(twoSum.twoSumSlow(sortedArray, targetValue));
+ }
+
+ @Test
+ public void givenASortedArrayOfIntegers_whenTwoSum_thenPairExists() {
+
+ sortedArray = new int[] { 0, 1, 2, 3, 4, 5, 5, 6, 7, 8, 9, 9 };
+
+ targetValue = 12;
+
+ assertTrue(twoSum.twoSum(sortedArray, targetValue));
+ }
+
+ @Test
+ public void givenASortedArrayOfIntegers_whenTwoSum_thenPairDoesNotExists() {
+
+ sortedArray = new int[] { 0, 1, 2, 3, 4, 5, 5, 6, 7, 8, 9, 9 };
+
+ targetValue = 20;
+
+ assertFalse(twoSum.twoSum(sortedArray, targetValue));
+ }
+
+}
diff --git a/algorithms-miscellaneous-3/src/test/java/com/baeldung/folding/FoldingHashUnitTest.java b/algorithms-miscellaneous-3/src/test/java/com/baeldung/folding/FoldingHashUnitTest.java
new file mode 100644
index 0000000000..43e33d8378
--- /dev/null
+++ b/algorithms-miscellaneous-3/src/test/java/com/baeldung/folding/FoldingHashUnitTest.java
@@ -0,0 +1,54 @@
+package com.baeldung.folding;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+
+public class FoldingHashUnitTest {
+
+ @Test
+ public void givenStringJavaLanguage_whenSize2Capacity100000_then48933() throws Exception {
+ final FoldingHash hasher = new FoldingHash();
+ final int value = hasher.hash("Java language", 2, 100_000);
+ assertEquals(value, 48933);
+ }
+
+ @Test
+ public void givenStringVaJaLanguage_whenSize2Capacity100000_thenSameAsJavaLanguage() throws Exception {
+ final FoldingHash hasher = new FoldingHash();
+ final int java = hasher.hash("Java language", 2, 100_000);
+ final int vaja = hasher.hash("vaJa language", 2, 100_000);
+ assertTrue(java == vaja);
+ }
+
+ @Test
+ public void givenSingleElementArray_whenOffset0Size2_thenSingleElement() throws Exception {
+ final FoldingHash hasher = new FoldingHash();
+ final int[] value = hasher.extract(new int[] { 5 }, 0, 2);
+ assertArrayEquals(new int[] { 5 }, value);
+ }
+
+ @Test
+ public void givenFiveElementArray_whenOffset0Size3_thenFirstThreeElements() throws Exception {
+ final FoldingHash hasher = new FoldingHash();
+ final int[] value = hasher.extract(new int[] { 1, 2, 3, 4, 5 }, 0, 3);
+ assertArrayEquals(new int[] { 1, 2, 3 }, value);
+ }
+
+ @Test
+ public void givenFiveElementArray_whenOffset1Size2_thenTwoElements() throws Exception {
+ final FoldingHash hasher = new FoldingHash();
+ final int[] value = hasher.extract(new int[] { 1, 2, 3, 4, 5 }, 1, 2);
+ assertArrayEquals(new int[] { 2, 3 }, value);
+ }
+
+ @Test
+ public void givenFiveElementArray_whenOffset2SizeTooBig_thenElementsToTheEnd() throws Exception {
+ final FoldingHash hasher = new FoldingHash();
+ final int[] value = hasher.extract(new int[] { 1, 2, 3, 4, 5 }, 2, 2000);
+ assertArrayEquals(new int[] { 3, 4, 5 }, value);
+ }
+
+}
diff --git a/algorithms-sorting/pom.xml b/algorithms-sorting/pom.xml
index 2aee6e9199..b25adf05a8 100644
--- a/algorithms-sorting/pom.xml
+++ b/algorithms-sorting/pom.xml
@@ -49,7 +49,6 @@
- 1.16.123.6.13.9.01.11
diff --git a/animal-sniffer-mvn-plugin/pom.xml b/animal-sniffer-mvn-plugin/pom.xml
index cdfb1fb2a3..55e37e2ec4 100644
--- a/animal-sniffer-mvn-plugin/pom.xml
+++ b/animal-sniffer-mvn-plugin/pom.xml
@@ -3,9 +3,9 @@
4.0.0com.baeldunganimal-sniffer-mvn-plugin
- jar1.0-SNAPSHOTanimal-sniffer-mvn-plugin
+ jarhttp://maven.apache.org
diff --git a/annotations/pom.xml b/annotations/pom.xml
index 6d83f5b057..5fe89adf0a 100644
--- a/annotations/pom.xml
+++ b/annotations/pom.xml
@@ -3,8 +3,8 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0annotations
- pomannotations
+ pomparent-modules
diff --git a/antlr/pom.xml b/antlr/pom.xml
index ac66891598..91b939a882 100644
--- a/antlr/pom.xml
+++ b/antlr/pom.xml
@@ -10,6 +10,14 @@
1.0.0-SNAPSHOT
+
+
+ org.antlr
+ antlr4-runtime
+ ${antlr.version}
+
+
+
@@ -44,13 +52,7 @@
-
-
- org.antlr
- antlr4-runtime
- ${antlr.version}
-
-
+
4.7.13.0.0
diff --git a/apache-avro/pom.xml b/apache-avro/pom.xml
index 18f9c34d64..e6fb4d24ff 100644
--- a/apache-avro/pom.xml
+++ b/apache-avro/pom.xml
@@ -7,14 +7,6 @@
0.0.1-SNAPSHOTapache-avro
-
- UTF-8
- 3.5
- 1.8.2
- 1.8
- 1.7.25
-
-
com.baeldungparent-modules
@@ -25,7 +17,7 @@
junitjunit
- 4.10
+ ${junit.version}test
@@ -85,4 +77,12 @@
+
+
+ UTF-8
+ 3.5
+ 1.8.2
+ 1.7.25
+
+
diff --git a/apache-curator/pom.xml b/apache-curator/pom.xml
index bcca38b199..259319d547 100644
--- a/apache-curator/pom.xml
+++ b/apache-curator/pom.xml
@@ -3,8 +3,8 @@
4.0.0apache-curator0.0.1-SNAPSHOT
- jarapache-curator
+ jarcom.baeldung
@@ -39,7 +39,7 @@
com.fasterxml.jackson.corejackson-databind
- ${jackson-databind.version}
+ ${jackson.version}
@@ -59,7 +59,6 @@
4.0.13.4.11
- 2.9.43.6.11.7.0
diff --git a/apache-cxf/sse-jaxrs/sse-jaxrs-client/pom.xml b/apache-cxf/sse-jaxrs/sse-jaxrs-client/pom.xml
index c7acf22c32..be2138e172 100644
--- a/apache-cxf/sse-jaxrs/sse-jaxrs-client/pom.xml
+++ b/apache-cxf/sse-jaxrs/sse-jaxrs-client/pom.xml
@@ -12,9 +12,18 @@
0.0.1-SNAPSHOT
-
- 3.2.0
-
+
+
+ org.apache.cxf
+ cxf-rt-rs-client
+ ${cxf-version}
+
+
+ org.apache.cxf
+ cxf-rt-rs-sse
+ ${cxf-version}
+
+
@@ -45,17 +54,8 @@
-
-
- org.apache.cxf
- cxf-rt-rs-client
- ${cxf-version}
-
-
- org.apache.cxf
- cxf-rt-rs-sse
- ${cxf-version}
-
-
+
+ 3.2.0
+
diff --git a/apache-cxf/sse-jaxrs/sse-jaxrs-server/pom.xml b/apache-cxf/sse-jaxrs/sse-jaxrs-server/pom.xml
index eeb5726ee1..43bbcf1ef4 100644
--- a/apache-cxf/sse-jaxrs/sse-jaxrs-server/pom.xml
+++ b/apache-cxf/sse-jaxrs/sse-jaxrs-server/pom.xml
@@ -13,11 +13,28 @@
0.0.1-SNAPSHOT
-
- 2.4.2
- false
- 18.0.0.2
-
+
+
+
+ javax.ws.rs
+ javax.ws.rs-api
+ 2.1
+ provided
+
+
+ javax.enterprise
+ cdi-api
+ 2.0
+ provided
+
+
+ javax.json.bind
+ javax.json.bind-api
+ 1.0
+ provided
+
+
+ ${project.artifactId}
@@ -59,27 +76,10 @@
-
-
-
- javax.ws.rs
- javax.ws.rs-api
- 2.1
- provided
-
-
- javax.enterprise
- cdi-api
- 2.0
- provided
-
-
- javax.json.bind
- javax.json.bind-api
- 1.0
- provided
-
-
-
+
+ 2.4.2
+ false
+ 18.0.0.2
+
diff --git a/apache-fop/README.md b/apache-fop/README.md
index 772681ad57..1e734a5f36 100644
--- a/apache-fop/README.md
+++ b/apache-fop/README.md
@@ -3,7 +3,3 @@
## Core Java Cookbooks and Examples
### Relevant Articles:
-- [Immutable ArrayList in Java](http://www.baeldung.com/java-immutable-list)
-- [Java - Reading a Large File Efficiently](http://www.baeldung.com/java-read-lines-large-file)
-- [Java InputStream to String](http://www.baeldung.com/convert-input-stream-to-string)
-
diff --git a/apache-geode/pom.xml b/apache-geode/pom.xml
index 738accdcb8..15c7e04d29 100644
--- a/apache-geode/pom.xml
+++ b/apache-geode/pom.xml
@@ -12,22 +12,6 @@
parent-modules1.0.0-SNAPSHOT
-
-
- 1.6.0
-
-
-
-
- org.apache.maven.plugins
- maven-compiler-plugin
-
- 1.8
- 1.8
-
-
-
-
@@ -38,8 +22,24 @@
junitjunit
- RELEASE
+ ${junit.version}
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+ ${java.version}
+ ${java.version}
+
+
+
+
+
+
+ 1.6.0
+
\ No newline at end of file
diff --git a/apache-geode/src/test/java/com/baeldung/geode/GeodeSamplesIntegrationTest.java b/apache-geode/src/test/java/com/baeldung/geode/GeodeSamplesLiveTest.java
similarity index 98%
rename from apache-geode/src/test/java/com/baeldung/geode/GeodeSamplesIntegrationTest.java
rename to apache-geode/src/test/java/com/baeldung/geode/GeodeSamplesLiveTest.java
index b96d2c9b6a..359568db98 100644
--- a/apache-geode/src/test/java/com/baeldung/geode/GeodeSamplesIntegrationTest.java
+++ b/apache-geode/src/test/java/com/baeldung/geode/GeodeSamplesLiveTest.java
@@ -21,7 +21,7 @@ import java.util.stream.Stream;
import static org.junit.Assert.assertEquals;
-public class GeodeSamplesIntegrationTest {
+public class GeodeSamplesLiveTest {
ClientCache cache = null;
Region region = null;
diff --git a/apache-meecrowave/pom.xml b/apache-meecrowave/pom.xml
index cf13aa1c1b..4eb1094f94 100644
--- a/apache-meecrowave/pom.xml
+++ b/apache-meecrowave/pom.xml
@@ -6,52 +6,64 @@
0.0.1apache-meecrowaveA sample REST API application with Meecrowave
+
+
+ com.baeldung
+ parent-modules
+ 1.0.0-SNAPSHOT
+
-
- 1.8
- 1.8
- org.apache.meecrowavemeecrowave-core
- 1.2.1
+ ${meecrowave-core.version}org.apache.meecrowavemeecrowave-jpa
- 1.2.1
+ ${meecrowave-jpa.version}com.squareup.okhttp3okhttp
- 3.10.0
+ ${okhttp.version}org.apache.meecrowavemeecrowave-junit
- 1.2.0
+ ${meecrowave-junit.version}testjunitjunit
- 4.10
+ ${junit.version}test
-
+
org.apache.meecrowavemeecrowave-maven-plugin
- 1.2.1
+ ${meecrowave-maven-plugin.version}
+
+
+ 1.8
+ 1.8
+ 1.2.0
+ 3.10.0
+ 1.2.1
+ 1.2.1
+ 1.2.1
+
\ No newline at end of file
diff --git a/apache-meecrowave/src/test/java/com/baeldung/meecrowave/ArticleEndpointsTest.java b/apache-meecrowave/src/test/java/com/baeldung/meecrowave/ArticleEndpointsUnitTest.java
similarity index 96%
rename from apache-meecrowave/src/test/java/com/baeldung/meecrowave/ArticleEndpointsTest.java
rename to apache-meecrowave/src/test/java/com/baeldung/meecrowave/ArticleEndpointsUnitTest.java
index 0dc9773490..f9a06fd7b9 100644
--- a/apache-meecrowave/src/test/java/com/baeldung/meecrowave/ArticleEndpointsTest.java
+++ b/apache-meecrowave/src/test/java/com/baeldung/meecrowave/ArticleEndpointsUnitTest.java
@@ -17,7 +17,7 @@ import okhttp3.Request;
import okhttp3.Response;
@RunWith(MonoMeecrowave.Runner.class)
-public class ArticleEndpointsTest {
+public class ArticleEndpointsUnitTest {
@ConfigurationInject
private Meecrowave.Builder config;
diff --git a/apache-olingo/README.md b/apache-olingo/README.md
new file mode 100644
index 0000000000..bfbdc97700
--- /dev/null
+++ b/apache-olingo/README.md
@@ -0,0 +1,3 @@
+## Relevant articles:
+
+- [OData Protocol Guide](https://www.baeldung.com/odata)
diff --git a/apache-olingo/Samples.md b/apache-olingo/Samples.md
new file mode 100644
index 0000000000..def8971d64
--- /dev/null
+++ b/apache-olingo/Samples.md
@@ -0,0 +1,21 @@
+## OData test URLs
+
+This following table contains test URLs that can be used with the Olingo V2 demo project.
+
+| URL | Description |
+|------------------------------------------|-------------------------------------------------|
+| `http://localhost:8180/odata/$metadata` | fetch OData metadata document |
+| `http://localhost:8180/odata/CarMakers?$top=10&$skip=10` | Get 10 entities starting at offset 10 |
+| `http://localhost:8180/odata/CarMakers?$count` | Return total count of entities in this set |
+| `http://localhost:8180/odata/CarMakers?$filter=startswith(Name,'B')` | Return entities where the *Name* property starts with 'B' |
+| `http://localhost:8180/odata/CarModels?$filter=Year eq 2008 and CarMakerDetails/Name eq 'BWM'` | Return *CarModel* entities where the *Name* property of its maker starts with 'B' |
+| `http://localhost:8180/odata/CarModels(1L)?$expand=CarMakerDetails` | Return the *CarModel* with primary key '1', along with its maker|
+| `http://localhost:8180/odata/CarModels(1L)?$select=Name,Sku` | Return the *CarModel* with primary key '1', returing only its *Name* and *Sku* properties |
+| `http://localhost:8180/odata/CarModels?$orderBy=Name asc,Sku desc` | Return *CarModel* entities, ordered by the their *Name* and *Sku* properties |
+| `http://localhost:8180/odata/CarModels?$format=json` | Return *CarModel* entities, using a JSON representation|
+
+
+
+
+
+
diff --git a/apache-olingo/olingo2/.gitignore b/apache-olingo/olingo2/.gitignore
new file mode 100644
index 0000000000..153c9335eb
--- /dev/null
+++ b/apache-olingo/olingo2/.gitignore
@@ -0,0 +1,29 @@
+HELP.md
+/target/
+!.mvn/wrapper/maven-wrapper.jar
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+/build/
+
+### VS Code ###
+.vscode/
diff --git a/apache-olingo/olingo2/pom.xml b/apache-olingo/olingo2/pom.xml
new file mode 100644
index 0000000000..320f56b717
--- /dev/null
+++ b/apache-olingo/olingo2/pom.xml
@@ -0,0 +1,89 @@
+
+
+ 4.0.0
+ org.baeldung.examples.olingo2
+ olingo2-sample
+ 0.0.1-SNAPSHOT
+ olingo2-sample
+ Sample Olingo 2 Project
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.1.3.RELEASE
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-jersey
+
+
+ org.springframework.boot
+ spring-boot-starter-data-jpa
+
+
+ com.h2database
+ h2
+ runtime
+
+
+ org.springframework.boot
+ spring-boot-configuration-processor
+ true
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+
+ org.apache.olingo
+ olingo-odata2-core
+ ${olingo2.version}
+
+
+
+ javax.ws.rs
+ javax.ws.rs-api
+
+
+
+
+ org.apache.olingo
+ olingo-odata2-jpa-processor-core
+ ${olingo2.version}
+
+
+ org.apache.olingo
+ olingo-odata2-jpa-processor-ref
+ ${olingo2.version}
+
+
+ org.eclipse.persistence
+ eclipselink
+
+
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
+ 1.8
+ 2.0.11
+
+
+
diff --git a/apache-olingo/olingo2/src/main/java/org/baeldung/examples/olingo2/CarsODataJPAServiceFactory.java b/apache-olingo/olingo2/src/main/java/org/baeldung/examples/olingo2/CarsODataJPAServiceFactory.java
new file mode 100644
index 0000000000..65a0428154
--- /dev/null
+++ b/apache-olingo/olingo2/src/main/java/org/baeldung/examples/olingo2/CarsODataJPAServiceFactory.java
@@ -0,0 +1,298 @@
+package org.baeldung.examples.olingo2;
+
+import java.util.List;
+import java.util.Map;
+
+import javax.persistence.EntityGraph;
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+import javax.persistence.EntityTransaction;
+import javax.persistence.FlushModeType;
+import javax.persistence.LockModeType;
+import javax.persistence.Persistence;
+import javax.persistence.Query;
+import javax.persistence.StoredProcedureQuery;
+import javax.persistence.SynchronizationType;
+import javax.persistence.TypedQuery;
+import javax.persistence.criteria.CriteriaBuilder;
+import javax.persistence.criteria.CriteriaDelete;
+import javax.persistence.criteria.CriteriaQuery;
+import javax.persistence.criteria.CriteriaUpdate;
+import javax.persistence.metamodel.Metamodel;
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.olingo.odata2.api.processor.ODataContext;
+import org.apache.olingo.odata2.jpa.processor.api.ODataJPAContext;
+import org.apache.olingo.odata2.jpa.processor.api.ODataJPAServiceFactory;
+import org.apache.olingo.odata2.jpa.processor.api.exception.ODataJPARuntimeException;
+import org.baeldung.examples.olingo2.JerseyConfig.EntityManagerFilter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.orm.jpa.EntityManagerFactoryUtils;
+import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
+import org.springframework.stereotype.Component;
+
+/**
+ * ODataJPAServiceFactory implementation for our sample domain
+ * @author Philippe
+ *
+ */
+@Component
+public class CarsODataJPAServiceFactory extends ODataJPAServiceFactory {
+
+ private static final Logger log = LoggerFactory.getLogger(CarsODataJPAServiceFactory.class);
+
+ public CarsODataJPAServiceFactory() {
+ // Enable detailed error messages (useful for debugging)
+ setDetailErrors(true);
+ }
+
+ /**
+ * This method will be called by Olingo on every request to
+ * initialize the ODataJPAContext that will be used.
+ */
+ @Override
+ public ODataJPAContext initializeODataJPAContext() throws ODataJPARuntimeException {
+
+ log.info("[I32] >>> initializeODataJPAContext()");
+ ODataJPAContext ctx = getODataJPAContext();
+ ODataContext octx = ctx.getODataContext();
+ HttpServletRequest request = (HttpServletRequest)octx.getParameter(ODataContext.HTTP_SERVLET_REQUEST_OBJECT);
+ EntityManager em = (EntityManager)request.getAttribute(EntityManagerFilter.EM_REQUEST_ATTRIBUTE);
+
+ // Here we're passing the EM that was created by the EntityManagerFilter (see JerseyConfig)
+ ctx.setEntityManager(new EntityManagerWrapper(em));
+ ctx.setPersistenceUnitName("default");
+
+ // We're managing the EM's lifecycle, so we must inform Olingo that it should not
+ // try to manage transactions and/or persistence sessions
+ ctx.setContainerManaged(true);
+ return ctx;
+ }
+
+ static class EntityManagerWrapper implements EntityManager {
+
+ private EntityManager delegate;
+
+ public void persist(Object entity) {
+ log.info("[I68] persist: entity.class=" + entity.getClass()
+ .getSimpleName());
+ delegate.persist(entity);
+ // delegate.flush();
+ }
+
+ public T merge(T entity) {
+ log.info("[I74] merge: entity.class=" + entity.getClass()
+ .getSimpleName());
+ return delegate.merge(entity);
+ }
+
+ public void remove(Object entity) {
+ log.info("[I78] remove: entity.class=" + entity.getClass()
+ .getSimpleName());
+ delegate.remove(entity);
+ }
+
+ public T find(Class entityClass, Object primaryKey) {
+ return delegate.find(entityClass, primaryKey);
+ }
+
+ public T find(Class entityClass, Object primaryKey, Map properties) {
+ return delegate.find(entityClass, primaryKey, properties);
+ }
+
+ public T find(Class entityClass, Object primaryKey, LockModeType lockMode) {
+ return delegate.find(entityClass, primaryKey, lockMode);
+ }
+
+ public T find(Class entityClass, Object primaryKey, LockModeType lockMode, Map properties) {
+ return delegate.find(entityClass, primaryKey, lockMode, properties);
+ }
+
+ public T getReference(Class entityClass, Object primaryKey) {
+ return delegate.getReference(entityClass, primaryKey);
+ }
+
+ public void flush() {
+ delegate.flush();
+ }
+
+ public void setFlushMode(FlushModeType flushMode) {
+ delegate.setFlushMode(flushMode);
+ }
+
+ public FlushModeType getFlushMode() {
+ return delegate.getFlushMode();
+ }
+
+ public void lock(Object entity, LockModeType lockMode) {
+ delegate.lock(entity, lockMode);
+ }
+
+ public void lock(Object entity, LockModeType lockMode, Map properties) {
+ delegate.lock(entity, lockMode, properties);
+ }
+
+ public void refresh(Object entity) {
+ delegate.refresh(entity);
+ }
+
+ public void refresh(Object entity, Map properties) {
+ delegate.refresh(entity, properties);
+ }
+
+ public void refresh(Object entity, LockModeType lockMode) {
+ delegate.refresh(entity, lockMode);
+ }
+
+ public void refresh(Object entity, LockModeType lockMode, Map properties) {
+ delegate.refresh(entity, lockMode, properties);
+ }
+
+ public void clear() {
+ delegate.clear();
+ }
+
+ public void detach(Object entity) {
+ delegate.detach(entity);
+ }
+
+ public boolean contains(Object entity) {
+ return delegate.contains(entity);
+ }
+
+ public LockModeType getLockMode(Object entity) {
+ return delegate.getLockMode(entity);
+ }
+
+ public void setProperty(String propertyName, Object value) {
+ delegate.setProperty(propertyName, value);
+ }
+
+ public Map getProperties() {
+ return delegate.getProperties();
+ }
+
+ public Query createQuery(String qlString) {
+ return delegate.createQuery(qlString);
+ }
+
+ public TypedQuery createQuery(CriteriaQuery criteriaQuery) {
+ return delegate.createQuery(criteriaQuery);
+ }
+
+ public Query createQuery(CriteriaUpdate updateQuery) {
+ return delegate.createQuery(updateQuery);
+ }
+
+ public Query createQuery(CriteriaDelete deleteQuery) {
+ return delegate.createQuery(deleteQuery);
+ }
+
+ public TypedQuery createQuery(String qlString, Class resultClass) {
+ return delegate.createQuery(qlString, resultClass);
+ }
+
+ public Query createNamedQuery(String name) {
+ return delegate.createNamedQuery(name);
+ }
+
+ public TypedQuery createNamedQuery(String name, Class resultClass) {
+ return delegate.createNamedQuery(name, resultClass);
+ }
+
+ public Query createNativeQuery(String sqlString) {
+ return delegate.createNativeQuery(sqlString);
+ }
+
+ public Query createNativeQuery(String sqlString, Class resultClass) {
+ return delegate.createNativeQuery(sqlString, resultClass);
+ }
+
+ public Query createNativeQuery(String sqlString, String resultSetMapping) {
+ return delegate.createNativeQuery(sqlString, resultSetMapping);
+ }
+
+ public StoredProcedureQuery createNamedStoredProcedureQuery(String name) {
+ return delegate.createNamedStoredProcedureQuery(name);
+ }
+
+ public StoredProcedureQuery createStoredProcedureQuery(String procedureName) {
+ return delegate.createStoredProcedureQuery(procedureName);
+ }
+
+ public StoredProcedureQuery createStoredProcedureQuery(String procedureName, Class... resultClasses) {
+ return delegate.createStoredProcedureQuery(procedureName, resultClasses);
+ }
+
+ public StoredProcedureQuery createStoredProcedureQuery(String procedureName, String... resultSetMappings) {
+ return delegate.createStoredProcedureQuery(procedureName, resultSetMappings);
+ }
+
+ public void joinTransaction() {
+ delegate.joinTransaction();
+ }
+
+ public boolean isJoinedToTransaction() {
+ return delegate.isJoinedToTransaction();
+ }
+
+ public T unwrap(Class cls) {
+ return delegate.unwrap(cls);
+ }
+
+ public Object getDelegate() {
+ return delegate.getDelegate();
+ }
+
+ public void close() {
+ log.info("[I229] close");
+ delegate.close();
+ }
+
+ public boolean isOpen() {
+ boolean isOpen = delegate.isOpen();
+ log.info("[I236] isOpen: " + isOpen);
+ return isOpen;
+ }
+
+ public EntityTransaction getTransaction() {
+ log.info("[I240] getTransaction()");
+ return delegate.getTransaction();
+ }
+
+ public EntityManagerFactory getEntityManagerFactory() {
+ return delegate.getEntityManagerFactory();
+ }
+
+ public CriteriaBuilder getCriteriaBuilder() {
+ return delegate.getCriteriaBuilder();
+ }
+
+ public Metamodel getMetamodel() {
+ return delegate.getMetamodel();
+ }
+
+ public EntityGraph createEntityGraph(Class rootType) {
+ return delegate.createEntityGraph(rootType);
+ }
+
+ public EntityGraph> createEntityGraph(String graphName) {
+ return delegate.createEntityGraph(graphName);
+ }
+
+ public EntityGraph> getEntityGraph(String graphName) {
+ return delegate.getEntityGraph(graphName);
+ }
+
+ public List> getEntityGraphs(Class entityClass) {
+ return delegate.getEntityGraphs(entityClass);
+ }
+
+ public EntityManagerWrapper(EntityManager delegate) {
+ this.delegate = delegate;
+ }
+
+ }
+
+}
diff --git a/apache-olingo/olingo2/src/main/java/org/baeldung/examples/olingo2/JerseyConfig.java b/apache-olingo/olingo2/src/main/java/org/baeldung/examples/olingo2/JerseyConfig.java
new file mode 100644
index 0000000000..78caf99861
--- /dev/null
+++ b/apache-olingo/olingo2/src/main/java/org/baeldung/examples/olingo2/JerseyConfig.java
@@ -0,0 +1,125 @@
+ package org.baeldung.examples.olingo2;
+
+import java.io.IOException;
+
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+import javax.persistence.EntityTransaction;
+import javax.servlet.ServletContext;
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.ApplicationPath;
+import javax.ws.rs.Path;
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.container.ContainerRequestFilter;
+import javax.ws.rs.container.ContainerResponseContext;
+import javax.ws.rs.container.ContainerResponseFilter;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.ext.Provider;
+
+import org.apache.olingo.odata2.api.ODataServiceFactory;
+import org.apache.olingo.odata2.core.rest.ODataRootLocator;
+import org.apache.olingo.odata2.core.rest.app.ODataApplication;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+
+/**
+ * Jersey JAX-RS configuration
+ * @author Philippe
+ *
+ */
+@Component
+@ApplicationPath("/odata")
+public class JerseyConfig extends ResourceConfig {
+
+
+ public JerseyConfig(CarsODataJPAServiceFactory serviceFactory, EntityManagerFactory emf) {
+
+ ODataApplication app = new ODataApplication();
+
+ app
+ .getClasses()
+ .forEach( c -> {
+ // Avoid using the default RootLocator, as we want
+ // a Spring Managed one
+ if ( !ODataRootLocator.class.isAssignableFrom(c)) {
+ register(c);
+ }
+ });
+
+ register(new CarsRootLocator(serviceFactory));
+ register( new EntityManagerFilter(emf));
+ }
+
+ /**
+ * This filter handles the EntityManager transaction lifecycle.
+ * @author Philippe
+ *
+ */
+ @Provider
+ public static class EntityManagerFilter implements ContainerRequestFilter, ContainerResponseFilter {
+
+ private static final Logger log = LoggerFactory.getLogger(EntityManagerFilter.class);
+ public static final String EM_REQUEST_ATTRIBUTE = EntityManagerFilter.class.getName() + "_ENTITY_MANAGER";
+
+ private final EntityManagerFactory emf;
+
+ @Context
+ private HttpServletRequest httpRequest;
+
+ public EntityManagerFilter(EntityManagerFactory emf) {
+ this.emf = emf;
+ }
+
+ @Override
+ public void filter(ContainerRequestContext ctx) throws IOException {
+ log.info("[I60] >>> filter");
+ EntityManager em = this.emf.createEntityManager();
+ httpRequest.setAttribute(EM_REQUEST_ATTRIBUTE, em);
+
+ // Start a new transaction unless we have a simple GET
+ if (!"GET".equalsIgnoreCase(ctx.getMethod())) {
+ em.getTransaction()
+ .begin();
+ }
+ }
+
+ @Override
+ public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException {
+
+ log.info("[I68] <<< filter");
+ EntityManager em = (EntityManager) httpRequest.getAttribute(EM_REQUEST_ATTRIBUTE);
+
+ if (!"GET".equalsIgnoreCase(requestContext.getMethod())) {
+ EntityTransaction t = em.getTransaction();
+ if (t.isActive()) {
+ if (!t.getRollbackOnly()) {
+ t.commit();
+ }
+ }
+ }
+
+ em.close();
+
+ }
+
+ }
+
+ @Path("/")
+ public static class CarsRootLocator extends ODataRootLocator {
+
+ private CarsODataJPAServiceFactory serviceFactory;
+
+ public CarsRootLocator(CarsODataJPAServiceFactory serviceFactory) {
+ this.serviceFactory = serviceFactory;
+ }
+
+ @Override
+ public ODataServiceFactory getServiceFactory() {
+ return this.serviceFactory;
+ }
+
+ }
+
+}
diff --git a/apache-olingo/olingo2/src/main/java/org/baeldung/examples/olingo2/Olingo2SampleApplication.java b/apache-olingo/olingo2/src/main/java/org/baeldung/examples/olingo2/Olingo2SampleApplication.java
new file mode 100644
index 0000000000..fa58612088
--- /dev/null
+++ b/apache-olingo/olingo2/src/main/java/org/baeldung/examples/olingo2/Olingo2SampleApplication.java
@@ -0,0 +1,14 @@
+package org.baeldung.examples.olingo2;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.builder.SpringApplicationBuilder;
+import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
+
+@SpringBootApplication
+public class Olingo2SampleApplication extends SpringBootServletInitializer {
+
+ public static void main(String[] args) {
+ SpringApplication.run(Olingo2SampleApplication.class);
+ }
+}
diff --git a/apache-olingo/olingo2/src/main/java/org/baeldung/examples/olingo2/domain/CarMaker.java b/apache-olingo/olingo2/src/main/java/org/baeldung/examples/olingo2/domain/CarMaker.java
new file mode 100644
index 0000000000..e66d266062
--- /dev/null
+++ b/apache-olingo/olingo2/src/main/java/org/baeldung/examples/olingo2/domain/CarMaker.java
@@ -0,0 +1,115 @@
+package org.baeldung.examples.olingo2.domain;
+
+import java.util.List;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.OneToMany;
+import javax.persistence.Table;
+import javax.validation.constraints.NotNull;
+
+@Entity
+@Table(name = "car_maker")
+public class CarMaker {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ private Long id;
+
+ @NotNull
+ @Column(name = "name")
+ private String name;
+
+ @OneToMany(mappedBy = "maker", orphanRemoval = true, cascade = CascadeType.ALL)
+ private List models;
+
+ /**
+ * @return the id
+ */
+ public Long getId() {
+ return id;
+ }
+
+ /**
+ * @param id the id to set
+ */
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ /**
+ * @return the name
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * @param name the name to set
+ */
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ /**
+ * @return the models
+ */
+ public List getModels() {
+ return models;
+ }
+
+ /**
+ * @param models the models to set
+ */
+ public void setModels(List models) {
+ this.models = models;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#hashCode()
+ */
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((id == null) ? 0 : id.hashCode());
+ result = prime * result + ((models == null) ? 0 : models.hashCode());
+ result = prime * result + ((name == null) ? 0 : name.hashCode());
+ return result;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ CarMaker other = (CarMaker) obj;
+ if (id == null) {
+ if (other.id != null)
+ return false;
+ } else if (!id.equals(other.id))
+ return false;
+ if (models == null) {
+ if (other.models != null)
+ return false;
+ } else if (!models.equals(other.models))
+ return false;
+ if (name == null) {
+ if (other.name != null)
+ return false;
+ } else if (!name.equals(other.name))
+ return false;
+ return true;
+ }
+
+}
diff --git a/apache-olingo/olingo2/src/main/java/org/baeldung/examples/olingo2/domain/CarModel.java b/apache-olingo/olingo2/src/main/java/org/baeldung/examples/olingo2/domain/CarModel.java
new file mode 100644
index 0000000000..f9f563e01e
--- /dev/null
+++ b/apache-olingo/olingo2/src/main/java/org/baeldung/examples/olingo2/domain/CarModel.java
@@ -0,0 +1,159 @@
+package org.baeldung.examples.olingo2.domain;
+
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+import javax.validation.constraints.NotNull;
+
+@Entity
+@Table(name = "car_model")
+public class CarModel {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.AUTO)
+ private Long id;
+
+ @NotNull
+ private String name;
+
+ @NotNull
+ private Integer year;
+
+ @NotNull
+ private String sku;
+
+ @ManyToOne(optional = false, fetch = FetchType.LAZY)
+ @JoinColumn(name = "maker_fk")
+ private CarMaker maker;
+
+ /**
+ * @return the id
+ */
+ public Long getId() {
+ return id;
+ }
+
+ /**
+ * @param id the id to set
+ */
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ /**
+ * @return the name
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * @param name the name to set
+ */
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ /**
+ * @return the year
+ */
+ public Integer getYear() {
+ return year;
+ }
+
+ /**
+ * @param year the year to set
+ */
+ public void setYear(Integer year) {
+ this.year = year;
+ }
+
+ /**
+ * @return the sku
+ */
+ public String getSku() {
+ return sku;
+ }
+
+ /**
+ * @param sku the sku to set
+ */
+ public void setSku(String sku) {
+ this.sku = sku;
+ }
+
+ /**
+ * @return the maker
+ */
+ public CarMaker getMaker() {
+ return maker;
+ }
+
+ /**
+ * @param maker the maker to set
+ */
+ public void setMaker(CarMaker maker) {
+ this.maker = maker;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#hashCode()
+ */
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((id == null) ? 0 : id.hashCode());
+ result = prime * result + ((maker == null) ? 0 : maker.hashCode());
+ result = prime * result + ((name == null) ? 0 : name.hashCode());
+ result = prime * result + ((sku == null) ? 0 : sku.hashCode());
+ result = prime * result + ((year == null) ? 0 : year.hashCode());
+ return result;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ CarModel other = (CarModel) obj;
+ if (id == null) {
+ if (other.id != null)
+ return false;
+ } else if (!id.equals(other.id))
+ return false;
+ if (maker == null) {
+ if (other.maker != null)
+ return false;
+ } else if (!maker.equals(other.maker))
+ return false;
+ if (name == null) {
+ if (other.name != null)
+ return false;
+ } else if (!name.equals(other.name))
+ return false;
+ if (sku == null) {
+ if (other.sku != null)
+ return false;
+ } else if (!sku.equals(other.sku))
+ return false;
+ if (year == null) {
+ if (other.year != null)
+ return false;
+ } else if (!year.equals(other.year))
+ return false;
+ return true;
+ }
+
+}
diff --git a/apache-olingo/olingo2/src/main/resources/application.yml b/apache-olingo/olingo2/src/main/resources/application.yml
new file mode 100644
index 0000000000..71df0c4166
--- /dev/null
+++ b/apache-olingo/olingo2/src/main/resources/application.yml
@@ -0,0 +1,12 @@
+server:
+ port: 8080
+
+spring:
+ jersey:
+ application-path: /odata
+
+ jpa:
+ show-sql: true
+ open-in-view: false
+ hibernate:
+ ddl-auto: update
\ No newline at end of file
diff --git a/apache-olingo/olingo2/src/main/resources/data.sql b/apache-olingo/olingo2/src/main/resources/data.sql
new file mode 100644
index 0000000000..327f2688c5
--- /dev/null
+++ b/apache-olingo/olingo2/src/main/resources/data.sql
@@ -0,0 +1,12 @@
+insert into car_maker(id,name) values (1,'Special Motors');
+insert into car_maker(id,name) values (2,'BWM');
+insert into car_maker(id,name) values (3,'Dolores');
+
+insert into car_model(id,maker_fk,name,sku,year) values(1,1,'Muze','SM001',2018);
+insert into car_model(id,maker_fk,name,sku,year) values(2,1,'Empada','SM002',2008);
+
+insert into car_model(id,maker_fk,name,sku,year) values(4,2,'BWM-100','BWM100',2008);
+insert into car_model(id,maker_fk,name,sku,year) values(5,2,'BWM-200','BWM200',2009);
+insert into car_model(id,maker_fk,name,sku,year) values(6,2,'BWM-300','BWM300',2008);
+
+alter sequence hibernate_sequence restart with 100;
\ No newline at end of file
diff --git a/apache-olingo/olingo2/src/test/java/org/baeldung/examples/olingo2/Olingo2SampleApplicationTests.java b/apache-olingo/olingo2/src/test/java/org/baeldung/examples/olingo2/Olingo2SampleApplicationTests.java
new file mode 100644
index 0000000000..687f6ab1ff
--- /dev/null
+++ b/apache-olingo/olingo2/src/test/java/org/baeldung/examples/olingo2/Olingo2SampleApplicationTests.java
@@ -0,0 +1,16 @@
+package org.baeldung.examples.olingo2;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest
+public class Olingo2SampleApplicationTests {
+
+ @Test
+ public void contextLoads() {
+ }
+
+}
diff --git a/apache-olingo/olingo2/src/test/resources/olingo2-queries.json b/apache-olingo/olingo2/src/test/resources/olingo2-queries.json
new file mode 100644
index 0000000000..9fdade6d10
--- /dev/null
+++ b/apache-olingo/olingo2/src/test/resources/olingo2-queries.json
@@ -0,0 +1,256 @@
+{
+ "info": {
+ "_postman_id": "afa8e1e5-ab0e-4f1d-8b99-b7d1f091f975",
+ "name": "OLingo2 - Cars",
+ "schema": "https://schema.getpostman.com/json/collection/v2.0.0/collection.json"
+ },
+ "item": [
+ {
+ "name": "GET Metadata",
+ "request": {
+ "method": "GET",
+ "header": [],
+ "body": {
+ "mode": "raw",
+ "raw": ""
+ },
+ "url": "http://localhost:8080/odata/$metadata"
+ },
+ "response": []
+ },
+ {
+ "name": "GET All CarMakers",
+ "request": {
+ "method": "GET",
+ "header": [],
+ "body": {
+ "mode": "raw",
+ "raw": ""
+ },
+ "url": "http://localhost:8080/odata/CarMakers"
+ },
+ "response": []
+ },
+ {
+ "name": "GET Makers with Pagination",
+ "request": {
+ "method": "GET",
+ "header": [],
+ "body": {
+ "mode": "raw",
+ "raw": ""
+ },
+ "url": {
+ "raw": "http://localhost:8080/odata/CarMakers?$top=1&$orderby=Name&$skip=3",
+ "protocol": "http",
+ "host": [
+ "localhost"
+ ],
+ "port": "8080",
+ "path": [
+ "odata",
+ "CarMakers"
+ ],
+ "query": [
+ {
+ "key": "$top",
+ "value": "1"
+ },
+ {
+ "key": "$orderby",
+ "value": "Name"
+ },
+ {
+ "key": "$skip",
+ "value": "3"
+ }
+ ]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "GET Makers and Models",
+ "request": {
+ "method": "GET",
+ "header": [],
+ "body": {
+ "mode": "raw",
+ "raw": ""
+ },
+ "url": {
+ "raw": "http://localhost:8080/odata/CarMakers?$expand=CarModelDetails",
+ "protocol": "http",
+ "host": [
+ "localhost"
+ ],
+ "port": "8080",
+ "path": [
+ "odata",
+ "CarMakers"
+ ],
+ "query": [
+ {
+ "key": "$expand",
+ "value": "CarModelDetails"
+ }
+ ]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "GET Makers with filter",
+ "request": {
+ "method": "GET",
+ "header": [
+ {
+ "key": "Accept",
+ "value": "application/json",
+ "type": "text"
+ }
+ ],
+ "body": {
+ "mode": "raw",
+ "raw": ""
+ },
+ "url": {
+ "raw": "http://localhost:8080/odata/CarMakers?$filter=Name eq 'BWM'&$expand=CarModelDetails",
+ "protocol": "http",
+ "host": [
+ "localhost"
+ ],
+ "port": "8080",
+ "path": [
+ "odata",
+ "CarMakers"
+ ],
+ "query": [
+ {
+ "key": "$filter",
+ "value": "Name eq 'BWM'"
+ },
+ {
+ "key": "$expand",
+ "value": "CarModelDetails"
+ }
+ ]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "Create CarMaker",
+ "request": {
+ "method": "POST",
+ "header": [
+ {
+ "key": "Content-Type",
+ "name": "Content-Type",
+ "value": "application/atom+xml",
+ "type": "text"
+ },
+ {
+ "key": "Accept",
+ "value": "application/atom+xml",
+ "type": "text"
+ }
+ ],
+ "body": {
+ "mode": "raw",
+ "raw": " \r\n\r\n \r\n 2019-04-02T21:36:47Z\r\n \r\n \r\n \r\n \r\n \r\n \r\n Lucien\r\n \r\n \r\n"
+ },
+ "url": "http://localhost:8080/odata/CarMakers"
+ },
+ "response": []
+ },
+ {
+ "name": "Create CarModel",
+ "request": {
+ "method": "POST",
+ "header": [
+ {
+ "key": "Content-Type",
+ "name": "Content-Type",
+ "type": "text",
+ "value": "application/atom+xml"
+ },
+ {
+ "key": "Accept",
+ "type": "text",
+ "value": "application/atom+xml"
+ }
+ ],
+ "body": {
+ "mode": "raw",
+ "raw": " \r\n\r\n \r\n 2019-04-02T21:36:47Z\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n\t Tata\r\n\t TT101\r\n\t 2018\r\n \r\n \r\n"
+ },
+ "url": "http://localhost:8080/odata/CarModels"
+ },
+ "response": []
+ },
+ {
+ "name": "Update CarMaker",
+ "request": {
+ "method": "PUT",
+ "header": [
+ {
+ "key": "Content-Type",
+ "name": "Content-Type",
+ "type": "text",
+ "value": "application/atom+xml"
+ },
+ {
+ "key": "Accept",
+ "type": "text",
+ "value": "application/atom+xml"
+ }
+ ],
+ "body": {
+ "mode": "raw",
+ "raw": " \r\n\r\n \r\n 2019-04-02T21:36:47Z\r\n \r\n \r\n \r\n \r\n \r\n \r\n 5\r\n KaiserWagen\r\n \r\n \r\n"
+ },
+ "url": "http://localhost:8080/odata/CarMakers(5L)"
+ },
+ "response": []
+ },
+ {
+ "name": "All CarModels",
+ "request": {
+ "method": "GET",
+ "header": [],
+ "body": {
+ "mode": "raw",
+ "raw": ""
+ },
+ "url": "http://localhost:8080/odata/CarModels"
+ },
+ "response": []
+ },
+ {
+ "name": "Delete CarModel",
+ "request": {
+ "method": "DELETE",
+ "header": [
+ {
+ "key": "Content-Type",
+ "name": "Content-Type",
+ "type": "text",
+ "value": "application/atom+xml"
+ },
+ {
+ "key": "Accept",
+ "type": "text",
+ "value": "application/atom+xml"
+ }
+ ],
+ "body": {
+ "mode": "raw",
+ "raw": ""
+ },
+ "url": "http://localhost:8080/odata/CarModels(100L)"
+ },
+ "response": []
+ }
+ ]
+}
\ No newline at end of file
diff --git a/apache-pulsar/pom.xml b/apache-pulsar/pom.xml
index a4c09586eb..11df6d0b87 100644
--- a/apache-pulsar/pom.xml
+++ b/apache-pulsar/pom.xml
@@ -11,12 +11,14 @@
org.apache.pulsarpulsar-client
- 2.1.1-incubating
+ ${pulsar-client.version}compile
+
1.81.8
+ 2.1.1-incubating
diff --git a/apache-solrj/pom.xml b/apache-solrj/pom.xml
index 9a807c2f26..1227fdca46 100644
--- a/apache-solrj/pom.xml
+++ b/apache-solrj/pom.xml
@@ -4,8 +4,8 @@
com.baeldungapache-solrj0.0.1-SNAPSHOT
- jarapache-solrj
+ jarcom.baeldung
diff --git a/apache-spark/README.md b/apache-spark/README.md
index fb8059eb27..a4dce212b4 100644
--- a/apache-spark/README.md
+++ b/apache-spark/README.md
@@ -1,3 +1,4 @@
### Relevant articles
- [Introduction to Apache Spark](http://www.baeldung.com/apache-spark)
+- [Building a Data Pipeline with Kafka, Spark Streaming and Cassandra](https://www.baeldung.com/kafka-spark-data-pipeline)
diff --git a/apache-spark/pom.xml b/apache-spark/pom.xml
index 290b63a14d..b8c1962dd4 100644
--- a/apache-spark/pom.xml
+++ b/apache-spark/pom.xml
@@ -4,8 +4,8 @@
com.baeldungapache-spark1.0-SNAPSHOT
- jarapache-spark
+ jarhttp://maven.apache.org
@@ -15,16 +15,79 @@
-
org.apache.spark
- spark-core_2.10
+ spark-core_2.11${org.apache.spark.spark-core.version}
+ provided
+
+ org.apache.spark
+ spark-sql_2.11
+ ${org.apache.spark.spark-sql.version}
+ provided
+
+
+ org.apache.spark
+ spark-streaming_2.11
+ ${org.apache.spark.spark-streaming.version}
+ provided
+
+
+ org.apache.spark
+ spark-streaming-kafka-0-10_2.11
+ ${org.apache.spark.spark-streaming-kafka.version}
+
+
+ com.datastax.spark
+ spark-cassandra-connector_2.11
+ ${com.datastax.spark.spark-cassandra-connector.version}
+
+
+ com.datastax.spark
+ spark-cassandra-connector-java_2.11
+ ${com.datastax.spark.spark-cassandra-connector-java.version}
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ ${maven-compiler-plugin.version}
+
+ ${java.version}
+ ${java.version}
+
+
+
+ maven-assembly-plugin
+
+
+ package
+
+ single
+
+
+
+
+
+ jar-with-dependencies
+
+
+
+
+
+
- 2.2.0
+ 2.3.0
+ 2.3.0
+ 2.3.0
+ 2.3.0
+ 2.3.0
+ 1.5.2
+ 3.2
diff --git a/apache-spark/src/main/java/com/baeldung/data/pipeline/Word.java b/apache-spark/src/main/java/com/baeldung/data/pipeline/Word.java
new file mode 100644
index 0000000000..b0caa468b1
--- /dev/null
+++ b/apache-spark/src/main/java/com/baeldung/data/pipeline/Word.java
@@ -0,0 +1,25 @@
+package com.baeldung.data.pipeline;
+
+import java.io.Serializable;
+
+public class Word implements Serializable {
+ private static final long serialVersionUID = 1L;
+ private String word;
+ private int count;
+ Word(String word, int count) {
+ this.word = word;
+ this.count = count;
+ }
+ public String getWord() {
+ return word;
+ }
+ public void setWord(String word) {
+ this.word = word;
+ }
+ public int getCount() {
+ return count;
+ }
+ public void setCount(int count) {
+ this.count = count;
+ }
+}
\ No newline at end of file
diff --git a/apache-spark/src/main/java/com/baeldung/data/pipeline/WordCountingApp.java b/apache-spark/src/main/java/com/baeldung/data/pipeline/WordCountingApp.java
new file mode 100644
index 0000000000..db2a73b411
--- /dev/null
+++ b/apache-spark/src/main/java/com/baeldung/data/pipeline/WordCountingApp.java
@@ -0,0 +1,80 @@
+package com.baeldung.data.pipeline;
+
+import static com.datastax.spark.connector.japi.CassandraJavaUtil.javaFunctions;
+import static com.datastax.spark.connector.japi.CassandraJavaUtil.mapToRow;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.kafka.clients.consumer.ConsumerRecord;
+import org.apache.kafka.common.serialization.StringDeserializer;
+import org.apache.log4j.Level;
+import org.apache.log4j.Logger;
+import org.apache.spark.SparkConf;
+import org.apache.spark.api.java.JavaRDD;
+import org.apache.spark.streaming.Durations;
+import org.apache.spark.streaming.api.java.JavaDStream;
+import org.apache.spark.streaming.api.java.JavaInputDStream;
+import org.apache.spark.streaming.api.java.JavaPairDStream;
+import org.apache.spark.streaming.api.java.JavaStreamingContext;
+import org.apache.spark.streaming.kafka010.ConsumerStrategies;
+import org.apache.spark.streaming.kafka010.KafkaUtils;
+import org.apache.spark.streaming.kafka010.LocationStrategies;
+
+import scala.Tuple2;
+
+public class WordCountingApp {
+
+ public static void main(String[] args) throws InterruptedException {
+ Logger.getLogger("org")
+ .setLevel(Level.OFF);
+ Logger.getLogger("akka")
+ .setLevel(Level.OFF);
+
+ Map kafkaParams = new HashMap<>();
+ kafkaParams.put("bootstrap.servers", "localhost:9092");
+ kafkaParams.put("key.deserializer", StringDeserializer.class);
+ kafkaParams.put("value.deserializer", StringDeserializer.class);
+ kafkaParams.put("group.id", "use_a_separate_group_id_for_each_stream");
+ kafkaParams.put("auto.offset.reset", "latest");
+ kafkaParams.put("enable.auto.commit", false);
+
+ Collection topics = Arrays.asList("messages");
+
+ SparkConf sparkConf = new SparkConf();
+ sparkConf.setMaster("local[2]");
+ sparkConf.setAppName("WordCountingApp");
+ sparkConf.set("spark.cassandra.connection.host", "127.0.0.1");
+
+ JavaStreamingContext streamingContext = new JavaStreamingContext(sparkConf, Durations.seconds(1));
+
+ JavaInputDStream> messages = KafkaUtils.createDirectStream(streamingContext, LocationStrategies.PreferConsistent(), ConsumerStrategies. Subscribe(topics, kafkaParams));
+
+ JavaPairDStream results = messages.mapToPair(record -> new Tuple2<>(record.key(), record.value()));
+
+ JavaDStream lines = results.map(tuple2 -> tuple2._2());
+
+ JavaDStream words = lines.flatMap(x -> Arrays.asList(x.split("\\s+"))
+ .iterator());
+
+ JavaPairDStream wordCounts = words.mapToPair(s -> new Tuple2<>(s, 1))
+ .reduceByKey((i1, i2) -> i1 + i2);
+
+ wordCounts.foreachRDD(javaRdd -> {
+ Map wordCountMap = javaRdd.collectAsMap();
+ for (String key : wordCountMap.keySet()) {
+ List wordList = Arrays.asList(new Word(key, wordCountMap.get(key)));
+ JavaRDD rdd = streamingContext.sparkContext()
+ .parallelize(wordList);
+ javaFunctions(rdd).writerBuilder("vocabulary", "words", mapToRow(Word.class))
+ .saveToCassandra();
+ }
+ });
+
+ streamingContext.start();
+ streamingContext.awaitTermination();
+ }
+}
\ No newline at end of file
diff --git a/apache-spark/src/main/java/com/baeldung/data/pipeline/WordCountingAppWithCheckpoint.java b/apache-spark/src/main/java/com/baeldung/data/pipeline/WordCountingAppWithCheckpoint.java
new file mode 100644
index 0000000000..efbe5f3851
--- /dev/null
+++ b/apache-spark/src/main/java/com/baeldung/data/pipeline/WordCountingAppWithCheckpoint.java
@@ -0,0 +1,97 @@
+package com.baeldung.data.pipeline;
+
+import static com.datastax.spark.connector.japi.CassandraJavaUtil.javaFunctions;
+import static com.datastax.spark.connector.japi.CassandraJavaUtil.mapToRow;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.kafka.clients.consumer.ConsumerRecord;
+import org.apache.kafka.common.serialization.StringDeserializer;
+import org.apache.log4j.Level;
+import org.apache.log4j.Logger;
+import org.apache.spark.SparkConf;
+import org.apache.spark.api.java.JavaRDD;
+import org.apache.spark.api.java.JavaSparkContext;
+import org.apache.spark.api.java.function.Function2;
+import org.apache.spark.streaming.Durations;
+import org.apache.spark.streaming.StateSpec;
+import org.apache.spark.streaming.api.java.JavaDStream;
+import org.apache.spark.streaming.api.java.JavaInputDStream;
+import org.apache.spark.streaming.api.java.JavaMapWithStateDStream;
+import org.apache.spark.streaming.api.java.JavaPairDStream;
+import org.apache.spark.streaming.api.java.JavaStreamingContext;
+import org.apache.spark.streaming.kafka010.ConsumerStrategies;
+import org.apache.spark.streaming.kafka010.KafkaUtils;
+import org.apache.spark.streaming.kafka010.LocationStrategies;
+
+import scala.Tuple2;
+
+public class WordCountingAppWithCheckpoint {
+
+ public static JavaSparkContext sparkContext;
+
+ public static void main(String[] args) throws InterruptedException {
+
+ Logger.getLogger("org")
+ .setLevel(Level.OFF);
+ Logger.getLogger("akka")
+ .setLevel(Level.OFF);
+
+ Map kafkaParams = new HashMap<>();
+ kafkaParams.put("bootstrap.servers", "localhost:9092");
+ kafkaParams.put("key.deserializer", StringDeserializer.class);
+ kafkaParams.put("value.deserializer", StringDeserializer.class);
+ kafkaParams.put("group.id", "use_a_separate_group_id_for_each_stream");
+ kafkaParams.put("auto.offset.reset", "latest");
+ kafkaParams.put("enable.auto.commit", false);
+
+ Collection topics = Arrays.asList("messages");
+
+ SparkConf sparkConf = new SparkConf();
+ sparkConf.setMaster("local[2]");
+ sparkConf.setAppName("WordCountingAppWithCheckpoint");
+ sparkConf.set("spark.cassandra.connection.host", "127.0.0.1");
+
+ JavaStreamingContext streamingContext = new JavaStreamingContext(sparkConf, Durations.seconds(1));
+
+ sparkContext = streamingContext.sparkContext();
+
+ streamingContext.checkpoint("./.checkpoint");
+
+ JavaInputDStream> messages = KafkaUtils.createDirectStream(streamingContext, LocationStrategies.PreferConsistent(), ConsumerStrategies. Subscribe(topics, kafkaParams));
+
+ JavaPairDStream results = messages.mapToPair(record -> new Tuple2<>(record.key(), record.value()));
+
+ JavaDStream lines = results.map(tuple2 -> tuple2._2());
+
+ JavaDStream words = lines.flatMap(x -> Arrays.asList(x.split("\\s+"))
+ .iterator());
+
+ JavaPairDStream wordCounts = words.mapToPair(s -> new Tuple2<>(s, 1))
+ .reduceByKey((Function2) (i1, i2) -> i1 + i2);
+
+ JavaMapWithStateDStream> cumulativeWordCounts = wordCounts.mapWithState(StateSpec.function((word, one, state) -> {
+ int sum = one.orElse(0) + (state.exists() ? state.get() : 0);
+ Tuple2 output = new Tuple2<>(word, sum);
+ state.update(sum);
+ return output;
+ }));
+
+ cumulativeWordCounts.foreachRDD(javaRdd -> {
+ List> wordCountList = javaRdd.collect();
+ for (Tuple2 tuple : wordCountList) {
+ List wordList = Arrays.asList(new Word(tuple._1, tuple._2));
+ JavaRDD rdd = sparkContext.parallelize(wordList);
+ javaFunctions(rdd).writerBuilder("vocabulary", "words", mapToRow(Word.class))
+ .saveToCassandra();
+ }
+ });
+
+ streamingContext.start();
+ streamingContext.awaitTermination();
+ }
+}
\ No newline at end of file
diff --git a/apache-velocity/pom.xml b/apache-velocity/pom.xml
index 19cf77d945..24ab0b861d 100644
--- a/apache-velocity/pom.xml
+++ b/apache-velocity/pom.xml
@@ -4,8 +4,8 @@
com.baeldung0.1-SNAPSHOTapache-velocity
- warapache-velocity
+ warcom.baeldung
@@ -59,7 +59,6 @@
- 1.24.5.21.72.0
diff --git a/autovalue/README.md b/autovalue/README.md
index c6a08359ef..f33ff6899f 100644
--- a/autovalue/README.md
+++ b/autovalue/README.md
@@ -1,3 +1,4 @@
### Relevant Articles:
- [Introduction to AutoValue](http://www.baeldung.com/introduction-to-autovalue)
- [Introduction to AutoFactory](http://www.baeldung.com/autofactory)
+- [Google AutoService](https://www.baeldung.com/google-autoservice)
diff --git a/autovalue/pom.xml b/autovalue/pom.xml
index 3ec2d26b35..a10e8ef055 100644
--- a/autovalue/pom.xml
+++ b/autovalue/pom.xml
@@ -29,6 +29,12 @@
+
+ com.google.auto.service
+ auto-service
+ ${auto-service.version}
+ true
+ com.google.inject
@@ -40,6 +46,7 @@
1.31.0-beta5
+ 1.0-rc54.2.0
diff --git a/autovalue/src/main/java/com/baeldung/autofactory/provided/IntermediateAssembler.java b/autovalue/src/main/java/com/baeldung/autofactory/provided/IntermediateAssembler.java
index e0ee8879a5..65d0eb6f58 100644
--- a/autovalue/src/main/java/com/baeldung/autofactory/provided/IntermediateAssembler.java
+++ b/autovalue/src/main/java/com/baeldung/autofactory/provided/IntermediateAssembler.java
@@ -1,8 +1,9 @@
package com.baeldung.autofactory.provided;
+import com.baeldung.autofactory.model.Camera;
import com.google.auto.factory.AutoFactory;
import com.google.auto.factory.Provided;
-import javafx.scene.Camera;
+
import javax.inject.Provider;
diff --git a/autovalue/src/main/java/com/baeldung/autoservice/BingTranslationServiceProvider.java b/autovalue/src/main/java/com/baeldung/autoservice/BingTranslationServiceProvider.java
new file mode 100644
index 0000000000..86d42e80fa
--- /dev/null
+++ b/autovalue/src/main/java/com/baeldung/autoservice/BingTranslationServiceProvider.java
@@ -0,0 +1,14 @@
+package com.baeldung.autoservice;
+
+import com.google.auto.service.AutoService;
+
+import java.util.Locale;
+
+@AutoService(TranslationService.class)
+public class BingTranslationServiceProvider implements TranslationService {
+ @Override
+ public String translate(String message, Locale from, Locale to) {
+ // implementation details
+ return message + " (translated by Bing)";
+ }
+}
diff --git a/autovalue/src/main/java/com/baeldung/autoservice/GoogleTranslationServiceProvider.java b/autovalue/src/main/java/com/baeldung/autoservice/GoogleTranslationServiceProvider.java
new file mode 100644
index 0000000000..0bf91ee5ec
--- /dev/null
+++ b/autovalue/src/main/java/com/baeldung/autoservice/GoogleTranslationServiceProvider.java
@@ -0,0 +1,14 @@
+package com.baeldung.autoservice;
+
+import com.google.auto.service.AutoService;
+
+import java.util.Locale;
+
+@AutoService(TranslationService.class)
+public class GoogleTranslationServiceProvider implements TranslationService {
+ @Override
+ public String translate(String message, Locale from, Locale to) {
+ // implementation details
+ return message + " (translated by Google)";
+ }
+}
diff --git a/autovalue/src/main/java/com/baeldung/autoservice/TranslationService.java b/autovalue/src/main/java/com/baeldung/autoservice/TranslationService.java
new file mode 100644
index 0000000000..580db46cd1
--- /dev/null
+++ b/autovalue/src/main/java/com/baeldung/autoservice/TranslationService.java
@@ -0,0 +1,7 @@
+package com.baeldung.autoservice;
+
+import java.util.Locale;
+
+public interface TranslationService {
+ String translate(String message, Locale from, Locale to);
+}
\ No newline at end of file
diff --git a/autovalue/src/test/java/com/baeldung/autoservice/TranslationServiceUnitTest.java b/autovalue/src/test/java/com/baeldung/autoservice/TranslationServiceUnitTest.java
new file mode 100644
index 0000000000..9e1bd6d291
--- /dev/null
+++ b/autovalue/src/test/java/com/baeldung/autoservice/TranslationServiceUnitTest.java
@@ -0,0 +1,37 @@
+package com.baeldung.autoservice;
+
+import com.baeldung.autoservice.TranslationService;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.ServiceLoader;
+import java.util.stream.StreamSupport;
+
+import static org.junit.Assert.assertEquals;
+
+public class TranslationServiceUnitTest {
+
+ private ServiceLoader loader;
+
+ @Before
+ public void setUp() {
+ loader = ServiceLoader.load(TranslationService.class);
+ }
+
+ @Test
+ public void whenServiceLoaderLoads_thenLoadsAllProviders() {
+ long count = StreamSupport.stream(loader.spliterator(), false).count();
+ assertEquals(2, count);
+ }
+
+ @Test
+ public void whenServiceLoaderLoadsGoogleService_thenGoogleIsLoaded() {
+ TranslationService googleService = StreamSupport.stream(loader.spliterator(), false)
+ .filter(p -> p.getClass().getSimpleName().equals("GoogleTranslationServiceProvider"))
+ .findFirst()
+ .get();
+
+ String message = "message";
+ assertEquals(message + " (translated by Google)", googleService.translate(message, null, null));
+ }
+}
\ No newline at end of file
diff --git a/aws-lambda/pom.xml b/aws-lambda/pom.xml
index c47c3cd86f..c799718e61 100644
--- a/aws-lambda/pom.xml
+++ b/aws-lambda/pom.xml
@@ -5,8 +5,8 @@
com.baeldungaws-lambda0.1.0-SNAPSHOT
- jaraws-lambda
+ jarparent-modules
diff --git a/aws/README.md b/aws/README.md
index 2c61928095..d14ea8a75e 100644
--- a/aws/README.md
+++ b/aws/README.md
@@ -4,7 +4,6 @@
- [AWS S3 with Java](http://www.baeldung.com/aws-s3-java)
- [AWS Lambda With Java](http://www.baeldung.com/java-aws-lambda)
- [Managing EC2 Instances in Java](http://www.baeldung.com/ec2-java)
-- [http://www.baeldung.com/aws-s3-multipart-upload](https://github.com/eugenp/tutorials/tree/master/aws)
- [Multipart Uploads in Amazon S3 with Java](http://www.baeldung.com/aws-s3-multipart-upload)
- [Integration Testing with a Local DynamoDB Instance](http://www.baeldung.com/dynamodb-local-integration-tests)
- [Using the JetS3t Java Client With Amazon S3](http://www.baeldung.com/jets3t-amazon-s3)
diff --git a/aws/pom.xml b/aws/pom.xml
index ab63f6afa1..560f9145f9 100644
--- a/aws/pom.xml
+++ b/aws/pom.xml
@@ -4,8 +4,8 @@
com.baeldungaws0.1.0-SNAPSHOT
- jaraws
+ jarcom.baeldung
diff --git a/axon/pom.xml b/axon/pom.xml
index c643ea9e57..2b9ac1fcdd 100644
--- a/axon/pom.xml
+++ b/axon/pom.xml
@@ -4,29 +4,61 @@
4.0.0axonaxon
-
+ Basic Axon Framework with Spring Boot configuration tutorial
+
- parent-modulescom.baeldung
- 1.0.0-SNAPSHOT
+ parent-boot-2
+ 0.0.1-SNAPSHOT
+ ../parent-boot-2
+
+ org.axonframework
+ axon-spring-boot-starter
+ ${axon.version}
+
+
+ org.axonframework
+ axon-server-connector
+
+
+
+
org.axonframeworkaxon-test${axon.version}test
+
- org.axonframework
- axon-core
- ${axon.version}
+ org.springframework.boot
+ spring-boot-autoconfigure
+ ${spring-boot.version}
+ compile
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ org.springframework.boot
+ spring-boot-starter-data-jpa
+
+
+
+ com.h2database
+ h2
+ runtime
- 3.0.2
+ 4.0.3
\ No newline at end of file
diff --git a/axon/src/main/java/com/baeldung/axon/MessagesRunner.java b/axon/src/main/java/com/baeldung/axon/MessagesRunner.java
deleted file mode 100644
index 77b50d09bd..0000000000
--- a/axon/src/main/java/com/baeldung/axon/MessagesRunner.java
+++ /dev/null
@@ -1,54 +0,0 @@
-package com.baeldung.axon;
-
-import com.baeldung.axon.aggregates.MessagesAggregate;
-import com.baeldung.axon.commands.CreateMessageCommand;
-import com.baeldung.axon.commands.MarkReadMessageCommand;
-import com.baeldung.axon.eventhandlers.MessagesEventHandler;
-import org.axonframework.commandhandling.AggregateAnnotationCommandHandler;
-import org.axonframework.commandhandling.CommandBus;
-import org.axonframework.commandhandling.SimpleCommandBus;
-import org.axonframework.commandhandling.gateway.CommandGateway;
-import org.axonframework.commandhandling.gateway.DefaultCommandGateway;
-import org.axonframework.eventhandling.AnnotationEventListenerAdapter;
-import org.axonframework.eventsourcing.EventSourcingRepository;
-import org.axonframework.eventsourcing.eventstore.EmbeddedEventStore;
-import org.axonframework.eventsourcing.eventstore.EventStore;
-import org.axonframework.eventsourcing.eventstore.inmemory.InMemoryEventStorageEngine;
-
-import java.util.UUID;
-
-public class MessagesRunner {
-
- public static void main(String[] args) {
- CommandBus commandBus = new SimpleCommandBus();
-
- CommandGateway commandGateway = new DefaultCommandGateway(commandBus);
-
- EventStore eventStore = new EmbeddedEventStore(new InMemoryEventStorageEngine());
-
- EventSourcingRepository repository =
- new EventSourcingRepository<>(MessagesAggregate.class, eventStore);
-
-
- AggregateAnnotationCommandHandler messagesAggregateAggregateAnnotationCommandHandler =
- new AggregateAnnotationCommandHandler(MessagesAggregate.class, repository);
- messagesAggregateAggregateAnnotationCommandHandler.subscribe(commandBus);
-
- final AnnotationEventListenerAdapter annotationEventListenerAdapter =
- new AnnotationEventListenerAdapter(new MessagesEventHandler());
- eventStore.subscribe(eventMessages -> eventMessages.forEach(e -> {
- try {
- annotationEventListenerAdapter.handle(e);
- } catch (Exception e1) {
- throw new RuntimeException(e1);
-
- }
- }
-
- ));
-
- final String itemId = UUID.randomUUID().toString();
- commandGateway.send(new CreateMessageCommand(itemId, "Hello, how is your day? :-)"));
- commandGateway.send(new MarkReadMessageCommand(itemId));
- }
-}
\ No newline at end of file
diff --git a/axon/src/main/java/com/baeldung/axon/OrderApplication.java b/axon/src/main/java/com/baeldung/axon/OrderApplication.java
new file mode 100644
index 0000000000..8f507e141c
--- /dev/null
+++ b/axon/src/main/java/com/baeldung/axon/OrderApplication.java
@@ -0,0 +1,13 @@
+package com.baeldung.axon;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class OrderApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(OrderApplication.class, args);
+ }
+
+}
\ No newline at end of file
diff --git a/axon/src/main/java/com/baeldung/axon/aggregates/MessagesAggregate.java b/axon/src/main/java/com/baeldung/axon/aggregates/MessagesAggregate.java
deleted file mode 100644
index e762604b74..0000000000
--- a/axon/src/main/java/com/baeldung/axon/aggregates/MessagesAggregate.java
+++ /dev/null
@@ -1,36 +0,0 @@
-package com.baeldung.axon.aggregates;
-
-import com.baeldung.axon.commands.CreateMessageCommand;
-import com.baeldung.axon.commands.MarkReadMessageCommand;
-import com.baeldung.axon.events.MessageCreatedEvent;
-import com.baeldung.axon.events.MessageReadEvent;
-import org.axonframework.commandhandling.CommandHandler;
-import org.axonframework.commandhandling.model.AggregateIdentifier;
-import org.axonframework.eventhandling.EventHandler;
-
-import static org.axonframework.commandhandling.model.AggregateLifecycle.apply;
-
-
-public class MessagesAggregate {
-
- @AggregateIdentifier
- private String id;
-
- public MessagesAggregate() {
- }
-
- @CommandHandler
- public MessagesAggregate(CreateMessageCommand command) {
- apply(new MessageCreatedEvent(command.getId(), command.getText()));
- }
-
- @EventHandler
- public void on(MessageCreatedEvent event) {
- this.id = event.getId();
- }
-
- @CommandHandler
- public void markRead(MarkReadMessageCommand command) {
- apply(new MessageReadEvent(id));
- }
-}
\ No newline at end of file
diff --git a/axon/src/main/java/com/baeldung/axon/commandmodel/OrderAggregate.java b/axon/src/main/java/com/baeldung/axon/commandmodel/OrderAggregate.java
new file mode 100644
index 0000000000..b37b2fdd66
--- /dev/null
+++ b/axon/src/main/java/com/baeldung/axon/commandmodel/OrderAggregate.java
@@ -0,0 +1,58 @@
+package com.baeldung.axon.commandmodel;
+
+import static org.axonframework.modelling.command.AggregateLifecycle.apply;
+
+import org.axonframework.commandhandling.CommandHandler;
+import org.axonframework.eventsourcing.EventSourcingHandler;
+import org.axonframework.modelling.command.AggregateIdentifier;
+import org.axonframework.spring.stereotype.Aggregate;
+
+import com.baeldung.axon.coreapi.commands.ConfirmOrderCommand;
+import com.baeldung.axon.coreapi.commands.PlaceOrderCommand;
+import com.baeldung.axon.coreapi.commands.ShipOrderCommand;
+import com.baeldung.axon.coreapi.events.OrderConfirmedEvent;
+import com.baeldung.axon.coreapi.events.OrderPlacedEvent;
+import com.baeldung.axon.coreapi.events.OrderShippedEvent;
+
+@Aggregate
+public class OrderAggregate {
+
+ @AggregateIdentifier
+ private String orderId;
+ private boolean orderConfirmed;
+
+ @CommandHandler
+ public OrderAggregate(PlaceOrderCommand command) {
+ apply(new OrderPlacedEvent(command.getOrderId(), command.getProduct()));
+ }
+
+ @CommandHandler
+ public void handle(ConfirmOrderCommand command) {
+ apply(new OrderConfirmedEvent(orderId));
+ }
+
+ @CommandHandler
+ public void handle(ShipOrderCommand command) {
+ if (!orderConfirmed) {
+ throw new IllegalStateException("Cannot ship an order which has not been confirmed yet.");
+ }
+
+ apply(new OrderShippedEvent(orderId));
+ }
+
+ @EventSourcingHandler
+ public void on(OrderPlacedEvent event) {
+ this.orderId = event.getOrderId();
+ orderConfirmed = false;
+ }
+
+ @EventSourcingHandler
+ public void on(OrderConfirmedEvent event) {
+ orderConfirmed = true;
+ }
+
+ protected OrderAggregate() {
+ // Required by Axon to build a default Aggregate prior to Event Sourcing
+ }
+
+}
\ No newline at end of file
diff --git a/axon/src/main/java/com/baeldung/axon/commands/CreateMessageCommand.java b/axon/src/main/java/com/baeldung/axon/commands/CreateMessageCommand.java
deleted file mode 100644
index d0651bf12e..0000000000
--- a/axon/src/main/java/com/baeldung/axon/commands/CreateMessageCommand.java
+++ /dev/null
@@ -1,24 +0,0 @@
-package com.baeldung.axon.commands;
-
-
-import org.axonframework.commandhandling.TargetAggregateIdentifier;
-
-public class CreateMessageCommand {
-
- @TargetAggregateIdentifier
- private final String id;
- private final String text;
-
- public CreateMessageCommand(String id, String text) {
- this.id = id;
- this.text = text;
- }
-
- public String getId() {
- return id;
- }
-
- public String getText() {
- return text;
- }
-}
\ No newline at end of file
diff --git a/axon/src/main/java/com/baeldung/axon/commands/MarkReadMessageCommand.java b/axon/src/main/java/com/baeldung/axon/commands/MarkReadMessageCommand.java
deleted file mode 100644
index e66582d9ec..0000000000
--- a/axon/src/main/java/com/baeldung/axon/commands/MarkReadMessageCommand.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.baeldung.axon.commands;
-
-
-import org.axonframework.commandhandling.TargetAggregateIdentifier;
-
-public class MarkReadMessageCommand {
-
- @TargetAggregateIdentifier
- private final String id;
-
- public MarkReadMessageCommand(String id) {
- this.id = id;
- }
-
- public String getId() {
- return id;
- }
-}
\ No newline at end of file
diff --git a/axon/src/main/java/com/baeldung/axon/coreapi/commands/ConfirmOrderCommand.java b/axon/src/main/java/com/baeldung/axon/coreapi/commands/ConfirmOrderCommand.java
new file mode 100644
index 0000000000..244b69f3b7
--- /dev/null
+++ b/axon/src/main/java/com/baeldung/axon/coreapi/commands/ConfirmOrderCommand.java
@@ -0,0 +1,43 @@
+package com.baeldung.axon.coreapi.commands;
+
+import org.axonframework.modelling.command.TargetAggregateIdentifier;
+
+import java.util.Objects;
+
+public class ConfirmOrderCommand {
+
+ @TargetAggregateIdentifier
+ private final String orderId;
+
+ public ConfirmOrderCommand(String orderId) {
+ this.orderId = orderId;
+ }
+
+ public String getOrderId() {
+ return orderId;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(orderId);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null || getClass() != obj.getClass()) {
+ return false;
+ }
+ final ConfirmOrderCommand other = (ConfirmOrderCommand) obj;
+ return Objects.equals(this.orderId, other.orderId);
+ }
+
+ @Override
+ public String toString() {
+ return "ConfirmOrderCommand{" +
+ "orderId='" + orderId + '\'' +
+ '}';
+ }
+}
diff --git a/axon/src/main/java/com/baeldung/axon/coreapi/commands/PlaceOrderCommand.java b/axon/src/main/java/com/baeldung/axon/coreapi/commands/PlaceOrderCommand.java
new file mode 100644
index 0000000000..c70d503050
--- /dev/null
+++ b/axon/src/main/java/com/baeldung/axon/coreapi/commands/PlaceOrderCommand.java
@@ -0,0 +1,51 @@
+package com.baeldung.axon.coreapi.commands;
+
+import java.util.Objects;
+
+import org.axonframework.modelling.command.TargetAggregateIdentifier;
+
+public class PlaceOrderCommand {
+
+ @TargetAggregateIdentifier
+ private final String orderId;
+ private final String product;
+
+ public PlaceOrderCommand(String orderId, String product) {
+ this.orderId = orderId;
+ this.product = product;
+ }
+
+ public String getOrderId() {
+ return orderId;
+ }
+
+ public String getProduct() {
+ return product;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(orderId, product);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null || getClass() != obj.getClass()) {
+ return false;
+ }
+ final PlaceOrderCommand other = (PlaceOrderCommand) obj;
+ return Objects.equals(this.orderId, other.orderId)
+ && Objects.equals(this.product, other.product);
+ }
+
+ @Override
+ public String toString() {
+ return "PlaceOrderCommand{" +
+ "orderId='" + orderId + '\'' +
+ ", product='" + product + '\'' +
+ '}';
+ }
+}
\ No newline at end of file
diff --git a/axon/src/main/java/com/baeldung/axon/coreapi/commands/ShipOrderCommand.java b/axon/src/main/java/com/baeldung/axon/coreapi/commands/ShipOrderCommand.java
new file mode 100644
index 0000000000..7312bc1fdb
--- /dev/null
+++ b/axon/src/main/java/com/baeldung/axon/coreapi/commands/ShipOrderCommand.java
@@ -0,0 +1,43 @@
+package com.baeldung.axon.coreapi.commands;
+
+import java.util.Objects;
+
+import org.axonframework.modelling.command.TargetAggregateIdentifier;
+
+public class ShipOrderCommand {
+
+ @TargetAggregateIdentifier
+ private final String orderId;
+
+ public ShipOrderCommand(String orderId) {
+ this.orderId = orderId;
+ }
+
+ public String getOrderId() {
+ return orderId;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(orderId);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null || getClass() != obj.getClass()) {
+ return false;
+ }
+ final ShipOrderCommand other = (ShipOrderCommand) obj;
+ return Objects.equals(this.orderId, other.orderId);
+ }
+
+ @Override
+ public String toString() {
+ return "ShipOrderCommand{" +
+ "orderId='" + orderId + '\'' +
+ '}';
+ }
+}
\ No newline at end of file
diff --git a/axon/src/main/java/com/baeldung/axon/coreapi/events/OrderConfirmedEvent.java b/axon/src/main/java/com/baeldung/axon/coreapi/events/OrderConfirmedEvent.java
new file mode 100644
index 0000000000..d2b7d58435
--- /dev/null
+++ b/axon/src/main/java/com/baeldung/axon/coreapi/events/OrderConfirmedEvent.java
@@ -0,0 +1,40 @@
+package com.baeldung.axon.coreapi.events;
+
+import java.util.Objects;
+
+public class OrderConfirmedEvent {
+
+ private final String orderId;
+
+ public OrderConfirmedEvent(String orderId) {
+ this.orderId = orderId;
+ }
+
+ public String getOrderId() {
+ return orderId;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(orderId);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null || getClass() != obj.getClass()) {
+ return false;
+ }
+ final OrderConfirmedEvent other = (OrderConfirmedEvent) obj;
+ return Objects.equals(this.orderId, other.orderId);
+ }
+
+ @Override
+ public String toString() {
+ return "OrderConfirmedEvent{" +
+ "orderId='" + orderId + '\'' +
+ '}';
+ }
+}
diff --git a/axon/src/main/java/com/baeldung/axon/coreapi/events/OrderPlacedEvent.java b/axon/src/main/java/com/baeldung/axon/coreapi/events/OrderPlacedEvent.java
new file mode 100644
index 0000000000..06de4c5f9f
--- /dev/null
+++ b/axon/src/main/java/com/baeldung/axon/coreapi/events/OrderPlacedEvent.java
@@ -0,0 +1,48 @@
+package com.baeldung.axon.coreapi.events;
+
+import java.util.Objects;
+
+public class OrderPlacedEvent {
+
+ private final String orderId;
+ private final String product;
+
+ public OrderPlacedEvent(String orderId, String product) {
+ this.orderId = orderId;
+ this.product = product;
+ }
+
+ public String getOrderId() {
+ return orderId;
+ }
+
+ public String getProduct() {
+ return product;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(orderId, product);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null || getClass() != obj.getClass()) {
+ return false;
+ }
+ final OrderPlacedEvent other = (OrderPlacedEvent) obj;
+ return Objects.equals(this.orderId, other.orderId)
+ && Objects.equals(this.product, other.product);
+ }
+
+ @Override
+ public String toString() {
+ return "OrderPlacedEvent{" +
+ "orderId='" + orderId + '\'' +
+ ", product='" + product + '\'' +
+ '}';
+ }
+}
\ No newline at end of file
diff --git a/axon/src/main/java/com/baeldung/axon/coreapi/events/OrderShippedEvent.java b/axon/src/main/java/com/baeldung/axon/coreapi/events/OrderShippedEvent.java
new file mode 100644
index 0000000000..76aa684629
--- /dev/null
+++ b/axon/src/main/java/com/baeldung/axon/coreapi/events/OrderShippedEvent.java
@@ -0,0 +1,40 @@
+package com.baeldung.axon.coreapi.events;
+
+import java.util.Objects;
+
+public class OrderShippedEvent {
+
+ private final String orderId;
+
+ public OrderShippedEvent(String orderId) {
+ this.orderId = orderId;
+ }
+
+ public String getOrderId() {
+ return orderId;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(orderId);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null || getClass() != obj.getClass()) {
+ return false;
+ }
+ final OrderShippedEvent other = (OrderShippedEvent) obj;
+ return Objects.equals(this.orderId, other.orderId);
+ }
+
+ @Override
+ public String toString() {
+ return "OrderShippedEvent{" +
+ "orderId='" + orderId + '\'' +
+ '}';
+ }
+}
\ No newline at end of file
diff --git a/axon/src/main/java/com/baeldung/axon/coreapi/queries/FindAllOrderedProductsQuery.java b/axon/src/main/java/com/baeldung/axon/coreapi/queries/FindAllOrderedProductsQuery.java
new file mode 100644
index 0000000000..9d6ca2cfb2
--- /dev/null
+++ b/axon/src/main/java/com/baeldung/axon/coreapi/queries/FindAllOrderedProductsQuery.java
@@ -0,0 +1,5 @@
+package com.baeldung.axon.coreapi.queries;
+
+public class FindAllOrderedProductsQuery {
+
+}
diff --git a/axon/src/main/java/com/baeldung/axon/coreapi/queries/OrderStatus.java b/axon/src/main/java/com/baeldung/axon/coreapi/queries/OrderStatus.java
new file mode 100644
index 0000000000..d215c5fc32
--- /dev/null
+++ b/axon/src/main/java/com/baeldung/axon/coreapi/queries/OrderStatus.java
@@ -0,0 +1,7 @@
+package com.baeldung.axon.coreapi.queries;
+
+public enum OrderStatus {
+
+ PLACED, CONFIRMED, SHIPPED
+
+}
diff --git a/axon/src/main/java/com/baeldung/axon/coreapi/queries/OrderedProduct.java b/axon/src/main/java/com/baeldung/axon/coreapi/queries/OrderedProduct.java
new file mode 100644
index 0000000000..d847bb2a98
--- /dev/null
+++ b/axon/src/main/java/com/baeldung/axon/coreapi/queries/OrderedProduct.java
@@ -0,0 +1,64 @@
+package com.baeldung.axon.coreapi.queries;
+
+import java.util.Objects;
+
+public class OrderedProduct {
+
+ private final String orderId;
+ private final String product;
+ private OrderStatus orderStatus;
+
+ public OrderedProduct(String orderId, String product) {
+ this.orderId = orderId;
+ this.product = product;
+ orderStatus = OrderStatus.PLACED;
+ }
+
+ public String getOrderId() {
+ return orderId;
+ }
+
+ public String getProduct() {
+ return product;
+ }
+
+ public OrderStatus getOrderStatus() {
+ return orderStatus;
+ }
+
+ public void setOrderConfirmed() {
+ this.orderStatus = OrderStatus.CONFIRMED;
+ }
+
+ public void setOrderShipped() {
+ this.orderStatus = OrderStatus.SHIPPED;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(orderId, product, orderStatus);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null || getClass() != obj.getClass()) {
+ return false;
+ }
+ final OrderedProduct other = (OrderedProduct) obj;
+ return Objects.equals(this.orderId, other.orderId)
+ && Objects.equals(this.product, other.product)
+ && Objects.equals(this.orderStatus, other.orderStatus);
+ }
+
+ @Override
+ public String toString() {
+ return "OrderedProduct{" +
+ "orderId='" + orderId + '\'' +
+ ", product='" + product + '\'' +
+ ", orderStatus=" + orderStatus +
+ '}';
+ }
+}
diff --git a/axon/src/main/java/com/baeldung/axon/eventhandlers/MessagesEventHandler.java b/axon/src/main/java/com/baeldung/axon/eventhandlers/MessagesEventHandler.java
deleted file mode 100644
index 3e51e19c4e..0000000000
--- a/axon/src/main/java/com/baeldung/axon/eventhandlers/MessagesEventHandler.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package com.baeldung.axon.eventhandlers;
-
-import com.baeldung.axon.events.MessageReadEvent;
-import com.baeldung.axon.events.MessageCreatedEvent;
-import org.axonframework.eventhandling.EventHandler;
-
-
-public class MessagesEventHandler {
-
- @EventHandler
- public void handle(MessageCreatedEvent event) {
- System.out.println("Message received: " + event.getText() + " (" + event.getId() + ")");
- }
-
- @EventHandler
- public void handle(MessageReadEvent event) {
- System.out.println("Message read: " + event.getId());
- }
-}
\ No newline at end of file
diff --git a/axon/src/main/java/com/baeldung/axon/events/MessageCreatedEvent.java b/axon/src/main/java/com/baeldung/axon/events/MessageCreatedEvent.java
deleted file mode 100644
index 3c9aac5ed8..0000000000
--- a/axon/src/main/java/com/baeldung/axon/events/MessageCreatedEvent.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package com.baeldung.axon.events;
-
-public class MessageCreatedEvent {
-
- private final String id;
- private final String text;
-
- public MessageCreatedEvent(String id, String text) {
- this.id = id;
- this.text = text;
- }
-
- public String getId() {
- return id;
- }
-
- public String getText() {
- return text;
- }
-}
\ No newline at end of file
diff --git a/axon/src/main/java/com/baeldung/axon/events/MessageReadEvent.java b/axon/src/main/java/com/baeldung/axon/events/MessageReadEvent.java
deleted file mode 100644
index 57bfc8e19e..0000000000
--- a/axon/src/main/java/com/baeldung/axon/events/MessageReadEvent.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package com.baeldung.axon.events;
-
-public class MessageReadEvent {
-
- private final String id;
-
- public MessageReadEvent(String id) {
- this.id = id;
- }
-
- public String getId() {
- return id;
- }
-}
\ No newline at end of file
diff --git a/axon/src/main/java/com/baeldung/axon/gui/OrderRestEndpoint.java b/axon/src/main/java/com/baeldung/axon/gui/OrderRestEndpoint.java
new file mode 100644
index 0000000000..a9f34cc691
--- /dev/null
+++ b/axon/src/main/java/com/baeldung/axon/gui/OrderRestEndpoint.java
@@ -0,0 +1,52 @@
+package com.baeldung.axon.gui;
+
+import java.util.List;
+import java.util.UUID;
+
+import org.axonframework.commandhandling.gateway.CommandGateway;
+import org.axonframework.messaging.responsetypes.ResponseTypes;
+import org.axonframework.queryhandling.QueryGateway;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.baeldung.axon.coreapi.commands.ConfirmOrderCommand;
+import com.baeldung.axon.coreapi.commands.PlaceOrderCommand;
+import com.baeldung.axon.coreapi.commands.ShipOrderCommand;
+import com.baeldung.axon.coreapi.queries.FindAllOrderedProductsQuery;
+import com.baeldung.axon.coreapi.queries.OrderedProduct;
+
+@RestController
+public class OrderRestEndpoint {
+
+ private final CommandGateway commandGateway;
+ private final QueryGateway queryGateway;
+
+ public OrderRestEndpoint(CommandGateway commandGateway, QueryGateway queryGateway) {
+ this.commandGateway = commandGateway;
+ this.queryGateway = queryGateway;
+ }
+
+ @PostMapping("/ship-order")
+ public void shipOrder() {
+ String orderId = UUID.randomUUID().toString();
+ commandGateway.send(new PlaceOrderCommand(orderId, "Deluxe Chair"));
+ commandGateway.send(new ConfirmOrderCommand(orderId));
+ commandGateway.send(new ShipOrderCommand(orderId));
+ }
+
+ @PostMapping("/ship-unconfirmed-order")
+ public void shipUnconfirmedOrder() {
+ String orderId = UUID.randomUUID().toString();
+ commandGateway.send(new PlaceOrderCommand(orderId, "Deluxe Chair"));
+ // This throws an exception, as an Order cannot be shipped if it has not been confirmed yet.
+ commandGateway.send(new ShipOrderCommand(orderId));
+ }
+
+ @GetMapping("/all-orders")
+ public List findAllOrderedProducts() {
+ return queryGateway.query(new FindAllOrderedProductsQuery(), ResponseTypes.multipleInstancesOf(OrderedProduct.class))
+ .join();
+ }
+
+}
diff --git a/axon/src/main/java/com/baeldung/axon/querymodel/OrderedProductsEventHandler.java b/axon/src/main/java/com/baeldung/axon/querymodel/OrderedProductsEventHandler.java
new file mode 100644
index 0000000000..d4cf3d999b
--- /dev/null
+++ b/axon/src/main/java/com/baeldung/axon/querymodel/OrderedProductsEventHandler.java
@@ -0,0 +1,50 @@
+package com.baeldung.axon.querymodel;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.axonframework.eventhandling.EventHandler;
+import org.axonframework.queryhandling.QueryHandler;
+import org.springframework.stereotype.Service;
+
+import com.baeldung.axon.coreapi.events.OrderConfirmedEvent;
+import com.baeldung.axon.coreapi.events.OrderPlacedEvent;
+import com.baeldung.axon.coreapi.events.OrderShippedEvent;
+import com.baeldung.axon.coreapi.queries.FindAllOrderedProductsQuery;
+import com.baeldung.axon.coreapi.queries.OrderedProduct;
+
+@Service
+public class OrderedProductsEventHandler {
+
+ private final Map orderedProducts = new HashMap<>();
+
+ @EventHandler
+ public void on(OrderPlacedEvent event) {
+ String orderId = event.getOrderId();
+ orderedProducts.put(orderId, new OrderedProduct(orderId, event.getProduct()));
+ }
+
+ @EventHandler
+ public void on(OrderConfirmedEvent event) {
+ orderedProducts.computeIfPresent(event.getOrderId(), (orderId, orderedProduct) -> {
+ orderedProduct.setOrderConfirmed();
+ return orderedProduct;
+ });
+ }
+
+ @EventHandler
+ public void on(OrderShippedEvent event) {
+ orderedProducts.computeIfPresent(event.getOrderId(), (orderId, orderedProduct) -> {
+ orderedProduct.setOrderShipped();
+ return orderedProduct;
+ });
+ }
+
+ @QueryHandler
+ public List handle(FindAllOrderedProductsQuery query) {
+ return new ArrayList<>(orderedProducts.values());
+ }
+
+}
\ No newline at end of file
diff --git a/axon/src/main/resources/order-api.http b/axon/src/main/resources/order-api.http
new file mode 100644
index 0000000000..a3c69c72bc
--- /dev/null
+++ b/axon/src/main/resources/order-api.http
@@ -0,0 +1,11 @@
+POST http://localhost:8080/ship-order
+
+###
+
+POST http://localhost:8080/ship-unconfirmed-order
+
+###
+
+GET http://localhost:8080/all-orders
+
+###
diff --git a/axon/src/test/java/com/baeldung/axon/MessagesAggregateIntegrationTest.java b/axon/src/test/java/com/baeldung/axon/MessagesAggregateIntegrationTest.java
deleted file mode 100644
index ad099d2c2b..0000000000
--- a/axon/src/test/java/com/baeldung/axon/MessagesAggregateIntegrationTest.java
+++ /dev/null
@@ -1,42 +0,0 @@
-package com.baeldung.axon;
-
-import com.baeldung.axon.aggregates.MessagesAggregate;
-import com.baeldung.axon.commands.CreateMessageCommand;
-import com.baeldung.axon.commands.MarkReadMessageCommand;
-import com.baeldung.axon.events.MessageCreatedEvent;
-import com.baeldung.axon.events.MessageReadEvent;
-import org.axonframework.test.aggregate.AggregateTestFixture;
-import org.axonframework.test.aggregate.FixtureConfiguration;
-import org.junit.Before;
-import org.junit.Test;
-
-import java.util.UUID;
-
-public class MessagesAggregateIntegrationTest {
-
- private FixtureConfiguration fixture;
-
- @Before
- public void setUp() throws Exception {
- fixture = new AggregateTestFixture(MessagesAggregate.class);
-
- }
-
- @Test
- public void giveAggregateRoot_whenCreateMessageCommand_thenShouldProduceMessageCreatedEvent() throws Exception {
- String eventText = "Hello, how is your day?";
- String id = UUID.randomUUID().toString();
- fixture.given()
- .when(new CreateMessageCommand(id, eventText))
- .expectEvents(new MessageCreatedEvent(id, eventText));
- }
-
- @Test
- public void givenMessageCreatedEvent_whenReadMessageCommand_thenShouldProduceMessageReadEvent() throws Exception {
- String id = UUID.randomUUID().toString();
-
- fixture.given(new MessageCreatedEvent(id, "Hello :-)"))
- .when(new MarkReadMessageCommand(id))
- .expectEvents(new MessageReadEvent(id));
- }
-}
\ No newline at end of file
diff --git a/axon/src/test/java/com/baeldung/axon/commandmodel/OrderAggregateUnitTest.java b/axon/src/test/java/com/baeldung/axon/commandmodel/OrderAggregateUnitTest.java
new file mode 100644
index 0000000000..9beedbaa19
--- /dev/null
+++ b/axon/src/test/java/com/baeldung/axon/commandmodel/OrderAggregateUnitTest.java
@@ -0,0 +1,61 @@
+package com.baeldung.axon.commandmodel;
+
+import java.util.UUID;
+
+import org.axonframework.test.aggregate.AggregateTestFixture;
+import org.axonframework.test.aggregate.FixtureConfiguration;
+import org.junit.*;
+
+import com.baeldung.axon.coreapi.commands.ConfirmOrderCommand;
+import com.baeldung.axon.coreapi.commands.PlaceOrderCommand;
+import com.baeldung.axon.coreapi.commands.ShipOrderCommand;
+import com.baeldung.axon.coreapi.events.OrderConfirmedEvent;
+import com.baeldung.axon.coreapi.events.OrderPlacedEvent;
+import com.baeldung.axon.coreapi.events.OrderShippedEvent;
+
+public class OrderAggregateUnitTest {
+
+ private FixtureConfiguration fixture;
+
+ @Before
+ public void setUp() {
+ fixture = new AggregateTestFixture<>(OrderAggregate.class);
+ }
+
+ @Test
+ public void giveNoPriorActivity_whenPlaceOrderCommand_thenShouldPublishOrderPlacedEvent() {
+ String orderId = UUID.randomUUID().toString();
+ String product = "Deluxe Chair";
+ fixture.givenNoPriorActivity()
+ .when(new PlaceOrderCommand(orderId, product))
+ .expectEvents(new OrderPlacedEvent(orderId, product));
+ }
+
+ @Test
+ public void givenOrderPlacedEvent_whenConfirmOrderCommand_thenShouldPublishOrderConfirmedEvent() {
+ String orderId = UUID.randomUUID().toString();
+ String product = "Deluxe Chair";
+ fixture.given(new OrderPlacedEvent(orderId, product))
+ .when(new ConfirmOrderCommand(orderId))
+ .expectEvents(new OrderConfirmedEvent(orderId));
+ }
+
+ @Test
+ public void givenOrderPlacedEvent_whenShipOrderCommand_thenShouldThrowIllegalStateException() {
+ String orderId = UUID.randomUUID().toString();
+ String product = "Deluxe Chair";
+ fixture.given(new OrderPlacedEvent(orderId, product))
+ .when(new ShipOrderCommand(orderId))
+ .expectException(IllegalStateException.class);
+ }
+
+ @Test
+ public void givenOrderPlacedEventAndOrderConfirmedEvent_whenShipOrderCommand_thenShouldPublishOrderShippedEvent() {
+ String orderId = UUID.randomUUID().toString();
+ String product = "Deluxe Chair";
+ fixture.given(new OrderPlacedEvent(orderId, product), new OrderConfirmedEvent(orderId))
+ .when(new ShipOrderCommand(orderId))
+ .expectEvents(new OrderShippedEvent(orderId));
+ }
+
+}
\ No newline at end of file
diff --git a/azure/README.md b/azure/README.md
index c60186e1ce..ae8c443660 100644
--- a/azure/README.md
+++ b/azure/README.md
@@ -1,4 +1,4 @@
### Relevant Articles:
-- [Deploy Spring Boot App to Azure](http://www.baeldung.com/spring-boot-azure)
+- [Deploy a Spring Boot App to Azure](http://www.baeldung.com/spring-boot-azure)
diff --git a/azure/pom.xml b/azure/pom.xml
index 555efeef70..270b3e4829 100644
--- a/azure/pom.xml
+++ b/azure/pom.xml
@@ -5,9 +5,9 @@
com.baeldungazure0.1
- warazureDemo project for Spring Boot on Azure
+ warparent-boot-2
@@ -127,7 +127,6 @@
${azure.containerRegistry}.azurecr.io1.1.01.1.0
- 1.8
diff --git a/blade/README.md b/blade/README.md
new file mode 100644
index 0000000000..1f2a00ed3f
--- /dev/null
+++ b/blade/README.md
@@ -0,0 +1,5 @@
+### Relevant Articles:
+
+- [Blade – A Complete Guidebook](http://www.baeldung.com/blade)
+
+Run Integration Tests with `mvn integration-test`
diff --git a/blade/pom.xml b/blade/pom.xml
new file mode 100644
index 0000000000..37615bed01
--- /dev/null
+++ b/blade/pom.xml
@@ -0,0 +1,205 @@
+
+
+ 4.0.0
+
+ com.baeldung
+ blade
+ 1.0.0-SNAPSHOT
+ blade
+
+
+
+
+
+
+
+
+
+
+
+ com.bladejava
+ blade-mvc
+ ${blade-mvc.version}
+
+
+
+ org.webjars
+ bootstrap
+ ${bootstrap.version}
+
+
+
+ org.apache.commons
+ commons-lang3
+ ${commons-lang3.version}
+
+
+
+
+ org.projectlombok
+ lombok
+ ${lombok.version}
+ provided
+
+
+
+
+ junit
+ junit
+ ${junit.version}
+ test
+
+
+ org.assertj
+ assertj-core
+ ${assertj-core.version}
+ test
+
+
+ org.apache.httpcomponents
+ httpclient
+ ${httpclient.version}
+ test
+
+
+ org.apache.httpcomponents
+ httpmime
+ ${httpmime.version}
+ test
+
+
+ org.apache.httpcomponents
+ httpcore
+ ${httpcore.version}
+ test
+
+
+
+ sample-blade-app
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+ ${maven-surefire-plugin.version}
+
+ 3
+ true
+
+ **/*LiveTest.java
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-failsafe-plugin
+ ${maven-failsafe-plugin.version}
+
+
+ **/*LiveTest.java
+
+
+
+
+
+ integration-test
+ verify
+
+
+
+
+
+
+ com.bazaarvoice.maven.plugins
+ process-exec-maven-plugin
+ ${process-exec-maven-plugin.version}
+
+
+
+ blade-process
+ pre-integration-test
+
+ start
+
+
+ Blade
+ false
+
+ java
+ -jar
+ sample-blade-app.jar
+
+
+
+
+
+
+ stop-all
+ post-integration-test
+
+ stop-all
+
+
+
+
+
+
+
+ maven-assembly-plugin
+ 3.1.0
+
+ ${project.build.finalName}
+ false
+
+
+ com.baeldung.blade.sample.App
+
+
+
+ jar-with-dependencies
+
+
+
+
+ make-assembly
+ package
+
+ single
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ ${maven-compiler-plugin.version}
+
+ ${maven.compiler.source}
+ ${maven.compiler.target}
+ UTF-8
+
+
+
+
+
+
+ 1.8
+ 1.8
+ 2.0.14.RELEASE
+ 4.2.1
+ 3.8.1
+ 1.18.4
+ 4.12
+ 4.5.6
+ 4.5.6
+ 4.4.10
+ 3.11.1
+ 3.0.0-M3
+ 0.7
+ 2.21.0
+ 3.7.0
+
+
diff --git a/blade/src/main/java/com/baeldung/blade/sample/App.java b/blade/src/main/java/com/baeldung/blade/sample/App.java
new file mode 100644
index 0000000000..f3f3d4aebd
--- /dev/null
+++ b/blade/src/main/java/com/baeldung/blade/sample/App.java
@@ -0,0 +1,38 @@
+package com.baeldung.blade.sample;
+
+import com.baeldung.blade.sample.interceptors.BaeldungMiddleware;
+import com.blade.Blade;
+import com.blade.event.EventType;
+import com.blade.mvc.WebContext;
+import com.blade.mvc.http.Session;
+
+public class App {
+
+ private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(App.class);
+
+ public static void main(String[] args) {
+
+ Blade.of()
+ .get("/", ctx -> ctx.render("index.html"))
+ .get("/basic-route-example", ctx -> ctx.text("GET called"))
+ .post("/basic-route-example", ctx -> ctx.text("POST called"))
+ .put("/basic-route-example", ctx -> ctx.text("PUT called"))
+ .delete("/basic-route-example", ctx -> ctx.text("DELETE called"))
+ .addStatics("/custom-static")
+ // .showFileList(true)
+ .enableCors(true)
+ .before("/user/*", ctx -> log.info("[NarrowedHook] Before '/user/*', URL called: " + ctx.uri()))
+ .on(EventType.SERVER_STARTED, e -> {
+ String version = WebContext.blade()
+ .env("app.version")
+ .orElse("N/D");
+ log.info("[Event::serverStarted] Loading 'app.version' from configuration, value: " + version);
+ })
+ .on(EventType.SESSION_CREATED, e -> {
+ Session session = (Session) e.attribute("session");
+ session.attribute("mySessionValue", "Baeldung");
+ })
+ .use(new BaeldungMiddleware())
+ .start(App.class, args);
+ }
+}
diff --git a/blade/src/main/java/com/baeldung/blade/sample/AttributesExampleController.java b/blade/src/main/java/com/baeldung/blade/sample/AttributesExampleController.java
new file mode 100644
index 0000000000..339ba701f7
--- /dev/null
+++ b/blade/src/main/java/com/baeldung/blade/sample/AttributesExampleController.java
@@ -0,0 +1,37 @@
+package com.baeldung.blade.sample;
+
+import com.blade.mvc.annotation.GetRoute;
+import com.blade.mvc.annotation.Path;
+import com.blade.mvc.http.Request;
+import com.blade.mvc.http.Response;
+import com.blade.mvc.http.Session;
+
+@Path
+public class AttributesExampleController {
+
+ public final static String REQUEST_VALUE = "Some Request value";
+ public final static String SESSION_VALUE = "1337";
+ public final static String HEADER = "Some Header";
+
+ @GetRoute("/request-attribute-example")
+ public void getRequestAttribute(Request request, Response response) {
+ request.attribute("request-val", REQUEST_VALUE);
+ String requestVal = request.attribute("request-val");
+ response.text(requestVal);
+ }
+
+ @GetRoute("/session-attribute-example")
+ public void getSessionAttribute(Request request, Response response) {
+ Session session = request.session();
+ session.attribute("session-val", SESSION_VALUE);
+ String sessionVal = session.attribute("session-val");
+ response.text(sessionVal);
+ }
+
+ @GetRoute("/header-example")
+ public void getHeader(Request request, Response response) {
+ String headerVal = request.header("a-header", HEADER);
+ response.header("a-header", headerVal);
+ }
+
+}
diff --git a/blade/src/main/java/com/baeldung/blade/sample/LogExampleController.java b/blade/src/main/java/com/baeldung/blade/sample/LogExampleController.java
new file mode 100644
index 0000000000..f0c22c70dd
--- /dev/null
+++ b/blade/src/main/java/com/baeldung/blade/sample/LogExampleController.java
@@ -0,0 +1,22 @@
+package com.baeldung.blade.sample;
+
+import com.blade.mvc.annotation.Path;
+import com.blade.mvc.annotation.Route;
+import com.blade.mvc.http.Response;
+
+@Path
+public class LogExampleController {
+
+ private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(LogExampleController.class);
+
+ @Route(value = "/test-logs")
+ public void testLogs(Response response) {
+ log.trace("This is a TRACE Message");
+ log.debug("This is a DEBUG Message");
+ log.info("This is an INFO Message");
+ log.warn("This is a WARN Message");
+ log.error("This is an ERROR Message");
+ response.text("Check in ./logs");
+ }
+
+}
diff --git a/blade/src/main/java/com/baeldung/blade/sample/ParameterInjectionExampleController.java b/blade/src/main/java/com/baeldung/blade/sample/ParameterInjectionExampleController.java
new file mode 100644
index 0000000000..bc28244022
--- /dev/null
+++ b/blade/src/main/java/com/baeldung/blade/sample/ParameterInjectionExampleController.java
@@ -0,0 +1,71 @@
+package com.baeldung.blade.sample;
+
+import java.nio.file.Files;
+import java.nio.file.StandardOpenOption;
+
+import com.baeldung.blade.sample.vo.User;
+import com.blade.mvc.annotation.CookieParam;
+import com.blade.mvc.annotation.GetRoute;
+import com.blade.mvc.annotation.HeaderParam;
+import com.blade.mvc.annotation.JSON;
+import com.blade.mvc.annotation.MultipartParam;
+import com.blade.mvc.annotation.Param;
+import com.blade.mvc.annotation.Path;
+import com.blade.mvc.annotation.PathParam;
+import com.blade.mvc.annotation.PostRoute;
+import com.blade.mvc.http.Response;
+import com.blade.mvc.multipart.FileItem;
+import com.blade.mvc.ui.RestResponse;
+
+@Path
+public class ParameterInjectionExampleController {
+
+ private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(ParameterInjectionExampleController.class);
+
+ @GetRoute("/params/form")
+ public void formParam(@Param String name, Response response) {
+ log.info("name: " + name);
+ response.text(name);
+ }
+
+ @GetRoute("/params/path/:uid")
+ public void restfulParam(@PathParam Integer uid, Response response) {
+ log.info("uid: " + uid);
+ response.text(String.valueOf(uid));
+ }
+
+ @PostRoute("/params-file") // DO NOT USE A SLASH WITHIN THE ROUTE OR IT WILL BREAK (?)
+ @JSON
+ public RestResponse> fileParam(@MultipartParam FileItem fileItem) throws Exception {
+ try {
+ byte[] fileContent = fileItem.getData();
+
+ log.debug("Saving the uploaded file");
+ java.nio.file.Path tempFile = Files.createTempFile("baeldung_tempfiles", ".tmp");
+ Files.write(tempFile, fileContent, StandardOpenOption.WRITE);
+
+ return RestResponse.ok();
+ } catch (Exception e) {
+ log.error(e.getMessage(), e);
+ return RestResponse.fail(e.getMessage());
+ }
+ }
+
+ @GetRoute("/params/header")
+ public void headerParam(@HeaderParam String customheader, Response response) {
+ log.info("Custom header: " + customheader);
+ response.text(customheader);
+ }
+
+ @GetRoute("/params/cookie")
+ public void cookieParam(@CookieParam(defaultValue = "default value") String myCookie, Response response) {
+ log.info("myCookie: " + myCookie);
+ response.text(myCookie);
+ }
+
+ @PostRoute("/params/vo")
+ public void voParam(@Param User user, Response response) {
+ log.info("user as voParam: " + user.toString());
+ response.html(user.toString() + "
Back");
+ }
+}
\ No newline at end of file
diff --git a/blade/src/main/java/com/baeldung/blade/sample/RouteExampleController.java b/blade/src/main/java/com/baeldung/blade/sample/RouteExampleController.java
new file mode 100644
index 0000000000..7ba2a270a9
--- /dev/null
+++ b/blade/src/main/java/com/baeldung/blade/sample/RouteExampleController.java
@@ -0,0 +1,78 @@
+package com.baeldung.blade.sample;
+
+import com.baeldung.blade.sample.configuration.BaeldungException;
+import com.blade.mvc.WebContext;
+import com.blade.mvc.annotation.DeleteRoute;
+import com.blade.mvc.annotation.GetRoute;
+import com.blade.mvc.annotation.Path;
+import com.blade.mvc.annotation.PostRoute;
+import com.blade.mvc.annotation.PutRoute;
+import com.blade.mvc.annotation.Route;
+import com.blade.mvc.http.HttpMethod;
+import com.blade.mvc.http.Request;
+import com.blade.mvc.http.Response;
+
+@Path
+public class RouteExampleController {
+
+ private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(RouteExampleController.class);
+
+ @GetRoute("/route-example")
+ public String get() {
+ return "get.html";
+ }
+
+ @PostRoute("/route-example")
+ public String post() {
+ return "post.html";
+ }
+
+ @PutRoute("/route-example")
+ public String put() {
+ return "put.html";
+ }
+
+ @DeleteRoute("/route-example")
+ public String delete() {
+ return "delete.html";
+ }
+
+ @Route(value = "/another-route-example", method = HttpMethod.GET)
+ public String anotherGet() {
+ return "get.html";
+ }
+
+ @Route(value = "/allmatch-route-example")
+ public String allmatch() {
+ return "allmatch.html";
+ }
+
+ @Route(value = "/triggerInternalServerError")
+ public void triggerInternalServerError() {
+ int x = 1 / 0;
+ }
+
+ @Route(value = "/triggerBaeldungException")
+ public void triggerBaeldungException() throws BaeldungException {
+ throw new BaeldungException("Foobar Exception to threat differently");
+ }
+
+ @Route(value = "/user/foo")
+ public void urlCoveredByNarrowedWebhook(Response response) {
+ response.text("Check out for the WebHook covering '/user/*' in the logs");
+ }
+
+ @GetRoute("/load-configuration-in-a-route")
+ public void loadConfigurationInARoute(Response response) {
+ String authors = WebContext.blade()
+ .env("app.authors", "Unknown authors");
+ log.info("[/load-configuration-in-a-route] Loading 'app.authors' from configuration, value: " + authors);
+ response.render("index.html");
+ }
+
+ @GetRoute("/template-output-test")
+ public void templateOutputTest(Request request, Response response) {
+ request.attribute("name", "Blade");
+ response.render("template-output-test.html");
+ }
+}
diff --git a/blade/src/main/java/com/baeldung/blade/sample/configuration/BaeldungException.java b/blade/src/main/java/com/baeldung/blade/sample/configuration/BaeldungException.java
new file mode 100644
index 0000000000..01a030b7e7
--- /dev/null
+++ b/blade/src/main/java/com/baeldung/blade/sample/configuration/BaeldungException.java
@@ -0,0 +1,9 @@
+package com.baeldung.blade.sample.configuration;
+
+public class BaeldungException extends RuntimeException {
+
+ public BaeldungException(String message) {
+ super(message);
+ }
+
+}
\ No newline at end of file
diff --git a/blade/src/main/java/com/baeldung/blade/sample/configuration/GlobalExceptionHandler.java b/blade/src/main/java/com/baeldung/blade/sample/configuration/GlobalExceptionHandler.java
new file mode 100644
index 0000000000..ab7b81c0dc
--- /dev/null
+++ b/blade/src/main/java/com/baeldung/blade/sample/configuration/GlobalExceptionHandler.java
@@ -0,0 +1,25 @@
+package com.baeldung.blade.sample.configuration;
+
+import com.blade.ioc.annotation.Bean;
+import com.blade.mvc.WebContext;
+import com.blade.mvc.handler.DefaultExceptionHandler;
+
+@Bean
+public class GlobalExceptionHandler extends DefaultExceptionHandler {
+
+ private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(GlobalExceptionHandler.class);
+
+ @Override
+ public void handle(Exception e) {
+ if (e instanceof BaeldungException) {
+ Exception baeldungException = (BaeldungException) e;
+ String msg = baeldungException.getMessage();
+ log.error("[GlobalExceptionHandler] Intercepted an exception to threat with additional logic. Error message: " + msg);
+ WebContext.response()
+ .render("index.html");
+
+ } else {
+ super.handle(e);
+ }
+ }
+}
\ No newline at end of file
diff --git a/blade/src/main/java/com/baeldung/blade/sample/configuration/LoadConfig.java b/blade/src/main/java/com/baeldung/blade/sample/configuration/LoadConfig.java
new file mode 100644
index 0000000000..0f1aab1b52
--- /dev/null
+++ b/blade/src/main/java/com/baeldung/blade/sample/configuration/LoadConfig.java
@@ -0,0 +1,23 @@
+package com.baeldung.blade.sample.configuration;
+
+import com.blade.Blade;
+import com.blade.ioc.annotation.Bean;
+import com.blade.loader.BladeLoader;
+import com.blade.mvc.WebContext;
+
+@Bean
+public class LoadConfig implements BladeLoader {
+
+ private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(LoadConfig.class);
+
+ @Override
+ public void load(Blade blade) {
+ String version = WebContext.blade()
+ .env("app.version")
+ .orElse("N/D");
+ String authors = WebContext.blade()
+ .env("app.authors", "Unknown authors");
+
+ log.info("[LoadConfig] loaded 'app.version' (" + version + ") and 'app.authors' (" + authors + ") in a configuration bean");
+ }
+}
\ No newline at end of file
diff --git a/blade/src/main/java/com/baeldung/blade/sample/configuration/ScheduleExample.java b/blade/src/main/java/com/baeldung/blade/sample/configuration/ScheduleExample.java
new file mode 100644
index 0000000000..c170975818
--- /dev/null
+++ b/blade/src/main/java/com/baeldung/blade/sample/configuration/ScheduleExample.java
@@ -0,0 +1,15 @@
+package com.baeldung.blade.sample.configuration;
+
+import com.blade.ioc.annotation.Bean;
+import com.blade.task.annotation.Schedule;
+
+@Bean
+public class ScheduleExample {
+
+ private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(ScheduleExample.class);
+
+ @Schedule(name = "baeldungTask", cron = "0 */1 * * * ?")
+ public void runScheduledTask() {
+ log.info("[ScheduleExample] This is a scheduled Task running once per minute.");
+ }
+}
diff --git a/blade/src/main/java/com/baeldung/blade/sample/interceptors/BaeldungHook.java b/blade/src/main/java/com/baeldung/blade/sample/interceptors/BaeldungHook.java
new file mode 100644
index 0000000000..4d0d178b0d
--- /dev/null
+++ b/blade/src/main/java/com/baeldung/blade/sample/interceptors/BaeldungHook.java
@@ -0,0 +1,17 @@
+package com.baeldung.blade.sample.interceptors;
+
+import com.blade.ioc.annotation.Bean;
+import com.blade.mvc.RouteContext;
+import com.blade.mvc.hook.WebHook;
+
+@Bean
+public class BaeldungHook implements WebHook {
+
+ private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(BaeldungHook.class);
+
+ @Override
+ public boolean before(RouteContext ctx) {
+ log.info("[BaeldungHook] called before Route method");
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/blade/src/main/java/com/baeldung/blade/sample/interceptors/BaeldungMiddleware.java b/blade/src/main/java/com/baeldung/blade/sample/interceptors/BaeldungMiddleware.java
new file mode 100644
index 0000000000..3342cd8b01
--- /dev/null
+++ b/blade/src/main/java/com/baeldung/blade/sample/interceptors/BaeldungMiddleware.java
@@ -0,0 +1,15 @@
+package com.baeldung.blade.sample.interceptors;
+
+import com.blade.mvc.RouteContext;
+import com.blade.mvc.hook.WebHook;
+
+public class BaeldungMiddleware implements WebHook {
+
+ private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(BaeldungMiddleware.class);
+
+ @Override
+ public boolean before(RouteContext context) {
+ log.info("[BaeldungMiddleware] called before Route method and other WebHooks");
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/blade/src/main/java/com/baeldung/blade/sample/vo/User.java b/blade/src/main/java/com/baeldung/blade/sample/vo/User.java
new file mode 100644
index 0000000000..b493dc3663
--- /dev/null
+++ b/blade/src/main/java/com/baeldung/blade/sample/vo/User.java
@@ -0,0 +1,16 @@
+package com.baeldung.blade.sample.vo;
+
+import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
+
+import lombok.Getter;
+import lombok.Setter;
+
+public class User {
+ @Getter @Setter private String name;
+ @Getter @Setter private String site;
+
+ @Override
+ public String toString() {
+ return ReflectionToStringBuilder.toString(this);
+ }
+}
\ No newline at end of file
diff --git a/blade/src/main/resources/application.properties b/blade/src/main/resources/application.properties
new file mode 100644
index 0000000000..ebf365406a
--- /dev/null
+++ b/blade/src/main/resources/application.properties
@@ -0,0 +1,5 @@
+mvc.statics.show-list=true
+mvc.view.404=my-404.html
+mvc.view.500=my-500.html
+app.version=0.0.1
+app.authors=Andrea Ligios
diff --git a/blade/src/main/resources/custom-static/icon.png b/blade/src/main/resources/custom-static/icon.png
new file mode 100644
index 0000000000..59af395afc
Binary files /dev/null and b/blade/src/main/resources/custom-static/icon.png differ
diff --git a/blade/src/main/resources/favicon.ico b/blade/src/main/resources/favicon.ico
new file mode 100644
index 0000000000..ca63a6a890
Binary files /dev/null and b/blade/src/main/resources/favicon.ico differ
diff --git a/blade/src/main/resources/static/app.css b/blade/src/main/resources/static/app.css
new file mode 100644
index 0000000000..9fff13d9b6
--- /dev/null
+++ b/blade/src/main/resources/static/app.css
@@ -0,0 +1 @@
+/* App CSS */
\ No newline at end of file
diff --git a/core-java-io/src/main/resources/META-INF/BenchmarkList b/blade/src/main/resources/static/app.js
old mode 100755
new mode 100644
similarity index 100%
rename from core-java-io/src/main/resources/META-INF/BenchmarkList
rename to blade/src/main/resources/static/app.js
diff --git a/blade/src/main/resources/static/file-upload.html b/blade/src/main/resources/static/file-upload.html
new file mode 100644
index 0000000000..b805be81b1
--- /dev/null
+++ b/blade/src/main/resources/static/file-upload.html
@@ -0,0 +1,43 @@
+
+
+
+
+Title
+
+
+
+
+
+
File Upload and download test
+
+
+
+ Back
+
+
+
+
\ No newline at end of file
diff --git a/blade/src/main/resources/static/user-post.html b/blade/src/main/resources/static/user-post.html
new file mode 100644
index 0000000000..ccfc4e8d0b
--- /dev/null
+++ b/blade/src/main/resources/static/user-post.html
@@ -0,0 +1,25 @@
+
+
+
+
+Title
+
+
+
+
+
+
User POJO post test
+
+
+
+
+
+ Back
+
+
+
\ No newline at end of file
diff --git a/blade/src/main/resources/templates/allmatch.html b/blade/src/main/resources/templates/allmatch.html
new file mode 100644
index 0000000000..7a4bfa070f
--- /dev/null
+++ b/blade/src/main/resources/templates/allmatch.html
@@ -0,0 +1 @@
+ALLMATCH called
\ No newline at end of file
diff --git a/blade/src/main/resources/templates/delete.html b/blade/src/main/resources/templates/delete.html
new file mode 100644
index 0000000000..1acb4b0b62
--- /dev/null
+++ b/blade/src/main/resources/templates/delete.html
@@ -0,0 +1 @@
+DELETE called
\ No newline at end of file
diff --git a/blade/src/main/resources/templates/get.html b/blade/src/main/resources/templates/get.html
new file mode 100644
index 0000000000..2c37aa1058
--- /dev/null
+++ b/blade/src/main/resources/templates/get.html
@@ -0,0 +1 @@
+GET called
\ No newline at end of file
diff --git a/blade/src/main/resources/templates/index.html b/blade/src/main/resources/templates/index.html
new file mode 100644
index 0000000000..6b7c2e77ad
--- /dev/null
+++ b/blade/src/main/resources/templates/index.html
@@ -0,0 +1,30 @@
+
+
+
+
+Baeldung Blade App • Written by Andrea Ligios
+
+
+
+
Baeldung Blade App - Showcase
+
+
Manual tests
+
The following are tests which are not covered by integration tests, but that can be run manually in order to check the functionality, either in the browser or in the logs, depending on the case.
+
+
+
+
+
\ No newline at end of file
diff --git a/blade/src/main/resources/templates/my-404.html b/blade/src/main/resources/templates/my-404.html
new file mode 100644
index 0000000000..0fa694f241
--- /dev/null
+++ b/blade/src/main/resources/templates/my-404.html
@@ -0,0 +1,10 @@
+
+
+
+
+ 404 Not found
+
+
+ Custom Error 404 Page
+
+
\ No newline at end of file
diff --git a/blade/src/main/resources/templates/my-500.html b/blade/src/main/resources/templates/my-500.html
new file mode 100644
index 0000000000..cc8438bfd6
--- /dev/null
+++ b/blade/src/main/resources/templates/my-500.html
@@ -0,0 +1,12 @@
+
+
+
+
+ 500 Internal Server Error
+
+
+
Custom Error 500 Page
+
The following error occurred: "${message}"
+
${stackTrace}
+
+
\ No newline at end of file
diff --git a/blade/src/main/resources/templates/post.html b/blade/src/main/resources/templates/post.html
new file mode 100644
index 0000000000..b7a8a931cd
--- /dev/null
+++ b/blade/src/main/resources/templates/post.html
@@ -0,0 +1 @@
+POST called
\ No newline at end of file
diff --git a/blade/src/main/resources/templates/put.html b/blade/src/main/resources/templates/put.html
new file mode 100644
index 0000000000..bdbe6d3285
--- /dev/null
+++ b/blade/src/main/resources/templates/put.html
@@ -0,0 +1 @@
+PUT called
\ No newline at end of file
diff --git a/blade/src/main/resources/templates/template-output-test.html b/blade/src/main/resources/templates/template-output-test.html
new file mode 100644
index 0000000000..233b12fb88
--- /dev/null
+++ b/blade/src/main/resources/templates/template-output-test.html
@@ -0,0 +1 @@
+