Reputation: 212
I'm using json4s with play framework and I have some places where I'll run a post/get request in a future, then onSuccess parse the response in to an object and have the actor send it back to itself.. Here's an example:
WS.url(authUrl).post("username=admin&password=admin") map {
response =>
self ! (parse(response.body) \ "body").extract[AuthObject]
}
and then back in the receive method:
case AuthObject(_, sid) => //handle authorization token
Is this bad practice? What's the correct way to go about this? The advantage I see is being able to have your actors data flow handled by a single control structure, but of course I could be wrong in saying that's an advantage.
Upvotes: 4
Views: 287
Reputation: 21595
The recommended way to send future results to actors is to use the pipe
pattern. You code would then look like this:
def receive:Reveice= {
case authUrl:String =>
val authObjectF=WS.url(authUrl).post("username=admin&password=admin") map { response =>
(parse(response.body) \ "body").extract[AuthObject]
}
authObjectF pipeTo self
}
The reason this is considered superior to map {x => self ! x }
is error handling. If you don't handle the error cases, they will simply be silently discarded.
Using the pipe
pattern, the errors will be wrapped in a akka.actor.Status.Failure
and sent to the destination actor (in this case to self
) in place of the result.
Piping the result of a future to self is a common pattern, possibly used in conjunction with context.become/unbecome and stash to create state machines.
It is still very easy to close over actor internal mutable state in a map/flatmap and break the concurrency guarantees of the actor model in doing so. If you are manipulating futures in actors I strongly suggest reading this http://doc.akka.io/docs/akka/2.3.2/general/jmm.html#jmm-shared-state if you haven't done so already.
Upvotes: 8
Reputation: 2785
There's nothing inherently wrong with it. Sending a message to yourself is similar to a human keeping a "to do" list and putting something at the end of the list. Your actor will get there .. eventually. And, that's really the only concern: the timing of when AuthObject
message gets processed. If your application only requires ordering but not time guarantees then it is fine to process it that way.
I would be wary, however, of your \ operator returning a JsError in the case there is no "body" field in your response.body (presumably Json). In that case your message never gets sent and there's no error delivered anywhere either.
Upvotes: 1