10

我正在使用来自 Java 的 Akka。根据文档,context.become()作为Procedure<Object>参数。事实上,它预计PartialFunction<Object, BoxedUnit>这似乎是由许多具有奇怪名称的方法自动生成的。

从 Java中使用become()的正确方法是什么?

PS我正在使用Akka 2.0.3

更新:看起来有两种方法:context() 和 getContext()。第一个返回 ActorContext,第二个返回 UntypedActorContext。UntypedActorContext 有become(Procedure<Object>).

4

3 回答 3

8

您混淆了 Akka Java 和 Scala API。从技术上讲,您可以从 Java 代码中使用像 Akka 这样的 Scala 库,但它通常是冗长而繁琐的。因此 Akka 团队决定开发分离 API——Scala 和 Java 适配器中的原生 API。

在 Scala API 中,您扩展akka.actor.Actor了具有contexttype 的字段akka.actor.ActorContext。这ActorContext.become()接受PartialFunction,这是一个 Scala 特定的类。

另一方面,在 Java API 中,您扩展akka.actor.UntypedActor了(类 Java)方法getContext(),返回akka.actor.UntypedActorContext. 这一个接受akka.japi.Procedure

长话短说 - 如果您使用的是 Java API,请坚持使用它。Scala 和 Java 文档之间有明显的区别。

于 2013-02-04T16:39:36.117 回答
0

也有很多关于如何在 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);
}

} }

于 2017-09-25T17:49:10.633 回答
0

简而言之,在使用 时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();
    }
}

或者这个(科特林)

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 中相同的想法来完成

于 2019-07-28T23:31:07.200 回答