Question

EDIT2:

So another heads up on this: I still have no idea why this happens, but I have now a similar problem with jOOQ and the Dialect I have to it. My code here looks like this:

object MyDB {
    private lazy val dialect = SQLDialect.POSTGRES
    def withSession[T](f: DSLContext => T) = f(DSL.using(getConnectionPool, dialect))
}

if I remove the "lazy" it blows up when I try to execute jOOQ queries in line 552 of https://github.com/jOOQ/jOOQ/blob/version-3.2.0/jOOQ/src/main/java/org/jooq/impl/DefaultRenderContext.java

That happens to be a line where the dialect is evaluated. After I added the lazy everything works as expected.

Maybe this is an issue with the threading of LiftWeb and the executing thread does not see the correct value of the val? I have no idea...

EDIT:

I have found a way to do what I want simply by adding a lazy to the values in the first, broken version. So with lazy vals it all works well. However I'll let this stay open, as I have no idea how to explain this behavior.

Original Post:

So I am trying to use Parameterized Queries in Slick. My code is below, my problem is that I get an NPE (see comments) when I try to run this from within the webapplication (liftweb, container started with sbt) (the application creates an object of the class PlayerListCollector that is given the string "cola") When I execute the object as App from within Eclipse the println at the bottom works just fine.

class PlayerListCollector(term: String) {
  import PlayerListCollector._
  val searchResult = executeSearch(term)
}

object PlayerListCollector extends Loggable with App{
  private val searchNameCurrent = Parameters[String].flatMap {
    case (term) => {
      for {
        p <- Players if p.uberName.isNotNull
        n <- p.displayName if (n.displayName.toLowerCase.like(term))
      } yield (p.id, n.displayName)
    }
  }

  private def executeSearch(term: String) = {
    val lowerTerm = "%"+term.toLowerCase()+"%"
    logger info "HELLO " +lowerTerm // prints HELLO %cola%
    val foo = searchNameCurrent(lowerTerm) // NPE right in this line
    logger info foo // never executed from here on ...
    val byCurrent = foo.list
    logger info byCurrent

    [...]
  }

  // this works if run directly from within eclipse!
  println(DB withSession {
    searchNameCurrent("%cola%").list
  })
}

The problem vanishes when I change the code to look like this:

[...]
object PlayerListCollector extends Loggable with App{

  private def executeSearch(term: String) = {
      val searchNameCurrent = Parameters[String].flatMap {
        case (term) => {
          for {
            p <- Players if p.uberName.isNotNull
            n <- p.displayName if (n.displayName.toLowerCase.like(term))
          } yield (p.id, n.displayName)
        }
      }

    val lowerTerm = "%"+term.toLowerCase()+"%"
    logger info "HELLO " +lowerTerm // prints HELLO %cola%
    val foo = searchNameCurrent(lowerTerm) // executes just fine when the query is in a local val
    logger info foo
    val byCurrent = foo.list
    logger info byCurrent // prints expected output

    [...]
  }
  [...]
}

I have no idea whatsoever why this happens. Isn't the whole point of a paramterized query to put it in a val that is only once filled with a value so it does not need to be compiled multiple times?

Was it helpful?

Solution

So it turns out I used the App-Trait (http://www.scala-lang.org/api/current/index.html#scala.App) on these objects. Reading the big fat caveat tells us what is happening I guess.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top