Reputation: 423
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
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