1

I am deploying a JAX-RS application to JBoss EAP 6.2. I am trying to obtain a ServletContext from inside of a JAX-RS resource class so that I can read some context-param values that I have set in the WEB-INF/web.xml file. I.e., after I've gotten hold of the ServletContext I was planning to call ServletContext#getInitParam to get the value. I am using injection to get the ServletContext as advised here.

The relevant portion of my web.xml is:

<servlet>
    <servlet-name>resteasy-servlet</servlet-name>
    <servlet-class>
        org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher
    </servlet-class>
    <init-param>
        <param-name>javax.ws.rs.Application</param-name>
        <param-value>foo.MyApplication</param-value>
    </init-param>
</servlet>
<servlet-mapping>
    <servlet-name>resteasy-servlet</servlet-name>
    <url-pattern>/jax-rs/*</url-pattern>
</servlet-mapping>

So I am using RESTEasy which is bundled with JBoss.

Class MyApplication is:

public class MyApplication extends Application {

    private Set<Object> singletons = new HashSet<>();

    public MyApplication() {
        singletons.add( new MyResource() );
    }

    @Override
    public Set<Object> getSingletons() {
        return singletons;
    }
}

… and finally in class MyResource I have the following:

@Path(...)
public class MyResource {

    @Context
    ServletContext context;

    public MyResource() {
        // I understand context is supposed to be null here
    }

    // ... but it should have been injected by the time we reach the service method.
    @Path("/somePath")
    @GET
    @Produces(MediaType.APPLICATION_JSON) 
    public Response someMethod( ) {
        if (context==null) throw new RuntimeException();
        ...
    }
}

The above code always results in the RuntimeException being thrown. I.e. RESTEasy somehow fails to inject the ServletContext. Note that I don't have any other JAX-RS problems. I.e. if I hardcode the context-param values I was hoping to be able to retrieve via `ServletContext#getInitParameter", then the JAX-RS rest functionality works as expected when the WAR is deployed to JBoss.

Experimenting further I discovered that the ServletContextis only injected if I perform the injection at an argument of the service method like this:

@Path("/somePath")
@GET
@Produces(MediaType.APPLICATION_JSON) 
public Response someMethod(@Context ServletContext servletContext) {
    ...
}

… however I would prefer not to change the API. Moreover, I would like to perform some costly initialization based on the context-param value once and for all, not on every service method invocation.

My questions are:

  1. why is the injection failing?
  2. I am a little tired of the annotations magic failing at runtime, is there a way to get the ServletContext without using annotations?
  3. Alternatively, is it possible for my MyApplication class to obtain the ServletContext and pass it to the MyResource class as a constructor parameter?
  4. If all else fails I guess I can always read and parse the web.xml file myself using Class#getResourceAsStream ?
Community
  • 1
  • 1
Marcus Junius Brutus
  • 26,087
  • 41
  • 189
  • 331

1 Answers1

3

Based on the comment by FrAn that links to this answer, this is what I ended up doing:

public class JaxRsApplication extends Application {

    private Set<Object> singletons = new HashSet<>();

    public JaxRsApplication(@Context ServletContext servletContext) {
        Assert.assertNotNull(servletContext);
        singletons.add( new UserDatabaseResource(servletContext) );
    }

    @Override
    public Set<Object> getSingletons() {
        return singletons;
    }
}

… and then, in the UserDatabaseResource class I have the following:

public UserDatabaseResource(ServletContext servletContext) {
    Assert.assertNotNull(servletContext);
    ...
    String jndiNameForDatasource = servletContext.getInitParameter("whatever")) ;
    ...
}

This works as the UserDatabaseResource class which is my DAL layer is a singleton and I just needed to get the JNDI name of the datasource to use (from the web.xml file). But maybe this approach also works with some minor adjustments for non-singleton classes as well.

Community
  • 1
  • 1
Marcus Junius Brutus
  • 26,087
  • 41
  • 189
  • 331