I am getting below error while consuming message on rabbit mq through fanout approach :
2022-08-24 12:53:29.559 ERROR 42 --- [2.20.43.29:5672] o.s.a.r.c.CachingConnectionFactory : Channel shutdown: channel error; protocol method: #method<channel.close>(reply-code=406, reply-text=PRECONDITION_FAILED - inequivalent arg 'type' for exchange 'avitas.nodedata' in vhost 'avitas': received 'topic' but current is 'fanout', class-id=40, method-id=10)
I am using spring-boot-starter-webflux and spring-boot-starter-rsocket version 2.7.1
The rSocket transport is set to websocket like this:
spring.rsocket.server.transport=websocket
spring.rsocket.server.mapping-path=/rsocket
# this setting has no effect when transport==WEBSOCKET
spring.rsocket.server.port=7000
There's a spring #Controller endpoint #MessageMapping setup for a simple string like:
#MessageMapping("test")
String test() {
Logs.Info("*** Received test ***");
return "tested";
}
I want to get a successful test done with Postman. Run the spring boot app locally and connect to ws://localhost:7000 using mime types
dataMimeType: 'application/json'
metadataMimeType: 'message/x.rsocket.routing.v0'
Like this:
The rsocket websocket connects, but I can't hit the endpoint test
With error 1005 No Status Received: Missing status code even though one was expected
On the server the error is
DEBUG [reactor-http-nio-2] debug: [c4e97d34-1, L:/127.0.0.1:7000 - R:/127.0.0.1:2051] Cancelling Websocket inbound. Closing Websocket
DEBUG [reactor-http-nio-2] debug: [c4e97d34, L:/127.0.0.1:7000 - R:/127.0.0.1:2051] Removed handler: PongHandler, pipeline: DefaultChannelPipeline{(wsencoder = io.netty.handler.codec.http.websocketx.WebSocket13FrameEncoder), (wsdecoder = io.netty.handler.codec.http.websocketx.WebSocket13FrameDecoder), (reactor.right.reactiveBridge = reactor.netty.channel.ChannelOperationsHandler)}
DEBUG [reactor-http-nio-2] debug: [c4e97d34, L:/127.0.0.1:7000 ! R:/127.0.0.1:2051] An outbound error could not be processed
java.nio.channels.ClosedChannelException
at reactor.core.publisher.MonoErrorSupplied.call(MonoErrorSupplied.java:61)
at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.subscribeNext(MonoIgnoreThen.java:228)
at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.onComplete(MonoIgnoreThen.java:203)
at reactor.core.publisher.SinkEmptyMulticast$VoidInner.complete(SinkEmptyMulticast.java:238)
at reactor.core.publisher.SinkEmptyMulticast.tryEmitEmpty(SinkEmptyMulticast.java:70)
at reactor.core.publisher.SinkEmptySerialized.tryEmitEmpty(SinkEmptySerialized.java:46)
What's the incorrect setting in Postman?
The answer is don't use postman. Rsocket is a binary protocol, Even though based on Websocket, There are many tools test it.
use spring message write a unit test
#Autowired
private RSocketRequester rSocketRequester;
StepVerifier.create(rSocketRequester
.route("test")
.retrieveMono(String.class))
.expectNext("tested")
.verifyComplete();
RSocket Client CLI (RSC)
rsc --request --route=test --debug ws://localhost:7000/rsocket
Actually the following message was received:
{
"data":"test",
"metadata":4
}
Per screenshot
But now the error on the server side is:
DEBUG [reactor-http-nio-6] lambda$receive$0: receiving ->
Frame => Stream ID: 2064452128 Type: REQUEST_N Flags: 0b100000 Length: 42
RequestN: 539124833
Data:
DEBUG [reactor-http-nio-6] sendErrorAndClose: sending -> InvalidSetupException: SETUP or RESUME frame must be received before any others
Use Eclipse IDE in an attempt to create a java websocket client for an OpenHab project, thus using default Jetty websocket library. The OpenHab project intend to connect to a websocket endpoint requiring token authorization, send a request message and retrieve live/continuous measurements.
So, I have
public static final String SUBSCRIPTION_URL = "wss://api.tibber.com/v1-beta/gql/subscriptions";
Further, my WS open code:
public void open() throws Exception {
if (isConnected()) {
logger.warn("Open: connection is already open");
}
logger.warn("Connecting to: {}", SUBSCRIPTION_URL);
sslContextFactory = new SslContextFactory(true);
sslContextFactory.setTrustAll(true);
client = new WebSocketClient(sslContextFactory);
client.setMaxIdleTimeout(360 * 1000);
TibberWebSocketListener socket = new TibberWebSocketListener();
request = new ClientUpgradeRequest();
String token = new StringBuilder("Bearer ").append(configuration.getToken()).toString();
request.setHeader("Authorization", token);
request.setSubProtocols("graphql-subscriptions");
client.start();
client.connect(socket, new URI(SUBSCRIPTION_URL), request);
}
However, with this code it seems like I get connected, but end up with an IOException: Broken pipe after 1 minute. I get the same error both if I just connect without message / connect with send message.
13:59:15.987 [safeCall-1] WARN o.o.b.t.i.handler.TibberHandler:346 - Connecting to: wss://api.tibber.com/v1-beta/gql/subscriptions
13:59:16.390 [#1379116703-141] WARN o.o.b.t.i.handler.TibberHandler:385 - Connected to Server
14:00:16.430 [#1379116703-142] WARN o.o.b.t.i.handler.TibberHandler:392 - Closing a WebSocket due to Disconnected
14:00:16.434 [#1379116703-139] WARN o.o.b.t.i.handler.TibberHandler:399 - Error during websocket communication: Broken pipe
java.io.IOException: Broken pipe
at org.eclipse.jetty.io.ssl.SslConnection$DecryptedEndPoint.flush(SslConnection.java:928)
at org.eclipse.jetty.io.WriteFlusher.flush(WriteFlusher.java:422)
at org.eclipse.jetty.io.WriteFlusher.write(WriteFlusher.java:277)
at org.eclipse.jetty.io.AbstractEndPoint.write(AbstractEndPoint.java:381)
at org.eclipse.jetty.websocket.common.io.FrameFlusher.flush(FrameFlusher.java:264)
at org.eclipse.jetty.websocket.common.io.FrameFlusher.process(FrameFlusher.java:193)
at org.eclipse.jetty.util.IteratingCallback.processing(IteratingCallback.java:241)
at org.eclipse.jetty.util.IteratingCallback.iterate(IteratingCallback.java:223)
at org.eclipse.jetty.websocket.common.io.AbstractWebSocketConnection.outgoingFrame(AbstractWebSocketConnection.java:516)
at org.eclipse.jetty.websocket.client.io.WebSocketClientConnection.outgoingFrame(WebSocketClientConnection.java:72)
at org.eclipse.jetty.websocket.common.io.AbstractWebSocketConnection.close(AbstractWebSocketConnection.java:184)
at org.eclipse.jetty.websocket.common.io.AbstractWebSocketConnection.onFillable(AbstractWebSocketConnection.java:458)
at org.eclipse.jetty.websocket.common.io.AbstractWebSocketConnection.onFillable(AbstractWebSocketConnection.java:428)
at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:311)
at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:103)
at org.eclipse.jetty.io.ssl.SslConnection$DecryptedEndPoint.onFillable(SslConnection.java:426)
at org.eclipse.jetty.io.ssl.SslConnection.onFillable(SslConnection.java:320)
at org.eclipse.jetty.io.ssl.SslConnection$2.succeeded(SslConnection.java:158)
at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:103)
at org.eclipse.jetty.io.ChannelEndPoint$2.run(ChannelEndPoint.java:117)
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.runTask(EatWhatYouKill.java:336)
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.doProduce(EatWhatYouKill.java:313)
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.tryProduce(EatWhatYouKill.java:171)
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.run(EatWhatYouKill.java:129)
at org.eclipse.jetty.util.thread.ReservedThreadExecutor$ReservedThread.run(ReservedThreadExecutor.java:367)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:782)
at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.run(QueuedThreadPool.java:918)
at java.lang.Thread.run(Thread.java:748)
14:00:16.435 [#1379116703-139] WARN o.o.b.t.i.handler.TibberHandler:392 - Closing a WebSocket due to Broken pipe
java.io.IOException: Broken pipe
That means the OS or network below Java (and Jetty) detected that the connection was closed.
"Broken Pipe" is actually fairly common, especially with mobile devices or wireless networking.
Not much Java or Jetty can do about it either, it happened outside of its control.
In my application, a user can restart a video from the beginning after it has ended.
To implement this, I have overridden in the custom receiver the receiver library MediaManager.onEnded() method, and send a custom message to the sender, rather than calling resetMediaElement, which is the default behavior of this method.
At this point, the user hits a play button, and the sender calls the RemoteMediaPlayer.play() method, which should cause the receiver library to call the play() method on the <video> element.
But instead, the receiver library sends back a message saying INVALID REQUEST, INVALID_MEDIA_SESSSION_ID.
Also. the receiver library has logged a message saying "
Unexpected command, player is in the IDLE state so the media session ID is not yet valid
But the last state update from the receiver shows the player in the PLAYING state in both the receiver and sender logs.
Here is the receiver log:
::mmOnLoad() mediacast.js:480
url: http://192.168.1.50/apps/chromecast/videos/Inside%20Diamond%20Head-0001.mp4 mediacast.js:498
duration: 0 mediacast.js:500
::showVideo()- message:[object Object] mediacast.js:257
url:http://192.168.1.50/apps/chromecast/videos/Inside%20Diamond%20Head-0001.mp4 mediacast.js:259
::fadeOutOldMediaElement() mediacast.js:384
::mmOnLoad()- presenting video from http://192.168.1.50/apps/chromecast/videos/Inside%20Diamond%20Head-0001.mp4, duration 0 mediacast.js:552
::fadeOutOldMediaElement0() mediacast.js:393
::videoFadedOut()- url: http://192.168.1.50/apps/chromecast/videos/Inside%20Diamond%20Head-0001.mp4 mediacast.js:265
::videoFadedOut()- setting media element [object HTMLVideoElement] mediacast.js:279
::removeMediaElementOrOverlay() mediacast.js:398
::removeOldMediaElement() mediacast.js:432
::removeOverlay() mediacast.js:427
[ 40.701s] [cast.receiver.MediaManager] Metadata loaded
cast_receiver.javascript:574
[ 40.736s] [cast.receiver.MediaManager] Sending broadcast status message
cast_receiver.javascript:574
>>>>>the media element state is paused mediacast.js:603
media element networkState = 2, readyState = 1 mediacast.js:605
[ 40.802s] [cast.receiver.IpcChannel] IPC message sent: {"namespace":"urn:x-cast:com.google.cast.media","senderId":"*:*","data":"{\"type\":\"MEDIA_STATUS\",\"status\":[{\"mediaSessionId\":1,\"playbackRate\":1,\"playerState\":\"PAUSED\",\"currentTime\":0,\"supportedMediaCommands\":15,\"volume\":{\"level\":0.06666666666666667,\"muted\":false},\"media\":{\"customData\":{\"volume\":0.06666666666666667,\"pauseAfter\":true,\"pauseBefore\":true,\"rotation\":0},\"streamType\":\"BUFFERED\",\"duration\":42.4,\"contentType\":\"video/mp4\",\"contentId\":\"http://192.168.1.50/apps/chromecast/videos/Inside%20Diamond%20Head-0001.mp4\",\"metadata\":{\"metadataType\":1}}}],\"requestId\":1}"}
cast_receiver.javascript:574
::videoLoaded() mediacast.js:291
::videoLoaded0() mediacast.js:302
::addVideo() mediacast.js:421
::videoLoaded1() mediacast.js:309
[ 48.434s] [cast.receiver.IpcChannel] Received message: {"data":"{\"type\":\"PLAY\",\"requestId\":2,\"mediaSessionId\":1}","namespace":"urn:x-cast:com.google.cast.media","senderId":"51:name.renkel.james.mediacast-6"}
cast_receiver.javascript:574
[ 48.440s] [cast.receiver.CastMessageBus] Dispatching CastMessageBus message [urn:x-cast:com.google.cast.media, 51:name.renkel.james.mediacast-6]: {"type":"PLAY","requestId":2,"mediaSessionId":1}
cast_receiver.javascript:574
[ 48.446s] [cast.receiver.MediaManager] MediaManager message received [51:name.renkel.james.mediacast-6] {"type":"PLAY","requestId":2,"mediaSessionId":1}
cast_receiver.javascript:574
[ 48.449s] [cast.receiver.MediaManager] Dispatching MediaManager play event
cast_receiver.javascript:574
[ 48.457s] [cast.receiver.MediaManager] onPlay
cast_receiver.javascript:574
[ 48.473s] [cast.receiver.MediaManager] Sending broadcast status message
cast_receiver.javascript:574
>>>>>the media element state is buffering mediacast.js:603
media element networkState = 1, readyState = 4 mediacast.js:605
[ 48.491s] [cast.receiver.IpcChannel] IPC message sent: {"namespace":"urn:x-cast:com.google.cast.media","senderId":"*:*","data":"{\"type\":\"MEDIA_STATUS\",\"status\":[{\"mediaSessionId\":1,\"playbackRate\":1,\"playerState\":\"BUFFERING\",\"currentTime\":0.033322,\"supportedMediaCommands\":15,\"volume\":{\"level\":0.06666666666666667,\"muted\":false}}],\"requestId\":2}"}
cast_receiver.javascript:574
[ 49.071s] [cast.receiver.MediaManager] Buffering state changed, isPlayerBuffering: false old time: 0.033322 current time: 0.433322
cast_receiver.javascript:574
[ 49.077s] [cast.receiver.MediaManager] Sending broadcast status message
cast_receiver.javascript:574
>>>>>the media element state is playing mediacast.js:603
media element networkState = 2, readyState = 4 mediacast.js:605
[ 49.090s] [cast.receiver.IpcChannel] IPC message sent: {"namespace":"urn:x-cast:com.google.cast.media","senderId":"*:*","data":"{\"type\":\"MEDIA_STATUS\",\"status\":[{\"mediaSessionId\":1,\"playbackRate\":1,\"playerState\":\"PLAYING\",\"currentTime\":0.433322,\"supportedMediaCommands\":15,\"volume\":{\"level\":0.06666666666666667,\"muted\":false}}],\"requestId\":0}"}
cast_receiver.javascript:574
::onEnded(VIDEO) mediacast.js:369
::onEnded- network state:1 mediacast.js:370
::onEnded- ready state:4 mediacast.js:371
::onEnded- paused:true mediacast.js:372
::onEnded- ended:true mediacast.js:373
::sendMessage({"indication":"ended"}) mediacast.js:108
[ 90.955s] [cast.receiver.IpcChannel] IPC message sent: {"namespace":"urn:x-cast:name.renkel.james.mediacast","senderId":"51:name.renkel.james.mediacast-6","data":"{\"indication\":\"ended\"}"}
cast_receiver.javascript:574
[110.341s] [cast.receiver.IpcChannel] Received message: {"data":"{\"type\":\"PLAY\",\"requestId\":3,\"mediaSessionId\":1}","namespace":"urn:x-cast:com.google.cast.media","senderId":"51:name.renkel.james.mediacast-6"}
cast_receiver.javascript:574
[110.350s] [cast.receiver.CastMessageBus] Dispatching CastMessageBus message [urn:x-cast:com.google.cast.media, 51:name.renkel.james.mediacast-6]: {"type":"PLAY","requestId":3,"mediaSessionId":1}
cast_receiver.javascript:574
[110.358s] [cast.receiver.MediaManager] Unexpected command, player is in IDLE state so the media session ID is not valid yet
cast_receiver.javascript:574ib cast_receiver.javascript:574gb.Gb cast_receiver.javascript:562B.log cast_receiver.javascript:361E cast_receiver.javascript:412Z.M cast_receiver.javascript:1654W.ra cast_receiver.javascript:1181Hb cast_receiver.javascript:885g.dispatchEvent cast_receiver.javascript:856g.M cast_receiver.javascript:1104Hb cast_receiver.javascript:885g.dispatchEvent cast_receiver.javascript:856g.M cast_receiver.javascript:968
[110.362s] [cast.receiver.MediaManager] Sending error message to 51:name.renkel.james.mediacast-6
cast_receiver.javascript:574
[110.368s] [cast.receiver.IpcChannel] IPC message sent: {"namespace":"urn:x-cast:com.google.cast.media","senderId":"51:name.renkel.james.mediacast-6","data":"{\"requestId\":3,\"type\":\"INVALID_REQUEST\",\"reason\":\"INVALID_MEDIA_SESSION_ID\"}"}
cast_receiver.javascript:574
And here is the sender log:
11-10 13:36:36.631: D/MC_Sender(15051): ::showVideo()- url: http://192.168.1.50/apps/chromecast/videos/Inside%20Diamond%20Head-0001.mp4 11-10 13:36:36.732: D/MC_MainActivity.PagerAdapter(15051): ::setPrimaryItem(0)
11-10 13:36:36.732: D/MC_MainActivity(15051): ::setContentPosition(0)
11-10 13:36:40.325: D/MC_MediaPlayer(15051): ::onMessageReceived(): device-TV Room; namespace-urn:x-cast:com.google.cast.media; message-{"type":"MEDIA_STATUS","status":[{"mediaSessionId":2,"playbackRate":1,"playerState":"PAUSED","currentTime":0,"supportedMediaCommands":15,"volume":{"level":0.06666666666666667,"muted":false},"media":{"customData":{"volume":0.06666666666666667,"pauseAfter":true,"pauseBefore":true,"rotation":0},"streamType":"BUFFERED","duration":42.4,"contentType":"video/mp4","contentId":"http://192.168.1.50/apps/chromecast/videos/Inside%20Diamond%20Head-0001.mp4","metadata":{"metadataType":1}}}],"requestId":4}
11-10 13:36:40.375: D/MC_Listeners(15051): ::onStatusUpdated()- playerState=PAUSED
11-10 13:36:40.426: D/MC_Runner(15051): ::onSenderStateChange(PAUSED)- runState=LOADING
11-10 13:36:40.426: D/MC_Runner(15051): ::setRunState(RUNNING)- stopWhenRunning=false
11-10 13:36:40.426: D/MC_CastFragment(15051): ::runnerUpdate()
11-10 13:36:40.456: D/MC_Listeners(15051): ::onStatusUpdated()- playerState=PAUSED
11-10 13:36:40.456: D/MC_Listeners(15051): ::onMetadataUpdated()- mediaType=MOVIE
11-10 13:36:40.516: D/MC_MainActivity.PagerAdapter(15051): ::setPrimaryItem(0)
11-10 13:36:40.516: D/MC_MainActivity(15051): ::setContentPosition(0)
11-10 13:36:40.806: D/MC_Sender(15051): ::loadMedia()- statusCode: 0; success: true
11-10 13:36:40.806: D/MC_Runner(15051): LoadCallback::callback(true): wasStopped=false
...
11-10 13:38:47.201: D/MC_Sender(15051): ::playMedia()
11-10 13:38:47.391: D/MC_MediaPlayer(15051): ::onMessageReceived(): device-TV Room; namespace-urn:x-cast:com.google.cast.media; message-{"type":"MEDIA_STATUS","status":[{"mediaSessionId":1,"playbackRate":1,"playerState":"BUFFERING","currentTime":0.033322,"supportedMediaCommands":15,"volume":{"level":0.06666666666666667,"muted":false}}],"requestId":2}
11-10 13:38:47.411: D/MC_Listeners(15051): ::onStatusUpdated()- playerState=BUFFERING
11-10 13:38:47.531: D/MC_Runner(15051): ::onSenderStateChange(BUFFERING)- runState=RUNNING
11-10 13:38:47.671: D/MC_MainActivity.PagerAdapter(15051): ::setPrimaryItem(0)
11-10 13:38:47.671: D/MC_MainActivity(15051): ::setContentPosition(0)
11-10 13:38:48.372: D/MC_Sender(15051): ::playMedia()- statusCode: 0; success: true
11-10 13:38:48.382: D/MC_MediaPlayer(15051): ::onMessageReceived(): device-TV Room; namespace-urn:x-cast:com.google.cast.media; message-{"type":"MEDIA_STATUS","status":[{"mediaSessionId":1,"playbackRate":1,"playerState":"PLAYING","currentTime":0.6,"supportedMediaCommands":15,"volume":{"level":0.06666666666666667,"muted":false}}],"requestId":0}
...
11-10 13:39:29.736: D/MC_Listeners(15051): ::onMessageReceived()- nameSpace: urn:x-cast:name.renkel.james.mediacast; message: {"indication":"ended"}
11-10 13:39:29.806: D/MC_Runner(15051): ::onSenderStateChange(ENDED)- runState=RUNNING
...
11-10 13:42:19.918: D/MC_CastFragment(15051): ::onClick()
11-10 13:42:19.918: D/MC_Sender(15051): ::playMedia()
11-10 13:42:20.398: D/MC_MediaPlayer(15051): ::onMessageReceived(): device-TV Room; namespace-urn:x-cast:com.google.cast.media; message-{"requestId":3,"type":"INVALID_REQUEST","reason":"INVALID_MEDIA_SESSION_ID"}
11-10 13:42:20.418: D/MC_Sender(15051): ::playMedia()- statusCode: 1; success: false
I believe that once the video ends, it goes to an IDLE state whether resetMediaElement is called or not. There's different reasons why the status might be IDLE that you can specify: https://developers.google.com/cast/docs/reference/receiver/cast.receiver.media.IdleReason.
It's a bit roundabout, but based on the methods listed at https://developers.google.com/cast/docs/reference/receiver/cast.receiver.MediaManager, you could:
1) check if the video successfully finished playing
2) set the idle reason as cast.receiver.media.IdleReason.FINISHED
Then, in your sender, you can override customizedStatusCallback() to check the status and idle reason and change the status before sending it to your sender so that it can replay correctly.