views:

429

answers:

2

Rather new to REST and Jersey, and I'm trying out some basic examples. I've got one particular question though, which I haven't really found an answer for yet (don't really know how to look for this): how would you go about storing/defining common services so that they are stateful and accessible to all/some resources?

For instance, a logger instance (Log4J or whatever). Do I have to manually initialize this and store it in the HttpSession? Is there a "best practice" way of doing this so that my logger is accessible to all/some resources?

Thanks a lot.

+1  A: 

Speaking strictly about the Logger, are you sure you want it to be stateful? Most projects I've been on just grab one in whatever class needs it

Logger log = Logger.getLogger(this.getClass().getName());

Cut and paste that everywhere and let the logging magic begin!

To your original question regarding keeping state: Are you looking to keep something stateful per user (like a session) or some other state across the application (like a runtime configured logger)? Sessions can be managed with the HttpRequest and some ServletFilters. Grab the request in your JErsey code like so

@Path("/awesome")
public class AwesomeService {

    @GET
    @Produces("text/awesome")
    public String getAwesome(@Context HttpServletRequest req) {   
        HttpSession session= req.getSession(true);
        //brilliance
    }
}

Application resources, like an entity manager or a konfabulator can be initialized statically and used as Singletons or with Factories.

class EntityManager { 
EntityManager manager;
public static EntityManager getManager() {
        if(manager == null) {
            manager = initManager();
        }
        return manager;
    }
}
gmoore
Excellent point about the logger. I'm so used to defining loggers as singletons that I forgot they do not have to be singletons, each resource can simply define its own.
pHk
+1  A: 

Your best option is to inject the services into the Resource using something like Spring. Adding a setter in your Resource for the particular service makes it available for various scopes. The following tutorial explains in detail how to use Spring and Jersey. Below are examples of the various pieces needed to make this work. Specifically answering your question however the "best practice" is to allow Spring to manage the "stateful"ness or "scope" of a particular service.

Simple Service Bean

public class SimpleBean {
    private int counter;
    public String sayHello() {  
        return Integer.toString(counter++);
    }  
}

Simple JAX-RS Resource

public class HelloWorldResource {

    private SimpleBean simpleBean;

    public void setSimpleBean(SimpleBean simpleBean) {
        this.simpleBean = simpleBean;
    }

    @GET @Path("/Hello") @Produces(MediaType.APPLICATION_JSON)
    public String sayHello() {
        return "{\"Hello\": \"" + this.simpleBean.sayHello() + "\"}";
    }
}

Simple Spring applicationContext.xml, notice the "scope" for the Bean and Resource. This defines how stateful these objects are.

<bean id="simpleBean" scope="prototype" class="myhealth.spring.SimpleBean"/>

<bean id="helloWorldResource" scope="singleton" class="myhealth.ajax.HelloWorldResource">
    <property name="simpleBean">
        <ref bean="simpleBean"/>
    </property>
</bean>
Alex Winston