Zach's Blog

Just another WordPress.com weblog

Posts Tagged ‘guice

Jersey + Guice + Scala

with 6 comments

At Pongr, our RESTful web services are built using Jersey, Guice and Scala (among many other technologies). Here’s a quick post that shows how to set up an example project that uses all three. By the end we’ll be able to declare Guice bindings in our own custom module and have them injected into Jersey resource classes.

We’ll manage everything with Maven, so first create your pom.xml. I know it looks like a lot, but only has three Jersey dependencies (and one on the Servlet 2.5 API to make things compile). The rest of this junk is mainly configuring plugins for Scala – don’t worry about it. The upshot is that you can a) run this all using mvn jetty:run, and b) can generate an Eclipse project using mvn eclipse:eclipse.

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.pongr</groupId>
    <artifactId>jerseyguicescala</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>
    <name>jerseyguicescala</name>
    <properties>
        <jersey-version>1.1.1-ea</jersey-version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>com.sun.jersey</groupId>
            <artifactId>jersey-server</artifactId>
            <version>${jersey-version}</version>
        </dependency>
        <dependency>
            <groupId>com.sun.jersey.contribs</groupId>
            <artifactId>jersey-guice</artifactId>
            <version>${jersey-version}</version>
        </dependency>
        <dependency>
            <groupId>com.sun.jersey.contribs</groupId>
            <artifactId>jersey-scala</artifactId>
            <version>${jersey-version}</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <version>2.5</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <!-- Run with "mvn jetty:run" -->
            <plugin>
                <groupId>org.mortbay.jetty</groupId>
                <artifactId>maven-jetty-plugin</artifactId>
                <version>6.1.19</version>
                <configuration>
                    <contextPath>/</contextPath>
                </configuration>
            </plugin>
            <!-- Begin scala plugins, inspired by: http://scala-tools.org/mvnsites/maven-scala-plugin/usage_java.html -->
            <plugin>
                <groupId>org.scala-tools</groupId>
                <artifactId>maven-scala-plugin</artifactId>
                <executions>
                    <execution>
                        <id>scala-compile-first</id>
                        <phase>process-resources</phase>
                        <goals>
                            <goal>add-source</goal>
                            <goal>compile</goal>
                        </goals>
                    </execution>
                    <execution>
                        <id>scala-test-compile</id>
                        <phase>process-test-resources</phase>
                        <goals>
                            <goal>testCompile</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.6</source>
                    <target>1.6</target>
                </configuration>
                <executions>
                    <execution>
                        <phase>compile</phase>
                        <goals>
                            <goal>compile</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <artifactId>maven-eclipse-plugin</artifactId>
                <configuration>
                    <sourceIncludes>
                        <sourceInclude>**/*.scala</sourceInclude>
                    </sourceIncludes>
                    <buildcommands>
                        <buildcommand>ch.epfl.lamp.sdt.core.scalabuilder</buildcommand>
                    </buildcommands>
                    <additionalProjectnatures>
                        <!-- This nature gets put after org.eclipse.jdt.core.javanature in .project so Eclipse has a J badge on the project instead of an S -->
                        <projectnature>ch.epfl.lamp.sdt.core.scalanature</projectnature>
                    </additionalProjectnatures>
                    <classpathContainers>
                        <classpathContainer>org.eclipse.jdt.launching.JRE_CONTAINER</classpathContainer>
                        <classpathContainer>ch.epfl.lamp.sdt.launching.SCALA_CONTAINER</classpathContainer>
                    </classpathContainers>
                </configuration>
            </plugin>
            <!-- http://groups.google.com/group/liftweb/browse_thread/thread/3dac7002f9e59546/3918bba2f7a92cd3?pli=1 -->
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>build-helper-maven-plugin</artifactId>
                <executions>
                    <execution>
                        <id>add-source</id>
                        <phase>generate-sources</phase>
                        <goals>
                            <goal>add-source</goal>
                        </goals>
                        <configuration>
                            <sources>
                                <source>src/main/scala</source>
                            </sources>
                        </configuration>
                    </execution>
                    <execution>
                        <id>add-test-source</id>
                        <phase>generate-sources</phase>
                        <goals>
                            <goal>add-test-source</goal>
                        </goals>
                        <configuration>
                            <sources>
                                <source>src/test/scala</source>
                            </sources>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
            <!-- End scala plugins -->
        </plugins>
    </build>
</project>

Next up, create the src/main/webapp/WEB-INF/web.xml file. This just registers our special GuiceConfig class that, uh, configures Guice.

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_5.xsd" metadata-complete="false" version="2.5">
    <listener>
        <listener-class>com.pongr.GuiceConfig</listener-class>
    </listener>
    <filter>
        <filter-name>guiceFilter</filter-name>
        <filter-class>com.google.inject.servlet.GuiceFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>guiceFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
</web-app>

We’ll create an example Guice module in the src/main/java/com/pongr/ExampleModule.java file. It just binds a message String that we’ll inject into our resource classes later.

package com.pongr;

import com.google.inject.*;
import com.google.inject.name.*;

public class ExampleModule extends AbstractModule
{
    @Override
    protected void configure()
    {
        bindConstant().annotatedWith(Names.named("message")).to("Hello, World!");
    }
}

Next up is src/main/java/com/pongr/GuiceConfig.java where we connect Jersey to Guice. This is where we create the Guice Injector using our ExampleModule and configure any Jersey properties, like the package(s) that contain our resource classes.

package com.pongr;

import java.util.*;

import com.google.inject.*;
import com.google.inject.servlet.*;
import com.sun.jersey.api.core.*;
import com.sun.jersey.guice.spi.container.servlet.*;

public class GuiceConfig extends GuiceServletContextListener
{
    @Override
    protected Injector getInjector()
    {
        final Map<String, String> params = new HashMap<String, String>();
        params.put(PackagesResourceConfig.PROPERTY_PACKAGES, "com.pongr");
        return Guice.createInjector(new ExampleModule(), new ServletModule()
        {
            @Override
            protected void configureServlets()
            {
                serve("/*").with(GuiceContainer.class, params);
            }
        });
    }
}

Now for the fun! This src/main/java/com/pongr/JavaResource.java file gets the message String injected and displays it.

package com.pongr;

import javax.ws.rs.*;
import javax.ws.rs.core.*;

import com.google.inject.*;
import com.google.inject.name.*;

@Path("java")
public class JavaResource
{
    private String message;

    @Inject
    public JavaResource(@Named("message") String message)
    {
        this.message = message;
    }

    @GET
    @Produces(MediaType.TEXT_PLAIN)
    public String get()
    {
        return "From Java: " + message;
    }
}

And for good measure here’s src/main/scala/com/pongr/ScalaResource.scala. Same as JavaResource, except in Scala. The Guice @Inject and @Named annotations can be a bit tricky for constructor injection, so here’s how it’s done.

package com.pongr

import javax.ws.rs._
import javax.ws.rs.core._

import com.google.inject._
import com.google.inject.name._

@Path("scala")
class ScalaResource @Inject() (@Named("message") message: String) {
  @GET
  @Produces(Array(MediaType.TEXT_PLAIN))
  def get(): String = "From Scala: " + message
}

That’s it! Now just run mvn jetty:run on your command line and hit http://localhost:8080/java and http://localhost:8080/scala in your browser to see these resources in action. As always, you can also visit http://localhost:8080/application.wadl to get an overview of the available resources. Enjoy!

Written by Zach Cox

September 22, 2009 at 10:03 pm

Posted in Java, Scala

Tagged with , , , ,

ActiveObjects + EasyMock + Guice

leave a comment »

In the last post we saw how using Guice for dependency injection and EasyMock for mock objects produces a well-designed system that is easy to unit test.  In this post I’ll describe how the ActiveObjects ORM fits in nicely with these other tools.

When using ActiveObjects, each database table is represented by a Java interface, called an entity.  Each column in the database corresponds to get/set methods in the interface.  Individual rows in the table correspond to instances of the interface.  For example, here is a very simple AO entity for a restaurants table:

import net.java.ao.*;

public interface Restaurant extends Entity
{
    public String getName();
    public void setName(String name);

    public String getAddress();
    public void setAddress(String address);

    public String getPhone();
    public void setPhone(String phone);

    public int getTableCount();
    public void setTableCount(int tableCount);
}

Since every entity is an interface, they are incredibly easy to mock.  We saw this in the last example, where the Restaurant object was mocked and then we specified an expectation for its getName() method:

public class ShareTest
{
    private Share share;
    private Twitter twitter;
    private Restaurant restaurant;
    private Credentials credentials;

    @Before
    public void setup()
    {
        twitter = createMock(Twitter.class);
        restaurant = createMock(Restaurant.class);
        credentials = new Credentials("username", "password");
        share = new Share(twitter, credentials);
    }

    @Test
    public void testShare()
    {
        expect(restaurant.getName()).andReturn("Mucho Burrito");
        twitter.update(credentials, "I loved eating at Mucho Burrito!");

        replay(restaurant, twitter);
        share.share(restaurant);
        verify(restaurant, twitter);
    }
}

In a strict definition of unit testing, you should not be accessing a database at all.  The code that you are testing should be completely isolated from everything around it.  By mocking the AO entities in our code, we do not have to deal with databases at all in our unit tests.  (Testing your code with a database is also a good idea though – for that I recommend DbUnit).

AO provides a class called EntityManager that you use to create new entities or query the database for existing entities.  While you can mock an EntityManager using the EasyMock Class Extension in your unit tests, I actually create an IEntityManager interface that duplicates EntityManager’s API, along with a few extra convenience methods.  Any class that needs to create or find entities gets an instance of IEntityManager injected to its constructor (via Guice, of course).  The unit tests for that class then just mock the IEntityManager and pass it into the constructor when creating the instance in the setup() method.

In our restaurant review site, we want to provide a way for users to add new restaurants to the system.  On the back-end we need to take the user’s input (from an HTML form submit) and create a new Restaurant entity.  Let’s assume we use the following class to create a new restaurant:

import com.google.inject.*;

public class CreateRestaurant
{
    private IEntityManager manager;

    @Inject
    public CreateRestaurant(IEntityManager manager)
    {
        this.manager = manager;
    }

    public void create(String name, String address, String phone, int tableCount) throws SQLException
    {
        Restaurant restaurant = manager.create(Restaurant.class);
        restaurant.setName(name);
        restaurant.setAddress(address);
        restaurant.setPhone(phone);
        restaurant.setTableCount(tableCount);
        restaurant.save();
    }
}

Unit testing this class is a simple matter of mocking IEntityManager and Restaurant entities and asserting that proper methods are called on them in the create() method:

import static org.junit.Assert.*;
import static org.easymock.EasyMock.*;
import java.sql.*;
import org.junit.*;

public class CreateRestaurantTest
{
    private IEntityManager manager;
    private Restaurant restaurant;
    private CreateRestaurant creator;

    @Before
    public void setUp() throws Exception
    {
        manager = createMock(IEntityManager.class);
        restaurant = createMock(Restaurant.class);
        creator = new CreateRestaurant(manager);
    }

    @Test
    public void testCreate() throws SQLException
    {
        String name = "Mucho Burrito";
        String address = "50 Mapleview Dr W Barrie, ON L4N 9H5";
        String phone = "(705) 739-6824";
        int tableCount = 15;

        expect(manager.create(Restaurant.class)).andReturn(restaurant);
        restaurant.setName(name);
        restaurant.setAddress(address);
        restaurant.setPhone(phone);
        restaurant.setTableCount(tableCount);
        restaurant.save();

        replay(manager, restaurant);
        assertSame(restaurant, creator.create(name, address, phone, tableCount));
        verify(manager, restaurant);
    }
}

Again, we exploited the fact that the CreateRestaurant class only uses instances of AO interfaces to make unit testing extremely simple & contained.

import static org.junit.Assert.*;
import static org.easymock.EasyMock.*;

import java.sql.*;

import org.junit.*;

import com.pongr.ao.*;

public class CreateRestaurantTest
{
private IEntityManager manager;
private Restaurant restaurant;
private CreateRestaurant creator;

@Before
public void setUp() throws Exception
{
manager = createMock(IEntityManager.class);
restaurant = createMock(Restaurant.class);
creator = new CreateRestaurant(manager);
}

@Test
public void testCreate() throws SQLException
{
String name = “Mucho Burrito”;
String address = “50 Mapleview Dr W Barrie, ON L4N 9H5″;
String phone = “(705) 739-6824″;
int tableCount = 15;
expect(manager.create(Restaurant.class)).andReturn(restaurant);
restaurant.setName(name);
restaurant.setAddress(address);
restaurant.setPhone(phone);
restaurant.setTableCount(tableCount);
restaurant.save();

replay(manager, restaurant);
assertSame(restaurant, creator.create(name, address, phone, tableCount));
verify(manager, restaurant);
}
}

Written by Zach Cox

June 8, 2009 at 11:28 am

Posted in Java

Tagged with , ,

Guice + EasyMock = Flexible Testable Code

leave a comment »

Dependency injection and mock object testing are great practices on their own.  When used together your code ends up being very flexible and testable.  In this article we’ll use Guice and EasyMock.

When you design your system to use DI you end up with lots of interfaces that provide specific services, concrete implementations of those interfaces, and classes that depend on those interfaces.  Let’s pretend we’re building a web app that lets users find restaurants in their area and write reviews for them.  One little feature we just added lets the user share their love for a particular restaurant on Twitter.  There are several Java libraries for the Twitter API but we want our code to be really simple and not depend on any specific library.  Thus we create the Twitter interface (and a concrete implementation that wraps one of those Twitter Java libraries):

public interface Twitter
{
    public void update(Credentials credentials, String status);
}

Next we create the class that does the sharing.  This would probably respond to some kind of AJAX call from the browser – the specifics don’t really matter here.  The important thing is that we’re using Guice to inject two dependencies into this class’s constructor: a Twitter object that wraps some Twitter Java library, and a Credentials object that stores the current user’s Twitter username and password or OAuth tokens.

public class Share
{
    private Twitter twitter;
    private Credentials credentials;

    @Inject
    public Share(Twitter twitter, Credentials credentials)
    {
        this.twitter = twitter;
        this.credentials = credentials;
    }

    public void share(Restaurant restaurant)
    {
        twitter.update(credentials, "I loved eating at " + restaurant.getName() + "!");
    }
}

To properly unit test this class we really don’t want to be making real HTTP requests to Twitter’s API and then use their API to assert that the user’s status was actually updated with the correct content (that would be more of an integration test).

Instead we should completely isolate this Share class from everything around it, control the inputs to it and assert that is performing the correct behavior.  This is where mock objects come in handy.

public class ShareTest
{
    private Share share;
    private Twitter twitter;
    private Restaurant restaurant;
    private Credentials credentials;

    @Before
    public void setup()
    {
        twitter = createMock(Twitter.class);
        restaurant = createMock(Restaurant.class);
        credentials = new Credentials("username", "password");
        share = new Share(twitter, credentials);
    }

    @Test
    public void testShare()
    {
        expect(restaurant.getName()).andReturn("Mucho Burrito");
        twitter.update(credentials, "I loved eating at Mucho Burrito!");

        replay(restaurant, twitter);
        share.share(restaurant);
        verify(restaurant, twitter);
    }
}

Because we followed proper DI principles and hid the Twitter Java library behind an interface, we can easily provide our own mock Twitter object and totally control it (so no HTTP requests are made).  We use EasyMock in the setup() method to create the mock Twitter object and give it to the new Share object.  Then in the testShare() method we specify the calls we expect on our mocks and call the share() method.

Just by using DI with interfaces and constructor injection, we made our Share class easy to test.  EasyMock then gave us a great way to create the mock objects that isolate the Share class from its dependencies and properly unit test it.

Written by Zach Cox

June 1, 2009 at 12:42 pm

Follow

Get every new post delivered to your Inbox.