The Artima Developer Community
Sponsored Link

Weblogs Forum
Practical Scala/Java interoperability by small examples

0 replies on 1 page.

Welcome Guest
  Sign In

Go back to the topic listing  Back to Topic List Click to reply to this topic  Reply to this Topic Click to search messages in this forum  Search Forum Click for a threaded view of the topic  Threaded View   
Previous Topic   Next Topic
Flat View: This topic has 0 replies on 1 page
Vlad Patryshev

Posts: 4
Nickname: patryshev
Registered: Apr, 2008

Practical Scala/Java interoperability by small examples (View in Weblogs)
Posted: Nov 8, 2010 7:52 PM
Reply to this message Reply
Summary
While Scala can work with Java collections, and Java, more or less, can work with Scala collections, for sanity sake they better should be kept separate. So how do Java and Scala code exchange collections?
Advertisement
If you try to combine Java code with Scala in your application, everything seems to go fine until you bump into big differences between Java collections and Scala collections. A Scala Traversable is not Java Iterable and vice versa; maps are different, etc. So, in practice, you have to do conversion. Fortunately, there are pretty good implicit converters in Scala 2.8; what remains is to use them properly. I'll show a couple of pretty self-explaining examples here. Here our Scala code returns a Set to Java:
package com.company.user
 
import java.util.{Set => JavaSet}
import scala.collection.JavaConversions._
 
class GetAllGadgets(withHistory: Boolean) extends Getter[JavaSet[GadgetView]] {
 
  overide def execute = allGadgets map { g => g view withHistory }
}
process is declared in (a Java interface) as returning JavaSet; so an implicit conversion is applied to the set produced by mapping allGadgets using g => g.view(withHistory) transformation. Here's how a unittest may look like:
    final Gadget gadget = new Gadget("test gadget");
    GetAllGadgets query = new GetAllGadgets(true);
    Mockery mockery = new Mockery();
    final GadgetStorage storage = mockery.mock(GadgetStorage.class);
    query.setStorage(storage);
 
    mockery.checking(new Expectations() {{
      one(storage).allGadgets(); will(returnValue(Sets.newHashSet(gadget)));
    }});
 
    Set<GadgetView> result = query.exec();
    assertEquals(1, result.size());
    assertEquals("test gadget", result.iterator().next().getName());
In the following example, the Scala class takes a Java Iterable and returns a Java Set:
...
import scala.collection.mutable.{Set => MutableSet}
import java.util.{Set => JavaSet}
import scala.collection.JavaConversions._
 
class GetGadgets(val ids: java.lang.Iterable[Id[Gadget]]) extends Getter[JavaSet[GadgetView]] {
 
  def gadgets: MutableSet[Gadget] = repo.find(Gadget.ID, ids)
  override def exec = gadgets map { g => g view false }
}
What happens here: we explicitly show that we accept a Java Iterable, but all other conversions are implicit. First, storage.find(Gadget.ID, ids) is a Java code; it returns a Java Set. This set is implicitly transformed into scala.collection.mutable.Set, known in the code under an alias of MutableSet, for clarity. Then process transform the set into a set of views, same as in the previous example - and converts the result, implicitly, to java.util.Set, just because such is the signature of the method process. A Java programmer would probably complain about not having the result of process explicitly defined right here. Well... the language is Scala, not Java. Wind of change. In an unfortunate case when we need both Scala and Java collections, we will have to declare two methods, like in the example below:
import java.util.{Map => JavaMap}
import scala.collection.JavaConversions._
 
class EntityIdentity {...
  def allProperties: Map[String, String] =
    Map("shortName"   -> entityNameShortForm,
        "longName"    -> etityNameLongForm,
        "emailSuffix" -> emailSuffix,
        "domainName"  -> domainName)
 
  def allPropertiesForJava: JavaMap[String, String] = allProperties 
This may be a little bit awkward, but still writing code in Java is a temporary nuisance, right?

Topic: Breaking Up The Monolith: coming at last Previous Topic   Next Topic Topic: JavaOne 2010: Upcoming Java Features

Sponsored Links



Google
  Web Artima.com   

Copyright © 1996-2019 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use