scalascala-java-interop

Instanciating POJO with nulls values from Scala Option


Many years of using Scala and still I don't know the right way to interoperate with Java. :(

To be honest, this is not something that I'm doing every day, but sometimes there is no other option (today is Firestore Java libraries).

My question today is about the proper way to instantiate POJOs that can have null values. At the end of the day, I always use something like the def toJavaLong(l: Option[Long]): java.lang.Long = if (l.isEmpty) l.get else null, but pretty sure that there is a better and elegant way.

Please, could you show me the path? I expect something like orNull working out of the box, but it is never the case.

I'm using Scala 2.13, but feel free to show alternatives to Scala 3 as well.

In the next example, I explain the errors that I have using orNull and getOrElse:

Pojo:

public class ExamplePojo {
   public Long value;

   public ExamplePojo(Long value) {
      this.value = value;
   }
}

Scala object instanciating the Pojo:

object CreatePojo {
  def main(args: Array[String]): Unit = {
    val noneValue = Option.empty[Long]
    val oneValue = Some(1L)

    def toJavaLong(l: Option[Long]): java.lang.Long =
      if (l.isEmpty) l.get else null

    // Next line works fine.
    new ExamplePojo(toJavaLong(noneValue))

    // Next line works fine of course, but not helpful. :)
    new ExamplePojo(oneValue.get)

    // Next line throws a compilation error:
    // type arguments [Long] do not conform to method orNull's type parameter bounds [A1 >: Long]
    new ExamplePojo(noneValue.orNull)

    // Next line throws a compilation error:
    // type mismatch;
    //  found   : Any
    //  required: Long
    new ExamplePojo(noneValue.getOrElse(null))

    // This will throw a `java.util.NoSuchElementException`
    new ExamplePojo(noneValue.get)
  }
}

Of course, this is only an example to reproduce the case.


Solution

  • The problem, in this case, is not the null, but the fact that scala.Long is not the same as java.lang.Long

    What you can do is the following:

    new ExamplePojo(l.map(Long.box).orNull)