2015-04-13 9 views
0

Я работаю над приложением Spring-MVC, в котором я пытаюсь интегрировать функции чата с Cometd. Я получаю сообщение об ошибке, что несколько энтузиастов не могут быть развернуты по тому же пути. Может ли кто-нибудь сказать мне, что я делаю неправильно и как его решить. Большое спасибо.Cometd, предоставляющий несколько точек enpoint, не может быть развернут на тот же путь [/ cometd]

журнал

Ошибка:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'cometDInitializer.Processor': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private org.cometd.bayeux.server.BayeuxServer com.journaldev.spring.chat.CometDInitializer$Processor.bayeuxServer; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'bayeuxServer' defined in class path resource [com/journaldev/spring/chat/CometDInitializer.class]: Invocation of init method failed; nested exception is java.lang.RuntimeException: javax.websocket.DeploymentException: Multiple Endpoints may not be deployed to the same path [/cometd] 
    org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:292) 
    org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1185) 
    org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:537) 

Если кто-то хочет полный журнал ошибок, Here it is on pastebin

CometdInitializer.java:

@Component 
public class CometDInitializer implements ServletContextAware 
{ 
    private ServletContext servletContext; 

    @Bean(initMethod = "start", destroyMethod = "stop") 
    public BayeuxServer bayeuxServer() 
    { 
     BayeuxServerImpl bean = new BayeuxServerImpl(); 
     bean.setTransports(new WebSocketTransport(bean), new JSONTransport(bean), new JSONPTransport(bean)); 
     servletContext.setAttribute(BayeuxServer.ATTRIBUTE, bean); 
     bean.setOption(ServletContext.class.getName(), servletContext); 
     bean.setOption("ws.cometdURLMapping", "/cometd/*"); 
     return bean; 
    } 

    public void setServletContext(ServletContext servletContext) 
    { 
     this.servletContext = servletContext; 
    } 

    @Component 
    public static class Processor implements DestructionAwareBeanPostProcessor 
    { 
     @Inject 
     private BayeuxServer bayeuxServer; 
     private ServerAnnotationProcessor processor; 

     @PostConstruct 
     private void init() 
     { 
      this.processor = new ServerAnnotationProcessor(bayeuxServer); 
     } 

     @PreDestroy 
     private void destroy() 
     { 
     } 

     public Object postProcessBeforeInitialization(Object bean, String name) throws BeansException 
     { 
      processor.processDependencies(bean); 
      processor.processConfigurations(bean); 
      processor.processCallbacks(bean); 
      return bean; 
     } 

     public Object postProcessAfterInitialization(Object bean, String name) throws BeansException 
     { 
      return bean; 
     } 

     public void postProcessBeforeDestruction(Object bean, String name) throws BeansException 
     { 
      processor.deprocessCallbacks(bean); 
     } 
    } 
} 

HelloService.java:

@Named 
@Singleton 
@Service("helloService") 
public class HelloService 
{ 
    @Inject 
    private BayeuxServer bayeux; 
    @Session 
    private ServerSession serverSession; 

    @PostConstruct 
    public void init() 
    { 
    } 

    @Listener("/service/hello") 
    public void processHello(ServerSession remote, ServerMessage message) 
    { 
     System.out.println("We recieved a helo msg"); 
     Map<String, Object> input = message.getDataAsMap(); 
     String name = (String)input.get("name"); 

     Map<String, Object> output = new HashMap<>(); 
     output.put("greeting", "Hello, " + name); 
     remote.deliver(serverSession, "/hello", output); 
    } 
} 

application.js:

(function($) 
{ 
    var cometd = $.cometd; 

    $(document).ready(function() 
    { 
     function _connectionEstablished() 
     { 
      $('#body').append('<div>CometD Connection Established</div>'); 
     } 

     function _connectionBroken() 
     { 
      $('#body').append('<div>CometD Connection Broken</div>'); 
     } 

     function _connectionClosed() 
     { 
      $('#body').append('<div>CometD Connection Closed</div>'); 
     } 

     // Function that manages the connection status with the Bayeux server 
     var _connected = false; 
     function _metaConnect(message) 
     { 
      if (cometd.isDisconnected()) 
      { 
       _connected = false; 
       _connectionClosed(); 
       return; 
      } 

      var wasConnected = _connected; 
      _connected = message.successful === true; 
      if (!wasConnected && _connected) 
      { 
       _connectionEstablished(); 
      } 
      else if (wasConnected && !_connected) 
      { 
       _connectionBroken(); 
      } 
     } 

     // Function invoked when first contacting the server and 
     // when the server has lost the state of this client 
     function _metaHandshake(handshake) 
     { 
      if (handshake.successful === true) 
      { 
       cometd.batch(function() 
       { 
        cometd.subscribe('/hello', function(message) 
        { 
         $('#body').append('<div>Server Says: ' + message.data.greeting + '</div>'); 
        }); 
        // Publish on a service channel since the message is for the server only 
        cometd.publish('/service/hello', { name: 'World' }); 
       }); 
      } 
     } 

     // Disconnect when the page unloads 
     $(window).unload(function() 
     { 
      cometd.disconnect(true); 
     }); 

     var cometURL = location.protocol + "//" + location.host + config.contextPath + "/cometd"; 
     cometd.configure({ 
      url: cometURL, 
      logLevel: 'debug' 
     }); 

     cometd.addListener('/meta/handshake', _metaHandshake); 
     cometd.addListener('/meta/connect', _metaConnect); 

     cometd.handshake(); 
    }); 
})(jQuery); 

web.xml:

<servlet-mapping> 
     <servlet-name>cometd</servlet-name> 
     <url-pattern>/cometd/*</url-pattern> 
    </servlet-mapping> 
    <servlet> 
     <servlet-name>cometd</servlet-name> 
     <servlet-class>org.cometd.server.CometDServlet</servlet-class> 
     <init-param> 
      <param-name>transports</param-name> 
      <param-value>org.cometd.websocket.server.WebSocketTransport</param-value> 
     </init-param> 
     <init-param> 
      <param-name>ws.cometdURLMapping</param-name> 
      <param-value>/cometd/*</param-value> 
     </init-param> 

     <init-param> 
      <param-name>logLevel</param-name> 
      <param-value>3</param-value> 
     </init-param> 

     <load-on-startup>1</load-on-startup> 
    </servlet> 

Редактировать

Итак, наконец, это была версия неправильно матч из кода от MVN: archtype от cometd. Файл ниже работает:

@Component 
public class BayeuxInitializer implements DestructionAwareBeanPostProcessor, ServletContextAware 
{ 
    private BayeuxServer bayeuxServer; 
    private ServerAnnotationProcessor processor; 

    @Inject 
    private void setBayeuxServer(BayeuxServer bayeuxServer) 
    { 
     this.bayeuxServer = bayeuxServer; 
    } 

    @PostConstruct 
    private void init() 
    { 
     this.processor = new ServerAnnotationProcessor(bayeuxServer); 
    } 

    @PreDestroy 
    private void destroy() 
    { 
    } 

    public Object postProcessBeforeInitialization(Object bean, String name) throws BeansException 
    { 
     processor.processDependencies(bean); 
     processor.processConfigurations(bean); 
     processor.processCallbacks(bean); 
     return bean; 
    } 

    public Object postProcessAfterInitialization(Object bean, String name) throws BeansException 
    { 
     return bean; 
    } 

    public void postProcessBeforeDestruction(Object bean, String name) throws BeansException 
    { 
     processor.deprocessCallbacks(bean); 
    } 

    @Bean(initMethod = "start", destroyMethod = "stop") 
    public BayeuxServer bayeuxServer() 
    { 
     BayeuxServerImpl bean = new BayeuxServerImpl(); 
    // bean.setTransports(new WebSocketTransport(bean), new JSONTransport(bean), new JSONPTransport(bean)); 
     return bean; 
    } 

    public void setServletContext(ServletContext servletContext) 
    { 
     servletContext.setAttribute(BayeuxServer.ATTRIBUTE, bayeuxServer); 
    } 
} 

Любая помощь будет приятной. Большое спасибо. :-)

ответ

0

Исключение вызвано дизайна:

  • Там может быть только один экземпляр BayeuxServer, так как при регистрации

    bean.setOption("ws.cometdURLMapping", "/cometd/*"); 
    

    должен быть вызван только для одного экземпляра.

  • Существует несколько аннотаций @Inject. Таким образом генерируются несколько экземпляров. Один экземпляр на @Inject

Solution: Добавить @Singleton

@Bean(initMethod = "start", destroyMethod = "stop") 
@Singleton 
public BayeuxServer bayeuxServer() 

В настоящее время существует только один экземпляр BayeuxServer. Все @Inject получат один и тот же экземпляр.

Это работает, только если реализация JSR330 известна. (К сожалению, весна не !?)

жесткий кодированный путь для одиночек:

private static BayeuxServer beanInstance; 
public static synchronized BayeuxServer bayeuxServer() 
{ 
    if (beanInstance != null) 
     return beanInstance; 
    BayeuxServerImpl bean = new BayeuxServerImpl(); 
    bean.setTransports(new WebSocketTransport(bean), new JSONTransport(bean), new JSONPTransport(bean)); 
    servletContext.setAttribute(BayeuxServer.ATTRIBUTE, bean); 
    bean.setOption(ServletContext.class.getName(), servletContext); 
    bean.setOption("ws.cometdURLMapping", "/cometd/*"); 
    beanInstance = bean; 
    return beanInstance; 
} 
+0

Это не помогло, ошибка же, вот код ошибки: http://pastebin.com/ YkCvZTpC –

+0

Я также попытался изменить параметр bean.setOptions 2nd, ничего не работает в этом, я получаю ту же ошибку. –