Search code examples
javaakkamatchactor

Java Akka. How to match actor behavior to the many generics


I'm begginer in akka and during my education I have the next question:

For example I have main actor which send messages to other two child actors. Both of them will return the different lists.

    ChildActorA return Optional<List<Entity1>>
    ChildActorB return Optional<List<Entity2>>

How can I match main actor to process theese responses?

Some demonstartion code:

    public class MainActor extends AbstractLoggingActor {

        @Override
        public Receive createReceive() {
            return receiveBuilder()
                    .match(Entity1.class, this::onEntity1)
                    .match(Entity2.class, this::onEntity2)
                   //How match to the list of these entities?
                    .match(Optional<List<Entity1>>, this::onList1)
                    .match(Optional<List<Entity2>>, this::onList2)                  
                    .build();
        }
}


private void onEntity1(Entity1 entity1) {
        final ActorRef entity1ChildActor = getContext().actorOf(Entity1ChildActor.props());

        entity1ChildActor.tell("printIt", getSelf());
    }

    private void onEntity2(Entity2 entity2) {
        final ActorRef entity21ChildActor = getContext().actorOf(Entity2ChildActor.props());

        entity2ChildActor.tell("printIt", getSelf());
    }

One of the children actors:

public class Entity1ChildActor extends AbstractLoggingActor {

    @Override
    public Receive createReceive() {
        return receiveBuilder()
                .match(String.class, this::onPrint)
                .build();
    }

    private void onPrint(Entity1 entity1) {
        System.out.println(entity1);

         //Here I want to tell to parent List of something
         //namely Optional<List<Entity1>>
         //How can I match parent behavior? 

         getSender().tell(someOptionalList, getSelf());
    }

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

Solution

  • Generic type arguments are a compile-time concern. They are lost at runtime. It's called type erasure. So at runtime both Optional<List<Entity1>> and Optional<List<Entity2>> become simply Optional and are indistinguishable by type.

    However, you can create 2 concrete classes to use as messages and encapsulate the optional lists and match against those. Alternatively, you can create 1 concrete class and have it hold the type of entity in a field and expose it, so that you can use it in the predicate of the match method.