Chapter 11. Interoperability between Scala and Java

This chapter covers

  • Using Java classes in Scala
  • Working with Java generics and collections
  • Solving integration challenges
  • Building web applications using Java frameworks

One of the most exciting features of Scala is that it runs on the JVM. The benefit of running on a JVM is that you can take advantage of all the frameworks and tools built into other JVM languages. More companies are moving to the JVM even if they don’t use Java as their primary programming language. I strongly believe that any language that doesn’t have support for the JVM is almost a nonstarter, for most of the software projects in the enterprise.

One of the main design goals of Scala is to run on a JVM and provide interoperability with Java. Scala is compiled to Java bytecodes, and you can use tools like javap (Java class file disassembler) to disassemble bytecodes generated by the Scala compiler. In most cases, Scala features are translated to Java features so that Scala can easily integrate with Java. For example, Scala uses type erasure[1] to be compatible with Java. Type erasure also allows Scala to be easily integrated with dynamically typed languages for the JVM. Some Scala features (such as traits) don’t directly map to Java, and in those cases you have to use workarounds (more about this in section 11.3).

1 Java Tutorials: Type erasure, http://download.oracle.com/javase/tutorial/java/generics/erasure.html.

Even though integration with Java is easy for the most part, I encourage you to use pure Scala as much as possible. When I’m working with the Java library or framework, I try to find something equivalent in Scala first, and use Java if there’s no equivalent Scala library available. The downside of using the Java library is that you have to deal with mutability, exceptions, and nulls that are absolutely discouraged in the Scala world. Be extra careful when choosing a Java library or framework before using it in Scala. A good example of a well-written Java library is Joda-Time (http://joda-time.sourceforge.net).

The most common integration of Scala and Java has part of the project written in Scala. Section 11.4 shows how to use Scala with existing Java frameworks such as Hibernate and Spring to build a web application.

In most cases, the integration between Scala and Java is seamless, but be aware of some corner cases because they will occur when you’re integrating Java code with Scala and vice versa. The goal of this chapter is to show you how easily you can integrate Scala with Java and which practices to follow to avoid integration problems. You’ve been integrating with Java classes and frameworks throughout the book without my pointing them out, but here you’ll focus on integration so you can take advantage of both worlds.

The easiest way to introduce Scala in an existing Java project is to write some part of it in Scala and demonstrate the benefits the language has to offer over Java—and then gradually rewrite the Java parts to Scala. I’ve seen this transition path work successfully many times.

Let’s kick off the chapter with some integration examples between Java and Scala. You’ll learn how to handle features that are available in Java but not in Scala, such as static members and checked exceptions, and how to use Scala features like traits in Java code. You’ll also learn how Scala annotations help in integration—for example, generating JavaBean-style get and set. At the end of the chapter you’ll build a web application using Java frameworks.

11.1. Using Java classes in Scala

It’s easy to integrate Java classes with Scala. Because working with dates in Java is always a painful process, the following Java code snippet uses the Joda-Time library to calculate the number of days between two dates:

package chap11.java;

import org.joda.time.DateTime;
import org.joda.time.Days;
import java.util.Date;

public class DateCalculator {
  public int daysBetween(Date start, Date end) {
    Days d = Days.daysBetween(new DateTime(start.getTime()),
    new DateTime(end.getTime()));
    return d.getDays();
     }
   }

In a new SBT project, save the preceding code snippet to DateCalculator.java in the src/main/java/chap11/java folder. SBT knows how to cross-compile Java and Scala code. To use this class in Scala, extend the Java class as follows:

package chap11.scala

import chap11.java._
import java.util.Date

class PaymentCalculator(val payPerDay: Int = 100) extends DateCalculator {
  def calculatePayment(start: Date, end: Date) = {
    daysBetween(start, end) * payPerDay
  }
}

The Scala class is calculating the payment using the daysBetween method defined in the DateCalculator Java class. The integration is so seamless, you won’t even notice the difference.

In the next section you’ll learn how to use Java static members in Scala.

Compiling Java and Scala together

SBT knows how to build mixed Scala and Java projects out of the box. The Scala compiler allows you to build against both Java classes and Java source code. That way, if you have bidirectional dependency between Java and Scala, you can build them together without worrying about order.

You can also use the Maven build tool to build mixed Java and Scala projects. To do so, you have to add an additional Maven plug-in. In this chapter’s final example you’ll use Maven to build an example project.

11.1.1. Working with Java static members

When working with Java classes that declare static members, you need to understand how they’re interpreted in Scala.

Scala doesn’t have any static keywords, and Scala interprets Java static methods by thinking of them as methods of a companion object. Take a look at the following example to see how it works. This code adds a static method that returns the chronology (chronological calendar system) used by Joda-Time to represent time:

To access the static member, you have to refer it as if it’s defined in a companion object, like the following:

class PaymentCalculator(val payPerDay: Int = 100) extends DateCalculator {
  ...
  def chronologyUsed = DateCalculator.getChronologyUsed
}

You’re accessing the static method defined in DateCalculator by using the class name like you access a companion object.

Visibility issues between Scala and Java

Scala and Java implement visibility differently.

Scala enforces visibility at compile time but makes everything public at runtime. There’s a reason for that: in Scala, companion objects are allowed to access protected members of companion classes, and that can’t be encoded at the bytecode level without making everything public.

Java enforces visibility rules both at compile time and runtime. This brings up some interesting corner cases. For example, if you have a protected static member defined in a Java class, there’s no way to access that member in Scala. The only workaround is to wrap it in a public member so that can be accessed.

Up next, you’ll see how to work with Java checked exceptions, because Scala doesn’t have them.

11.1.2. Working with Java checked exceptions

Scala’s lack of checked exceptions at times creates confusion when working with Java codebases where the compiler enforces checked exceptions. If you invoke the following Java method in Scala, you don’t have to wrap the call in a try/catch block:

package chap11.java;
import java.io.*;
public class Writer {
  public void writeToFile(String content) throws IOException {
    File f = File.createTempFile("tmpFile", ".tmp");
    new FileWriter(f).write(content);
  }
}

In Scala, you can invoke the method without a try/catch block:

scala> def write(content: String) = {
     | val w = new Writer
     | w.writeToFile(content)
     | }
write: (content: String)Unit
scala> write("This is a test")

As a programmer, it’s your responsibility to determine whether you need to catch the exception. The Scala compiler won’t force you. In cases where you think you should catch the exception, don’t rethrow the exception from Scala. It’s a bad practice. A better way is to create an instance of the Either or Option type. The following code snippet invokes the writeToFile method and returns an instance of Either[Exception, Boolean]:

def write(content: String): Either[Exception, Boolean] = {
  val w = new Writer
  try {
    w.writeToFile(content)
    Right(true)
  }catch {
    case e: java.io.IOException => Left(e)
  }
}

The benefit is now you can compose with the result. Always remember that exceptions don’t compose. But there may be cases where you have to throw an exception because some framework or client code expects it, and in these cases you can use Scala annotations to generate bytecodes that throw an exception (section 11.2.1 has more on this). For now, let’s move on to Java generics. Understanding how Java generics work is important because they’re used in Java collections.

11.1.3. Working with Java generics using existential types

Java generics translate straightforwardly to Scala type parameters. For example, Comparator<T> translates to Comparator[T], and ArrayList<T> to ArrayList[T]. But things become interesting when you have classes defined in Java with wildcard types. Here are two examples of Java collections with wildcard types:

Vector<?> names = new Vector<?>()
List numbers = new ArrayList()

In both cases, the type parameter is unknown. These are called raw types in Scala, and existential types let you handle these raw types in Scala. Vector<?> could be represented as Vector[T] forSome { type T } in Scala. Reading from left to right, this type expression represents a vector of T for some type of T. This type T is unknown and could be anything. But T is fixed to some type for this vector.

Let’s look at an example to see how to use Java raw types in Scala. The following creates a Java vector with a wildcard type:

import java.util.*;
class JavaRawType {
  public static Vector<?> languages() {
    Vector languages = new Vector();
    languages.add("Scala");
    languages.add("Java");
    languages.add("Haskell");
    return languages;
  }
}

JavaRawType.languages returns a vector of three languages, but with wildcard type ?. To use the languages method in Scala, you have to use the existential type. The type signature will be Vector[T] forSome { type T}, as in the following:

import java.util.{Vector => JVector }

def printLanguages[C <: JVector[T] forSome { type T}](langs: C):Unit = {
  for(i <- 0 until langs.size) println(langs.get(i))
}
Working with Java collections

Working with Java collection classes in Scala is painful once you get used to the power of the Scala collections library. Ideally, you should work with Scala collections in Scala code and transform them into the Java collection equivalent when crossing into Java code, and vice versa. That way, you can use the power of the Scala collections library when needed and easily integrate with Java codebases that only understand Java collection classes. The Scala library ships with two utility classes that do exactly that for you: scala.collection.JavaConversions scala.collection.JavaConverters

scala.collection.JavaConversions
scala.collection.JavaConverters

Both of these classes provide the same set of features, but they’re implemented differently. JavaConversions provides a series of implicit conversions that convert between a Java collection and the closest corresponding Scala collection, and vice versa. JavaConverters uses a “Pimp my Library” pattern to add the asScala method to Java collection and asJava method to Scala collection types. My recommendation would be to use JavaConverters because it makes the conversion explicit. The following example uses JavaConverters to convert java.util.List to Scala and back:

scala> import java.util.{ArrayList => JList }
import java.util.{ArrayList => JList}
scala> val jList = new JList[Int]()
jList: java.util.ArrayList[Int] = []
scala> jList.add(1)
res1: Boolean = true
scala> jList.add(2)
res2: Boolean = true
scala> import scala.collection.JavaConverters._
import scala.collection.JavaConverters._

scala> jList.asScala foreach println

The asScala on jList transforms the java.util.ArrayList to scala.collection.mutable.Buffer so that you can invoke foreach on it. The following transforms scala List to java.util.List:

scala> List(1, 2).asJava
res4: java.util.List[Int] = [1, 2]

The existential type sets the upper bound of the type C and prints all the elements of the Java vector.

There’s placeholder syntax for existential type JVector[_]. It means the same thing as JVector[T] forSome { type T }. The preceding printLanguages method could also be written as follows:

def printLanguages[C <: JVector[_]](langs: C):Unit = {
    for(i <- 0 until langs.size) println(langs.get(i))
  }

11.2. Using Scala classes in Java

One of the most interesting language features of Scala is traits, which are used a lot in Scala codebases. If you define a trait with only abstract methods, it gets compiled in the Java interface, and you can use it in Java without any issues. But if you have a trait with concrete methods, things become interesting. Let’s take an example where you’ll have a trait with concrete methods and see how that’s compiled into Java bytecode.

The following example has a Scala trait that makes objects persistable to a database when mixed in:

package chap11.scala

trait Persistable[T]{
  def getEntity: T

  def save(): T = {
    persistToDb(getEntity)
    getEntity
  }
  private def persistToDb(t: T) = {...}
}

You have an abstract method called getEntity and two concrete methods, save and persistToDb. When this code is compiled, the Scala compiler generates two class files, Persistable.class and Persistable$class. To verify the content of each class file, you can use the :javap option in the SBT console:

scala> :javap chap11.scala.Persistable
Compiled from "ScalaJavaMash.scala"
public interface chap11.scala.Persistable extends scala.ScalaObject{
    public abstract java.lang.Object getEntity();
    public abstract java.lang.Object save();
}

scala> :javap chap11.scala.Persistable$class
Compiled from "ScalaJavaMash.scala"
public abstract class chap11.scala.Persistable$class extends
  java.lang.Object{
    public static java.lang.Object save(chap11.scala.Persistable);
    public static void $init$(chap11.scala.Persistable);
}

The Persistable.class file represents the Java interface, with all the public methods declared in the Persistable trait, and extends scala.ScalaObject. Every user-defined class in Scala extends scala.ScalaObject. On the other hand, the Persistable $class file defines an abstract class that defines all the concrete methods of the trait. Think of this abstract class as a façade to all the concrete methods defined in the trait.

On the Java side, take the help of both classes. You’ll extend the interface and use the abstract class as a façade to access the concrete methods of the trait. The following example has an Account type that implements the Persistable interface and uses the static methods in Persistable$class to access concrete methods of the Persistable trait:

The implementation of the Persistable interface is straightforward. getEntity returns an instance of the Account object, and the save method delegates to the static save method of the Persistable$class class to access the implementation-defined trait. Note that when working with stackable traits, it’s much better to create a concrete class in Scala and then directly use it or extend it in Java. (This chapter’s accompanying codebase has an example of that.)

One of the first hurdles people face when integrating Scala with Java frameworks is that Scala classes don’t have JavaBean-style get and set methods. Scala annotations provide the flexibility to specify how you want the Scala compiler to generate bytecodes and are helpful in cases like these.

11.2.1. Using Scala annotations

Scala doesn’t follow the standard Java getter and setter pattern. In Scala, getters and setters look different. For example, to create a Scala class with a Scala-style getter and setter, all you have to do is declare members as var, as in the following:

class ScalaBean(var name: String)

When compiled, this class generates the following bytecode:

If you compare the following code with the code generated in the preceding snippet, it will make sense:

scala> val s = new chap11.scala.ScalaBean("Nima")
s: chap11.scala.ScalaBean = chap11.scala.ScalaBean@6cd4be25

scala> s.name
res0: String = Nima

scala> s.name = "Paul"
s.name: String = Paul

If you add the scala.reflect.BeanProperty annotation to a property, the Scala compiler will generate corresponding get and set methods. In the case of name, it will generate getName and setName methods:

class ScalaBean(@scala.reflect.BeanProperty var name: String)

Here’s how it looks when inspected using javap:

Note here that when using the BeanProperty annotation, the Scala compiler will generate both Scala and Java-style get and set methods. Using BeanProperty does increase the size of the class file generated, but that’s a small price to pay for the interoperability with Java. Now if you want to generate JavaBean-compliant BeanInfo, you can use scala.reflect.BeanInfo.

Section 11.1 showed that Scala doesn’t have checked exceptions, and Scala doesn’t have a throws keywords to declare methods that throw exceptions. This at times causes problems. For example, if you want to use Scala to declare a java.rmi.Remote interface, you’ll have trouble because each method declared in the Remote interface needs to throw RemoteException. Again, using annotations you could instruct the Scala compiler to generate methods with a throws clause. The following code defines an RMI interface in Scala:

trait RemoteLogger extends java.rmi.Remote {
  @throws(classOf[java.rmi.RemoteException])
  def log(m: String)
}

The RemoteLogger trait extends the standard java.rmi.Remote to mark the interface as an RMI remote interface; to generate the throws clause it’s using the scala.throws annotation defined in the Scala standard library. Look into the generated bytecode, and you’ll see the throws clause:

scala> :javap chap11.scala.RemoteLogger
Compiled from "ScalaJavaMash.scala"
public interface chap11.scala.RemoteLogger extends java.rmi.Remote{
  public abstract void log(java.lang.String) throws
    java.rmi.RemoteException;
}

You can also use Scala’s target meta annotation to control where annotations on fields and class parameters are copied. In the following code the Id annotation will only be added to the Bean getter getX:

import javax.persistence.Id
class A {   @(Id @beanGetter) @BeanProperty val x = 0 }

Otherwise, by default, annotations on fields end up on the fields. This becomes important when you’re dealing with Java frameworks that are particular about where the annotation is defined. In the next section you’ll see some usage of the target annotation and how to use popular frameworks like Spring and Hibernate in the Scala codebase.

11.3. Building web applications in Scala using Java frameworks

In this section you’ll build a web application using Scala classes with Java frameworks. This example will show how you can use Scala in a Java-heavy environment, so when adopting or migrating to Scala you don’t have to throw away all your investment in Java frameworks and infrastructure. Obviously, some of the boilerplate code goes away when you use frameworks built for Scala. Nonetheless, learning to work with Java frameworks is important for cases where you don’t have the option to select Scalabased frameworks. In this section you’re going to build a web application using the Spring framework (www.springsource.org) and Hibernate (www.hibernate.org). You’ll also let go of your favorite build tool, SBT, and use Maven to build your Java because it’s the most common build tool used in Java projects.

Note

This section assumes that you’ve previously used Spring, Hibernate, and Maven to build Java web applications. If you haven’t, it may become hard to follow. It’s also safe to skip this section if you aren’t interested in working with Java frameworks.

Before going any further, let’s identify the type of application you’re going to build. You’ll build a small web application called topArtists that displays top artists from Last.fm (www.last.fm). Last.fm is a popular music website that lets visitors access internet radio stations. Last.fm also provides an API you can use to retrieve various charts about songs and artists. You’ll be using its chart.getTopArtists REST API to retrieve all the current top artists and save them in your local database. You’ll also display all the artists stored in your local database to the user. Let’s move on and set up the Maven build.

Note

You first need to get an API key from Last.fm. Make sure you have it before you run this example. You can acquire an API key at the Last.fm website (www.last.fm/api/authentication).

If you’ve done Java development, then most likely you’ve already used Maven. But if Maven isn’t set up, download the latest version of the Maven build tool (http://maven.apache.org/download.html). Maven knows how to compile Java source files, but to make it compile Scala source files you need to add the Maven Scala plug-in.[2] To create an empty web application using Maven, execute the following command:

2 Maven Scala plug-in download, http://scala-tools.org/mvnsites/maven-scala-plugin/.

mvn archetype:generate -DgroupId=scala.in.action -DartifactId=top.artists
 -DarchetypeArtifactId=maven-archetype-webapp

That command will create an empty web project for you. The structure of the project should be familiar because it’s exactly the same as an SBT project (SBT follows Maven conventions). Once you have the pom.xml file (the Maven build file generated by the preceding command), you can configure all the dependencies. As mentioned, you’ll use the Hibernate and Spring frameworks to build the application. To save time, you can copy the pom.xml file from the codebase associated with the project.

There’s no need to explain how Maven works because once you configure all the dependencies, it gets out of your way. But if you’ve never used Maven, remember that pom.xml is the build file you use to configure Maven and specify all the dependencies.

For the topArtists application you’ll use Spring to build the web layer and also use it as a dependency injection framework. Hibernate will be your ORM layer and will save all the artists retrieved from Last.fm to the database. For your toy application, you’ll be using the database HSQLDB (http://hsqldb.org). But to make a REST request to Last.fm, you’ll use a pure Scala library called dispatch.[3] Dispatch is a Scala library, built on top of the Async Http Client library, that makes it easy to work with web services.[4]

3 Dispatch Scala library: http://dispatch.databinder.net/Dispatch.html.

4 See “AsyncHttpClient/async-http-client,” https://github.com/AsyncHttpClient/async-http-client.

Note

The complete version of the topArtists web application is available in the code that accompanies this chapter.

Let’s move on and write the code necessary to build the application.

Compiling Scala code with Maven

By default, Maven knows how to compile Java code. If you take a look at the pom.xml file associated with the codebase of this chapter, you’ll notice the following snippet:

...
<groupId>org.scala-tools</groupId>
<artifactId>maven-scala-plugin</artifactId>
<version>2.15.2</version>
...

This adds the Maven Scala plug-in. As you can see, this code calls for the 2.15.2 version of the plug-in, but make sure you always use the latest version. Once you add the plug-in, it will create goals (tasks) to compile and run Scala classes. For example, you can use Maven’s scala:compile to compile Scala code and scala:cc to have a continuous compilation (similar to ~compile in SBT). You can find more options at the Maven Scala plug-in documentation page.

11.3.1. Building the model, view, and controller

The topArtists application displays artists retrieved from the REST API call from Last.fm. To see what information you can retrieve from Last.fm, invoke the following URL from any web browser window:

http://ws.audioscrobbler.com/2.0/?method=chart.gettopartists&api_key=
<your api key>

Make sure you use your Last.fm API key before invoking the URL. If the request is successful, you’ll see information about artists, including name, number of times the songs have been played, listeners, URL, and other attributes. To keep things simple, use only the result from the first page and store the name of the artist, play count, and listeners. Your simple domain object will look like the following:

package chap11.top.artists.model

class Artist {
  var name: String = ""
  var playCount: Long = 0
  var listeners: Long = 0
}

This model class represents an artist by name, number of times songs by the artist have been played, and number of listeners. You’ll retrieve all this data from the Last.fm feed.

Because you’re using Hibernate as your ORM tool, you need to make your domain object compatible with Hibernate. First use @BeanProperty to generate JavaBean-style get/set methods. Then use necessary javax.persistence annotations so that Hibernate knows how to retrieve and save Artist domain objects into the database. The following listing shows the complete Artist domain object.

Listing 11.1. Artist Hibernate domain object

Hibernate implements the Java Persistence API (JPA), and by using the JPA annotation Entity you’re specifying Hibernate to persist the object to the database. You’re using the Id annotation to specify the ID field of the class and scala.annotation.target to generate the Id and GeneratedValue annotation at the field level.

Now, to save and retrieve the artist from the database, you have to work with the Hibernate session factory. Create a new class to encapsulate that and call it ArtistDb. This class will help you hide Hibernate-specific details from the rest of the code. Think of this class as a data access object. Because you’re using Spring, you can easily inject the necessary Hibernate dependencies into this new class. The following listing shows the complete implementation of the ArtistDb class.

Listing 11.2. ArtistDb.scala database access with Hibernate

The ArtistRepository class is marked with the Spring stereotype annotation Repository so that the Spring framework can automatically scan and load the component from the classpath. When Spring loads the class, it also sets the sessionFactory dependency. In the next section, you’ll see how all these components are configured. For now, assume that the sessionFactory will be available in the ArtistRepository class to make database calls using Hibernate. The save method is straightforward: using the current Hibernate session, it saves an instance of Artist to the database. asInstanceOf[Long] typecasts the return value of the save to Long. In this case, you know that the save operation will return the Id value of the object saved. findAll queries the database and returns all the artists stored in the database. You typecast using asInstanceOf because by default the Hibernate list method returns a List of objects. At this point, you have enough code to save and retrieve domain objects from the database. Let’s move on to build the controller.

As discussed earlier, you’re going to use Spring to build your web tier. Again, you’ll use Spring’s stereotype annotation @Controller to mark a class as a controller. The job of the controller you’ll build will be to get the top artists from Last.fm and display artists stored in the local database. Start off with the action that retrieves the list from the local database and sends it to the view to render. You already have an ArtistDb that knows how to retrieve artists from the database, and you’ll use Spring to inject an instance of ArtistDb to the controller:

@Controller
class ArtistsController {
  @Autowired
  val db: ArtistDb = null
}

Add a method in the controller that maps to a URL and returns a list of artists to the view:

@RequestMapping(value = Array("/artists"), method = Array(GET))
def loadArtists() =
   new ModelAndView("artists", "topArtists", db.findAll)

The @RequestMapping annotation maps the "/artists" URI to the method loadArtists. And in the method it uses db.findAll to find all the artists from the database. The first parameter to ModelAndView is the name of the view that will be rendered as a result of the method. The topArtists parameter is a handy way to name the response of db.findAll. Using the topArtists name inside the view, you can access all artists returned from the findAll call. But before you can return a list of artists successfully, you have to first get the list from Last.fm. Allow the user to refresh the artists saved in the local database. To implement refresh, invoke the REST API specified by Last.fm. Use the Dispatch library to make a REST call to Last.fm. Dispatch provides a nice DSL or wrapper over the Apache HttpClient library. The following code snippet creates an Http request object from the URL:

val rootUrl = "http://ws.audioscrobbler.com/2.0/"
val apiMethod = "chart.gettopartists"
val apiKey = sys.props("api.key")
val req = url(rootUrl + "?method=" + apiMethod + "&api_key=" + apiKey)

The API key is retrieved from the system property. When running the application, you have to specify the API as a system property. The url method takes a string URL as an input and returns an instance of Http request. But creating an Http request won’t do much unless you tell Dispatch how to process the response received from the request. You can easily do that by specifying a handler. In this case we will use the built-in handler as.xml.Elem to handle the XHTML response:

Http(req OK as.xml.Elem).map {resp => ...}

Http returns the Promise of scala.xml.Elem (since every HTTP request is handled asynchronously) and we are using map to access the contents of the Promise object. Since we are not using Spring’s asynchronous support, we will wait for the Promise (by invoking the apply method) to finish before rendering the result. The response from Last.fm consists of an XML with a list of artists and looks something like the following:

<lfm status="ok">
  <artists page="1" perPage="50" totalPages="20"
     total="1000">
    <artist>
       ...
     </artist>
    <artist>
       ...
     </artist>
    ...
  </artists>
</lfm>

You’ll use Scala’s awesome native XML support to parse the result. Dispatch already converted the response to an instance of NodeSeq, and now you have to extract all the artists from the response, create a Hibernate Artist object, and save it to the database. Here’s the method that does exactly that:

The refresh action of the controller needs to use the retrieveAndLoad method to load and save the artists to the database and display the artists view. The following listing shows the complete controller implementation.

Listing 11.3. Completed ArtistsController.scala

Now that you have the code for the model and controller, it’s time to turn to the view. This simple view will take the response from the controller and render that using Java-Server Pages (JSP). The example uses a pure Java solution for the view, but you can experiment with template libraries written in Java, like Scalate (http://scalate.fusesource.org). Your JSP view will take the topArtists parameter returned from the controller and iterate through it to render the response. The following listing shows what the view looks like.

Listing 11.4. artists.jsp to render all the artists

You use the topArtists to access the list of artists returned from the controller and display them. In the next section you’ll integrate all the pieces using Spring configuration files.

11.3.2. Configuring and running the application

You’ll use the Spring configuration to configure both Spring MVC and Hibernate. This way Spring will ensure that all the necessary dependencies you need for your model and controller objects are properly initialized and injected. Because you followed all the conventions using Scala and Java annotations at the Spring configuration level, you won’t have any problem configuring Scala classes. This is a great benefit of smooth interoperability between Scala and Java. In the following listing’s spring-context-data.xml file, you’re configuring the model and controller objects.

Listing 11.5. Configuring the model and Hibernate using Spring

Using this file, you’re configuring Hibernate with HSQLDB and the domain objects that are used with Hibernate. You’re also using Spring’s component scan to look for ArtistDb so that it gets initialized with the necessary Hibernate dependencies. Check Spring’s documentation for more about the tags used in the configuration file. In the following listing’s spring-context-web.xml file, you’re configuring the controller and the Spring servlets you’re going to use to intercept HTTP requests.

Listing 11.6. Configuring the controller and web using Spring

The UrlBasedViewResolver class from Spring is used to intercept the HTTP request and forward the request to the appropriate controller. In this case, it’s ArtistsController. You also configure suffix with .jsp so that when you return ModelAndView with "artists" from the controller, it can look for the artists.jsp file in the WEB-INF/jsp folder. To load these configuration files when the application starts, add them to the web.xml file. The following listing shows the complete web.xml.

Listing 11.7. web.xml of the topArtists web application

Most of the content of this file should be familiar to you if you’ve built a web application for the JVM. All the Java web containers read the web.xml to initialize Java-based web applications. The listener attribute allows applications to listen to events generated by containers, such as when an application is loaded or unloaded. In this case, the listener configured is ContextLoaderListener, and this class knows how to configure Spring by reading context-param . To run the application, you can use the already configured Jetty web server using the following command:

mvn -Dapi.key=<your-last.fm-pai-key> jetty:run

As you can see, setting up and creating web applications using Scala and Java frameworks is easy. Some of the boilerplate configuration is unavoidable when working with Java frameworks, but you can still have fun writing Scala code.

11.4. Summary

One thing that should be clear from this chapter is that Scala’s interoperability with Java is pain-free. There are a few places where you have to take extra precautions, but for the most part you can integrate with existing Java codebases without thinking too much. The extra carefulness comes when you have to integrate some features of Scala that aren’t supported in Java and vice versa. You learned how to deal with situations like that throughout this chapter. Because Scala is designed from the ground up to interoperate with Java, most of the workarounds are also simple to implement and learn.

The benefit of simple integration with Java means you can easily get started with Scala in existing codebases. As the final example demonstrates, you can use Scala with existing popular Java frameworks without rewriting entire applications.

The next chapter looks into one of the most exciting Scala frameworks: Akka. This framework lets you build large, scalable, and distributed applications using various concurrency models. I know you’ve been waiting for this for a long time—so without further delay, let’s jump into the exciting world of Akka.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset