Container-Agnostic Websocket throws NPE with Embedded Jetty

瘦欲@ 提交于 2019-12-08 07:02:32

问题


I'm writing a container-agnostic Websocket server. My development environment uses IntelliJ IDEA with an embedded Jetty version 9.3.11.v20160721 (embed code below).

My code, however, uses the Tomcat Websocket libraries, tomcat-websocket-api and tomcat-websocket, version 8.5.4.

I want to register the Websocket EndPoint with a ServletContextListener. Following some examples from the Tyrus project, as well as some answers on SO and in the Jetty mailing list by Joakim Erdfelt (@joakim-erdfelt), I wrote the following implementation and added it via a listener in web.xml.

The code enters the contextInitialized() method so that part seems to work properly, but unfortunately the ServletContext does not contain the attribute javax.websocket.server.ServerContainer and therefore it returns 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(); }
}

The only available attributes are 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

What am I doing wrong? Is this strictly an embedding-issue? Will it run properly in standard Jetty (i.e., not embedded)?

The embed code is below:

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();

回答1:


The JSR ServerContainer isn't initialized automatically in embedded-jetty.

Use the 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: The WebSocketServerContainerInitializer is a javax.servlet.ServerContainerInitializer and you could set up your embedded-jetty to execute that ServerContainerInitializer automatically.

If you heavily rely on bytecode scanning of annotations, or have a javax.websocket.server.ServerApplicationConfig implementation, then you'll want to have the ServerContainerInitializer execute automatically.

Note: the javax.servlet.ServerContainerInitializer is only valid for a org.eclipse.jetty.webapp.WebAppContext.

If you use the org.eclipse.jetty.servlet.ServletContextHandler (the more common form in embedded-jetty) then you cannot use a javax.servlet.ServerContainerInitializer.

To set that up, do this:

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);


来源:https://stackoverflow.com/questions/39440297/container-agnostic-websocket-throws-npe-with-embedded-jetty

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!