Pages

Tuesday, August 24, 2010

RESTEasy. rest, easy.

I've spent some days figuring out how does RESTEasy initializes itself. The goal, which came actually from a support case, was to hook into the framework and make it possible to add new resources with @Path annotation without re-deploying the application itself.

It turned out that as RESTEasy has 3 main options for bootstrapping: servlet (which actually has a plenty of configuration switches), listener, and filter. This is quite important as RESTEasy initializes itself a little bit differently depending on what kind of configuration is provided.

I've managed to patch the internals of RESTEasy in a way, so that in case of "servlet" bootstrapping, when adding a new resource to the application, the new context path appeared instantly, without re-deploying the application.

For a demo, I used the 'jaxb-json' example that is bundled with RESTEasy distribution. By default, the example uses listener bootstrapping configuration, thus web.xml has to be modified a little bit to use 'servlet' configuration instead:

<?xml version="1.0"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
    "http://java.sun.com/dtd/web-app_2_3.dtd">

<web-app>
  <display-name>Archetype Created Web Application</display-name>

  <context-param>
    <param-name>resteasy.servlet.mapping.prefix</param-name>
    <param-value>/resteasy</param-value>
  </context-param>

  <servlet>
    <servlet-name>Resteasy</servlet-name>
    <servlet-class>
      org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher
    </servlet-class>
    <init-param>
      <param-name>javax.ws.rs.Application>
      <param-value>org.jboss.resteasy.examples.service.LibraryApplication</param-value>
    </init-param>
  </servlet>

  <servlet-mapping>
    <servlet-name>Resteasy</servlet-name>
    <url-pattern>/resteasy/*</url-pattern>
  </servlet-mapping>

</web-app>

Next, run the application, and see that localhost:8080/resteasy/library/books/badger responds as intended for the given example.  Now, if we use JRebel to make the class re-loading possible, and patch some classes of RESTEasy framework, one will be able to add new methods to the resource class without having to re-deploy the application. Say, I've added a new method to the class, and marked it with the @Path annotation:

@Path("library")
public class Library {
   @GET
   @Path("books/test")
   @Produces("text/html")
   public String getTest() throws Exception {
      return "my test";
   }
}

So now I could go to localhost:8080/resteasy/library/books/test and see the changes instantly! Hopefully we can add this feature to support all kinds of RESTEasy configurations. The feature will be available quite soon in one of the upcoming JRebel nightly builds.

No comments:

Disqus for Code Impossible