我尝试通过使用@Error注解来改进控制器中的错误处理。
@Get(uri = "/{id}")
@Secured("ROLE_VIEW")
HttpResponse<AuthorResource> show(Long id) {
try {
ok(authorService.get(id).get())
} catch (Exception e) {
e.printStackTrace()
throw e
}
}
get()
方法将返回AuthorResource(io.vavr.control.Try
),或者抛出一个自定义异常,即我们的基本ErrorContext异常类的子类。
然后,我在控制器中添加了以下错误处理程序:
@Error(exception = ErrorContext, global = true)
HttpResponse<ErrorContext> onErrorContext(HttpRequest request, ErrorContext error) {
HttpResponse.<ErrorContext>status(HttpStatus.valueOf(error.code)).body(error)
}
不幸的是,异常处理程序似乎没有被调用,并且触发了INTERNAL_SERVER_ERROR(而不是本例中的NOT_FOUND)。gradle测试任务的输出如下所示。
我已尝试以下方法:
- 使用全局处理程序(
global=true
) - 使用抛出的实际子类注解处理程序(
ErrorContextWithoutStacktrace
)
我错过什么了吗?
我已经创建了一个工作的application in github here
Controller class
Test class
测试输出(包括由于SO中的长度限制导致的部分堆栈跟踪):
10:50:31.455 [ForkJoinPool.commonPool-worker-7] INFO i.m.t.e.TestResourcesResolverLoader - Loaded 1 test resources resolvers: io.micronaut.testresources.testcontainers.GenericTestContainerProvider
10:50:31.579 [main] INFO i.m.testresources.server.Application - A Micronaut Test Resources server is listening on port 43207, started in 182ms
10:50:33.164 [default-nioEventLoopGroup-1-2] INFO i.m.t.e.TestResourcesResolverLoader - Loaded 1 test resources resolvers: io.micronaut.testresources.testcontainers.GenericTestContainerProvider
> Task :test
AuthorControllerSpec STANDARD_OUT
10:50:32.581 [Test worker] INFO i.m.context.env.DefaultEnvironment - Established active environments: [test]
10:50:33.131 [multithreadEventLoopGroup-1-1] DEBUG i.m.h.client.netty.DefaultHttpClient - Sending HTTP GET to http://localhost:43207/requirements/entries
10:50:33.190 [multithreadEventLoopGroup-1-1] DEBUG i.m.h.client.netty.DefaultHttpClient - Received response 200 from http://localhost:43207/requirements/entries
10:50:33.216 [multithreadEventLoopGroup-1-2] DEBUG i.m.h.client.netty.DefaultHttpClient - Sending HTTP POST to http://localhost:43207/list
10:50:33.246 [multithreadEventLoopGroup-1-2] DEBUG i.m.h.client.netty.DefaultHttpClient - Received response 200 from http://localhost:43207/list
10:50:33.249 [multithreadEventLoopGroup-1-3] DEBUG i.m.h.client.netty.DefaultHttpClient - Sending HTTP GET to http://localhost:43207/requirements/entries
10:50:33.254 [multithreadEventLoopGroup-1-3] DEBUG i.m.h.client.netty.DefaultHttpClient - Received response 200 from http://localhost:43207/requirements/entries
10:50:33.258 [multithreadEventLoopGroup-1-4] DEBUG i.m.h.client.netty.DefaultHttpClient - Sending HTTP POST to http://localhost:43207/list
10:50:33.262 [multithreadEventLoopGroup-1-4] DEBUG i.m.h.client.netty.DefaultHttpClient - Received response 200 from http://localhost:43207/list
10:50:33.367 [Test worker] INFO i.m.c.h.g.HibernateDatastoreFactory - Starting GORM for Hibernate
10:50:33.883 [Test worker] INFO org.hibernate.Version - HHH000412: Hibernate ORM core version 5.6.11.Final
10:50:33.984 [Test worker] INFO o.h.validator.internal.util.Version - HV000001: Hibernate Validator 6.2.5.Final
10:50:34.074 [Test worker] INFO o.h.annotations.common.Version - HCANN000001: Hibernate Commons Annotations {5.1.2.Final}
10:50:34.139 [Test worker] INFO org.hibernate.dialect.Dialect - HHH000400: Using dialect: org.hibernate.dialect.H2Dialect
AuthorControllerSpec > It fails to get an non-existing Author > example.controller.AuthorControllerSpec.It fails to get an non-existing Author [badId: 546252431, #0] STANDARD_OUT
10:50:34.879 [default-nioEventLoopGroup-3-2] DEBUG i.m.h.client.netty.DefaultHttpClient - Sending HTTP GET to http://localhost:37361/author/546252431
AuthorControllerSpec > It fails to get an non-existing Author > example.controller.AuthorControllerSpec.It fails to get an non-existing Author [badId: 546252431, #0] STANDARD_ERROR
error.ErrorContextWithoutStacktrace: Author with id 546252431 not found.
AuthorControllerSpec > It fails to get an non-existing Author > example.controller.AuthorControllerSpec.It fails to get an non-existing Author [badId: 546252431, #0] STANDARD_OUT
10:50:34.999 [default-nioEventLoopGroup-3-3] ERROR i.m.http.server.RouteExecutor - Unexpected error occurred: Required argument [HttpRequest request] not specified
io.micronaut.web.router.exceptions.UnsatisfiedRouteException: Required argument [HttpRequest request] not specified
at io.micronaut.web.router.exceptions.UnsatisfiedRouteException.create(UnsatisfiedRouteException.java:76)
at io.micronaut.web.router.AbstractRouteMatch.execute(AbstractRouteMatch.java:297)
at io.micronaut.web.router.RouteMatch.execute(RouteMatch.java:111)
at io.micronaut.http.context.ServerRequestContext.with(ServerRequestContext.java:103)
at io.micronaut.http.server.RouteExecutor.lambda$executeRoute$14(RouteExecutor.java:659)
at reactor.core.publisher.FluxDeferContextual.subscribe(FluxDeferContextual.java:49)
[Skipped a lot of reactive frames]
at reactor.core.publisher.Flux.subscribe(Flux.java:8522)
at io.micronaut.http.server.netty.RoutingInBoundHandler.handleRouteMatch(RoutingInBoundHandler.java:601)
at io.micronaut.http.server.netty.RoutingInBoundHandler.channelRead0(RoutingInBoundHandler.java:457)
at io.micronaut.http.server.netty.RoutingInBoundHandler.channelRead0(RoutingInBoundHandler.java:147)
at io.netty.channel.SimpleChannelInboundHandler.channelRead(SimpleChannelInboundHandler.java:99)
[Skipped a lot of netty channel stuff]
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:562)
at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:997)
at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.base/java.lang.Thread.run(Thread.java:833)
10:50:35.031 [default-nioEventLoopGroup-3-2] DEBUG i.m.h.client.netty.DefaultHttpClient - Received response 500 from http://localhost:37361/author/546252431
10:50:35.049 [Test worker] ERROR i.m.r.intercept.RecoveryInterceptor - Type [example.controller.Api$Intercepted] executed with error: error.ErrorResource@475fb7
io.micronaut.http.client.exceptions.HttpClientResponseException: error.ErrorResource@475fb7
at io.micronaut.http.client.netty.DefaultHttpClient$FullHttpResponseHandler.makeErrorFromRequestBody(DefaultHttpClient.java:2226)
at io.micronaut.http.client.netty.DefaultHttpClient$FullHttpResponseHandler.buildResponse(DefaultHttpClient.java:2199)
at io.micronaut.http.client.netty.DefaultHttpClient$FullHttpResponseHandler.buildResponse(DefaultHttpClient.java:2122)
at io.micronaut.http.client.netty.DefaultHttpClient$BaseHttpResponseHandler.channelReadInstrumented(DefaultHttpClient.java:2097)
at io.micronaut.http.client.netty.DefaultHttpClient$FullHttpResponseHandler.channelReadInstrumented(DefaultHttpClient.java:2158)
at io.micronaut.http.client.netty.DefaultHttpClient$FullHttpResponseHandler.channelReadInstrumented(DefaultHttpClient.java:2122)
at io.micronaut.http.client.netty.SimpleChannelInboundHandlerInstrumented.channelRead0(SimpleChannelInboundHandlerInstrumented.java:49)
at io.netty.channel.SimpleChannelInboundHandler.channelRead(SimpleChannelInboundHandler.java:99)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:444)
[Skipped a lot of netty channel stuff]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919)
at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:166)
at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:788)
at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:724)
at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:650)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:562)
at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:997)
at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.base/java.lang.Thread.run(Thread.java:833)
Suppressed: java.lang.Exception: #block terminated with an error
at reactor.core.publisher.BlockingSingleSubscriber.blockingGet(BlockingSingleSubscriber.java:99)
at reactor.core.publisher.Flux.blockFirst(Flux.java:2600)
at io.micronaut.http.client.netty.DefaultHttpClient$1.exchange(DefaultHttpClient.java:498)
at io.micronaut.http.client.netty.DefaultHttpClient$1.retrieve(DefaultHttpClient.java:505)
at io.micronaut.http.client.interceptor.HttpClientIntroductionAdvice.lambda$intercept$5(HttpClientIntroductionAdvice.java:409)
at io.micronaut.http.client.interceptor.HttpClientIntroductionAdvice.handleBlockingCall(HttpClientIntroductionAdvice.java:508)
at io.micronaut.http.client.interceptor.HttpClientIntroductionAdvice.intercept(HttpClientIntroductionAdvice.java:408)
at io.micronaut.aop.chain.MethodInterceptorChain.proceed(MethodInterceptorChain.java:137)
at io.micronaut.retry.intercept.RecoveryInterceptor.intercept(RecoveryInterceptor.java:92)
at io.micronaut.aop.chain.MethodInterceptorChain.proceed(MethodInterceptorChain.java:137)
at example.controller.Api$Intercepted.getAuthor(Unknown Source)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at org.codehaus.groovy.runtime.callsite.PlainObjectMetaMethodSite.doInvoke(PlainObjectMetaMethodSite.java:43)
at org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite$PojoCachedMethodSiteNoUnwrap.invoke(PojoMetaMethodSite.java:203)
at org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite.call(PojoMetaMethodSite.java:56)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:47)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:125)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:148)
at example.controller.AuthorControllerSpec.$spock_feature_0_0(AuthorControllerSpec.groovy:33)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at org.spockframework.util.ReflectionUtil.invokeMethod(ReflectionUtil.java:198)
[Skipped a lot of gradle, junit, and spock stuff]
at worker.org.gradle.process.internal.worker.GradleWorkerMain.main(GradleWorkerMain.java:74)
AuthorControllerSpec > It fails to get an non-existing Author > example.controller.AuthorControllerSpec.It fails to get an non-existing Author [badId: 546252431, #0] FAILED
org.spockframework.runtime.SpockComparisonFailure at AuthorControllerSpec.groovy:37
1条答案
按热度按时间py49o6xq1#
您导入了错误的
HttpRequest
您应该汇入
import io.micronaut.http.HttpRequest
,而不是import java.net.http.HttpRequest
。但是即使这样你也不会捕获到
HttpClientResponseException
,因为你在测试中没有使用任何Client
。如果你想收到这个异常,你应该写这样的代码: