Option-izing Java getters
Asked Answered
D

1

3

When working with Java from Scala, we have to account for null.

HttpServletRequest getters (getAttribute, getHeader, etc.) for example, all potentially return null.

I know I can manually do a case/match or map operation on each call to an HttpServletRequest method, but that's a bit tedious. Also, method calls like request.getHeader("Accept-Encoding") are a mouthful.

I came up with an enrichment to handle both issues:

class Servlet_Request_Provides_NullSafe_Getters (r: HttpServletRequest) {

  def header(s: String) = Option( r.getHeader(s) )
  def attrib(s: String) = Option( r.getAttribute(s) )
  def remoteHost        = Option( r.getRemoteHost )
  def accepts = header("Accept-Encoding")
}
implicit def request2Option(r: HttpServletRequest) = 
  new Servlet_Request_Provides_NullSafe_Getters(r)

1) Is there another/better way than enrich-my-library to achieve the same/similar affect?
2) If this is "the" way to go, what are the performance impacts/risks? In other words, can one get burned by the apparent utility/conveniences of this pattern?

Sorry if this stuff is obvious, only just started enriching the other day, and it really seems quite useful. Just want to make sure I'm applying the pattern in the proper scenarios...

EDIT
@dhg pointed out that Option.apply() and:

def safe[T](v: T) = v match {
  case null => None
  case x => Some(x)
}

are equivalent, so the getter methods now use Option(f()) instead of my extraneous safe(f()) wrapper

Thanks

Deannedeans answered 6/4, 2012 at 19:37 Comment(3)
BTW: your safe method can be replaced by Option.apply. For example: Option(5) yields Some(5) and Option(null) yields None.Basir
+1 nice, that's cool, did not know that. Type preserved as well, I love this language ;-)Deannedeans
In the opposite direction when providing parameters to API calls that can be null from Option[T] to T (where T can be null) use Option.orNull but remember this is not he same as Option.getOrElse(null) as it is restricted to T <: AnyRefNapkin
L
4

As already mentioned in the comments:

def safe[T](v: T) = Option(v)

Option(v) is equivalent to:

v match {
  case null => None
  case x    => Some(x)
}

Also the safe method is unnecessarily public and part of the class. I would suggest simply inlining it.

2) If this is "the" way to go, what are the performance impacts/risks?

Generally adapting Java legacy APIs to utilize Option is a good idea. I do this often with EntityManager.find() that can return null.

Your implicit conversion is also fine. However don't use underscores in class names, Java/Scala naming conventions prefer CamelCase.

Luminal answered 6/4, 2012 at 19:44 Comment(1)
k, on the right track then. re: underscore in class names, the only place I am using them is here, in pimped classes, as the SomeApiProvidesSomeExtraFunctionality class name is for me not as readable as the underscore versionDeannedeans

© 2022 - 2024 — McMap. All rights reserved.