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.
Related
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);
I'm building a websocket application using glassfish I need in a given event my server to send message to all connected clients. I can send and receive messages from both, but I am not able to use the class server to send messages.
My server class has the following body:
#ApplicationScoped
#ServerEndpoint("/actions")
public class DeviceWebSocketServer {
#Inject
private DeviceSessionHandler sessionHandler;
#OnOpen
public void open(Session session) {
sessionHandler.addSession(session);
}
#OnClose
public void close(Session session) {
sessionHandler.removeSession(session);
}
#OnError
public void onError(Throwable error) {
Logger.getLogger(DeviceWebSocketServer.class.getName()).log(Level.SEVERE, null, error);
}
#OnMessage
public void handleMessage(String message, Session session) {
System.out.println("Chegou uma mensagem: " + message);
System.out.println("Na sessao: " + session.getId());
try (JsonReader reader = Json.createReader(new StringReader(message))) {
JsonObject jsonMessage = reader.readObject();
if ("add".equals(jsonMessage.getString("action"))) {
Device device = new Device();
device.setName(jsonMessage.getString("name"));
device.setDescription(jsonMessage.getString("description"));
device.setType(jsonMessage.getString("type"));
device.setStatus("Off");
sessionHandler.addDevice(device);
}
if ("remove".equals(jsonMessage.getString("action"))) {
int id = (int) jsonMessage.getInt("id");
sessionHandler.removeDevice(id);
}
if ("toggle".equals(jsonMessage.getString("action"))) {
int id = (int) jsonMessage.getInt("id");
sessionHandler.toggleDevice(id);
}
}
}
How do I send messages to customers after receiving an event? Should I instantiate my class server?
Theres a example on howto send messages to all connected clients in this whiteboard app:
https://netbeans.org/kb/docs/javaee/maven-websocketapi.html
#ServerEndpoint(value="/whiteboardendpoint", encoders = {FigureEncoder.class}, decoders = {FigureDecoder.class})
public class MyWhiteboard {
private static Set<Session> peers = Collections.synchronizedSet(new HashSet<Session>());
#OnMessage
public void broadcastFigure(Figure figure, Session session) throws IOException, EncodeException {
System.out.println("broadcastFigure: " + figure);
for (Session peer : peers) {
if (!peer.equals(session)) {
peer.getBasicRemote().sendObject(figure);
}
}
}
I have the following web-socket server code from (https://github.com/TooTallNate/Java-WebSocket):
public class WebsocketServer extends WebSocketServer {
private static int PORT = 2005;
private Set<WebSocket> conns;
public WebsocketServer() {
super(new InetSocketAddress(PORT));
conns = new HashSet<>();
}
#Override
public void onOpen(WebSocket conn, ClientHandshake handshake) {
conns.add(conn);
System.out.println("New connection from " + conn.getRemoteSocketAddress().getAddress().getHostAddress());
}
#Override
public void onClose(WebSocket conn, int code, String reason, boolean remote) {
conns.remove(conn);
System.out.println("Closed connection to " + conn.getRemoteSocketAddress().getAddress().getHostAddress());
}
#Override
public void onMessage(WebSocket conn, String message) {
System.out.println("Received: " + message);
for (WebSocket sock : conns) {
sock.send(messageToSend);
}
}
#Override
public void onError(WebSocket conn, Exception ex) {
ex.printStackTrace();
if (conn != null) {
conns.remove(conn);
// do some thing if required
}
System.out.println("ERROR from " + conn.getRemoteSocketAddress().getAddress().getHostAddress());
}
public static void main(String[] args) throws IOException, InterruptedException {
WebsocketServer server = new WebsocketServer();
server.run();
BufferedReader sysin = new BufferedReader(new InputStreamReader(System.in));
while (true) {
String in = sysin.readLine();
server.sendToAll(in);
if (in.equals("exit")) {
server.stop();
break;
} else if (in.equals("restart")) {
server.stop();
server.start();
break;
}
}
}
public void sendToAll(String text) {
Collection<WebSocket> con = connections();
synchronized (con) {
for (WebSocket c : con) {
c.send(text);
}
}
}
}
The codes works fine, but all codes that comes after server.run(); won't start/work! that part I need to send messages from Java console to client.
What I am doing wrong?
Note: My client works in JavaScript and can connect to the server
You need to start() Runnable class, not run() it directly
server.start();
instead of
server.run();
I created a simple chat server in Java with a Javascript client , but I'm having a problem receiving messages from JavaScript to Java.
When i use the Java client it is work fine, but when i use Javascript i have the problem.
My code:
Java
public class ChatRunner {
public static void main(String[] args) throws Exception {
Server server = new Server();
ServerConnector connector = new ServerConnector(server);
connector.setPort(8080);
server.addConnector(connector);
ServletContextHandler context = new ServletContextHandler(
ServletContextHandler.SESSIONS);
context.setContextPath("/");
server.setHandler(context);
try {
ServerContainer wscontainer = WebSocketServerContainerInitializer
.configureContext(context);
wscontainer.addEndpoint(ChatEndpoint.class);
server.start();
server.dump(System.err);
server.join();
} catch (Throwable t) {
t.printStackTrace(System.err);
}
}
}
#ServerEndpoint(value="/events/")
public class ChatEndpoint {
#OnOpen
public void onWebSocketConnect(Session sess) {
System.out.println("Socket Connected: " + sess);
}
#OnMessage
public void onWebSocketText(String message) {
System.out.println("Received TEXT message: " + message);
}
#OnClose
public void onWebSocketClose(CloseReason reason) {
System.out.println("Socket Closed: " + reason);
}
#OnError
public void onWebSocketError(Throwable cause) {
cause.printStackTrace(System.err);
}
}
JavaScript:
var ws = new WebSocket("ws://localhost:8080/events/");
ws.onopen = function() { ws.send("Hello"); };
Well you can test your server using https://www.websocket.org/echo.html. Simply put your global url and test.
I managed to make the client send objects to the server and the server does reply correctly but only to the client who sent the object, I had to forward ports on the server side and allowed port connections on the server side, now I can't seem to send a reply/message to a specific client and always get a connection refused error, meddling with portforwardind/firewall on the client side is not possible since anyone should be able to use the chat(the client must stay a client and not become a server). Any ideas how to make this work ? I heard about http tunneling or rmi proxy but how does it work code-wise ?
here's my main code on the client side :
public class Main {
public static void main(String [] args) {
String input;
Scanner in = new Scanner(System.in);
input = in.nextLine();
try
{
Message b =(Message) Naming.lookup("//xx.xx.xx.xx:1099/Message");
Client c=new Client(input);
UnicastRemoteObject.exportObject(c, 1100);
b.addUser(c);
while(true)
{
input = in.nextLine();
if(input.contentEquals("deconnection"))
{
b.exit();
break;
}
else if(input.startsWith(">"))
{
b.broadcast(c,"test");
}
}
in.close();
}
catch (NotBoundException re) { System.out.println(re) ; }
catch (RemoteException re) { System.out.println(re) ; }
catch (MalformedURLException e) { System.out.println(e) ; }
}
}
on the server side :
public class Serveur
{
public static void main(String [] args) {
try {
MessageImpl objLocal = new MessageImpl();
Naming.rebind("rmi://localhost:"+1099+"/Message" , UnicastRemoteObject.exportObject(objLocal, 1100)) ;
System.out.println("Serveur pret");
}
catch (RemoteException re) { System.out.println(re) ; }
catch (MalformedURLException e) { System.out.println(e) ; }
}
}
with the MessageImpl.java where the clientlist is found :
public class MessageImpl
implements Message {
public Vector<ClientInterface> clientlist;
public MessageImpl () throws RemoteException {super();listec=new Vector<ClientInterface>();};
public String envoiMessage() throws RemoteException {
return( "message test" );
}
public boolean isNew(ClientInterface c) throws RemoteException
{
return false;
}
public String test() throws RemoteException
{
System.out.println("re");
return "test";
}
public void addUser(ClientInterface c) throws RemoteException
{
test();
clientlist.add(c);
}
public void broadcast(ClientInterface c,String message) throws RemoteException
{
int i;
for(i=0;i<clientlist.size();i++)
{
if(clientlist.elementAt(i).getUsername().equals(c.getUsername()))
{}
else
{
clientlist.elementAt(i).getMessage(c.getUsername()+" : "+message);
}
}
}
public String exit() throws RemoteException
{
try{
return "exiting messenger";
}
catch(Exception e){return "erreur deconnection";}
}
}
If 'meddling' with the client firewall isn't possible, your system is unimplementable as designed. You would have to use polling instead of callbacks on the client side.