users@grizzly.java.net

Re: [Q] Bayeux Comet example with Grizzlets [was: Re: [Q] Grizzlets update clients connected to different servers]

From: ALT Mobile DEV <dev_at_altmobile.com>
Date: Fri, 18 Jan 2008 14:21:47 -0500

Hi... comments are embedded. much thanks.

--Zaid

http:/altmobile.com


On Jan 18, 2008, at 11:00 AM, Jeanfrancois Arcand wrote:

>
>
> ALT Mobile DEV wrote:
>> Hi, I've embedded a few more questions... thanks for your continued
>> help.
>> --Zaid
>> http://altmobile.com
>> On Jan 17, 2008, at 11:28 AM, Jeanfrancois Arcand wrote:
>>>
>>>
>>> ALT Mobile DEV wrote:
>>>> Hi and thank you for all the help.
>>>> My response is embedded below.
>>>> --Zaid
>>>> http://altmobile.com
>>>> On Jan 16, 2008, at 11:46 AM, Jeanfrancois Arcand wrote:
>>>>>
>>>>>
>>>>> ALT Mobile DEV wrote:
>>>>>> as expected... perfect :-)
>>>>>
>>>>> Thanks
>>>>>
>>>>>> Do you have a Bayeux Comet example with Grizzlets?
>>>>>
>>>>> Since cometd is a client side technology, you don't need to
>>>>> write any Grizzlet as by default, a cometd client will work with
>>>>> any web server that support the bayeux protocol (JSON based).
>>>>> Take a look at the following blog for a client examples
>>>>>
>>>>> http://weblogs.java.net/blog/jfarcand/archive/2007/11/finally_grizzly.html
>>>>>
>>>>> the way it works is the DOJO client is sending http request, and
>>>>> the request body take the form of a JSON message. On the server
>>>>> side, Grizzly Cometd implementation receive the request, decode
>>>>> the JSON message and execute the proper operation. Like I've
>>>>> said, any web server that understand bayeux will be able to
>>>>> decode the message.
>>>> [ZAID] yes, I used the blog as a reference for our current
>>>> Grizzlet implementation but it was not obvious to me how is the
>>>> channel/operation exposed to the Grizzlet:
>>>> [72] String action = req.getParameterValues("action")[0];
>>>> [73] String name = req.getParameterValues("name")[0];
>>>> Our current implementation of the Dynamic Mashup Server runs 1
>>>> mash-up on each Grizzly server which is connected to the Web 2.0
>>>> containers. That architecture works well for consumer mash-ups.
>>>> An alternative use case is found in enterprise dashboard-style
>>>> mash-ups where the AJAX browser client wants to display multiple
>>>> mash-ups on the same page. For example, a GlassFish dashboard
>>>> could display the compilation status/bug list of each GlassFish
>>>> component. So that's 10+ mash-ups where each mash-up aggregates 2
>>>> remote HTTP calls: 1 for the bug list and another for the
>>>> continues integration stuff.
>>>> If a Cometd/Bayeux client can request multiple channels/
>>>> operations to the server (port, Grizzly server, Grizzlet, Web 2.0
>>>> container) then that's the bees knees since we can selectively
>>>> update specific aspects of this meta mash-up client.
>>>>>
>>>>>
>>>>> Now you might want to have client that aren't supporting bayeux
>>>>> (they *don't* encode the request body using JSON) to be able to
>>>>> interact with the cometd 'channel' (be able to update bayeux
>>>>> clients). To do that, you can use Grizzly Comet or Grizzlet to
>>>>> get notification (or to push) data to those client. Before I go
>>>>> into the details, are you planning to use Comet *and* Cometd
>>>>> client (and do they have to interact each other via Grizzy Comet
>>>>> or Cometd)?
>>>>>
>>>> [ZAID] yes, with your help :-)
>>>>> If yes, get ready to get a long email explaining how to do
>>>>> it :-) :-)
>>>
>>> OK thank for the explanation. So what you need to do is to share
>>> information between CometContext(s). One of your CometContext will
>>> be the one registered with '/cometd', which is the one that
>>> support the bayeux protocol. The first steps for you will consist
>>> of bootstrapping the cometd implementation inside your Java
>>> startup classes
>>>
>>>> 109 selectorThread.setWebAppRootPath(folder);
>>>> 110 111 String adapterClass =
>>>> System.getProperty(ADAPTER);
>>>> 112 Adapter adapter;
>>>> 113 if (adapterClass == null){
>>>> 114 adapter = new CometdAdapter();
>>>> 115 } else {
>>>> 116 adapter = (Adapter)loadInstance(adapterClass);
>>>> 117 }
>>>
>> [ZAID] I assume that I do _not_ need to create a new subclass of
>> StaticResourcesAdapter since CometdAdapter registers the
>> CometContext correctly. But, I must create a separate
>> SelectorThread for the Bayeux clients and therefore open another
>> port , since there is a 1:1 relationship in Grizzly 1.7 between
>> SelectorThread and Adapter.
>
> Exact. Multi-Adapter support is right now supported in GlassFish v3.
> Having our own in Grizzly can be a good idea as well, but require
> more work as you need to map the request with the proper adapter. I
> can take a look if you need it and help testing :-)...we will
> compete more with v3 as this is one of their key extension they did
> with Grizzly (LOL)
>
>

[ZAID] for our first release of the Dynamic Mashup Server, it'll be ok
to run separate ports for the Comet and Cometd clients. So it's not an
urgent requirement.


> Also,
>> there does not seem a way for the Grizzlet to be invoked as with
>> the standard GrizzletAdapter.
>>> Next is to create a CometHandler who can be invoked everytime the
>>> cometd CometContext is updated:
>>>
>>>> CometHandler cometdListenerHandler = new CometHandler(){
>>>> ....
>>>> }
>>>> CometEngine.getEngine().getCometContext("/
>>>> cometd").addCometHandler(cometdListenerHandler);
>>>
>> [ZAID] If I understand correctly, this new CometHandler is simply
>> for my app to process the JSON messages since the
>> BayeuxCometHandler is doing the protocol work. The CometHandler
>> takes the place of Grizzlets in non-Cometd code. Is this correct?
>
> Correct. Grizzlet are just simplifying/hiding the complexity of
> Grizzly Comet. Grizzlet make it simple, but under the hood they are
> build on top of Grizzly Comet (like Cometd). So you have the choice
> of using Grizzly Comet, Grizzlet and Grizzly Continuation. By
> definition,
>
> Grizzly Comet supports
> ----------------------
> + Asynchronous Content Handler (async read and write)
> + Suspendable Requests (suspend/resume a request)
> + Container managed server push
>
> Grizzlet support
> -----------------
> + Suspendable Requests
> + Container Managed Server Push
>
> Grizzly Continuation
> ---------------------
> + Suspendable Requests
>
>
> Continuation/cometd/Grizzlet build on top of Grizzly Comet, which in
> turn build on top of Grizzly Asynchronous Request Processing (this
> is the foundation of Project Open ESB BTW). You can find more
> information about Comet/Continuation/Grizzlet here:
>
> http://weblogs.java.net/blog/jfarcand/archive/2008/01/slides_to_my_re.html
>
>> I was running the chat sample from the GlassFish download to
>> ensure that my CometHandler was working but got this:
>> Jan 18, 2008 8:45:09 AM
>> com.sun.grizzly.standalone.StaticResourcesAdapter <init>
>> INFO: New Servicing page from: /Users/.../ALTMobile/objsvr
>> Bayeux Server startup in 153 ms
>> Jan 18, 2008 8:48:34 AM com.sun.grizzly.http.DefaultProcessorTask
>> invokeAdapter
>> SEVERE: processorTask.serviceError
>> java.lang.ClassCastException: java.lang.Double cannot be cast to
>> java.lang.String
>> at
>> com.sun.grizzly.cometd.bayeux.VerbUtils.newHandshake(VerbUtils.java:
>> 125)
>> at
>> com.sun.grizzly.cometd.bayeux.VerbUtils.parseMap(VerbUtils.java:97)
>> at com.sun.grizzly.cometd.bayeux.VerbUtils.parse(VerbUtils.java:
>> 69)
>> at
>> com.sun.grizzly.cometd.EventRouterImpl.route(EventRouterImpl.java:91)
>> at
>> com
>> .sun
>> .grizzly.cometd.standalone.CometdAdapter.service(CometdAdapter.java:
>> 240) at
>> com
>> .sun
>> .grizzly
>> .http.DefaultProcessorTask.invokeAdapter(DefaultProcessorTask.java:
>> 599) at
>> com.sun.grizzly.comet.CometEngine.executeServlet(CometEngine.java:
>> 547)
>> at com.sun.grizzly.comet.CometEngine.handle(CometEngine.java:299)
>> at
>> com
>> .sun.grizzly.comet.CometAsyncFilter.doFilter(CometAsyncFilter.java:
>> 87)
>> at
>> com
>> .sun
>> .grizzly
>> .arp.DefaultAsyncExecutor.invokeFilters(DefaultAsyncExecutor.java:
>> 162) at
>> com
>> .sun
>> .grizzly
>> .arp.DefaultAsyncExecutor.interrupt(DefaultAsyncExecutor.java:
>> 140) at
>> com
>> .sun.grizzly.arp.AsyncProcessorTask.doTask(AsyncProcessorTask.java:
>> 79)
>> at com.sun.grizzly.http.TaskBase.call(TaskBase.java:346)
>> at
>> com.sun.grizzly.util.WorkerThreadImpl.run(WorkerThreadImpl.java:179)
>> I haven't had the chance to study and modify the JavaScript but I
>> wanted you to see if I missed something fundamental.
>
> Hum...this is strange. Is this with the trunk? Which version of
> Grizzly? Can you post your Javascript?
>
>

[ZAID] yes, it's from Jan 16 and it uses your modifications to
GrizzletAdaptor's constructor. Here's an HTTP Monitor screen shot of
the traffic... it GET's the index.html and then does a POST for the
handshake:

http://altmobile.com/images/grizzly_test/1.png

and here's the web page from the glassfish chat example:

http://altmobile.com/images/grizzly_test/2.png


I'll try to Google for a simpler dojo example but I just wanted to
ensure that my CometHandler was properly installed... but the
handshake seems to fail.



>>> So on every bayeux requests, the cometdListenerHandlsr.onEvent()
>>> will be invoked, containing the JSON message. You can parse the
>>> message and do something with it, like notifying other
>>> CometContext (ex: /comet_80) by invoking:
>>>
>>>> CometEngine.getEngine().getCometContext("/
>>>> comet_80").notify(JSON_parsed_message);
>> [ZAID] I haven't gotten this far but I'm hopeful :-)
>
> Let's fix the cometd problem first :-)
>
> Thanks
>
> -- jeanfrancois
>
>>>>
>>>
>>> By doing that, your Comet clients will be able to notified by
>>> Cometd clients.
>>>
>>> Does it make sense?
>>>
>>> Thanks!
>>>
>>> -- Jeanfrancois
>>>
>>>
>>>
>>>
>>>
>>>
>>>>>
>>>>> A+
>>>>>
>>>>> -- Jeanfrancois
>>>>>
>>>>>
>>>>>> continued thanks.
>>>>>> --Zaid
>>>>>> http://altmobile.com
>>>>>> On Jan 15, 2008, at 10:16 PM, Jeanfrancois Arcand wrote:
>>>>>>>
>>>>>>>
>>>>>>> Jeanfrancois Arcand wrote:
>>>>>>>> Hi,
>>>>>>>> ALT Mobile DEV wrote:
>>>>>>>>> Hi,
>>>>>>>>>
>>>>>>>>> I'm running multiple servers in the same JVM where each
>>>>>>>>> server is associated with a different instance of the same
>>>>>>>>> Grizllet class. Each server of course is bound to a
>>>>>>>>> different port.
>>>>>>>>>
>>>>>>>>> Confusingly, the unique content from each Grizzlet is pushed
>>>>>>>>> to all clients irrespective of the server:port they are
>>>>>>>>> connected.
>>>>>>>> Yes :-( I didn't expected that Grizzly will be used like you
>>>>>>>> just explained. Mainly, since Grizzly build on top of Grizzly
>>>>>>>> Comet, the CometHandler I did for Grizzly is registered as '/
>>>>>>>> comet'. Since there is only one CometEngine (this is a
>>>>>>>> singleton), all Grizzlet will be invoked when the Grizzly
>>>>>>>> Comet do a push, as internally it will do:
>>>>>>>
>>>>>>> Should have read:
>>>>>>>
>>>>>>> > Yes :-( I didn't expected that GrizzLET will be used like
>>>>>>> you just
>>>>>>> > explained. Mainly, since GrizzLET build on top of Grizzly
>>>>>>> Comet, the
>>>>>>> > CometHandler I did for GrizzLET is registered as '/comet'.
>>>>>>> Since there is
>>>>>>> > only one CometEngine (this is a singleton), all Grizzlets
>>>>>>> will be invoked
>>>>>>> > when the Grizzly Comet do a push, as internally it will do:
>>>>>>>
>>>>>>> Its Grizzlet that build on top of Grizzly Comet, nor Grizzly :-)
>>>>>>>
>>>>>>> A+
>>>>>>>
>>>>>>> --jeanfrancois
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>> cometContext.notify(...);
>>>>>>>> and the cometContext is bind to 'comet'.
>>>>>>>>>
>>>>>>>>> It seems that the AsyncConnection is shared across all
>>>>>>>>> Grizzlets and servers.
>>>>>>>>>
>>>>>>>>> I was expecting that:
>>>>>>>>>
>>>>>>>>> Grizzly server = unique port + unique Grizzlet instance +
>>>>>>>>> unique comet context.
>>>>>>>> OK I've just added a new API to let you customize the
>>>>>>>> cometContextName. When you initialize the GrizzlyAdapter,
>>>>>>>> just pass the name of the cometContext you want to use. In
>>>>>>>> your case, it can be the just the port like the following:
>>>>>>>>> 113 AsyncHandler asyncHandler = new
>>>>>>>>> DefaultAsyncHandler();
>>>>>>>>> 114 asyncHandler.addAsyncFilter(new
>>>>>>>>> CometAsyncFilter());
>>>>>>>>> 115 selectorThread.setAsyncHandler(asyncHandler);
>>>>>>>>> 116 117 118 GrizzletAdapter adapter = new
>>>>>>>>> GrizzletAdapter(String.valueOf(port));
>>>>>>>>> 119 selectorThread.setAdapter(adapter);
>>>>>>>>> 120 Grizzlet grizzlet =
>>>>>>>>> (Grizzlet)loadInstance(grizzletClassName);
>>>>>>>>> 121
>>>>>>>> Try it and let me know if that works :-) I've uploaded the
>>>>>>>> new artifacts to the m2 repository, or you can rebuild the
>>>>>>>> comet module to get the changes.
>>>>>>>> Thanks
>>>>>>>> -- Jeanfrancois
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> thanks for any help.
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> --Zaid
>>>>>>>>>
>>>>>>>>> http://altmobile.com
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> ---------------------------------------------------------------------
>>>>>>>>> To unsubscribe, e-mail: users-unsubscribe_at_grizzly.dev.java.net
>>>>>>>>> For additional commands, e-mail: users-help_at_grizzly.dev.java.net
>>>>>>>>>
>>>>>>>> ---------------------------------------------------------------------
>>>>>>>> To unsubscribe, e-mail: users-unsubscribe_at_grizzly.dev.java.net
>>>>>>>> For additional commands, e-mail: users-
>>>>>>>> help_at_grizzly.dev.java.net
>>>>>>>
>>>>>>> ---------------------------------------------------------------------
>>>>>>> To unsubscribe, e-mail: users-unsubscribe_at_grizzly.dev.java.net
>>>>>>> For additional commands, e-mail: users-help_at_grizzly.dev.java.net
>>>>>>>
>>>>>> ---------------------------------------------------------------------
>>>>>> To unsubscribe, e-mail: users-unsubscribe_at_grizzly.dev.java.net
>>>>>> For additional commands, e-mail: users-help_at_grizzly.dev.java.net
>>>>>
>>>>> ---------------------------------------------------------------------
>>>>> To unsubscribe, e-mail: users-unsubscribe_at_grizzly.dev.java.net
>>>>> For additional commands, e-mail: users-help_at_grizzly.dev.java.net
>>>>>
>>>> ---------------------------------------------------------------------
>>>> To unsubscribe, e-mail: users-unsubscribe_at_grizzly.dev.java.net
>>>> For additional commands, e-mail: users-help_at_grizzly.dev.java.net
>>>
>>> ---------------------------------------------------------------------
>>> To unsubscribe, e-mail: users-unsubscribe_at_grizzly.dev.java.net
>>> For additional commands, e-mail: users-help_at_grizzly.dev.java.net
>>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: users-unsubscribe_at_grizzly.dev.java.net
>> For additional commands, e-mail: users-help_at_grizzly.dev.java.net
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe_at_grizzly.dev.java.net
> For additional commands, e-mail: users-help_at_grizzly.dev.java.net
>