Search code examples
angularspringwebsocketstompsockjs

Angular 7 + Java Spring - Websocket returning 404


I am trying to use Spring 4 Websocket and Angular 7 through @stomp/stompjs and SockJS library, however it keeps returning 404 not found, and connection to websocket keeps closing as a result.

My configuration code at Spring:

import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.web.socket.config.annotation.AbstractWebSocketMessageBrokerConfigurer;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;

@Configuration
@EnableWebSocketMessageBroker
public class SocketConfig extends AbstractWebSocketMessageBrokerConfigurer {

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint("/batch-socket").withSockJS();
    }

    @Override
    public void configureMessageBroker(MessageBrokerRegistry registry) {
        registry.enableSimpleBroker("/socketio/");
    }   
} 

SocketHandlerService.java to send a message template

@Service
public class SocketHandlerService  extends AbsLogger<SocketHandlerService> implements ApplicationListener<BrokerAvailabilityEvent> {

   private final MessageSendingOperations<String> messagingTemplate;

   @Autowired
   public SocketHandlerService(MessageSendingOperations<String> messagingTemplate) {
       this.messagingTemplate = messagingTemplate;      
   }

   public SocketDetails sendRestMessage() {
         ...some code...
                        this.messagingTemplate.convertAndSend("/socketio/batchupdate", data);
         ...some code...            
     } 
   }

Angular socket.service.ts to handle websockets at client side

  init() {
    let connectionUrl = this.baseUrl + "batch-socket";

    return new Promise((resolve, reject) => {
        let config = new StompConfig();
        config.heartbeatOutgoing = 5000;
        config.heartbeatIncoming = 5000;
        config.webSocketFactory = function () {
          return new SockJS(connectionUrl, null, { transports: ['websocket' , 'xhr-streaming','xhr-polling' ] });
        }
        config.debug = function (str) {
          console.log("@socketDebug: " + str)
        }
      this.client = new Client();
      this.client.configure(config);

      enableLogs && console.log(this.client);
      console.log("@socketSvc: starting connection...");

      const _this = this;
      this.client.onConnect = function (frame) {
        console.log("@socketSvc: connection established.");
        console.log(frame);
        _this.state = new BehaviorSubject<any>(SocketClientState.ATTEMPTING);
        _this.state.next(SocketClientState.CONNECTED);
        resolve(frame.headers['user-name']);
      }

      this.client.onWebSocketClose = function (msg){
        console.log("@socketSvc: connection closed.");
        console.log(msg);
      }

      this.client.activate();
    });

  }

I have checked that the endpoint urls match and that the domain for both server and client that is using is the same as well. However when deployed the following console output appears:

POST https://exampleWebsite.com/Portal/batch-socket/718/ky4ln33y/xhr_send?t=1576031555275 404 (Not Found)
                                                           main.7459b10fe35bab2c58d4.js:179295 

@socketDebug: Connection closed to https://exampleWebsite.com/Portal/batch-socket 
                                                           main.7459b10fe35bab2c58d4.js:179310 

@socketSvc: connection closed.                             main.7459b10fe35bab2c58d4.js:179311 

i {type: "close", bubbles: false, cancelable: false, timeStamp: 1576031555344, wasClean: false, …}bubbles: falsecancelable: falsecode: 1006reason: "Sending error: Error: http status 404"timeStamp: 1576031555344type: "close" wasClean: false__proto__: r
                                                           main.7459b10fe35bab2c58d4.js:179295 

@socketDebug: STOMP: scheduling reconnection in 5000ms

I have also took a look in the developer tools for web browser to check the network: network tab

May I know what is the issue for causing a close connection? Sometimes it takes a few tries before the websocket is successfully established. Other times it takes forever to have a successful connection.


Solution

  • The following code runs for me!!

    @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("/batch-socket");
             registry.addEndpoint("/batch-socket").withSockJS();
        }
    }
    

    Message-Handling Controller:

    @MessageMapping("/batch-socket")
    @SendTo("/topic/messages")
    public OutputMessage send(Message message) throws Exception {
        String time = new SimpleDateFormat("HH:mm").format(new Date());
        return new OutputMessage(message.getFrom(), message.getText(), time);
    }
    

    Payload:

    public class Message {
    
        private String from;
        private String text;
    
        // getters and setters
    }