问题
I try to taste Quarkus myself.
And migrate a working sample from my Helidon-sample to Quarkus, but it does not work as expected.
I got an exception like when save comments of an post.
curl -X POST http://localhost:8080/posts/ffba7fa8-d804-403c-8812-9ab2a0d3c16b/comments -d "{\"content\":\"test comments\"}" -H "Content-Type:application/json"
2019-09-06 18:20:35,405 WARN [io.qua.arc.run.ArcRecorder] (executor-thread-1) Bean matching class com.example.CommentResource was marked as unused and removed during build.
Extensions can eliminate false positives using:
- a custom UnremovableBeanBuildItem
- AdditionalBeanBuildItem(false, beanClazz)
2019-09-06 18:20:35,499 ERROR [io.und.req.io] (executor-thread-1) Exception handling request 98229ff8-08fc-43da-aa3b-3ffc14d5b439-1 to /posts/8059eb1d-5d26-4eb3-b9df-39151a5f71f5/comments: 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:363)
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:249)
at io.quarkus.resteasy.runtime.ResteasyFilter.doFilter(ResteasyFilter.java:30)
at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61)
at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131)
at io.undertow.servlet.handlers.FilterHandler.handleRequest(FilterHandler.java:84)
at io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:62)
at io.undertow.servlet.handlers.ServletChain$1.handleRequest(ServletChain.java:68)
at io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36)
at io.undertow.servlet.handlers.RedirectDirHandler.handleRequest(RedirectDirHandler.java:68)
at io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:132)
at io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:57)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:46)
at io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:64)
at io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:60)
at io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:77)
at io.undertow.security.handlers.AbstractSecurityContextAssociationHandler.handleRequest(AbstractSecurityContextAssociationHandler.java:43)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:269)
at io.undertow.servlet.handlers.ServletInitialHandler.access$100(ServletInitialHandler.java:78)
at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:133)
at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:130)
at io.undertow.servlet.core.ServletRequestContextThreadSetupAction$1.call(ServletRequestContextThreadSetupAction.java:48)
at io.undertow.servlet.core.ContextClassLoaderSetupAction$1.call(ContextClassLoaderSetupAction.java:43)
at io.quarkus.undertow.runtime.UndertowDeploymentRecorder$9$1$1.call(UndertowDeploymentRecorder.java:513)
at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:249)
at io.undertow.servlet.handlers.ServletInitialHandler.handleRequest(ServletInitialHandler.java:174)
at io.undertow.server.handlers.HttpContinueReadHandler.handleRequest(HttpContinueReadHandler.java:65)
at io.quarkus.undertow.runtime.UndertowDeploymentRecorder$1.handleRequest(UndertowDeploymentRecorder.java:92)
at io.undertow.server.handlers.CanonicalPathHandler.handleRequest(CanonicalPathHandler.java:49)
at io.quarkus.undertow.deployment.devmode.UndertowHotReplacementSetup.handleHotDeploymentRequest(UndertowHotReplacementSetup.java:85)
at io.quarkus.undertow.deployment.devmode.UndertowHotReplacementSetup$1$1.handleRequest(UndertowHotReplacementSetup.java:61)
at io.undertow.server.Connectors.executeRootHandler(Connectors.java:376)
at io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:830)
at io.quarkus.runtime.CleanableExecutor$CleaningRunnable.run(CleanableExecutor.java:224)
at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
at org.jboss.threads.ContextClassLoaderSavingRunnable.run(ContextClassLoaderSavingRunnable.java:35)
at org.jboss.threads.EnhancedQueueExecutor.safeRun(EnhancedQueueExecutor.java:2011)
at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.doRunTask(EnhancedQueueExecutor.java:1535)
at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1395)
at org.jboss.threads.DelegatingRunnable.run(DelegatingRunnable.java:29)
at org.jboss.threads.ThreadLocalResettingRunnable.run(ThreadLocalResettingRunnable.java:29)
at java.base/java.lang.Thread.run(Thread.java:834)
at org.jboss.threads.JBossThread.run(JBossThread.java:479)
Caused by: java.lang.NullPointerException
at com.example.CommentResource.saveComment(CommentResource.java:43)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.jboss.resteasy.core.MethodInjectorImpl.invoke(MethodInjectorImpl.java:151)
at org.jboss.resteasy.core.MethodInjectorImpl.lambda$invoke$3(MethodInjectorImpl.java:122)
at java.base/java.util.concurrent.CompletableFuture.uniApplyNow(CompletableFuture.java:680)
at java.base/java.util.concurrent.CompletableFuture.uniApplyStage(CompletableFuture.java:658)
at java.base/java.util.concurrent.CompletableFuture.thenApply(CompletableFuture.java:2094)
at java.base/java.util.concurrent.CompletableFuture.thenApply(CompletableFuture.java:143)
at org.jboss.resteasy.core.MethodInjectorImpl.invoke(MethodInjectorImpl.java:122)
at org.jboss.resteasy.core.ResourceMethodInvoker.internalInvokeOnTarget(ResourceMethodInvoker.java:594)
at org.jboss.resteasy.core.ResourceMethodInvoker.invokeOnTargetAfterFilter(ResourceMethodInvoker.java:468)
at org.jboss.resteasy.core.ResourceMethodInvoker.lambda$invokeOnTarget$2(ResourceMethodInvoker.java:421)
at org.jboss.resteasy.core.interception.jaxrs.PreMatchContainerRequestContext.filter(PreMatchContainerRequestContext.java:363)
at org.jboss.resteasy.core.ResourceMethodInvoker.invokeOnTarget(ResourceMethodInvoker.java:423)
at org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:391)
at org.jboss.resteasy.core.ResourceLocatorInvoker.invokeOnTargetObject(ResourceLocatorInvoker.java:158)
at org.jboss.resteasy.core.ResourceLocatorInvoker.lambda$invoke$3(ResourceLocatorInvoker.java:113)
at java.base/java.util.concurrent.CompletableFuture.uniComposeStage(CompletableFuture.java:1106)
at java.base/java.util.concurrent.CompletableFuture.thenCompose(CompletableFuture.java:2235)
at java.base/java.util.concurrent.CompletableFuture.thenCompose(CompletableFuture.java:143)
at org.jboss.resteasy.core.ResourceLocatorInvoker.invoke(ResourceLocatorInvoker.java:113)
at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:477)
... 51 more
The CommentResource
is registered in PostResource
.
@Path("posts")
@RequestScoped
public class PostResource{
//other methods are omitted
@Path("{id}/comments")
public CommentResource commentResource() {
return resourceContext.getResource(CommentResource.class);
}
}
The Commentresource code is like this.
@RequestScoped
public class CommentResource {
private final static Logger LOGGER = Logger.getLogger(CommentResource.class.getName());
private final CommentRepository comments;
@Context
UriInfo uriInfo;
@Context
ResourceContext resourceContext;
@PathParam("id")
String postId;
@Inject
public CommentResource(CommentRepository commentRepository) {
this.comments = commentRepository;
}
@GET
public Response getAllComments() {
return ok(this.comments.allByPostId(this.postId)).build();
}
@POST
public Response saveComment(Comment commentForm) {
Comment saved = this.comments.save(Comment.of(this.postId, commentForm.getContent()));
return created(
uriInfo.getBaseUriBuilder()
.path("/posts/{id}/comments/{commentId}")
.build(this.postId, saved.getId())
).build();
}
}
It seems the CommentRepository
in the CommentResource
is not recognized by CDI and RestEasy Inject provider.
回答1:
For now, I think you can work around the issue by adding the @Unremovable
annotation to your CommentResource
class.
You might also have to add the @RegisterForReflection
annotation.
We will see if we can find a better way to detect the subresources automatically and do that for you.
来源:https://stackoverflow.com/questions/57820428/jax-rs-subresource-issue-in-quarkus