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 09:14:50 -0500

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. 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?


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.


> 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 :-)


>>
>
> 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
>