I am creating a group chat functionality on my app and I am having some issues. Requirements are Java and Websockets in Java(both server and the client part). I have created both server and client WebSockets and communication by itself works(sending text from client to server and visa versa), but what I want to do is send Objects through the socket and serialize it into XML. I have created the serialization and it work perfectly without the socket. The problem appears when I want to combine the two.
For now I tried embedding the encoder and decoder to socket implementation and sending Player object through the socket and got this error(whatever I tried later the error stayed the same):
java.lang.ClassNotFoundException: model/Player
Continuing ...
java.lang.NoSuchMethodException: <unbound>=XMLDecoder.new();
Continuing ...
java.lang.IllegalStateException: The outer element does not return value
Continuing ...
java.lang.IllegalStateException: The outer element does not return value
Continuing ...
java.lang.ArrayIndexOutOfBoundsException: 0
at java.beans.XMLDecoder.readObject(Unknown Source)
at Util.Util.getObjectFromXml(Util.java:43)
at Util.WebDecoder.decode(WebDecoder.java:28)
at org.apache.tomcat.websocket.pojo.PojoMessageHandlerWholeText.decode(PojoMessageHandlerWholeText.java:108)
at org.apache.tomcat.websocket.pojo.PojoMessageHandlerWholeText.decode(PojoMessageHandlerWholeText.java:39)
at org.apache.tomcat.websocket.pojo.PojoMessageHandlerWholeBase.onMessage(PojoMessageHandlerWholeBase.java:57)
at org.apache.tomcat.websocket.WsFrameBase.sendMessageText(WsFrameBase.java:395)
at org.apache.tomcat.websocket.WsFrameBase.processDataText(WsFrameBase.java:495)
at org.apache.tomcat.websocket.WsFrameBase.processData(WsFrameBase.java:294)
at org.apache.tomcat.websocket.WsFrameBase.processInputBuffer(WsFrameBase.java:133)
at org.apache.tomcat.websocket.WsFrameClient.processSocketRead(WsFrameClient.java:95)
at org.apache.tomcat.websocket.WsFrameClient.resumeProcessing(WsFrameClient.java:209)
at org.apache.tomcat.websocket.WsFrameClient.access$300(WsFrameClient.java:31)
at org.apache.tomcat.websocket.WsFrameClient$WsFrameClientCompletionHandler.doResumeProcessing(WsFrameClient.java:186)
at org.apache.tomcat.websocket.WsFrameClient$WsFrameClientCompletionHandler.completed(WsFrameClient.java:163)
at org.apache.tomcat.websocket.WsFrameClient$WsFrameClientCompletionHandler.completed(WsFrameClient.java:148)
at sun.nio.ch.Invoker.invokeUnchecked(Unknown Source)
at sun.nio.ch.Invoker$2.run(Unknown Source)
at sun.nio.ch.AsynchronousChannelGroupImpl$1.run(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
I tried serializing the data into String sending it through the socket like text, receiving String and deserializing it on the client side of the app. The Exception persisted.
Xml decoder and encoder, they both work properly, but just in case I am wrong I'll put it here.
public class Util
{
public static String getXmlFromObject(Object o)
{
ByteArrayOutputStream baos = new ByteArrayOutputStream();
XMLEncoder xmlEncoder = new XMLEncoder(baos);
xmlEncoder.writeObject(o);
xmlEncoder.close();
return new String(baos.toByteArray()).replace("\n", "")+"\n";
}
public static Object getObjectFromXml(String xml)
{
ByteArrayInputStream bais = new ByteArrayInputStream(xml.getBytes());
XMLDecoder xmlDecoder = new XMLDecoder(bais);
Object o = xmlDecoder.readObject();
xmlDecoder.close();
return o;
}
}
WebSocket on the server side:
#ServerEndpoint(value="/chat", encoders= {WebEncoder.class}, decoders= {WebDecoder.class})
public class ChatWebSocket
{
List<Session> sessions = new ArrayList<Session>();
#OnOpen
public void open(Session session)
{
sessions.add(session);
}
#OnClose
public void close(Session session)
{
sessions.remove(session);
}
#OnError
public void OnError(Session session, Throwable t)
{
System.out.println(session);
sessions.remove(session);
t.printStackTrace();
}
#OnMessage
public void handleMessage(Object message, Session session)
{
for (Session s : sessions)
{
System.out.println(s);
try
{
s.getBasicRemote().sendObject(message);
} catch (IOException | EncodeException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
WebSocket for the client side and a code snippet sending the message and for receiving it on the client side:
#ClientEndpoint(encoders= {WebEncoder.class}, decoders= {WebDecoder.class})
public class ChatWebSocketClient
{
Session session = null;
private MessageHandler messageHandler;
public ChatWebSocketClient(URI endpointURI)
{
try
{
WebSocketContainer container = ContainerProvider.getWebSocketContainer();
container.connectToServer(this, endpointURI);
} catch (Exception e)
{
e.printStackTrace();
}
}
#OnOpen
public void open(Session session)
{
this.session = session;
}
#OnClose
public void close(Session sesion, CloseReason reason)
{
this.session = null;
}
#OnError
public void onError(Session session, Throwable t)
{
t.printStackTrace();
}
#OnMessage
public void OnMessage(Object message)
{
if (this.messageHandler != null)
{
this.messageHandler.handleMessage(message);
}
}
public void addMessageHandler(MessageHandler msgHandler)
{
messageHandler = msgHandler;
}
public void sendMessage(Object message)
{
try
{
session.getBasicRemote().sendObject(message);
} catch (IOException | EncodeException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
final ChatWebSocketClient webSocket = new ChatWebSocketClient(new URI("ws://localhost:8080/XOX/chat"));
webSocket.addMessageHandler(new MessageHandler(){
#Override
public void handleMessage(Object message)
{
System.out.println("jsp "+message.getClass().getName());
System.out.println("jsp "+Util.getXmlFromObject(message));
}
});
webSocket.sendMessage(player);
Related
Is there any way to enable cdi within this #ClientEndpoint class (still using annotations as opposed to programmatic endpoint classes)? I am using wildfly 14 and java 8.
Here is the code that creates the session, passing the classname to the "createConnection" method:
#ApplicationScoped //TODO move this to be request scoped
public class SessionProducer {
#Produces
public Session getSession(InjectionPoint ip) {
SessionAnnotation annotation = ip.getAnnotated().getAnnotation(SessionAnnotation.class);
if(annotation != null) {
Class clazz = annotation.clazz();
String url = annotation.serverURL();
WebSocketContainer webSocketContainer = ContainerProvider.getWebSocketContainer();
try {
return webSocketContainer.connectToServer(clazz, new URI(url)); //<----------this is the line that uses the annotated class (clazz is a reference to the class)
} catch (DeploymentException | IOException | URISyntaxException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return null;
}
/**
* The destroy/disposer metho for the session
* #param session
*/
public void close(#Disposes Session session) {
try {
session.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Here is the annotated endpoint class:
#ClientEndpoint
public class CryptoCompareWSClient {
#Inject
#CryptoCompare
private Event<String> cryptoCompareEvent; //<--------this is always null, no cdi happens
public CryptoCompareWSClient() {
System.out.println("constructor");
//cryptoCompareEvent = new Event();
}
#PostConstruct
public void init() {
System.out.println("post construct"); //<---------this never gets called
}
#OnOpen
public void open(Session session) {
//session.getAsyncRemote().sendText("SubAdd: { subs: ['0~Poloniex~BTC~USD'] }" /*"test"*/);
System.out.println("opened");
}
#OnClose
public void close(Session session) {
System.out.println("Session " + session + " closed");
}
#OnError
public void error(Throwable error) {
System.out.println("Error: " + error.getMessage());
}
#OnMessage
public void message(String message, Session session) {
System.out.println("Message");
//cryptoCompareEvent.fireAsync(message);
}
}
Is there any way to enable cdi in the enabled class?
Thanks.
I need to close connection but I get this
2016-10-28 10:46:07.624:WARN:oeji.nio:handle failed
java.lang.NullPointerException: ssl == null
at com.android.org.conscrypt.NativeCrypto.SSL_read_BIO(Native Method)
at com.android.org.conscrypt.OpenSSLEngineImpl.unwrap(OpenSSLEngineImpl.java:477)
at javax.net.ssl.SSLEngine.unwrap(SSLEngine.java:1014)
at org.eclipse.jetty.io.nio.SslConnection.unwrap(SslConnection.java:536)
at org.eclipse.jetty.io.nio.SslConnection.process(SslConnection.java:359)
at org.eclipse.jetty.io.nio.SslConnection.access$900(SslConnection.java:48)
at org.eclipse.jetty.io.nio.SslConnection$SslEndPoint.fill(SslConnection.java:678)
at org.eclipse.jetty.websocket.WebSocketParserRFC6455.parseNext(WebSocketParserRFC6455.java:181)
at org.eclipse.jetty.websocket.WebSocketConnectionRFC6455.handle(WebSocketConnectionRFC6455.java:225)
at org.eclipse.jetty.io.nio.SslConnection.handle(SslConnection.java:196)
at org.eclipse.jetty.io.nio.SelectChannelEndPoint.handle(SelectChannelEndPoint.java:667)
at org.eclipse.jetty.io.nio.SelectChannelEndPoint$1.run(SelectChannelEndPoint.java:52)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:608)
at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:543)
at java.lang.Thread.run(Thread.java:833)
This is my code for sockets:
private WebSocket webSocket = new WebSocket.OnTextMessage() {
#Override
public void onMessage(String data) {
//...
}
#Override
public void onOpen(Connection connection) {
//...
}
#Override
public void onClose(int closeCode, String message) {
//...
// this is called after connection.close()
}
};
WebSocketClientFactory webSocketClientFactory = new WebSocketClientFactory();
public void start(){
webSocketClientFactory.stop();
String urlConnect = "wss://test.test.com:111111/websocket";
webSocketClientFactory.setBufferSize(100000);
webSocketClientFactory.start();
WebSocketClient webSocketClient = webSocketClientFactory.newWebSocketClient();
webSocketClient.setMaxBinaryMessageSize(100000);
webSocketClient.setMaxTextMessageSize(100000);
Future<WebSocket.Connection> connectionFuture = webSocketClient.open(URI.create(urlConnect), webSocket);
}
// .......
// after some time call this
public void stop(){
try {
connection.close(); //this is going fine, error comes after
} catch (Throwable t) {
t.printStackTrace();//this not called
}
}
I can't understand what is the reason of that error and how I can fix it? I look through jetty docs and checked some thread here, but found nothing about that specific error
You have to stop the WebSocketClient.
Try this:
public void stop(){
try {
webSocketClient.stop();
} catch (Throwable t) {
t.printStackTrace();//this not called
}
}
or
public void stop(){
try {
webSocketClient.stop();
connection.close();
} catch (Throwable t) {
t.printStackTrace();//this not called
}
}
Link: where I have see it
I am experiencing a problem where client does not start in non-debug mode in eclipse. Message do appear in debug mode.
Please let me know if any one else also facing same issue.
Calling method:
client = ClientManager.createClient();
ClientEndpointConfig cec = ClientEndpointConfig.Builder.create().build();
client.getProperties().put(ClientProperties.PROXY_URI, "http://192.168.1.1:80");
session = client.connectToServer(new ClientEndpoint(), cec, URI.create(url));
Below is the code of ClientEndpoint class:
private static class ClientEndpoint extends Endpoint {
#Override
public void onOpen(final Session session, EndpointConfig config) {
System.out.println("ClientEndpoint: server session opened: "+session);
session.addMessageHandler(new MessageHandler.Whole<String>() {
#Override
public void onMessage(String message) {
System.out.println("ClientEndpoint: received message: "+message);
if(lastmessage != message)
{
lastmessage = message;
session.getUserProperties().put("Message", lastmessage);
}
else
{
enter code here
session.getUserProperties().put("Message", lastmessage);
}
}
});
}
#Override
public void onClose(Session session, CloseReason closeReason) {
try {
latch.countDown();
session.close();
safeDisconnect(session);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
#Override
public void onError(Session session, Throwable th)
{
try {
session.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
th.printStackTrace();
}
}
Any thoughts? Please do let me know the configuration.
I'm using websocket in the client side (javascript) and in the server side a java class.
This is my WordgameServerEndpoint side class
#ServerEndpoint(value = "/socket")
public class WordgameServerEndpoint {
private Logger logger = Logger.getLogger(this.getClass().getName());
#OnOpen
public void onOpen(Session session) {
logger.info("Connected ... " + session.getId());
}
#OnMessage
public String onMessage(String unscrambledWord, Session session) {
logger.info("Starting the game by sending first word");
return unscrambledWord;
}
#OnClose
public void onClose(Session session, CloseReason closeReason) {
logger.info(String.format("Session %s closed because of %s", session.getId(), closeReason));
}
}
This is the WebSocketServer class
public class WebSocketServer {
public static void main(String[] args) {
runServer();
}
public static void runServer() {
Server server = new Server("localhost", 9988, "/websockets", WordgameServerEndpoint.class);
try {
server.start();
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
System.out.print("Please press a key to stop the server.");
//reader.readLine();
System.out.println(reader.readLine());
} catch (Exception e) {
e.printStackTrace();
} finally {
server.stop();
}
}
}
and this is my javascript function to send message
$scope.savedata=function(){
socket= new WebSocket('ws://majed-PC:9988/websockets/socket');
socket.onopen= function() {
socket.send('hello');
};
};
How do I get the value of the sent message on the server side?
See
#OnMessage
public String onMessage(String unscrambledWord, Session session) {
logger.info("Starting the game by sending first word");
return unscrambledWord;
}
on server side. unscrambledWord is the received message. Your implementation just echoes it back, which might not be what you want to do - just place your logic there.
I'm new to Jerry, and trying to implement WebSocket Client on Jetty9.
I saw an example on Jetty8.
org.eclipse.jetty.websocket Class WebSocketClient
http://archive.eclipse.org/jetty/8.0.0.v20110901/apidocs/org/eclipse/jetty/websocket/WebSocketClient.html
to create a new instance of WebSocketClient is :
WebSocketClientFactory factory = new WebSocketClientFactory();
factory.start();
WebSocketClient client = factory.newWebSocketClient();
// Configure the client
WebSocket.Connection connection = client.open(new
URI("ws://127.0.0.1:8080/"), new WebSocket.OnTextMessage()
{
public void onOpen(Connection connection)
{
// open notification
}
public void onClose(int closeCode, String message)
{
// close notification
}
public void onMessage(String data)
{
// handle incoming message
}
}).get(5, TimeUnit.SECONDS);
connection.sendMessage("Hello World");
However, I've never seen a document for Jetty9 for this.
So far, referring to
org.eclipse.jetty.websocket.common
Interface SessionFactory
//----------------------------------------------
WebSocketSession createSession(URI requestURI,
EventDriver websocket,
LogicalConnection connection)
//----------------------------------------------
I've tried
private WebSocketSessionFactory factory = new WebSocketSessionFactory();
try
{
WebSocketSession session = factory.createSession(uri,
eventDriver, connection);
RemoteEndpoint ep = session.getRemote();
}
catch (Exception ex)
{
System.out.println("=ERROR= " + ex);
//=ERROR= java.lang.NullPointerException
}
private EventDriver eventDriver = new EventDriver()
{
#Override
public WebSocketPolicy getPolicy()
{
return null;
}
//......................................
#Override
public void incomingFrame(Frame frame)
{
}
};
private LogicalConnection connection = new LogicalConnection()
{
#Override
public void close()
{
}
//...............................
#Override
public void resume()
{
}
};
but I've encounter java.lang.NullPointerException
How do we implement Jetty9 WebSocket Client ??
Thanks for your advise.
Hope this helpful: EventClient.java