Atmosphere Request Scoped Broadcasts
I'm having trouble restricting the scope of my broadcasts, using Atmosphere 0.7.2.
I have a Jersey POJO, with an open
method, and I want to pass the broadcaster to a non-webservice class. This is to allow separation between WAR and EJB layers.
@Path("/")
public class MyJerseyPojo {
@Context
private Broadcaster broadcaster;
@GET
@Suspend
public String open() {
Manager.register(/* Session ID */, new NonWebservice(this.broadcaster));
return "";
}
}
public class NonWebService implements Sender {
private Broadcaster broadcaster;
public NonWebService(Broadcaster b) {
this.broadcaster = b;
}
@Override
public void send(String thing) {
this.broadcaster.broadcast(thing);
}
}
The idea is that update events will call send
, and this will notify the client with the suspended response. Each client should be associated with a separate broadcaster.
The problem is, this solution uses the same broadcaster for all clients. I have tried adding @Suspend(scope = Suspend.SCOPE.REQUEST)
to the open
method, but this causes no broadcast messages to be received.
I also tried the following in the open
method:
@GET
@Suspend
public String open() {
Broadcaster b = BroadcasterFactory.getDefault().get(JerseyBroadcaster.class, UUID.randomUUID());
b.setScope(Broadcaster.SCOPE.REQUEST);
Manager.register(/* Session ID */, new NonWebservice(b));
}
This didn't work, either using @Suspend
or @Suspend(scope = Suspend.SCOPE.REQUEST)
. In each case, the client didn't receive any broadcast messages. I did once get a message that the broadcaster had been destroyed and couldn't be used, but I can't remember how I did this!
I have seen a similar question but I'm not su开发者_开发百科re how to translate it to my POJO, as I'm not extending AtmosphereHandler
.
Thanks
It turns out, after a lot of digging, that it's not safe to cache broadcasters, as the AtmosphereFilter was creating a new, Request-scoped broadcaster after my open() method completed.
Hence, in the NonWebservice
class now looks like this:
public class NonWebService implements Sender {
private Class<? extends Broadcaster> clazz;
private Object broadcasterId;
public NonWebService(Class<? extends Broadcaster> clazz, Object broadcasterId) {
this.clazz = clazz;
this.broadcasterId = broadcasterId;
}
@Override
public void send(String thing) {
Broadcaster b = BroadcasterLookup.getDefault().get(this.clazz, this.broadcasterId);
b.broadcast(thing);
}
}
Now I could do with figuring out how to schedule request-scoped fixed broadcasts...
Actually, in the end I found that I needed to return a broadcastable from my suspended method. The broadcaster was recreated as session-scoped but kept available for later broadcasts. Just make sure that you don't broadcast anything until the suspended method has returned, as that might get lost.
精彩评论