coolaiddrinker
coolaiddrinker

Reputation: 33

Access SevletContext from interceptor in restful web service

Below is my jersey webservice page ( application.java ) which invokes an interceptor

@Context ServletContext context 

@Path("/application") 
public class application{

  @POST
  @Path("/getData")
  @Produces(MediaType.APPLICATION_JSON)
  @Consumes(MediaType.APPLICATION_JSON)   
  @Interceptors(Interceptor.class)
  public int metthod(Object input) throws Exception{
    // do something 
  }
}

ServletContext is accessible on appliation.java if i use @Context ServletContext context but I get NullPointerException if I use same inside the Interceptor class.

How do i access ServletContext from an Interceptor class.

Thanks

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance xsi:schemaLocation="http://java.sun.com/xml/ns/javaee    http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">

<display-name>ws</display-name>
<description>Web Services</description>

<servlet>
    <servlet-name>jersey-servlet</servlet-name>
    <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
    <init-param>
        <param-name>jersey.config.server.provider.packages</param-name>
        <param-value>com.java.files;com.fasterxml.jackson.jaxrs.json</param-value>
    </init-param>

    <init-param>
        <param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
        <param-value>true</param-value>
    </init-param>

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

</servlet>

<listener>
    <listener-class>com.java.listener.appServletContextListener</listener-class>
</listener>

<servlet-mapping>
    <servlet-name>jersey-servlet</servlet-name>
    <url-pattern>/*</url-pattern>
</servlet-mapping>

<welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>index.htm</welcome-file>
</welcome-file-list>

Upvotes: 0

Views: 1032

Answers (1)

pandaadb
pandaadb

Reputation: 6456

I will attempt to help you with your query and do this in an answer so that it can be formatted and easier to read. Please comment on it in case there is something I am misunderstanding.

From your question I think you are not using any other frameworks other than Weblogic and Jersey.

I will have to make a few assumptions here:

  1. Your interceptor is created through some sort of XML markup for you, and you tell it to intercept all invocations of your resource methods?
  2. This is wired together statically in your xml config somewhere

If you could update your question and add how you create the interceptor?

By the sounds of it, Weblogic offers a container that is running the jax.rs reference implementation for you (jersey). (Correct me if I am wrong).

The essential problem is that Weblogic has no concept of context. If you see your annotation, you can see that the Annotation is a jax-rs annotation:

javax.ws.rs.core.Context

What this means is that you can use this annotation with reference implementations of the jax-rs framework, which would be jersey. Jersey manages beans for you (creation/injection/interception etc) and is request scoped, which is why it can inject all sorts of interesting Attributes for you that have something to do with your Webservice.

This is also why the @Context annotation works in your Resource, because your resource is jersey handled. Your interceptor however seems to be a Weblogic interceptor, that is handled by weblogic. It is not hooked into your jersey logic, hence injection does not work here.

There is ways around this, in form of using a DI framework and scoped beans (e.g. guice can do this for you), however this is not necessary. For your issue, there is a more integrated and smooth way of intercepting resource calls.

A webservice should never be called from within the Application (e.g. it reacts to HTTP requests). That means, you will want to intercept these calls with jersey interceptors, not weblogic interceptors. For this, you can see these two Interfaces:

javax.ws.rs.container.ContainerRequestFilter

javax.ws.rs.container.ContainerResponseFilter

You guessed it right - one of them intercepts Requests before your resource gets them, the other intercepts after your resource has processed the request.

You can read more about this here: https://jersey.java.net/documentation/latest/filters-and-interceptors.html

So in your usecase, you want to intercept the request before handing it off to your resource. In case your ServletContextMap has some value, you'll want to abort the request (return it to the user with some error).

The advantage of this is that Filter are handled by jersey, hence they can be injected by jersey with your context.

Consider this:

public class MyFilter implements ContainerRequestFilter {

    @Context
    private ServletContext context;

    @Override
    public void filter(ContainerRequestContext requestContext) throws IOException {

        boolean  result = evaluateMyMap();

        if(!result) {

            // This is the jersey way of not calling proceed. It will return a 400 response
            // to the user with the message

            requestContext.abortWith(Response.status(Status.BAD_REQUEST)
                    .entity("The Hashmap in the Context has some wonky value").build());
        }

    }

    private boolean evaluateMyMap() {

        // access your context here and do your map evanulation
        // return true if you want the request to be processed, false otherwise 

        return false;
    }

}

In the filter class, the injected context is accessible for you and you can access your map as well.

Please note that your filters must be registered with jersey as well. How to do that, I am not sure (because I haven't used weblogic before)

I hope that explains your issue and how to tackle it. Let me know if you need some more advise/help.

Regards, Artur

Upvotes: 1

Related Questions