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

dbc
  • 104,963
  • 20
  • 228
  • 340
virtualeyes
  • 11,147
  • 6
  • 56
  • 91
  • 10
    BTW: your `safe` method can be replaced by `Option.apply`. For example: `Option(5)` yields `Some(5)` and `Option(null)` yields `None`. – dhg Apr 06 '12 at 19:41
  • 1
    +1 nice, that's cool, did not know that. Type preserved as well, I love this language ;-) – virtualeyes Apr 06 '12 at 19:46
  • 1
    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 <: AnyRef – Don Mackenzie Apr 06 '12 at 20:55

1 Answers1

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.

Tomasz Nurkiewicz
  • 334,321
  • 69
  • 703
  • 674
  • 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 version – virtualeyes Apr 06 '12 at 21:09