Merge remote-tracking branch 'Baeldung/master' into active_mq

# Conflicts:
#	.gitignore
#	LICENSE
#	README.md
#	core-java-modules/README.md
#	core-java-modules/core-java-11/README.md
#	core-java-modules/core-java-11/pom.xml
#	core-java-modules/core-java-8/README.md
#	core-java-modules/core-java-8/pom.xml
#	core-java-modules/core-java-8/src/main/resources/logback.xml
#	core-java-modules/core-java-annotations/README.md
#	core-java-modules/core-java-annotations/pom.xml
#	core-java-modules/core-java-collections-2/README.md
#	core-java-modules/core-java-collections-2/pom.xml
#	core-java-modules/core-java-collections-3/README.md
#	core-java-modules/core-java-collections-3/pom.xml
#	core-java-modules/core-java-collections-conversions-2/README.md
#	core-java-modules/core-java-collections-conversions-2/pom.xml
#	core-java-modules/core-java-collections-conversions/README.md
#	core-java-modules/core-java-collections-conversions/pom.xml
#	core-java-modules/core-java-collections-list/README.md
#	core-java-modules/core-java-collections-list/pom.xml
#	core-java-modules/core-java-collections/pom.xml
#	core-java-modules/core-java-datetime-conversion/README.md
#	core-java-modules/core-java-datetime-conversion/pom.xml
#	core-java-modules/core-java-datetime-conversion/src/test/java/com/baeldung/datetime/ConvertInstantToTimestampUnitTest.java
#	core-java-modules/core-java-io-2/pom.xml
#	core-java-modules/core-java-io/README.md
#	core-java-modules/core-java-io/pom.xml
#	core-java-modules/core-java-io/src/test/resources/fileTest.txt
#	core-java-modules/core-java-io/src/test/resources/sampleTextFile.txt
#	core-java-modules/core-java-lambdas/README.md
#	core-java-modules/core-java-lambdas/pom.xml
#	core-java-modules/core-java-serialization/pom.xml
#	core-java-modules/core-java-streams/README.md
#	core-java-modules/core-java-streams/pom.xml
#	core-java-modules/core-java-strings/README.md
#	core-java-modules/core-java-strings/pom.xml
#	core-java-modules/core-java-strings/src/test/resources/stringtoolong.txt
#	core-java-modules/core-java-uuid/README.md
#	core-java-modules/core-java-uuid/pom.xml
#	core-java-modules/pom.xml
#	image-processing/README.md
#	image-processing/pom.xml
#	image-processing/src/main/java/com/baeldung/imageprocessing/addingtext/AddText.java
#	image-processing/src/main/java/com/baeldung/imageprocessing/opencv/CameraStream.java
#	jackson-modules/jackson-annotations/README.md
#	jackson-modules/jackson-annotations/pom.xml
#	jackson-modules/jackson-conversions-2/README.md
#	jackson-modules/jackson-conversions-2/pom.xml
#	jackson-modules/jackson-conversions/README.md
#	jackson-modules/jackson-conversions/pom.xml
#	jackson-modules/jackson-custom-conversions/README.md
#	jackson-modules/jackson-custom-conversions/pom.xml
#	jackson-modules/jackson-custom-conversions/src/test/java/com/baeldung/defaultserializercustomserializer/CallingDefaultSerializerUnitTest.java
#	jackson-modules/jackson-custom-conversions/src/test/java/com/baeldung/deserialization/CustomDeserializationUnitTest.java
#	jackson-modules/jackson-exceptions/README.md
#	jackson-modules/jackson-exceptions/pom.xml
#	jackson-modules/jackson-exceptions/src/test/java/com/baeldung/exceptions/JacksonExceptionsUnitTest.java
#	jackson-modules/jackson-exceptions/src/test/java/com/baeldung/mappingexception/JacksonMappingExceptionUnitTest.java
#	jackson-modules/pom.xml
#	parent-boot-1/pom.xml
#	parent-boot-2/pom.xml
#	parent-boot-3/pom.xml
#	patterns-modules/design-patterns-architectural/pom.xml
#	patterns-modules/design-patterns-architectural/src/main/java/com/baeldung/repositoryvsdaopattern/UserDaoImpl.java
#	patterns-modules/design-patterns-behavioral-2/README.md
#	patterns-modules/design-patterns-behavioral-2/pom.xml
#	patterns-modules/design-patterns-creational-2/README.md
#	patterns-modules/design-patterns-creational-2/pom.xml
#	patterns-modules/design-patterns-singleton/README.md
#	patterns-modules/design-patterns-structural/src/main/resources/log4jstructuraldp.properties
#	patterns-modules/enterprise-patterns/pom.xml
#	patterns-modules/intercepting-filter/pom.xml
#	patterns-modules/pom.xml
#	persistence-modules/activejdbc/pom.xml
#	persistence-modules/hibernate5/README.md
#	persistence-modules/hibernate5/pom.xml
#	persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/interceptors/CustomInterceptor.java
#	persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/interceptors/entity/User.java
#	persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/namingstrategy/CustomPhysicalNamingStrategy.java
#	persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/persistjson/Customer.java
#	persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/persistjson/HashMapConverter.java
#	persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/pojo/OrderEntryIdClass.java
#	persistence-modules/hibernate5/src/main/java/com/baeldung/hibernate/pojo/OrderEntryPK.java
#	persistence-modules/hibernate5/src/test/java/com/baeldung/hibernate/IdentifiersIntegrationTest.java
#	persistence-modules/hibernate5/src/test/java/com/baeldung/hibernate/bootstrap/BootstrapAPIIntegrationTest.java
#	persistence-modules/hibernate5/src/test/java/com/baeldung/hibernate/proxy/HibernateProxyUnitTest.java
#	persistence-modules/hibernate5/src/test/resources/hibernate-interceptors.properties
#	persistence-modules/hibernate5/src/test/resources/hibernate-lifecycle.properties
#	persistence-modules/hibernate5/src/test/resources/hibernate-namingstrategy.properties
#	persistence-modules/hibernate5/src/test/resources/hibernate-persistjson.properties
#	persistence-modules/hibernate5/src/test/resources/hibernate.properties
#	persistence-modules/pom.xml
#	persistence-modules/spring-data-jpa-crud/pom.xml
#	persistence-modules/spring-data-jpa-crud/src/main/java/com/baeldung/repository/FruitRepository.java
#	persistence-modules/spring-data-jpa-repo-2/README.md
#	persistence-modules/spring-data-jpa-repo-2/pom.xml
#	persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/customrepository/model/User.java
#	persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/customrepository/repository/CustomUserRepositoryImpl.java
#	persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/saveperformance/Book.java
#	persistence-modules/spring-data-jpa-repo-2/src/main/resources/application.properties
#	persistence-modules/spring-data-mongodb-reactive/pom.xml
#	persistence-modules/spring-data-redis/README.md
#	persistence-modules/spring-data-redis/pom.xml
#	persistence-modules/spring-data-redis/src/main/java/com/baeldung/spring/data/reactive/redis/config/RedisConfig.java
#	persistence-modules/spring-data-redis/src/main/java/com/baeldung/spring/data/redis/config/RedisConfig.java
#	persistence-modules/spring-data-redis/src/main/java/com/baeldung/spring/data/redis/model/Student.java
#	persistence-modules/spring-data-redis/src/main/java/com/baeldung/spring/data/redis/queue/RedisMessageSubscriber.java
#	persistence-modules/spring-data-redis/src/test/java/com/baeldung/spring/data/reactive/redis/template/RedisKeyCommandsManualTest.java
#	persistence-modules/spring-data-redis/src/test/java/com/baeldung/spring/data/reactive/redis/template/RedisTemplateListOpsManualTest.java
#	persistence-modules/spring-data-redis/src/test/java/com/baeldung/spring/data/reactive/redis/template/RedisTemplateValueOpsManualTest.java
#	persistence-modules/spring-data-redis/src/test/java/com/baeldung/spring/data/redis/repo/StudentRepositoryManualTest.java
#	pom.xml
#	testing-modules/assertion-libraries/README.md
#	testing-modules/assertion-libraries/pom.xml
#	testing-modules/junit-5-basics/README.md
#	testing-modules/junit-5-basics/pom.xml
#	testing-modules/mockito-2/src/main/java/com/baeldung/nullmatcher/Helper.java
#	testing-modules/mockito-2/src/main/java/com/baeldung/nullmatcher/Main.java
#	testing-modules/mockito-2/src/main/java/com/baeldung/wantedbutnotinvocked/Helper.java
#	testing-modules/mockito-2/src/main/java/com/baeldung/wantedbutnotinvocked/Main.java
#	testing-modules/mockito-2/src/test/java/com/baeldung/nullmatcher/MainUnitTest.java
#	testing-modules/mockito-2/src/test/java/com/baeldung/wantedbutnotinvocked/MainUnitTest.java
#	testing-modules/pom.xml
#	testing-modules/spring-mockito/pom.xml
#	web-modules/dropwizard/pom.xml
#	web-modules/jakarta-ee/README.md
#	web-modules/jakarta-ee/pom.xml
#	web-modules/jakarta-ee/src/test/java/com/baeldung/eclipse/krazo/UserControllerUnitTest.java
#	web-modules/java-lite/pom.xml
#	web-modules/javax-servlets-2/README.md
#	web-modules/javax-servlets-2/pom.xml
#	web-modules/javax-servlets/pom.xml
#	web-modules/jee-7/pom.xml
#	web-modules/jooby/pom.xml
#	web-modules/ninja/pom.xml
#	web-modules/pom.xml
#	web-modules/ratpack/pom.xml
#	web-modules/resteasy/pom.xml
#	web-modules/restx/pom.xml
#	web-modules/spark-java/pom.xml
#	web-modules/vraptor/pom.xml
#	xml/README.md
#	xml/pom.xml
#	xml/src/main/resources/customer-binding.xml
#	xml/src/main/resources/sax/baeldung.xml
#	xml/src/test/resources/example_default_parser.xml
#	xml/src/test/resources/example_dom4j.xml
#	xml/src/test/resources/example_jaxb.xml
#	xml/src/test/resources/example_jaxen.xml
#	xml/src/test/resources/example_jdom.xml
#	xml/src/test/resources/example_stax.xml
#	xml/src/test/resources/sax/baeldung.xml
#	xml/src/test/resources/xml/websites.xml
#	xml/src/test/resources/xml/xee_attribute.xml
This commit is contained in:
YuCheng Hu
2024-04-30 12:23:19 -04:00
27985 changed files with 1594773 additions and 0 deletions
+32
View File
@@ -0,0 +1,32 @@
---
name: Issue Report
about: Report an issue to help us improve
title: '[ISSUE] '
---
**Article and Module Links**
A link to the affected article and the affected module. You can find the link to the module in the Conclusion section in the "on Github" standard phase.
**Describe the Issue**
A clear and concise description of what the issue is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected Behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Environment (please complete the following information):**
- OS: [e.g. Windows]
- Browser [e.g. chrome, safari]
- Version [e.g. 22]
**Additional Context**
Add any other context about the issue here.
+11
View File
@@ -0,0 +1,11 @@
# Contributing to Baeldung Tutorials
First off, thank you for considering contributing to Baeldung Tutorials.
## Reporting Issues
Before you submit an issue, please review the guidelines below:
1. **No Custom Modifications:** If your issue arises from any custom modifications you've made to the code in the repository, we won't be able to assist. We can only help if the issue is reproducible with the untouched codebase from this repo. If you're working with a modified version, consider asking for help on StackOverflow or other relevant forums.
2. **Use a clear and descriptive title** for the issue to identify the problem.
3. **Include a link to the article** you're having issues with.
4. **Describe the exact steps which reproduce the problem** in as many details as possible.
5. **Additional Details:** Offer any other context or descriptions that could be useful. Screenshots, error messages, copy/pasteable snippets, or logs can be immensely helpful.
+3
View File
@@ -0,0 +1,3 @@
## Akka
This module contains modules about Akka.
+7
View File
@@ -0,0 +1,7 @@
## Akka HTTP
This module contains articles about Akka actors.
### Relevant articles:
- [Introduction to Akka Actors in Java](https://www.baeldung.com/akka-actors-java)
+33
View File
@@ -0,0 +1,33 @@
<?xml version="1.0" encoding="UTF-8"?>
<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">
<modelVersion>4.0.0</modelVersion>
<artifactId>akka-actors</artifactId>
<name>akka-actors</name>
<parent>
<groupId>com.baeldung</groupId>
<artifactId>akka-modules</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<dependencies>
<dependency>
<groupId>com.typesafe.akka</groupId>
<artifactId>akka-actor_${scala.version}</artifactId>
<version>${typesafe-akka.version}</version>
</dependency>
<dependency>
<groupId>com.typesafe.akka</groupId>
<artifactId>akka-testkit_${scala.version}</artifactId>
<version>${typesafe-akka.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<properties>
<typesafe-akka.version>2.5.11</typesafe-akka.version>
</properties>
</project>
@@ -0,0 +1,32 @@
package com.baeldung.akkaactors;
import akka.actor.AbstractActor;
import akka.actor.Props;
import akka.event.Logging;
import akka.event.LoggingAdapter;
public class FirstActor extends AbstractActor {
private final LoggingAdapter log = Logging.getLogger(getContext().getSystem(), this);
public static Props props() {
return Props.create(FirstActor.class);
}
@Override
public void preStart() {
log.info("Actor started");
}
@Override
public void postStop() {
log.info("Actor stopped");
}
// Messages will not be handled
@Override
public Receive createReceive() {
return receiveBuilder()
.build();
}
}
@@ -0,0 +1,24 @@
package com.baeldung.akkaactors;
import akka.actor.AbstractActor;
import akka.event.Logging;
import akka.event.LoggingAdapter;
public class MyActor extends AbstractActor {
private final LoggingAdapter log = Logging.getLogger(getContext().getSystem(), this);
@Override
public void postStop() {
log.info("Stopping actor {}", this);
}
public Receive createReceive() {
return receiveBuilder()
.matchEquals("printit", p -> {
System.out.println("The address of this actor is: " + getSelf());
getSender().tell("Got Message", getSelf());
})
.build();
}
}
@@ -0,0 +1,45 @@
package com.baeldung.akkaactors;
import akka.actor.AbstractActor;
import akka.actor.Props;
import akka.event.Logging;
import akka.event.LoggingAdapter;
public class PrinterActor extends AbstractActor {
private final LoggingAdapter log = Logging.getLogger(getContext().getSystem(), this);
public static Props props(String text) {
return Props.create(PrinterActor.class, text);
}
public static final class PrintFinalResult {
Integer totalNumberOfWords;
public PrintFinalResult(Integer totalNumberOfWords) {
this.totalNumberOfWords = totalNumberOfWords;
}
}
@Override
public void preStart() {
log.info("Starting PrinterActor {}", this);
}
@Override
public void postStop() {
log.info("Stopping PrinterActor {}", this);
}
@Override
public Receive createReceive() {
return receiveBuilder()
.match(PrinterActor.PrintFinalResult.class,
r -> {
log.info("Received PrintFinalResult message from " + getSender());
log.info("The text has a total number of {} words", r.totalNumberOfWords);
})
.build();
}
}
@@ -0,0 +1,73 @@
package com.baeldung.akkaactors;
import akka.actor.AbstractActor;
import akka.actor.ActorRef;
import akka.actor.Props;
import akka.event.Logging;
import akka.event.LoggingAdapter;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import static akka.pattern.PatternsCS.ask;
public class ReadingActor extends AbstractActor {
private final LoggingAdapter log = Logging.getLogger(getContext().getSystem(), this);
private String text;
public ReadingActor(String text) {
this.text = text;
}
public static Props props(String text) {
return Props.create(ReadingActor.class, text);
}
public static final class ReadLines {
}
@Override
public void preStart() {
log.info("Starting ReadingActor {}", this);
}
@Override
public void postStop() {
log.info("Stopping ReadingActor {}", this);
}
@Override
public Receive createReceive() {
return receiveBuilder()
.match(ReadLines.class, r -> {
log.info("Received ReadLines message from " + getSender());
String[] lines = text.split("\n");
List<CompletableFuture> futures = new ArrayList<>();
for (int i = 0; i < lines.length; i++) {
String line = lines[i];
ActorRef wordCounterActorRef = getContext().actorOf(Props.create(WordCounterActor.class), "word-counter-" + i);
CompletableFuture<Object> future =
ask(wordCounterActorRef, new WordCounterActor.CountWords(line), 1000).toCompletableFuture();
futures.add(future);
}
Integer totalNumberOfWords = futures.stream()
.map(CompletableFuture::join)
.mapToInt(n -> (Integer) n)
.sum();
ActorRef printerActorRef = getContext().actorOf(Props.create(PrinterActor.class), "Printer-Actor");
printerActorRef.forward(new PrinterActor.PrintFinalResult(totalNumberOfWords), getContext());
// printerActorRef.tell(new PrinterActor.PrintFinalResult(totalNumberOfWords), getSelf());
})
.build();
}
}
@@ -0,0 +1,55 @@
package com.baeldung.akkaactors;
import akka.actor.AbstractActor;
import akka.event.Logging;
import akka.event.LoggingAdapter;
public class WordCounterActor extends AbstractActor {
private final LoggingAdapter log = Logging.getLogger(getContext().getSystem(), this);
public static final class CountWords {
String line;
public CountWords(String line) {
this.line = line;
}
}
@Override
public void preStart() {
log.info("Starting WordCounterActor {}", this);
}
@Override
public Receive createReceive() {
return receiveBuilder()
.match(CountWords.class, r -> {
try {
log.info("Received CountWords message from " + getSender());
int numberOfWords = countWordsFromLine(r.line);
getSender().tell(numberOfWords, getSelf());
} catch (Exception ex) {
getSender().tell(new akka.actor.Status.Failure(ex), getSelf());
throw ex;
}
})
.build();
}
private int countWordsFromLine(String line) throws Exception {
if (line == null) {
throw new IllegalArgumentException("The text to process can't be null!");
}
int numberOfWords = 0;
String[] words = line.split(" ");
for (String possibleWord : words) {
if (possibleWord.trim().length() > 0) {
numberOfWords++;
}
}
return numberOfWords;
}
}
@@ -0,0 +1,104 @@
package com.baeldung.akkaactors;
import akka.actor.ActorRef;
import akka.actor.ActorSystem;
import akka.actor.Props;
import akka.testkit.TestKit;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import scala.concurrent.duration.Duration;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import static akka.pattern.PatternsCS.ask;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
public class AkkaActorsUnitTest {
private static ActorSystem system = null;
@BeforeClass
public static void setup() {
system = ActorSystem.create("test-system");
}
@AfterClass
public static void teardown() {
TestKit.shutdownActorSystem(system, Duration.apply(1000, TimeUnit.MILLISECONDS), true);
system = null;
}
@Test
public void givenAnActor_sendHimAMessageUsingTell() {
final TestKit probe = new TestKit(system);
ActorRef myActorRef = probe.childActorOf(Props.create(MyActor.class));
myActorRef.tell("printit", probe.testActor());
probe.expectMsg("Got Message");
}
@Test
public void givenAnActor_sendHimAMessageUsingAsk() throws ExecutionException, InterruptedException {
final TestKit probe = new TestKit(system);
ActorRef wordCounterActorRef = probe.childActorOf(Props.create(WordCounterActor.class));
CompletableFuture<Object> future =
ask(wordCounterActorRef, new WordCounterActor.CountWords("this is a text"), 1000).toCompletableFuture();
Integer numberOfWords = (Integer) future.get();
assertTrue("The actor should count 4 words", 4 == numberOfWords);
}
@Test
public void givenAnActor_whenTheMessageIsNull_respondWithException() {
final TestKit probe = new TestKit(system);
ActorRef wordCounterActorRef = probe.childActorOf(Props.create(WordCounterActor.class));
CompletableFuture<Object> future =
ask(wordCounterActorRef, new WordCounterActor.CountWords(null), 1000).toCompletableFuture();
try {
future.get(1000, TimeUnit.MILLISECONDS);
} catch (ExecutionException e) {
assertTrue("Invalid error message", e.getMessage().contains("The text to process can't be null!"));
} catch (InterruptedException | TimeoutException e) {
fail("Actor should respond with an exception instead of timing out !");
}
}
@Test
public void givenAnAkkaSystem_countTheWordsInAText() {
ActorSystem system = ActorSystem.create("test-system");
ActorRef myActorRef = system.actorOf(Props.create(MyActor.class), "my-actor");
myActorRef.tell("printit", null);
// system.stop(myActorRef);
// myActorRef.tell(PoisonPill.getInstance(), ActorRef.noSender());
// myActorRef.tell(Kill.getInstance(), ActorRef.noSender());
ActorRef readingActorRef = system.actorOf(ReadingActor.props(TEXT), "readingActor");
readingActorRef.tell(new ReadingActor.ReadLines(), ActorRef.noSender()); //ActorRef.noSender() means the sender ref is akka://test-system/deadLetters
// Future<Terminated> terminateResponse = system.terminate();
}
private static String TEXT = "Lorem Ipsum is simply dummy text\n" +
"of the printing and typesetting industry.\n" +
"Lorem Ipsum has been the industry's standard dummy text\n" +
"ever since the 1500s, when an unknown printer took a galley\n" +
"of type and scrambled it to make a type specimen book.\n" +
" It has survived not only five centuries, but also the leap\n" +
"into electronic typesetting, remaining essentially unchanged.\n" +
" It was popularised in the 1960s with the release of Letraset\n" +
" sheets containing Lorem Ipsum passages, and more recently with\n" +
" desktop publishing software like Aldus PageMaker including\n" +
"versions of Lorem Ipsum.";
}
+7
View File
@@ -0,0 +1,7 @@
## Akka HTTP
This module contains articles about Akka HTTP.
### Relevant articles:
- [Introduction to Akka HTTP](https://www.baeldung.com/akka-http)
+44
View File
@@ -0,0 +1,44 @@
<?xml version="1.0" encoding="UTF-8"?>
<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">
<modelVersion>4.0.0</modelVersion>
<artifactId>akka-http</artifactId>
<name>akka-http</name>
<parent>
<groupId>com.baeldung</groupId>
<artifactId>akka-modules</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<dependencies>
<dependency>
<groupId>com.typesafe.akka</groupId>
<artifactId>akka-http_${scala.version}</artifactId>
<version>${akka.http.version}</version>
</dependency>
<dependency>
<groupId>com.typesafe.akka</groupId>
<artifactId>akka-stream_${scala.version}</artifactId>
<version>${akka.stream.version}</version>
</dependency>
<dependency>
<groupId>com.typesafe.akka</groupId>
<artifactId>akka-http-jackson_${scala.version}</artifactId>
<version>${akka.http.version}</version>
</dependency>
<dependency>
<groupId>com.typesafe.akka</groupId>
<artifactId>akka-http-testkit_${scala.version}</artifactId>
<version>${akka.http.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<properties>
<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,53 @@
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.Ignore;
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());
@Ignore
@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(405);
appRoute.run(HttpRequest.DELETE("/users/42"))
.assertStatusCode(405);
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\"}";
}
}
+7
View File
@@ -0,0 +1,7 @@
## Akka Streams
This module contains articles about Akka Streams.
### Relevant articles
- [Guide to Akka Streams](https://www.baeldung.com/akka-streams)
+32
View File
@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8"?>
<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">
<modelVersion>4.0.0</modelVersion>
<artifactId>akka-streams</artifactId>
<name>akka-streams</name>
<parent>
<groupId>com.baeldung</groupId>
<artifactId>akka-modules</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<dependencies>
<dependency>
<groupId>com.typesafe.akka</groupId>
<artifactId>akka-stream_${scala.version}</artifactId>
<version>${akkastreams.version}</version>
</dependency>
<dependency>
<groupId>com.typesafe.akka</groupId>
<artifactId>akka-stream-testkit_${scala.version}</artifactId>
<version>${akkastreams.version}</version>
</dependency>
</dependencies>
<properties>
<akkastreams.version>2.5.2</akkastreams.version>
</properties>
</project>
@@ -0,0 +1,14 @@
package com.baeldung.akkastreams;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
public class AverageRepository {
CompletionStage<Double> save(Double average) {
return CompletableFuture.supplyAsync(() -> {
System.out.println("saving average: " + average);
return average;
});
}
}
@@ -0,0 +1,74 @@
package com.baeldung.akkastreams;
import akka.Done;
import akka.NotUsed;
import akka.actor.ActorSystem;
import akka.stream.ActorMaterializer;
import akka.stream.javadsl.Flow;
import akka.stream.javadsl.Keep;
import akka.stream.javadsl.Sink;
import akka.stream.javadsl.Source;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
import java.util.stream.Collectors;
public class DataImporter {
private final ActorSystem actorSystem;
private final AverageRepository averageRepository = new AverageRepository();
public DataImporter(ActorSystem actorSystem) {
this.actorSystem = actorSystem;
}
private List<Integer> parseLine(String line) {
String[] fields = line.split(";");
return Arrays.stream(fields)
.map(Integer::parseInt)
.collect(Collectors.toList());
}
private Flow<String, Integer, NotUsed> parseContent() {
return Flow.of(String.class).mapConcat(this::parseLine);
}
private Flow<Integer, Double, NotUsed> computeAverage() {
return Flow.of(Integer.class).grouped(2).mapAsyncUnordered(8, integers ->
CompletableFuture.supplyAsync(() -> integers
.stream()
.mapToDouble(v -> v)
.average()
.orElse(-1.0)));
}
Flow<String, Double, NotUsed> calculateAverage() {
return Flow.of(String.class)
.via(parseContent())
.via(computeAverage());
}
private Sink<Double, CompletionStage<Done>> storeAverages() {
return Flow.of(Double.class)
.mapAsyncUnordered(4, averageRepository::save)
.toMat(Sink.ignore(), Keep.right());
}
CompletionStage<Done> calculateAverageForContent(String content) {
return Source.single(content)
.via(calculateAverage())
.runWith(storeAverages(), ActorMaterializer.create(actorSystem))
.whenComplete((d, e) -> {
if (d != null) {
System.out.println("Import finished ");
} else {
e.printStackTrace();
}
});
}
}
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
</pattern>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="STDOUT" />
</root>
</configuration>
@@ -0,0 +1,43 @@
package com.baeldung.akkastreams;
import akka.NotUsed;
import akka.actor.ActorSystem;
import akka.stream.ActorMaterializer;
import akka.stream.javadsl.Flow;
import akka.stream.javadsl.Source;
import akka.stream.testkit.javadsl.TestSink;
import org.junit.Test;
public class DataImporterUnitTest {
private final ActorSystem actorSystem = ActorSystem.create();
@Test
public void givenStreamOfIntegers_whenCalculateAverageOfPairs_thenShouldReturnProperResults() {
//given
Flow<String, Double, NotUsed> tested = new DataImporter(actorSystem).calculateAverage();
String input = "1;9;11;0";
//when
Source<Double, NotUsed> flow = Source.single(input).via(tested);
//then
flow
.runWith(TestSink.probe(actorSystem), ActorMaterializer.create(actorSystem))
.request(4)
.expectNextUnordered(5d, 5.5);
}
@Test
public void givenStreamOfIntegers_whenCalculateAverageAndSaveToSink_thenShouldFinishSuccessfully() {
//given
DataImporter dataImporter = new DataImporter(actorSystem);
String input = "10;90;110;10";
//when
dataImporter.calculateAverageForContent(input)
.thenAccept(d -> actorSystem.terminate());
}
}
+38
View File
@@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8"?>
<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">
<modelVersion>4.0.0</modelVersion>
<artifactId>akka-modules</artifactId>
<packaging>pom</packaging>
<name>akka-modules</name>
<parent>
<artifactId>parent-modules</artifactId>
<groupId>com.baeldung</groupId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<modules>
<module>akka-actors</module>
<module>akka-http</module>
<module>akka-streams</module>
<module>spring-akka</module>
</modules>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</pluginManagement>
</build>
<properties>
<scala.version>2.12</scala.version>
</properties>
</project>
+6
View File
@@ -0,0 +1,6 @@
## Spring Akka
This module contains articles about Spring with Akka
### Relevant Articles:
- [Introduction to Spring with Akka](https://www.baeldung.com/akka-with-spring)
+50
View File
@@ -0,0 +1,50 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
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>
<artifactId>spring-akka</artifactId>
<version>0.1-SNAPSHOT</version>
<name>spring-akka</name>
<parent>
<groupId>com.baeldung</groupId>
<artifactId>akka-modules</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
<dependency>
<groupId>com.typesafe.akka</groupId>
<artifactId>akka-actor_${scala.version}</artifactId>
<version>${akka.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-framework-bom</artifactId>
<version>${spring.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<properties>
<spring.version>5.3.25</spring.version>
<akka.version>2.4.14</akka.version>
</properties>
</project>
@@ -0,0 +1,24 @@
package com.baeldung.akka;
import akka.actor.ActorSystem;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan
public class AppConfiguration {
@Autowired
private ApplicationContext applicationContext;
@Bean
public ActorSystem actorSystem() {
ActorSystem system = ActorSystem.create("akka-spring-demo");
SpringExtension.SPRING_EXTENSION_PROVIDER.get(system).initialize(applicationContext);
return system;
}
}
@@ -0,0 +1,42 @@
package com.baeldung.akka;
import akka.actor.UntypedActor;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
@Component
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class GreetingActor extends UntypedActor {
private GreetingService greetingService;
public GreetingActor(GreetingService greetingService) {
this.greetingService = greetingService;
}
@Override
public void onReceive(Object message) throws Throwable {
if (message instanceof Greet) {
String name = ((Greet) message).getName();
getSender().tell(greetingService.greet(name), getSelf());
} else {
unhandled(message);
}
}
public static class Greet {
private String name;
public Greet(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
}

Some files were not shown because too many files have changed in this diff Show More