question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Error sending STOMP message via websocket

See original GitHub issue

While upgrading from Spring Boot 2.0.5 to 2.1.1, I encountered a problem in a service which sends STOMP messages via a web socket. I have isolated the problem and created an example project:

https://github.com/purple52/websocket-sleuth-test

If you build that project and run the test using ./gradlew clean build --info, it’ll fail with this error:

2019-01-17 10:01:14.876 ERROR [websocket-sleuth-test,86b7bbc97c2ae296,14d3361a3e31673e,false] 6022 --- [    Test worker] o.s.m.s.b.SimpleBrokerMessageHandler     : Failed to send GenericMessage [payload=byte[16], headers={spanTraceId=86b7bbc97c2ae296, spanId=86b7bbc97c2ae296, simpMessageType=MESSAGE, nativeHeaders={spanTraceId=[86b7bbc97c2ae296], spanId=[86b7bbc97c2ae296], spanSampled=[0]}, spanSampled=0, contentType=application/json;charset=UTF-8, simpDestination=/topic/foo}]
2019-01-17 10:01:14.877 ERROR [websocket-sleuth-test,86b7bbc97c2ae296,86b7bbc97c2ae296,false] 6022 --- [    Test worker] o.s.m.s.ExecutorSubscribableChannel      : Exception from afterMessageHandled in org.springframework.cloud.sleuth.instrument.messaging.TracingChannelInterceptor@3d415f8

I am not 100% sure this is a Cloud Sleuth defect, or whether it’s Spring Messaging at fault, but I’m starting by reporting it here, since my test passes if I remove Cloud Sleuth from the project. This is using version 2.0.2-RELEASE of Cloud Sleuth, but still happens if I override and use 2.1.0-RC3.

What appears to happen is that TracingChannelInterceptor tries to remove the trace headers by calling NativeMessageHeaderAccessor.removeNativeHeader which checks that the headers are mutable, then tries to remove the native header. However, although the accessor says it is mutable, the native headers are returned in an unmodifiable map which throws an UnsupportedOperationException when the attempt is made to remove the headers.

You can see the full exception thrown with a breakpoint at AbstractMessageChannel.java#L142. Here’s the stacktrace:

java.lang.UnsupportedOperationException
	at java.util.Collections$UnmodifiableMap.remove(Collections.java:1460)
	at org.springframework.messaging.support.NativeMessageHeaderAccessor.removeNativeHeader(NativeMessageHeaderAccessor.java:209)
	at org.springframework.cloud.sleuth.instrument.messaging.MessageHeaderPropagation.removeAnyTraceHeaders(MessageHeaderPropagation.java:158)
	at org.springframework.cloud.sleuth.instrument.messaging.TracingChannelInterceptor.preSend(TracingChannelInterceptor.java:135)
	at org.springframework.messaging.support.AbstractMessageChannel$ChannelInterceptorChain.applyPreSend(AbstractMessageChannel.java:178)
	at org.springframework.messaging.support.AbstractMessageChannel.send(AbstractMessageChannel.java:132)
	at org.springframework.messaging.support.AbstractMessageChannel.send(AbstractMessageChannel.java:122)
	at org.springframework.messaging.simp.broker.SimpleBrokerMessageHandler.lambda$sendMessageToSubscribers$0(SimpleBrokerMessageHandler.java:401)
	at java.util.Map.forEach(Map.java:630)
	at org.springframework.messaging.simp.broker.SimpleBrokerMessageHandler.sendMessageToSubscribers(SimpleBrokerMessageHandler.java:388)
	at org.springframework.messaging.simp.broker.SimpleBrokerMessageHandler.handleMessageInternal(SimpleBrokerMessageHandler.java:304)
	at org.springframework.messaging.simp.broker.AbstractBrokerMessageHandler.handleMessage(AbstractBrokerMessageHandler.java:256)
	at org.springframework.messaging.support.ExecutorSubscribableChannel$SendTask.run(ExecutorSubscribableChannel.java:144)
	at org.springframework.messaging.support.ExecutorSubscribableChannel.sendInternal(ExecutorSubscribableChannel.java:100)
	at org.springframework.messaging.support.AbstractMessageChannel.send(AbstractMessageChannel.java:136)
	at org.springframework.messaging.support.AbstractMessageChannel.send(AbstractMessageChannel.java:122)
	at org.springframework.messaging.simp.SimpMessagingTemplate.sendInternal(SimpMessagingTemplate.java:187)
	at org.springframework.messaging.simp.SimpMessagingTemplate.doSend(SimpMessagingTemplate.java:162)
	at org.springframework.messaging.simp.SimpMessagingTemplate.doSend(SimpMessagingTemplate.java:48)
	at org.springframework.messaging.core.AbstractMessageSendingTemplate.send(AbstractMessageSendingTemplate.java:109)
	at org.springframework.messaging.core.AbstractMessageSendingTemplate.convertAndSend(AbstractMessageSendingTemplate.java:151)
	at org.springframework.messaging.core.AbstractMessageSendingTemplate.convertAndSend(AbstractMessageSendingTemplate.java:129)
	at org.springframework.messaging.core.AbstractMessageSendingTemplate.convertAndSend(AbstractMessageSendingTemplate.java:122)
	at com.example.WebsocketTest.Can pass message via websocket(WebsocketTest.kt:69)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
	at org.springframework.test.context.junit4.statements.RunBeforeTestExecutionCallbacks.evaluate(RunBeforeTestExecutionCallbacks.java:74)
	at org.springframework.test.context.junit4.statements.RunAfterTestExecutionCallbacks.evaluate(RunAfterTestExecutionCallbacks.java:84)
	at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
	at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
	at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:251)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:97)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
	at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
	at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:190)
	at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
	at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
	at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
	at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
	at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Comments:24 (7 by maintainers)

github_iconTop GitHub Comments

7reactions
marcingrzejszczakcommented, Apr 2, 2019

I’m working on this as we speak. The workaround is to disable Sleuth’s websocket messaging support via spring.sleuth.integration.websockets.enabled=false

0reactions
rstoyanchevcommented, Dec 13, 2020
Read more comments on GitHub >

github_iconTop Results From Across the Web

Send STOMP ERROR from Spring Websocket program
You can send ERROR Message like this: StompHeaderAccessor headerAccessor = StompHeaderAccessor.create(StompCommand.ERROR); headerAccessor.
Read more >
Sending STOMP messages over a WebSocket in Spring Boot 2
In this blog, we will have a look at how to set up an application to send and receive STOMP messages over a...
Read more >
Using Spring Boot for WebSocket Implementation with STOMP
The communication starts with SockJS sending GET /info to obtain basic information from the server. Basing on the response, SockJS decides on the...
Read more >
StompSubProtocolErrorHandler (Spring Framework 6.0.2 API)
Handle errors thrown while processing client messages providing an opportunity to prepare the error message or to prevent one from being sent.
Read more >
WebSocket: error event - Web APIs | MDN
The error event is fired when a connection with a WebSocket has been closed due to an error (some data couldn't be sent...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found