javaspringrestjerseyspring-jersey

Jersey - resource variables null value despite non-null initialization


I have a resource in my Jersey REST api that has a private instance variable:

@Path("test")
public class TestResource implements ServletContextListener
{
    private String someString;

    @GET
    public void test()
    {
        System.out.println("someString " + someString);
    }

    @Override
    public void contextDestroyed(ServletContextEvent ctxt) {
        System.out.println("Destroying context");
    }

    @Override
    public void contextInitialized(ServletContextEvent ctxt) {
        System.out.println("TestResource initialized!");

        someString = "SET";
        System.out.println("someString has been set. someString: " + someString);
    }
}

On server startup/restart the instance variable someString is initialized during contextInitialized() and is correctly printed out. However when I set a GET request to http://localhost:8080/myapp/api/test (i.e. invoke the test() method above) the variable someString is null.

How can I prevent that?


Solution

  • From the JAX-RS specification:

    By default a new resource class instance is created for each request to that resource.

    So, any state you set on your resource class instance is meaningless, since the instance is never used again. If you want to persist a value, place it in the ServletContext’s attributes:

    // All classes in the web app share a ServletContext, so attribute names
    // need to start with package names to prevent collisions.
    private static final String SOME_ATTRIBUTE = TestResource.class.getName() + ".someAttribute";
    
    @Override
    public void contextInitialized(ServletContextEvent ctxt) {
        System.out.println("TestResource initialized!");
    
        String someString = "SET";
        System.out.println("someString has been set. someString: " + someString);
    
        ctxt.getServletContext().setAttribute(SOME_ATTRIBUTE, someString);
    }
    
    @GET
    public void test(@Context ServletContext context) {
        System.out.println("someString " + context.getAttribute(SOME_ATTRIBUTE));
    }
    

    Storing values in static fields will require you to implement thread safety and will not work in a distributed production environment.