📜 ⬆️ ⬇️

Akka for Java developer (part 1)

Recently, quite a lot of programming languages ​​have appeared that are used for the JVM as a platform for execution. One of the hottest topics for discussion lately is Scala. In this article I will not consider it deserved or not, I just want to tell you how you can use the tools of this language using Java and without writing a single line in Scala.

The concept of actors was born long before Scala appeared and was implemented in various programming languages, including Java. To put it in two words, actor is an object that processes messages sent to it. It is important that the messages are immutable (immutable) and the sequence of their processing follows the order of their receipt. Actually, this is the basis of the concept, and then there are implementation features - whether the message queue is preserved for an object, whether it is possible to change the message processing code in the process, whether actor is tied to a thread or a thread pool, the ability to send messages to actor on other machines and etc.

In general, if someone is familiar with JEE, then actor is very similar to Message bean, only the message queue lives inside the JVM.
The author of the Scala language decided to implement the actor concept for the Scala language and called it Akka and is developing this project as a commercial open source. The project is developing quite actively, the current version is 1.1.3 and work is underway on version 2.0, which is going to be released in the fall. There will be support for distributed queues and better organization of clusters.

Why did I choose Akka? Firstly, I wanted to feel a new way of dealing with the complexity of distributed computing and high-load systems. The second and very important is the documentation. About actor'y now only two projects are active JetLang and Akka, and Akka is captivating with detailed documentation for both Java and Scala, with code examples and detailed explanations of where and what. And the third reason is that there is no need to learn a new language in order to take advantage of the use of technology.
')
So, let's begin.

In order to write something using Akka, you need to download the akka.io/downloads distribution kit or connect the following libraries to maven.

< repository > <br> < id > akka.repository </ id > <br> < name > Akka Maven Repository </ name > <br> < url > akka.io/repository </ url > <br> </ repository > <br><br> < dependency > <br> < groupId > se.scalablesolutions.akka </ groupId > <br> < artifactId > akka-actor </ artifactId > <br> < version > 1.1.3 </ version > <br> </ dependency > <br><br> < dependency > <br> < groupId > se.scalablesolutions.akka </ groupId > <br> < artifactId > akka-typed-actor </ artifactId > <br> < version > 1.1.3 </ version > <br> </ dependency > <br><br> * This source code was highlighted with Source Code Highlighter .


In Akka, two types of actors are implemented - UntypedActor and TypedActor. UntypedActor provides a standard interface for processing messages through the onReceive method

import akka.actor.UntypedActor;

public class TestUntypedActor extends UntypedActor {

public void onReceive(Object message) throws Exception {
if (message instanceof MySuperMessage) {
System. out .println( "We've got super message - " + message);
} else if (message instance of String) {
System. out .println( "Process string - " + message);
}
}


* This source code was highlighted with Source Code Highlighter .


Thus, we will get a lot of classes with which you can interact through sending messages.
For TypedActor, you must first describe the interaction interface, and then implement it using actor.

interface RegistrationService {
void register(User user, Credentials cred);
User getUserFor(String username);
}

import akka.actor.TypedActor;

public class RegistrationServiceImpl extends TypedActor implements RegistrationService {
public void register(User user, Credentials cred) {
... //
}

public User getUserFor(String username) {
... //
return user;
}
}


* This source code was highlighted with Source Code Highlighter .


In this case, we will have many classes with interfaces for business logic and implementation using actors. And if you use Spring in your application, then the integration of actors into existing applications will be at the configuration level and will be almost painless (in the following articles I will show how).

So we have actor descriptions and now we need to somehow create instances of classes, because the simple new does not work here. Actors factory is used to create UntypedActor

ActorRef testActor = Actors.actorOf(TestUntypedActor. class );

* This source code was highlighted with Source Code Highlighter .


After creation, the factory returns a reference (ActorRef) to a specific instance of actor, which can be serialized or sent to another machine to send a message to a specific instance (in the case of remote actor).

The following code is used to create the TypedActor.

// - , -
UserService service =
(UserService) TypedActor.newInstance(UserService. class , UserServiceImpl. class );

// TypedActor

UserService service = TypedActor.newInstance(UserService. class , new TypedActorFactory() {
public TypedActor create() {
return new UserServiceImpl( "default user storage" ));
});


* This source code was highlighted with Source Code Highlighter .


Which returns a link to the interface for communicating with actor.

Akka has three types of sending messages to actor's - fire-and-forget (“sent and forgotten”, asynchronous sending a message without waiting for a result), request-reply (“question-answer”, sending a message and waiting for a response, synchronous mode) , request-reply-with-future (“send and receive a reply in the future”, sending a message and receiving a reply further by code using a special object).

For UntypedActor, all three ways look like this.

actorRef.sendOneWay( "Hello" ); //

actorRef.sendOneWay( new MySuperObject(), ontext()); // . context actor' ( ), context().reply()

Object result = actorRef.sendRequestReply( "get result" ); // . context() ( ActorTimeoutException)

Future<MyResult> future = actorRef.sendRequestReplyFuture( "Hello" ); // . context() . Future await ( ), result ( ), exception ( )

* This source code was highlighted with Source Code Highlighter .


For TypedActor, the calling methods depend on the signature of the method. If the method does not return values ​​(void), then the fire-and-forget call is implicitly used. If any object is returned, request-reply is used. If the method returns the value of Future, then request-reply-with-future is used.

Well, the last thing for today - do not forget to start UntypedActors and stop them to free up resources. If you send messages to a not started actor, they will be added to his turn and not processed. Therefore, to understand that something is not working will be difficult.

Source: https://habr.com/ru/post/125717/


All Articles