Frame91 Frame91 - 3 months ago 37
reST (reStructuredText) Question

JAX RS and WebSockets with Stomp in Spring Boot conflict

I am using Spring-Boot. I would like to use JAX RS as my basic REST-API in combination with WebSockets (using Stomp). However, these two libraries seem to end up in a conflict.

I have the following WebSocketConfig:

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {

@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableSimpleBroker("/topic");
config.setApplicationDestinationPrefixes("/app");
}

@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/hello").setAllowedOrigins("http://localhost:8000").withSockJS();
}


and the following AppConfig:

public class AppConfig extends ResourceConfig {
public AppConfig() {
register(...);
}
}


The problem occurs, if both classes are commented in. If I comment out AppConfig, my socket-connection will connect without any problems. In the other cases, my REST-Api works but the WebSocket-Connection cannot be established (404 exception). I assume the problem lies in the Jax RS component which probably tries to 'consume' the /hello call and does not find a resource mapped to it.

My question is: How can I tell Jax RS to either ignore the /hello call, so that it gets passed through to the WebSocketMessageBroker or to get it working next to each other?

Answer

It's related to Spring-Boot Jersey: allow Jersey to serve static content. The default mapping for the Jersey servlet is /*, which hogs up all the requests. By default it will not forward any routes for which it can't find.

You have couple options:

  • Change the default mapping for the Jersey servlet. You can do that by either

    1. Adding an @ApplicationPath("/new-root") annotation on top of theResourceConfig` subclass.
    2. Or setting the mapping in the application.properties file, using the following property: spring.jersey.applicationPath
  • Make Jersey run as a servlet filter instead of a servlet. Doing this allows you to set a property with Jersey that will will allow it forward requested routes to the servlet container, that are not mapped in the Jersey application.

    You can see how to work this solution, in this post