Search code examples
spring-boot-admin

Override Info Endpoint for Spring Boot Admin


tl;dr;

Can I tell Spring Boot Admin to look for /info.json instead of /info?

Full question

I have a Spring Boot Admin server that monitors a number of Spring Boot apps. I'd like to add some frontends that are deployed as static websites, so that I can see all the application version numbers in one place.

My plan is to include info.json and health.json files in my frontend bundle that mimic the Actuator endpoints. I've been able to configure Spring Boot Admin to find these applications using the techniques described on Static Configuration using SimpleDiscoveryClient. This is my discovery configuration

server:
  port: 8096
spring:
  cloud:
    discovery:
      client:
        simple:
          instances:
            frontend:
              - uri: http://localhost:4200
                metadata:
                  management.context-path: /assets/actuator
                  health.path: /health.json

However I've been unable to tell Spring Boot Admin how to find the /info.json endpoint, as it is non-standard.

My application is discovered, and the custom health.path configuration allows it to identify the health endpoint and determine the application is healthy.

Spring Boot Admin discovering my frontend

But because the /info endpoint doesn't exist, Spring Boot Admin can't retreive the version number. Spring Boot Admin showing errors for /info

Is there a way to set a custom info endpoint? I've tried removing the .json file extension on my info.json file, but Spring Boot Admin throws an exception because the MIME type is no longer set. I'd like to avoid custom URL rewrites or MIME type manipulation if at all possible.

org.springframework.http.InvalidMediaTypeException: Invalid mime type "; charset=UTF-8": 'mimeType' must not be empty
    at org.springframework.http.MediaType.parseMediaType(MediaType.java:742) ~[spring-web-6.0.7.jar:6.0.7]
    Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException: 
Error has been observed at the following site(s):
    *__checkpoint ⇢ Request to GET info [DefaultWebClient]
Original Stack Trace:
        at org.springframework.http.MediaType.parseMediaType(MediaType.java:742) ~[spring-web-6.0.7.jar:6.0.7]
        at org.springframework.http.HttpHeaders.getContentType(HttpHeaders.java:999) ~[spring-web-6.0.7.jar:6.0.7]
        at org.springframework.http.ReadOnlyHttpHeaders.getContentType(ReadOnlyHttpHeaders.java:61) ~[spring-web-6.0.7.jar:6.0.7]
        at org.springframework.web.reactive.function.client.DefaultClientResponse$DefaultHeaders.contentType(DefaultClientResponse.java:278) ~[spring-webflux-6.0.7.jar:6.0.7]
        at de.codecentric.boot.admin.server.web.client.InstanceExchangeFilterFunctions.isLegacyResponse(InstanceExchangeFilterFunctions.java:157) ~[spring-boot-admin-server-3.0.2.jar:3.0.2]
        at de.codecentric.boot.admin.server.web.client.InstanceExchangeFilterFunctions.lambda$convertLegacyEndpoints$7(InstanceExchangeFilterFunctions.java:144) ~[spring-boot-admin-server-3.0.2.jar:3.0.2]
        at reactor.core.publisher.FluxMap$MapSubscriber.onNext(FluxMap.java:106) ~[reactor-core-3.5.4.jar:3.5.4]
        at reactor.core.publisher.FluxMap$MapSubscriber.onNext(FluxMap.java:122) ~[reactor-core-3.5.4.jar:3.5.4]
        at reactor.core.publisher.FluxRetry$RetrySubscriber.onNext(FluxRetry.java:87) ~[reactor-core-3.5.4.jar:3.5.4]
        at reactor.core.publisher.SerializedSubscriber.onNext(SerializedSubscriber.java:99) ~[reactor-core-3.5.4.jar:3.5.4]
        at reactor.core.publisher.SerializedSubscriber.onNext(SerializedSubscriber.java:99) ~[reactor-core-3.5.4.jar:3.5.4]
        at reactor.core.publisher.FluxTimeout$TimeoutMainSubscriber.onNext(FluxTimeout.java:180) ~[reactor-core-3.5.4.jar:3.5.4]
        at reactor.core.publisher.FluxMap$MapSubscriber.onNext(FluxMap.java:122) ~[reactor-core-3.5.4.jar:3.5.4]
        at reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onNext(FluxOnErrorResume.java:79) ~[reactor-core-3.5.4.jar:3.5.4]
        at reactor.core.publisher.FluxPeek$PeekSubscriber.onNext(FluxPeek.java:200) ~[reactor-core-3.5.4.jar:3.5.4]
        at reactor.core.publisher.FluxPeek$PeekSubscriber.onNext(FluxPeek.java:200) ~[reactor-core-3.5.4.jar:3.5.4]
        at reactor.core.publisher.FluxPeek$PeekSubscriber.onNext(FluxPeek.java:200) ~[reactor-core-3.5.4.jar:3.5.4]
        at reactor.core.publisher.MonoNext$NextSubscriber.onNext(MonoNext.java:82) ~[reactor-core-3.5.4.jar:3.5.4]
        at reactor.core.publisher.MonoFlatMapMany$FlatMapManyInner.onNext(MonoFlatMapMany.java:250) ~[reactor-core-3.5.4.jar:3.5.4]
        at reactor.core.publisher.FluxContextWrite$ContextWriteSubscriber.onNext(FluxContextWrite.java:107) ~[reactor-core-3.5.4.jar:3.5.4]
        at reactor.core.publisher.Operators$ScalarSubscription.request(Operators.java:2545) ~[reactor-core-3.5.4.jar:3.5.4]
        at reactor.core.publisher.FluxContextWrite$ContextWriteSubscriber.request(FluxContextWrite.java:136) ~[reactor-core-3.5.4.jar:3.5.4]
        at reactor.core.publisher.MonoFlatMapMany$FlatMapManyMain.onSubscribeInner(MonoFlatMapMany.java:150) ~[reactor-core-3.5.4.jar:3.5.4]
        at reactor.core.publisher.MonoFlatMapMany$FlatMapManyInner.onSubscribe(MonoFlatMapMany.java:245) ~[reactor-core-3.5.4.jar:3.5.4]
        at reactor.core.publisher.FluxContextWrite$ContextWriteSubscriber.onSubscribe(FluxContextWrite.java:101) ~[reactor-core-3.5.4.jar:3.5.4]
        at reactor.core.publisher.FluxJust.subscribe(FluxJust.java:68) ~[reactor-core-3.5.4.jar:3.5.4]
        at reactor.core.publisher.Flux.subscribe(Flux.java:8671) ~[reactor-core-3.5.4.jar:3.5.4]
        at reactor.core.publisher.MonoFlatMapMany$FlatMapManyMain.onNext(MonoFlatMapMany.java:195) ~[reactor-core-3.5.4.jar:3.5.4]
        at reactor.core.publisher.SerializedSubscriber.onNext(SerializedSubscriber.java:99) ~[reactor-core-3.5.4.jar:3.5.4]
        at reactor.core.publisher.FluxRetryWhen$RetryWhenMainSubscriber.onNext(FluxRetryWhen.java:174) ~[reactor-core-3.5.4.jar:3.5.4]
        at reactor.core.publisher.MonoCreate$DefaultMonoSink.success(MonoCreate.java:172) ~[reactor-core-3.5.4.jar:3.5.4]
        at reactor.netty.http.client.HttpClientConnect$HttpIOHandlerObserver.onStateChange(HttpClientConnect.java:435) ~[reactor-netty-http-1.1.5.jar:1.1.5]
        at reactor.netty.ReactorNetty$CompositeConnectionObserver.onStateChange(ReactorNetty.java:710) ~[reactor-netty-core-1.1.5.jar:1.1.5]
        at reactor.netty.resources.DefaultPooledConnectionProvider$DisposableAcquire.onStateChange(DefaultPooledConnectionProvider.java:195) ~[reactor-netty-core-1.1.5.jar:1.1.5]
        at reactor.netty.resources.DefaultPooledConnectionProvider$PooledConnection.onStateChange(DefaultPooledConnectionProvider.java:456) ~[reactor-netty-core-1.1.5.jar:1.1.5]
        at reactor.netty.http.client.HttpClientOperations.onInboundNext(HttpClientOperations.java:647) ~[reactor-netty-http-1.1.5.jar:1.1.5]
        at reactor.netty.channel.ChannelOperationsHandler.channelRead(ChannelOperationsHandler.java:113) ~[reactor-netty-core-1.1.5.jar:1.1.5]
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:444) ~[netty-transport-4.1.90.Final.jar:4.1.90.Final]
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420) ~[netty-transport-4.1.90.Final.jar:4.1.90.Final]
        at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412) ~[netty-transport-4.1.90.Final.jar:4.1.90.Final]
        at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:103) ~[netty-codec-4.1.90.Final.jar:4.1.90.Final]
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:444) ~[netty-transport-4.1.90.Final.jar:4.1.90.Final]
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420) ~[netty-transport-4.1.90.Final.jar:4.1.90.Final]
        at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412) ~[netty-transport-4.1.90.Final.jar:4.1.90.Final]
        at io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelRead(CombinedChannelDuplexHandler.java:436) ~[netty-transport-4.1.90.Final.jar:4.1.90.Final]
        at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:346) ~[netty-codec-4.1.90.Final.jar:4.1.90.Final]
        at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:333) ~[netty-codec-4.1.90.Final.jar:4.1.90.Final]
        at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:454) ~[netty-codec-4.1.90.Final.jar:4.1.90.Final]
        at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:290) ~[netty-codec-4.1.90.Final.jar:4.1.90.Final]
        at io.netty.channel.CombinedChannelDuplexHandler.channelRead(CombinedChannelDuplexHandler.java:251) ~[netty-transport-4.1.90.Final.jar:4.1.90.Final]
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:442) ~[netty-transport-4.1.90.Final.jar:4.1.90.Final]
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420) ~[netty-transport-4.1.90.Final.jar:4.1.90.Final]
        at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412) ~[netty-transport-4.1.90.Final.jar:4.1.90.Final]
        at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410) ~[netty-transport-4.1.90.Final.jar:4.1.90.Final]
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:440) ~[netty-transport-4.1.90.Final.jar:4.1.90.Final]
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420) ~[netty-transport-4.1.90.Final.jar:4.1.90.Final]
        at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919) ~[netty-transport-4.1.90.Final.jar:4.1.90.Final]
        at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:166) ~[netty-transport-4.1.90.Final.jar:4.1.90.Final]
        at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:788) ~[netty-transport-4.1.90.Final.jar:4.1.90.Final]
        at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:724) ~[netty-transport-4.1.90.Final.jar:4.1.90.Final]
        at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:650) ~[netty-transport-4.1.90.Final.jar:4.1.90.Final]
        at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:562) ~[netty-transport-4.1.90.Final.jar:4.1.90.Final]
        at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:997) ~[netty-common-4.1.90.Final.jar:4.1.90.Final]
        at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) ~[netty-common-4.1.90.Final.jar:4.1.90.Final]
        at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) ~[netty-common-4.1.90.Final.jar:4.1.90.Final]
        at java.base/java.lang.Thread.run(Thread.java:833) ~[na:na]
Caused by: org.springframework.util.InvalidMimeTypeException: Invalid mime type "; charset=UTF-8": 'mimeType' must not be empty
    at org.springframework.util.MimeTypeUtils.parseMimeTypeInternal(MimeTypeUtils.java:220) ~[spring-core-6.0.7.jar:6.0.7]
    at org.springframework.util.ConcurrentLruCache.get(ConcurrentLruCache.java:100) ~[spring-core-6.0.7.jar:6.0.7]
    at org.springframework.util.MimeTypeUtils.parseMimeType(MimeTypeUtils.java:213) ~[spring-core-6.0.7.jar:6.0.7]
    at org.springframework.http.MediaType.parseMediaType(MediaType.java:739) ~[spring-web-6.0.7.jar:6.0.7]
    at org.springframework.http.HttpHeaders.getContentType(HttpHeaders.java:999) ~[spring-web-6.0.7.jar:6.0.7]
    at org.springframework.http.ReadOnlyHttpHeaders.getContentType(ReadOnlyHttpHeaders.java:61) ~[spring-web-6.0.7.jar:6.0.7]
    at org.springframework.web.reactive.function.client.DefaultClientResponse$DefaultHeaders.contentType(DefaultClientResponse.java:278) ~[spring-webflux-6.0.7.jar:6.0.7]
    at de.codecentric.boot.admin.server.web.client.InstanceExchangeFilterFunctions.isLegacyResponse(InstanceExchangeFilterFunctions.java:157) ~[spring-boot-admin-server-3.0.2.jar:3.0.2]
    at de.codecentric.boot.admin.server.web.client.InstanceExchangeFilterFunctions.lambda$convertLegacyEndpoints$7(InstanceExchangeFilterFunctions.java:144) ~[spring-boot-admin-server-3.0.2.jar:3.0.2]
    at reactor.core.publisher.FluxMap$MapSubscriber.onNext(FluxMap.java:106) ~[reactor-core-3.5.4.jar:3.5.4]
    at reactor.core.publisher.FluxMap$MapSubscriber.onNext(FluxMap.java:122) ~[reactor-core-3.5.4.jar:3.5.4]
    at reactor.core.publisher.FluxRetry$RetrySubscriber.onNext(FluxRetry.java:87) ~[reactor-core-3.5.4.jar:3.5.4]
    at reactor.core.publisher.SerializedSubscriber.onNext(SerializedSubscriber.java:99) ~[reactor-core-3.5.4.jar:3.5.4]
    at reactor.core.publisher.SerializedSubscriber.onNext(SerializedSubscriber.java:99) ~[reactor-core-3.5.4.jar:3.5.4]
    at reactor.core.publisher.FluxTimeout$TimeoutMainSubscriber.onNext(FluxTimeout.java:180) ~[reactor-core-3.5.4.jar:3.5.4]
    at reactor.core.publisher.FluxMap$MapSubscriber.onNext(FluxMap.java:122) ~[reactor-core-3.5.4.jar:3.5.4]
    at reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onNext(FluxOnErrorResume.java:79) ~[reactor-core-3.5.4.jar:3.5.4]
    at reactor.core.publisher.FluxPeek$PeekSubscriber.onNext(FluxPeek.java:200) ~[reactor-core-3.5.4.jar:3.5.4]
    at reactor.core.publisher.FluxPeek$PeekSubscriber.onNext(FluxPeek.java:200) ~[reactor-core-3.5.4.jar:3.5.4]
    at reactor.core.publisher.FluxPeek$PeekSubscriber.onNext(FluxPeek.java:200) ~[reactor-core-3.5.4.jar:3.5.4]
    at reactor.core.publisher.MonoNext$NextSubscriber.onNext(MonoNext.java:82) ~[reactor-core-3.5.4.jar:3.5.4]
    at reactor.core.publisher.MonoFlatMapMany$FlatMapManyInner.onNext(MonoFlatMapMany.java:250) ~[reactor-core-3.5.4.jar:3.5.4]
    at reactor.core.publisher.FluxContextWrite$ContextWriteSubscriber.onNext(FluxContextWrite.java:107) ~[reactor-core-3.5.4.jar:3.5.4]
    at reactor.core.publisher.Operators$ScalarSubscription.request(Operators.java:2545) ~[reactor-core-3.5.4.jar:3.5.4]
    at reactor.core.publisher.FluxContextWrite$ContextWriteSubscriber.request(FluxContextWrite.java:136) ~[reactor-core-3.5.4.jar:3.5.4]
    at reactor.core.publisher.MonoFlatMapMany$FlatMapManyMain.onSubscribeInner(MonoFlatMapMany.java:150) ~[reactor-core-3.5.4.jar:3.5.4]
    at reactor.core.publisher.MonoFlatMapMany$FlatMapManyInner.onSubscribe(MonoFlatMapMany.java:245) ~[reactor-core-3.5.4.jar:3.5.4]
    at reactor.core.publisher.FluxContextWrite$ContextWriteSubscriber.onSubscribe(FluxContextWrite.java:101) ~[reactor-core-3.5.4.jar:3.5.4]
    at reactor.core.publisher.FluxJust.subscribe(FluxJust.java:68) ~[reactor-core-3.5.4.jar:3.5.4]
    at reactor.core.publisher.Flux.subscribe(Flux.java:8671) ~[reactor-core-3.5.4.jar:3.5.4]
    at reactor.core.publisher.MonoFlatMapMany$FlatMapManyMain.onNext(MonoFlatMapMany.java:195) ~[reactor-core-3.5.4.jar:3.5.4]
    at reactor.core.publisher.SerializedSubscriber.onNext(SerializedSubscriber.java:99) ~[reactor-core-3.5.4.jar:3.5.4]
    at reactor.core.publisher.FluxRetryWhen$RetryWhenMainSubscriber.onNext(FluxRetryWhen.java:174) ~[reactor-core-3.5.4.jar:3.5.4]
    at reactor.core.publisher.MonoCreate$DefaultMonoSink.success(MonoCreate.java:172) ~[reactor-core-3.5.4.jar:3.5.4]
    at reactor.netty.http.client.HttpClientConnect$HttpIOHandlerObserver.onStateChange(HttpClientConnect.java:435) ~[reactor-netty-http-1.1.5.jar:1.1.5]
    at reactor.netty.ReactorNetty$CompositeConnectionObserver.onStateChange(ReactorNetty.java:710) ~[reactor-netty-core-1.1.5.jar:1.1.5]
    at reactor.netty.resources.DefaultPooledConnectionProvider$DisposableAcquire.onStateChange(DefaultPooledConnectionProvider.java:195) ~[reactor-netty-core-1.1.5.jar:1.1.5]
    at reactor.netty.resources.DefaultPooledConnectionProvider$PooledConnection.onStateChange(DefaultPooledConnectionProvider.java:456) ~[reactor-netty-core-1.1.5.jar:1.1.5]
    at reactor.netty.http.client.HttpClientOperations.onInboundNext(HttpClientOperations.java:647) ~[reactor-netty-http-1.1.5.jar:1.1.5]
    at reactor.netty.channel.ChannelOperationsHandler.channelRead(ChannelOperationsHandler.java:113) ~[reactor-netty-core-1.1.5.jar:1.1.5]
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:444) ~[netty-transport-4.1.90.Final.jar:4.1.90.Final]
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420) ~[netty-transport-4.1.90.Final.jar:4.1.90.Final]
    at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412) ~[netty-transport-4.1.90.Final.jar:4.1.90.Final]
    at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:103) ~[netty-codec-4.1.90.Final.jar:4.1.90.Final]
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:444) ~[netty-transport-4.1.90.Final.jar:4.1.90.Final]
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420) ~[netty-transport-4.1.90.Final.jar:4.1.90.Final]
    at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412) ~[netty-transport-4.1.90.Final.jar:4.1.90.Final]
    at io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelRead(CombinedChannelDuplexHandler.java:436) ~[netty-transport-4.1.90.Final.jar:4.1.90.Final]
    at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:346) ~[netty-codec-4.1.90.Final.jar:4.1.90.Final]
    at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:333) ~[netty-codec-4.1.90.Final.jar:4.1.90.Final]
    at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:454) ~[netty-codec-4.1.90.Final.jar:4.1.90.Final]
    at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:290) ~[netty-codec-4.1.90.Final.jar:4.1.90.Final]
    at io.netty.channel.CombinedChannelDuplexHandler.channelRead(CombinedChannelDuplexHandler.java:251) ~[netty-transport-4.1.90.Final.jar:4.1.90.Final]
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:442) ~[netty-transport-4.1.90.Final.jar:4.1.90.Final]
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420) ~[netty-transport-4.1.90.Final.jar:4.1.90.Final]
    at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412) ~[netty-transport-4.1.90.Final.jar:4.1.90.Final]
    at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410) ~[netty-transport-4.1.90.Final.jar:4.1.90.Final]
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:440) ~[netty-transport-4.1.90.Final.jar:4.1.90.Final]
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420) ~[netty-transport-4.1.90.Final.jar:4.1.90.Final]
    at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919) ~[netty-transport-4.1.90.Final.jar:4.1.90.Final]
    at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:166) ~[netty-transport-4.1.90.Final.jar:4.1.90.Final]
    at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:788) ~[netty-transport-4.1.90.Final.jar:4.1.90.Final]
    at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:724) ~[netty-transport-4.1.90.Final.jar:4.1.90.Final]
    at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:650) ~[netty-transport-4.1.90.Final.jar:4.1.90.Final]
    at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:562) ~[netty-transport-4.1.90.Final.jar:4.1.90.Final]
    at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:997) ~[netty-common-4.1.90.Final.jar:4.1.90.Final]
    at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) ~[netty-common-4.1.90.Final.jar:4.1.90.Final]
    at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) ~[netty-common-4.1.90.Final.jar:4.1.90.Final]
    at java.base/java.lang.Thread.run(Thread.java:833) ~[na:na]

Solution

  • Spring Boot Admin uses EndpointDetectionStrategys to discover endpoints on registered services. Using the default auto-configuration, the first strategy that is used is QueryIndexEndpointStrategy. It will query the actuator endpoint (the one you configured via management.context-path) and try to get endpoints from there. A real actuator will return something like

    {
      "_links": {
        [...]
        "info": {
          "href": "https://<host>/actuator/info",
          "templated": false
        },
        [...]
    }
    

    Since your "actuator response" is probably static, try to change the href attribute to point to your info.json file.