From Java to Scala - The Web Tier

It's quite clear that switching from Java to Scala can drastically shorten your code, make it more type safe and maintainable, and improve you productivity. However there is concern among developers who need to maintain an existing Java codebase - does switching to Scala means I have to rewrite my entire application from scratch? Can Java and Scala live side by side? What about existing libraries and business logic?

In the next series of posts I intend to demonstrate how to migrate existing parts of common applications from Java to Scala. These will be simple down-to-earth examples, aiming for a smooth transition to Scala.

This post covers the web tier. A very common practice these days is to use JSON services, so for our example we will use a simple service that takes no arguments and returns a JSON containing two string fields: language and framework.

The snippets are part of the example application https://github.com/GabiAxel/scala-examples/tree/master/scala-web-example
This is a Maven project with Tomcat plugin which allows you to quickly run it using the following command:

mvn tomcat7:run-war


When Tomcat is running you can access the following URLs:
http://localhost:8080/java
http://localhost:8080/scala
http://localhost:8080/spring
http://localhost:8080/unfiltered

The simplest possible implementation in Java would be a Servlet. We will use Jackson to serialize an ImmutableMap from Guava as the HTTP response body. the POM should contain the following dependencies:

<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>3.1.0</version>
    <scope>provided</scope>
</dependency>
<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>14.0.1</version>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.2.2</version>
</dependency>


and this is the servlet code, using Servlets 3.0 @WebServlet annotation to map it to "/java":
 

@WebServlet("/java")
public class JavaServlet extends HttpServlet {
	
	private static final long serialVersionUID = 1L;

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		
		response.setContentType("application/json");
		
		Map<string,> value = ImmutableMap.of(
			"language", "Java",
			"framework", "Servlet");
		
		ObjectMapper mapper = new ObjectMapper();
	
		mapper.writeValue(response.getOutputStream(), value);
	}

}
</string,>


We can rewrite this servlet in Scala, but first we need to add Scala support by adding the Maven Scala plugin so that Scala classes will also be compiled in Maven's "compile" phase:

<plugin>
    <groupId>org.scala-tools</groupId>
    <artifactId>maven-scala-plugin</artifactId>
    <executions>
        <execution>
            <goals>
                <goal>compile</goal>
            </goals>
        </execution>
    </executions>
</plugin>


and add Jackson's Scala module in order to support serializing Scala classes (in this case Scala Map):

<dependency>
    <groupId>com.fasterxml.jackson.module</groupId>
    <artifactId>jackson-module-scala_2.10</artifactId>
    <version>2.2.2</version>
</dependency>


now we can write the Scala Servlet:
 

@WebServlet(Array("/scala"))
class ScalaServlet extends HttpServlet {

  override def doGet(request: HttpServletRequest, response: HttpServletResponse) = {
	
    response setContentType "application/json"
    
    val value = Map(
        "language" -> "Scala", 
        "framework" -> "Servlet")
    
    val mapper = new ObjectMapper().registerModule(DefaultScalaModule)
    
    mapper.writeValue(response.getOutputStream, value)
  }

}


This example is pretty self-explanatory. The difference from the Java servlet is that we are using Scala Map, so we don't need a syntactic sugar third-party library like Guava. We also need to register Jackson Scala module so that the mapper will be able to serialize the Scala map.

If you implemented a REST API in Java, you probably used a framework for that, and not used Servlets directly. Spring MVC is a popular framework for implementing such services. To use it we first add it to the POM:

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>3.2.2.RELEASE</version>
</dependency>


add the dispatcher servlet configuration to web.xml:

<servlet>
    <servlet-name>spring</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>spring</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>


and add bean definitions in spring-servlet.xml, in this case we use package scan and annotation support:

<context:component-scan base-package="com.gabiaxel.example"/>
<mvc:annotation-driven />


Here is a controller which is equivalent to the Servlet we saw earlier:
 

@Controller
public class SpringController {

	@ResponseBody
	@RequestMapping(value="/spring", method=GET)
	public Object getValue() {

		return ImmutableMap.of(
			"language", "Java",
			"framework", "Spring MVC");
	}
}


@Controller marks this class as a Spring controller bean, @RequestMapping maps HTTP GET requests to "/spring" path to the getValue method, and @ResponseBody indicates that the method's returned value will be serialized to JSON (when Jackson is in the classpath).

This time we will not simply rewrite the code in Scala, but look for a library that provides this functionality "the Scala way". The library I chose for this example is Unfiltered, accompanied by Argonaut Unfiltered JSON integration. The dependencies are:

<dependency>
    <groupId>net.databinder</groupId>
    <artifactId>unfiltered-filter_2.10</artifactId>
    <version>0.6.8</version>
</dependency>
<dependency>
    <groupId>io.argonaut</groupId>
    <artifactId>argonaut-unfiltered_2.10</artifactId>
    <version>6.0-RC3</version>
</dependency>


With Unfiltered we write a filter that extends Plan and map it in web.xml:

<filter>
    <filter-name>unfiltered</filter-name>
    <filter-class>com.gabiaxel.example.UnfilteredApp</filter-class>
</filter>
<filter-mapping>
    <filter-name>unfiltered</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>


in the filter itself we implement the intent method, where we map HTTP requests to partial methods:
 

class UnfilteredApp extends Plan {

  def intent = {
    
  	case GET(Path("/unfiltered")) => {
    
  	  val value = Map(
          "language" -> "Scala", 
          "framework" -> "Unfiltered")
      
      JsonResponse(value)
    }
  }
}


Pretty much the same idea as Spring MVC, but using Scala constructs.

Of course there are plenty of libraries for implementing RESTful services, and we barely scratched the surface even with Unfiltered. What was important for me to convey is how easy it is to gradually make the transition to Scala in an existing Java web application - you don't have to switch to SBT (Scala build system) and you can have Java and Scala Servlets and filters co-existing while each handles its own HTTP mappings.

So go ahead - pick a few methods in your web app and migrate them to Scala servlets or any Scala REST framework and share your experience in the comments - What libraries did you use? How smooth was the transition? What challenges did you encounter and how did you overcome them?

 

 

 

Thank you for your interest!

We will contact you as soon as possible.

Send us a message

Oops, something went wrong
Please try again or contact us by email at info@tikalk.com