Akka with java


Hello friends ,

In last few days i was working on a project with akka using java . This was really an amazing experience in akka .

Here we will discuss that how to use Akka in java and write the test case for the same .

If we see documentation of Akka they extends a class named UntypedActor to create an actor .  But here we will discuss about AbstractActor which leads less cost and hence seems  pretty and concise   .

At first add following dependency for Akka and testcase :

"com.typesafe.akka" %% "akka-slf4j" % "2.4.8"

Now to create an actor at first we need to create Props   :

<strong>public static Props props() {</strong>
<strong>    return Props.create(HappyBdayActor.class);</strong>
<strong>}</strong>

Then after we write the responsiblity of an actor as following :

class HappyBdayActor extends AbstractActor {

    public static Props props() {
        return Props.create(HappyBdayActor.class);
    }

   <strong> @Override</strong>
<strong>    public PartialFunction&lt;Object, BoxedUnit&gt; receive() {</strong>
<strong>      //responsiblity of this actor can be here </strong>
<strong>    }</strong>
}

Now  we need to find out the message passed to this actor and perform accordingly .  We can do this as follow :

@Override
public PartialFunction&lt;Object, BoxedUnit&gt; receive() {
       return ReceiveBuilder
            .match(String.class, message -&gt; {
                logger.info("Message received from someone : {}"+ message);
            })
            .matchAny(message -&gt; logger.error("Some unknown things happened : {}", message))
            .build();
}

Now everybody will need an Supervisior . As we know Supervisior is an another Actor to supervise actors .  Following code may be the way to supervise actor :

private final SupervisorStrategy strategy = new OneForOneStrategy(false,
        match(InterruptedException.class, e -&gt;
                SupervisorStrategy.resume()
        ).
                match(Throwable.class, e -&gt;
                        SupervisorStrategy.restart()
                ).build());

@Override
public SupervisorStrategy supervisorStrategy() {
    return strategy;
}

Now Cheers !!! we have an architecture of akka actor.

After that i decided to introduce Google guice injection . So to proceed with this we need to add following dependency at first :

"com.google.inject" % "guice" % "4.1.0"

we will inject our service to actor , so we here go to create a simple service :

@Singleton
public class MessageHandlerService {

    static final String BEAN_NAME = "messageHandlerService";

    public final String substr(String message , int index){
        return "Happy bday "+message.substring(index);
    }
}

Now create an another class to define injections as follow  :

public class Config extends AbstractModule {

    @Override
    protected final void configure() {
        bind(ActorSystem.class).toInstance(ActorSystem.apply());
        bind(MessageHandlerService.class).annotatedWith(Names.named(MessageHandlerService.BEAN_NAME)).
                to(MessageHandlerService.class);
    }

    @Singleton
    @Provides
    @Named(value = Supervisor.BEAN_NAME)
    public final ActorRef supervisorRef(final ActorSystem system) {
        return system.actorOf(Supervisor.props());
    }

    @Provides
    @Inject
    @Named(value = HappyBdayActor.BEAN_NAME)
    public final ActorRef HappyBdayActorRef(@Named(Supervisor.BEAN_NAME) final ActorRef supervisor,
                                            @Named(MessageHandlerService.BEAN_NAME) final MessageHandlerService messageHandlerService) throws Exception {

        CompletionStage&lt;Object&gt; eventFuture = ask(supervisor, HappyBdayActor.props(messageHandlerService),
                Timeout.apply(50, TimeUnit.MILLISECONDS));
        return (ActorRef) eventFuture.toCompletableFuture().get(60, TimeUnit.MILLISECONDS);
    }
}

and also modify the actor as :

final LoggingAdapter logger = Logging.getLogger(context().system(), this);
<strong>public static final String BEAN_NAME = "HappyBdayActorRef";</strong>
<strong>private final MessageHandlerService messageHandlerService;</strong>

<strong>HappyBdayActor(MessageHandlerService messageHandlerServie) {</strong>
<strong>    this.messageHandlerService = messageHandlerServie;</strong>
<strong>}</strong>

public static Props props(<strong>MessageHandlerService messageHandlerService</strong>) {
    return Props.create(HappyBdayActor.class, messageHandlerService);
}

Now we can write our launcher to start actor’s execution as  :

public class Launcher {

    private ActorRef happyBdayActorRef;

    @Inject
    public Launcher(@Named(HappyBdayActor.BEAN_NAME) ActorRef happyBdayActorRef) {
        this.happyBdayActorRef = happyBdayActorRef;
    }

    public ActorRef getHappyBdayActorRef() {
        return happyBdayActorRef;
    }

    public static void main(String[] args) {
        Injector injector = Guice.createInjector(new Config());
        Launcher app = injector.getInstance(Launcher.class);
        app.getHappyBdayActorRef().tell("Hello",ActorRef.noSender());

    }

}

Now we developer always curious about how to write unit test case . so at first add the following sbt dependency :

"junit" % "junit" % "4.12" % "test" exclude("hamcrest-core", "org.hamcrest"),
"com.typesafe.akka" %% "akka-http-testkit" % "2.4.8" % "test",
"org.mockito" % "mockito-core" % "1.10.19" % "test" exclude("hamcrest-core", "org.hamcrest"),
"org.hamcrest" % "hamcrest-all" % "1.3" % "test"

and here we go for unit test case :

public classHappyBdayActor {

 private static ActorSystem system;
 private static MessageHandlerService messageHandlerService;

 @BeforeClass
 public static void setup() {
 system = ActorSystem.create();
 messageHandlerService = mock(MessageHandlerService.class);
 }

 @AfterClass
 public static void teardown() {
 JavaTestKit.shutdownActorSystem(system);
 system = null;
 }

 @Test
 public void testProps() {
 final JavaTestKit probe = new JavaTestKit(system);
 Props props = HappyBdayActor.props(messageHandlerService);
 assertThat(props.actorClass(), is(equalTo(HappyBdayActor.class)));
 }

 @Test
 public void testEventLoggerActorFirebaseRequestMatch() {

 TestProbe probe = TestProbe.apply(system);

 final Props props = HappyBdayActor.props(messageHandlerService);

 when(messageHandlerService.substr("RahulKumar",5))
 .thenReturn(String.valueOf("Kumar"));

 final TestActorRef&lt;HappyBdayActor&gt;happyBdayActorTestActorRef = TestActorRef.create(system, props);
 happyBdayActorTestActorRef.tell("RahulKumar", happyBdayActorTestActorRef);

 probe.expectNoMsg();

 }
}

For complete code click here 

 

Thanks

KNOLDUS-advt-sticker

 

Advertisements

About Rahul Kumar

Software Consultant At Knoldus
This entry was posted in Akka, Java, Scala. Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s