Sunday, October 9, 2016

Getting started Akka

I started to learn Akka and came up against several tutorials and fragments of code. Neither of them give the complete example of a simple "HelloWorld" project with the recent Akka release. This post should fill the gap: it gives complete examples of several simple Akka applications. It is recommended to have some reading on Akka documentation site before going on.

Maven dependencies

 <dependency>  
     <groupId>com.typesafe.akka</groupId>  
     <artifactId>akka-actor_2.11</artifactId>  
     <version>2.4.11</version>  
     <scope>provided</scope>  
 </dependency>  

Two styles of actors


The abstract class UntypedActor is the "old-style" root actor. It has an abstract method onReceive, which should be implemented by a concrete actor in the following manner:
 public void onReceive(Object message) throws Exception {
     if (message instanceof Message1) {
        System.out.println("Received Message1");
     }
     else if (message instanceof Message2) {
        System.out.println("Received Message2");
     }
     else {
         unhandled(message);
     }
 }   

Newly Akka releases supports Java 8 with so called Lambda actors. A root class for this style is a class AbstractActor. An actor should implement a call to receive method with arguments, which specify supported messages types and processing to be done. The arguments of receive method should be specified like this:
 (ReceiveBuilder
     .match(Message1.class, m->System.out.println("Message1"))
     .match(Message2.class, m->System.out.println("Message2"))
     .matchAny(m->unhandled(m))
     .build());
The receive arguments may be provided in a constructor or by overriding receive implementation. The list below shows both cases, but in a real actor only one of them should be done:
 public class MyActor extends AbstractActor {  
    static class Message1 {}  
    static class Message2 {}  
    MyActor() {  
         receive(ReceiveBuilder  
                   .match(Message1.class, m->System.out.println("Message1"))  
                   .match(Message2.class, m->System.out.println("Message2"))  
                   .matchAny(m->unhandled(m))  
                   .build());  
    }  
    @Override  
    public PartialFunction<Object, BoxedUnit> receive() {  
         return ReceiveBuilder.match(Message1.class, m->System.out.println("Message1"))  
               .match(Message2.class, m->System.out.println("Message2"))  
               .matchAny(m->unhandled(m))  
               .build();  
    }  

A simple actor example with UntypedActor


A HelloMessager1 actor in the example prints "Hello" each time it receives HelloRequest and counts, how many hello requests arrived.
 public class HelloMessager1 extends UntypedActor {  
      // Protocol  
      static class HelloRequest {                 
      }  
      private static final String HELLO = "Hello";  
      private int counter;  
      public static Props props() {  
           return Props.create(HelloMessager1.class);  
      }  
      @Override  
      public void onReceive(Object message) throws Throwable {  
           if (message instanceof HelloRequest) {  
                sayHello((HelloRequest)message);  
           }  
           else {  
                unhandled(message);  
           }  
      }  
      private void sayHello(HelloRequest message) {            
           System.out.println(HELLO + " #" + (++counter));  
      }  
      public static void main( String[] args ) {  
        ActorSystem system = ActorSystem.create("MySystem");  
        ActorRef messager = system.actorOf(HelloMessager1.props(), "HelloMessager");  
        for (int i=0; i<5; i++) {  
             new Thread(new Runnable() {  
                     @Override  
                     public void run() {  
                          for (int j = 0; j<5; j++) {                           
                               messager.tell(new HelloRequest(), ActorRef.noSender());  
                          }  
                     }                   
             }).start();  
        }  
      System.out.println("The end");  
      system.stop(actor);  
      system.terminate();  
   }  
 }  

A simple actor example with AbstractActor


A HelloMessager2 actor in the example acts the same to the above HelloMessager1 actor, but it is implemented in the different style and so code is more compact.
 public class HelloMessager2 extends AbstractActor {  
      // Protocol  
      static class HelloRequest {                 
      }  
      private static final String HELLO = "Hello";  
      private int counter;  
      public static Props props() {  
           return Props.create(HelloMessager2.class);  
      }  
      public HelloMessager2() {  
           receive(ReceiveBuilder
                .match(HelloRequest.class, this::sayHello)
                .matchAny(this::unhandled)
                .build());
      }  
      private void sayHello(HelloRequest message) {            
           System.out.println(HELLO + " #" + (++counter));  
      }  
      public static void main( String[] args ) {  
        ActorSystem system = ActorSystem.create("MySystem");  
        ActorRef messager = system.actorOf(HelloMessager2.props(), "HelloMessager");  
        for (int i=0; i<5; i++) {  
             new Thread(new Runnable() {  
                     @Override  
                     public void run() {  
                          for (int j = 0; j<5; j++) {                           
                               messager.tell(new HelloRequest(), ActorRef.noSender());  
                          }  
                     }                   
             }).start();  
        }  
      System.out.println("The end");  
      system.stop(actor);  
      system.terminate();  
   }  
 }  
The next post shows examples of actors, which send periodic messages.
Full sources on Git.

No comments :

About the author

My Photo
I trust only simple code and believe that code should be handsome. This is not a matter of technology, but professional approach, consolidated after years of software development. I enjoy to cause things working and feel very happy, when I manage to solve a problem.
Back to Top