我正在尝试使用cometd作为dropwizard的servlet,但是BayeuxServer似乎没有注入我的服务。我正在添加我的两个servlet(注意,我没有使用web.xml
因此我自己定义了params):
cometdConfig.put("services", MyService.class.getCanonicalName());
System.out.print("OrderService name: " + MyService.class.getCanonicalName());
environment.addServlet(AnnotationCometdServlet.class, "/cometd/*").addInitParams(cometdConfig).setInitOrder(1);
environment.addServlet(new MyServiceServlet(), "/orders/*").setInitOrder(2);
我的服务(这是我的代码失败的地方):
public class MyService
implements MyWatcher.Listener
{
@Inject
private BayeuxServer bayeuxServer;
@Session
private LocalSession sender;
private final String _channelName;
private ServerChannel _channel = null;
public OrderService() {
_channelName = "/cometd/";
initChannel();
}
private void initChannel() {
// I get an NPE here
bayeuxServer.createIfAbsent(_channelName, new ConfigurableServerChannel.Initializer() {
@Override
public void configureChannel(ConfigurableServerChannel channel) {
// ...
}
});
_channel = bayeuxServer.getChannel(_channelName);
}
}
我还尝试创建自己的BayeuxServer实例,但随后在BayeuxServerImpl.freeze();
中导致单独的NPE
任何人都知道如何使用dropwizard正确使用cometd?
答案 0 :(得分:3)
为了注入BayeuxServer
实例,CometD必须具有要注入的服务实例,在本例中是类MyService
的实例。
不幸的是,从构造函数(我认为你在上面命名为OrderService
),你调用的是initChannel()
方法,它尝试使用尚未提供的BayeuxServer
字段因为构造函数仍在执行而注入。
解决方案是将您的频道初始化推迟到使用@PostConstruct
注释的其他方法:
public class MyService
{
@Inject
private BayeuxServer bayeuxServer;
@Session
private LocalSession sender;
private final String _channelName;
private ServerChannel _channel;
public MyService()
{
_channelName = "/cometd/";
}
@PostConstruct
private void initChannel()
{
_channel = bayeuxServer.createChannelIfAbsent(_channelName).getReference();
}
}
使用的CometD API来自CometD 2.7.0,如果您使用较旧的CometD版本,我建议使用它。