问题
I'm trying to use cometd as a servlet to dropwizard but BayeuxServer doesn't seem to get injected in my service. I'm adding my two servlets as so (note, I'm not using web.xml
so I'm defining the params myself):
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);
And my service (this is where my code fails):
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);
}
}
I have also tried creating my own instance of the BayeuxServer but then that leads to a separate NPE in BayeuxServerImpl.freeze();
Anyone know how to properly use cometd with dropwizard?
回答1:
In order to inject the BayeuxServer
instance, CometD must have the instance of the service to inject to, in this case an instance of your class MyService
.
Unfortunately, from the constructor (which I think you misnamed above, calling it OrderService
) you are calling the initChannel()
method, which tries to use the BayeuxServer
field which is not yet injected because the constructor is still executing.
The solution is to defer your channel initialization to a different method annotated with @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();
}
}
The CometD API used is from CometD 2.7.0, which I recommend to use if you are on older CometD versions.
来源:https://stackoverflow.com/questions/20154457/using-cometd-in-dropwizard