NPE when accessing val that is not lazy - scala

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?

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.

Related

How to declare static global values and define them later in Scala?

Primary goal
I want to use some static vals in a class so that I don't have to pass them as function parameters.
My approach
Since I want them to be static, I am declaring them in the companion object. But I cannot assign them values when I declare them, for some reasons. So I am following the below approach.
case class DemoParams(name: String)
class Demo {
def foo = {
println("Demo params name is: ", Demo.demoParams.name) // Works fine
anotherFoo(Demo.demoParams.name) // Throws NPE !
}
def anotherFoo(someName: String) = {
// some code
}
}
object Demo {
var demoParams: DemoParams = _ // Declare here
def apply() = new Demo()
def run = {
demoParams = DemoParams(name = "Salmon") // Define here
val demoObj = Demo()
demoObj.foo
}
def main() = {
run
}
}
Demo.main()
I am able to print Demo.demoParams but surprisingly, this throws a NullPointerException when I pass Demo.demoParams to another function, while running the Spark app on a cluster.
Questions
Firstly, is this the right way of declaring static values and defining them later? I would prefer to not use vars and use immutable vals. Is there a better alternative?
Second, could you think of any reason I would be getting a NPE while passing Demo.demoParams.name to another function?
Your code works fine and doesn't throw anything (after fixing a few compile errors).
But ... Don't do this, it's ... yucky :/
How about passing params to the class as ... well ... params instead?
case class Demo(params: DemoParams) {
def foo() = {
println("Demo params name is: " + params.name)
}
}
object Demo {
def run() = {
val demoParams = DemoParams(name = "Salmon")
val demoObj = Demo(demoParams)
demoObj.foo()
}
}
Not sure this is the best alternative, but consider using a trait, which still keeps you in the FP zone by avoiding the use of var:
case class DemoParams(name: String)
trait Demo {
val demoParams: DemoParams
}
Then just define it where you need it, and it's ready for use:
object MainApp extends App {
val demoObj = new Demo {
override val demoParams: DemoParams = DemoParams(name = "Salmon")
}
println("Demo params name is: ", demoObj.demoParams.name) // (Demo params name is: ,Salmon)
anotherFoo(demoObj.demoParams.name) // Salmon
def anotherFoo(name: String): Unit = println(name)
}
About the second question, without the actual code one can only guess (this sample code does not throw NPE). Probably somewhere you are using it without defining it previously, because var demoParams: DemoParams = _ just initializes demoParams to the default value of the reference type DemoParams, which is null in this case, and you get NPE when you try to access the name value of a null object. This is why using var is discouraged.

Scala, Specs2 and shared state

I am writing some Specs2 specifications; that looks like:
class ComponentSpecification extends Specification with Mockito {
private val dependency = mock[Dependency]
private val subject = new Component(..)
"methodOne" should {
"handle happy path" in {
val result = subject.methodOne("Param1", 42)
result must ...
there was one(dependency).something()
}
"deal with border case" in {
val result = subject.methodOne("", -1)
result must ...
there was one(dependency).something()
}
}
}
However, those tests fails because the mock[Dependency] is shared.
One solution would be to make them sequential and reset the mock before each test but this look odd and as written in the doc about "Parallel by default":
it encourages to write independent examples when the result of a given example should not be influenced by others
Another would be to move the val to the test itself. But while I should be able to reduce the duplication with this still looks like a strange structure. And looks like the subject is stateful while it should not.
I can also try to use a less strict approach by verifying with there was atLestOne(dependency).something() but:
this does not validate that the method was called in this specific test case and
argument capture and validation is painful.
So my question is:
How can I create readable tests with detailed verifications on mock.
Thanks a lot.
Scopes can provide fresh state to each test like so
class ComponentSpecification extends mutable.Specification with Mockito {
trait FooScope extends Scope {
val dependency = mock[Dependency]
val subject = new Component(dependency)
}
"methodOne" should {
"handle happy path" in new FooScope {
val result = subject.methodOne("Param1", 42)
there was one(dependency).something()
}
"deal with border case" in new FooScope {
val result = subject.methodOne("", -1)
there was one(dependency).something()
}
}
}
where there is no need to reset the mock before each test.
I was going to accept the answer from #Mario Galic. However, regarding the comment of #Eric (author of Specs2) I ended with a method that creates the context as expected but removes duplication. By using pattern matching I extract the interesting part :
class ComponentSpecification extends mutable.Specification with Mockito {
def givenOneCallToMethodOneWithDependency(s:String, i:Int):(Result, Dependency) = {
val dependency = mock[Dependency]
val subject = new Component(dependency)
val result = subject.methodOne(s, i)
(result, dependency)
}
"methodOne" should {
"handle happy path" in new FooScope {
val (result, dependency) = givenOneCallToMethodOneWithDependency("Param1", 42)
there was one(dependency).something()
}
"deal with border case" in new FooScope {
val (result, dependency) = givenOneCallToMethodOneWithDependency("", -1)
there was one(dependency).something()
}
}
}

calling an object in main class

quick question on calling an object and running it from main just need the last command val op = df.coalesce(1).write.mode("overwrite").format("csv").save("report")to be able called from a main class
how do we intilize an instance of object and run to get to write to csv?
def run(implicit context: Context): Unit = {
val timer = Timer.start()
//not working
val newRep = Report_Adhoc
val d = newRep.tab.toDF()
val op = d.coalesce(1).write.mode("overwrite").format("csv").save("report")
println(s"pipeline complete in [${timer.elapsedTime()}]")
}
Main class is this ^ but this throws null point exception
object Report_Adhoc extends App with TransientLogger{
// code not including too verbose
val tab =
counts
.filter(c => c._1.id.nonEmpty && c._2.id.nonEmpty)
.map(c => (c._1, c._2, c._3, c._3.values.sum))
.sort($"_4".desc)
.map(count =>
row(
count._1.id, count._1.label,
count._2.id, count._2.label,
count._3(CITE), count._3(CROSS), count._3(MANUAL),
count._3(RECIPROCAL), count._3(TRANSITIVE), count._3(FAMILY),
count._4
)
)
val df = tab.toDF()
val op = df.coalesce(1).write.mode("overwrite").format("csv").save("report")
}
take a look at this:
https://www.scala-lang.org/api/2.12.3/scala/DelayedInit.html
https://www.scala-lang.org/api/2.12.3/scala/App.html
Also, don't put underscore in names. don't reuse main class/object. Last but not least, make a minimum reproduction instead of pasting big block of code like this.

ScalaFX: how to asynchronously update a TreeTableView

I want to represent the data I have in a Tree and show it using TreeTableView. The items shown are wrapped in a case class:
case class Foo(name: StringProperty, desc:StringPropert) {
def this(_name: String, _desc: String) = this(StringProperty(_name), StringProperty(_dest))
}
Populating the tree is done asynchronously (calling an external program which takes time) via (basically):
val runner = Future {
// run command
}
runner onComplete {
case Success(ret) => // parse ret and update TreeTableView somehow
...
}
Since this is done async, I started with an empty node for the tree:
val ViewPkgs = new TreeItem[Foo](new Foo("root", "desc"))
...
val ViewTable = new TreeTableView[Foo](ViewPkgs) { columns ++= ... }
How do I update the list of packages from the async call above?
What I tried is creating a
val ViewBuf = ObservableBuffer[Foo]()
ViewPkgs.children = ObservableBuffer( ViewBuf.map { p => new TreeItem[Foo](p) } )
but that didn't help.
Thanks for any suggestions.

Symbol value does not exist in someMethod

This is my source code for testing:
import org.openqa.selenium.firefox.FirefoxDriver
import org.scalatest.FlatSpec
import org.scalatest.Matchers
import play.api.test.FakeApplication
import play.api.test.WithApplication
class FunctionalSpec extends FlatSpec with Matchers {
def withDriver(f: FirefoxDriver => Unit) = {
val driver = new FirefoxDriver
try {
new WithApplication(
new FakeApplication(additionalConfiguration = Map("application.secret" -> "secret"))) {
f(driver)
}
} finally {
driver.quit
}
}
}
It doesn't show any compile-error in Eclipse. But when I execute the test command it shows a very long error message. This is the first line of the errors:
symbol value f$1 does not exist in test.FunctionalSpec$$anon$1$delayedInit$body.apply
I tried to play around a bit by modifying the code as shown below:
def withDriver(f: FirefoxDriver => Unit) = {
val driver = new FirefoxDriver
try {
val g = f
val driver2 = driver
new WithApplication(
new FakeApplication(additionalConfiguration = Map("application.secret" -> "secret"))) {
val h = g
val driver3 = driver2
h(driver3)
}
} finally {
driver.quit
}
}
There are no errors thrown when I executed the test command. Any idea what's happening? Is there any limit of how deep a block of code can go in order to keep the identifiers recognised?
EDIT:
Using my modified code above results in runtime-error. I added the code below:
"The admin" should "be able to login and logout correctly" in withDriver { implicit driver =>
// Don't do anything yet.
}
This one is displayed in one line of the runtime-error messages:
Cause: java.lang.NoSuchFieldError: g$1
Any suggestion for a workaround?
ADDITIONAL NOTE:
All the codes above compile just fine. Neither Eclipse or scalac complain. All the errors above happen only when I do the test command from the Play command shell.
This doesn't directly answer your question, but I would do two things:
Use Specs2 instead of ScalaTest
Rewrite your tests as described here: http://www.playframework.com/documentation/2.2.x/ScalaFunctionalTest