Akka/Java: Handling multiple message types inside a custom actor?
No you are not missing anything. I am not a fan either. In Scala it is a bit better because the onReceive method can be swapped out to simulate the changing state of a protocol and it uses partial functions which are a little nicer than if/elseif/else... but it is still icky. It is nicer in Erlang, which is where this model originated but that said given the limitations faced by the akka team, they made the right design choices and did an excellent job.
An alternative strategy is to perform a double dispatch. So pass the command into the actor to be actions, or lookup in a map a handler for the message. Akka agents are essentially the former, and when used to their strength are quite nice. But in general a double dispatch just adds complexity, so for most cases one just has to get used to the standard approach. Which in java means either if instanceof or a switch statement.
An example of double dispatch (psuedo code), included here for completeness, to aid understanding. As an approach it comes with health warnings, so I reiterate; the standard approach is standard for a reason and that one should use that 99% of the time.
onReceive( msg ) {
msg.doWork()
}
The problem with this approach is that now the message needs to know how to process itself, which is dirty; it causes tight coupling and can be fragile. Yuck.
So we can go with using a lookup for handlers (command pattern stylie)
val handlers = Map( "msgid1"->Handler1, "msgid2->Handler2 )
onReceive( msg ) {
val h = handlers(msg.id)
h.doWork( msg )
}
the problem here is that now it is unclear what the commands are and following the code through involves jumping around more. But there are times that this is worth while.
As pointed out by Roland, care must be taken when passing around a reference to the actor itself. The examples above do not fall foul of that problem, but it would be an easy temptation to do.