quarkus: Injection does not work with interface based rest endpoint
Hello,
I’m having a problem with this scenario. Tipically we are using interfaces for REST endpoints where the annotations are placed to the interfaces (JAX-RS and OpenAPI annotations), we like to make our implementations super clear. I don’t know if it is a Quarkus based practice or just not working but see the following code: Project created with this line of codes:
mvn io.quarkus:quarkus-maven-plugin:0.14.0:create \
-DprojectGroupId=org.acme \
-DprojectArtifactId=rest-json \
-DclassName="org.acme.rest.json.FruitResource" \
-Dpath="/fruits" \
-Dextensions="resteasy-jsonb"
We have an action, just keep it super simple:
package org.acme.rest.json;
import javax.enterprise.inject.Model;
@Model
public class UserAction {
public String getUser() {
return "adminUser";
}
}
and then we have a REST endpoint:
package org.acme.rest.json;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
@Model
@Path("/users")
public class UserResource {
@Inject
UserAction userAction;
@GET
@Produces(MediaType.TEXT_PLAIN)
public Response getUser() {
return Response.ok(userAction.getUser()).build();
}
}
When we call the /users URI with GET, everything works, and it returns the adminUser string. My problem comes when I’m trying to use an interface for my implementation.
package org.acme.rest.json;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
@Path("/users")
public interface IUserResource {
@GET
@Produces(MediaType.TEXT_PLAIN)
Response getUser();
}
and then implement it:
package org.acme.rest.json;
import javax.enterprise.inject.Model;
import javax.inject.Inject;
import javax.ws.rs.core.Response;
@Model
public class UserResource implements IUserResource {
@Inject
UserAction userAction;
@Override
public Response getUser() {
return Response.ok(userAction.getUser()).build();
}
}
When we call the /users URI withj GET, we are getting an NPE for the userAction, which is NULL…
ERROR [io.und.request] (executor-thread-1) UT005023: Exception handling request to /users: org.jboss.resteasy.spi.UnhandledException: java.lang.NullPointerException
at org.jboss.resteasy.core.ExceptionHandler.handleApplicationException(ExceptionHandler.java:106)
at org.jboss.resteasy.core.ExceptionHandler.handleException(ExceptionHandler.java:372)
at org.jboss.resteasy.core.SynchronousDispatcher.writeException(SynchronousDispatcher.java:209)
at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:496)
at org.jboss.resteasy.core.SynchronousDispatcher.lambda$invoke$4(SynchronousDispatcher.java:252)
at org.jboss.resteasy.core.SynchronousDispatcher.lambda$preprocess$0(SynchronousDispatcher.java:153)
at org.jboss.resteasy.core.interception.jaxrs.PreMatchContainerRequestContext.filter(PreMatchContainerRequestContext.java:362)
at org.jboss.resteasy.core.SynchronousDispatcher.preprocess(SynchronousDispatcher.java:156)
at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:238)
at org.jboss.resteasy.plugins.server.servlet.ServletContainerDispatcher.service(ServletContainerDispatcher.java:234)
at io.quarkus.resteasy.runtime.ResteasyFilter$ResteasyResponseWrapper.sendError(ResteasyFilter.java:72)
at io.undertow.servlet.handlers.DefaultServlet.doGet(DefaultServlet.java:175)
....
Caused by: java.lang.NullPointerException
at org.acme.rest.json.UserResource.getUser(UserResource.java:15)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.acme.rest.json.UserResource.getUser(UserResource.java:15)
which is this line: return Response.ok(userAction.getUser()).build();
When the endpoint is called, before the NPE drops there is another LOG message:
[io.qua.arc.run.ArcDeploymentTemplate] (executor-thread-1) Bean matching class org.acme.rest.json.UserResource was marked as unused and removed during build.
Extensions can eliminate false positives using:
- a custom UnremovableBeanBuildItem
- AdditionalBeanBuildItem(false, beanClazz)
What am I missing? It should work, shouln’t it? Did I miss something in the docs?
About this issue
- Original URL
- State: closed
- Created 5 years ago
- Comments: 20 (11 by maintainers)
Commits related to this issue
- Fix injection into interface-based resources - resolves #2280 — committed to mkouba/quarkus by mkouba 5 years ago
Yes 😉
Ok, then I’m going to send a PR today.
@Holi60k Ok, if RESTEasy does support this and no one has any objections we can make it work. However, I’d like to know what the expected behavior is.