4

I have a curious issue when using Squeryl with Play!.

Normal usage and everything else works completely fine. However, if I use more than one transaction in the same request, I get an error.

That's how I set up Squeryl:

def initDB() {
  import org.squeryl._
  import play.db.DB

  Class.forName("com.mysql.jdbc.Driver")
  SessionFactory.concreteFactory = Some(() =>
    Session.create( DB.getConnection, new MySQLAdapter) )
}

Sample transaction, also the one referenced in the stack trace below:

transaction {
  import models.Game
  Game.planets.insert(planetList) 
  Game.moons.insert(moonList)
}

Stack trace:

Internal Server Error (500) for request GET /generate-galaxy

Execution exception (In /app/Generator.scala around line 330)
SQLException occured : You can't operate on a closed Connection!!!

play.exceptions.JavaExecutionException: You can't operate on a closed Connection!!!
    at play.mvc.ActionInvoker.invoke(ActionInvoker.java:228)
    at Invocation.HTTP Request(Play!)
Caused by: java.sql.SQLException: You can't operate on a closed Connection!!!
    at com.mchange.v2.sql.SqlUtils.toSQLException(SqlUtils.java:106)
    at com.mchange.v2.sql.SqlUtils.toSQLException(SqlUtils.java:65)
    at org.squeryl.dsl.QueryDsl$class._executeTransactionWithin(QueryDsl.scala:95)
    at org.squeryl.dsl.QueryDsl$class.transaction(QueryDsl.scala:64)
    at org.squeryl.PrimitiveTypeMode$.transaction(PrimitiveTypeMode.scala:40)
    at generator.Generator$$anonfun$generatePlanets$2.apply(Generator.scala:330)
    at generator.Generator$$anonfun$generatePlanets$2.apply(Generator.scala:55)
    at generator.Generator$.generatePlanets(Generator.scala:55)
    at generator.Generator$.generateGalaxy(Generator.scala:36)
    at controllers.MainRouter$.generateGalaxy(MainRouter.scala:29)
    at play.mvc.ActionInvoker.invokeWithContinuation(ActionInvoker.java:543)
    at play.mvc.ActionInvoker.invoke(ActionInvoker.java:499)
    at play.mvc.ActionInvoker.invokeControllerMethod(ActionInvoker.java:493)
    at play.mvc.ActionInvoker.invokeControllerMethod(ActionInvoker.java:470)
    at play.mvc.ActionInvoker.invoke(ActionInvoker.java:158)
    ... 1 more
Caused by: java.lang.NullPointerException
    ... 14 more

I know that the problem is not in my queries, because they worked fine when using scalatra as a web framework. I could just put everything into one transaction block, but that's not really elegant and I'm also not sure if it would work in this case - the planetList list has about 3 million members, which caused scala to run out of memory before I split database insertion up into smaller blocks of 50k elements.

Mononofu
  • 902
  • 7
  • 15
  • Did you ever get an answer? I'm experiencing the same issue. – Ladlestein Nov 17 '11 at 01:09
  • IIRC, I just resorted to only ever using one transaction. – Mononofu Dec 06 '11 at 20:34
  • I experience a lot of this same issue although my problem is a little different and simpler. When I pass a Squeryl value through RenderArgs it seems to save the whole damn SQL query and try to run it again...instead of just passing the value. Let me know if you find a simpler fix. – crockpotveggies Mar 02 '12 at 00:13

2 Answers2

1

Could you please re-post your question to the Squeryl mailing list? I'm not familiar with Play! but I know that some of the other users and commiters are. If you could publish an example project to GitHub and include a link that would be helpful as well.

Dave Whittaker
  • 3,102
  • 13
  • 14
1

I'd like to see how the first tx is related, does it get immidiately executed before ? Are they nested ?

When you have 2 transactions, you could do this :

val s1 = Session.create( DB.getConnection, new MySQLAdapter) )
val s2 = Session.create( DB.getConnection, new MySQLAdapter) )


using(s1) {...   .... s1.connection.commit}
using(s2) {...   .... s1.connection.commit}
Max L.
  • 9,774
  • 15
  • 56
  • 86
  • The transactions are executed serially: some processing is done, then it's committed to the DB, some more processing, write to DB, etc. I thought I was supposed to use just one session per request. – Mononofu Aug 10 '11 at 16:23