tyrus
  1. tyrus
  2. TYRUS-161

My WebSocket application failed to deploy.

    Details

    • Type: Bug Bug
    • Status: Resolved
    • Priority: Blocker Blocker
    • Resolution: Invalid
    • Affects Version/s: None
    • Fix Version/s: 1.0-rc1
    • Component/s: None
    • Labels:
      None
    • Environment:

      Windows 7 SP1
      Glassfish v4_b80 zipped and exe versions.

      Description

      While I am deploying my application (that runs before on GFv4_b78) I got the following errors when registering and instantiating the endpoint:

      SEVERE:   WebModule[/RTRC]Exception starting filter WebSocket filter
      java.lang.InstantiationException
      	at org.apache.catalina.core.ApplicationFilterConfig.<init>(ApplicationFilterConfig.java:135)
      	at org.apache.catalina.core.StandardContext.filterStart(StandardContext.java:5297)
      	at org.apache.catalina.core.StandardContext.start(StandardContext.java:5909)
      	at com.sun.enterprise.web.WebModule.start(WebModule.java:691)
      	at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:1041)
      	at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:1024)
      	at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:747)
      	at com.sun.enterprise.web.WebContainer.loadWebModule(WebContainer.java:2291)
      	at com.sun.enterprise.web.WebContainer.loadWebModule(WebContainer.java:1937)
      	at com.sun.enterprise.web.WebApplication.start(WebApplication.java:139)
      	at org.glassfish.internal.data.EngineRef.start(EngineRef.java:122)
      	at org.glassfish.internal.data.ModuleInfo.start(ModuleInfo.java:291)
      	at org.glassfish.internal.data.ApplicationInfo.start(ApplicationInfo.java:352)
      	at com.sun.enterprise.v3.server.ApplicationLifecycle.deploy(ApplicationLifecycle.java:497)
      	at com.sun.enterprise.v3.server.ApplicationLifecycle.deploy(ApplicationLifecycle.java:219)
      	at org.glassfish.deployment.admin.DeployCommand.execute(DeployCommand.java:491)
      	at com.sun.enterprise.v3.admin.CommandRunnerImpl$2$1.run(CommandRunnerImpl.java:527)
      	at com.sun.enterprise.v3.admin.CommandRunnerImpl$2$1.run(CommandRunnerImpl.java:523)
      	at java.security.AccessController.doPrivileged(Native Method)
      	at javax.security.auth.Subject.doAs(Subject.java:356)
      	at com.sun.enterprise.v3.admin.CommandRunnerImpl$2.execute(CommandRunnerImpl.java:522)
      	at com.sun.enterprise.v3.admin.CommandRunnerImpl.doCommand(CommandRunnerImpl.java:546)
      	at com.sun.enterprise.v3.admin.CommandRunnerImpl.doCommand(CommandRunnerImpl.java:1423)
      	at com.sun.enterprise.v3.admin.CommandRunnerImpl.access$1500(CommandRunnerImpl.java:108)
      	at com.sun.enterprise.v3.admin.CommandRunnerImpl$ExecutionContext.execute(CommandRunnerImpl.java:1761)
      	at com.sun.enterprise.v3.admin.CommandRunnerImpl$ExecutionContext.execute(CommandRunnerImpl.java:1674)
      	at com.sun.enterprise.v3.admin.AdminAdapter.doCommand(AdminAdapter.java:534)
      	at com.sun.enterprise.v3.admin.AdminAdapter.onMissingResource(AdminAdapter.java:224)
      	at org.glassfish.grizzly.http.server.StaticHttpHandler.service(StaticHttpHandler.java:297)
      	at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:246)
      	at org.glassfish.grizzly.http.server.HttpHandler.runService(HttpHandler.java:191)
      	at org.glassfish.grizzly.http.server.HttpHandler.doHandle(HttpHandler.java:168)
      	at org.glassfish.grizzly.http.server.HttpServerFilter.handleRead(HttpServerFilter.java:189)
      	at org.glassfish.grizzly.filterchain.ExecutorResolver$9.execute(ExecutorResolver.java:119)
      	at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:288)
      	at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:206)
      	at org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:136)
      	at org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:114)
      	at org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:77)
      	at org.glassfish.grizzly.nio.transport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:838)
      	at org.glassfish.grizzly.strategies.AbstractIOStrategy.fireIOEvent(AbstractIOStrategy.java:113)
      	at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.run0(WorkerThreadIOStrategy.java:115)
      	at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.access$100(WorkerThreadIOStrategy.java:55)
      	at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy$WorkerThreadRunnable.run(WorkerThreadIOStrategy.java:135)
      	at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:564)
      	at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:544)
      	at java.lang.Thread.run(Thread.java:722)
      Caused by: javax.servlet.ServletException: Web socket server initialization failed.
      	at org.glassfish.tyrus.servlet.TyrusServletFilter.init(TyrusServletFilter.java:150)
      	at org.apache.catalina.core.ApplicationFilterConfig.getFilter(ApplicationFilterConfig.java:275)
      	at org.apache.catalina.core.ApplicationFilterConfig.<init>(ApplicationFilterConfig.java:131)
      	... 46 more
      Caused by: javax.websocket.DeploymentException: Text MessageHandler already registered.
      	at org.glassfish.tyrus.core.ErrorCollector.composeComprehensiveException(ErrorCollector.java:83)
      	at org.glassfish.tyrus.server.TyrusServerContainer.start(TyrusServerContainer.java:144)
      	at org.glassfish.tyrus.servlet.TyrusServletFilter.init(TyrusServletFilter.java:148)
      	... 48 more
      

      My Server code:

      /**
       *
       * @author mohamed_taman
       */
      @ServerEndpoint(value = "/server/register",
              decoders = {RunnerMessageConverter.class, LoginMessageDecoder.class},
              encoders = {RunnerMessageConverter.class})
      public class RTRCServer {
      ...........
      

        Activity

        Hide
        Pavel Bucek added a comment -

        Hi Mohamed,

        can you please provide more details? We would need to see whole RTRCServer class (at least method signatures) to be able to analyze this further.

        Thanks!

        Show
        Pavel Bucek added a comment - Hi Mohamed, can you please provide more details? We would need to see whole RTRCServer class (at least method signatures) to be able to analyze this further. Thanks!
        Hide
        Mohamed Taman added a comment -

        Hi Pavel

        Here is my code for RTRCServer

        package com.taman.rtrc.endpoint.server;
        
        import com.taman.rtrc.endpoint.data.LoginMessage;
        import com.taman.rtrc.endpoint.data.LoginMessageDecoder;
        import com.taman.rtrc.endpoint.data.RunnerMessage;
        import com.taman.rtrc.endpoint.data.RunnerMessageConverter;
        import java.io.IOException;
        import java.util.concurrent.ConcurrentHashMap;
        import java.util.logging.Level;
        import java.util.logging.Logger;
        import javax.websocket.DeploymentException;
        import javax.websocket.OnClose;
        import javax.websocket.OnMessage;
        import javax.websocket.OnOpen;
        import static javax.websocket.RemoteEndpoint.Basic;
        import javax.websocket.Session;
        import javax.websocket.server.ServerEndpoint;
        import org.glassfish.tyrus.server.Server;
        
        /**
         *
         * @author mohamed_taman
         */
        @ServerEndpoint(value = "/server/register",
                decoders = {RunnerMessageConverter.class, LoginMessageDecoder.class},
                encoders = {RunnerMessageConverter.class} )
        public class RTRCServer {
        
            final static Logger logger = Logger.getLogger(RTRCServer.class.getName());
            private static ConcurrentHashMap<String, Session> runners = new ConcurrentHashMap<>();
        
            @OnOpen
            public void init(Session runner) {
                try {
                    logger.info(runner.getId());
                    runner.getBasicRemote().sendText("Connected to RTRC server.");
                } catch (IOException ex) {
                    logger.log(Level.SEVERE, null, ex);
                }
            }
        
            @OnMessage
            public void handleMessage(RunnerMessage msg) {
                logger.info(msg.toString());
        
                broadcast(msg);
            }
        
            @OnMessage
            public boolean doLogin(LoginMessage msg, Session runner) {
        
                logger.info(msg.toString());
        
                runners.put(msg.getUsername(), runner);
        
                logger.log(Level.INFO, "Current runneres = {0}", runners.size());
        
                return true;
            }
        
            @OnClose
            public void disconnected(Session runner) {
                String username = null;
                logger.info("The web socket closed");
                for (String s : runners.keySet()) {
                    if (runners.equals(runners.get(s))) {
                        username = s;
                        runners.remove(s);
                        break;
                    }
                }
        
                logger.log(Level.INFO, "Current runneres = {0}", runners.size());
        
                if (username != null) {
                    // this.notifyAll(username, " has just left...rather abruptly !");
                }
            }
        
            private void broadcast(RunnerMessage msg) {
                logger.info("Broadcasting updated user list");
        
                for (Session nextSession : runners.values()) {
                    Basic remote = nextSession.getBasicRemote();
                    try {
                        remote.sendText(msg.toJSON());
                    } catch (IOException ioe) {
                        logger.log(Level.WARNING, "Error updating a client {0} : {1}", new Object[]{remote, ioe.getMessage()});
                    }
                }
            }
        
            public static void main(String[] args) throws DeploymentException {
        
                Server server = new Server("localhost", 2020, "/RTRC", RTRCServer.class);
        
                try {
                    server.start();
                    System.out.println("Press any key to exit");
                    System.in.read();
                } catch (IOException ex) {
                    logger.log(Level.SEVERE, null, ex);
                } finally {
                    server.stop();
                    System.out.println("Server stopped.");
                }
        
            }
        }
        
        Show
        Mohamed Taman added a comment - Hi Pavel Here is my code for RTRCServer package com.taman.rtrc.endpoint.server; import com.taman.rtrc.endpoint.data.LoginMessage; import com.taman.rtrc.endpoint.data.LoginMessageDecoder; import com.taman.rtrc.endpoint.data.RunnerMessage; import com.taman.rtrc.endpoint.data.RunnerMessageConverter; import java.io.IOException; import java.util.concurrent.ConcurrentHashMap; import java.util.logging.Level; import java.util.logging.Logger; import javax.websocket.DeploymentException; import javax.websocket.OnClose; import javax.websocket.OnMessage; import javax.websocket.OnOpen; import static javax.websocket.RemoteEndpoint.Basic; import javax.websocket.Session; import javax.websocket.server.ServerEndpoint; import org.glassfish.tyrus.server.Server; /** * * @author mohamed_taman */ @ServerEndpoint(value = "/server/register" , decoders = {RunnerMessageConverter.class, LoginMessageDecoder.class}, encoders = {RunnerMessageConverter.class} ) public class RTRCServer { final static Logger logger = Logger.getLogger(RTRCServer.class.getName()); private static ConcurrentHashMap< String , Session> runners = new ConcurrentHashMap<>(); @OnOpen public void init(Session runner) { try { logger.info(runner.getId()); runner.getBasicRemote().sendText( "Connected to RTRC server." ); } catch (IOException ex) { logger.log(Level.SEVERE, null , ex); } } @OnMessage public void handleMessage(RunnerMessage msg) { logger.info(msg.toString()); broadcast(msg); } @OnMessage public boolean doLogin(LoginMessage msg, Session runner) { logger.info(msg.toString()); runners.put(msg.getUsername(), runner); logger.log(Level.INFO, "Current runneres = {0}" , runners.size()); return true ; } @OnClose public void disconnected(Session runner) { String username = null ; logger.info( "The web socket closed" ); for ( String s : runners.keySet()) { if (runners.equals(runners.get(s))) { username = s; runners.remove(s); break ; } } logger.log(Level.INFO, "Current runneres = {0}" , runners.size()); if (username != null ) { // this .notifyAll(username, " has just left...rather abruptly !" ); } } private void broadcast(RunnerMessage msg) { logger.info( "Broadcasting updated user list" ); for (Session nextSession : runners.values()) { Basic remote = nextSession.getBasicRemote(); try { remote.sendText(msg.toJSON()); } catch (IOException ioe) { logger.log(Level.WARNING, "Error updating a client {0} : {1}" , new Object []{remote, ioe.getMessage()}); } } } public static void main( String [] args) throws DeploymentException { Server server = new Server( "localhost" , 2020, "/RTRC" , RTRCServer.class); try { server.start(); System .out.println( "Press any key to exit" ); System .in.read(); } catch (IOException ex) { logger.log(Level.SEVERE, null , ex); } finally { server.stop(); System .out.println( "Server stopped." ); } } }
        Hide
        Pavel Bucek added a comment -

        you have 2 message handlers for decodable (text?) type:

            @OnMessage
            public void handleMessage(RunnerMessage msg) {
                logger.info(msg.toString());
        
                broadcast(msg);
            }
        
            @OnMessage
            public boolean doLogin(LoginMessage msg, Session runner) {
        
                logger.info(msg.toString());
        
                runners.put(msg.getUsername(), runner);
        
                logger.log(Level.INFO, "Current runneres = {0}", runners.size());
        
                return true;
            }
        

        which is forbidden in latest spec draft.

        Show
        Pavel Bucek added a comment - you have 2 message handlers for decodable (text?) type: @OnMessage public void handleMessage(RunnerMessage msg) { logger.info(msg.toString()); broadcast(msg); } @OnMessage public boolean doLogin(LoginMessage msg, Session runner) { logger.info(msg.toString()); runners.put(msg.getUsername(), runner); logger.log(Level.INFO, "Current runneres = {0}" , runners.size()); return true ; } which is forbidden in latest spec draft.
        Hide
        Pavel Bucek added a comment -

        (and that rule was introduced after glassfish build 78, so it might seem as a regression, but it is not. Tyrus just started behaving according to WebSocket spec.)

        Show
        Pavel Bucek added a comment - (and that rule was introduced after glassfish build 78, so it might seem as a regression, but it is not. Tyrus just started behaving according to WebSocket spec.)
        Hide
        Pavel Bucek added a comment -

        closed as invalid, Tyrus correctly implements WebSocket spec in this case.

        You can always file an issue against specification, see http://java.net/jira/browse/WEBSOCKET_SPEC

        Show
        Pavel Bucek added a comment - closed as invalid, Tyrus correctly implements WebSocket spec in this case. You can always file an issue against specification, see http://java.net/jira/browse/WEBSOCKET_SPEC

          People

          • Assignee:
            Pavel Bucek
            Reporter:
            Mohamed Taman
          • Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: