Cometd Oort Cluster - Spring configuration

466 views Asked by At

I am trying to enable Oort with multicast in our Comet app following this example. I just need the Oort now. Not the Seti part. But Oort doesn't seem to be working. I have the cometd debug enabled and I don't see Oort being initialized.

I also tested by running two instances of Oort nodes in my local(on different ports), say A and B. Have the client connect to node A. I would then publish a message from node A on /user/* channel and client receives it. But if I publish a message from node B, client doesn't get anything.

Spring Configuration:

import org.cometd.annotation.ServerAnnotationProcessor;
import org.cometd.bayeux.server.BayeuxServer;
import org.cometd.oort.Oort;
import org.cometd.oort.OortMulticastConfigServlet;
import org.cometd.oort.OortMulticastConfigurer;
import org.cometd.server.BayeuxServerImpl;
import org.cometd.server.transport.AsyncJSONTransport;
import org.cometd.server.transport.JSONTransport;
import org.cometd.websocket.server.WebSocketTransport;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.DestructionAwareBeanPostProcessor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.context.ServletContextAware;

import javax.annotation.PostConstruct;
import javax.servlet.ServletContext;

@Configuration
public class BayeuxInitializer implements DestructionAwareBeanPostProcessor, ServletContextAware {

    private ServerAnnotationProcessor processor;
    private ServletContext context;

    @PostConstruct
    private void init() {
        BayeuxServer bayeuxServer = bayeuxServer();
        this.processor = new ServerAnnotationProcessor(bayeuxServer);
        Oort oort = oort();
        oort.observeChannel("/user/*");
    }

    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 AsyncJSONTransport(bean));
        bean.setOption("timeout", 60000);
        bean.setOption("ws.timeout", 60000);
        bean.setOption("maxSessionsPerBrowser", 20);
        bean.setOption(ServletContext.class.getName(), context);
        bean.setOption("cometdURLMapping", "/,/svc");
        context.setAttribute(BayeuxServer.ATTRIBUTE, bean);
        return bean;
    }

    @Bean(initMethod = "start", destroyMethod = "stop")
    public Oort oort() {
        Oort oort = new Oort(bayeuxServer(), "http://localhost:8094/comet/svc");
        context.setAttribute(Oort.OORT_ATTRIBUTE, oort);
        return oort;
    }

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

web.xml:

    <servlet>
        <servlet-name>cometd</servlet-name>
        <servlet-class>org.cometd.server.CometDServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
        <async-supported>true</async-supported>
    </servlet>
    <servlet-mapping>
        <servlet-name>cometd</servlet-name>
        <url-pattern>/svc/*</url-pattern>
    </servlet-mapping>

Oort seems to be working if I initialize it in web.xml as below:

    <servlet>
        <servlet-name>cometd</servlet-name>
        <servlet-class>org.cometd.server.CometDServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
        <async-supported>true</async-supported>
    </servlet>
    <servlet-mapping>
        <servlet-name>cometd</servlet-name>
        <url-pattern>/svc/*</url-pattern>
    </servlet-mapping>


    <servlet>
        <servlet-name>oort</servlet-name>
        <servlet-class>org.cometd.oort.OortMulticastConfigServlet</servlet-class>
        <init-param>
            <param-name>oort.url</param-name>
            <param-value>http://localhost:8094/comet/svc</param-value>
        </init-param>
        <init-param>
            <param-name>oort.channels</param-name>
            <param-value>/user/*</param-value>
        </init-param>
        <load-on-startup>2</load-on-startup>
    </servlet>

But as per the documentation Oort should be initialized in Spring if BayeuxServer is being initialized in Spring. So my questions are:

  1. Is there anything wrong with my Oort Spring configuration?
  2. Considering Oort works for me with web.xml initialization, are there any problems with doing that(keeping BayeuxServer config in Spring itself)?
  3. The example here just initializes Oort object. How does cometd know whether its Multicast or Static?

cometd version: 3.0.10

jetty version: 9.3.11

Any help appreciated!

1

There are 1 answers

1
sbordet On BEST ANSWER

When you create an Oort object via Spring (or other embedded code), you have created a node, but it's not linked to other Oort nodes.

In your code, you call:

Oort oort = oort();
oort.observeChannel("/user/*");

This creates the node, configures it to observe messages on channel /user/* from other nodes, but it does not connect it with other nodes.

In the example you linked, there is the missing piece, where it calls:

oort.observeComet("http://cloud.cometd.org/cometd");

That call is commented out in the example because, being an example, it does not know the exact URI of the other node, so as an example uses http://cloud.cometd.org/cometd, but that URI does not point to an existing node - that is why is commented out.

Now, since you want to use multicast, the example you linked suggests to use OortMulticastConfigurer.

OortMulticastConfigurer is what is being used by OortMulticastConfigServlet that you successfully use in your web.xml.

Let's have a look at how OortMulticastConfigServlet uses OortMulticastConfigurer here.

As you can see, OortMulticastConfigurer is created, configured and started.

If you stay on the default values, the minimum code becomes:

configurer = new OortMulticastConfigurer(oort);
configurer.start();

Add those 2 lines to your BayeuxInitializer.init() method and you should be good to go.