@Client未从/ measure端点接收正文

时间:2019-03-17 21:35:53

标签: micronaut

我尝试使用@Client界面检索度量。当我使用自己的松散类型类时:

data class Tags(
        val tag: String,
        val values: List<String>
)

data class Metrics(
        val names: List<String>?,
        val name: String?,
        val measurements: List<Map<String, Any>>?,
        val availableTags: List<Tags>?
)

和界面:

@Client("/metrics")
interface MetricsClient {

    @Get("{/name}")
    fun metrics(name: String? = null): Metrics
}

我得到了期望的数据,但是我尝试使用端点中定义的类使代码与服务器客户端报告“空主体”响应保持同步。

带有的代码不起作用:

@Client("/metrics")
interface MetricsClient {

    @Get("/")
    fun metricsList(): MetricsEndpoint.MetricNames

    @Get("/{name}")
    fun metricsDetails(name: String): MetricsEndpoint.MetricDetails
}

client.metricsList()的首次调用会引发异常,表明正文为空。

此代码有什么问题?为什么不起作用?

编辑: 我为所有功能启用了DEBUG,这就是通过使用以下URL重新加载页面所得到的:

23:22:27.683 [pool-1-thread-7] DEBUG i.m.context.DefaultBeanContext - Resolved existing bean [io.micronaut.health.HeartbeatTask@55d58825] for type [class io.micronaut.health.HeartbeatTask] and qualifier [null]
23:22:27.683 [pool-1-thread-7] DEBUG i.m.c.e.ApplicationEventPublisher - Publishing event: io.micronaut.health.HeartbeatEvent[source=io.micronaut.http.server.netty.NettyEmbeddedServerInstance@2d64160c]
23:22:27.683 [pool-1-thread-7] DEBUG i.m.context.DefaultBeanContext - Resolving beans for type: <HeartbeatEvent> io.micronaut.context.event.ApplicationEventListener 
23:22:29.469 [nioEventLoopGroup-1-14] DEBUG i.m.h.server.netty.NettyHttpServer - Server localhost:8080 Received Request: GET /khal
23:22:29.469 [nioEventLoopGroup-1-14] DEBUG i.m.h.s.netty.RoutingInBoundHandler - Matching route GET - /khal
23:22:29.469 [nioEventLoopGroup-1-14] DEBUG i.m.h.s.netty.RoutingInBoundHandler - Matched route GET - /khal to controller class com.helpchoice.kotlin.mn.management.$EndpointsControllerDefinition$Intercepted
23:22:29.473 [nioEventLoopGroup-1-16] DEBUG i.m.http.client.DefaultHttpClient - Sending HTTP Request: GET /metrics
23:22:29.474 [nioEventLoopGroup-1-16] DEBUG i.m.http.client.DefaultHttpClient - Chosen Server: localhost(8080)
23:22:29.476 [nioEventLoopGroup-1-17] DEBUG i.m.h.server.netty.NettyHttpServer - Server localhost:8080 Received Request: GET /metrics
23:22:29.476 [nioEventLoopGroup-1-17] DEBUG i.m.h.s.netty.RoutingInBoundHandler - Matching route GET - /metrics
23:22:29.476 [nioEventLoopGroup-1-17] DEBUG i.m.h.s.netty.RoutingInBoundHandler - Matched route GET - /metrics to controller class io.micronaut.configuration.metrics.management.endpoint.MetricsEndpoint
23:22:29.479 [pool-1-thread-6] DEBUG i.m.h.s.netty.RoutingInBoundHandler - Encoding emitted response object [io.micronaut.configuration.metrics.management.endpoint.MetricsEndpoint$MetricNames@719dde52] using codec: io.micronaut.jackson.codec.JsonMediaTypeCodec@6c9320c2
23:22:29.482 [nioEventLoopGroup-1-16] DEBUG i.m.http.client.DefaultHttpClient - Unable to decode response body using codec JsonMediaTypeCodec:Error decoding JSON stream for type [class io.micronaut.configuration.metrics.management.endpoint.MetricsEndpoint$MetricNames]: Cannot construct instance of `io.micronaut.configuration.metrics.management.endpoint.MetricsEndpoint$MetricNames` (no Creators, like default construct, exist): cannot deserialize from Object value (no delegate- or property-based Creator)
 at [Source: (byte[])"{"names":["executor","executor.active","executor.completed","executor.pool.size","executor.queued","http.client.requests","http.server.requests","jvm.buffer.count","jvm.buffer.memory.used","jvm.buffer.total.capacity","jvm.classes.loaded","jvm.classes.unloaded","jvm.gc.live.data.size","jvm.gc.max.data.size","jvm.gc.memory.allocated","jvm.gc.memory.promoted","jvm.gc.pause","jvm.memory.committed","jvm.memory.max","jvm.memory.used","jvm.threads.daemon","jvm.threads.live","jvm.threads.peak","logback."[truncated 171 bytes]; line: 1, column: 2]
io.micronaut.http.codec.CodecException: Error decoding JSON stream for type [class io.micronaut.configuration.metrics.management.endpoint.MetricsEndpoint$MetricNames]: Cannot construct instance of `io.micronaut.configuration.metrics.management.endpoint.MetricsEndpoint$MetricNames` (no Creators, like default construct, exist): cannot deserialize from Object value (no delegate- or property-based Creator)
 at [Source: (byte[])"{"names":["executor","executor.active","executor.completed","executor.pool.size","executor.queued","http.client.requests","http.server.requests","jvm.buffer.count","jvm.buffer.memory.used","jvm.buffer.total.capacity","jvm.classes.loaded","jvm.classes.unloaded","jvm.gc.live.data.size","jvm.gc.max.data.size","jvm.gc.memory.allocated","jvm.gc.memory.promoted","jvm.gc.pause","jvm.memory.committed","jvm.memory.max","jvm.memory.used","jvm.threads.daemon","jvm.threads.live","jvm.threads.peak","logback."[truncated 171 bytes]; line: 1, column: 2]
    at io.micronaut.jackson.codec.JsonMediaTypeCodec.decode(JsonMediaTypeCodec.java:139)
    at io.micronaut.http.client.FullNettyClientHttpResponse.convertByteBuf(FullNettyClientHttpResponse.java:239)
    at io.micronaut.http.client.FullNettyClientHttpResponse.lambda$getBody$1(FullNettyClientHttpResponse.java:189)
    at java.util.HashMap.computeIfAbsent(HashMap.java:1126)
    at io.micronaut.http.client.FullNettyClientHttpResponse.getBody(FullNettyClientHttpResponse.java:167)
    at io.micronaut.http.client.FullNettyClientHttpResponse.<init>(FullNettyClientHttpResponse.java:100)
    at io.micronaut.http.client.DefaultHttpClient$10.channelRead0(DefaultHttpClient.java:1743)
    at io.micronaut.http.client.DefaultHttpClient$10.channelRead0(DefaultHttpClient.java:1705)
    at io.netty.channel.SimpleChannelInboundHandler.channelRead(SimpleChannelInboundHandler.java:105)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)
    at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340)
    at io.micronaut.http.netty.stream.HttpStreamsHandler.channelRead(HttpStreamsHandler.java:186)
    at io.micronaut.http.netty.stream.HttpStreamsClientHandler.channelRead(HttpStreamsClientHandler.java:181)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)
    at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340)
    at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:102)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)
    at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340)
    at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:102)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)
    at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340)
    at io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelRead(CombinedChannelDuplexHandler.java:438)
    at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:323)
    at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:297)
    at io.netty.channel.CombinedChannelDuplexHandler.channelRead(CombinedChannelDuplexHandler.java:253)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)
    at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340)
    at io.netty.handler.timeout.IdleStateHandler.channelRead(IdleStateHandler.java:286)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)
    at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340)
    at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1434)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)
    at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:965)
    at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:163)
    at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:644)
    at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:579)
    at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:496)
    at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:458)
    at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:897)
    at io.micronaut.http.context.ServerRequestContext.with(ServerRequestContext.java:53)
    at io.micronaut.http.context.ServerRequestContext.lambda$instrument$0(ServerRequestContext.java:69)
    at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
    at java.lang.Thread.run(Thread.java:745)
23:22:29.483 [pool-1-thread-5] ERROR i.m.r.intercept.RecoveryInterceptor - Type [com.helpchoice.kotlin.mn.management.MetricsClient$Intercepted] executed with error: Empty body
io.micronaut.http.client.exceptions.HttpClientResponseException: Empty body
    at io.micronaut.http.client.BlockingHttpClient.lambda$retrieve$0(BlockingHttpClient.java:141)
    at java.util.Optional.orElseThrow(Optional.java:290)
    at io.micronaut.http.client.BlockingHttpClient.retrieve(BlockingHttpClient.java:141)
    at io.micronaut.http.client.interceptor.HttpClientIntroductionAdvice.intercept(HttpClientIntroductionAdvice.java:501)
    at io.micronaut.aop.MethodInterceptor.intercept(MethodInterceptor.java:41)
    at io.micronaut.aop.chain.InterceptorChain.proceed(InterceptorChain.java:147)
    at io.micronaut.retry.intercept.RecoveryInterceptor.intercept(RecoveryInterceptor.java:74)
    at io.micronaut.aop.MethodInterceptor.intercept(MethodInterceptor.java:41)
    at io.micronaut.aop.chain.InterceptorChain.proceed(InterceptorChain.java:147)
    at com.helpchoice.kotlin.mn.management.MetricsClient$Intercepted.metricsList(Unknown Source)
    at com.helpchoice.kotlin.mn.management.EndpointsController.metrics(EndpointsController.kt:142)
    at com.helpchoice.kotlin.mn.management.$EndpointsControllerDefinition$$exec4.invokeInternal(Unknown Source)
    at io.micronaut.context.AbstractExecutableMethod.invoke(AbstractExecutableMethod.java:145)
    at io.micronaut.context.DefaultBeanContext$BeanExecutionHandle.invoke(DefaultBeanContext.java:2447)
    at io.micronaut.web.router.AbstractRouteMatch.execute(AbstractRouteMatch.java:237)
    at io.micronaut.web.router.RouteMatch.execute(RouteMatch.java:123)
    at io.micronaut.http.server.netty.RoutingInBoundHandler.lambda$buildResultEmitter$16(RoutingInBoundHandler.java:1288)
    at io.reactivex.internal.operators.flowable.FlowableCreate.subscribeActual(FlowableCreate.java:71)
    at io.reactivex.Flowable.subscribe(Flowable.java:14479)
    at io.reactivex.internal.operators.flowable.FlowableMap.subscribeActual(FlowableMap.java:37)
    at io.reactivex.Flowable.subscribe(Flowable.java:14479)
    at io.reactivex.internal.operators.flowable.FlowableSwitchIfEmpty.subscribeActual(FlowableSwitchIfEmpty.java:32)
    at io.reactivex.Flowable.subscribe(Flowable.java:14479)
    at io.reactivex.Flowable.subscribe(Flowable.java:14429)
    at io.micronaut.http.context.ServerRequestTracingPublisher.lambda$subscribe$0(ServerRequestTracingPublisher.java:53)
    at io.micronaut.http.context.ServerRequestContext.with(ServerRequestContext.java:53)
    at io.micronaut.http.context.ServerRequestTracingPublisher.subscribe(ServerRequestTracingPublisher.java:53)
    at io.reactivex.internal.operators.flowable.FlowableFromPublisher.subscribeActual(FlowableFromPublisher.java:29)
    at io.reactivex.Flowable.subscribe(Flowable.java:14479)
    at io.reactivex.internal.operators.flowable.FlowableSwitchMap.subscribeActual(FlowableSwitchMap.java:49)
    at io.reactivex.Flowable.subscribe(Flowable.java:14479)
    at io.reactivex.Flowable.subscribe(Flowable.java:14429)
    at io.micronaut.configuration.metrics.binder.web.WebMetricsPublisher.subscribe(WebMetricsPublisher.java:123)
    at io.reactivex.internal.operators.flowable.FlowableFromPublisher.subscribeActual(FlowableFromPublisher.java:29)
    at io.reactivex.Flowable.subscribe(Flowable.java:14479)
    at io.reactivex.Flowable.subscribe(Flowable.java:14426)
    at io.reactivex.internal.operators.flowable.FlowableSubscribeOn$SubscribeOnSubscriber.run(FlowableSubscribeOn.java:82)
    at io.reactivex.internal.schedulers.ExecutorScheduler$ExecutorWorker$BooleanRunnable.run(ExecutorScheduler.java:260)
    at io.reactivex.internal.schedulers.ExecutorScheduler$ExecutorWorker.run(ExecutorScheduler.java:225)
    at io.micrometer.core.instrument.composite.CompositeTimer.record(CompositeTimer.java:79)
    at io.micrometer.core.instrument.Timer.lambda$wrap$0(Timer.java:126)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)
23:22:29.484 [pool-1-thread-5] ERROR i.m.h.s.netty.RoutingInBoundHandler - Unexpected error occurred: Empty body
io.micronaut.http.client.exceptions.HttpClientResponseException: Empty body
    at io.micronaut.http.client.BlockingHttpClient.lambda$retrieve$0(BlockingHttpClient.java:141)
    at java.util.Optional.orElseThrow(Optional.java:290)
    at io.micronaut.http.client.BlockingHttpClient.retrieve(BlockingHttpClient.java:141)
    at io.micronaut.http.client.interceptor.HttpClientIntroductionAdvice.intercept(HttpClientIntroductionAdvice.java:501)
    at io.micronaut.aop.MethodInterceptor.intercept(MethodInterceptor.java:41)
    at io.micronaut.aop.chain.InterceptorChain.proceed(InterceptorChain.java:147)
    at io.micronaut.retry.intercept.RecoveryInterceptor.intercept(RecoveryInterceptor.java:74)
    at io.micronaut.aop.MethodInterceptor.intercept(MethodInterceptor.java:41)
    at io.micronaut.aop.chain.InterceptorChain.proceed(InterceptorChain.java:147)
    at com.helpchoice.kotlin.mn.management.MetricsClient$Intercepted.metricsList(Unknown Source)
    at com.helpchoice.kotlin.mn.management.EndpointsController.metrics(EndpointsController.kt:142)
    at com.helpchoice.kotlin.mn.management.$EndpointsControllerDefinition$$exec4.invokeInternal(Unknown Source)
    at io.micronaut.context.AbstractExecutableMethod.invoke(AbstractExecutableMethod.java:145)
    at io.micronaut.context.DefaultBeanContext$BeanExecutionHandle.invoke(DefaultBeanContext.java:2447)
    at io.micronaut.web.router.AbstractRouteMatch.execute(AbstractRouteMatch.java:237)
    at io.micronaut.web.router.RouteMatch.execute(RouteMatch.java:123)
    at io.micronaut.http.server.netty.RoutingInBoundHandler.lambda$buildResultEmitter$16(RoutingInBoundHandler.java:1288)
    at io.reactivex.internal.operators.flowable.FlowableCreate.subscribeActual(FlowableCreate.java:71)
    at io.reactivex.Flowable.subscribe(Flowable.java:14479)
    at io.reactivex.internal.operators.flowable.FlowableMap.subscribeActual(FlowableMap.java:37)
    at io.reactivex.Flowable.subscribe(Flowable.java:14479)
    at io.reactivex.internal.operators.flowable.FlowableSwitchIfEmpty.subscribeActual(FlowableSwitchIfEmpty.java:32)
    at io.reactivex.Flowable.subscribe(Flowable.java:14479)
    at io.reactivex.Flowable.subscribe(Flowable.java:14429)
    at io.micronaut.http.context.ServerRequestTracingPublisher.lambda$subscribe$0(ServerRequestTracingPublisher.java:53)
    at io.micronaut.http.context.ServerRequestContext.with(ServerRequestContext.java:53)
    at io.micronaut.http.context.ServerRequestTracingPublisher.subscribe(ServerRequestTracingPublisher.java:53)
    at io.reactivex.internal.operators.flowable.FlowableFromPublisher.subscribeActual(FlowableFromPublisher.java:29)
    at io.reactivex.Flowable.subscribe(Flowable.java:14479)
    at io.reactivex.internal.operators.flowable.FlowableSwitchMap.subscribeActual(FlowableSwitchMap.java:49)
    at io.reactivex.Flowable.subscribe(Flowable.java:14479)
    at io.reactivex.Flowable.subscribe(Flowable.java:14429)
    at io.micronaut.configuration.metrics.binder.web.WebMetricsPublisher.subscribe(WebMetricsPublisher.java:123)
    at io.reactivex.internal.operators.flowable.FlowableFromPublisher.subscribeActual(FlowableFromPublisher.java:29)
    at io.reactivex.Flowable.subscribe(Flowable.java:14479)
    at io.reactivex.Flowable.subscribe(Flowable.java:14426)
    at io.reactivex.internal.operators.flowable.FlowableSubscribeOn$SubscribeOnSubscriber.run(FlowableSubscribeOn.java:82)
    at io.reactivex.internal.schedulers.ExecutorScheduler$ExecutorWorker$BooleanRunnable.run(ExecutorScheduler.java:260)
    at io.reactivex.internal.schedulers.ExecutorScheduler$ExecutorWorker.run(ExecutorScheduler.java:225)
    at io.micrometer.core.instrument.composite.CompositeTimer.record(CompositeTimer.java:79)
    at io.micrometer.core.instrument.Timer.lambda$wrap$0(Timer.java:126)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)
23:22:29.484 [pool-1-thread-5] DEBUG i.m.h.s.netty.RoutingInBoundHandler - Encoding emitted response object [Internal Server Error: Empty body] using codec: io.micronaut.jackson.codec.JsonMediaTypeCodec@6c9320c2

1 个答案:

答案 0 :(得分:0)

我解决这个问题的方法是明确地将类型声明为 Argument

client.toBlocking()
            .exchange(request, Argument.of(Payload::class.java, DataDto::class.java))

其中我的端点的返回类型是 Payload<DataDto>

做的时候:

client.toBlocking()
            .exchange<RequestDto, Payload<DataDto>>(request)

主体类型似乎在 exchange 方法的深处丢失了。