Search code examples
scalahazelcasthazelcast-imap

Hazelcast get always returns null, containsKey always return false


Got started looking at Hazelcast (3.4.4). Minimal configuration. Test:

 case class Ticket(id:Int, name:String)

val ticketCount = 20
      val tickets:List[Ticket] = for { n <- (0 until ticketCount).toList } yield Ticket(n, s"ticket$n")

val map: IMap[Long, Ticket] = hz1.getMap[Long,Ticket]("com.foo.testmap")

tickets foreach { t =>
    println(s"submitting $t")
    Thread.sleep(10)  // some delay to submit one ticket
    map.putIfAbsent(t.id, t)
}


Thread.sleep(2000) // two seconds to make sure all is set..


var value1 = map.get(19)             // null 

var value2 = map.containsKey(19) )   // false  

val value3 = map.getAsync(19).get()   // Ticket(19,ticket19)

Why null, why false, why only map.getAsync(19).get() works?

This, though:

  val iterator = map.entrySet().iterator()      // will print all values
  while(iterator.hasNext) {
    val next = iterator.next()
    println(next)
  }

Will print all entries.

Update:

in config:

<map name="com.foo.testmap">
  <in-memory-format>OBJECT</in-memory-format>
</map>

Solution

  • It works as expected when you change var value1 = map.get(19) to var value1 = map.get(19l)

    You are using Long as keys when storing data into a map. However you are using Integer to get the data back. As you can see in the IMap contract the equality comparison uses binary (serialized) form of the key, not the key itself. Obviously a long is serialized into a different binary than integer.

    The getAsync() works as unlike the get() method it does use generics and I assume Scala compiler converts the key into a Long behind the scene.

    It's a combination of auto-boxing and Scala compiler sorcery creating a seemingly inconsistent behaviour. However when I'm thinking about it it's not really that unexpected. Behaviour of j.u.Map is exactly the same. Following test is failing as well:

    @Test
    public void surpriseNotReally() {
        Map<Long, String> map = new HashMap<>();
    
        long key = 1;
        String expectedValue = "foo";
        map.put(key, expectedValue);
    
        String actualValue =  map.get(1);
        assertEquals(expectedValue, actualValue);
    }