twitter4s: how to return future from Action.async in play framework

44 Views Asked by At

i am using twitter4s and play-framework-2.4.3

i am fetching tweets sending to the actor for performing some processing on it and the actor needs to send back the response back to the controller Action here is my code

def totalTweetCount = Action.async {
    log.debug("in the action tofaltweets")
            def getTweet: PartialFunction[StreamingMessage, Unit] = {
      case tweet: Tweet =>
        future = ask(myActor, TotalNumberOfTweets(tweet)).mapTo[Int]  
    }
    val streaming: Future[TwitterStream] = streamingClient.sampleStatuses(stall_warnings = true)(getTweet)
}


class MyActor extends Actor {
//sends back the response to the calling code
}

now the problem is below line runs continuously (its the twitter stream) and call's getTweet method continuously and send the tweet object to the actor

val streaming: Future[TwitterStream] = streamingClient.sampleStatuses(stall_warnings = true)(getTweet)

i want to fetch the actor response and display it in Ok block of my Action when i do something like this i got NullPointerException

def totalTweetCount = Action.async {
    log.debug("in the action tofaltweets")



      def getTweet: PartialFunction[StreamingMessage, Unit] = {
          case tweet: Tweet =>
            var future: Future[Int] = null
            future = ask(myActor, TotalNumberOfTweets(tweet)).mapTo[Int]

        }
        val streaming: Future[TwitterStream] = streamingClient.sampleStatuses(stall_warnings = true)(getTweet)
    future.map {
              result =>
                Ok("Total number of tweets" + result)
            }
      }

if i do this def totalTweetCount = Action.async { log.debug("in the action tofaltweets")

def getTweet: PartialFunction[StreamingMessage, Unit] = {
  case tweet: Tweet =>
    var future: Future[Int] = null
    future = ask(actorManager, TotalNumberOfTweets(tweet)).mapTo[Int]
    future.map {
      result =>
        Ok("Total number of tweets" + result)
    }
}
val streaming: Future[TwitterStream] = streamingClient.sampleStatuses(stall_warnings = true)(getTweet)

} its also wrong so what should be the right approach

1

There are 1 best solutions below

0
Rodrigo Vedovato On

I'm not sure what you're trying to do here, but here it goes:

In all solutions, you're calling the streamingClient.sampleStatuses method inside your controller, which doesn't make a lot of sense, since that is a streaming method. Reading twitter4s docs, it seems they have an asynchronous approach for getting tweets.

Now, if what you're trying to do is to receive tweets, store them and them getting the total amount in a separate method, you should:

Call streamingClient.sampleStatuses inside your main method and send the incoming tweet to your actor

streamingClient.sampleStatuses(stall_warnings = true) {
  case t: Tweet => tweetsActor ! t    
}

That will send all tweet data to your actor class. Supposing your actor's implementations will be something like

class Tweets extends Actor {
  var tweets = ListBuffer[Tweet]()

  def receive = {
    case t: Tweet => tweets += t
    case TotalTweetCount = sender() ! tweets.length
  }
}

Your controller method will look like this:

import akka.pattern.ask_

def totalTweetCount = Action.async {
  (tweetActor ? TotalTweetCount).mapTo[Int]
}

That should do the trick.