Search code examples
scalacollectionsakkaactormutable

Mutable collections in akka Actor return NullPointerException


I have an actor which is calling a websocket and updating a map everytime it receives an update form the web socket. the same map is being used by the actor at another point in the command.

class MyActor(broker: InMemoryBroker) extends Actor {
val myMap: TrieMap[String, String] = new TrieMap[String, String]()

//Gets a response every 1 second 
webSocket.get(onReponse= r=> myMap(r.key) = r.value)


def receive()={
 case MyCommand(key)=>
   if(myMap.get(key).isDefined){     //Null pointer exception is thrown here
       //Do stuff
   }
}

I was expecting TrieMap to be thread safe and not have such issues. Any suggestions?


Solution

  • You should do as much processing as possible in the receive method. So rather than updating the map directly in onResponse, send yourself a message and update the map when you receive it:

    class MyActor(broker: InMemoryBroker) extends Actor {
      val myMap: TrieMap[String, String] = new TrieMap[String, String]()
    
      private case class UpdateMap(r: ???)
    
      //Gets a response every 1 second 
      webSocket.get(onReponse = r => self ! UpdateMap(r))
    
      def receive() = {
        case UpdateMap(r) =>
          myMap(r.key) = r.value
    
        case MyCommand(key) =>
          if (myMap.get(key).isDefined) { //Null pointer exception is thrown here
            //Do stuff
          }
      }
    }
    

    With the method the TrieMap is only accessed from a single thread at a time.

    Also, that test is better done as:

    myMap.get(key).foreach{ value =>
      ???
    }