Could this be a Thread Visibility problem?

I have a test (ObjectOfMapSpec) that throws a NullPointerException when run a 24xcore machine while it works fine on a 2-core machine. Question is whether the problem is related to Thread Visibility, and if so, why does it occur.

import java.util.UUID
import java.util.concurrent.ConcurrentHashMap
import org.scalatest.FlatSpec
import org.scalatest.Matchers

trait Resource {
val key: String = UUID.randomUUID().toString()
}

trait SubResource extends Resource {
val name: String
//In a multi-core machine, removing the comment creates a NullPointerException in the map
override val key: String = name
}

object ObjectOfResource extends SubResource {
val name = “ObjectOfResource”
}

trait SomeMap {
private val hashMap = new ConcurrentHashMap[String, Resource]

def addResource(someResource: Resource): Resource = {
//In a multi-core machine, key becomes null
println("…" + someResource.key)
hashMap.putIfAbsent(someResource.key, someResource)
}
}

object ObjectOfMap extends SomeMap {
addResource(ObjectOfResource)
def dummyMethod() = true
}

class ObjectOfMapSpec extends FlatSpec with Matchers {
“ObjectOfMap” should “work just fine…” in {
val ok = ObjectOfMap.dummyMethod()
ok should be(true)
}
}

It is not a thread visibility problem and it should fail in any computer regardless of thread count.

It is an initialization order issue.
You can fix it by making name a def on the trait and overriding it with a final val on the object.
Like this:

import java.util.UUID
import java.util.concurrent.ConcurrentHashMap

trait Resource {
  // I personally would also make this a def and remove the default implementation.
  val key: String = UUID.randomUUID().toString()
}

trait SubResource extends Resource {
  def name: String
  override val key: String = name
}

object ObjectOfResource extends SubResource {
  override final val name = "ObjectOfResource"
}

trait SomeMap {
  // I made this final and private[this], because subclasses shouldn't know about this.
  private[this] final val hashMap = new ConcurrentHashMap[String, Resource]

  def addResource(someResource: Resource): Resource = {
    println(s"Adding resource: ${someResource.key}")
    hashMap.putIfAbsent(someResource.key, someResource)
  }
}

object ObjectOfMap extends SomeMap {
  addResource(ObjectOfResource)
}

You can see the code running here.

Thanks for an excellent answer. Your solution works perfectly!

It turns out that making “name” from “val” to “def” in both the trait and the object, also works:

trait Resource {
val key: String = UUID.randomUUID().toString()
}

trait SubResource extends Resource {
def name: String
override val key: String = name
}

object ObjectOfResource extends SubResource {
def name = “ObjectOfResource”
}