Reputation: 372
I want to have a client which will receive WS messages and store them for further analysis.
I created a Client based on https://dzone.com/articles/sample-java-web-socket-client
Unfortunately on each onMessage method call the field which will store the values is null and message cannot be added.
Code
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;
}
}
Log
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: []
Upvotes: 1
Views: 835
Reputation: 5324
WebSocket client creates new instance and the "testContext" field is not populated there.
Make it static and it will start to work. Also, you need to make it thread safe. (i.e.: CopyOnWriteArrayList).
Another option is to call #connectToServer(Object, URI), which will force WebSocket client to use the provided instance (not to create a new one). Again, you need to make sure your collection (and any other fields accessed during processing) are accessed in thread-safe manner.
Upvotes: 1