Y. Tarion
Y. Tarion

Reputation: 423

Java jersey 2.6: ContainerRequestFilter: Not Inside a request scope

I have a service rest on my tomcat and it correctly works but when I deploy it on another tomcat server, it throws an exception.

I'm trying to implement a ContainerRequestFilter. And this exception seems caused by the @Context resourceInfo in my authenticationFilter (the class that implements ContainerRequestFilter). But I don't understand why and how to fix it. (I followed this tutorial)

A MultiException has 3 exceptions.  They are:
1. java.lang.IllegalStateException: Not inside a request scope.
2. java.lang.IllegalArgumentException: While attempting to resolve the dependencies of services.AuthentificationFilter errors were found
3. java.lang.IllegalStateException: Unable to perform operation: resolve on services.AuthentificationFilter

org.jvnet.hk2.internal.Collector.throwIfErrors(Collector.java:88)
org.jvnet.hk2.internal.ClazzCreator.resolveAllDependencies(ClazzCreator.java:270)
org.jvnet.hk2.internal.ClazzCreator.create(ClazzCreator.java:414)
org.jvnet.hk2.internal.SystemDescriptor.create(SystemDescriptor.java:456)
org.jvnet.hk2.internal.SingletonContext$1.compute(SingletonContext.java:114)
org.jvnet.hk2.internal.SingletonContext$1.compute(SingletonContext.java:102)
org.glassfish.hk2.utilities.cache.Cache$OriginThreadAwareFuture$1.call(Cache.java:97)
java.util.concurrent.FutureTask.run(FutureTask.java:266)
org.glassfish.hk2.utilities.cache.Cache$OriginThreadAwareFuture.run(Cache.java:154)
org.glassfish.hk2.utilities.cache.Cache.compute(Cache.java:199)
org.jvnet.hk2.internal.SingletonContext.findOrCreate(SingletonContext.java:153)
org.jvnet.hk2.internal.Utilities.createService(Utilities.java:2445)
org.jvnet.hk2.internal.ServiceHandleImpl.getService(ServiceHandleImpl.java:98)
org.jvnet.hk2.internal.ServiceHandleImpl.getService(ServiceHandleImpl.java:87)
org.glassfish.jersey.internal.inject.Providers.getAllRankedProviders(Providers.java:234)
org.glassfish.jersey.server.ApplicationHandler.getProcessingProviders(ApplicationHandler.java:616)
org.glassfish.jersey.server.ApplicationHandler.initialize(ApplicationHandler.java:409)
org.glassfish.jersey.server.ApplicationHandler.access$500(ApplicationHandler.java:161)
org.glassfish.jersey.server.ApplicationHandler$3.run(ApplicationHandler.java:286)
org.glassfish.jersey.internal.Errors$2.call(Errors.java:289)
org.glassfish.jersey.internal.Errors$2.call(Errors.java:286)
org.glassfish.jersey.internal.Errors.process(Errors.java:315)
org.glassfish.jersey.internal.Errors.process(Errors.java:297)
org.glassfish.jersey.internal.Errors.processWithException(Errors.java:286)
org.glassfish.jersey.server.ApplicationHandler.<init>(ApplicationHandler.java:283)
org.glassfish.jersey.servlet.WebComponent.<init>(WebComponent.java:298)
org.glassfish.jersey.servlet.ServletContainer.init(ServletContainer.java:167)
org.glassfish.jersey.servlet.ServletContainer.init(ServletContainer.java:349)
javax.servlet.GenericServlet.init(GenericServlet.java:158)
org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:620)
org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:349)
org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:784)
org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:802)
org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1410)
org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
java.lang.Thread.run(Thread.java:745)

The code of my authenticationFilter

@Provider
public class AuthentificationFilter implements javax.ws.rs.container.ContainerRequestFilter {

@Context
private ResourceInfo resourceInfo;

private static final String AUTHORIZATION = "Authorization";
private static final String BASIC = "Basic";
private static final Response ACCESS_DENIED = Response.status(Response.Status.UNAUTHORIZED).entity("Essayez de mettre sudo devant votre requete").build();
private static final Response ACCESS_FORBIDDEN = Response.status(Response.Status.FORBIDDEN).entity("You shall not pass !").build();

@Override
public void filter(final ContainerRequestContext context) throws IOException {
    Method method = resourceInfo.getResourceMethod();
    if(!method.isAnnotationPresent(PermitAll.class)) {
        MultivaluedMap<String, String> headers = context.getHeaders();
        List<String> authorization = headers.get(AUTHORIZATION);

        if(method.isAnnotationPresent(DenyAll.class)) {
            context.abortWith(ACCESS_FORBIDDEN);
            return;
        }else if(authorization == null || authorization.isEmpty()) {
            context.abortWith(ACCESS_DENIED);
            return;
        }

        String encodedUserPassword = authorization.get(0).replaceFirst(BASIC + " ", "");
        String auth = new String(Base64.getDecoder().decode(encodedUserPassword.getBytes()));;

        String[] authTab = auth.split(":");
        String username = authTab[0];
        String password = authTab[1];

        if(method.isAnnotationPresent(RolesAllowed.class)) {
            RolesAllowed rolesAnnotation = method.getAnnotation(RolesAllowed.class);
            Set<String> rolesSet = new HashSet<String>(Arrays.asList(rolesAnnotation.value()));
            if(!isAllowed(username, password, rolesSet)) {
                context.abortWith(ACCESS_DENIED);
                return;
            }
        }
    }
}

private boolean isAllowed(final String username, final String password, final Set<String> rolesSet)
{
    boolean isAllowed = false;
    User user;
    if((user = new UserMapper().get(username, password)) != null) {
        String role = user.getStatus().toString();
        if(rolesSet.contains(role))
            isAllowed = true;
    }
    return isAllowed;
}

}

The code of MyApplication.java that registers the filter:

public class MyApplication extends ResourceConfig {

public MyApplication() {
    packages("services");
    register(AuthentificationFilter.class);
}
}

And finally the web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
     version="3.1">

<servlet>
    <servlet-name>Example API</servlet-name>
    <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
    <init-param>
        <param-name>javax.ws.rs.Application</param-name>
        <param-value>services.MyApplication</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>

<servlet-mapping>
    <servlet-name>Example API</servlet-name>
    <url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>

What am I doing wrong ?

Upvotes: 1

Views: 2692

Answers (1)

Y. Tarion
Y. Tarion

Reputation: 423

I finally found the solution. I had to create a class that implements DynamicFeature and register my AuthenticationFilter thanks to a custom constructor.

@Provider
public class AuthenticationDynamicFeature implements DynamicFeature {

    @Override
    public void configure(ResourceInfo resourceInfo, FeatureContext featureContext) {
        featureContext.register(new AuthenticationFilter(resourceInfo));
    }
}

And here the custom constructor :

public AuthenticationFilter(ResourceInfo resourceInfo) {
    super();
    this.resourceInfo = resourceInfo;
}

I tried a lot of other ways, and this one, it's the only one that worked for me.

Upvotes: 1

Related Questions