Showing posts with label Java. Show all posts
Showing posts with label Java. Show all posts

Tuesday, July 3, 2012

Jersey Unit Testing with Guice and EasyMock

This post will expand on my earlier postings on Guice integration in Jersey here
and here. Jersey has a little known but powerful in-memory test framework. Using
an in-memory test container along with Guice allows you to unit test resource
lookup without the expense of full HTTP protocol handling. This post shows you
how.

First, a sample software stack in Maven POM:
   <properties>
       <guice.version>3.0</guice.version>
       <jersey.version>1.12</jersey.version>
       <easymock.version>3.1</easymock.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.google.inject.extensions</groupId>
      <artifactId>guice-assistedinject</artifactId>
      <version>${guice.version}</version>
   </dependency>      
    <dependency>
        <groupId>com.sun.jersey.jersey-test-framework</groupId>
        <artifactId>jersey-test-framework-inmemory</artifactId>
        <version>${jersey.version}</version>
        <scope>test</scope>
    </dependency>
   <dependency>
       <groupId>org.easymock</groupId>
       <artifactId>easymock</artifactId>
       <version>${easymock.version}</version>
       <scope>test</scope>
   </dependency>  
  </dependencies>  

We will now work through unit-testing a sub-resource locator example from my
last post. The resource classes are reproduced here for convinence:
// In BarResource.java file
class BarResource {
   @GET Response get();
}
 
// In FooResource.java file
import com.google.inject.Provider;
@Path("/foo")
class FooResource {
   private final Provider barProvider;
 
   @Inject 
   FooResource(final Provider barProvider) {
      this.barProvider = barProvider;
   }
   
   @Path("bar") 
  @Produces(MediaType.APPLICATION_JSON)
   public Response getBar() {
      // Client request /bar will will be redirected
      //to BarResource
      BarResource bar = barProvider.get();
      bar.get();
   }
}
Our goal is to mock the sub-resource BarResource so we can uni-test resource lookup in FooResource without launching a full-scale HTTP client and server. How do we do this? The trick lies in Jerey's InMemoryTestContainerFactory. Unfortunately, it is not obvious that you can provide your own IoC container with this Factory. You only need to make one line change in the start() method.

Change:

webApp.initiate(resourceConfig);
To:
webApp.initiate(resourceConfig, new GuiceComponentProviderFactory(resourceConfig, injector));
We would have preferred InMemoryTestContainerFactory to be made extensible so we can just pass-in our injector. But we make do for now by creating our own GuiceInMmoryTestContainerFactory class based on the InMemoryTestContainerFactory code with this one line change. I will only show a skeleton implementation here to save space:
public final class GuiceInMemoryTestContainerFactory implements
        TestContainerFactory {

    private final Injector injector;

    public GuiceInMemoryTestContainerFactory(final Injector injector) {
        this.injector = injector;
    }

    @Override
    public Class<LowLevelAppDescriptor> supports() {
        return LowLevelAppDescriptor.class;
    }

    @Override
    public TestContainer create(final URI baseUri, final AppDescriptor ad){
        if (!(ad instanceof LowLevelAppDescriptor)) {
            throw new IllegalArgumentException(
                    "The application descriptor must be an instance of LowLevelAppDescriptor");
        }

        return new GuiceInMemoryTestContainer(baseUri, (LowLevelAppDescriptor) ad, injector);
        
    }

    /**
     * The class defines methods for starting/stopping an in-memory test container,
     * and for running tests on the container.
     */
    private static final class GuiceInMemoryTestContainer implements TestContainer {

        // Copy other fields from InMemoryTestContainer here.
        
        final Injector injector;

        /**
         * Creates an instance of {@link InMemoryTestContainer}
         * @param baseUri URI of the application
         * @param ad instance of {@link LowLevelAppDescriptor}
         */
        private GuiceInMemoryTestContainer(final URI baseUri, final LowLevelAppDescriptor ad, 
                final Injector injector) {
            // Copy other statements from InMemoryTestContainer here
            this.injector = injector;
        }

        // Copy other methods from InMemoryTestContainer here

        @Override public void start() {
            if (!webApp.isInitiated()) {
                LOGGER.info("Starting low level InMemory test container");

                webApp.initiate(resourceConfig, 
                                new GuiceComponentProviderFactory(resourceConfig, injector));
            }
        }
    }
}    
Now we use Jersey's test framework JerseyTest to write our unit test for FooResource.
The key elements are:
  1. Statically initialize a Guice injector;
  2. Use GuiceInMemoryTestContainer to initilize the test framework;
  3. Use JerseyServletModule to mock up dependencies.
Here is the code:
public class FooResourceTest extends JerseyTest {
    private static Injector injector;
    @BeforeClass public static void init() {
        injector = Guice.createInjector(new MockServletModule());
    }
    
    public FooResourceTest() {
        super(new GuiceInMemoryTestContainerFactory(injector));
    }
    
    @Test public void testGetBar() {
        BarResource barMock = injector.getInstance(BarResource.class);
        barMock.get();
        EasyMock.expectLastCall().andStubReturn(createMock(Response.class));
        EasyMock.replay(barMock);
        
        WebResource wr = resource();
        ClientResponse r = wr.path("/foo/bar").get(ClientResponse.class);
        assertNotNull(r.getStatus());
        
        EasyMock.verify(barMock);
    }
    

    private static class MockServletModule extends JerseyServletModule {
        @Override protected void configureServlets() {
            bind(FooResource.class);
        }
        
        @Provides BarResource providesBarResource() {
            BarResource barMock = createMock(BarResource.class);
            return barMock;
        }
    }
    
}
Run this test and you will be on your way to test restful interactions in a
Guice-enabled POJO fashion.

Thursday, November 3, 2011

Rules for Configuring ThreadPoolExecutor Pool Size

I came across a blog Rules of ThreadPoolExecutor Pool Size. In that blog, the author explained reasonably well how TPE creates new threads in relation to thread pool size. But the author incorrectly stated that the TPE would always fill a task queue first before creating a new thread. Thread creation is determined by queuing strategy. Choosing a direct handoff strategy will achieve the author's "user anticipated way". But there is risk in that particular way. Here is a table listing the general pros and cons of each queuing strategy:


Queuing Strategy
Example
Design Trade-off
Worst Case
Usage
Direct Handoff
SynchronousQueue
Zero task queue but can create unlimited number of threads.
OutOfMemory
For tasks that may have interdependency. For example, task i changes a global state that affects the execution of task j.
Unbounded Queue
LinkedBlokingQueue
Limit the number of threads by the max pool size but allows submission of unlimited tasks.
OutOfMemory
For tasks that are completely independent of each other.
BoundedQueue
ArrayBlockingQueue
Limit both the number of threads and the queue size.
Low throughput from imbalanced pool and queue sizes.
For burning midnight oil.



Thursday, October 20, 2011

Log4J Appender Additivity in Plain English

Let's start with the root logger in a Log4j.properties file:

log4j.rootLogger=INFO,stdout

This root logger is configured to have a logging level INFO with an appender named stdout. Now we want to turn debug on in our own package but keep the rest at the INFO level. So we add this to our Log4j.properties file:

log4j.category.com.mypackage.name=DEBUG
log4j.rootLogger=INFO,stdout

Everything looks good. But then we want to pipe our debug log to a different appender so we change the configuration to:

log4j.category.com.mypackage.name=DEBUG, myappender
log4j.rootLogger=INFO,stdout

When we start our app, we suddently notice that our debug logs still show up in stdout in addition to myappender! This is caused by appender additivity. To turn it off, change the additivity flag to false:

log4j.category.com.mypackage.name=DEBUG, myappender
log4j.additivity.com.mypackage.name=false
log4j.rootLogger=INFO,stdout

Thursday, May 5, 2011

Singleton Injection in JAX-RS

JAX-RS defines a Java API for implementing RESTful server-side functions in Java. Being a post-Spring framework, it uses annotations extensively to denotate "resource" injection points. One of these DI annotations is called Provider. A provider is an application supplied class used to extend a JAX-RS run-time such as Jersey. A JAX-RS implementation is required to load only one instance of a provider class in a JAX-RS run-time instance. An application developer can leverage this feature to inject singletons, e.g. a database manager class, into JAX-RS resources. Here is an example on how to do this.

First, define the singleton class.
public class MyDBManager{
   public void store(final String key, final String value) {
      // Store the key-value pair in a DB.
   }
}
As you can see, this class is just a POJO. No special singleton marking anywhere in the class definition.

Next, we will use ContextResolver and @Provider annotatoin to turn MyDBManager into a JAX-RS provider.
import javax.ws.rs.ext.ContextResolver;
import javax.ws.rs.ext.Provider;

@Provider
public class DBResolver implements ContextResolver<MyDBManager> {
   private MyDBManager db;
   
   // A provider must have at least a zero-arg constructor.
   public DBResolver() {
      db = new MyDBManager();
   }
   public MyDBManager getContext(Class type) {
      return db;
   }
}

Now we can inject MyDBManager into a resource class through @Context like this:
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.ext.ContextResolver;

@Path("/myresrc")
public class MyResource {
   @POST
   @Path("/{id}")
   @Consumes("text/plain")
   @Produces("text/plain")
   public String post(final @Context ContextResolver myDbManager,
                      final @PathParam("id") String id) {
      myDbManager.getContext(MyResource.class).store(id, "someValue");
      return "OK";
   }
}

Two observations from this method of injecting a singleton:
  • The singleton instance of DBManager is not instantiated until MyResource is invoked the first time.
  • The type T in ContextResolver<T> can be an interface so an implementation of the ContextResolver<T> can return an implementation of the T. But, the implementation of T can only be determined by a Class object.
Therefore, this @Provider-based injection method should not be taken as a general purpose DI mechanism because JAX-RS is not a general purpose DI framework. It is not only ugly but also comes with a reflection overhead when the resource is invoked. Using Guice or Spring instead for general purpose DI.

Tuesday, February 22, 2011

Tips in Using Gcore Dump with Java Tools

When analyzing gcore dump from a running JVM process, it is very important to know which Java binary used by gcore to generate the core dump. This is because gcore may not use the Java binary on user's path. If they are different, the user will not be able to attach to the core file to the Java tool in the path. Knowing this will save you hours of frantic head scratching. More information can be found on this discussion about using gcore with jmap.

Another issue is the core file size. A 32-bit Java tool will have problem attaching to a core dump greater than 2GB in size. A workaround is to generate the gcore on a 64-bit JVM and then use the 64-bit Java tool to load the core file.

Wednesday, February 2, 2011

Socket and DataInputStream

While Java provides great I/O abstraction facilities like InputStream and OutputStream, the non-blocking nature of Java NIO often leads to subtle behavior differences in high-level network programming constructs.  The case in point is DataInputStream, which enables an application to parse Java primitive types right out of an input stream.  However, the stream reading methods in the DataInputStream class exhibit two distinct behaviors when the underline stream is a socket.  The following methods are non-blocking:

read(byte[] b)
read(byte[] b, int off, int len)

A non-blocking read means that the first read(byte[] b, int off, int len)may not return the expected len number of bytes.  Therefore, the reader program is usually put into a loop to read repeatedly until the len of bytes are read or the EOF is reached.

The primitive type reading methods in DataInputStream are blocking.  Take readInt() as an example.  That read will block if there are not enough bytes, 4 in this case, in the stream.

Consistency is a good software engineering principle to practice.  When using DataInputStream to parse a socket input stream, it is best to always use the primitive type reading methods to avoid confusion of blocking vs non-blocking socket I/O.

Wednesday, September 8, 2010

Programmatically Disabling Java SSL Certificate Check for Testing

Continuous integration testing with Java SSL code is prone to certificate mismatch problems. Sometimes valuable development time can be saved by disabling just the certificate verification logic in the SSL client while preserving all other security logics. This technique is particularly useful for testing with a self-signed certificate because it eliminates the need to install the certificate on every client machine or device that needs to communicate with the SSL server. It is perfectly safe in a well-controlled development environment.

First, we create stub implementations of HostnameVerifier and X509TrustManager.
public static class NullVerifier implements HostnameVerifier {
      @Override
      public final boolean verify(final String hostname,
                                  final SSLSession sslSession) {
         return true;
      }

   }
   
   public static class NullTrustManager implements X509TrustManager {
      @Override
      public void checkClientTrusted(final X509Certificate[] chain, 
                                     final String authType) 
         throws CertificateException {
      }

      @Override
      public void checkServerTrusted(final X509Certificate[] chain, 
                                     final String authType) 
         throws CertificateException {
      }

      @Override
      public final X509Certificate[] getAcceptedIssuers() {
         return new X509Certificate[] {};
      }

Then, we install our stub implementations to the SSL connection.
      // Configure SSL Context
      SSLContext sslContext = SSLContext.getInstance("TLS");
      X509TrustManager nullTrustManager = new NullTrustManager();
      TrustManager[] nullTrustManagers = {nullTrustManager};
      sslContext.init(null, nullTrustManagers, new SecureRandom());

      // Create HTTPS connection
      URL url = new URL("https", "127.0.0.1", 8443, "/ssltest");
      HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
      conn.setHostnameVerifier(new NullVerifier());
      conn.setSSLSocketFactory(sslContext.getSocketFactory());