Возникли проблемы с вызовом службы при получении данных из веб-сокета в Spring-Boot - PullRequest
0 голосов
/ 25 февраля 2020

Я создаю обработчик, который расширяет TextWebSocketHandler и способен печатать данные, отправленные с моего клиента, в Flutter.io. Однако, когда я пытаюсь передать данные в службу, я получаю кучу ошибок, как показано ниже:

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]

Сначала я подумал, что это проблема с тем, как я называю свою службу, однако я используя @Autowired, а также попытался использовать ApplicationContext для настройки моего DI. Теперь я просто не знаю, в чем проблема. Я бы использовал конфигурации STOMP и Sock JS Websocket, если бы Flutter.io предоставил поддержку для этого, теперь я использую эти конфигурации и классы для обработки входящих данных с помощью веб-сокетов.

Ниже приведен мой код

WSConfig. java | Как я настроил свой веб-сокет

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 | Как я обрабатываю входящие данные

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 | Служба, которую я использую для обработки входящих данных из текста веб-сокета

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";
    }
}

Заранее спасибо, и если я подхожу к этому совершенно неправильно, пожалуйста, дайте мне знать.

1 Ответ

1 голос
/ 25 февраля 2020

Проблема здесь в том, что это не автоматическое подключение WebsocketService к SocketHandler, потому что вы используете оператор new в registerWebSocketHandlers(). Вам нужно автоматически подключить socketHandler в WSConfig и использовать экземпляр с автопроводкой.

Как правило, вы никогда не должны вызывать new на управляемом компоненте Spring, вместо этого автоматически подключать его.

Как правило, не следует использовать @Service и @Configurable вместе, один регистрация bean-компонента Spring, а другой говорит Spring, что вы создадите свои собственные экземпляры. В этом случае вы должны использовать только @Service

...