Servlets 容器不可知Websocket抛出带有嵌入式码头的NPE

Servlets 容器不可知Websocket抛出带有嵌入式码头的NPE,servlets,websocket,jetty,embedded-jetty,java-websocket,Servlets,Websocket,Jetty,Embedded Jetty,Java Websocket,我正在编写一个容器无关的Websocket服务器。我的开发环境使用IntelliJ IDEA和嵌入式Jetty版本9.3.11.v20160721(下面的嵌入式代码) 但是,我的代码使用Tomcat Websocket库,Tomcat Websocket api和Tomcat Websocket,版本8.5.4 我想用ServletContextListener注册Websocket端点。根据Joakim Erdfelt(@Joakim Erdfelt))的Jetty邮件列表中的一些示例以及SO

我正在编写一个容器无关的Websocket服务器。我的开发环境使用IntelliJ IDEA和嵌入式Jetty版本
9.3.11.v20160721
(下面的嵌入式代码)

但是,我的代码使用Tomcat Websocket库,
Tomcat Websocket api
Tomcat Websocket
,版本
8.5.4

我想用
ServletContextListener
注册Websocket
端点。根据Joakim Erdfelt(@Joakim Erdfelt))的Jetty邮件列表中的一些示例以及SO上的一些答案,我编写了以下实现,并通过
web.xml
中的
侦听器添加了它

代码进入
contextInitialized()
方法,使该部分看起来工作正常,但不幸的是,ServletContext不包含属性
javax.websocket.server.ServerContainer
,因此返回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(); }
}
唯一可用的属性是
javax.servlet.context.tempdir
org.eclipse.jetty.util.DecoratedObjectFactory
org.eclipse.jetty.tlds
org.eclipse.jetty.resources
org.eclipse.jetty.webFragments

我做错了什么?这完全是一个嵌入问题吗?它是否能在标准码头正常运行(即未嵌入)

嵌入代码如下所示:

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

JSR ServerContainer未在嵌入式jetty中自动初始化

使用
WebSocketServerContainerInitializer

WebAppContext webapp=new WebAppContext();
webapp.setContextPath(“/”);
webapp.setResourceBase(webroot);
setDescriptor(webroot+“/WEB-INF/WEB.xml”);
服务器=新服务器();
ServerConnector连接器=新的ServerConnector(服务器);
连接器。设置端口(8080);
setConnectors(新的ServerConnector[]{connector});
setHandler(webapp);
//添加这一行
WebSocketServerContainerInitializer.configureContext(webapp);
server.start();
join();
注意:
WebSocketServerContainerInitializer
是一个
javax.servlet.ServerContainerInitializer
,您可以设置
嵌入式jetty
自动执行该
ServerContainerInitializer

如果您严重依赖于注释的字节码扫描,或者有一个
javax.websocket.server.ServerApplicationConfig
实现,那么您需要让
servercontainerinInitializer
自动执行

注意:
javax.servlet.ServerContainerInitializer
仅对
org.eclipse.jetty.webapp.WebAppContext
有效

如果使用
org.eclipse.jetty.servlet.ServletContextHandler
(嵌入式jetty中更常见的形式),则不能使用
javax.servlet.ServerContainerInitializer

要进行设置,请执行以下操作:

private void enableAnnotationScanning(服务器)
{
Configuration.ClassList ClassList=Configuration.ClassList.setServerDefault(服务器);
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”);
}
// ... 后来。。。
服务器=新服务器();
enableAnnotationScanning(服务器);

感谢您的及时回复。因此,澄清一下,这是一个严格的嵌入问题,在部署到标准Servlet容器时不应该发生,对吗?添加该行会在早期引发另一个NPE:
线程“main”java.lang.NullPointerException中的异常与目标VM断开连接,地址:'127.0.0.1:50113',传输:org.eclipse.jetty.websocket.jsr356.server.deploy.websocketservercontainerininitializer.configureContext(websocketservercontainerininitializer.java:100)
我更新了您的答案。必须在
server.setHandler(webapp)
之后下移行,这修复了两个NPE。谢谢只要在
jetty分发版中启用了
--module=websocket
,它就可以在不需要额外行的情况下工作。实际上,我试图避免扫描,因为它们会延长启动时间。嵌入式Jetty主要用于开发目的,因此添加该线路不是问题。我正在讨论是否在这个项目中使用
Jetty Websocket
Tomcat Websocket
,而Tomcat的依赖关系似乎更“有条理”(我可能错了),所以至少目前我选择了Tomcat。我可能会转用Jetty,因为你们在这里提供了巨大的支持。