2016-09-11 9 views
1

Я пишу контейнер-агностический сервер Websocket. В моей среде разработки используется IntelliJ IDEA со встроенной версией Jetty 9.3.11.v20160721 (код для встраивания ниже).Контейнерно-агностический интернет-бросок NPE с встроенным причалом

Мой код, однако, использует библиотеки Tomcat Websocket, tomcat-websocket-api и tomcat-websocket, версия 8.5.4.

Я хочу зарегистрировать веб-сайт EndPoint с ServletContextListener. Следуя некоторым примерам из Tyrus project, а также некоторым ответам на SO и в списке рассылки Jetty от Joakim Erdfelt (@ joakim-erdfelt), я написал следующую реализацию и добавил ее через listener в 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.server.Executor, 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(); 

ответ

2

The JSR ServerContainer не инициализируется автоматически во встроенном-причале.

Используйте 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(); 

Примечание: WebSocketServerContainerInitializer является javax.servlet.ServerContainerInitializer и вы можете настроить ваш embedded-jetty выполнить что ServerContainerInitializer автоматически.

Если вы в значительной степени полагаетесь на сканирование аннотаций по байт-коду или имеете реализацию javax.websocket.server.ServerApplicationConfig, то вы должны автоматически выполнить команду ServerContainerInitializer.

Примечание: javax.servlet.ServerContainerInitializer действителен только для org.eclipse.jetty.webapp.WebAppContext.

Если вы используете org.eclipse.jetty.servlet.ServletContextHandler (более распространенная форма в встроенном причале), вы не можете использовать javax.servlet.ServerContainerInitializer.

Чтобы установить, что, сделайте следующее:

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

Спасибо за быстрый ответ. Поэтому, чтобы уточнить, это строго проблема внедрения и не должна возникать при развертывании в стандартные контейнеры Servlet, это правильно? – isapir

+0

Добавление этой строки накладывает еще один NPE на раннем этапе: «Исключение в потоке» main »java.lang.NullPointerException Отключено от целевой виртуальной машины, адрес: '127.0.0.1:50113', транспорт: 'socket' \t at org.eclipse .jetty.websocket.jsr356.server.deploy.WebSocketServerContainerInitializer.configureContext (WebSocketServerContainerInitializer.java: 100) ' – isapir

+0

Я обновил ваш ответ. Если бы вы переместили строку вниз после 'server.setHandler (webapp)' и зафиксировали оба NPE. Благодаря! – isapir