groovy Micronaut @错误注解不工作(micronaut 3.7.3)

9cbw7uwe  于 2022-11-21  发布在  其他
关注(0)|答案(1)|浏览(159)

我尝试通过使用@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
py49o6xq

py49o6xq1#

您导入了错误的HttpRequest
您应该汇入import io.micronaut.http.HttpRequest,而不是import java.net.http.HttpRequest
但是即使这样你也不会捕获到HttpClientResponseException,因为你在测试中没有使用任何Client。如果你想收到这个异常,你应该写这样的代码:

@Inject
    @Client("/author")
    HttpClient client

    @IgnoreRest
    def "It fails to get an non-existing Author with an HttpClient"() {
        given:
        def token = viewer()

        when:
        def author = client.toBlocking().exchange(HttpRequest.create(
                HttpMethod.GET,
                "/" + badId
        ).bearerAuth(token))

        then:
        def ex = thrown(HttpClientResponseException)
        ex.status == NOT_FOUND
        ex.getResponse().getBody(ErrorResource).map {
            assert it.message == "Author with id ${badId} not found."
            it
        }.isPresent()

        where:
        badId = anyInt()
    }

相关问题