Merge remote-tracking branch 'upstream/master' into BAEL-2564
This commit is contained in:
commit
de366357bb
|
@ -14,7 +14,7 @@ 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`.
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
## Relevant articles:
|
||||
|
||||
- [Introduction to Akka HTTP](https://www.baeldung.com/akka-http)
|
|
@ -0,0 +1,48 @@
|
|||
<?xml version="1.0"?>
|
||||
<project
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
|
||||
xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>akka-http</artifactId>
|
||||
<name>akka-http</name>
|
||||
|
||||
<parent>
|
||||
<artifactId>parent-modules</artifactId>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.typesafe.akka</groupId>
|
||||
<artifactId>akka-http_2.12</artifactId>
|
||||
<version>${akka.http.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.typesafe.akka</groupId>
|
||||
<artifactId>akka-stream_2.12</artifactId>
|
||||
<version>2.5.11</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.typesafe.akka</groupId>
|
||||
<artifactId>akka-http-jackson_2.12</artifactId>
|
||||
<version>${akka.http.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.typesafe.akka</groupId>
|
||||
<artifactId>akka-http-testkit_2.12</artifactId>
|
||||
<version>${akka.http.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||
<java.version>1.8</java.version>
|
||||
<akka.http.version>10.0.11</akka.http.version>
|
||||
<akka.stream.version>2.5.11</akka.stream.version>
|
||||
</properties>
|
||||
</project>
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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<CreateUserMessage> handleCreateUser() {
|
||||
return createUserMessageMessage -> {
|
||||
userService.createUser(createUserMessageMessage.getUser());
|
||||
sender().tell(new ActionPerformed(String.format("User %s created.", createUserMessageMessage.getUser()
|
||||
.getName())), getSelf());
|
||||
};
|
||||
}
|
||||
|
||||
private FI.UnitApply<GetUserMessage> handleGetUser() {
|
||||
return getUserMessageMessage -> {
|
||||
sender().tell(userService.getUser(getUserMessageMessage.getUserId()), getSelf());
|
||||
};
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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<Optional<User>> user = PatternsCS.ask(userActor, new GetUserMessage(id), timeout)
|
||||
.thenApply(obj -> (Optional<User>) 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<ActionPerformed> 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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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<User> 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<User> getUser(Long id) {
|
||||
return users.stream()
|
||||
.filter(user -> user.getId()
|
||||
.equals(id))
|
||||
.findFirst();
|
||||
}
|
||||
|
||||
public void createUser(User user) {
|
||||
users.add(user);
|
||||
}
|
||||
|
||||
public List<User> getUsers(){
|
||||
return users;
|
||||
}
|
||||
|
||||
}
|
|
@ -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\"}";
|
||||
}
|
||||
|
||||
}
|
|
@ -12,4 +12,6 @@
|
|||
- [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)
|
||||
- [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 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)
|
||||
- [Java Two Pointer Technique](https://www.baeldung.com/java-two-pointer-technique)
|
||||
|
|
|
@ -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();
|
||||
|
||||
}
|
|
@ -0,0 +1,123 @@
|
|||
package com.baeldung.algorithms.permutation;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
||||
public class Permutation {
|
||||
|
||||
public static <T> void printAllRecursive(T[] elements, char delimiter) {
|
||||
printAllRecursive(elements.length, elements, delimiter);
|
||||
}
|
||||
|
||||
public static <T> 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 <T> 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 <T extends Comparable<T>> 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 <T> void printRandom(T[] elements, char delimiter) {
|
||||
|
||||
Collections.shuffle(Arrays.asList(elements));
|
||||
printArray(elements, delimiter);
|
||||
}
|
||||
|
||||
private static <T> void swap(T[] elements, int a, int b) {
|
||||
|
||||
T tmp = elements[a];
|
||||
elements[a] = elements[b];
|
||||
elements[b] = tmp;
|
||||
}
|
||||
|
||||
private static <T> 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, ';');
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
package com.baeldung.algorithms.twopointertechnique;
|
||||
|
||||
public class LinkedListFindMiddle {
|
||||
|
||||
public <T> T findMiddle(MyNode<T> head) {
|
||||
MyNode<T> slowPointer = head;
|
||||
MyNode<T> fastPointer = head;
|
||||
|
||||
while (fastPointer.next != null && fastPointer.next.next != null) {
|
||||
fastPointer = fastPointer.next.next;
|
||||
slowPointer = slowPointer.next;
|
||||
}
|
||||
return slowPointer.data;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
package com.baeldung.algorithms.twopointertechnique;
|
||||
|
||||
public class MyNode<E> {
|
||||
MyNode<E> next;
|
||||
E data;
|
||||
|
||||
public MyNode(E value) {
|
||||
data = value;
|
||||
next = null;
|
||||
}
|
||||
|
||||
public MyNode(E value, MyNode<E> n) {
|
||||
data = value;
|
||||
next = n;
|
||||
}
|
||||
|
||||
public void setNext(MyNode<E> n) {
|
||||
next = n;
|
||||
}
|
||||
}
|
|
@ -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--;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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<String> head = createNodesList(8);
|
||||
|
||||
assertThat(linkedListFindMiddle.findMiddle(head)).isEqualTo("4");
|
||||
|
||||
head = createNodesList(9);
|
||||
|
||||
assertThat(linkedListFindMiddle.findMiddle(head)).isEqualTo("5");
|
||||
}
|
||||
|
||||
private static MyNode<String> createNodesList(int n) {
|
||||
|
||||
MyNode<String> head = new MyNode<String>("1");
|
||||
MyNode<String> current = head;
|
||||
|
||||
for (int i = 2; i <= n; i++) {
|
||||
MyNode<String> newNode = new MyNode<String>(String.valueOf(i));
|
||||
current.setNext(newNode);
|
||||
current = newNode;
|
||||
}
|
||||
|
||||
return head;
|
||||
}
|
||||
|
||||
}
|
|
@ -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 });
|
||||
}
|
||||
|
||||
}
|
|
@ -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));
|
||||
}
|
||||
|
||||
}
|
|
@ -15,16 +15,76 @@
|
|||
</parent>
|
||||
|
||||
<dependencies>
|
||||
<!-- https://mvnrepository.com/artifact/org.apache.spark/spark-core_2.10 -->
|
||||
<dependency>
|
||||
<groupId>org.apache.spark</groupId>
|
||||
<artifactId>spark-core_2.10</artifactId>
|
||||
<artifactId>spark-core_2.11</artifactId>
|
||||
<version>${org.apache.spark.spark-core.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.spark</groupId>
|
||||
<artifactId>spark-sql_2.11</artifactId>
|
||||
<version>${org.apache.spark.spark-sql.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.spark</groupId>
|
||||
<artifactId>spark-streaming_2.11</artifactId>
|
||||
<version>${org.apache.spark.spark-streaming.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.spark</groupId>
|
||||
<artifactId>spark-streaming-kafka-0-10_2.11</artifactId>
|
||||
<version>${org.apache.spark.spark-streaming-kafka.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.datastax.spark</groupId>
|
||||
<artifactId>spark-cassandra-connector_2.11</artifactId>
|
||||
<version>${com.datastax.spark.spark-cassandra-connector.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.datastax.spark</groupId>
|
||||
<artifactId>spark-cassandra-connector-java_2.11</artifactId>
|
||||
<version>${com.datastax.spark.spark-cassandra-connector-java.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.2</version>
|
||||
<configuration>
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-assembly-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>single</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<descriptorRefs>
|
||||
<descriptorRef>jar-with-dependencies</descriptorRef>
|
||||
</descriptorRefs>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<properties>
|
||||
<org.apache.spark.spark-core.version>2.2.0</org.apache.spark.spark-core.version>
|
||||
<org.apache.spark.spark-core.version>2.3.0</org.apache.spark.spark-core.version>
|
||||
<org.apache.spark.spark-sql.version>2.3.0</org.apache.spark.spark-sql.version>
|
||||
<org.apache.spark.spark-streaming.version>2.3.0</org.apache.spark.spark-streaming.version>
|
||||
<org.apache.spark.spark-streaming-kafka.version>2.3.0</org.apache.spark.spark-streaming-kafka.version>
|
||||
<com.datastax.spark.spark-cassandra-connector.version>2.3.0</com.datastax.spark.spark-cassandra-connector.version>
|
||||
<com.datastax.spark.spark-cassandra-connector-java.version>1.5.2</com.datastax.spark.spark-cassandra-connector-java.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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<String, Object> 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<String> 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<ConsumerRecord<String, String>> messages = KafkaUtils.createDirectStream(streamingContext, LocationStrategies.PreferConsistent(), ConsumerStrategies.<String, String> Subscribe(topics, kafkaParams));
|
||||
|
||||
JavaPairDStream<String, String> results = messages.mapToPair(record -> new Tuple2<>(record.key(), record.value()));
|
||||
|
||||
JavaDStream<String> lines = results.map(tuple2 -> tuple2._2());
|
||||
|
||||
JavaDStream<String> words = lines.flatMap(x -> Arrays.asList(x.split("\\s+"))
|
||||
.iterator());
|
||||
|
||||
JavaPairDStream<String, Integer> wordCounts = words.mapToPair(s -> new Tuple2<>(s, 1))
|
||||
.reduceByKey((i1, i2) -> i1 + i2);
|
||||
|
||||
wordCounts.foreachRDD(javaRdd -> {
|
||||
Map<String, Integer> wordCountMap = javaRdd.collectAsMap();
|
||||
for (String key : wordCountMap.keySet()) {
|
||||
List<Word> wordList = Arrays.asList(new Word(key, wordCountMap.get(key)));
|
||||
JavaRDD<Word> rdd = streamingContext.sparkContext()
|
||||
.parallelize(wordList);
|
||||
javaFunctions(rdd).writerBuilder("vocabulary", "words", mapToRow(Word.class))
|
||||
.saveToCassandra();
|
||||
}
|
||||
});
|
||||
|
||||
streamingContext.start();
|
||||
streamingContext.awaitTermination();
|
||||
}
|
||||
}
|
|
@ -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<String, Object> 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<String> 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<ConsumerRecord<String, String>> messages = KafkaUtils.createDirectStream(streamingContext, LocationStrategies.PreferConsistent(), ConsumerStrategies.<String, String> Subscribe(topics, kafkaParams));
|
||||
|
||||
JavaPairDStream<String, String> results = messages.mapToPair(record -> new Tuple2<>(record.key(), record.value()));
|
||||
|
||||
JavaDStream<String> lines = results.map(tuple2 -> tuple2._2());
|
||||
|
||||
JavaDStream<String> words = lines.flatMap(x -> Arrays.asList(x.split("\\s+"))
|
||||
.iterator());
|
||||
|
||||
JavaPairDStream<String, Integer> wordCounts = words.mapToPair(s -> new Tuple2<>(s, 1))
|
||||
.reduceByKey((Function2<Integer, Integer, Integer>) (i1, i2) -> i1 + i2);
|
||||
|
||||
JavaMapWithStateDStream<String, Integer, Integer, Tuple2<String, Integer>> cumulativeWordCounts = wordCounts.mapWithState(StateSpec.function((word, one, state) -> {
|
||||
int sum = one.orElse(0) + (state.exists() ? state.get() : 0);
|
||||
Tuple2<String, Integer> output = new Tuple2<>(word, sum);
|
||||
state.update(sum);
|
||||
return output;
|
||||
}));
|
||||
|
||||
cumulativeWordCounts.foreachRDD(javaRdd -> {
|
||||
List<Tuple2<String, Integer>> wordCountList = javaRdd.collect();
|
||||
for (Tuple2<String, Integer> tuple : wordCountList) {
|
||||
List<Word> wordList = Arrays.asList(new Word(tuple._1, tuple._2));
|
||||
JavaRDD<Word> rdd = sparkContext.parallelize(wordList);
|
||||
javaFunctions(rdd).writerBuilder("vocabulary", "words", mapToRow(Word.class))
|
||||
.saveToCassandra();
|
||||
}
|
||||
});
|
||||
|
||||
streamingContext.start();
|
||||
streamingContext.awaitTermination();
|
||||
}
|
||||
}
|
46
axon/pom.xml
46
axon/pom.xml
|
@ -4,29 +4,61 @@
|
|||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>axon</artifactId>
|
||||
<name>axon</name>
|
||||
|
||||
<description>Basic Axon Framework with Spring Boot configuration tutorial</description>
|
||||
|
||||
<parent>
|
||||
<artifactId>parent-modules</artifactId>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
<artifactId>parent-boot-2</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<relativePath>../parent-boot-2</relativePath>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.axonframework</groupId>
|
||||
<artifactId>axon-spring-boot-starter</artifactId>
|
||||
<version>${axon.version}</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.axonframework</groupId>
|
||||
<artifactId>axon-server-connector</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.axonframework</groupId>
|
||||
<artifactId>axon-test</artifactId>
|
||||
<version>${axon.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.axonframework</groupId>
|
||||
<artifactId>axon-core</artifactId>
|
||||
<version>${axon.version}</version>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-autoconfigure</artifactId>
|
||||
<version>2.1.1.RELEASE</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-jpa</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.h2database</groupId>
|
||||
<artifactId>h2</artifactId>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<properties>
|
||||
<axon.version>3.0.2</axon.version>
|
||||
<axon.version>4.0.3</axon.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
|
@ -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<MessagesAggregate> repository =
|
||||
new EventSourcingRepository<>(MessagesAggregate.class, eventStore);
|
||||
|
||||
|
||||
AggregateAnnotationCommandHandler<MessagesAggregate> messagesAggregateAggregateAnnotationCommandHandler =
|
||||
new AggregateAnnotationCommandHandler<MessagesAggregate>(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));
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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));
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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 + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
|
@ -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 + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
|
@ -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 + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
|
@ -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 + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
|
@ -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 + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
|
@ -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 + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
package com.baeldung.axon.coreapi.queries;
|
||||
|
||||
public class FindAllOrderedProductsQuery {
|
||||
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
package com.baeldung.axon.coreapi.queries;
|
||||
|
||||
public enum OrderStatus {
|
||||
|
||||
PLACED, CONFIRMED, SHIPPED
|
||||
|
||||
}
|
|
@ -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 +
|
||||
'}';
|
||||
}
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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<OrderedProduct> findAllOrderedProducts() {
|
||||
return queryGateway.query(new FindAllOrderedProductsQuery(), ResponseTypes.multipleInstancesOf(OrderedProduct.class))
|
||||
.join();
|
||||
}
|
||||
|
||||
}
|
|
@ -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<String, OrderedProduct> 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<OrderedProduct> handle(FindAllOrderedProductsQuery query) {
|
||||
return new ArrayList<>(orderedProducts.values());
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
POST http://localhost:8080/ship-order
|
||||
|
||||
###
|
||||
|
||||
POST http://localhost:8080/ship-unconfirmed-order
|
||||
|
||||
###
|
||||
|
||||
GET http://localhost:8080/all-orders
|
||||
|
||||
###
|
|
@ -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<MessagesAggregate> fixture;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
fixture = new AggregateTestFixture<MessagesAggregate>(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));
|
||||
}
|
||||
}
|
|
@ -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<OrderAggregate> 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));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
### Relevant Articles:
|
||||
|
||||
- [Blade - A Complete GuideBook](http://www.baeldung.com/blade)
|
||||
|
||||
Run Integration Tests with `mvn integration-test`
|
|
@ -0,0 +1,189 @@
|
|||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>blade</artifactId>
|
||||
<name>blade</name>
|
||||
|
||||
<!-- WITH THIS mvn integration-test DOES WORK -->
|
||||
<groupId>com.baeldung</groupId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
|
||||
<!-- WITH THIS mvn integration-test DOESN'T WORK -->
|
||||
<!-- <parent> -->
|
||||
<!-- <groupId>com.baeldung</groupId> -->
|
||||
<!-- <artifactId>parent-modules</artifactId> -->
|
||||
<!-- <version>1.0.0-SNAPSHOT</version> -->
|
||||
<!-- </parent> -->
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>1.8</maven.compiler.source>
|
||||
<maven.compiler.target>1.8</maven.compiler.target>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.bladejava</groupId>
|
||||
<artifactId>blade-mvc</artifactId>
|
||||
<version>2.0.14.RELEASE</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.webjars</groupId>
|
||||
<artifactId>bootstrap</artifactId>
|
||||
<version>4.2.1</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
<version>3.8.1</version>
|
||||
</dependency>
|
||||
|
||||
<!-- PROVIDED -->
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>1.18.4</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- TEST -->
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.12</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.assertj</groupId>
|
||||
<artifactId>assertj-core</artifactId>
|
||||
<version>3.11.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpclient</artifactId>
|
||||
<version>4.5.6</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpmime</artifactId>
|
||||
<version>4.5.6</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpcore</artifactId>
|
||||
<version>4.4.10</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<finalName>sample-blade-app</finalName>
|
||||
<plugins>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<forkCount>3</forkCount>
|
||||
<reuseForks>true</reuseForks>
|
||||
<excludes>
|
||||
<exclude>**/*LiveTest.java</exclude>
|
||||
</excludes>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-failsafe-plugin</artifactId>
|
||||
<version>3.0.0-M3</version>
|
||||
<configuration>
|
||||
<includes>
|
||||
<include>**/*LiveTest.java</include>
|
||||
</includes>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>integration-test</goal>
|
||||
<goal>verify</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>com.bazaarvoice.maven.plugins</groupId>
|
||||
<artifactId>process-exec-maven-plugin</artifactId>
|
||||
<version>0.7</version>
|
||||
<executions>
|
||||
<!--Start Blade -->
|
||||
<execution>
|
||||
<id>blade-process</id>
|
||||
<phase>pre-integration-test</phase>
|
||||
<goals>
|
||||
<goal>start</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<name>Blade</name>
|
||||
<waitForInterrupt>false</waitForInterrupt>
|
||||
<arguments>
|
||||
<argument>java</argument>
|
||||
<argument>-jar</argument>
|
||||
<argument>sample-blade-app.jar</argument>
|
||||
</arguments>
|
||||
</configuration>
|
||||
</execution>
|
||||
|
||||
<!--Stop all processes in reverse order -->
|
||||
<execution>
|
||||
<id>stop-all</id>
|
||||
<phase>post-integration-test</phase>
|
||||
<goals>
|
||||
<goal>stop-all</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
|
||||
<plugin>
|
||||
<artifactId>maven-assembly-plugin</artifactId>
|
||||
<version>3.1.0</version>
|
||||
<configuration>
|
||||
<finalName>${project.build.finalName}</finalName>
|
||||
<appendAssemblyId>false</appendAssemblyId>
|
||||
<archive>
|
||||
<manifest>
|
||||
<mainClass>com.baeldung.blade.sample.App</mainClass>
|
||||
</manifest>
|
||||
</archive>
|
||||
<descriptorRefs>
|
||||
<descriptorRef>jar-with-dependencies</descriptorRef>
|
||||
</descriptorRefs>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>make-assembly</id>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>single</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
<encoding>UTF-8</encoding>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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");
|
||||
}
|
||||
|
||||
}
|
|
@ -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() + "<br/><br/><a href='/'>Back</a>");
|
||||
}
|
||||
}
|
|
@ -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");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
package com.baeldung.blade.sample.configuration;
|
||||
|
||||
public class BaeldungException extends RuntimeException {
|
||||
|
||||
public BaeldungException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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");
|
||||
}
|
||||
}
|
|
@ -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.");
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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
|
Binary file not shown.
After Width: | Height: | Size: 28 KiB |
Binary file not shown.
After Width: | Height: | Size: 650 B |
|
@ -0,0 +1 @@
|
|||
/* App CSS */
|
|
@ -0,0 +1,43 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Title</title>
|
||||
<script src="https://cdn.staticfile.org/jquery/3.3.1/jquery.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
|
||||
<h1>File Upload and download test</h1>
|
||||
<form id="uploadForm" enctype="multipart/form-data">
|
||||
<input id="file" type="file" name="file" />
|
||||
<button id="upload" type="button">Upload</button>
|
||||
</form>
|
||||
|
||||
<br />
|
||||
<a href="/">Back</a>
|
||||
<script>
|
||||
var data = new FormData();
|
||||
|
||||
$('#upload').click(function() {
|
||||
$.ajax({
|
||||
url : '/params-file',
|
||||
type : 'POST',
|
||||
cache : false,
|
||||
data : new FormData($('#uploadForm')[0]),
|
||||
processData : false,
|
||||
contentType : false
|
||||
}).done(function(res) {
|
||||
console.log(res);
|
||||
if (res.success) {
|
||||
alert('Ok');
|
||||
} else {
|
||||
alert(res.msg || 'Error');
|
||||
}
|
||||
}).fail(function(res) {
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,25 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Title</title>
|
||||
<script src="https://cdn.staticfile.org/jquery/3.3.1/jquery.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
|
||||
<h1>User POJO post test</h1>
|
||||
|
||||
|
||||
<form id="uploadForm" action="/params/vo" method="post">
|
||||
<span>Person POJO:</span>
|
||||
<input type="text" name="name" placeholder="name"/>
|
||||
<input type="text" name="site" placeholder="site"/>
|
||||
<button id="upload" type="submit">Send user object</button>
|
||||
</form>
|
||||
|
||||
<br />
|
||||
<a href="/">Back</a>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1 @@
|
|||
ALLMATCH called
|
|
@ -0,0 +1 @@
|
|||
DELETE called
|
|
@ -0,0 +1 @@
|
|||
GET called
|
|
@ -0,0 +1,30 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Baeldung Blade App • Written by Andrea Ligios</title>
|
||||
<link href="/static/app.css" rel="stylesheet" />
|
||||
</head>
|
||||
<body>
|
||||
<h1>Baeldung Blade App - Showcase</h1>
|
||||
|
||||
<h3>Manual tests</h3>
|
||||
<p>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.</p>
|
||||
|
||||
<ul>
|
||||
<li><a href="/static/file-upload.html">File Upload</a></li>
|
||||
<li><a href="/static/user-post.html">User POJO Post</a></li>
|
||||
<li><a href="/user/foo">Webhook narrowed to the '/user/*' URL</a></li>
|
||||
<li><a href="/load-configuration-in-a-route">Load Configuration in a Route</a></li>
|
||||
<li><a href="/triggerInternalServerError">Trigger internal server error (and test the custom error 500 page)</a></li>
|
||||
<li><a href="/triggerBaeldungException">Trigger BaeldungException (and test the Global Exception Handler)</a></li>
|
||||
</ul>
|
||||
|
||||
|
||||
<h3>Session value created in App.java</h3>
|
||||
<p>mySessionValue = ${mySessionValue}</p>
|
||||
|
||||
|
||||
<script src="/static/app.js"></script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,10 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>404 Not found</title>
|
||||
</head>
|
||||
<body>
|
||||
Custom Error 404 Page
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,12 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>500 Internal Server Error</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1> Custom Error 500 Page </h1>
|
||||
<p> The following error occurred: "<strong>${message}</strong>"</p>
|
||||
<pre> ${stackTrace} </pre>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1 @@
|
|||
POST called
|
|
@ -0,0 +1 @@
|
|||
PUT called
|
|
@ -0,0 +1 @@
|
|||
<h1>Hello, ${name}!</h1>
|
|
@ -0,0 +1,56 @@
|
|||
package com.baeldung.blade.sample;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||
import org.apache.http.client.methods.HttpDelete;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.client.methods.HttpPost;
|
||||
import org.apache.http.client.methods.HttpPut;
|
||||
import org.apache.http.client.methods.HttpUriRequest;
|
||||
import org.apache.http.impl.client.HttpClientBuilder;
|
||||
import org.apache.http.util.EntityUtils;
|
||||
import org.junit.Test;
|
||||
|
||||
public class AppLiveTest {
|
||||
|
||||
@Test
|
||||
public void givenBasicRoute_whenGet_thenCorrectOutput() throws Exception {
|
||||
final HttpUriRequest request = new HttpGet("http://localhost:9000/basic-route-example");
|
||||
try (final CloseableHttpResponse httpResponse = HttpClientBuilder.create()
|
||||
.build()
|
||||
.execute(request);) {
|
||||
assertThat(EntityUtils.toString(httpResponse.getEntity())).isEqualTo("GET called");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenBasicRoute_whenPost_thenCorrectOutput() throws Exception {
|
||||
final HttpUriRequest request = new HttpPost("http://localhost:9000/basic-route-example");
|
||||
try (final CloseableHttpResponse httpResponse = HttpClientBuilder.create()
|
||||
.build()
|
||||
.execute(request);) {
|
||||
assertThat(EntityUtils.toString(httpResponse.getEntity())).isEqualTo("POST called");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenBasicRoute_whenPut_thenCorrectOutput() throws Exception {
|
||||
final HttpUriRequest request = new HttpPut("http://localhost:9000/basic-route-example");
|
||||
try (final CloseableHttpResponse httpResponse = HttpClientBuilder.create()
|
||||
.build()
|
||||
.execute(request);) {
|
||||
assertThat(EntityUtils.toString(httpResponse.getEntity())).isEqualTo("PUT called");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenBasicRoute_whenDelete_thenCorrectOutput() throws Exception {
|
||||
final HttpUriRequest request = new HttpDelete("http://localhost:9000/basic-route-example");
|
||||
try (final CloseableHttpResponse httpResponse = HttpClientBuilder.create()
|
||||
.build()
|
||||
.execute(request);) {
|
||||
assertThat(EntityUtils.toString(httpResponse.getEntity())).isEqualTo("DELETE called");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
package com.baeldung.blade.sample;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.client.methods.HttpUriRequest;
|
||||
import org.apache.http.impl.client.HttpClientBuilder;
|
||||
import org.apache.http.util.EntityUtils;
|
||||
import org.junit.Test;
|
||||
|
||||
public class AttributesExampleControllerLiveTest {
|
||||
|
||||
@Test
|
||||
public void givenRequestAttribute_whenSet_thenRetrieveWithGet() throws Exception {
|
||||
final HttpUriRequest request = new HttpGet("http://localhost:9000/request-attribute-example");
|
||||
try (final CloseableHttpResponse httpResponse = HttpClientBuilder.create()
|
||||
.build()
|
||||
.execute(request);) {
|
||||
assertThat(EntityUtils.toString(httpResponse.getEntity())).isEqualTo(AttributesExampleController.REQUEST_VALUE);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenSessionAttribute_whenSet_thenRetrieveWithGet() throws Exception {
|
||||
final HttpUriRequest request = new HttpGet("http://localhost:9000/session-attribute-example");
|
||||
try (final CloseableHttpResponse httpResponse = HttpClientBuilder.create()
|
||||
.build()
|
||||
.execute(request);) {
|
||||
assertThat(EntityUtils.toString(httpResponse.getEntity())).isEqualTo(AttributesExampleController.SESSION_VALUE);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenHeader_whenSet_thenRetrieveWithGet() throws Exception {
|
||||
final HttpUriRequest request = new HttpGet("http://localhost:9000/header-example");
|
||||
request.addHeader("a-header","foobar");
|
||||
try (final CloseableHttpResponse httpResponse = HttpClientBuilder.create()
|
||||
.build()
|
||||
.execute(request);) {
|
||||
assertThat(httpResponse.getHeaders("a-header")[0].getValue()).isEqualTo("foobar");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenNoHeader_whenSet_thenRetrieveDefaultValueWithGet() throws Exception {
|
||||
final HttpUriRequest request = new HttpGet("http://localhost:9000/header-example");
|
||||
try (final CloseableHttpResponse httpResponse = HttpClientBuilder.create()
|
||||
.build()
|
||||
.execute(request);) {
|
||||
assertThat(httpResponse.getHeaders("a-header")[0].getValue()).isEqualTo(AttributesExampleController.HEADER);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
package com.baeldung.blade.sample;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.client.methods.HttpUriRequest;
|
||||
import org.apache.http.client.utils.URIBuilder;
|
||||
import org.apache.http.impl.client.HttpClientBuilder;
|
||||
import org.apache.http.util.EntityUtils;
|
||||
import org.junit.Test;
|
||||
|
||||
public class ParameterInjectionExampleControllerLiveTest {
|
||||
|
||||
@Test
|
||||
public void givenFormParam_whenSet_thenRetrieveWithGet() throws Exception {
|
||||
URIBuilder builder = new URIBuilder("http://localhost:9000/params/form");
|
||||
builder.setParameter("name", "Andrea Ligios");
|
||||
|
||||
final HttpUriRequest request = new HttpGet(builder.build());
|
||||
|
||||
try (final CloseableHttpResponse httpResponse = HttpClientBuilder.create()
|
||||
.build()
|
||||
.execute(request);) {
|
||||
assertThat(EntityUtils.toString(httpResponse.getEntity())).isEqualTo("Andrea Ligios");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenPathParam_whenSet_thenRetrieveWithGet() throws Exception {
|
||||
final HttpUriRequest request = new HttpGet("http://localhost:9000/params/path/1337");
|
||||
|
||||
try (final CloseableHttpResponse httpResponse = HttpClientBuilder.create()
|
||||
.build()
|
||||
.execute(request);) {
|
||||
assertThat(EntityUtils.toString(httpResponse.getEntity())).isEqualTo("1337");
|
||||
}
|
||||
}
|
||||
|
||||
// @Test
|
||||
// public void givenFileParam_whenSet_thenRetrieveWithGet() throws Exception {
|
||||
//
|
||||
// byte[] data = "this is some temp file content".getBytes("UTF-8");
|
||||
// java.nio.file.Path tempFile = Files.createTempFile("baeldung_test_tempfiles", ".tmp");
|
||||
// Files.write(tempFile, data, StandardOpenOption.WRITE);
|
||||
//
|
||||
// //HttpEntity entity = MultipartEntityBuilder.create().addPart("file", new FileBody(tempFile.toFile())).build();
|
||||
// HttpEntity entity = MultipartEntityBuilder.create().addTextBody("field1", "value1")
|
||||
// .addBinaryBody("fileItem", tempFile.toFile(), ContentType.create("application/octet-stream"), "file1.txt").build();
|
||||
//
|
||||
// final HttpPost post = new HttpPost("http://localhost:9000/params-file");
|
||||
// post.setEntity(entity);
|
||||
//
|
||||
// try (final CloseableHttpResponse httpResponse = HttpClientBuilder.create().build().execute(post);) {
|
||||
// assertThat(EntityUtils.toString(httpResponse.getEntity())).isEqualTo("file1.txt");
|
||||
// }
|
||||
// }
|
||||
|
||||
@Test
|
||||
public void givenHeader_whenSet_thenRetrieveWithGet() throws Exception {
|
||||
final HttpUriRequest request = new HttpGet("http://localhost:9000/params/header");
|
||||
request.addHeader("customheader", "foobar");
|
||||
try (final CloseableHttpResponse httpResponse = HttpClientBuilder.create()
|
||||
.build()
|
||||
.execute(request);) {
|
||||
assertThat(EntityUtils.toString(httpResponse.getEntity())).isEqualTo("foobar");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenNoCookie_whenCalled_thenReadDefaultValue() throws Exception {
|
||||
|
||||
final HttpUriRequest request = new HttpGet("http://localhost:9000/params/cookie");
|
||||
try (final CloseableHttpResponse httpResponse = HttpClientBuilder.create()
|
||||
.build()
|
||||
.execute(request);) {
|
||||
assertThat(EntityUtils.toString(httpResponse.getEntity())).isEqualTo("default value");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,117 @@
|
|||
package com.baeldung.blade.sample;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||
import org.apache.http.client.methods.HttpDelete;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.client.methods.HttpPost;
|
||||
import org.apache.http.client.methods.HttpPut;
|
||||
import org.apache.http.client.methods.HttpUriRequest;
|
||||
import org.apache.http.impl.client.HttpClientBuilder;
|
||||
import org.apache.http.util.EntityUtils;
|
||||
import org.junit.Test;
|
||||
|
||||
public class RouteExampleControllerLiveTest {
|
||||
|
||||
@Test
|
||||
public void givenRoute_whenGet_thenCorrectOutput() throws Exception {
|
||||
final HttpUriRequest request = new HttpGet("http://localhost:9000/route-example");
|
||||
try (final CloseableHttpResponse httpResponse = HttpClientBuilder.create()
|
||||
.build()
|
||||
.execute(request);) {
|
||||
assertThat(EntityUtils.toString(httpResponse.getEntity())).isEqualTo("GET called");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenRoute_whenPost_thenCorrectOutput() throws Exception {
|
||||
final HttpUriRequest request = new HttpPost("http://localhost:9000/route-example");
|
||||
try (final CloseableHttpResponse httpResponse = HttpClientBuilder.create()
|
||||
.build()
|
||||
.execute(request);) {
|
||||
assertThat(EntityUtils.toString(httpResponse.getEntity())).isEqualTo("POST called");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenRoute_whenPut_thenCorrectOutput() throws Exception {
|
||||
final HttpUriRequest request = new HttpPut("http://localhost:9000/route-example");
|
||||
try (final CloseableHttpResponse httpResponse = HttpClientBuilder.create()
|
||||
.build()
|
||||
.execute(request);) {
|
||||
assertThat(EntityUtils.toString(httpResponse.getEntity())).isEqualTo("PUT called");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenRoute_whenDelete_thenCorrectOutput() throws Exception {
|
||||
final HttpUriRequest request = new HttpDelete("http://localhost:9000/route-example");
|
||||
try (final CloseableHttpResponse httpResponse = HttpClientBuilder.create()
|
||||
.build()
|
||||
.execute(request);) {
|
||||
assertThat(EntityUtils.toString(httpResponse.getEntity())).isEqualTo("DELETE called");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenAnotherRoute_whenGet_thenCorrectOutput() throws Exception {
|
||||
final HttpUriRequest request = new HttpGet("http://localhost:9000/another-route-example");
|
||||
try (final CloseableHttpResponse httpResponse = HttpClientBuilder.create()
|
||||
.build()
|
||||
.execute(request);) {
|
||||
assertThat(EntityUtils.toString(httpResponse.getEntity())).isEqualTo("GET called");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenAllMatchRoute_whenGet_thenCorrectOutput() throws Exception {
|
||||
final HttpUriRequest request = new HttpGet("http://localhost:9000/allmatch-route-example");
|
||||
try (final CloseableHttpResponse httpResponse = HttpClientBuilder.create()
|
||||
.build()
|
||||
.execute(request);) {
|
||||
assertThat(EntityUtils.toString(httpResponse.getEntity())).isEqualTo("ALLMATCH called");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenAllMatchRoute_whenPost_thenCorrectOutput() throws Exception {
|
||||
final HttpUriRequest request = new HttpPost("http://localhost:9000/allmatch-route-example");
|
||||
try (final CloseableHttpResponse httpResponse = HttpClientBuilder.create()
|
||||
.build()
|
||||
.execute(request);) {
|
||||
assertThat(EntityUtils.toString(httpResponse.getEntity())).isEqualTo("ALLMATCH called");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenAllMatchRoute_whenPut_thenCorrectOutput() throws Exception {
|
||||
final HttpUriRequest request = new HttpPut("http://localhost:9000/allmatch-route-example");
|
||||
try (final CloseableHttpResponse httpResponse = HttpClientBuilder.create()
|
||||
.build()
|
||||
.execute(request);) {
|
||||
assertThat(EntityUtils.toString(httpResponse.getEntity())).isEqualTo("ALLMATCH called");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenAllMatchRoute_whenDelete_thenCorrectOutput() throws Exception {
|
||||
final HttpUriRequest request = new HttpDelete("http://localhost:9000/allmatch-route-example");
|
||||
try (final CloseableHttpResponse httpResponse = HttpClientBuilder.create()
|
||||
.build()
|
||||
.execute(request);) {
|
||||
assertThat(EntityUtils.toString(httpResponse.getEntity())).isEqualTo("ALLMATCH called");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenRequestAttribute_whenRenderedWithTemplate_thenCorrectlyEvaluateIt() throws Exception {
|
||||
final HttpUriRequest request = new HttpGet("http://localhost:9000/template-output-test");
|
||||
try (final CloseableHttpResponse httpResponse = HttpClientBuilder.create()
|
||||
.build()
|
||||
.execute(request);) {
|
||||
assertThat(EntityUtils.toString(httpResponse.getEntity())).isEqualTo("<h1>Hello, Blade!</h1>");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -2,4 +2,4 @@
|
|||
|
||||
- [Java 11 Single File Source Code](https://www.baeldung.com/java-single-file-source-code)
|
||||
- [Java 11 Local Variable Syntax for Lambda Parameters](https://www.baeldung.com/java-var-lambda-params)
|
||||
|
||||
- [Java 11 String API Additions](https://www.baeldung.com/java-11-string-api)
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
package com.baeldung;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public class Outer {
|
||||
|
||||
public void outerPublic() {
|
||||
}
|
||||
|
||||
private void outerPrivate() {
|
||||
}
|
||||
|
||||
class Inner {
|
||||
|
||||
public void innerPublic() {
|
||||
outerPrivate();
|
||||
}
|
||||
|
||||
public void innerPublicReflection(Outer ob) throws Exception {
|
||||
Method method = ob.getClass().getDeclaredMethod("outerPrivate");
|
||||
method.invoke(ob);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
package com.baeldung;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import org.junit.Test;
|
||||
|
||||
public class OuterUnitTest {
|
||||
|
||||
private static final String NEST_HOST_NAME = "com.baeldung.Outer";
|
||||
|
||||
@Test
|
||||
public void whenGetNestHostFromOuter_thenGetNestHost() {
|
||||
is(Outer.class.getNestHost().getName()).equals(NEST_HOST_NAME);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenGetNestHostFromInner_thenGetNestHost() {
|
||||
is(Outer.Inner.class.getNestHost().getName()).equals(NEST_HOST_NAME);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenCheckNestmatesForNestedClasses_thenGetTrue() {
|
||||
is(Outer.Inner.class.isNestmateOf(Outer.class)).equals(true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenCheckNestmatesForUnrelatedClasses_thenGetFalse() {
|
||||
is(Outer.Inner.class.isNestmateOf(Outer.class)).equals(false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenGetNestMembersForNestedClasses_thenGetAllNestedClasses() {
|
||||
Set<String> nestMembers = Arrays.stream(Outer.Inner.class.getNestMembers())
|
||||
.map(Class::getName)
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
is(nestMembers.size()).equals(2);
|
||||
|
||||
assertTrue(nestMembers.contains("com.baeldung.Outer"));
|
||||
assertTrue(nestMembers.contains("com.baeldung.Outer$Inner"));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
package com.baeldung.optional;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link Optional} in Java 11.
|
||||
*/
|
||||
public class OptionalUnitTest {
|
||||
|
||||
@Test
|
||||
public void givenAnEmptyOptional_isEmpty_thenBehavesAsExpected() {
|
||||
Optional<String> opt = Optional.of("Baeldung");
|
||||
assertFalse(opt.isEmpty());
|
||||
|
||||
opt = Optional.ofNullable(null);
|
||||
assertTrue(opt.isEmpty());
|
||||
}
|
||||
}
|
|
@ -33,3 +33,8 @@
|
|||
- [Java Primitives versus Objects](https://www.baeldung.com/java-primitives-vs-objects)
|
||||
- [How to Use if/else Logic in Java 8 Streams](https://www.baeldung.com/java-8-streams-if-else-logic)
|
||||
- [How to Replace Many if Statements in Java](https://www.baeldung.com/java-replace-if-statements)
|
||||
- [Java @Override Annotation](https://www.baeldung.com/java-override)
|
||||
- [Java @SuppressWarnings Annotation](https://www.baeldung.com/java-suppresswarnings)
|
||||
- [Java @SafeVarargs Annotation](https://www.baeldung.com/java-safevarargs)
|
||||
- [Java @Deprecated Annotation](https://www.baeldung.com/java-deprecated)
|
||||
- [Java 8 Predicate Chain](https://www.baeldung.com/java-predicate-chain)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>core-java-8</artifactId>
|
||||
|
@ -104,6 +104,24 @@
|
|||
<artifactId>aspectjweaver</artifactId>
|
||||
<version>${asspectj.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.powermock</groupId>
|
||||
<artifactId>powermock-module-junit4</artifactId>
|
||||
<version>${powermock.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.powermock</groupId>
|
||||
<artifactId>powermock-api-mockito2</artifactId>
|
||||
<version>${powermock.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jmockit</groupId>
|
||||
<artifactId>jmockit</artifactId>
|
||||
<version>${jmockit.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
@ -119,7 +137,7 @@
|
|||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.1</version>
|
||||
<version>${maven-compiler-plugin.version}</version>
|
||||
<configuration>
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
|
@ -142,6 +160,16 @@
|
|||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>${maven-surefire-plugin.version}</version>
|
||||
<configuration>
|
||||
<argLine>
|
||||
-javaagent:${settings.localRepository}/org/jmockit/jmockit/${jmockit.version}/jmockit-${jmockit.version}.jar
|
||||
</argLine>
|
||||
<disableXmlReport>true</disableXmlReport>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
|
@ -159,9 +187,14 @@
|
|||
<!-- testing -->
|
||||
<assertj.version>3.6.1</assertj.version>
|
||||
<asspectj.version>1.8.9</asspectj.version>
|
||||
<powermock.version>2.0.0-RC.4</powermock.version>
|
||||
<jmockit.version>1.44</jmockit.version>
|
||||
<avaitility.version>1.7.0</avaitility.version>
|
||||
<jmh-core.version>1.19</jmh-core.version>
|
||||
<jmh-generator.version>1.19</jmh-generator.version>
|
||||
<spring-boot-maven-plugin.version>2.0.4.RELEASE</spring-boot-maven-plugin.version>
|
||||
<!-- plugins -->
|
||||
<maven-compiler-plugin.version>3.8.0</maven-compiler-plugin.version>
|
||||
<maven-surefire-plugin.version>2.22.1</maven-surefire-plugin.version>
|
||||
</properties>
|
||||
</project>
|
||||
|
|
|
@ -1,21 +0,0 @@
|
|||
package com.baeldung.interfaces.polymorphysim;
|
||||
|
||||
public class Circle implements Shape {
|
||||
|
||||
private double radius;
|
||||
|
||||
public Circle(double radius){
|
||||
this.radius = radius;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String name() {
|
||||
return "Circle";
|
||||
}
|
||||
|
||||
@Override
|
||||
public double area() {
|
||||
return Math.PI * (radius * radius);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
package com.baeldung.interfaces.polymorphysim;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class DisplayShape {
|
||||
|
||||
private ArrayList<Shape> shapes;
|
||||
|
||||
public DisplayShape() {
|
||||
shapes = new ArrayList<>();
|
||||
}
|
||||
|
||||
public void add(Shape shape) {
|
||||
shapes.add(shape);
|
||||
}
|
||||
|
||||
public void display() {
|
||||
for (Shape shape : shapes) {
|
||||
System.out.println(shape.name() + " area: " + shape.area());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
package com.baeldung.interfaces.polymorphysim;
|
||||
|
||||
public class MainPolymorphic {
|
||||
public static void main(String[] args){
|
||||
|
||||
Shape circleShape = new Circle(2);
|
||||
Shape squareShape = new Square(2);
|
||||
|
||||
DisplayShape displayShape = new DisplayShape();
|
||||
displayShape.add(circleShape);
|
||||
displayShape.add(squareShape);
|
||||
|
||||
displayShape.display();
|
||||
}
|
||||
}
|
|
@ -1,20 +0,0 @@
|
|||
package com.baeldung.interfaces.polymorphysim;
|
||||
|
||||
public class Square implements Shape {
|
||||
|
||||
private double width;
|
||||
|
||||
public Square(double width) {
|
||||
this.width = width;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String name() {
|
||||
return "Square";
|
||||
}
|
||||
|
||||
@Override
|
||||
public double area() {
|
||||
return width * width;
|
||||
}
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
package com.baeldung.interfaces;
|
||||
|
||||
import com.baeldung.interfaces.polymorphysim.Circle;
|
||||
import com.baeldung.interfaces.polymorphysim.Shape;
|
||||
import com.baeldung.interfaces.polymorphysim.Square;
|
||||
import org.assertj.core.api.Assertions;
|
||||
import org.junit.Test;
|
||||
|
||||
public class PolymorphysimUnitTest {
|
||||
|
||||
@Test
|
||||
public void whenInterfacePointsToCircle_CircleAreaMethodisBeingCalled(){
|
||||
double expectedArea = 12.566370614359172;
|
||||
Shape circle = new Circle(2);
|
||||
double actualArea = circle.area();
|
||||
Assertions.assertThat(actualArea).isEqualTo(expectedArea);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenInterfacePointsToSquare_SquareAreaMethodisBeingCalled(){
|
||||
double expectedArea = 4;
|
||||
Shape square = new Square(2);
|
||||
double actualArea = square.area();
|
||||
Assertions.assertThat(actualArea).isEqualTo(expectedArea);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
package com.baeldung.time;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.powermock.core.classloader.annotations.PrepareForTest;
|
||||
import org.powermock.modules.junit4.PowerMockRunner;
|
||||
|
||||
import java.time.Clock;
|
||||
import java.time.Instant;
|
||||
import java.time.ZoneId;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.powermock.api.mockito.PowerMockito.mockStatic;
|
||||
|
||||
@RunWith(PowerMockRunner.class)
|
||||
@PrepareForTest({ Instant.class })
|
||||
public class InstantUnitTest {
|
||||
|
||||
@Test
|
||||
public void givenInstantMock_whenNow_thenGetFixedInstant() {
|
||||
String instantExpected = "2014-12-22T10:15:30Z";
|
||||
Clock clock = Clock.fixed(Instant.parse(instantExpected), ZoneId.of("UTC"));
|
||||
Instant instant = Instant.now(clock);
|
||||
mockStatic(Instant.class);
|
||||
when(Instant.now()).thenReturn(instant);
|
||||
|
||||
Instant now = Instant.now();
|
||||
|
||||
assertThat(now.toString()).isEqualTo(instantExpected);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenFixedClock_whenNow_thenGetFixedInstant() {
|
||||
String instantExpected = "2014-12-22T10:15:30Z";
|
||||
Clock clock = Clock.fixed(Instant.parse(instantExpected), ZoneId.of("UTC"));
|
||||
|
||||
Instant instant = Instant.now(clock);
|
||||
|
||||
assertThat(instant.toString()).isEqualTo(instantExpected);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
package com.baeldung.time;
|
||||
|
||||
import mockit.Expectations;
|
||||
import mockit.Mock;
|
||||
import mockit.MockUp;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.time.Clock;
|
||||
import java.time.Instant;
|
||||
import java.time.ZoneId;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class InstantWithJMockUnitTest {
|
||||
|
||||
@Test
|
||||
public void givenInstantWithJMock_whenNow_thenGetFixedInstant() {
|
||||
String instantExpected = "2014-12-21T10:15:30Z";
|
||||
Clock clock = Clock.fixed(Instant.parse(instantExpected), ZoneId.of("UTC"));
|
||||
new MockUp<Instant>() {
|
||||
@Mock
|
||||
public Instant now() {
|
||||
return Instant.now(clock);
|
||||
}
|
||||
};
|
||||
|
||||
Instant now = Instant.now();
|
||||
|
||||
assertThat(now.toString()).isEqualTo(instantExpected);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenInstantWithExpectations_whenNow_thenGetFixedInstant() {
|
||||
Clock clock = Clock.fixed(Instant.parse("2014-12-23T10:15:30.00Z"), ZoneId.of("UTC"));
|
||||
Instant instantExpected = Instant.now(clock);
|
||||
new Expectations(Instant.class) {
|
||||
{
|
||||
Instant.now();
|
||||
result = instantExpected;
|
||||
}
|
||||
};
|
||||
|
||||
Instant now = Instant.now();
|
||||
|
||||
assertThat(now).isEqualTo(instantExpected);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
package com.baeldung.time;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.powermock.core.classloader.annotations.PrepareForTest;
|
||||
import org.powermock.modules.junit4.PowerMockRunner;
|
||||
|
||||
import java.time.Clock;
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneId;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.powermock.api.mockito.PowerMockito.mockStatic;
|
||||
|
||||
@RunWith(PowerMockRunner.class)
|
||||
@PrepareForTest({ LocalDateTime.class })
|
||||
public class LocalDateTimeUnitTest {
|
||||
|
||||
@Test
|
||||
public void givenLocalDateTimeMock_whenNow_thenGetFixedLocalDateTime() {
|
||||
Clock clock = Clock.fixed(Instant.parse("2014-12-22T10:15:30.00Z"), ZoneId.of("UTC"));
|
||||
LocalDateTime dateTime = LocalDateTime.now(clock);
|
||||
mockStatic(LocalDateTime.class);
|
||||
when(LocalDateTime.now()).thenReturn(dateTime);
|
||||
String dateTimeExpected = "2014-12-22T10:15:30";
|
||||
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
|
||||
assertThat(now).isEqualTo(dateTimeExpected);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenFixedClock_whenNow_thenGetFixedLocalDateTime() {
|
||||
Clock clock = Clock.fixed(Instant.parse("2014-12-22T10:15:30.00Z"), ZoneId.of("UTC"));
|
||||
String dateTimeExpected = "2014-12-22T10:15:30";
|
||||
|
||||
LocalDateTime dateTime = LocalDateTime.now(clock);
|
||||
|
||||
assertThat(dateTime).isEqualTo(dateTimeExpected);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
package com.baeldung.time;
|
||||
|
||||
import mockit.Expectations;
|
||||
import mockit.Mock;
|
||||
import mockit.MockUp;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.time.Clock;
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneId;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class LocalDateTimeWithJMockUnitTest {
|
||||
|
||||
@Test
|
||||
public void givenLocalDateTimeWithJMock_whenNow_thenGetFixedLocalDateTime() {
|
||||
Clock clock = Clock.fixed(Instant.parse("2014-12-21T10:15:30.00Z"), ZoneId.of("UTC"));
|
||||
new MockUp<LocalDateTime>() {
|
||||
@Mock
|
||||
public LocalDateTime now() {
|
||||
return LocalDateTime.now(clock);
|
||||
}
|
||||
};
|
||||
String dateTimeExpected = "2014-12-21T10:15:30";
|
||||
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
|
||||
assertThat(now).isEqualTo(dateTimeExpected);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenLocalDateTimeWithExpectations_whenNow_thenGetFixedLocalDateTime() {
|
||||
Clock clock = Clock.fixed(Instant.parse("2014-12-23T10:15:30.00Z"), ZoneId.of("UTC"));
|
||||
LocalDateTime dateTimeExpected = LocalDateTime.now(clock);
|
||||
new Expectations(LocalDateTime.class) {
|
||||
{
|
||||
LocalDateTime.now();
|
||||
result = dateTimeExpected;
|
||||
}
|
||||
};
|
||||
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
|
||||
assertThat(now).isEqualTo(dateTimeExpected);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
package com.baeldung.java9.set;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public class UnmodifiableSet {
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
Set<String> set = new HashSet<>();
|
||||
set.add("Canada");
|
||||
set.add("USA");
|
||||
|
||||
coreJDK(set);
|
||||
guavaOf();
|
||||
copyOf(set);
|
||||
java9Of();
|
||||
}
|
||||
|
||||
private static void java9Of() {
|
||||
Set<String> immutable = Set.of("Canada", "USA");
|
||||
System.out.println(immutable);
|
||||
}
|
||||
|
||||
private static void guavaOf() {
|
||||
Set<String> immutable = ImmutableSet.of("Canada", "USA");
|
||||
System.out.println(immutable);
|
||||
}
|
||||
|
||||
private static void copyOf(Set<String> set) {
|
||||
Set<String> immutable = ImmutableSet.copyOf(set);
|
||||
set.add("Costa Rica");
|
||||
System.out.println(immutable);
|
||||
}
|
||||
|
||||
private static void coreJDK(Set<String> set) {
|
||||
Set<String> unmodifiableSet = Collections.unmodifiableSet(set);
|
||||
set.add("Costa Rica");
|
||||
System.out.println(unmodifiableSet);
|
||||
}
|
||||
}
|
|
@ -1,5 +1,7 @@
|
|||
package com.baeldung.java9;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import org.junit.Test;
|
||||
|
||||
|
@ -23,4 +25,14 @@ public class SetExamplesUnitTest {
|
|||
Set<Integer> intSet = Set.of(intArray);
|
||||
assertEquals(intSet.size(), intArray.length);
|
||||
}
|
||||
|
||||
@Test(expected = UnsupportedOperationException.class)
|
||||
public void testUnmodifiableSet() {
|
||||
Set<String> set = new HashSet<>();
|
||||
set.add("Canada");
|
||||
set.add("USA");
|
||||
|
||||
Set<String> unmodifiableSet = Collections.unmodifiableSet(set);
|
||||
unmodifiableSet.add("Costa Rica");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,3 +13,4 @@
|
|||
- [How to Invert an Array in Java](http://www.baeldung.com/java-invert-array)
|
||||
- [Array Operations in Java](http://www.baeldung.com/java-common-array-operations)
|
||||
- [Intersection Between two Integer Arrays](https://www.baeldung.com/java-array-intersection)
|
||||
- [Sorting Arrays in Java](https://www.baeldung.com/java-sorting-arrays)
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue