5

Finally I have my websocket client connecting to the endpoint but I can't extract message payload. I can get headers but payload is not recognized.

My WebSocket client looks like below:

    WebSocketTransport webSocketTransport = new WebSocketTransport(standardWebSocketClient);
    SockJsClient sockJsClient = new SockJsClient(Arrays.asList(webSocketTransport));
    WebSocketStompClient stompClient = new WebSocketStompClient(sockJsClient);

    stompClient.setMessageConverter(new StringMessageConverter());

    StompSessionHandler sessionHandler = new MyStompSessionHandler();
    ListenableFuture<StompSession> connect = stompClient.connect(URL, sessionHandler);

        StompSession stompSession = connect.get();
        System.out.println("sessionId: " + stompSession.getSessionId());

        String path = "/queue/orders";

        stompSession.subscribe(path, new MySimpleStompFrameHandler());

Stomp Frame Handler:

    private class MySimpleStompFrameHandler implements StompFrameHandler {

    @Override
    public Type getPayloadType(StompHeaders stompHeaders) {
        System.out.println("Headers " + stompHeaders.toString());
        return String.class;
    }

    @Override
    public void handleFrame(StompHeaders stompHeaders, Object payload) {
        System.out.println("Msg " + payload.toString());
        completableFuture.complete(payload.toString());
    }
}

I have headers written in the terminal but there is nothing from handleFrame method. Any idea ?

Edited: After debugging i see that the problem is in DefaultStompSession class which uses my implementation of frameHandler

    private void invokeHandler(StompFrameHandler handler, Message<byte[]> message, StompHeaders stompHeaders) {
    if (message.getPayload().length == 0) {
        handler.handleFrame(stompHeaders, null);
        return;
    }
    Type type = handler.getPayloadType(stompHeaders);
    Class<?> payloadType = ResolvableType.forType(type).resolve();
    Object object = getMessageConverter().fromMessage(message, payloadType);
    if (object == null) {
        throw new MessageConversionException("No suitable converter, payloadType=" + payloadType +
                ", handlerType=" + handler.getClass());
    }
    handler.handleFrame(stompHeaders, object);
}

Problem is after this line Type type = handler.getPayloadType(stompHeaders); After that nothing more is executed and my program just ends so handleFrame() is not even executed. What is wrong there ? Maybe with Type returned from getPayloadType - I choose String because I think every message can be presented as string.

kris82pl
  • 977
  • 3
  • 12
  • 21

4 Answers4

8

I had a similar issue.

The problem was that I had specified stompClient.setMessageConverter(new StringMessageConverter());, while a JSON was passed as payload.

Solution (for my issue): stompClient.setMessageConverter(new MappingJackson2MessageConverter());

What you can do to find a solution:

  • Throw (or log) when an exception is triggered. For your case, you should add an override for the following method in MyStompSessionHandler:

     @Override
     public void handleException(StompSession session, StompCommand command, StompHeaders headers, byte[] payload, Throwable exception) {
         throw new RuntimeException("Failure in WebSocket handling", exception);
     }
    
  • While debugging invokeHandler, check the content of the payload. If you are able to execute the code, you can do this by executing new String((byte[]) message.getPayload()).

user969039
  • 511
  • 2
  • 7
  • 18
  • you saved my day, i used this line new String((byte[]) message.getPayload()) and i was able to do my custom implementation, thanks – Jairo Cordero Sep 04 '19 at 15:16
0

I got your point you need to extend StompSessionHandlerAdapter implement StompFrameHandler.

I tried something for you :

public class MySimpleStompFrameHandler extends StompSessionHandlerAdapter implements StompFrameHandler {

private Logger logger = LogManager.getLogger(MyStompSessionHandler.class);

@Override
public void afterConnected(StompSession session, StompHeaders connectedHeaders) {
    System.out.println("Connected");
}

@Override
public void handleException(StompSession session, StompCommand command, StompHeaders 
 headers, byte[] payload, Throwable exception) {
    logger.error("Got an exception", exception);
}

@Override
public Type getPayloadType(StompHeaders headers) {
    return <payload_type>.class;
}

@Override
public void handleFrame(StompHeaders headers, Object payload) {
    <payload_type> msg = (<payload_type>) payload;
    System.out.println(msg);
    logger.info("Received : " + msg);
}

}

Where payload_type is your user-defined class which you want to convert stream data

Good to go !!

I'm_Pratik
  • 541
  • 8
  • 22
0

I share my implementation, hope to be usefull. I didn't set a messageconverter and did my custom implementation of method handleFrame

    WebSocketClient client = new StandardWebSocketClient();
    WebSocketStompClient stompClient = new WebSocketStompClient(client);
    StompSessionHandler sessionHandler = new MyStompSessionHandler(prop);
    WebSocketHttpHeaders webSocketHttpHeaders = new WebSocketHttpHeaders();
    webSocketHttpHeaders.add("Authorization", "Bearer " + token);

    StompSession session = stompClient.connect(endpoint, webSocketHttpHeaders, sessionHandler).get();

and then handling the message sent, in my case a JSON String Object

    @Override
    public Type getPayloadType(StompHeaders headers) {
        return null;
    }

    @Override
    public void handleFrame(StompHeaders headers, Object payload) {
        String cadena = new String((byte[]) payload);
        JsonParser parser = new JsonParser();
        JsonObject obj = parser.parse(cadena).getAsJsonObject();
        System.out.println(obj.toString());
    }   
Jairo Cordero
  • 640
  • 6
  • 8
0

It's need define MessageConverter and then implement method getPayloadType with object type JSON

SockJsClient sockJsClient = new SockJsClient(transports);
WebSocketStompClient stompClient = new WebSocketStompClient(sockJsClient);
stompClient.setMessageConverter(**new MappingJackson2MessageConverter()**);

....

public class SockJsWebsocketSubscriptionHandler implements StompFrameHandler {
    @Override
    public Type getPayloadType(StompHeaders headers) {
        return **HelloMessage.class;**
    }
...
}