1

I have a WebSockets connection between a server and a client. This allows me to send a command to a client, and he responds me with data. The server has web services too. I can then tell, "do this command on that client". So we have:

Client1 ---webservices--> server ---websockets---> Client2

The problem is, the method on the server which receives the data from Client2 is void.

How can I send back the data to Client1 ?

WebServices:

@Path("/ws")
public class QOSResource {
    public QOSResource(){}

    @Produces(MediaType.TEXT_PLAIN)
    @Path("/ping/{macAddr}")
    @GET
    public String getPing(@PathParam("macAddr") String macAddr){
    return"Mac adresse : "+macAddr;
    //WebSocketsCentralisation.getInstance().ping(macAddr);
    }
}

WebSockets

@OnWebSocketMessage
    public **void** onText(Session session, String message) {
        if (session.isOpen()) {
            if(firstConnection){
                firstConnection = false;
                this.macAddr = message;
                WebSocketsCentralisation.getInstance().join(this);
            }
            ObjectMapper mapper = new ObjectMapper();
                Object o;
                try {
                    o = mapper.readValue(message, Object.class);
                    if(o instanceof PingResult){
                         **// TODO return result to ws**

                        }
                } catch (JsonParseException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (JsonMappingException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
        }
    }

Thanks in advance for your help

jesse mcconnell
  • 7,102
  • 1
  • 22
  • 33
brunettia
  • 135
  • 4
  • 17

2 Answers2

1

The Session object you get in your method parameters contains the scope of your conversation with the remote endpoint.

You'll want to use the RemoteEndpoint that the Session.getRemote() returns in order to send messages.

Examples:

// Send BINARY websocket message (async)
byte data[] = mapper.toBytes(obj);
session.getRemote().sendBytesByFuture(data);

// Send TEXT websocket message (async)
String text = mapper.toString(obj);
session.getRemote().sendStringByFuture(text);

Be aware though that the session.getRemote() call will throw a WebSocketException if the remote endpoint connection is no longer in an open state (such as the case where the remote endpoint send you a message and then immediately initiated a CLOSE handshake control message).

// How to handle send message if remote isn't there
try {
    // Send message to remote
    session.getRemote().sendString(text);
} catch(WebSocketException e) {
    // WebSocket remote isn't available.
    // The connection is likely closed or in the process of closing.
}

Note: this style of websocket use, where you have a Session and a RemoteEndpoint is consistent with the upcoming JSR-356 standard (javax.websocket). In the standard API you will have javax.websocket.Session and javax.websocket.RemoteEndpoint to work with.

Joakim Erdfelt
  • 46,896
  • 7
  • 86
  • 136
  • I'm sorry, I think I can't explain myself correctly in english(i speak french). What you explain here is right and I use it. Where my problem is: my server has both websockets and webservices. The webservices allow me to reach a client via websockets. In my example, I want to get the ping of a remote device. So I use the API /ws/ping/macAddr. Here, I can access to the correct session and send my command (ping). What I can't do is get the answer back, because the method on the server which receive the data via websockets is void. – brunettia Jun 18 '13 at 13:08
  • That is correct, the Jetty API for a WebSocket @onMessage call are return type of `void`. This is because the Jetty internal WebSocket parser eventually calls this message and does not expect a return type. The upcoming Jetty 9.1 will support JSR-356 (javax.websocket) and it has the concept of a return type for @OnMessage calls, but be aware that this is also managed by the WebSocket implementation, you cannot hook into this JSR-356 return type outside of websockets. – Joakim Erdfelt Jun 18 '13 at 13:15
  • So here is my problem :) How can I send back the response to my webservices, if the "onText" method is void... – brunettia Jun 18 '13 at 13:23
  • The `onText` is a method for the WebSocket implementation to use. It would be difficult to use it arbitrarily as the Session parameter would need to be tracked and looked up. Consider a new method say `String onWebsocketMessage(String message)` and do the logic there, having `onText` just use this new method and returning the response. – Joakim Erdfelt Jun 18 '13 at 13:36
  • This other answer might be relevant in tracking the `Session` objects for multiple websockets - http://stackoverflow.com/a/15649791/775715 – Joakim Erdfelt Jun 18 '13 at 13:36
  • Like I said the Session is not the problem. Really, the problem comes when the websocket server gets the answer back from the remote device on the "onText" message, because it is void and it's an event. I can get back this result to the webservices – brunettia Jun 18 '13 at 13:49
0

Your websocket handler should have an associated Connection instance on which you can call sendMessage().

jtahlborn
  • 52,909
  • 5
  • 76
  • 118
  • I'm sorry I don't really see what you're saying. The communication between my websockets and my client2 is ok. The problem comes when client1 uses the webservice. How can I be synchronized between the moment where I tell "do the ping" (getPing) and the reception. – brunettia Jun 18 '13 at 12:05
  • @brunettia - your code indicates a void method for the _websockets_ call, but your question seems to refer tot the _webservices_ call. which is it? – jtahlborn Jun 18 '13 at 12:08
  • Both actually. The websocket server will receive the data, but in a void method. So how can I send the datas back to the webservices, and make it wait the response! – brunettia Jun 18 '13 at 12:12