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

Most upvoted comments

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.