2016-09-11 4 views
1

J'écris un serveur Websocket agnostique de conteneur. Mon environnement de développement utilise IntelliJ IDEA avec une version intégrée de Jetty 9.3.11.v20160721 (code d'intégration ci-dessous). Toutefois, mon code utilise les bibliothèques Tomcat Websocket, tomcat-websocket-api et tomcat-websocket, version 8.5.4. Je veux enregistrer la Websocket EndPoint avec un ServletContextListener. Après quelques exemples du Tyrus project, ainsi que quelques réponses sur SO et dans la liste de diffusion de Jetty par Joakim Erdfelt (@ joakim-erdfelt), j'ai écrit l'implémentation suivante et l'ai ajoutée via un listener dans web.xml.Websocket conteneur-Agnostic jette NPE avec Embedded Jetty

Le code entre la méthode contextInitialized() afin que la partie semble fonctionner correctement, mais malheureusement le ServletContext ne contient pas l'attribut javax.websocket.server.ServerContainer et par conséquent il renvoie null.

@Override 
public void contextInitialized(ServletContextEvent servletContextEvent) { 

    final ServerContainer serverContainer = (ServerContainer) servletContextEvent 
      .getServletContext() 
      .getAttribute("javax.websocket.server.ServerContainer"); 

    // *** serverContainer is null *** 

    try { 
     serverContainer.addEndpoint(ChatAnnotation.class); 
    } 
    catch (DeploymentException e) { e.printStackTrace(); } 
} 

Les seuls attributs disponibles sont javax.servlet.context.tempdir, org.eclipse.jetty.util.DecoratedObjectFactory, org.eclipse.jetty.tlds, org.eclipse.jetty.resources, org.eclipse.jetty.server.Executor, org.eclipse.jetty.webFragments

Qu'est-ce que je fais mal? Est-ce strictement un problème d'intégration? Est-ce qu'il fonctionnera correctement dans la jetée standard (c.-à-d., Non incorporé)?

Le code embed est ci-dessous:

WebAppContext webapp = new WebAppContext(); 
webapp.setContextPath("/"); 
webapp.setResourceBase(webroot); 
webapp.setDescriptor(webroot + "/WEB-INF/web.xml"); 

Server server = new Server(); 

ServerConnector connector = new ServerConnector(server); 
connector.setPort(8080);    

server.setConnectors(new ServerConnector[] { connector }); 
server.setHandler(webapp);  
server.start(); 
server.join(); 

Répondre

2

La JSR ServerContainer n'est pas automatiquement initialisées dans la jetée intégrée.

Utilisez le WebSocketServerContainerInitializer ...

WebAppContext webapp = new WebAppContext(); 
webapp.setContextPath("/"); 
webapp.setResourceBase(webroot); 
webapp.setDescriptor(webroot + "/WEB-INF/web.xml"); 

Server server = new Server(); 

ServerConnector connector = new ServerConnector(server); 
connector.setPort(8080);    

server.setConnectors(new ServerConnector[] { connector }); 
server.setHandler(webapp); 

// Add this line 
WebSocketServerContainerInitializer.configureContext(webapp); 

server.start(); 
server.join(); 

Note: Le WebSocketServerContainerInitializer est un javax.servlet.ServerContainerInitializer et vous pouvez configurer votre embedded-jetty pour exécuter cette ServerContainerInitializer automatiquement.

Si vous vous reposez lourdement sur l'analyse de bytecode des annotations ou si vous avez une implémentation javax.websocket.server.ServerApplicationConfig, vous devez exécuter le ServerContainerInitializer automatiquement.

Remarque: le javax.servlet.ServerContainerInitializer n'est valide que pour un org.eclipse.jetty.webapp.WebAppContext.

Si vous utilisez le org.eclipse.jetty.servlet.ServletContextHandler (le formulaire le plus courant dans embedded-jetty), vous ne pouvez pas utiliser un javax.servlet.ServerContainerInitializer.

Pour établir cela, faites ceci:

private void enableAnnotationScanning(Server server) 
{ 
    Configuration.ClassList classlist = Configuration.ClassList.setServerDefault(server); 
    classlist.addAfter("org.eclipse.jetty.webapp.FragmentConfiguration", 
      "org.eclipse.jetty.plus.webapp.EnvConfiguration", 
      "org.eclipse.jetty.plus.webapp.PlusConfiguration"); 
    classlist.addBefore("org.eclipse.jetty.webapp.JettyWebXmlConfiguration", 
      "org.eclipse.jetty.annotations.AnnotationConfiguration"); 
} 

// ... later on ... 

Server server = new Server(); 
enableAnnotationScanning(server); 
+0

Merci pour la réponse rapide. Donc, pour clarifier, ceci est strictement un problème d'intégration et ne devrait pas se produire lorsqu'il est déployé dans des conteneurs Servlet standard, n'est-ce pas? – isapir

+0

L'ajout de cette ligne lance un autre NPE très tôt: 'Exception dans le thread" principal "java.lang.NullPointerException Déconnecté de la machine virtuelle cible, adresse: '127.0.0.1:50113', transport: 'socket' \t at org.eclipse .jetty.websocket.jsr356.server.deploy.WebSocketServerContainerInitializer.configureContext (WebSocketServerContainerInitializer.java: 100) ' – isapir

+0

J'ai mis à jour votre réponse. A dû déplacer la ligne après 'server.setHandler (webapp)' et cela a fixé les deux NPE. Merci! – isapir