我想要一个客户端来接收WS消息并存储它们以供进一步分析。
我创建了一个基于 https://dzone.com/articles/sample-java-web-socket-client 的客户端
不幸的是,在每个onMessage方法调用上,将存储值的字段为空,无法添加消息。
法典
package com.sample.ws;
import org.apache.log4j.Logger;
import javax.websocket.*;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import static java.lang.Thread.sleep;
@ClientEndpoint
public class WSClient {
private static final Logger LOG = Logger.getLogger(WSClient.class);
private List<String> testContext;
public static void main(String[] args) {
WSClient client = new WSClient();
List testContext = new ArrayList<String>();
client.setTestContext(testContext);
client.run();
LOG.info("Final state: " + testContext);
}
private void run() {
LOG.info("Initial state: " + testContext);
WebSocketContainer container = null;//
Session session = null;
try {
container = ContainerProvider.getWebSocketContainer();
session = container.connectToServer(com.sample.ws.WSClient.class, URI.create("ws://localhost:8080/wsserver-1.0/ratesrv"));
LOG.info("Connected to server");
sleep(10000L);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (session != null) {
try {
session.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
@OnMessage
private void onMessage(String message) {
//the new USD rate arrives from the websocket server side.
LOG.info("Received msg: " + message);
testContext.add(message);
}
private void setTestContext(List<String> testContext) {
this.testContext = testContext;
}
}
日志
INFO WSClient - Initial state: []
INFO WSClient - Connected to server
INFO WSClient - Received msg: USD Rate: 2.998
Feb 03, 2017 5:52:22 PM org.glassfish.tyrus.core.AnnotatedEndpoint onError
INFO: Unhandled exception in endpoint com.sample.ws.WSClient.
java.lang.NullPointerException
at com.sample.ws.WSClient.onMessage(WSClient.java:55)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.glassfish.tyrus.core.AnnotatedEndpoint.callMethod(AnnotatedEndpoint.java:520)
at org.glassfish.tyrus.core.AnnotatedEndpoint.access$100(AnnotatedEndpoint.java:87)
at org.glassfish.tyrus.core.AnnotatedEndpoint$WholeHandler$1.onMessage(AnnotatedEndpoint.java:619)
at org.glassfish.tyrus.core.TyrusSession.notifyMessageHandlers(TyrusSession.java:576)
at org.glassfish.tyrus.core.TyrusEndpointWrapper.onMessage(TyrusEndpointWrapper.java:879)
at org.glassfish.tyrus.core.TyrusWebSocket.onMessage(TyrusWebSocket.java:216)
at org.glassfish.tyrus.core.frame.TextFrame.respond(TextFrame.java:139)
at org.glassfish.tyrus.core.ProtocolHandler.process(ProtocolHandler.java:807)
at org.glassfish.tyrus.client.TyrusClientEngine$TyrusReadHandler.handle(TyrusClientEngine.java:747)
at org.glassfish.tyrus.container.grizzly.client.GrizzlyClientFilter$ProcessTask.execute(GrizzlyClientFilter.java:476)
at org.glassfish.tyrus.container.grizzly.client.TaskProcessor.processTask(TaskProcessor.java:114)
at org.glassfish.tyrus.container.grizzly.client.TaskProcessor.processTask(TaskProcessor.java:91)
at org.glassfish.tyrus.container.grizzly.client.GrizzlyClientFilter.handleRead(GrizzlyClientFilter.java:272)
at org.glassfish.grizzly.filterchain.ExecutorResolver$9.execute(ExecutorResolver.java:119)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:284)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:201)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:133)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:112)
at org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:77)
at org.glassfish.grizzly.nio.transport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:526)
at org.glassfish.grizzly.strategies.AbstractIOStrategy.fireIOEvent(AbstractIOStrategy.java:112)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.run0(WorkerThreadIOStrategy.java:117)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.access$100(WorkerThreadIOStrategy.java:56)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy$WorkerThreadRunnable.run(WorkerThreadIOStrategy.java:137)
at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:591)
at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:571)
at java.lang.Thread.run(Thread.java:745)
INFO WSClient - Final state: []
WebSocket客户端创建新实例,并且"testContext"字段未填充在那里。
让它成为静态的,它将开始工作。此外,您需要使其线程安全。(即:CopyOnWriteArrayList)。
另一种选择是调用 #connectToServer(对象,URI),这将强制 WebSocket 客户端使用提供的实例(而不是创建新实例)。同样,您需要确保以线程安全的方式访问集合(以及在处理过程中访问的任何其他字段)。