Search code examples
javarsocket

What is the equivalent of @ExceptionHandler in RSocket world please?


Small question regarding how to have a "Controller" level @ExceptionHandler, but for RSocket, please.

A bit naive, I tried having a Controller level ExceptionHandler with the following in my RSocket application. (like in any other MVC/Webflux application)

    @ExceptionHandler
    public Mono<ResponseEntity<String>> exception(final Exception exception) {
        return Mono.just(ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(exception.getMessage()));
    }

And so far, I am not seeing this "catching" anything. As I keep seeing this strange error.

io.netty.util.IllegalReferenceCountException: refCnt: 0
    at io.rsocket.util.ByteBufPayload.ensureAccessible(ByteBufPayload.java:208) ~[rsocket-core-1.1.0.jar:na]
    at io.rsocket.util.ByteBufPayload.sliceData(ByteBufPayload.java:155) ~[rsocket-core-1.1.0.jar:na]
    at org.springframework.messaging.rsocket.PayloadUtils.retainDataAndReleasePayload(PayloadUtils.java:54) ~[spring-messaging-5.3.2.jar:5.3.2]
    at org.springframework.messaging.rsocket.annotation.support.MessagingRSocket.retainDataAndReleasePayload(MessagingRSocket.java:184) ~[spring-messaging-5.3.2.jar:5.3.2]
    at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onNext(FluxMapFuseable.java:113) ~[reactor-core-3.4.1.jar:3.4.1]

So I was wondering, am I doing it wrong, or maybe, RSocket does not support @ExceptionHandler and I need to go via another mechanism?

Thanks for the help.


Solution

  • I believe the equivalent is MessageExceptionHandler if the RSocket is running over websockets.

    WebSockets Exception handling

    Just like regular Spring MVC, we can handle exceptions as well. However, rather than using the @ExceptionHandler annotation, we now have to use the @MessageExceptionHandler annotation.


    So something like this would work:

    @MessageExceptionHandler
    public Mono<ResponseEntity<String>> exception(final Exception exception) 
    {
        return Mono.just(ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                                        .body(exception.getMessage()));
    }
    

    Note that RSocket is a protocol that works over WebSockets, but also with plain TCP, among others. In this specific case, seems like your RSocket is over WS, so @MessageExceptionHandler is the correct annotation (not for being rsocket, but for acting like a websocket). If running over TCP, you may have to use the old @ExceptionHandler.

    edit -- As Rossen's comment states, there's no such link between MessageExceptionHandler and the protocol in use, so just ignore the text above!.