Integrating Java WebSockets (JSR-356) with SpringBoot

1.5k Views Asked by At

I'm having an issue getting a websocket deployed in SpringBoot. I've tried quite a few approaches based on https://spring.io/blog/2013/05/23/spring-framework-4-0-m1-websocket-support, Using Java API for WebSocket (JSR-356) with Spring Boot, etc with out any luck.

Here is what I'm trying:

web socket:

@ServerEndpoint(value="/socket/{name}", configurator = SpringConfigurator.class)
public class TestSocket {

    public ApiSocket(){}

    @OnOpen
    public void onOpen(
                Session session,
                @PathParam("name") String name) throws IOException {

        session.getBasicRemote().sendText("Hi " + name);
    }
}

applications.properties:

server.contextPath=/api

Main class:

@SpringBootApplication
public class Main {

    public static void main(String[] args) throws Exception {
        SpringApplication.run(Main.class, args);
    }
}

According to the blog post above, this should be all that's required. I've also tried the second approach described which involves a bean with no luck:

  @Bean
  public ServerEndpointExporter endpointExporter() {
      return new ServerEndpointExporter();
  }

I am trying to open a connection to ws://localhost:8080/api/socket/John and expecting to receive a response back with the path name:

var socket = new WebSocket('ws://localhost:8080/api/socket/John');

The result is a 404 during the handshake.

1

There are 1 best solutions below

3
On

You have to add also the TestSocket in your Bean in Spring Configuration and remove configurator = SpringConfigurator.class from your TestSocket.

Generally Spring overrides the normal java JSR 356 websocket by it's STOMP protocol which is part of websocket. It also not support fully binary message as normal websocket . You should add ServerEndpointExporter in Configuration as:

@Configuration
public class EndpointConfig 
{
    @Bean
    public ChatEndpointNew chatEndpointNew(){
        return new ChatEndpointNew();
    }


    @Bean
    public ServerEndpointExporter endpointExporter(){
        return new ServerEndpointExporter();
    }

}

Let's see the complete chatMessage with the room in which the client ge's connected as:

@ServerEndpoint(value="/chatMessage/{room}")
public class ChatEndpointNew 
{

    private final Logger log = Logger.getLogger(getClass().getName());

    @OnOpen
    public void open(final Session session, @PathParam("room")final String room)
    {
        log.info("session openend and bound to room: " + room);
        session.getUserProperties().put("room", room);
        System.out.println("session openend and bound to room: " + room);
    }

    @OnMessage
    public void onMessage(final Session session, final String message) {
        String room = (String)session.getUserProperties().get("room");
        try{
            for (Session s : session.getOpenSessions()){
                if(s.isOpen()
                          && room.equals(s.getUserProperties().get("room"))){
                    String username = (String) session.getUserProperties().get("username");
                    if(username == null){
                        s.getUserProperties().put("username", message);
                        s.getBasicRemote().sendText(buildJsonData("System", "You are now connected as:"+message));
                    }else{
                        s.getBasicRemote().sendText(buildJsonData(username, message));      
                    }
                }
            }
        }catch(IOException e) {
            log.log(Level.WARNING, "on Text Transfer failed", e);
        }
    }

    @OnClose
    public void onClose(final Session session){
        String room = (String)session.getUserProperties().get("room");
        session.getUserProperties().remove("room",room);
        log.info("session close and removed from room: " + room);
    }

    private String buildJsonData(String username, String message) {
        JsonObject jsonObject = Json.createObjectBuilder().add("message", "<tr><td class='user label label-info'style='font-size:20px;'>"+username+"</td>"+"<td class='message badge' style='font-size:15px;'> "+message+"</td></tr>").build();
        StringWriter stringWriter = new StringWriter();
        try(JsonWriter jsonWriter = Json.createWriter(stringWriter)){
            jsonWriter.write(jsonObject);
        }

        return stringWriter.toString();
    }
}

Note That, You should add ChatEndpointNew and ServerEndpointExporter separately of your main Spring configuration of your Application. If any bug appear try this:

<dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-websocket</artifactId>
   <version>4.0.0.RELEASE</version>
</dependency>

You can also go through this Spring documentation.