|
|
| 1 2 3 |
|
Jeanfrancois Arcand
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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:
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
|
||||||||||||||||
| Free Embeddable Forum Powered by Nabble | Help |