I am having a problem getting an extremely simple standalone Tyrus websocket server to work. I have gotten this to work under very specific circumstances that don't make sense to me.
The case that works correctly is where I define a top-level (in its own file) server endpoint class and annotate it with @ServerEndpoint. This class includes methods annotated with @OnOpen, @OnMessage, and @OnClose, all typical stuff. I pass this class to the Server constructor. My simple client can connect to this server, and send it messages successfully that are received by the server.
The problem occurs when I change the top-level server endpoint class to be an inner class of the class that is initializing the server (this is the ONLY change I made). In this case my client can connect and the client's @OnOpen method is called. But the server does not instantiate the server endpoint and, consequently, its @OnOpen method is never called. Obviously, server message receipt does not occur.
Is there a requirement in Tyrus that annotated server endpoint classes can't be inner classes? If not, are there specific permissions on server endpoint classes (everything has been made public attempting to get this to work with no luck)? I'm using Tyrus 1.9 with JDK 1.7 on a Mac, OSX 1.9.5.
The simple server (including and configured to use the inner server endpoint that fails):
package tyrus.example;
import java.util.concurrent.TimeUnit;
import javax.websocket.CloseReason;
import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import org.glassfish.tyrus.server.Server;
public class SimpleServer
{
private static final String HOST_ADDR = "localhost";
private static final int HOST_PORT = 8025;
public static void main(String[] args) {
Server websocketServer = new Server(HOST_ADDR, HOST_PORT, "/ws", null, InnerSimpleServerEndpoint.class);
try {
websocketServer.start();
Thread.sleep(TimeUnit.MINUTES.toMillis(5));
}
catch (Exception e) {
e.printStackTrace();
}
websocketServer.stop();
System.out.println("Done.");
}
@ServerEndpoint("/myapp")
public class InnerSimpleServerEndpoint {
@OnOpen
public void onOpen(Session session) {
System.out.println("Connection received for "+session.getRequestURI());
}
@OnMessage
public void onMessage(String message, Session session) {
System.out.println("Message received: "+message);
}
@OnClose
public void onClose(Session session, CloseReason closeReason) {
System.out.println("Session closed, reason: "+closeReason);
}
}
}
The simple client:
package tyrus.example;
import java.io.IOException;
import java.net.URI;
import javax.websocket.ClientEndpointConfig;
import javax.websocket.Endpoint;
import javax.websocket.EndpointConfig;
import javax.websocket.MessageHandler;
import javax.websocket.Session;
import org.glassfish.tyrus.client.ClientManager;
public class SimpleClient
{
private static final String DEF_WS_URL = "ws://localhost:8025/ws/myapp";
public static void main(String[] args) {
ClientEndpointConfig cec = ClientEndpointConfig.Builder.create().build();
ClientManager client = ClientManager.createClient();
try {
client.connectToServer(new ClientEndpoint(), cec, new URI(DEF_WS_URL));
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("Done.");
}
private static class ClientEndpoint extends Endpoint {
@Override
public void onOpen(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);
}
});
try {
session.getBasicRemote().sendText("Hello server!");
}
catch (IOException e) {
e.printStackTrace();
}
}
}
}
And finally the non-inner class server endpoint that works when the server uses it:
package tyrus.example;
import javax.websocket.CloseReason;
import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
@ServerEndpoint("/myapp")
public class SimpleServerEndpoint {
@OnOpen
public void onOpen(Session session) {
System.out.println("Connection received for "+session.getRequestURI());
}
@OnMessage
public void onMessage(String message, Session session) {
System.out.println("Message received: "+message);
}
@OnClose
public void onClose(Session session, CloseReason closeReason) {
System.out.println("Session closed, reason: "+closeReason);
}
}
Aucun commentaire:
Enregistrer un commentaire