configuring comet with spring

136 views
Skip to first unread message

Luis Montes

unread,
Sep 30, 2009, 10:27:45 AM9/30/09
to cometd...@googlegroups.com

There was a post a while back before I joined the list that discussed configuring comet with spring.

Just thought I'd post the details on how I got it work (maybe this would be better on a blog, but I'm not much of a blogger).  I wanted to try and do the spring configuration with as little custom code as possible so I could keep up to date with the latest ContinuationCometdServlet.

Any suggestions for improvements on this process are appreciated.  The timing of things initializing is important.

1:  Configure the ContinuationCometdServlet (cometd) servlet as usual in web.xml just make sure it has a load-on-startup property set.

2:  An important thing we need to put into our spring applicationContext.xml is:

    <bean id="bayeux" class="org.cometd.server.continuation.ContinuationBayeux" />
   
    <bean class="org.springframework.web.context.support.ServletContextAttributeExporter">
        <property name="attributes">
        <map>
            <entry key="org.cometd.bayeux"><ref bean="bayeux"/></entry>
        </map>
        </property>
    </bean>
   
    This creates the Bayeux object and puts it into the ServletContext before the cometd servlet starts up.
   
3: Configure your Bayeux Services

    <bean id="testService" class="com.testpackage.TestService" lazy-init="true" >
        <constructor-arg><ref bean="bayeux"/></constructor-arg>
    </bean>
   
    <bean id="testService2" class="com.testpackage.TestService2" lazy-init="true" >
        <constructor-arg><ref bean="bayeux"/></constructor-arg>
    </bean>
   
    <bean id="bayeuxServiceList" class="org.springframework.beans.factory.config.ListFactoryBean" lazy-init="true">
        <property name="sourceList">
            <list>
            <ref bean="testService" />
            <ref bean="testService2" />
            </list>
        </property>
    </bean>
   
    The important part here is that the services and the List holding them are set to lazy-init.  The Bayeux object for the service constructors wont be ready until after the cometd servlet initializes.
   
4:  The one custom piece of code I'm not sure how to do without yet is a servlet that simply initializes the spring configured Bayeux services after the Bayeux object has been properly initialized by the cometd servlet.

    import org.springframework.web.context.WebApplicationContext;
    import org.springframework.web.context.support.WebApplicationContextUtils;
    public class SpringBayeuxInitServlet extends GenericServlet
    {
     
        @Override

        public void service (ServletRequest req, ServletResponse res)  throws ServletException,  IOException
        {
            ((HttpServletResponse)res).sendError(503);
        }
       
        @Override
        public void init () throws ServletException
        {          
            WebApplicationContext wac = WebApplicationContextUtils.getRequiredWebApplicationContext(getServletContext());
            wac.getBean ("bayeuxServiceList");
        }
    }
   
    This servlet must have a load-on-startup property set to initialize after the cometd servlet just as the chat demo servlet does. It doesn't need a servlet mapping since all it does is initialize the custom bayeux services.
   
   


Luis

Simone Bordet

unread,
Sep 30, 2009, 10:48:20 AM9/30/09
to cometd...@googlegroups.com
Hi,

On Wed, Sep 30, 2009 at 16:27, Luis Montes <mont...@gmail.com> wrote:
>
> There was a post a while back before I joined the list that discussed
> configuring comet with spring.
>
> Just thought I'd post the details on how I got it work (maybe this would be
> better on a blog, but I'm not much of a blogger).  I wanted to try and do
> the spring configuration with as little custom code as possible so I could
> keep up to date with the latest ContinuationCometdServlet.

I had the plan to document how I did it, and there's even a bug associated:
http://bugs.cometd.org/browse/COMETD-14

I did it in a different way, though.

What I miss in your approach is how the Bayeux object is initialized
and configured from the servlet, such as the call to
initialize(ServletContext), and all the settings performed by
AbstractCometdServlet.
Is it some Spring magic that I don't see ?

Simon
--
http://bordet.blogspot.com
---
Finally, no matter how good the architecture and design are,
to deliver bug-free software with optimal performance and reliability,
the implementation technique must be flawless. Victoria Livschitz

Luis Montes

unread,
Sep 30, 2009, 11:23:30 AM9/30/09
to cometd...@googlegroups.com


On Wed, Sep 30, 2009 at 7:48 AM, Simone Bordet <simone...@gmail.com> wrote:

Hi,

On Wed, Sep 30, 2009 at 16:27, Luis Montes <mont...@gmail.com> wrote:
>
> There was a post a while back before I joined the list that discussed
> configuring comet with spring.
>
> Just thought I'd post the details on how I got it work (maybe this would be
> better on a blog, but I'm not much of a blogger).  I wanted to try and do
> the spring configuration with as little custom code as possible so I could
> keep up to date with the latest ContinuationCometdServlet.

I had the plan to document how I did it, and there's even a bug associated:
http://bugs.cometd.org/browse/COMETD-14

I did it in a different way, though.

What I miss in your approach is how the Bayeux object is initialized
and configured from the servlet, such as the call to
initialize(ServletContext), and all the settings performed by
AbstractCometdServlet.
Is it some Spring magic that I don't see ?

Simon


The magic in step 2.  Since the ContinuationBayeux doesn't have lazy-init it's one of the first things to be instaniated(but not initialized) and the spring context gets a reference to it. The ServletContextAttributeExporter spring object is what puts the Bayeux obect into the ServletContext.

The ContinuationCometdServlet doesn't get instatiated and intialized until after the Bayeux object is already in the ServletContext.  The cool thing about that is that the ContinuationCometdServle's init() is smart enough to check if the Bayeux object is already in the ServletContext before instatiating it's own Bayeux object.  Then the ContinuationCometdServlet goes and initializes the settings on the Bayeux object that the services need to have.

Now since my custom BayuexServices are lazy-initialized, the constructors on them don't get called until my custom servlet asks for List that's holding them.  And I make sure that this happends after the ContinuationCometdServlet is done initializing.  Keeping them in a lazy-initialized List allows me to just add new services without having to modify my custom servlet.

If a BayeuxService is instantiated before the ContinuationCometdServlet properly initializes the Bayeux object, we run into problems.  For one, the AbstractBayeux class has a java.util.Random member which only gets instantiated in AbstractBayeu's init(ServletContext) method.  The BayeuxService constructor will do an operation on that Random and throw a NullPointerException.  This is probably fixable.

Luis

Simone Bordet

unread,
Nov 17, 2009, 11:22:25 AM11/17/09
to cometd...@googlegroups.com
Hi,
I have documented the way I used in my project to integrate with Spring, here:
http://cometd.org/documentation/cometd-java/server/services/integration-spring

I am still working on the documentation, but I would appreciate
comments on this.
A benefit of my approach is that it does not require lazy
initialization, but does require a bit of glue code.

I don't mind to document your approach, but I am a little nervous
about the fact that it is based on a few Cometd implementation
internals and requires lazy init of Bayeux services (and of the
services that depend on them).

Any discussion on how to improve will be great.

Simone Bordet

unread,
Feb 23, 2010, 4:12:12 AM2/23/10
to cometd...@googlegroups.com
Hi,

On Wed, Feb 17, 2010 at 17:47, Matthieu.R <mret...@ebcubes.com> wrote:
> The documentation on the cometd website is missing the servlet that
> initializes the list of services after the server has been start. This
> is a crucial part and can go unoticed until you actually try to send
> messages to the service channel.

I have clarified the documentation.
Feedback welcome.

Thanks,

Reply all
Reply to author
Forward
0 new messages