javatomcatembedded-tomcat-7

How can I programmatically add a websocket endpoint in embedded tomcat?


I've been trying for weeks to get websockets working with embedded tomcat. I've tried emulating the examples in the tomcat unit tests to no avail. This is the first time I've tried to use websockets so I'm likely making a foolish mistake. Does anyone have any simple "Echo" examples for embedded tomcat websockets?

public void run() {

    if(!new File(consoleAppBase).isDirectory())
    {
         consoleAppBase = Paths.get("").toAbsolutePath().toString() + File.separatorChar + "wepapp";
    }

    tomcat = new Tomcat();

    tomcat.getService().removeConnector(tomcat.getConnector()); // remove default
    tomcat.getService().addConnector(createSslConnector(ConfigManager.getWeb_securePort())); // add secure option

    StandardServer server = (StandardServer) tomcat.getServer();
    AprLifecycleListener listener = new AprLifecycleListener();
    server.addLifecycleListener(listener);

    try {
        SecurityConstraint constraint = new SecurityConstraint();
        constraint.setDisplayName("SSL Redirect Constraint");
        constraint.setAuthConstraint(true);
        SecurityCollection collection = new SecurityCollection();
        collection.addPattern("/*");
        constraint.addAuthRole("administrator");
        constraint.addCollection(collection);

        //create the console webapp.
        consoleContext = tomcat.addWebapp(consoleContextPath, consoleAppBase);
        consoleContext.addConstraint(constraint);

        //this allows that little login popup for the console webapp.
        LoginConfig loginConfig = new LoginConfig();
        loginConfig.setAuthMethod("BASIC");
        consoleContext.setLoginConfig(loginConfig);
        consoleContext.addSecurityRole("administrator");

        //this creates a valid user.
        tomcat.addUser(ConfigManager.getWeb_username(), Encryptor.decrypt(ConfigManager.getWeb_passwordEncrypted()));
        tomcat.addRole("admin", "administrator");

    } catch (ServletException e) {
        LogMaster.getWebServerLogger().error("Error launching Web Application. Stopping Web Server.");
        LogMaster.getErrorLogger().error("Error launching Web Application. Stopping Web Server.", e);
        return;
    }

    addServlets(); // this is where I usually call a convenience method to add servlets

    // How can I add websocket endpoints instead?

}

Solution

  • I was using WebSocket in such way:

    import javax.websocket.OnClose;
    import javax.websocket.OnError;
    import javax.websocket.OnOpen;
    import javax.websocket.Session;
    import javax.websocket.server.ServerEndpoint;
    //...
    
    @ServerEndpoint("/move")
    public class TestWebSocketEndPoint {//@OnMessage 
    public void onMessage(Session session, String message) {}
    private static final Queue<Session> QUEUE = new ConcurrentLinkedQueue<Session>();
    
    @OnOpen
    public void open(Session session) {
        QUEUE.add(session);
    }
    
    @OnError
    public void error(Session session, Throwable t) {
        StaticLogger.log(TestWebSocketEndPoint.class, t);
        QUEUE.remove(session);
    }
    
    @OnClose
    public void closedConnection(Session session) {
        QUEUE.remove(session);
    }
    
    public static void sendToAll(String message) throws IOException {
        ArrayList<Session> closedSessions = new ArrayList<Session>();
        for (Session session : QUEUE) {
            if (!session.isOpen()) {
                closedSessions.add(session);
            } else {
                session.getBasicRemote().sendText(message);
            }
        }
        QUEUE.removeAll(closedSessions);
    }
    }
    


    And JS call:

    var webSocket;
    webSocket = new WebSocket("ws://localhost:8585/test/move");
    webSocket.onmessage = function () {
        alert('test');
    }
    


    Java call:

      TestWebSocketEndPoint.sendToAll(result);