Instanciating POJO with nulls values from Scala Option - scala

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.

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)

Likely not as concise as you'd expect but I tend to use the following:
option.getOrElse(null).asInstanceOf[java.lang.Long]
Or write an extension method asJavaOrNull that does what your toJavaLong currently do but with a nicer developer experience.

Related

Type bounds on methods not enforced

I can't comprehend why the compiler allows for the current code.
I use phantom types to protect access to methods. Only under specific "states" should methods be allowed to be called.
In most scenarios, this invariant is indeed verified by the compilation. Sometimes however, the compiler just ignores the constraint imposed by the phantom type.
This feels like a major bug. What am I not understanding?
I tried to simplify the problem as much as possible. My use case is more complex:
class Door[State <: DoorState] private {
def doorKey: Int = 1
def open[Phatom >: State <: Closed.type]: Door[Open.type] = new Door[Open.type]
def close[Phatom >: State <: Open.type]: Door[Closed.type] = new Door[Closed.type]
}
object Door {
def applyOpenDoor: Door[Open.type] = new Door[Open.type]
def applyClosedDoor: Door[Closed.type] = new Door[Closed.type]
}
sealed trait DoorState
case object Closed extends DoorState
case object Open extends DoorState
Then
val aClosedDoor = Door.applyClosedDoor
val res1 = aClosedDoor.close // does not compile. Good!
val res2 = aClosedDoor.open.close.close // does not compile. Good!
println(aClosedDoor.open.close.close) // does not compile. Good!
println(aClosedDoor.open.close.close.doorKey) // does not compile. Good!
aClosedDoor.open.close.close.doorKey == 1 // does not compile. Good!
println(aClosedDoor.open.close.close.doorKey == 1) // compiles! WTF?
As you can see above, the client can close a closed door. In my library, the corresponding behaviour is throwing a runtime exception. (I was confident the exception was well protected and impossible to reach)
I have only been able to replicate this problem for expressions returning boolean and when this is the argument to a function (in the example, println)
I am not looking for alternative solutions as much as I am looking for an explanation as to how this can happen? Don't you agree this is a considerable flaw? Or maybe I am missing something?
Scala version: 2.13.5
Edit
After a discussion on gitter, I opened bug request # https://github.com/scala/bug
The problem does not seem to occur in scala 3.
Seems it is an bug related to usage of nullary method
def doorKey: Int = 1
if instead it is defined as nilary method
def doorKey(): Int = 1
then it works as expected
println(aClosedDoor.open.close.close.doorKey() == 1) // compiler error

What are the semantics of the last expression in a block of scala code?

Following code does not work if I don't uncomment the commented line.It says
type mismatch; found : Unit required: Option[String]
import java.io._
import org.apache.pdfbox.pdmodel.PDDocument
import org.apache.pdfbox.text.PDFTextStripper
object PdfToText {
def main(args: Array[String]) {
val filename = "D:\\Scala\\DATA\\HelloWorld.pdf"
getTextFromPdf(filename)
}
def getTextFromPdf(filename: String): Option[String] = {
val pdf = PDDocument.load(new File(filename))
println(new PDFTextStripper().getText(pdf))
// Some(new PDFTextStripper().getText(pdf))
}
}
Code executes fine if I keep the line -
Some(new PDFTextStripper().getText(pdf))
Output:
Welcome
to
The World of Scala
Could anyone please explain the behaviour of the line
" Some(new PDFTextStripper().getText(pdf)"
The result of a method is the result of the final line of code. println returns Unit. If that's the last line then that's what the method returns, which conflicts with the stated Option[String] return type.
The code new PDFTextStripper().getText(pdf) returns a String and wrapping it in Some() makes it an Option[String] which does match the stated method return type.
explanation
Here is a method that compiles.
def six(): Int = { // takes no arguments and returns an Int
println("top") // string sent to stdout
6 // this is the Int it returns
}
Here is a method that does not compile.
def six(): Int = { // takes no arguments and returns an Int
6 // this is the Int it should return
println("end") // Error: type mismatch
}
This method is supposed to return an Int (that's what the : Int means) but the last line is a println() statement and println returns a Unit, not an Int, so that causes the error. This method is trying to return Unit when it is supposed to return Int.
This is a very basic concept in the Scala language.
Option is a Scala type that represents the presence or absence of a value. Instead of runtime constructs like null and exceptions which have significant downsides, Option (and equivalent constructs in other languages) allows for compile-time checking that you are handling both possibilities.
A common use of Option is a database lookup by id. It is quite possible there is no entity with that id. The return type of the function in Scala would be Option[Employee]. If you find one, it would return Some(employee); otherwise simply None. Both subclass Option. Note that you can think of Option like a container of zero or one element.
In your case, you have defined your function to return Option[String], which is why returning Some(String) containing the text of the file makes the compiler happy. I hope that answers your question.
Please note though that your function isn't really designed in a way that uses Option effectively since there is no issue of presence/absence--just always present. In other words, returning an Option isn't useful here. However, it would be perfectly appropriate to use Option to represent the cases where the file is or isn't available on the file system to be read.
For example:
object PdfToText {
def main(args: Array[String]) {
val filename = "D:\\Scala\\DATA\\HelloWorld.pdf"
val text = getTextFromPdf(filename)
val result = text.map(t => s"File contents: ${t}").getOrElse("Empty file")
println(result)
}
def getTextFromPdf(filename: String): Option[String] = {
val file = new File(filename)
if (file.exists() && !file.isDirectory) {
val pdf = PDDocument.load(new File(filename))
Some(new PDFTextStripper().getText(pdf))
} else {
None
}
}
}
Here presence is defined by the existence of a readable file, which allows me to return its contents in a Some, and absence is defined by the nonexistence of the file or the file being a directory, which manifests as a None
I then account for both possibilities in main. If there's text to be read because the function gave me back a Some, I call map (which only fires on Somes) to transform the text into a different string. If I get None, we skip over to the getOrElse and produce a default string.
Either way, we print out whatever we got, which is guaranteed to be a String no matter what happened with the original File.
As a shameless plug, you can learn more about Option in our tutorial Nine Reasons to Try Scala. Just fast forward to 8:36.

Can Scala infer the actual type from the return type actually expected by the caller?

I have a following question. Our project has a lot of code, that runs tests in Scala. And there is a lot of code, that fills the fields like this:
production.setProduct(new Product)
production.getProduct.setUuid("b1253a77-0585-291f-57a4-53319e897866")
production.setSubProduct(new SubProduct)
production.getSubProduct.setUuid("89a877fa-ddb3-3009-bb24-735ba9f7281c")
Eventually, I grew tired from this code, since all those fields are actually subclasses of the basic class that has the uuid field, so, after thinking a while, I wrote the auxiliary function like this:
def createUuid[T <: GenericEntity](uuid: String)(implicit m : Manifest[T]) : T = {
val constructor = m.runtimeClass.getConstructors()(0)
val instance = constructor.newInstance().asInstanceOf[T]
instance.setUuid(uuid)
instance
}
Now, my code got two times shorter, since now I can write something like this:
production.setProduct(createUuid[Product]("b1253a77-0585-291f-57a4-53319e897866"))
production.setSubProduct(createUuid[SubProduct]("89a877fa-ddb3-3009-bb24-735ba9f7281c"))
That's good, but I am wondering, if I could somehow implement the function createUuid so the last bit would like this:
// Is that really possible?
production.setProduct(createUuid("b1253a77-0585-291f-57a4-53319e897866"))
production.setSubProduct(createUuid("89a877fa-ddb3-3009-bb24-735ba9f7281c"))
Can scala compiler guess, that setProduct expects not just a generic entity, but actually something like Product (or it's subclass)? Or there is no way in Scala to implement this even shorter?
Scala compiler won't infer/propagate the type outside-in. You could however create implicit conversions like:
implicit def stringToSubProduct(uuid: String): SubProduct = {
val n = new SubProduct
n.setUuid(uuid)
n
}
and then just call
production.setSubProduct("89a877fa-ddb3-3009-bb24-735ba9f7281c")
and the compiler will automatically use the stringToSubProduct because it has applicable types on the input and output.
Update: To have the code better organized I suggest wrapping the implicit defs to a companion object, like:
case class EntityUUID(uuid: String) {
uuid.matches("[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}") // possible uuid format check
}
case object EntityUUID {
implicit def toProduct(e: EntityUUID): Product = {
val p = new Product
p.setUuid(e.uuid)
p
}
implicit def toSubProduct(e: EntityUUID): SubProduct = {
val p = new SubProduct
p.setUuid(e.uuid)
p
}
}
and then you'd do
production.setProduct(EntityUUID("b1253a77-0585-291f-57a4-53319e897866"))
so anyone reading this could have an intuition where to find the conversion implementation.
Regarding your comment about some generic approach (having 30 types), I won't say it's not possible, but I just do not see how to do it. The reflection you used bypasses the type system. If all the 30 cases are the same piece of code, maybe you should reconsider your object design. Now you can still implement the 30 implicit defs by calling some method that uses reflection similar what you have provided. But you will have the option to change it in the future on just this one (30) place(s).

Scala - how to create a single implicit that can be used for a type constructor

I'm trying to write a method which uses the isEmpty method on types String, Option and List. These classes don't share a common base trait with that method, so I've tried to pass an implicit EmptyChecker in with them:
trait EmptyChecker[Field] {
def isEmpty(data: Field): Boolean
}
implicit val StringEmptyChecker: EmptyChecker[String] = new EmptyChecker[String] {
def isEmpty(string: String): Boolean = string.isEmpty
}
def printEmptiness[Field](field: Field)(implicit emptyChecker: EmptyChecker[Field]): Unit = {
if (emptyChecker.isEmpty(field))
println("Empty")
else
println("Not empty")
}
printEmptiness("abc") // Works fine
The String empty checker works fine, but I've hit problems with making empty checkers for type constructors like Option and List.
For example, Option doesn't work:
implicit val OptionChecker: EmptyChecker[Option[_]] = new EmptyChecker[Option[_]] {
def isEmpty(option: Option[_]): Boolean = option.isEmpty
}
// Both fail compilation: "could not find implicit value for parameter emptyChecker: EmptyChecker[Some[Int]]
printEmptiness(Some(3))
printEmptiness[Option[Int]](Some(3))
If I use a specific Option[Int] checker, it works a little better, but is a bit ugly:
implicit val OptionIntChecker: EmptyChecker[Option[Int]] = new EmptyChecker[Option[Int]] {
def isEmpty(optionInt: Option[Int]): Boolean = optionInt.isEmpty
}
// Fails like above:
printEmptiness(Some(3))
// Passes compilation:
printEmptiness[Option[Int]](Some(3))
So my question is: is it possible to make a single EmptyChecker for each Option and List type and have them work with my method without needing to explicitly declare the type whenever I call it? I'm trying to get a type safe duck typing effect.
I'm using scala 2.11.6.
Thanks in advance!
The source of your problem is that the type of Some(1) is Some[Int], not Option[Int]. There are a couple of ways around this; you can explicitly upcast the expression with a type ascription: printEmptiness(Some(3): Option[Int]). Alternatively, you can define a helper method to do this for you automatically, and if you're using Scalaz, there's one of these provided:
import scalaz.syntax.std.option._
printEmptiness(3.some)
Furthermore if you do use Scalaz, you may find looking at the PlusEmpty/ApplicativePlus/MonadPlus type classes useful.

implicit conversions that add properties to a type, rather than to an instance of a type

I was reading through some older Scala posts to better understand type classes, and I ran
across this one that seemed quite useful, but the example seems to have gotten stale.
Can someone help me figure out the correct way to do what Phillipe intended ? Here is the code
trait Default[T] { def value : T }
implicit object DefaultInt extends Default[Int] {
def value = 42
}
implicit def listsHaveDefault[T : Default] = new Default[List[T]] {
def value = implicitly[Default[T]].value :: Nil
}
default[List[List[Int]]]
When copy/pasted and run in REPL, i get this>
scala> default[List[List[Int]]]
<console>:18: error: not found: value default
default[List[List[Int]]]
^
This doesn't have anything to do with the Scala version. If you read #Philippe's answer, you will notice that the default method simply isn't defined anywhere. That will not work in any Scala version.
It should look something like this:
def default[T: Default] = implicitly[Default[T]].value
Thanks to Jorg for his answer, which, in conjunction with this blog post helped me figure out what is going on here. Hopefully my additional answer will help others who have been confused by this.
My mental picture of type classes is that they are a means by which an author of a library would imbue his/her
library with the desireable trait of retroactive extensibility.
On the other hand, there is yet another technique for ad hoc polymorphism: implicits with wrapper classes.
You would use this latter technique when you are the consumer of a library which has some type
which is missing methods that you find useful.
I am going to try to extend Phillipe's example a bit to illustrate my understanding of how
type classes could be used by a library designer. I am not that experienced with Scala... so if
anyone notices something that is not correct in my understanding please do correct me ! ;^)
// 'Default' defines a trait that represents the ability to manufacture
// defaults for a particular type 'T'.
//
trait Default[T] { def value : T }
// Define a default for int.. this is an object default
//
implicit object DefaultInt extends Default[Int] {
def value = 42
}
// Define a default for Lists that contain instances of a 'T'.
// Interesting that this is method, not an object implicit definition. I
// guess that is to enable the 'on the fly' creation of default values for
// lists of any old type.... So I guess that's why we have
// a 'method implicit' rather than an 'object implicit' definition.
implicit def listsHaveDefault[T : Default] = new Default[List[T]] {
def value = implicitly[Default[T]].value :: Nil
}
// Here is the meat of the library... a method to make a message based of
// some arbitrary seed String, where that method is parameterized by 'T',
// a type chosen by the library user. That 'T' can be
// types for which implicits are already defined by the base library
// (T = Int, and List[T]), or an implicit defined by the library user.
//
// So the library is open for extension.
//
def makeMsg[T](msg: String)(implicit something: Default[T]) : String = {
msg + something.value
}
Given the above code, if I can create a message for the type List[List[Int]], or for Int's
makeMsg[List[List[Int]]]("moocow-")
makeMsg[Int]("dogbox")
And I get this result:
res0: String = moocow-List(List(42))
res1: String = dogbox42
If I want to override the default implicit value for a given type, I can do so like this:
makeMsg[Int]("moocow-")(something=new Object with Default[Int] { def value = 33344 } )
And I get this result:
res3: String = moocow-33344