javaservletsjerseyjax-rsobject-sharing

Injecting objects into servlet classes with JAX-RS


I am pretty new to this whole servlet thing, so please correct me if I mix or use incorrect/confusing terms for things. I am however writing a blog ping server in Java using JAX-RS (Jersey), and I'm facing a problem where I have one servlet class that accepts REST input, and another servlet class that lists the same content.

Right now they are sharing their objects through a class that looks like this:

public class BlogPingUtils {

    private static final String LIST_OF_CHANGES = "listOfChanges";

    public static List<PingInfo> getListOfChanges(ServletContext context) {
        List<PingInfo> listOfChanges = (List<PingInfo>)context.getAttribute(LIST_OF_CHANGES);
        if(listOfChanges == null) listOfChanges = new ArrayList<PingInfo>();

        return listOfChanges;
    }

    public static void setListOfChanges(ServletContext context, List<PingInfo> listOfChanges) {
        context.setAttribute(LIST_OF_CHANGES, listOfChanges);
    }
}

This works in a small-scale development environment, but it feels dirty and probably wouldn't work in a heavy-duty production environment because of concurrency issues and such. Also it's not very flexible. What I would like to do is have an interface that would have methods for reading and writing data. Then I would inject an object of a class that implements this interface into these two servlets, so that they are actually using the same object for interacting with the data. This would then be backed by a synchronized list or database transactions or something.

What would be the preferred way to do this? Is it possible? My web.xml is very simple right now and looks like this:

<?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_4.xsd" version="2.4">
  <display-name>Blog Ping</display-name>

  <servlet>
    <servlet-name>Jersey REST Service</servlet-name>
    <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>

    <init-param>
        <param-name>com.sun.jersey.config.property.packages</param-name>
        <param-value>com.vrutberg.blogping</param-value>
    </init-param>

    <load-on-startup>1</load-on-startup>
  </servlet>

  <servlet-mapping>
    <servlet-name>Jersey REST Service</servlet-name>
    <url-pattern>/*</url-pattern>
  </servlet-mapping>
</web-app>

Solution

  • Rather than a static class, I would design an Interface with your getters and setters, than create an implementation class.

    I would then register the singleton (or pool depending on your needs) implementation class with a thread-safe central repository visible by both servlets, such as JNDI.

    The servlets query the central repository and 'cast' to the interface.