Tutorial :Scala Actors suspends unexpected when connecting to a database


I have a problem with my understanding of the standard actor library in Scala. In the code below I have created a simple swing, which basically should test if it is able to connect to a postgreSQL server. However it doesnt make it that far, I use Actors since the UI otherwise would freeze up while doing the work needed to connect to the database. When er i use this line (meaning that I use actors instead of a single thread)

PostgresCheck ! new GetInfo()  

The Swing will never be updated. However if I comment the line out and use the next three lines. (meaning the actors wont be used)

      val result = PostgresCheck.checkPostgreSQL        if (result == "OK") pgText.background = GREEN else pgText.background = RED        pgText.text = result  

The Swing will freeze but after about 25 seconds the swing will be updated.

import dbc.Database  import dbc.vendor.PostgreSQL  import java.awt.Dimension  import java.net.URI  import java.sql.Connection  import swing.event._  import swing._  import actors.Actor  import java.awt.Color._  import scala.actors.Actor._    case class Info(reply: String)  case class GetInfo()    object Example extends SimpleSwingApplication {    val pgButton = new Button("Check PostgreSQL")    val pgText = new TextArea("Not Checked Yet")    val pgPanel = new GridPanel(1, 2)    pgPanel.contents += pgButton    pgPanel.contents += pgText      def top = new MainFrame {      title = "StateChecker"      contents = pgPanel    }      listenTo(pgButton)    reactions += {      case e: ButtonClicked if (e.source.eq(pgButton)) => {        PostgresCheck ! new GetInfo()          //val result = PostgresCheck.checkPostgreSQL        //if (result == "OK") pgText.background = GREEN else pgText.background = RED        //pgText.text = result      }    }      val guiActor = new Actor {      def act() = {        loop {          react {            case e: String => {              val result = e              if (result == "OK") pgText.background = GREEN else pgText.background = RED              pgText.text = result            }            case e => println(e.toString)          }        }      }    }    guiActor.start  }    object PostgresCheck extends Actor {    def checkPostgreSQL() = {      try {        val db = new Database(myPgSQL)        val con: Connection = myPgSQL.getConnection // Freezes while doing this method        val statement = con.createStatement        if (statement.getResultSet.getMetaData.getColumnCount == 1) "OK"        else statement.getWarnings.toString      }      catch {        case e => e.toString      }    }      def act() = {      loop {        react {          case e: GetInfo => {            sender ! new Info(checkPostgreSQL)          }        }      }    }    start()  }    object myPgSQL extends PostgreSQL {    val uri = new URI("jdbc:postgresql://whatever.com")    val user = "1234"    val pass = "1234"  }  


You are sending the message outside an actor, it seems. Try this:

Actor.actor { PostgresCheck ! new GetInfo() }  

Not sure if it will help, but it is standard advise.

And, now that I think of it, to whom will the answer be sent? You are replying to the non-existent sender. I suppose you want the answer going to guiActor, but I don't see you doing so.


Okay here we go, the problem was related to the line

sender ! new Info(checkPostgreSQL)  

It should actually have been

Example.guiActor! new Info(checkPostgreSQL)  

For some reason related to the Actor library it actually suspends when waiting for the database connection, and wont return because of an unknown sender. For instance the following lines result in a printout of just a single line in console with "1".

      val db = new Database(myPgSQL)        println("1")        // Freezes while doing this method        val con: Connection = myPgSQL.getConnection         println("2")  

When changing the mentioned line, the code behave as expected.

Note:If u also have question or solution just comment us below or mail us on toontricks1994@gmail.com
Next Post »