我正在开发一个Spring-MVC应用程序,我正在尝试将Chat功能与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>
修改的
最后,这是与来自mtn: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 :(得分:0)
例外是由您的设计引起的:
自注册
以来,只能有一个BayeuxServer实例bean.setOption("ws.cometdURLMapping", "/cometd/*");
只能为一个实例调用。
解决方案:添加@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;
}