javaakkaactorakka-typedactorsystem

Akka - reason: Incompatible types: Behavior<Message> is not convertible to Behavior<Object>


I have an OrderManagerActor that accepts messages from classes that implement the Message interface. This interface is implemented by the following classes CreateOrderMessage, DeleteOrderMessage, UpdateOrderStatusMessage.

When trying to register the createReceive() method in OrderManagerActor

 @Override
    public Receive<Message> createReceive() {
        return ReceiveBuilder.create()
                .onMessage(CreateOrderMessage.class, this::createOrder)
                .build();
    }

I get the following:

reason: Incompatible types: Behavior<Message> is not convertible to Behavior<Object>

Well, I can make sure that all the messages that my Actor receives are Objects, but it seems to me that this will not be entirely correct

OrderManagerActor class

package actor;

import akka.actor.typed.Behavior;
import akka.actor.typed.javadsl.*;
import message.Message;
import message.impl.CreateOrderMessage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class OrderManagerActor extends AbstractBehavior<Message> {
    private final Logger loggerFactory = LoggerFactory.getLogger(OrderManagerActor.class);

    public OrderManagerActor(ActorContext<Message> context) {
        super(context);
    }

    @Override
    public Receive<Message> createReceive() {
        return ReceiveBuilder.create()
                .onMessage(CreateOrderMessage.class, this::createOrder)
                .build();
    }

    private Behavior<Message> createOrder(CreateOrderMessage createOrderMessage) {
        loggerFactory.info(createOrderMessage.toString());
        return this;
    }

    public static Behavior<Message> createBehavior() {
        return Behaviors.setup(OrderManagerActor::new);
    }
}

Message interface:

package message;

public interface Message {
}

Message interface implementation:

package message.impl;

import message.Message;

public class CreateOrderMessage implements Message {
    private String id;

    public CreateOrderMessage(String id) {
        this.id = id;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }
}

UPDATE!

I fixed it, it was need to use a newReceiveBuilder builder.

 @Override
    public Receive<Message> createReceive() {
        return ReceiveBuilder.create()
                .onMessage(CreateOrderMessage.class, this::createOrder)
                .build();
    }

Solution

  • Good that you got it sorted using the factory method, which has an unbounded type parameter allowing the compiler to infer/fill in the type for you.

    It is important to note that Behavior<Message> is in fact not generally convertible to Behavior<Object>.

    A Behavior<Message> means that actors spawned with the behavior can handle messages of type Message and subtypes of Message. Object is not a subtype but a supertype of Message and would mean that you can send any object you want to the actor, which would fail because that is now what it can handle.