简体   繁体   中英

Having trouble calling a service when receiving data from a websocket in Spring-Boot

I am creating a Handler that extends TextWebSocketHandler and am able to print the data send from my client in Flutter.io . However, when I try passing the data to a service I am getting a bunch of errors as seen below:

Closing session due to exception for StandardWebSocketSession[id=9eb9b6b1-2fab-b27d-9ca1-22815c957e68, uri=ws://localhost:8080/name]

java.lang.NullPointerException: null
    at offtop.Config.SocketHandler.lambda$0(SocketHandler.java:41) ~[classes/:na]
    at java.base/java.util.stream.Streams$StreamBuilderImpl.forEachRemaining(Streams.java:411) ~[na:na]
    at java.base/java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:658) ~[na:na]
    at offtop.Config.SocketHandler.handleTextMessage(SocketHandler.java:40) ~[classes/:na]
    at org.springframework.web.socket.handler.AbstractWebSocketHandler.handleMessage(AbstractWebSocketHandler.java:43) ~[spring-websocket-5.2.1.RELEASE.jar:5.2.1.RELEASE]
    at org.springframework.web.socket.handler.WebSocketHandlerDecorator.handleMessage(WebSocketHandlerDecorator.java:75) ~[spring-websocket-5.2.1.RELEASE.jar:5.2.1.RELEASE]
    at org.springframework.web.socket.handler.LoggingWebSocketHandlerDecorator.handleMessage(LoggingWebSocketHandlerDecorator.java:56) ~[spring-websocket-5.2.1.RELEASE.jar:5.2.1.RELEASE]
    at org.springframework.web.socket.handler.ExceptionWebSocketHandlerDecorator.handleMessage(ExceptionWebSocketHandlerDecorator.java:58) ~[spring-websocket-5.2.1.RELEASE.jar:5.2.1.RELEASE]
    at org.springframework.web.socket.adapter.standard.StandardWebSocketHandlerAdapter.handleTextMessage(StandardWebSocketHandlerAdapter.java:114) ~[spring-websocket-5.2.1.RELEASE.jar:5.2.1.RELEASE]
    at org.springframework.web.socket.adapter.standard.StandardWebSocketHandlerAdapter.access$000(StandardWebSocketHandlerAdapter.java:43) ~[spring-websocket-5.2.1.RELEASE.jar:5.2.1.RELEASE]
    at org.springframework.web.socket.adapter.standard.StandardWebSocketHandlerAdapter$3.onMessage(StandardWebSocketHandlerAdapter.java:85) ~[spring-websocket-5.2.1.RELEASE.jar:5.2.1.RELEASE]
    at org.springframework.web.socket.adapter.standard.StandardWebSocketHandlerAdapter$3.onMessage(StandardWebSocketHandlerAdapter.java:82) ~[spring-websocket-5.2.1.RELEASE.jar:5.2.1.RELEASE]
    at org.apache.tomcat.websocket.WsFrameBase.sendMessageText(WsFrameBase.java:395) ~[tomcat-embed-websocket-9.0.27.jar:9.0.27]
    at org.apache.tomcat.websocket.server.WsFrameServer.sendMessageText(WsFrameServer.java:119) ~[tomcat-embed-websocket-9.0.27.jar:9.0.27]
    at org.apache.tomcat.websocket.WsFrameBase.processDataText(WsFrameBase.java:495) ~[tomcat-embed-websocket-9.0.27.jar:9.0.27]
    at org.apache.tomcat.websocket.WsFrameBase.processData(WsFrameBase.java:294) ~[tomcat-embed-websocket-9.0.27.jar:9.0.27]
    at org.apache.tomcat.websocket.WsFrameBase.processInputBuffer(WsFrameBase.java:133) ~[tomcat-embed-websocket-9.0.27.jar:9.0.27]
    at org.apache.tomcat.websocket.server.WsFrameServer.onDataAvailable(WsFrameServer.java:82) ~[tomcat-embed-websocket-9.0.27.jar:9.0.27]
    at org.apache.tomcat.websocket.server.WsFrameServer.doOnDataAvailable(WsFrameServer.java:171) ~[tomcat-embed-websocket-9.0.27.jar:9.0.27]
    at org.apache.tomcat.websocket.server.WsFrameServer.notifyDataAvailable(WsFrameServer.java:151) ~[tomcat-embed-websocket-9.0.27.jar:9.0.27]
    at org.apache.tomcat.websocket.server.WsHttpUpgradeHandler.upgradeDispatch(WsHttpUpgradeHandler.java:148) ~[tomcat-embed-websocket-9.0.27.jar:9.0.27]
    at org.apache.coyote.http11.upgrade.UpgradeProcessorInternal.dispatch(UpgradeProcessorInternal.java:54) ~[tomcat-embed-core-9.0.27.jar:9.0.27]
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:53) ~[tomcat-embed-core-9.0.27.jar:9.0.27]
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:861) ~[tomcat-embed-core-9.0.27.jar:9.0.27]
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1579) ~[tomcat-embed-core-9.0.27.jar:9.0.27]
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) ~[tomcat-embed-core-9.0.27.jar:9.0.27]
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) ~[na:na]
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) ~[na:na]
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[tomcat-embed-core-9.0.27.jar:9.0.27]
    at java.base/java.lang.Thread.run(Thread.java:835) ~[na:na]

I first thought it was an issue with how I am calling my service, however, I am using @Autowired and also tried using ApplicationContext to configure my DI. Now I'm just not sure what the issue is. I would be using STOMP and SockJS Websocket configuration if Flutter.io provided support for that, now I am using these configurations and classes to handle incoming data with websockets.

Below is my code

WSConfig.java | How I configured my websocket

package offtop.Config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;

@Configuration
@EnableWebSocket
public class WSConfig implements WebSocketConfigurer{
    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
        registry.addHandler(new SocketHandler(), "/name");
    }
}

SocketHandler.java | How I am handling incoming data

package offtop.Config;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.stream.Stream;
import com.google.gson.Gson;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import offtop.Services.WebsocketService;

@Component
public class SocketHandler extends TextWebSocketHandler {


    @Autowired
    private WebsocketService websocketService;

    List<WebSocketSession> sessions = new CopyOnWriteArrayList<>();

    @Override
    public void handleTextMessage(WebSocketSession session, TextMessage message)
            throws IOException {
        for (int i = 0; i < sessions.size(); i++) {
            WebSocketSession webSocketSession = (WebSocketSession) sessions.get(i);
            Map value = new Gson().fromJson(message.getPayload(), Map.class);
            System.out.println(value.toString());
            Stream<String> s = Stream.of(value.values().toString());
            s.forEach(val -> {
                    websocketService.logData(val);
            });     
            webSocketSession.sendMessage(new TextMessage("Received " + value.get("message") + " !"));
        }
    }

    @Override
    public void afterConnectionEstablished(final WebSocketSession session) throws Exception {
        System.out.println("sessions: " + session.toString());
        sessions.add(session);
    }

}

WebsocketService.java | Service I am using to manipulate incoming data from websocket text

package offtop.Services;

import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.stereotype.Service;

@Service
@Configurable
public class WebsocketService{
    public String logData(String val){
        System.out.println("val incoming: " + val);
        return "works";
    }
}

Thank you in advance, and If am approaching this completely wrong please let me know.

The issue here is that it is not autowiring WebsocketService into the SocketHandler because you are using the new operator in registerWebSocketHandlers() . You need to autowire the socketHandler in WSConfig and use the autowired instance.

As a general rule, you should never call new on a Spring managed bean, autowire it instead.

You should generally not use @Service and @Configurable together, one is registering a Spring bean and the other is telling Spring that you will create your own instances. In this case you should use only @Service

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM