I've fiddled with my blog template because I decided I wanted more horizontal viewing space, given that it was using less than a third of my 1920 horizontal pixels. If it feels too spread out for you, I added a drag-and-drop handle over to the left to let you resize the main content column. The javascript is pretty primitive. If it breaks, drop me a comment.
>
>
>
>

Monday, November 28, 2011

What is JSR 348 (JCP.next)?

I was thinking about how to keep track of the articles I read and things I take time to learn about, like JSR 348, and I realized I should just stick it on my blog. That's kinda why it's here. So here we go: JSR 348 is nicknamed JCP.next because it revises the Java Community Process, which dictates how revisions to the Java platform are made. The final release was 18 October 2011, which means that every new JSR after that date is required to conform to the new requirements of JCP 2.8 (the new revision).

Generally, JSR 348 is focused on making sure in-progress JSRs are more transparent, are easier for anybody to get involved with, and keep moving at a reasonable pace so they don't stall out unfinished, like many have in the past. Just some of the measures include requiring that communication take place in a public forum, widening the pool of people who can be involved in JSRs to include just about anybody, and providing for removing uncooperative or unproductive (or just plain missing) members from the Expert Group of a JSR as well as replacing the Spec Lead if necessary. The Executive Committee was itself the Expert Group for JSR 348, and while working on the JSR, they followed all the guidelines that they themselves were putting into the new version of the JSR. Comments from the EC seem to indicate they felt it was a very positive experience.

Overall, it seems like an attempt initiated by Oracle to overcome some of the criticism after their takeover of Java from Sun and the fears that Java would become more closed and tightly owned by Oracle and possibly stagnate. From what I've seen while browsing around, there's a lot of hope that JSR 348 will be a success on those fronts. It only took a handful of months to complete and puts some pretty aggressive measures in place that look like they'll keep things open and moving along at a good pace. More importantly, it's gaining quite a lot of acceptance in the community, and it seems like people are breathing a sigh of relief at seeing Java looking like it's ready to come out of the quagmire it seemed to be in. Maybe the major releases will come along more often now and we can look forward to regular infusions of new language improvements?

A couple of the articles I read that are fairly short but give a good overview of the JSR:
The JCP Program Moves Towards a New Version: JCP.next
JCP 2.8 Ushers in a New Era of Complete Transparency

Wednesday, April 20, 2011

Effective Testing of a Jersey Resource Class

For a while now, I've been using Jersey for ReSTful web services with the resources classes and dependencies managed by Spring. I'm pretty avid about TDD, and a tricky question has been how to effectively test the JAX-RS resource classes. This post will take you on a brief journey through my evolving answer to this question. We'll examine the problems and considerations involved in testing as I describe several iterations of my testing approach, ending with my current approach, which I feel is very effective. Depending on your needs, you may find one of the earlier versions to be quite satisfactory.

Iteration One: The Jersey Test Framework

Just starting off, you're faced with the question of whether to just do pure unit tests of the resource classes or whether you should find a way to deploy them to a Jersey container so you can test the ReSTfulness of your resources. If you're choosing the former, then you probably wouldn't even be reading this post. If, on the other hand, you'd like to deploy your JAX-RS resource classes into Jersey and test the ReST calls thus created, then a quick search including the terms "test" and "Jersey" should point you toward the "Jersey Test Framework". I'm not going to cover that in this post, as it's fairly straightforward to set up and I know there are some other blogs out there that talk about it. Suffice it to say that the JerseyTest class from the framework lets you very easily start up a Grizzly container running your Jersey application that is very accessible to tests. Since I use Spring with Jersey, all I really have to do is pass in my existing Spring context files to load, and my Jersey app is running and ready to test. This is iteration one: your Jersey app deployed for testing just as it might be in production.

The first thing you'll notice when following this approach is that your test suite will quickly drag to a crawl. Especially as your app grows in complexity and number of tests, it will start taking longer to start up, and starting it up fresh for every single test method (the behavior of JerseyTest) is just out of the question. This led me to question of how often it's acceptable to start (or restart) the test container. It was the doorway leading to iteration two.

Iteration Two: Customizing the JerseyTest

On the matter of where and when to start a test container, once per test is far too often. Once per test suite is a little inflexible and would require some extra test code outside of the typical test class, which is all that I ever write. So I eventually decided that starting it once per test class wasn't too bad. You probably won't/shouldn't have a huge number of JAX-RS resource classes in one module/project anyway, and it's not likely you'd write more than one test class per resource; therefore, the number of startups needed to test a module will be kept fairly low. Additionally, it gives you the flexibility to configure the Jersey container specifically for each test class. Getting to this point just requires a little bit of extra test support code. That's the meat of iteration two: writing your own test support class to take control of the starting of the Jersey container. This class will ensure that the app is only started once and maintain the WebResource that's created by the JerseyTest to hand out to tests as needed. This is a fairly simple exercise that's left up to the reader, as there are far more interesting things to come.

As your project's complexity continues to grow, you'll begin to wonder about the wisdom of deploying your full application stack to the Jersey test container, and rightly so. First, it continues to slow down your tests by adding to startup time. More importantly, it can no longer be called anything like a unit test because in order to test your ReST calls, you'll need intimate knowledge of all that goes on under them, such as what constitutes valid input, possibly database constraints, and other preconditions that have to be satisfied in order for your ReST call to succeed. In short, your tests will become bloated, unreadable, and meaningless. Third, and possibly most insidious, if you're following your code metrics, a test of this type will give you all kinds of bogus test coverage. While you're only intending to test the JAX-RS resource class, it's going to be touching lines of code all through your codebase and contributing to code coverage without really asserting anything about those lines. It can give a real false sense of security. This brings us to iteration three, and the really interesting part of this post.

Iteration Three: Sneaking in a Mock

What can you do to test your JAX-RS resource deployed into Jersey without testing all the stuff that's normally under it in a real deployment? That sounds like a job for mocks! But wait! Our application is deployed inside a servlet container that's running in our tests, and there's no way to get access to stuff "inside" it. Specifically, since I just pass in a list of Spring XML files and Jersey starts the ApplicationContext itself, how can I inject a mock into the context? Its lifecycle is completely out of my hands. It's hidden away inside Jersey in the Grizzly container. Believe me. I dug around the source code for a few hours, and there's no easy way to get the Spring ApplicationContext out of there. So it's time to get a little inventive. First, let's make up some brief sample code. Suppose you have a resource class like this:

    @Path("/foo")
    class FooResource {
        @Autowired
        private FooService service;

        @GET
        @Path("{id}")
        @Produces(MediaType.APPLICATION_JSON)
        public Foo getFoo(@PathParam("id") int id) {
            return service.getFoo(id);
        }
    }

It depends on a service with this interface:

    interface FooService {
        Foo getFoo(int id);
    }

The question is how to get a mock of FooService that's available to your test wired into the FooResource bean, which is out of your test's control. There are certainly a number of possibilities out there, but I strive for simplicity. Here is the (first) simplest thing I could come up with:

    class FooTestService implements FooService {
        private static FooService delegate;

        public static void setDelegate(FooService delegate) {
            FooTestService.delegate = delegate;
        }

        @Override
        public Foo getFoo(int id) {
            if (delegate != null) {
                return delegate.getFoo(id);
            }
            return null;
        }
    }

This is a class that lives with your tests. It implements, and therefore is-a, FooService. (Note that TestFooService, while more readable, is a BAD name for it, as the Maven surefire plugin assumes that any class beginning or ending with "Test" is a test class and will fail the build because of your "test class" without any test methods in it!) Since it's a FooService, it's eligible for wiring into a FooResource. It has a static field and setter, meaning that no matter where an instance of this thing is created, as long as we're in the same JVM (ClassLoader, really), we can inject a value as the "delegate", making it available to all instances of the class, wherever they may be. The delegate receives all calls made to any instance of this class. The if statement is there to provide some flexibility in use: you don't have to provide a delegate if you don't want/need to. By creating a test-specific Spring context file for our test, we gain the ability to inject a mock into a Spring context that is otherwise out of our control:

    <!-- file FooResourceTest-context.xml -->
    <beans>
        <context:annotation-config/>
        <bean class="com.foo.FooResource"/>
        <bean class="com.foo.FooTestService"/>
    </beans>

With this, our test can now do something like:

    class FooResourceTest {
        private FooService fooService;

        @Before
        public void setUp() {
            // start the Grizzly container with our test-specific context file
            ensureGrizzlyIsRunning("/FooResourceTest-context.xml");
            // create a mock of the FooService
            fooService = mock(FooService.class);
            // inject the mock
            FooTestService.setDelegate(fooService);
        }

        @Test
            ...
        }
    }

...and voila! We're now testing the FooResource in isolation. We can test indirect outputs, such as verifying that it calls the appropriate service method(s) at the appropriate time(s). We can provide indirect inputs by making our service mock return different Foo objects or throw exceptions. We've taken care of the three issues I mentioned in iteration two: your tests have minimal startup costs, they're very narrow in scope, and they don't create a bunch of test coverage out of thin air.

Everything will be fine with this approach for a while, but then you'll find that it's so useful that these *TestService classes are springing up everywhere. You might even have multiple copies of them to serve different modules. I had three separate copies of a particular one in my project. For the benefit these things give you, the cost is really quite small. It takes a bit of effort to write the first time, but there's hardly anything to them, and they virtually maintain themselves since adding an interface method immediately requires you to add the method to your *TestService classes. Still, when you get to where you have about 20 of them, many of which are duplicates, you'll become convinced that there is a definite pattern here that needs to be pulled out of the crowd. It took a couple of weeks sitting in the back of my mind to bring all the pieces together, but I finally arrived at iteration four, which so far looks like the end of the line for this particular puzzle.

Iteration Four: Generate Mock Containers Dynamically

For the final, long-term solution to this problem, I was looking for a single, simple class that could provide the functionality of all of these *TestServices that were floating around. I knew it would involve some kind of dynamic proxying or similar magic. I thought I might use something from Spring to help out. Finally, in a moment of clarity, it all came together, and it looked a bit like this (the code isn't in front of me right now, and I'm not checking this with a compiler, much less running it):

    class DelegatingProxyFactoryBean implements FactoryBean {
        private static Map<Class, Object> proxiesByType = new HashMap<Class, Object>();
        private Class proxyInterface;

        public void setProxyInterface(Class proxyInterface) {
            this.proxyInterface = proxyInterface;
        }

        public static void addProxy(Class proxyInterface, Object delegate) {
            Object proxy = Proxy.newProxyInstance(
            DelegatingProxyFactoryBean.class.getClassLoader(),
            new Class[] { proxyInterface },
            new DelegatingInvocationHandler(delegate));
            proxiesByType.put(proxyInterface, proxy);
        }

        @Override
        public Object getObject() {
            return proxiesByType.get(proxyInterface);
        }

        @Override
        public Class<?> getObjectType() {
            return proxyInterface;
        }

        @Override
        public boolean isSingleton() {
            return true;
        }

        static class DelegatingInvocationHandler implements InvocationHandler {
            private Object delegate;

            public DelegatingInvocationHandler(Object delegate) {
                this.delegate = delegate;
            }

            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                try {
                    return method.invoke(delegate, args);
                } catch (InvocationTargetException e) {
                    throw e.getCause();
                }
            }
        }
    }

It's a fairly simple class, but it has some voodoo in it. Overall, it's just a FactoryBean. The layer of indirection provided by the factory pattern is just what we need so that we can configure one bean in a Spring context to be any type. The class combines static and non-static code in the same way the former FooTestService did to allow us to smuggle mock objects into a Spring context. Ultimately, the mocks become the output of the getObject() method, so they become beans in a Spring context that can be wired into other beans, just like we did in iteration 3.

The only code here that could be considered notable is in the addProxy() and invoke() methods. The addProxy method is analogous to the setDelegate() method of iteration 3. It's how we tell this thing about a mock that we want it to use and the interface for that mock--FooService in our previous example. When we give it the interface and mock, it creates a dynamic proxy based on the interface and stores the proxy away to be returned by the getObject() method later. The DelegatingInvocationHandler is what delegates method calls on the proxy to the mock. In iteration 3, we implemented all the interface methods ourselves, filling in the delegation code manually. Here, the invocation handler receives a method invocation and then turns around to invoke the same method on the mock object it was constructed with: no more code to write or maintain! The invoke method in the handler looks a little fishy because it catches and unwraps an exception. You might get a violation out of this if you run static analysis tools on it (throwing away a stacktrace). The reason is that when you invoke a method using reflection, if the invoked method throws an exception, it's wrapped in an InvocationTargetException. Since we want our proxies to behave exactly like the objects they're delegating to, we'll need to strip the outer InvocationTargetException from any exception being thrown. Here's what this thing looks like in use:

    <!-- file FooResourceTest-context.xml -->
    <beans>
        <context:annotation-config/>
        <bean class="com.foo.FooResource"/>
        <bean class="com.foo.DelegatingProxyFactoryBean">
            <property name="proxyInterface" value="com.foo.FooService"/>
        </bean>
    </beans>

    class FooResourceTest {
        private FooService fooService;

        @Before
        public void setUp() {
            // create a mock of the FooService
            fooService = mock(FooService.class);
            // inject the mock
            DelegatingProxyFactoryBean.addProxy(FooService.class, fooService);
            // start the Grizzly container with our test-specific context file
            ensureGrizzlyIsRunning("/FooResourceTest-context.xml");
        }

        @Test
            ...
        }
    }

The changes here from iteration three are trivial: in the context file, we add our FactoryBean and tell it to spit out a FooService. In the test, we do exactly the same steps as before, but in a different order. The FactoryBean as written requires that the proxies be added before the Spring context starts.

Now, you might have noticed that the dynamic proxies aren't strictly necessary here. They're just a reflection of what we wrote manually in iteration 3. You could remove that bit and just have the factory bean return the mocks directly; however, with a bit more effort, you can easily make the mocks optional and, at the same time, remove the requirement of setting the mocks before starting Spring. As written above, getObject() will return null if no proxy has been added for the type set on the FactoryBean instance, and that's not very friendly. Just add some code there to create a proxy that has no delegate, and modify the invocation handler to return some default values if there's no delegate to invoke. Now it can generate test proxies with some basic behavior without needing a mock. Then alter addProxy() to inject mocks into existing invocation handlers instead of always creating new ones. Problems solved.

That's the end of the road. This DelegatingProxyFactoryBean--with the enhancements just discussed--allowed me to remove around 20 test classes of the iteration three variety. Furthermore, you'll notice that there are no references at all to "test" or "mock" in that class. It's generic enough that it could perhaps find its way into other use cases.

One final caveat: as I mentioned at least a couple of times, I haven't tested any of this code. I wrote it all in notepad++ with a couple of references to some javadocs. If you find problems, let me know, and I'll update this post.