Question

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?

Was it helpful?

Solution

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top