[FYI} Simple RESTFul Pub/Sub sample

42 messages Options
Embed this post
Permalink
1 2 3
Jeanfrancois Arcand

[FYI} Simple RESTFul Pub/Sub sample

Reply Threaded More More options
Print post
Permalink
Salut,

FYI I've just commited a very simple pub/sub sample called
atmosphere-pubsub. You can browse the code here:

>     @Suspend
>     @GET
>     @Path("/{topic}")
>     @Produces("text/txt;charset=ISO-8859-1")
>     public Broadcastable subscribe(@Context BroadcasterLookup bl,
>                                    @Context Broadcaster br,
>                                    @PathParam("topic") String topic) {
>
>         StringBuilder b = new StringBuilder();
>         // For IE, Safari and Chrome, we must output some junk to enable
>         // streaming
>         for (int i = 0; i < 10; i++) {
>             b.append(JUNK);
>         }
>
>         Broadcaster broadcaster = null;
>         try {
>             broadcaster = bl.lookup(topic);
>         } catch (OutOfScopeException ex) {
>             Logger.getLogger(PubSub.class.getName()).log(Level.SEVERE, null, ex);
>         }
>
>         // Just use the one we just got
>         if (broadcaster == null){
>             broadcaster = br;
>             broadcaster.setName(topic);
>         }
>
>         Broadcastable broadcastible = new Broadcastable(b.toString(),broadcaster);
>
>         return broadcastible;
>     }
>
>     @GET
>     @Path("/{topic}/{message}")
>     @Produces("text/txt;charset=ISO-8859-1")
>     @Broadcast
>     public Broadcastable publish(@Context BroadcasterLookup bl,
>                                  @PathParam("topic") String topic,
>                                  @PathParam("message") String message){
>
>         Broadcaster broadcaster = null;
>         try {
>             broadcaster = bl.lookup(topic);
>         } catch (OutOfScopeException ex) {
>             Logger.getLogger(PubSub.class.getName()).log(Level.SEVERE, null, ex);
>         }
>         Broadcastable broadcastible = new Broadcastable(message,broadcaster);
>
>         return broadcastible;
>     }


To subscribe to a queue/topic, you just need to do:

    /atmosphere-pubsub/atmosphere_is_cool

To publish, you just need to do:

    /atmosphere-pubsub/atmosphere_is_cool/really_cool

This sample demonstrate the power of injecting Broadcaster and
BroadcasterLookup instance to reduce lines of code :-)

Feedback appreciated as I'm sure we can make it event simpler.

Thanks!

-- Jeanfrancois


---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

gerard davison

Re: [FYI} Simple RESTFul Pub/Sub sample

Reply Threaded More More options
Print post
Permalink

Is the following possible?

Gerard


    @Suspend
    @GET
    @Path("/{topic}")
    @Produces("text/txt;charset=ISO-8859-1")
    public Broadcastable subscribe(@PathParam("topic") Broadcaster topic) {

        StringBuilder b = new StringBuilder();
        // For IE, Safari and Chrome, we must output some junk to enable
        // streaming
        for (int i = 0; i < 10; i++) {
            b.append(JUNK);
        }

        //

        Broadcastable broadcastible = new
Broadcastable(b.toString(),broadcaster);

        return broadcastible;
    }

    @GET
    @Path("/{topic}/{message}")
    @Produces("text/txt;charset=ISO-8859-1")
    @Broadcast
    public Broadcastable publish(@PathParam("message) String message,
                                                 @PathParam("topic")
Broadcaster broadcaster){

        Broadcastable broadcastible = new
Broadcastable(message,broadcaster);

        return broadcastible;
    }




On 27/10/2009 02:07, Jeanfrancois Arcand wrote:

> Salut,
>
> FYI I've just commited a very simple pub/sub sample called
> atmosphere-pubsub. You can browse the code here:
>
>>     @Suspend
>>     @GET
>>     @Path("/{topic}")
>>     @Produces("text/txt;charset=ISO-8859-1")
>>     public Broadcastable subscribe(@Context BroadcasterLookup bl,
>>                                    @Context Broadcaster br,
>>                                    @PathParam("topic") String topic) {
>>
>>         StringBuilder b = new StringBuilder();
>>         // For IE, Safari and Chrome, we must output some junk to enable
>>         // streaming
>>         for (int i = 0; i < 10; i++) {
>>             b.append(JUNK);
>>         }
>>
>>         Broadcaster broadcaster = null;
>>         try {
>>             broadcaster = bl.lookup(topic);
>>         } catch (OutOfScopeException ex) {
>>            
>> Logger.getLogger(PubSub.class.getName()).log(Level.SEVERE, null, ex);
>>         }
>>
>>         // Just use the one we just got
>>         if (broadcaster == null){
>>             broadcaster = br;
>>             broadcaster.setName(topic);
>>         }
>>
>>         Broadcastable broadcastible = new
>> Broadcastable(b.toString(),broadcaster);
>>
>>         return broadcastible;
>>     }
>>
>>     @GET
>>     @Path("/{topic}/{message}")
>>     @Produces("text/txt;charset=ISO-8859-1")
>>     @Broadcast
>>     public Broadcastable publish(@Context BroadcasterLookup bl,
>>                                  @PathParam("topic") String topic,
>>                                  @PathParam("message") String message){
>>
>>         Broadcaster broadcaster = null;
>>         try {
>>             broadcaster = bl.lookup(topic);
>>         } catch (OutOfScopeException ex) {
>>            
>> Logger.getLogger(PubSub.class.getName()).log(Level.SEVERE, null, ex);
>>         }
>>         Broadcastable broadcastible = new
>> Broadcastable(message,broadcaster);
>>
>>         return broadcastible;
>>     }
>
>
> To subscribe to a queue/topic, you just need to do:
>
>    /atmosphere-pubsub/atmosphere_is_cool
>
> To publish, you just need to do:
>
>    /atmosphere-pubsub/atmosphere_is_cool/really_cool
>
> This sample demonstrate the power of injecting Broadcaster and
> BroadcasterLookup instance to reduce lines of code :-)
>
> Feedback appreciated as I'm sure we can make it event simpler.
>
> Thanks!
>
> -- Jeanfrancois
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [hidden email]
> For additional commands, e-mail: [hidden email]
>

--
Gerard Davison | Senior Principal Software Engineer | +44 118 924 5095
Oracle JDeveloper Web Service Tooling Development
Oracle Corporation UK Ltd is a company incorporated in England & Wales.
Company Reg. No. 1782505.
Reg. office: Oracle Parkway, Thames Valley Park, Reading RG6 1RA.

Blog http://kingsfleet.blogspot.com


---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Jeanfrancois Arcand

Re: [FYI} Simple RESTFul Pub/Sub sample

Reply Threaded More More options
Print post
Permalink
Salut,

gerard davison wrote:

>
> Is the following possible?
>
> Gerard
>
>
>    @Suspend
>    @GET
>    @Path("/{topic}")
>    @Produces("text/txt;charset=ISO-8859-1")
>    public Broadcastable subscribe(@PathParam("topic") Broadcaster topic) {
>
>        StringBuilder b = new StringBuilder();
>        // For IE, Safari and Chrome, we must output some junk to enable
>        // streaming
>        for (int i = 0; i < 10; i++) {
>            b.append(JUNK);
>        }
>
>        //
>
>        Broadcastable broadcastible = new
> Broadcastable(b.toString(),broadcaster);
>
>        return broadcastible;
>    }

If I understand properly, you are injecting the Broadcaster directly.
That would be quite useful....I need to understand how this can be done
via Jersey.

Thanks

-- Jeanfrancois

>
>    @GET
>    @Path("/{topic}/{message}")
>    @Produces("text/txt;charset=ISO-8859-1")
>    @Broadcast
>    public Broadcastable publish(@PathParam("message) String message,
>                                                 @PathParam("topic")
> Broadcaster broadcaster){
>
>        Broadcastable broadcastible = new
> Broadcastable(message,broadcaster);
>
>        return broadcastible;
>    }
>
>
>
>
> On 27/10/2009 02:07, Jeanfrancois Arcand wrote:
>> Salut,
>>
>> FYI I've just commited a very simple pub/sub sample called
>> atmosphere-pubsub. You can browse the code here:
>>
>>>     @Suspend
>>>     @GET
>>>     @Path("/{topic}")
>>>     @Produces("text/txt;charset=ISO-8859-1")
>>>     public Broadcastable subscribe(@Context BroadcasterLookup bl,
>>>                                    @Context Broadcaster br,
>>>                                    @PathParam("topic") String topic) {
>>>
>>>         StringBuilder b = new StringBuilder();
>>>         // For IE, Safari and Chrome, we must output some junk to enable
>>>         // streaming
>>>         for (int i = 0; i < 10; i++) {
>>>             b.append(JUNK);
>>>         }
>>>
>>>         Broadcaster broadcaster = null;
>>>         try {
>>>             broadcaster = bl.lookup(topic);
>>>         } catch (OutOfScopeException ex) {
>>>            
>>> Logger.getLogger(PubSub.class.getName()).log(Level.SEVERE, null, ex);
>>>         }
>>>
>>>         // Just use the one we just got
>>>         if (broadcaster == null){
>>>             broadcaster = br;
>>>             broadcaster.setName(topic);
>>>         }
>>>
>>>         Broadcastable broadcastible = new
>>> Broadcastable(b.toString(),broadcaster);
>>>
>>>         return broadcastible;
>>>     }
>>>
>>>     @GET
>>>     @Path("/{topic}/{message}")
>>>     @Produces("text/txt;charset=ISO-8859-1")
>>>     @Broadcast
>>>     public Broadcastable publish(@Context BroadcasterLookup bl,
>>>                                  @PathParam("topic") String topic,
>>>                                  @PathParam("message") String message){
>>>
>>>         Broadcaster broadcaster = null;
>>>         try {
>>>             broadcaster = bl.lookup(topic);
>>>         } catch (OutOfScopeException ex) {
>>>            
>>> Logger.getLogger(PubSub.class.getName()).log(Level.SEVERE, null, ex);
>>>         }
>>>         Broadcastable broadcastible = new
>>> Broadcastable(message,broadcaster);
>>>
>>>         return broadcastible;
>>>     }
>>
>>
>> To subscribe to a queue/topic, you just need to do:
>>
>>    /atmosphere-pubsub/atmosphere_is_cool
>>
>> To publish, you just need to do:
>>
>>    /atmosphere-pubsub/atmosphere_is_cool/really_cool
>>
>> This sample demonstrate the power of injecting Broadcaster and
>> BroadcasterLookup instance to reduce lines of code :-)
>>
>> Feedback appreciated as I'm sure we can make it event simpler.
>>
>> Thanks!
>>
>> -- Jeanfrancois
>>
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: [hidden email]
>> For additional commands, e-mail: [hidden email]
>>
>

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Paul Sandoz

Re: [FYI} Simple RESTFul Pub/Sub sample

Reply Threaded More More options
Print post
Permalink

On Oct 27, 2009, at 4:55 PM, Jeanfrancois Arcand wrote:

> Salut,
>
> gerard davison wrote:
>> Is the following possible?
>> Gerard
>>   @Suspend
>>   @GET
>>   @Path("/{topic}")
>>   @Produces("text/txt;charset=ISO-8859-1")
>>   public Broadcastable subscribe(@PathParam("topic") Broadcaster  
>> topic) {
>>       StringBuilder b = new StringBuilder();
>>       // For IE, Safari and Chrome, we must output some junk to  
>> enable
>>       // streaming
>>       for (int i = 0; i < 10; i++) {
>>           b.append(JUNK);
>>       }
>>       //
>>       Broadcastable broadcastible = new  
>> Broadcastable(b.toString(),broadcaster);
>>       return broadcastible;
>>   }
>
> If I understand properly, you are injecting the Broadcaster  
> directly. That would be quite useful....I need to understand how  
> this can be done via Jersey.
>

It can be done :-)

@Provider
public final class PathParamInjectableProvider extends  
InjectableProvider<PathParam, Parameter> {
       public Injectable<Broadcaster> getInjectable(ComponentContext  
ic, PathParam a, Parameter c) {
           if (c.getParameterClass() != Broadcaster) return null;

           String parameterName = c.getSourceName();

           ...
       }
}

Paul.

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Paul Sandoz

Re: [FYI} Simple RESTFul Pub/Sub sample

Reply Threaded More More options
Print post
Permalink
BTW there is another way if you want to obtain a Broadcaster from any  
parameter value (header, cookie, query, matrix or path), see  
StringReaderProvder:

   https://jersey.dev.java.net/nonav/apidocs/1.1.2-ea/jersey/com/sun/jersey/spi/StringReaderProvider.html

Using this provider has the virtue of also working with default values  
[*].

Paul.

[*] Note that for deployment validation a StringReader will be called  
at initialization with the default value. I dunno if this will cause  
issues for the case of a Broadcaster type. If so we might be able to  
do something about that.


On Oct 27, 2009, at 5:11 PM, Paul Sandoz wrote:

>
> On Oct 27, 2009, at 4:55 PM, Jeanfrancois Arcand wrote:
>
>> Salut,
>>
>> gerard davison wrote:
>>> Is the following possible?
>>> Gerard
>>>  @Suspend
>>>  @GET
>>>  @Path("/{topic}")
>>>  @Produces("text/txt;charset=ISO-8859-1")
>>>  public Broadcastable subscribe(@PathParam("topic") Broadcaster  
>>> topic) {
>>>      StringBuilder b = new StringBuilder();
>>>      // For IE, Safari and Chrome, we must output some junk to  
>>> enable
>>>      // streaming
>>>      for (int i = 0; i < 10; i++) {
>>>          b.append(JUNK);
>>>      }
>>>      //
>>>      Broadcastable broadcastible = new  
>>> Broadcastable(b.toString(),broadcaster);
>>>      return broadcastible;
>>>  }
>>
>> If I understand properly, you are injecting the Broadcaster  
>> directly. That would be quite useful....I need to understand how  
>> this can be done via Jersey.
>>
>
> It can be done :-)
>
> @Provider
> public final class PathParamInjectableProvider extends  
> InjectableProvider<PathParam, Parameter> {
>      public Injectable<Broadcaster> getInjectable(ComponentContext  
> ic, PathParam a, Parameter c) {
>          if (c.getParameterClass() != Broadcaster) return null;
>
>          String parameterName = c.getSourceName();
>
>          ...
>      }
> }
>
> Paul.
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [hidden email]
> For additional commands, e-mail: [hidden email]
>


---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Jeanfrancois Arcand

Re: [FYI} Simple RESTFul Pub/Sub sample

Reply Threaded More More options
Print post
Permalink


Paul Sandoz wrote:
> BTW there is another way if you want to obtain a Broadcaster from any
> parameter value (header, cookie, query, matrix or path), see
> StringReaderProvder:
>
>  
> https://jersey.dev.java.net/nonav/apidocs/1.1.2-ea/jersey/com/sun/jersey/spi/StringReaderProvider.html 
>
>
> Using this provider has the virtue of also working with default values [*].

Thanks! I will work on that later today.

A+

-- Jeanfrancois

>
> Paul.
>
> [*] Note that for deployment validation a StringReader will be called at
> initialization with the default value. I dunno if this will cause issues
> for the case of a Broadcaster type. If so we might be able to do
> something about that.
>
>
> On Oct 27, 2009, at 5:11 PM, Paul Sandoz wrote:
>
>>
>> On Oct 27, 2009, at 4:55 PM, Jeanfrancois Arcand wrote:
>>
>>> Salut,
>>>
>>> gerard davison wrote:
>>>> Is the following possible?
>>>> Gerard
>>>>  @Suspend
>>>>  @GET
>>>>  @Path("/{topic}")
>>>>  @Produces("text/txt;charset=ISO-8859-1")
>>>>  public Broadcastable subscribe(@PathParam("topic") Broadcaster
>>>> topic) {
>>>>      StringBuilder b = new StringBuilder();
>>>>      // For IE, Safari and Chrome, we must output some junk to enable
>>>>      // streaming
>>>>      for (int i = 0; i < 10; i++) {
>>>>          b.append(JUNK);
>>>>      }
>>>>      //
>>>>      Broadcastable broadcastible = new
>>>> Broadcastable(b.toString(),broadcaster);
>>>>      return broadcastible;
>>>>  }
>>>
>>> If I understand properly, you are injecting the Broadcaster directly.
>>> That would be quite useful....I need to understand how this can be
>>> done via Jersey.
>>>
>>
>> It can be done :-)
>>
>> @Provider
>> public final class PathParamInjectableProvider extends
>> InjectableProvider<PathParam, Parameter> {
>>      public Injectable<Broadcaster> getInjectable(ComponentContext ic,
>> PathParam a, Parameter c) {
>>          if (c.getParameterClass() != Broadcaster) return null;
>>
>>          String parameterName = c.getSourceName();
>>
>>          ...
>>      }
>> }
>>
>> Paul.
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: [hidden email]
>> For additional commands, e-mail: [hidden email]
>>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [hidden email]
> For additional commands, e-mail: [hidden email]
>

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Jeanfrancois Arcand

Re: [FYI} Simple RESTFul Pub/Sub sample

Reply Threaded More More options
Print post
Permalink
Done. I've updated the sample

   * http://is.gd/4LegQ

Blog coming...

A+

-- Jeanfrancois


Jeanfrancois Arcand wrote:

>
>
> Paul Sandoz wrote:
>> BTW there is another way if you want to obtain a Broadcaster from any
>> parameter value (header, cookie, query, matrix or path), see
>> StringReaderProvder:
>>
>>  
>> https://jersey.dev.java.net/nonav/apidocs/1.1.2-ea/jersey/com/sun/jersey/spi/StringReaderProvider.html 
>>
>>
>> Using this provider has the virtue of also working with default values
>> [*].
>
> Thanks! I will work on that later today.
>
> A+
>
> -- Jeanfrancois
>
>>
>> Paul.
>>
>> [*] Note that for deployment validation a StringReader will be called
>> at initialization with the default value. I dunno if this will cause
>> issues for the case of a Broadcaster type. If so we might be able to
>> do something about that.
>>
>>
>> On Oct 27, 2009, at 5:11 PM, Paul Sandoz wrote:
>>
>>>
>>> On Oct 27, 2009, at 4:55 PM, Jeanfrancois Arcand wrote:
>>>
>>>> Salut,
>>>>
>>>> gerard davison wrote:
>>>>> Is the following possible?
>>>>> Gerard
>>>>>  @Suspend
>>>>>  @GET
>>>>>  @Path("/{topic}")
>>>>>  @Produces("text/txt;charset=ISO-8859-1")
>>>>>  public Broadcastable subscribe(@PathParam("topic") Broadcaster
>>>>> topic) {
>>>>>      StringBuilder b = new StringBuilder();
>>>>>      // For IE, Safari and Chrome, we must output some junk to enable
>>>>>      // streaming
>>>>>      for (int i = 0; i < 10; i++) {
>>>>>          b.append(JUNK);
>>>>>      }
>>>>>      //
>>>>>      Broadcastable broadcastible = new
>>>>> Broadcastable(b.toString(),broadcaster);
>>>>>      return broadcastible;
>>>>>  }
>>>>
>>>> If I understand properly, you are injecting the Broadcaster
>>>> directly. That would be quite useful....I need to understand how
>>>> this can be done via Jersey.
>>>>
>>>
>>> It can be done :-)
>>>
>>> @Provider
>>> public final class PathParamInjectableProvider extends
>>> InjectableProvider<PathParam, Parameter> {
>>>      public Injectable<Broadcaster> getInjectable(ComponentContext
>>> ic, PathParam a, Parameter c) {
>>>          if (c.getParameterClass() != Broadcaster) return null;
>>>
>>>          String parameterName = c.getSourceName();
>>>
>>>          ...
>>>      }
>>> }
>>>
>>> Paul.
>>>
>>> ---------------------------------------------------------------------
>>> To unsubscribe, e-mail: [hidden email]
>>> For additional commands, e-mail: [hidden email]
>>>
>>
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: [hidden email]
>> For additional commands, e-mail: [hidden email]
>>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [hidden email]
> For additional commands, e-mail: [hidden email]
>

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Jarosław Lewandowski

Re: [FYI} Simple RESTFul Pub/Sub sample

Reply Threaded More More options
Print post
Permalink
Hi,

Is it really working? In my understanding if you suspend something on  
some topic than anything sent to this topic should only be delivered  
to this one, doesn't it? I've deployed your sample Pub/Sub  
applications and did simple test:

- opened two URL in a different web browsers (or simply using curl):

curl -N http://localhost:8080/atmosphere-pubsub/topic_A
curl -N http://localhost:8080/atmosphere-pubsub/topic_B

so both were suspended after that

- then loaded third url in a separate browser tab (or new curl command  
call):

curl -N http://localhost:8080/atmosphere-pubsub/topic_A/TEST

.... and guess what... both long polling connection got a message!

I think that problem is in the scope of the broadcaster... as in  
current implementation it's only one instance global for whole  
application... and look at this code from AtmosphereProviders:


   Broadcaster broadcaster = null;
                     try {
                         broadcaster = BroadcasterLookup.lookup(topic);
                     } catch (OutOfScopeException ex) {
                         LoggerUtils.getLogger().log(Level.SEVERE,  
null, ex);
                         throw new WebApplicationException(ex);
                     }

                     AtmosphereResource r = null;
                     // Just use the one we just got
                     if (broadcaster == null) {
                         if ((Boolean) req.getAttribute
(AsynchronousProcessor.SUPPORT_SESSION)) {
                             r = (AtmosphereResource) req.getSession().
                                     getAttribute
(AtmosphereFilter.SUSPENDED_RESOURCE);
                         }

                         if (r == null) {
                             r = (AtmosphereResource) req.getAttribute
(ReflectorServletProcessor.ATMOSPHERE_RESOURCE);
                         }

                         broadcaster = r.getBroadcaster();
                         broadcaster.setName(topic);


BroadcasterLookup can only lookup from APPLICATION or VM scope and if  
it fails than any the broadcaster from AtmosphereResource is taken and  
it's name is changed... so the following sequence of requests:

http://localhost:8080/atmosphere-pubsub/topic_1/TEST1
http://localhost:8080/atmosphere-pubsub/topic_3/TEST2
http://localhost:8080/atmosphere-pubsub/topic_4/TEST3
http://localhost:8080/atmosphere-pubsub/topic_5/TEST4
http://localhost:8080/atmosphere-pubsub/topic_6/TEST5

will work and broadcasting to every suspended connection and every  
time changing the name of the APP scope broadcaster (this will work  
even if previously there was no connection suspended in such topics)


Just wonder whether BroadcasteLookup shouldn't also support REQUESTs  
scope broadcasters? I'm also a little bit concerned about performance  
of BroadcasterLookup implementation and usage of ConcurrentLinkedQueue  
for storing broadcaster and it's O(n) complexity... Maybe it would be  
better to use ConcurrentHashMap instead ? Especially for this fragment  
of code:

    public final boolean add(Broadcaster b){
         String name = b.getName();
         if (getBroadcaster(name) != null) return false;
         return store.offer(b);
     }

isn't quite atomic and thread safe :( But on the other hand the name  
of the broadcaster is mutable :(


Regards
Jaro

On 2 Nov 2009, at 17:37, Jeanfrancois Arcand wrote:

> Done. I've updated the sample
>
>  * http://is.gd/4LegQ
>
> Blog coming...
>
> A+
>
> -- Jeanfrancois
>
>
> Jeanfrancois Arcand wrote:
>> Paul Sandoz wrote:
>>> BTW there is another way if you want to obtain a Broadcaster from  
>>> any parameter value (header, cookie, query, matrix or path), see  
>>> StringReaderProvder:
>>>
>>>  https://jersey.dev.java.net/nonav/apidocs/1.1.2-ea/jersey/com/sun/jersey/spi/StringReaderProvider.html
>>>
>>> Using this provider has the virtue of also working with default  
>>> values [*].
>> Thanks! I will work on that later today.
>> A+
>> -- Jeanfrancois
>>>
>>> Paul.
>>>
>>> [*] Note that for deployment validation a StringReader will be  
>>> called at initialization with the default value. I dunno if this  
>>> will cause issues for the case of a Broadcaster type. If so we  
>>> might be able to do something about that.
>>>
>>>
>>> On Oct 27, 2009, at 5:11 PM, Paul Sandoz wrote:
>>>
>>>>
>>>> On Oct 27, 2009, at 4:55 PM, Jeanfrancois Arcand wrote:
>>>>
>>>>> Salut,
>>>>>
>>>>> gerard davison wrote:
>>>>>> Is the following possible?
>>>>>> Gerard
>>>>>> @Suspend
>>>>>> @GET
>>>>>> @Path("/{topic}")
>>>>>> @Produces("text/txt;charset=ISO-8859-1")
>>>>>> public Broadcastable subscribe(@PathParam("topic") Broadcaster  
>>>>>> topic) {
>>>>>>     StringBuilder b = new StringBuilder();
>>>>>>     // For IE, Safari and Chrome, we must output some junk to  
>>>>>> enable
>>>>>>     // streaming
>>>>>>     for (int i = 0; i < 10; i++) {
>>>>>>         b.append(JUNK);
>>>>>>     }
>>>>>>     //
>>>>>>     Broadcastable broadcastible = new Broadcastable(b.toString
>>>>>> (),broadcaster);
>>>>>>     return broadcastible;
>>>>>> }
>>>>>
>>>>> If I understand properly, you are injecting the Broadcaster  
>>>>> directly. That would be quite useful....I need to understand how  
>>>>> this can be done via Jersey.
>>>>>
>>>>
>>>> It can be done :-)
>>>>
>>>> @Provider
>>>> public final class PathParamInjectableProvider extends  
>>>> InjectableProvider<PathParam, Parameter> {
>>>>     public Injectable<Broadcaster> getInjectable(ComponentContext  
>>>> ic, PathParam a, Parameter c) {
>>>>         if (c.getParameterClass() != Broadcaster) return null;
>>>>
>>>>         String parameterName = c.getSourceName();
>>>>
>>>>         ...
>>>>     }
>>>> }
>>>>
>>>> Paul.
>>>>
>>>> ---------------------------------------------------------------------
>>>> To unsubscribe, e-mail: [hidden email]
>>>> For additional commands, e-mail: [hidden email]
>>>>
>>>
>>>
>>> ---------------------------------------------------------------------
>>> To unsubscribe, e-mail: [hidden email]
>>> For additional commands, e-mail: [hidden email]
>>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: [hidden email]
>> For additional commands, e-mail: [hidden email]
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [hidden email]
> For additional commands, e-mail: [hidden email]
>


---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

gcstang

Re: [FYI} Simple RESTFul Pub/Sub sample

Reply Threaded More More options
Print post
Permalink
In reply to this post by Jeanfrancois Arcand
In firefox all I get back is a text file shouldn't it load in my browser?

I'm using Tomcat 6.0.20 and Firefox 3.5.4

Thank you,

Also the last post has merit ....I'm receiving the message (in IE) if I send to any of the topics not just the one I sent it through.
Jeanfrancois Arcand

Re: [FYI} Simple RESTFul Pub/Sub sample

Reply Threaded More More options
Print post
Permalink
In reply to this post by Jarosław Lewandowski
Salut,

Jaros?aw Lewandowski wrote:

> Hi,
>
> Is it really working? In my understanding if you suspend something on
> some topic than anything sent to this topic should only be delivered to
> this one, doesn't it? I've deployed your sample Pub/Sub applications and
> did simple test:
>
> - opened two URL in a different web browsers (or simply using curl):
>
> curl -N http://localhost:8080/atmosphere-pubsub/topic_A
> curl -N http://localhost:8080/atmosphere-pubsub/topic_B
>
> so both were suspended after that
>
> - then loaded third url in a separate browser tab (or new curl command
> call):
>
> curl -N http://localhost:8080/atmosphere-pubsub/topic_A/TEST
>
> .... and guess what... both long polling connection got a message!

ah! This is a regression I may have added when I implemented the
@PathParam Broadcaster injection.

>
> I think that problem is in the scope of the broadcaster...

Indeed.

  as in current

> implementation it's only one instance global for whole application...
> and look at this code from AtmosphereProviders:
>
>
>   Broadcaster broadcaster = null;
>                     try {
>                         broadcaster = BroadcasterLookup.lookup(topic);
>                     } catch (OutOfScopeException ex) {
>                         LoggerUtils.getLogger().log(Level.SEVERE, null,
> ex);
>                         throw new WebApplicationException(ex);
>                     }
>
>                     AtmosphereResource r = null;
>                     // Just use the one we just got
>                     if (broadcaster == null) {
>                         if ((Boolean)
> req.getAttribute(AsynchronousProcessor.SUPPORT_SESSION)) {
>                             r = (AtmosphereResource) req.getSession().
>                                    
> getAttribute(AtmosphereFilter.SUSPENDED_RESOURCE);
>                         }
>
>                         if (r == null) {
>                             r = (AtmosphereResource)
> req.getAttribute(ReflectorServletProcessor.ATMOSPHERE_RESOURCE);
>                         }
>
>                         broadcaster = r.getBroadcaster();
>                         broadcaster.setName(topic);
>
>
> BroadcasterLookup can only lookup from APPLICATION or VM scope and if it
> fails than any the broadcaster from AtmosphereResource is taken and it's
> name is changed... so the following sequence of requests:
>
> http://localhost:8080/atmosphere-pubsub/topic_1/TEST1
> http://localhost:8080/atmosphere-pubsub/topic_3/TEST2
> http://localhost:8080/atmosphere-pubsub/topic_4/TEST3
> http://localhost:8080/atmosphere-pubsub/topic_5/TEST4
> http://localhost:8080/atmosphere-pubsub/topic_6/TEST5
>
> will work and broadcasting to every suspended connection and every time
> changing the name of the APP scope broadcaster (this will work even if
> previously there was no connection suspended in such topics)
>
>
> Just wonder whether BroadcasteLookup shouldn't also support REQUESTs
> scope broadcasters?

But security wise, it will be difficult to block someone from getting
access to another Broadcaster. Let me explore.


  I'm also a little bit concerned about performance of

> BroadcasterLookup implementation and usage of ConcurrentLinkedQueue for
> storing broadcaster and it's O(n) complexity... Maybe it would be better
> to use ConcurrentHashMap instead ? Especially for this fragment of code:
>
>    public final boolean add(Broadcaster b){
>         String name = b.getName();
>         if (getBroadcaster(name) != null) return false;
>         return store.offer(b);
>     }
>
> isn't quite atomic and thread safe :( But on the other hand the name of
> the broadcaster is mutable :(

Let me work on that.

Thanks for the analysis!

--Jeanfrancois



>
>
> Regards
> Jaro
>
> On 2 Nov 2009, at 17:37, Jeanfrancois Arcand wrote:
>
>> Done. I've updated the sample
>>
>>  * http://is.gd/4LegQ
>>
>> Blog coming...
>>
>> A+
>>
>> -- Jeanfrancois
>>
>>
>> Jeanfrancois Arcand wrote:
>>> Paul Sandoz wrote:
>>>> BTW there is another way if you want to obtain a Broadcaster from
>>>> any parameter value (header, cookie, query, matrix or path), see
>>>> StringReaderProvder:
>>>>
>>>>  https://jersey.dev.java.net/nonav/apidocs/1.1.2-ea/jersey/com/sun/jersey/spi/StringReaderProvider.html 
>>>>
>>>>
>>>> Using this provider has the virtue of also working with default
>>>> values [*].
>>> Thanks! I will work on that later today.
>>> A+
>>> -- Jeanfrancois
>>>>
>>>> Paul.
>>>>
>>>> [*] Note that for deployment validation a StringReader will be
>>>> called at initialization with the default value. I dunno if this
>>>> will cause issues for the case of a Broadcaster type. If so we might
>>>> be able to do something about that.
>>>>
>>>>
>>>> On Oct 27, 2009, at 5:11 PM, Paul Sandoz wrote:
>>>>
>>>>>
>>>>> On Oct 27, 2009, at 4:55 PM, Jeanfrancois Arcand wrote:
>>>>>
>>>>>> Salut,
>>>>>>
>>>>>> gerard davison wrote:
>>>>>>> Is the following possible?
>>>>>>> Gerard
>>>>>>> @Suspend
>>>>>>> @GET
>>>>>>> @Path("/{topic}")
>>>>>>> @Produces("text/txt;charset=ISO-8859-1")
>>>>>>> public Broadcastable subscribe(@PathParam("topic") Broadcaster
>>>>>>> topic) {
>>>>>>>     StringBuilder b = new StringBuilder();
>>>>>>>     // For IE, Safari and Chrome, we must output some junk to enable
>>>>>>>     // streaming
>>>>>>>     for (int i = 0; i < 10; i++) {
>>>>>>>         b.append(JUNK);
>>>>>>>     }
>>>>>>>     //
>>>>>>>     Broadcastable broadcastible = new
>>>>>>> Broadcastable(b.toString(),broadcaster);
>>>>>>>     return broadcastible;
>>>>>>> }
>>>>>>
>>>>>> If I understand properly, you are injecting the Broadcaster
>>>>>> directly. That would be quite useful....I need to understand how
>>>>>> this can be done via Jersey.
>>>>>>
>>>>>
>>>>> It can be done :-)
>>>>>
>>>>> @Provider
>>>>> public final class PathParamInjectableProvider extends
>>>>> InjectableProvider<PathParam, Parameter> {
>>>>>     public Injectable<Broadcaster> getInjectable(ComponentContext
>>>>> ic, PathParam a, Parameter c) {
>>>>>         if (c.getParameterClass() != Broadcaster) return null;
>>>>>
>>>>>         String parameterName = c.getSourceName();
>>>>>
>>>>>         ...
>>>>>     }
>>>>> }
>>>>>
>>>>> Paul.
>>>>>
>>>>> ---------------------------------------------------------------------
>>>>> To unsubscribe, e-mail: [hidden email]
>>>>> For additional commands, e-mail: [hidden email]
>>>>>
>>>>
>>>>
>>>> ---------------------------------------------------------------------
>>>> To unsubscribe, e-mail: [hidden email]
>>>> For additional commands, e-mail: [hidden email]
>>>>
>>> ---------------------------------------------------------------------
>>> To unsubscribe, e-mail: [hidden email]
>>> For additional commands, e-mail: [hidden email]
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: [hidden email]
>> For additional commands, e-mail: [hidden email]
>>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [hidden email]
> For additional commands, e-mail: [hidden email]
>

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Jeanfrancois Arcand

Re: [FYI} Simple RESTFul Pub/Sub sample

Reply Threaded More More options
Print post
Permalink
In reply to this post by gcstang

Salut,

gcstang wrote:
> In firefox all I get back is a text file shouldn't it load in my browser?
>
> I'm using Tomcat 6.0.20 and Firefox 3.5.4

Hum I didn't try with a browser :-) Let me look at it.

A+

-- Jeanfrancois


>
> Thank you,

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Jeanfrancois Arcand

Re: [FYI} Simple RESTFul Pub/Sub sample

Reply Threaded More More options
Print post
Permalink
In reply to this post by Jeanfrancois Arcand
Salut,

I've fixed the Broadcaster's scope:

> Sending        atmosphere/modules/cpr/src/main/java/org/atmosphere/cpr/AtmosphereServlet.java
> Sending        atmosphere/modules/jersey/src/main/java/org/atmosphere/jersey/AtmosphereProviders.java
> Sending        atmosphere/samples/pubsub/src/main/java/org/atmosphere/samples/pubsub/PubSub.java
> Transmitting file data ...
> Committed revision 646.

It wasn't a regressions. Now that tells me the next things I need to
work on it to add unit test to avoid such stupid mistakes from me. Can
you try it and let me know?

I will go ahead and implements your recommendation for BroadcasterLookup.

A+

-- Jeanfrancois



Jeanfrancois Arcand wrote:

> Salut,
>
> Jaros?aw Lewandowski wrote:
>> Hi,
>>
>> Is it really working? In my understanding if you suspend something on
>> some topic than anything sent to this topic should only be delivered
>> to this one, doesn't it? I've deployed your sample Pub/Sub
>> applications and did simple test:
>>
>> - opened two URL in a different web browsers (or simply using curl):
>>
>> curl -N http://localhost:8080/atmosphere-pubsub/topic_A
>> curl -N http://localhost:8080/atmosphere-pubsub/topic_B
>>
>> so both were suspended after that
>>
>> - then loaded third url in a separate browser tab (or new curl command
>> call):
>>
>> curl -N http://localhost:8080/atmosphere-pubsub/topic_A/TEST
>>
>> .... and guess what... both long polling connection got a message!
>
> ah! This is a regression I may have added when I implemented the
> @PathParam Broadcaster injection.
>
>>
>> I think that problem is in the scope of the broadcaster...
>
> Indeed.
>
>  as in current
>> implementation it's only one instance global for whole application...
>> and look at this code from AtmosphereProviders:
>>
>>
>>   Broadcaster broadcaster = null;
>>                     try {
>>                         broadcaster = BroadcasterLookup.lookup(topic);
>>                     } catch (OutOfScopeException ex) {
>>                         LoggerUtils.getLogger().log(Level.SEVERE,
>> null, ex);
>>                         throw new WebApplicationException(ex);
>>                     }
>>
>>                     AtmosphereResource r = null;
>>                     // Just use the one we just got
>>                     if (broadcaster == null) {
>>                         if ((Boolean)
>> req.getAttribute(AsynchronousProcessor.SUPPORT_SESSION)) {
>>                             r = (AtmosphereResource) req.getSession().
>>                                    
>> getAttribute(AtmosphereFilter.SUSPENDED_RESOURCE);
>>                         }
>>
>>                         if (r == null) {
>>                             r = (AtmosphereResource)
>> req.getAttribute(ReflectorServletProcessor.ATMOSPHERE_RESOURCE);
>>                         }
>>
>>                         broadcaster = r.getBroadcaster();
>>                         broadcaster.setName(topic);
>>
>>
>> BroadcasterLookup can only lookup from APPLICATION or VM scope and if
>> it fails than any the broadcaster from AtmosphereResource is taken and
>> it's name is changed... so the following sequence of requests:
>>
>> http://localhost:8080/atmosphere-pubsub/topic_1/TEST1
>> http://localhost:8080/atmosphere-pubsub/topic_3/TEST2
>> http://localhost:8080/atmosphere-pubsub/topic_4/TEST3
>> http://localhost:8080/atmosphere-pubsub/topic_5/TEST4
>> http://localhost:8080/atmosphere-pubsub/topic_6/TEST5
>>
>> will work and broadcasting to every suspended connection and every
>> time changing the name of the APP scope broadcaster (this will work
>> even if previously there was no connection suspended in such topics)
>>
>>
>> Just wonder whether BroadcasteLookup shouldn't also support REQUESTs
>> scope broadcasters?
>
> But security wise, it will be difficult to block someone from getting
> access to another Broadcaster. Let me explore.
>
>
>  I'm also a little bit concerned about performance of
>> BroadcasterLookup implementation and usage of ConcurrentLinkedQueue
>> for storing broadcaster and it's O(n) complexity... Maybe it would be
>> better to use ConcurrentHashMap instead ? Especially for this fragment
>> of code:
>>
>>    public final boolean add(Broadcaster b){
>>         String name = b.getName();
>>         if (getBroadcaster(name) != null) return false;
>>         return store.offer(b);
>>     }
>>
>> isn't quite atomic and thread safe :( But on the other hand the name
>> of the broadcaster is mutable :(
>
> Let me work on that.
>
> Thanks for the analysis!
>
> --Jeanfrancois
>
>
>
>>
>>
>> Regards
>> Jaro
>>
>> On 2 Nov 2009, at 17:37, Jeanfrancois Arcand wrote:
>>
>>> Done. I've updated the sample
>>>
>>>  * http://is.gd/4LegQ
>>>
>>> Blog coming...
>>>
>>> A+
>>>
>>> -- Jeanfrancois
>>>
>>>
>>> Jeanfrancois Arcand wrote:
>>>> Paul Sandoz wrote:
>>>>> BTW there is another way if you want to obtain a Broadcaster from
>>>>> any parameter value (header, cookie, query, matrix or path), see
>>>>> StringReaderProvder:
>>>>>
>>>>>  https://jersey.dev.java.net/nonav/apidocs/1.1.2-ea/jersey/com/sun/jersey/spi/StringReaderProvider.html 
>>>>>
>>>>>
>>>>> Using this provider has the virtue of also working with default
>>>>> values [*].
>>>> Thanks! I will work on that later today.
>>>> A+
>>>> -- Jeanfrancois
>>>>>
>>>>> Paul.
>>>>>
>>>>> [*] Note that for deployment validation a StringReader will be
>>>>> called at initialization with the default value. I dunno if this
>>>>> will cause issues for the case of a Broadcaster type. If so we
>>>>> might be able to do something about that.
>>>>>
>>>>>
>>>>> On Oct 27, 2009, at 5:11 PM, Paul Sandoz wrote:
>>>>>
>>>>>>
>>>>>> On Oct 27, 2009, at 4:55 PM, Jeanfrancois Arcand wrote:
>>>>>>
>>>>>>> Salut,
>>>>>>>
>>>>>>> gerard davison wrote:
>>>>>>>> Is the following possible?
>>>>>>>> Gerard
>>>>>>>> @Suspend
>>>>>>>> @GET
>>>>>>>> @Path("/{topic}")
>>>>>>>> @Produces("text/txt;charset=ISO-8859-1")
>>>>>>>> public Broadcastable subscribe(@PathParam("topic") Broadcaster
>>>>>>>> topic) {
>>>>>>>>     StringBuilder b = new StringBuilder();
>>>>>>>>     // For IE, Safari and Chrome, we must output some junk to
>>>>>>>> enable
>>>>>>>>     // streaming
>>>>>>>>     for (int i = 0; i < 10; i++) {
>>>>>>>>         b.append(JUNK);
>>>>>>>>     }
>>>>>>>>     //
>>>>>>>>     Broadcastable broadcastible = new
>>>>>>>> Broadcastable(b.toString(),broadcaster);
>>>>>>>>     return broadcastible;
>>>>>>>> }
>>>>>>>
>>>>>>> If I understand properly, you are injecting the Broadcaster
>>>>>>> directly. That would be quite useful....I need to understand how
>>>>>>> this can be done via Jersey.
>>>>>>>
>>>>>>
>>>>>> It can be done :-)
>>>>>>
>>>>>> @Provider
>>>>>> public final class PathParamInjectableProvider extends
>>>>>> InjectableProvider<PathParam, Parameter> {
>>>>>>     public Injectable<Broadcaster> getInjectable(ComponentContext
>>>>>> ic, PathParam a, Parameter c) {
>>>>>>         if (c.getParameterClass() != Broadcaster) return null;
>>>>>>
>>>>>>         String parameterName = c.getSourceName();
>>>>>>
>>>>>>         ...
>>>>>>     }
>>>>>> }
>>>>>>
>>>>>> Paul.
>>>>>>
>>>>>> ---------------------------------------------------------------------
>>>>>> To unsubscribe, e-mail: [hidden email]
>>>>>> For additional commands, e-mail: [hidden email]
>>>>>>
>>>>>
>>>>>
>>>>> ---------------------------------------------------------------------
>>>>> To unsubscribe, e-mail: [hidden email]
>>>>> For additional commands, e-mail: [hidden email]
>>>>>
>>>> ---------------------------------------------------------------------
>>>> To unsubscribe, e-mail: [hidden email]
>>>> For additional commands, e-mail: [hidden email]
>>>
>>> ---------------------------------------------------------------------
>>> To unsubscribe, e-mail: [hidden email]
>>> For additional commands, e-mail: [hidden email]
>>>
>>
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: [hidden email]
>> For additional commands, e-mail: [hidden email]
>>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [hidden email]
> For additional commands, e-mail: [hidden email]
>

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Jeanfrancois Arcand

Re: [FYI} Simple RESTFul Pub/Sub sample

Reply Threaded More More options
Print post
Permalink
In reply to this post by Jeanfrancois Arcand


Jeanfrancois Arcand wrote:
>
> Salut,
>
> gcstang wrote:
>> In firefox all I get back is a text file shouldn't it load in my browser?
>>
>> I'm using Tomcat 6.0.20 and Firefox 3.5.4
>
> Hum I didn't try with a browser :-) Let me look at it.

OK I've fixed the sample on trunk:

    @Produces("text/plain;charset=ISO-8859-1")

Just replace all text/txt by text/plain.

My mistake.

A+

-_ jeanfrancois


>
> A+
>
> -- Jeanfrancois
>
>
>>
>> Thank you,
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [hidden email]
> For additional commands, e-mail: [hidden email]
>

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Paul Sandoz

Automated tests <was> Re: [FYI} Simple RESTFul Pub/Sub sample

Reply Threaded More More options
Print post
Permalink
In reply to this post by Jeanfrancois Arcand

On Nov 4, 2009, at 5:49 PM, Jeanfrancois Arcand wrote:

> Salut,
>
> I've fixed the Broadcaster's scope:
>
>> Sending        atmosphere/modules/cpr/src/main/java/org/atmosphere/
>> cpr/AtmosphereServlet.java
>> Sending        atmosphere/modules/jersey/src/main/java/org/
>> atmosphere/jersey/AtmosphereProviders.java
>> Sending        atmosphere/samples/pubsub/src/main/java/org/
>> atmosphere/samples/pubsub/PubSub.java
>> Transmitting file data ...
>> Committed revision 646.
>
> It wasn't a regressions.

Do we need to starting thinking about automated tests?

It would be good if we could automate the testing of the samples in  
some way as well has have unit tests for the modules. But i do not  
know what Web tools are appropriate for such such testing. A Java-
based comet client API for testing would be handy (i would like to try  
and integrate something with the Jersey client API so that could be  
used for testing but that is secondary to the main problem).

Paul.



> Now that tells me the next things I need to work on it to add unit  
> test to avoid such stupid mistakes from me. Can you try it and let  
> me know?
>
> I will go ahead and implements your recommendation for  
> BroadcasterLookup.
>
> A+
>
> -- Jeanfrancois
>
>
>
> Jeanfrancois Arcand wrote:
>> Salut,
>> Jaros?aw Lewandowski wrote:
>>> Hi,
>>>
>>> Is it really working? In my understanding if you suspend something  
>>> on some topic than anything sent to this topic should only be  
>>> delivered to this one, doesn't it? I've deployed your sample Pub/
>>> Sub applications and did simple test:
>>>
>>> - opened two URL in a different web browsers (or simply using curl):
>>>
>>> curl -N http://localhost:8080/atmosphere-pubsub/topic_A
>>> curl -N http://localhost:8080/atmosphere-pubsub/topic_B
>>>
>>> so both were suspended after that
>>>
>>> - then loaded third url in a separate browser tab (or new curl  
>>> command call):
>>>
>>> curl -N http://localhost:8080/atmosphere-pubsub/topic_A/TEST
>>>
>>> .... and guess what... both long polling connection got a message!
>> ah! This is a regression I may have added when I implemented the  
>> @PathParam Broadcaster injection.
>>>
>>> I think that problem is in the scope of the broadcaster...
>> Indeed.
>> as in current
>>> implementation it's only one instance global for whole  
>>> application... and look at this code from AtmosphereProviders:
>>>
>>>
>>>  Broadcaster broadcaster = null;
>>>                    try {
>>>                        broadcaster =  
>>> BroadcasterLookup.lookup(topic);
>>>                    } catch (OutOfScopeException ex) {
>>>                        LoggerUtils.getLogger().log(Level.SEVERE,  
>>> null, ex);
>>>                        throw new WebApplicationException(ex);
>>>                    }
>>>
>>>                    AtmosphereResource r = null;
>>>                    // Just use the one we just got
>>>                    if (broadcaster == null) {
>>>                        if ((Boolean)  
>>> req.getAttribute(AsynchronousProcessor.SUPPORT_SESSION)) {
>>>                            r = (AtmosphereResource)  
>>> req.getSession().
>>>                                    
>>> getAttribute(AtmosphereFilter.SUSPENDED_RESOURCE);
>>>                        }
>>>
>>>                        if (r == null) {
>>>                            r = (AtmosphereResource)  
>>> req.getAttribute(ReflectorServletProcessor.ATMOSPHERE_RESOURCE);
>>>                        }
>>>
>>>                        broadcaster = r.getBroadcaster();
>>>                        broadcaster.setName(topic);
>>>
>>>
>>> BroadcasterLookup can only lookup from APPLICATION or VM scope and  
>>> if it fails than any the broadcaster from AtmosphereResource is  
>>> taken and it's name is changed... so the following sequence of  
>>> requests:
>>>
>>> http://localhost:8080/atmosphere-pubsub/topic_1/TEST1
>>> http://localhost:8080/atmosphere-pubsub/topic_3/TEST2
>>> http://localhost:8080/atmosphere-pubsub/topic_4/TEST3
>>> http://localhost:8080/atmosphere-pubsub/topic_5/TEST4
>>> http://localhost:8080/atmosphere-pubsub/topic_6/TEST5
>>>
>>> will work and broadcasting to every suspended connection and every  
>>> time changing the name of the APP scope broadcaster (this will  
>>> work even if previously there was no connection suspended in such  
>>> topics)
>>>
>>>
>>> Just wonder whether BroadcasteLookup shouldn't also support  
>>> REQUESTs scope broadcasters?
>> But security wise, it will be difficult to block someone from  
>> getting access to another Broadcaster. Let me explore.
>> I'm also a little bit concerned about performance of
>>> BroadcasterLookup implementation and usage of  
>>> ConcurrentLinkedQueue for storing broadcaster and it's O(n)  
>>> complexity... Maybe it would be better to use ConcurrentHashMap  
>>> instead ? Especially for this fragment of code:
>>>
>>>   public final boolean add(Broadcaster b){
>>>        String name = b.getName();
>>>        if (getBroadcaster(name) != null) return false;
>>>        return store.offer(b);
>>>    }
>>>
>>> isn't quite atomic and thread safe :( But on the other hand the  
>>> name of the broadcaster is mutable :(
>> Let me work on that.
>> Thanks for the analysis!
>> --Jeanfrancois
>>>
>>>
>>> Regards
>>> Jaro
>>>
>>> On 2 Nov 2009, at 17:37, Jeanfrancois Arcand wrote:
>>>
>>>> Done. I've updated the sample
>>>>
>>>> * http://is.gd/4LegQ
>>>>
>>>> Blog coming...
>>>>
>>>> A+
>>>>
>>>> -- Jeanfrancois
>>>>
>>>>
>>>> Jeanfrancois Arcand wrote:
>>>>> Paul Sandoz wrote:
>>>>>> BTW there is another way if you want to obtain a Broadcaster  
>>>>>> from any parameter value (header, cookie, query, matrix or  
>>>>>> path), see StringReaderProvder:
>>>>>>
>>>>>> https://jersey.dev.java.net/nonav/apidocs/1.1.2-ea/jersey/com/sun/jersey/spi/StringReaderProvider.html
>>>>>>
>>>>>> Using this provider has the virtue of also working with default  
>>>>>> values [*].
>>>>> Thanks! I will work on that later today.
>>>>> A+
>>>>> -- Jeanfrancois
>>>>>>
>>>>>> Paul.
>>>>>>
>>>>>> [*] Note that for deployment validation a StringReader will be  
>>>>>> called at initialization with the default value. I dunno if  
>>>>>> this will cause issues for the case of a Broadcaster type. If  
>>>>>> so we might be able to do something about that.
>>>>>>
>>>>>>
>>>>>> On Oct 27, 2009, at 5:11 PM, Paul Sandoz wrote:
>>>>>>
>>>>>>>
>>>>>>> On Oct 27, 2009, at 4:55 PM, Jeanfrancois Arcand wrote:
>>>>>>>
>>>>>>>> Salut,
>>>>>>>>
>>>>>>>> gerard davison wrote:
>>>>>>>>> Is the following possible?
>>>>>>>>> Gerard
>>>>>>>>> @Suspend
>>>>>>>>> @GET
>>>>>>>>> @Path("/{topic}")
>>>>>>>>> @Produces("text/txt;charset=ISO-8859-1")
>>>>>>>>> public Broadcastable subscribe(@PathParam("topic")  
>>>>>>>>> Broadcaster topic) {
>>>>>>>>>    StringBuilder b = new StringBuilder();
>>>>>>>>>    // For IE, Safari and Chrome, we must output some junk to  
>>>>>>>>> enable
>>>>>>>>>    // streaming
>>>>>>>>>    for (int i = 0; i < 10; i++) {
>>>>>>>>>        b.append(JUNK);
>>>>>>>>>    }
>>>>>>>>>    //
>>>>>>>>>    Broadcastable broadcastible = new  
>>>>>>>>> Broadcastable(b.toString(),broadcaster);
>>>>>>>>>    return broadcastible;
>>>>>>>>> }
>>>>>>>>
>>>>>>>> If I understand properly, you are injecting the Broadcaster  
>>>>>>>> directly. That would be quite useful....I need to understand  
>>>>>>>> how this can be done via Jersey.
>>>>>>>>
>>>>>>>
>>>>>>> It can be done :-)
>>>>>>>
>>>>>>> @Provider
>>>>>>> public final class PathParamInjectableProvider extends  
>>>>>>> InjectableProvider<PathParam, Parameter> {
>>>>>>>    public Injectable<Broadcaster>  
>>>>>>> getInjectable(ComponentContext ic, PathParam a, Parameter c) {
>>>>>>>        if (c.getParameterClass() != Broadcaster) return null;
>>>>>>>
>>>>>>>        String parameterName = c.getSourceName();
>>>>>>>
>>>>>>>        ...
>>>>>>>    }
>>>>>>> }
>>>>>>>
>>>>>>> Paul.
>>>>>>>
>>>>>>> ---------------------------------------------------------------------
>>>>>>> To unsubscribe, e-mail: users-
>>>>>>> [hidden email]
>>>>>>> For additional commands, e-mail: [hidden email]
>>>>>>>
>>>>>>
>>>>>>
>>>>>> ---------------------------------------------------------------------
>>>>>> To unsubscribe, e-mail: [hidden email]
>>>>>> For additional commands, e-mail: [hidden email]
>>>>>>
>>>>> ---------------------------------------------------------------------
>>>>> To unsubscribe, e-mail: [hidden email]
>>>>> For additional commands, e-mail: users-
>>>>> [hidden email]
>>>>
>>>> ---------------------------------------------------------------------
>>>> To unsubscribe, e-mail: [hidden email]
>>>> For additional commands, e-mail: [hidden email]
>>>>
>>>
>>>
>>> ---------------------------------------------------------------------
>>> To unsubscribe, e-mail: [hidden email]
>>> For additional commands, e-mail: [hidden email]
>>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: [hidden email]
>> For additional commands, e-mail: [hidden email]
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [hidden email]
> For additional commands, e-mail: [hidden email]
>


---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Jeanfrancois Arcand

Re: Automated tests <was> Re: [FYI} Simple RESTFul Pub/Sub sample

Reply Threaded More More options
Print post
Permalink
Salut,

Paul Sandoz wrote:

>
> On Nov 4, 2009, at 5:49 PM, Jeanfrancois Arcand wrote:
>
>> Salut,
>>
>> I've fixed the Broadcaster's scope:
>>
>>> Sending        
>>> atmosphere/modules/cpr/src/main/java/org/atmosphere/cpr/AtmosphereServlet.java
>>>
>>> Sending        
>>> atmosphere/modules/jersey/src/main/java/org/atmosphere/jersey/AtmosphereProviders.java
>>>
>>> Sending        
>>> atmosphere/samples/pubsub/src/main/java/org/atmosphere/samples/pubsub/PubSub.java
>>>
>>> Transmitting file data ...
>>> Committed revision 646.
>>
>> It wasn't a regressions.
>
> Do we need to starting thinking about automated tests?

Yes, we must as you will not find a better person that me when it's time
to breaks things :-)


>
> It would be good if we could automate the testing of the samples in some
> way as well has have unit tests for the modules.

Agree. I think using the SpadeServer might works.

But i do not know what
> Web tools are appropriate for such such testing. A Java-based comet
> client API for testing would be handy (i would like to try and integrate
> something with the Jersey client API so that could be used for testing
> but that is secondary to the main problem).

I will work on it this week as next week I'm starting the Atmosphere
talks marathon and I would like to use the Jersey client for all my demo
(painful to demonstrate Comet using Browser on a Laptor mini screen).

A+

-- Jeanfrancois


>
> Paul.
>
>
>
>> Now that tells me the next things I need to work on it to add unit
>> test to avoid such stupid mistakes from me. Can you try it and let me
>> know?
>>
>> I will go ahead and implements your recommendation for BroadcasterLookup.
>>
>> A+
>>
>> -- Jeanfrancois
>>
>>
>>
>> Jeanfrancois Arcand wrote:
>>> Salut,
>>> Jaros?aw Lewandowski wrote:
>>>> Hi,
>>>>
>>>> Is it really working? In my understanding if you suspend something
>>>> on some topic than anything sent to this topic should only be
>>>> delivered to this one, doesn't it? I've deployed your sample Pub/Sub
>>>> applications and did simple test:
>>>>
>>>> - opened two URL in a different web browsers (or simply using curl):
>>>>
>>>> curl -N http://localhost:8080/atmosphere-pubsub/topic_A
>>>> curl -N http://localhost:8080/atmosphere-pubsub/topic_B
>>>>
>>>> so both were suspended after that
>>>>
>>>> - then loaded third url in a separate browser tab (or new curl
>>>> command call):
>>>>
>>>> curl -N http://localhost:8080/atmosphere-pubsub/topic_A/TEST
>>>>
>>>> .... and guess what... both long polling connection got a message!
>>> ah! This is a regression I may have added when I implemented the
>>> @PathParam Broadcaster injection.
>>>>
>>>> I think that problem is in the scope of the broadcaster...
>>> Indeed.
>>> as in current
>>>> implementation it's only one instance global for whole
>>>> application... and look at this code from AtmosphereProviders:
>>>>
>>>>
>>>>  Broadcaster broadcaster = null;
>>>>                    try {
>>>>                        broadcaster = BroadcasterLookup.lookup(topic);
>>>>                    } catch (OutOfScopeException ex) {
>>>>                        LoggerUtils.getLogger().log(Level.SEVERE,
>>>> null, ex);
>>>>                        throw new WebApplicationException(ex);
>>>>                    }
>>>>
>>>>                    AtmosphereResource r = null;
>>>>                    // Just use the one we just got
>>>>                    if (broadcaster == null) {
>>>>                        if ((Boolean)
>>>> req.getAttribute(AsynchronousProcessor.SUPPORT_SESSION)) {
>>>>                            r = (AtmosphereResource) req.getSession().
>>>>                                    
>>>> getAttribute(AtmosphereFilter.SUSPENDED_RESOURCE);
>>>>                        }
>>>>
>>>>                        if (r == null) {
>>>>                            r = (AtmosphereResource)
>>>> req.getAttribute(ReflectorServletProcessor.ATMOSPHERE_RESOURCE);
>>>>                        }
>>>>
>>>>                        broadcaster = r.getBroadcaster();
>>>>                        broadcaster.setName(topic);
>>>>
>>>>
>>>> BroadcasterLookup can only lookup from APPLICATION or VM scope and
>>>> if it fails than any the broadcaster from AtmosphereResource is
>>>> taken and it's name is changed... so the following sequence of
>>>> requests:
>>>>
>>>> http://localhost:8080/atmosphere-pubsub/topic_1/TEST1
>>>> http://localhost:8080/atmosphere-pubsub/topic_3/TEST2
>>>> http://localhost:8080/atmosphere-pubsub/topic_4/TEST3
>>>> http://localhost:8080/atmosphere-pubsub/topic_5/TEST4
>>>> http://localhost:8080/atmosphere-pubsub/topic_6/TEST5
>>>>
>>>> will work and broadcasting to every suspended connection and every
>>>> time changing the name of the APP scope broadcaster (this will work
>>>> even if previously there was no connection suspended in such topics)
>>>>
>>>>
>>>> Just wonder whether BroadcasteLookup shouldn't also support REQUESTs
>>>> scope broadcasters?
>>> But security wise, it will be difficult to block someone from getting
>>> access to another Broadcaster. Let me explore.
>>> I'm also a little bit concerned about performance of
>>>> BroadcasterLookup implementation and usage of ConcurrentLinkedQueue
>>>> for storing broadcaster and it's O(n) complexity... Maybe it would
>>>> be better to use ConcurrentHashMap instead ? Especially for this
>>>> fragment of code:
>>>>
>>>>   public final boolean add(Broadcaster b){
>>>>        String name = b.getName();
>>>>        if (getBroadcaster(name) != null) return false;
>>>>        return store.offer(b);
>>>>    }
>>>>
>>>> isn't quite atomic and thread safe :( But on the other hand the name
>>>> of the broadcaster is mutable :(
>>> Let me work on that.
>>> Thanks for the analysis!
>>> --Jeanfrancois
>>>>
>>>>
>>>> Regards
>>>> Jaro
>>>>
>>>> On 2 Nov 2009, at 17:37, Jeanfrancois Arcand wrote:
>>>>
>>>>> Done. I've updated the sample
>>>>>
>>>>> * http://is.gd/4LegQ
>>>>>
>>>>> Blog coming...
>>>>>
>>>>> A+
>>>>>
>>>>> -- Jeanfrancois
>>>>>
>>>>>
>>>>> Jeanfrancois Arcand wrote:
>>>>>> Paul Sandoz wrote:
>>>>>>> BTW there is another way if you want to obtain a Broadcaster from
>>>>>>> any parameter value (header, cookie, query, matrix or path), see
>>>>>>> StringReaderProvder:
>>>>>>>
>>>>>>> https://jersey.dev.java.net/nonav/apidocs/1.1.2-ea/jersey/com/sun/jersey/spi/StringReaderProvider.html 
>>>>>>>
>>>>>>>
>>>>>>> Using this provider has the virtue of also working with default
>>>>>>> values [*].
>>>>>> Thanks! I will work on that later today.
>>>>>> A+
>>>>>> -- Jeanfrancois
>>>>>>>
>>>>>>> Paul.
>>>>>>>
>>>>>>> [*] Note that for deployment validation a StringReader will be
>>>>>>> called at initialization with the default value. I dunno if this
>>>>>>> will cause issues for the case of a Broadcaster type. If so we
>>>>>>> might be able to do something about that.
>>>>>>>
>>>>>>>
>>>>>>> On Oct 27, 2009, at 5:11 PM, Paul Sandoz wrote:
>>>>>>>
>>>>>>>>
>>>>>>>> On Oct 27, 2009, at 4:55 PM, Jeanfrancois Arcand wrote:
>>>>>>>>
>>>>>>>>> Salut,
>>>>>>>>>
>>>>>>>>> gerard davison wrote:
>>>>>>>>>> Is the following possible?
>>>>>>>>>> Gerard
>>>>>>>>>> @Suspend
>>>>>>>>>> @GET
>>>>>>>>>> @Path("/{topic}")
>>>>>>>>>> @Produces("text/txt;charset=ISO-8859-1")
>>>>>>>>>> public Broadcastable subscribe(@PathParam("topic") Broadcaster
>>>>>>>>>> topic) {
>>>>>>>>>>    StringBuilder b = new StringBuilder();
>>>>>>>>>>    // For IE, Safari and Chrome, we must output some junk to
>>>>>>>>>> enable
>>>>>>>>>>    // streaming
>>>>>>>>>>    for (int i = 0; i < 10; i++) {
>>>>>>>>>>        b.append(JUNK);
>>>>>>>>>>    }
>>>>>>>>>>    //
>>>>>>>>>>    Broadcastable broadcastible = new
>>>>>>>>>> Broadcastable(b.toString(),broadcaster);
>>>>>>>>>>    return broadcastible;
>>>>>>>>>> }
>>>>>>>>>
>>>>>>>>> If I understand properly, you are injecting the Broadcaster
>>>>>>>>> directly. That would be quite useful....I need to understand
>>>>>>>>> how this can be done via Jersey.
>>>>>>>>>
>>>>>>>>
>>>>>>>> It can be done :-)
>>>>>>>>
>>>>>>>> @Provider
>>>>>>>> public final class PathParamInjectableProvider extends
>>>>>>>> InjectableProvider<PathParam, Parameter> {
>>>>>>>>    public Injectable<Broadcaster> getInjectable(ComponentContext
>>>>>>>> ic, PathParam a, Parameter c) {
>>>>>>>>        if (c.getParameterClass() != Broadcaster) return null;
>>>>>>>>
>>>>>>>>        String parameterName = c.getSourceName();
>>>>>>>>
>>>>>>>>        ...
>>>>>>>>    }
>>>>>>>> }
>>>>>>>>
>>>>>>>> Paul.
>>>>>>>>
>>>>>>>> ---------------------------------------------------------------------
>>>>>>>>
>>>>>>>> To unsubscribe, e-mail: [hidden email]
>>>>>>>> For additional commands, e-mail: [hidden email]
>>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> ---------------------------------------------------------------------
>>>>>>>
>>>>>>> To unsubscribe, e-mail: [hidden email]
>>>>>>> For additional commands, e-mail: [hidden email]
>>>>>>>
>>>>>> ---------------------------------------------------------------------
>>>>>> To unsubscribe, e-mail: [hidden email]
>>>>>> For additional commands, e-mail: [hidden email]
>>>>>
>>>>> ---------------------------------------------------------------------
>>>>> To unsubscribe, e-mail: [hidden email]
>>>>> For additional commands, e-mail: [hidden email]
>>>>>
>>>>
>>>>
>>>> ---------------------------------------------------------------------
>>>> To unsubscribe, e-mail: [hidden email]
>>>> For additional commands, e-mail: [hidden email]
>>>>
>>> ---------------------------------------------------------------------
>>> To unsubscribe, e-mail: [hidden email]
>>> For additional commands, e-mail: [hidden email]
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: [hidden email]
>> For additional commands, e-mail: [hidden email]
>>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [hidden email]
> For additional commands, e-mail: [hidden email]
>

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Jeanfrancois Arcand

BroadcasterLookup <was> Re: [FYI} Simple RESTFul Pub/Sub sample

Reply Threaded More More options
Print post
Permalink
In reply to this post by Jeanfrancois Arcand
Salut,

I've implemented your recommendation of using a Map, and remembered why
I using a Queue when the Broadcaster's name was changing.

> New Revision: 649
>
> Modified:
>    trunk/atmosphere/modules/cpr/src/main/java/org/atmosphere/cpr/Broadcaster.java
>    trunk/atmosphere/modules/cpr/src/main/java/org/atmosphere/cpr/DefaultBroadcaster.java
>    trunk/atmosphere/modules/cpr/src/main/java/org/atmosphere/util/BroadcasterLookup.java
>    trunk/atmosphere/modules/cpr/src/main/java/org/atmosphere/util/gae/GAEDefaultBroadcaster.java
>    trunk/atmosphere/modules/jersey/src/main/java/org/atmosphere/jersey/JerseyBroadcaster.java


I added a new listener -> Broadcaster.BroadcasterStateListener to
Broadcaster and added BroadcasterLookup as a listener so now when the
name change the map gets updated.

The BroadcasterStateListener could be useful in many scenario I think.

Let me know what you think.

A+

--Jeanfrancois



Jeanfrancois Arcand wrote:

> Salut,
>
> Jaros?aw Lewandowski wrote:
>> Hi,
>>
>> Is it really working? In my understanding if you suspend something on
>> some topic than anything sent to this topic should only be delivered
>> to this one, doesn't it? I've deployed your sample Pub/Sub
>> applications and did simple test:
>>
>> - opened two URL in a different web browsers (or simply using curl):
>>
>> curl -N http://localhost:8080/atmosphere-pubsub/topic_A
>> curl -N http://localhost:8080/atmosphere-pubsub/topic_B
>>
>> so both were suspended after that
>>
>> - then loaded third url in a separate browser tab (or new curl command
>> call):
>>
>> curl -N http://localhost:8080/atmosphere-pubsub/topic_A/TEST
>>
>> .... and guess what... both long polling connection got a message!
>
> ah! This is a regression I may have added when I implemented the
> @PathParam Broadcaster injection.
>
>>
>> I think that problem is in the scope of the broadcaster...
>
> Indeed.
>
>  as in current
>> implementation it's only one instance global for whole application...
>> and look at this code from AtmosphereProviders:
>>
>>
>>   Broadcaster broadcaster = null;
>>                     try {
>>                         broadcaster = BroadcasterLookup.lookup(topic);
>>                     } catch (OutOfScopeException ex) {
>>                         LoggerUtils.getLogger().log(Level.SEVERE,
>> null, ex);
>>                         throw new WebApplicationException(ex);
>>                     }
>>
>>                     AtmosphereResource r = null;
>>                     // Just use the one we just got
>>                     if (broadcaster == null) {
>>                         if ((Boolean)
>> req.getAttribute(AsynchronousProcessor.SUPPORT_SESSION)) {
>>                             r = (AtmosphereResource) req.getSession().
>>                                    
>> getAttribute(AtmosphereFilter.SUSPENDED_RESOURCE);
>>                         }
>>
>>                         if (r == null) {
>>                             r = (AtmosphereResource)
>> req.getAttribute(ReflectorServletProcessor.ATMOSPHERE_RESOURCE);
>>                         }
>>
>>                         broadcaster = r.getBroadcaster();
>>                         broadcaster.setName(topic);
>>
>>
>> BroadcasterLookup can only lookup from APPLICATION or VM scope and if
>> it fails than any the broadcaster from AtmosphereResource is taken and
>> it's name is changed... so the following sequence of requests:
>>
>> http://localhost:8080/atmosphere-pubsub/topic_1/TEST1
>> http://localhost:8080/atmosphere-pubsub/topic_3/TEST2
>> http://localhost:8080/atmosphere-pubsub/topic_4/TEST3
>> http://localhost:8080/atmosphere-pubsub/topic_5/TEST4
>> http://localhost:8080/atmosphere-pubsub/topic_6/TEST5
>>
>> will work and broadcasting to every suspended connection and every
>> time changing the name of the APP scope broadcaster (this will work
>> even if previously there was no connection suspended in such topics)
>>
>>
>> Just wonder whether BroadcasteLookup shouldn't also support REQUESTs
>> scope broadcasters?
>
> But security wise, it will be difficult to block someone from getting
> access to another Broadcaster. Let me explore.
>
>
>  I'm also a little bit concerned about performance of
>> BroadcasterLookup implementation and usage of ConcurrentLinkedQueue
>> for storing broadcaster and it's O(n) complexity... Maybe it would be
>> better to use ConcurrentHashMap instead ? Especially for this fragment
>> of code:
>>
>>    public final boolean add(Broadcaster b){
>>         String name = b.getName();
>>         if (getBroadcaster(name) != null) return false;
>>         return store.offer(b);
>>     }
>>
>> isn't quite atomic and thread safe :( But on the other hand the name
>> of the broadcaster is mutable :(
>
> Let me work on that.
>
> Thanks for the analysis!
>
> --Jeanfrancois
>
>
>
>>
>>
>> Regards
>> Jaro
>>
>> On 2 Nov 2009, at 17:37, Jeanfrancois Arcand wrote:
>>
>>> Done. I've updated the sample
>>>
>>>  * http://is.gd/4LegQ
>>>
>>> Blog coming...
>>>
>>> A+
>>>
>>> -- Jeanfrancois
>>>
>>>
>>> Jeanfrancois Arcand wrote:
>>>> Paul Sandoz wrote:
>>>>> BTW there is another way if you want to obtain a Broadcaster from
>>>>> any parameter value (header, cookie, query, matrix or path), see
>>>>> StringReaderProvder:
>>>>>
>>>>>  https://jersey.dev.java.net/nonav/apidocs/1.1.2-ea/jersey/com/sun/jersey/spi/StringReaderProvider.html 
>>>>>
>>>>>
>>>>> Using this provider has the virtue of also working with default
>>>>> values [*].
>>>> Thanks! I will work on that later today.
>>>> A+
>>>> -- Jeanfrancois
>>>>>
>>>>> Paul.
>>>>>
>>>>> [*] Note that for deployment validation a StringReader will be
>>>>> called at initialization with the default value. I dunno if this
>>>>> will cause issues for the case of a Broadcaster type. If so we
>>>>> might be able to do something about that.
>>>>>
>>>>>
>>>>> On Oct 27, 2009, at 5:11 PM, Paul Sandoz wrote:
>>>>>
>>>>>>
>>>>>> On Oct 27, 2009, at 4:55 PM, Jeanfrancois Arcand wrote:
>>>>>>
>>>>>>> Salut,
>>>>>>>
>>>>>>> gerard davison wrote:
>>>>>>>> Is the following possible?
>>>>>>>> Gerard
>>>>>>>> @Suspend
>>>>>>>> @GET
>>>>>>>> @Path("/{topic}")
>>>>>>>> @Produces("text/txt;charset=ISO-8859-1")
>>>>>>>> public Broadcastable subscribe(@PathParam("topic") Broadcaster
>>>>>>>> topic) {
>>>>>>>>     StringBuilder b = new StringBuilder();
>>>>>>>>     // For IE, Safari and Chrome, we must output some junk to
>>>>>>>> enable
>>>>>>>>     // streaming
>>>>>>>>     for (int i = 0; i < 10; i++) {
>>>>>>>>         b.append(JUNK);
>>>>>>>>     }
>>>>>>>>     //
>>>>>>>>     Broadcastable broadcastible = new
>>>>>>>> Broadcastable(b.toString(),broadcaster);
>>>>>>>>     return broadcastible;
>>>>>>>> }
>>>>>>>
>>>>>>> If I understand properly, you are injecting the Broadcaster
>>>>>>> directly. That would be quite useful....I need to understand how
>>>>>>> this can be done via Jersey.
>>>>>>>
>>>>>>
>>>>>> It can be done :-)
>>>>>>
>>>>>> @Provider
>>>>>> public final class PathParamInjectableProvider extends
>>>>>> InjectableProvider<PathParam, Parameter> {
>>>>>>     public Injectable<Broadcaster> getInjectable(ComponentContext
>>>>>> ic, PathParam a, Parameter c) {
>>>>>>         if (c.getParameterClass() != Broadcaster) return null;
>>>>>>
>>>>>>         String parameterName = c.getSourceName();
>>>>>>
>>>>>>         ...
>>>>>>     }
>>>>>> }
>>>>>>
>>>>>> Paul.
>>>>>>
>>>>>> ---------------------------------------------------------------------
>>>>>> To unsubscribe, e-mail: [hidden email]
>>>>>> For additional commands, e-mail: [hidden email]
>>>>>>
>>>>>
>>>>>
>>>>> ---------------------------------------------------------------------
>>>>> To unsubscribe, e-mail: [hidden email]
>>>>> For additional commands, e-mail: [hidden email]
>>>>>
>>>> ---------------------------------------------------------------------
>>>> To unsubscribe, e-mail: [hidden email]
>>>> For additional commands, e-mail: [hidden email]
>>>
>>> ---------------------------------------------------------------------
>>> To unsubscribe, e-mail: [hidden email]
>>> For additional commands, e-mail: [hidden email]
>>>
>>
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: [hidden email]
>> For additional commands, e-mail: [hidden email]
>>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [hidden email]
> For additional commands, e-mail: [hidden email]
>

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Paul Sandoz

Re: Automated tests <was> Re: [FYI} Simple RESTFul Pub/Sub sample

Reply Threaded More More options
Print post
Permalink
In reply to this post by Jeanfrancois Arcand

On Nov 4, 2009, at 6:01 PM, Jeanfrancois Arcand wrote:

> Salut,
>
> Paul Sandoz wrote:
>> On Nov 4, 2009, at 5:49 PM, Jeanfrancois Arcand wrote:
>>> Salut,
>>>
>>> I've fixed the Broadcaster's scope:
>>>
>>>> Sending        atmosphere/modules/cpr/src/main/java/org/
>>>> atmosphere/cpr/AtmosphereServlet.java
>>>> Sending        atmosphere/modules/jersey/src/main/java/org/
>>>> atmosphere/jersey/AtmosphereProviders.java
>>>> Sending        atmosphere/samples/pubsub/src/main/java/org/
>>>> atmosphere/samples/pubsub/PubSub.java
>>>> Transmitting file data ...
>>>> Committed revision 646.
>>>
>>> It wasn't a regressions.
>> Do we need to starting thinking about automated tests?
>
> Yes, we must as you will not find a better person that me when it's  
> time to breaks things :-)
>

Actually, i think you have done a remarkable job of not breaking  
things given the rate of code production.


>
>> It would be good if we could automate the testing of the samples in  
>> some way as well has have unit tests for the modules.
>
> Agree. I think using the SpadeServer might works.
>

And how could we automate the testing using certain browsers?

Can we run something in a virtual machine with automated update and  
analysis of the browser DOM?

I am sure there is some off the shelf stuff we could use but i have  
zero experience in this area.


> But i do not know what
>> Web tools are appropriate for such such testing. A Java-based comet  
>> client API for testing would be handy (i would like to try and  
>> integrate something with the Jersey client API so that could be  
>> used for testing but that is secondary to the main problem).
>
> I will work on it this week as next week I'm starting the Atmosphere  
> talks marathon and I would like to use the Jersey client for all my  
> demo (painful to demonstrate Comet using Browser on a Laptor mini  
> screen).
>

Hopefully HttpURLConnection will not get in the way :-) It should be  
possible to do:

   WebResource r = ...
   InputStream in r.get(InputStream.class);

When "in" is passed to some comet layer. It may be possible to do  
something at a higher layer with a message body reader:

   ClientConfig cc = new DefaultClientConfig();
   cc.getProperties("CometHandlerFactory", ...);
   Client c = Client.create(cc);
   WebResource r = c.resource(...);
   CometHandlerManager ch = r.get(CometHandlerManager.class);


But what may be better is a way to extend WebResource for comet-style  
interactions (there is an issue open in Jersey for this and a  
developer has attached some code i need to review).

Paul.

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

gerard davison

Re: Automated tests <was> Re: [FYI} Simple RESTFul Pub/Sub sample

Reply Threaded More More options
Print post
Permalink

Paul, Jeanfrancois

We use Selenium a lot internally in JDeveloper to test our JSF apps. I
will support multiple browsers and from what I have heard is a pleasure
to use as you can pick your scripting langauge:

http://seleniumhq.org/

I haven't unfortunately got direct experience of using it.

Gerard


> And how could we automate the testing using certain browsers?
>
> Can we run something in a virtual machine with automated update and
> analysis of the browser DOM?
>
> I am sure there is some off the shelf stuff we could use but i have
> zero experience in this area.
>
>

--
Gerard Davison | Senior Principal Software Engineer | +44 118 924 5095
Oracle JDeveloper Web Service Tooling Development
Oracle Corporation UK Ltd is a company incorporated in England & Wales.
Company Reg. No. 1782505.
Reg. office: Oracle Parkway, Thames Valley Park, Reading RG6 1RA.

Blog http://kingsfleet.blogspot.com


---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Jarosław Lewandowski

Re: [FYI} Simple RESTFul Pub/Sub sample

Reply Threaded More More options
Print post
Permalink
In reply to this post by Jeanfrancois Arcand
Hi,
On 4 Nov 2009, at 16:49, Jeanfrancois Arcand wrote:

> Salut,
>
> I've fixed the Broadcaster's scope:
>
>> Sending        atmosphere/modules/cpr/src/main/java/org/atmosphere/
>> cpr/AtmosphereServlet.java
>> Sending        atmosphere/modules/jersey/src/main/java/org/
>> atmosphere/jersey/AtmosphereProviders.java
>> Sending        atmosphere/samples/pubsub/src/main/java/org/
>> atmosphere/samples/pubsub/PubSub.java
>> Transmitting file data ...
>> Committed revision 646.
>

The fix works well when Broadcaster is injected based on @PathParam,  
@QueryParam etc.... but imagine the case when you want to create some  
topics in separate groups... lets say:

/{group}/{topic}

so org.atmosphere.jersey.AtmosphereProviders$BroadcasterProvider would  
not possible to create/lookup for a new Broadcaster for a pair  
groupName:topicName (as topic name is not unique)

IMO it should be some easy way to have Broadcaster created/looked up  
from certain names... e.g. based on previous PubSub.java sample it  
could be something like that

        @GET
        @Suspend
        @Path("/{group}/{topic}")
        @Produces("text/plain;charset=ISO-8859-1")
        public Broadcastable subscribe(@Context Broadcaster br,
                @PathParam("group") String group, @PathParam("topic") String  
topic) {
                String brName = "topic/" + group + "/" + topic;

                Broadcaster broadcaster = null;
                try {
                        broadcaster = BroadcasterLookup.lookupOrCreate(brName);
                } catch (OutOfScopeException ex) {
                        throw new WebApplicationException();
                }

         if (broadcaster == null) {
          throw new WebApplicationException(Response.status
(Status.NOT_FOUND).entity("Broadcaster not found!").build());
         }
                Broadcastable broadcastible = new Broadcastable("", broadcaster);

                return broadcastible;
        }

        @GET
        @Path("/{group}/{topic}/{message}")
        @Produces("text/plain;charset=ISO-8859-1")
         @Broadcast
        public Broadcastable publish(@PathParam("group") String group,  
@PathParam("topic") String topic, @PathParam("message") String  
message) {
                String brName = "topic/" + group + "/" + topic;

         Broadcaster broadcaster = null;
         try {
             broadcaster = BroadcasterLookup.lookup(brName);
         } catch (OutOfScopeException ex) {
          throw new WebApplicationException();
         }

         if (broadcaster == null) {
          throw new WebApplicationException(Response.status
(Status.NOT_FOUND).entity("Broadcaster not found!").build());
         }

         return new Broadcastable(message, broadcaster);
        }


I'm not sure whether lookupOrCreate method should be inside  
BroadcasterLookup maybe 'create' part should be in separate class.

Regards
JL


BTW. I found that when method annotated with @Broadcast throws a  
WebApplicationException  constructed with Response with error status  
code then the response entity is still broadcasted to suspended  
connections :(




> It wasn't a regressions. Now that tells me the next things I need to  
> work on it to add unit test to avoid such stupid mistakes from me.  
> Can you try it and let me know?
>
> I will go ahead and implements your recommendation for  
> BroadcasterLookup.
>
> A+
>
> -- Jeanfrancois
>
>
>
> Jeanfrancois Arcand wrote:
>> Salut,
>> Jaros?aw Lewandowski wrote:
>>> Hi,
>>>
>>> Is it really working? In my understanding if you suspend something  
>>> on some topic than anything sent to this topic should only be  
>>> delivered to this one, doesn't it? I've deployed your sample Pub/
>>> Sub applications and did simple test:
>>>
>>> - opened two URL in a different web browsers (or simply using curl):
>>>
>>> curl -N http://localhost:8080/atmosphere-pubsub/topic_A
>>> curl -N http://localhost:8080/atmosphere-pubsub/topic_B
>>>
>>> so both were suspended after that
>>>
>>> - then loaded third url in a separate browser tab (or new curl  
>>> command call):
>>>
>>> curl -N http://localhost:8080/atmosphere-pubsub/topic_A/TEST
>>>
>>> .... and guess what... both long polling connection got a message!
>> ah! This is a regression I may have added when I implemented the  
>> @PathParam Broadcaster injection.
>>>
>>> I think that problem is in the scope of the broadcaster...
>> Indeed.
>> as in current
>>> implementation it's only one instance global for whole  
>>> application... and look at this code from AtmosphereProviders:
>>>
>>>
>>>  Broadcaster broadcaster = null;
>>>                    try {
>>>                        broadcaster = BroadcasterLookup.lookup
>>> (topic);
>>>                    } catch (OutOfScopeException ex) {
>>>                        LoggerUtils.getLogger().log(Level.SEVERE,  
>>> null, ex);
>>>                        throw new WebApplicationException(ex);
>>>                    }
>>>
>>>                    AtmosphereResource r = null;
>>>                    // Just use the one we just got
>>>                    if (broadcaster == null) {
>>>                        if ((Boolean) req.getAttribute
>>> (AsynchronousProcessor.SUPPORT_SESSION)) {
>>>                            r = (AtmosphereResource) req.getSession
>>> ().
>>>                                    getAttribute
>>> (AtmosphereFilter.SUSPENDED_RESOURCE);
>>>                        }
>>>
>>>                        if (r == null) {
>>>                            r = (AtmosphereResource)  
>>> req.getAttribute(ReflectorServletProcessor.ATMOSPHERE_RESOURCE);
>>>                        }
>>>
>>>                        broadcaster = r.getBroadcaster();
>>>                        broadcaster.setName(topic);
>>>
>>>
>>> BroadcasterLookup can only lookup from APPLICATION or VM scope and  
>>> if it fails than any the broadcaster from AtmosphereResource is  
>>> taken and it's name is changed... so the following sequence of  
>>> requests:
>>>
>>> http://localhost:8080/atmosphere-pubsub/topic_1/TEST1
>>> http://localhost:8080/atmosphere-pubsub/topic_3/TEST2
>>> http://localhost:8080/atmosphere-pubsub/topic_4/TEST3
>>> http://localhost:8080/atmosphere-pubsub/topic_5/TEST4
>>> http://localhost:8080/atmosphere-pubsub/topic_6/TEST5
>>>
>>> will work and broadcasting to every suspended connection and every  
>>> time changing the name of the APP scope broadcaster (this will  
>>> work even if previously there was no connection suspended in such  
>>> topics)
>>>
>>>
>>> Just wonder whether BroadcasteLookup shouldn't also support  
>>> REQUESTs scope broadcasters?
>> But security wise, it will be difficult to block someone from  
>> getting access to another Broadcaster. Let me explore.
>> I'm also a little bit concerned about performance of
>>> BroadcasterLookup implementation and usage of  
>>> ConcurrentLinkedQueue for storing broadcaster and it's O(n)  
>>> complexity... Maybe it would be better to use ConcurrentHashMap  
>>> instead ? Especially for this fragment of code:
>>>
>>>   public final boolean add(Broadcaster b){
>>>        String name = b.getName();
>>>        if (getBroadcaster(name) != null) return false;
>>>        return store.offer(b);
>>>    }
>>>
>>> isn't quite atomic and thread safe :( But on the other hand the  
>>> name of the broadcaster is mutable :(
>> Let me work on that.
>> Thanks for the analysis!
>> --Jeanfrancois
>>>
>>>
>>> Regards
>>> Jaro
>>>
>>> On 2 Nov 2009, at 17:37, Jeanfrancois Arcand wrote:
>>>
>>>> Done. I've updated the sample
>>>>
>>>> * http://is.gd/4LegQ
>>>>
>>>> Blog coming...
>>>>
>>>> A+
>>>>
>>>> -- Jeanfrancois
>>>>
>>>>
>>>> Jeanfrancois Arcand wrote:
>>>>> Paul Sandoz wrote:
>>>>>> BTW there is another way if you want to obtain a Broadcaster  
>>>>>> from any parameter value (header, cookie, query, matrix or  
>>>>>> path), see StringReaderProvder:
>>>>>>
>>>>>> https://jersey.dev.java.net/nonav/apidocs/1.1.2-ea/jersey/com/sun/jersey/spi/StringReaderProvider.html
>>>>>>
>>>>>> Using this provider has the virtue of also working with default  
>>>>>> values [*].
>>>>> Thanks! I will work on that later today.
>>>>> A+
>>>>> -- Jeanfrancois
>>>>>>
>>>>>> Paul.
>>>>>>
>>>>>> [*] Note that for deployment validation a StringReader will be  
>>>>>> called at initialization with the default value. I dunno if  
>>>>>> this will cause issues for the case of a Broadcaster type. If  
>>>>>> so we might be able to do something about that.
>>>>>>
>>>>>>
>>>>>> On Oct 27, 2009, at 5:11 PM, Paul Sandoz wrote:
>>>>>>
>>>>>>>
>>>>>>> On Oct 27, 2009, at 4:55 PM, Jeanfrancois Arcand wrote:
>>>>>>>
>>>>>>>> Salut,
>>>>>>>>
>>>>>>>> gerard davison wrote:
>>>>>>>>> Is the following possible?
>>>>>>>>> Gerard
>>>>>>>>> @Suspend
>>>>>>>>> @GET
>>>>>>>>> @Path("/{topic}")
>>>>>>>>> @Produces("text/txt;charset=ISO-8859-1")
>>>>>>>>> public Broadcastable subscribe(@PathParam("topic")  
>>>>>>>>> Broadcaster topic) {
>>>>>>>>>    StringBuilder b = new StringBuilder();
>>>>>>>>>    // For IE, Safari and Chrome, we must output some junk to  
>>>>>>>>> enable
>>>>>>>>>    // streaming
>>>>>>>>>    for (int i = 0; i < 10; i++) {
>>>>>>>>>        b.append(JUNK);
>>>>>>>>>    }
>>>>>>>>>    //
>>>>>>>>>    Broadcastable broadcastible = new Broadcastable(b.toString
>>>>>>>>> (),broadcaster);
>>>>>>>>>    return broadcastible;
>>>>>>>>> }
>>>>>>>>
>>>>>>>> If I understand properly, you are injecting the Broadcaster  
>>>>>>>> directly. That would be quite useful....I need to understand  
>>>>>>>> how this can be done via Jersey.
>>>>>>>>
>>>>>>>
>>>>>>> It can be done :-)
>>>>>>>
>>>>>>> @Provider
>>>>>>> public final class PathParamInjectableProvider extends  
>>>>>>> InjectableProvider<PathParam, Parameter> {
>>>>>>>    public Injectable<Broadcaster> getInjectable
>>>>>>> (ComponentContext ic, PathParam a, Parameter c) {
>>>>>>>        if (c.getParameterClass() != Broadcaster) return null;
>>>>>>>
>>>>>>>        String parameterName = c.getSourceName();
>>>>>>>
>>>>>>>        ...
>>>>>>>    }
>>>>>>> }
>>>>>>>
>>>>>>> Paul.
>>>>>>>
>>>>>>> ---------------------------------------------------------------------
>>>>>>> To unsubscribe, e-mail: users-
>>>>>>> [hidden email]
>>>>>>> For additional commands, e-mail: [hidden email]
>>>>>>>
>>>>>>
>>>>>>
>>>>>> ---------------------------------------------------------------------
>>>>>> To unsubscribe, e-mail: [hidden email]
>>>>>> For additional commands, e-mail: [hidden email]
>>>>>>
>>>>> ---------------------------------------------------------------------
>>>>> To unsubscribe, e-mail: [hidden email]
>>>>> For additional commands, e-mail: users-
>>>>> [hidden email]
>>>>
>>>> ---------------------------------------------------------------------
>>>> To unsubscribe, e-mail: [hidden email]
>>>> For additional commands, e-mail: [hidden email]
>>>>
>>>
>>>
>>> ---------------------------------------------------------------------
>>> To unsubscribe, e-mail: [hidden email]
>>> For additional commands, e-mail: [hidden email]
>>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: [hidden email]
>> For additional commands, e-mail: [hidden email]
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [hidden email]
> For additional commands, e-mail: [hidden email]
>


---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Jarosław Lewandowski

Re: BroadcasterLookup <was> Re: [FYI} Simple RESTFul Pub/Sub sample

Reply Threaded More More options
Print post
Permalink
In reply to this post by Jeanfrancois Arcand
Some javascript/style in this post has been disabled (why?)
Hi,


On 4 Nov 2009, at 21:24, Jeanfrancois Arcand wrote:

Salut,

I've implemented your recommendation of using a Map, and remembered why I using a Queue when the Broadcaster's name was changing.

New Revision: 649
Modified:
  trunk/atmosphere/modules/cpr/src/main/java/org/atmosphere/cpr/Broadcaster.java
  trunk/atmosphere/modules/cpr/src/main/java/org/atmosphere/cpr/DefaultBroadcaster.java
  trunk/atmosphere/modules/cpr/src/main/java/org/atmosphere/util/BroadcasterLookup.java
  trunk/atmosphere/modules/cpr/src/main/java/org/atmosphere/util/gae/GAEDefaultBroadcaster.java
  trunk/atmosphere/modules/jersey/src/main/java/org/atmosphere/jersey/JerseyBroadcaster.java


I added a new listener -> Broadcaster.BroadcasterStateListener to Broadcaster and added BroadcasterLookup as a listener so now when the name change the map gets updated.

The BroadcasterStateListener could be useful in many scenario I think.

Let me know what you think.



IMO the better implementation of Brodacsterlookup.add(...) method would look like:

public final boolean add(Broadcaster b){
        b.addBroadcasterStateListener(this);
        return store.putIfAbsent(b.getName(), b) == null;
    }

but still I'm a little bit concerned about multithread access to these objects... 

JL


A+

--Jeanfrancois



Jeanfrancois Arcand wrote:
Salut,
Jaros?aw Lewandowski wrote:
Hi,

Is it really working? In my understanding if you suspend something on some topic than anything sent to this topic should only be delivered to this one, doesn't it? I've deployed your sample Pub/Sub applications and did simple test:

- opened two URL in a different web browsers (or simply using curl):

curl -N http://localhost:8080/atmosphere-pubsub/topic_A
curl -N http://localhost:8080/atmosphere-pubsub/topic_B

so both were suspended after that

- then loaded third url in a separate browser tab (or new curl command call):

curl -N http://localhost:8080/atmosphere-pubsub/topic_A/TEST

.... and guess what... both long polling connection got a message!
ah! This is a regression I may have added when I implemented the @PathParam Broadcaster injection.

I think that problem is in the scope of the broadcaster...
Indeed.
as in current
implementation it's only one instance global for whole application... and look at this code from AtmosphereProviders:


 Broadcaster broadcaster = null;
                   try {
                       broadcaster = BroadcasterLookup.lookup(topic);
                   } catch (OutOfScopeException ex) {
                       LoggerUtils.getLogger().log(Level.SEVERE, null, ex);
                       throw new WebApplicationException(ex);
                   }

                   AtmosphereResource r = null;
                   // Just use the one we just got
                   if (broadcaster == null) {
                       if ((Boolean) req.getAttribute(AsynchronousProcessor.SUPPORT_SESSION)) {
                           r = (AtmosphereResource) req.getSession().
                                   getAttribute(AtmosphereFilter.SUSPENDED_RESOURCE);
                       }

                       if (r == null) {
                           r = (AtmosphereResource) req.getAttribute(ReflectorServletProcessor.ATMOSPHERE_RESOURCE);
                       }

                       broadcaster = r.getBroadcaster();
                       broadcaster.setName(topic);


BroadcasterLookup can only lookup from APPLICATION or VM scope and if it fails than any the broadcaster from AtmosphereResource is taken and it's name is changed... so the following sequence of requests:

http://localhost:8080/atmosphere-pubsub/topic_1/TEST1
http://localhost:8080/atmosphere-pubsub/topic_3/TEST2
http://localhost:8080/atmosphere-pubsub/topic_4/TEST3
http://localhost:8080/atmosphere-pubsub/topic_5/TEST4
http://localhost:8080/atmosphere-pubsub/topic_6/TEST5

will work and broadcasting to every suspended connection and every time changing the name of the APP scope broadcaster (this will work even if previously there was no connection suspended in such topics)


Just wonder whether BroadcasteLookup shouldn't also support REQUESTs scope broadcasters?
But security wise, it will be difficult to block someone from getting access to another Broadcaster. Let me explore.
I'm also a little bit concerned about performance of
BroadcasterLookup implementation and usage of ConcurrentLinkedQueue for storing broadcaster and it's O(n) complexity... Maybe it would be better to use ConcurrentHashMap instead ? Especially for this fragment of code:

  public final boolean add(Broadcaster b){
       String name = b.getName();
       if (getBroadcaster(name) != null) return false;
       return store.offer(b);
   }

isn't quite atomic and thread safe :( But on the other hand the name of the broadcaster is mutable :(
Let me work on that.
Thanks for the analysis!
--Jeanfrancois


Regards
Jaro

On 2 Nov 2009, at 17:37, Jeanfrancois Arcand wrote:

Done. I've updated the sample

* http://is.gd/4LegQ

Blog coming...

A+

-- Jeanfrancois


Jeanfrancois Arcand wrote:
Paul Sandoz wrote:
BTW there is another way if you want to obtain a Broadcaster from any parameter value (header, cookie, query, matrix or path), see StringReaderProvder:

https://jersey.dev.java.net/nonav/apidocs/1.1.2-ea/jersey/com/sun/jersey/spi/StringReaderProvider.html

Using this provider has the virtue of also working with default values [*].
Thanks! I will work on that later today.
A+
-- Jeanfrancois

Paul.

[*] Note that for deployment validation a StringReader will be called at initialization with the default value. I dunno if this will cause issues for the case of a Broadcaster type. If so we might be able to do something about that.


On Oct 27, 2009, at 5:11 PM, Paul Sandoz wrote:


On Oct 27, 2009, at 4:55 PM, Jeanfrancois Arcand wrote:

Salut,

gerard davison wrote:
Is the following possible?
Gerard
@Suspend
@GET
@Path("/{topic}")
@Produces("text/txt;charset=ISO-8859-1")
public Broadcastable subscribe(@PathParam("topic") Broadcaster topic) {
   StringBuilder b = new StringBuilder();
   // For IE, Safari and Chrome, we must output some junk to enable
   // streaming
   for (int i = 0; i < 10; i++) {
       b.append(JUNK);
   }
   //
   Broadcastable broadcastible = new Broadcastable(b.toString(),broadcaster);
   return broadcastible;
}

If I understand properly, you are injecting the Broadcaster directly. That would be quite useful....I need to understand how this can be done via Jersey.


It can be done :-)

@Provider
public final class PathParamInjectableProvider extends InjectableProvider<PathParam, Parameter> {
   public Injectable<Broadcaster> getInjectable(ComponentContext ic, PathParam a, Parameter c) {
       if (c.getParameterClass() != Broadcaster) return null;

       String parameterName = c.getSourceName();

       ...
   }
}

Paul.

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]



---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]



---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]


1 2 3