Skip to content

Spring WebFlux 7 (Spring Boot 4): NoSuchMethodError in DispatcherHandlerInstrumentation #4472

@arafat-wsd

Description

@arafat-wsd

Description

The agent's WebFlux instrumentation throws NoSuchMethodError on Spring Framework 7 (Spring Boot 4) with Netty.

PR #4397 added experimental Spring Boot 4 support for Spring MVC (servlet stack), but the WebFlux (reactive stack) instrumentation was not updated and remains incompatible with Spring Framework 7.

Environment

  • Agent version: 1.55.6
  • Spring Boot: 4.0.x
  • Spring Framework: 7.0.2
  • Spring WebFlux: 7.0.2
  • Reactor Netty: 1.3.1
  • Netty: 4.2.9.Final
  • JDK: 21

Stack trace

[reactor-http-nio-2] ERROR co.elastic.apm.agent.bci.IndyBootstrap - Advice threw an exception, this should never happen!
java.lang.NoSuchMethodError: 'java.util.List org.springframework.http.HttpHeaders.get(java.lang.Object)'
    at co.elastic.apm.agent.springwebflux.DispatcherHandlerInstrumentation$HandleAdvice.onEnter(DispatcherHandlerInstrumentation.java:64) ~[elastic-apm-agent-aefc330832b1a172028a4ec17f6d4d20-29542a5269d2cc8773f457e12848a276.jar:1.55.6]
    at org.springframework.web.reactive.DispatcherHandler.handle(DispatcherHandler.java:139) ~[spring-webflux-7.0.2.jar:7.0.2]
    at org.springframework.web.server.handler.DefaultWebFilterChain.lambda$filter$0(DefaultWebFilterChain.java:107) ~[spring-web-7.0.2.jar:7.0.2]
    at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:45) ~[reactor-core-3.6.11.jar:3.6.11]
    at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:76) ~[reactor-core-3.6.11.jar:3.6.11]
    at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:53) ~[reactor-core-3.6.11.jar:3.6.11]
    at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:76) ~[reactor-core-3.6.11.jar:3.6.11]
    at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:53) ~[reactor-core-3.6.11.jar:3.6.11]
    at reactor.core.publisher.Mono.subscribe(Mono.java:4576) ~[reactor-core-3.6.11.jar:3.6.11]
    at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.subscribeNext(MonoIgnoreThen.java:265) ~[reactor-core-3.6.11.jar:3.6.11]
    at reactor.core.publisher.MonoIgnoreThen.subscribe(MonoIgnoreThen.java:51) ~[reactor-core-3.6.11.jar:3.6.11]
    at reactor.core.publisher.Mono.subscribe(Mono.java:4576) ~[reactor-core-3.6.11.jar:3.6.11]
    at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.subscribeNext(MonoIgnoreThen.java:265) ~[reactor-core-3.6.11.jar:3.6.11]
    at reactor.core.publisher.MonoIgnoreThen.subscribe(MonoIgnoreThen.java:51) ~[reactor-core-3.6.11.jar:3.6.11]
    at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:76) ~[reactor-core-3.6.11.jar:3.6.11]
    at reactor.core.publisher.MonoDeferContextual.subscribe(MonoDeferContextual.java:55) ~[reactor-core-3.6.11.jar:3.6.11]
    at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:76) ~[reactor-core-3.6.11.jar:3.6.11]
    at reactor.netty.http.server.HttpServer$HttpServerHandle.onStateChange(HttpServer.java:1344) ~[reactor-netty-http-1.3.1.jar:1.3.1]
    at reactor.netty.ReactorNetty$CompositeConnectionObserver.onStateChange(ReactorNetty.java:730) ~[reactor-netty-core-1.3.1.jar:1.3.1]
    at reactor.netty.transport.ServerTransport$ChildObserver.onStateChange(ServerTransport.java:489) ~[reactor-netty-core-1.3.1.jar:1.3.1]
    at reactor.netty.http.server.HttpServerOperations.handleDefaultHttpRequest(HttpServerOperations.java:863) ~[reactor-netty-http-1.3.1.jar:1.3.1]
    at reactor.netty.http.server.HttpServerOperations.onInboundNext(HttpServerOperations.java:789) ~[reactor-netty-http-1.3.1.jar:1.3.1]
    at reactor.netty.channel.ChannelOperationsHandler.channelRead(ChannelOperationsHandler.java:115) ~[reactor-netty-core-1.3.1.jar:1.3.1]
    at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:356) ~[netty-transport-4.2.9.Final.jar:4.2.9.Final]
    at reactor.netty.http.server.HttpTrafficHandler.channelRead(HttpTrafficHandler.java:283) ~[reactor-netty-http-1.3.1.jar:1.3.1]
    at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:354) ~[netty-transport-4.2.9.Final.jar:4.2.9.Final]
    at io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelRead(CombinedChannelDuplexHandler.java:434) ~[netty-transport-4.2.9.Final.jar:4.2.9.Final]
    at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:361) ~[netty-codec-base-4.2.9.Final.jar:4.2.9.Final]
    at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:325) ~[netty-codec-base-4.2.9.Final.jar:4.2.9.Final]
    at io.netty.channel.CombinedChannelDuplexHandler.channelRead(CombinedChannelDuplexHandler.java:249) ~[netty-transport-4.2.9.Final.jar:4.2.9.Final]
    at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:354) ~[netty-transport-4.2.9.Final.jar:4.2.9.Final]
    at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1429) ~[netty-transport-4.2.9.Final.jar:4.2.9.Final]
    at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:918) ~[netty-transport-4.2.9.Final.jar:4.2.9.Final]
    at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:172) ~[netty-transport-4.2.9.Final.jar:4.2.9.Final]
    at io.netty.channel.nio.AbstractNioChannel$AbstractNioUnsafe.handle(AbstractNioChannel.java:445) ~[netty-transport-4.2.9.Final.jar:4.2.9.Final]
    at io.netty.channel.nio.NioIoHandler$DefaultNioRegistration.handle(NioIoHandler.java:388) ~[netty-transport-4.2.9.Final.jar:4.2.9.Final]
    at io.netty.channel.nio.NioIoHandler.processSelectedKey(NioIoHandler.java:596) ~[netty-transport-4.2.9.Final.jar:4.2.9.Final]
    at io.netty.channel.nio.NioIoHandler.processSelectedKeysOptimized(NioIoHandler.java:571) ~[netty-transport-4.2.9.Final.jar:4.2.9.Final]
    at io.netty.channel.nio.NioIoHandler.processSelectedKeys(NioIoHandler.java:512) ~[netty-transport-4.2.9.Final.jar:4.2.9.Final]
    at io.netty.channel.nio.NioIoHandler.run(NioIoHandler.java:484) ~[netty-transport-4.2.9.Final.jar:4.2.9.Final]
    at io.netty.channel.SingleThreadIoEventLoop.runIo(SingleThreadIoEventLoop.java:225) ~[netty-transport-4.2.9.Final.jar:4.2.9.Final]
    at io.netty.channel.SingleThreadIoEventLoop.run(SingleThreadIoEventLoop.java:196) ~[netty-transport-4.2.9.Final.jar:4.2.9.Final]
    at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:1195) ~[netty-common-4.2.9.Final.jar:4.2.9.Final]
    at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) ~[netty-common-4.2.9.Final.jar:4.2.9.Final]
    at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) ~[netty-common-4.2.9.Final.jar:4.2.9.Final]
    at java.lang.Thread.run(Thread.java:1583) [?:?]

Expected behavior

The WebFlux instrumentation should work with Spring Framework 7 / Spring Boot 4, similar to the MVC support added in #4397.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions