Use стать() из Java

Я использую Akka с Java. Согласно документации, context.become() принимает Procedure<Object> в качестве параметра. Фактически, он ожидает PartialFunction<Object, BoxedUnit>, который, кажется, является автогенерированным с множеством методов со странными именами.

Каков правильный способ использования функции get() из Java?

PS я использую Akka 2.0.3

Обновление: Похоже, существуют два метода: context() и getContext(). Первый возвращает ActorContext, а второй возвращает UntypedActorContext. UntypedActorContext имеет become(Procedure<Object>).

Ответ 1

Вы вводите в заблуждение Akka Java и Scala API. Технически вы можете использовать Scala библиотеки, такие как Akka, из Java-кода, но довольно часто это многословно и громоздко. Поэтому команда Akka решила разработать отдельные API-интерфейсы - родные в Scala и Java-адаптере.

В Scala API вы расширяете akka.actor.Actor, у которого есть поле context типа akka.actor.ActorContext. Этот ActorContext.become() принимает PartialFunction, который является Scala -специфическим классом.

С другой стороны, в Java API вы расширяете akka.actor.UntypedActor, имея (Java-подобный) метод getContext(), возвращая akka.actor.UntypedActorContext. Этот принимает akka.japi.Procedure.

Чтобы сократить длинную историю - если вы используете Java API, придерживайтесь ее. Существует четкое различие между документами Scala и Java.

Ответ 2

Есть много хороших примеров того, как это сделать в java. Надеюсь, этот пример поможет:

Procedure<Object> angry = new Procedure<Object>() {
@Override
public void apply(Object message) {
  if (message.equals("bar")) {
    getSender().tell("I am already angry?", getSelf());
  } else if (message.equals("foo")) {
    getContext().become(happy);
  }
}
};

Procedure<Object> happy = new Procedure<Object>() {
@Override
public void apply(Object message) {
  if (message.equals("bar")) {
    getSender().tell("I am already happy :-)", getSelf());
  } else if (message.equals("foo")) {
    getContext().become(angry);
  }
 }
};

public void onReceive(Object message) {
if (message.equals("bar")) {
  getContext().become(angry);
} else if (message.equals("foo")) {
  getContext().become(happy);
} else {
  unhandled(message);
}

} }

Ответ 3

Вкратце, при использовании Java API убедитесь, что вы вызываете метод getContext() вместо context(), который предназначен для использования с Scala API.

Оформить заказ это (Java)

@Slf4j
@RequiredArgsConstructor
public class Greeter extends AbstractActor {

    private final ActorRef printer;

    public static Props props(ActorRef printer) {
        return Props.create(Greeter.class, printer);
    }

    @Override
    public Receive createReceive() {
        return withWhomToGreet(""); // initial state
    }

    private Receive withWhomToGreet(String name) {
        return receiveBuilder()
                .match(WhoToGreet.class, // changing actor state context
                       whoToGreet -> getContext().become(withWhomToGreet(whoToGreet.getWho())))
                .match(Greet.class, greet -> {
                    String msg = format("Hola, %s", name);
                    log.info("sending {} to {}", msg, printer);
                    printer.tell(Greeting.of(msg), self());
                })
                .matchAny(o -> {
                    log.error("unexpected: {}", o);
                    unhandled(o);
                })
                .build();
    }
}

или это (kotlin)

class CounterActor : AbstractActor() {

    companion object Factory {
        sealed class Commands {
            override fun toString(): String = javaClass.simpleName

            object Increment : Commands()
            object Decrement : Commands()
            object GetState : Commands()
        }

        private val type = CounterActor::class.java
        val props: Props = Props.create(type) { CounterActor() }
        val name: String = type.simpleName
    }

    override fun createReceive(): Receive = withCounter(0) // init state

    private fun withCounter(counter: Int): Receive =
        receiveBuilder()
            .matchAny { cmd ->
                context.system.log().info("current: $counter, received: $cmd")
                when (cmd) {
                    is GetState -> sender.tell("counter value: $counter", self)
                    is Increment -> {
                        // switch context with new updated actor state,
                        // actor is still stateless, similarly like we
                        // doing in scala for context.become 
                        // Make sure with Java API you are calling
                        // getContext() method, not context()!
                        context.become(withCounter(counter + 1))
                    }
                    is Decrement -> // another change of actor state
                        context.become(withCounter(counter - 1))
                    else -> unhandled(cmd)
                }
            }
            .build()
}

Все может быть сделано с той же идеей, как в Scala