public void execute(Command command) { Broadcaster broadcaster = broadcasterFactory.lookup(DefaultBroadcaster.class, command.getChannel(), true); command.execute(broadcaster); if (!broadcaster.isDestroyed() && !isRunningThreadOnChannel(command.getChannel())) { startMessagingThread(command.getChannel(), broadcaster); } }
@Path("idleDestroyResumePolicy") @GET @Suspend( listeners = {ResumeListener.class}, outputComments = false) public Broadcastable suspendForever(@Context BroadcasterFactory f) { Broadcaster b = f.get(UUID.randomUUID().toString()); b.setBroadcasterLifeCyclePolicy( new BroadcasterLifeCyclePolicy.Builder() .policy(IDLE_RESUME) .idleTime(30, TimeUnit.SECONDS) .build()); return new Broadcastable(b); }
@Path("idleDestroyPolicy") @GET @Suspend( resumeOnBroadcast = true, listeners = {DestroyListener.class}) public Broadcastable suspend(@Context BroadcasterFactory f) { Broadcaster b = f.get(UUID.randomUUID().toString()); b.setBroadcasterLifeCyclePolicy( new BroadcasterLifeCyclePolicy.Builder() .policy(IDLE_DESTROY) .idleTime(20, TimeUnit.SECONDS) .build()); return new Broadcastable(b); }
@Override public void onOpen(AtmosphereResource resource) throws IOException { log.debug("Opening Atmosphere connection"); String broadcasterName = "/realtime/statuses/home_timeline/" + resource.getRequest().getRemoteUser(); if (log.isDebugEnabled()) { log.debug("Subscribing this resource to broadcaster: " + broadcasterName); } Broadcaster b = BroadcasterFactory.getDefault().lookup(broadcasterName, true); b.addAtmosphereResource(resource); }
/** * Invoked after {@link AtmosphereFramework#init()} gets invoked * * @param f an {@link org.atmosphere.cpr.AtmosphereFramework} */ public void onPostInit(AtmosphereFramework f) { Broadcaster broadcaster = factory.lookup("/mediator"); broadcaster.getBroadcasterConfig().addFilter(new RabbitBroadcastFilter()); try { RabbitMQConsumer consumer = new RabbitMQConsumer( Config.getInstance().getRabbitMQEndpoint(), new RabbitConsumerListener(broadcaster)); // Start Rabbit Consumer consumer.start(); } catch (Exception e) { e.printStackTrace(); } }
@GET @Resume @Path("suspendAndResume/{uuid}") public String resume() throws ExecutionException, InterruptedException { broadcaster.broadcast("resume").get(); return "resumed"; }
@Override public void run() { while (shouldRun) { counter++; broadcaster.broadcast("counter " + counter + ", channel: " + channel); await(); } runningPublishers.remove(channel); }
/** {@inheritDoc} */ @Override public void receive(final Message message) { final String msg = (String) message.getObject(); if (message.getSrc() != jchannel.getLocalAddress()) { if (msg != null) { receivedMessages.offer(msg); if (bc != null) { bc.broadcast(msg); } } } }
protected void idleResources() { for (Broadcaster b : config.getBroadcasterFactory().lookupAll()) { for (AtmosphereResource r : b.getAtmosphereResources()) { AtmosphereRequest req = AtmosphereResourceImpl.class.cast(r).getRequest(false); try { if (req.getAttribute(MAX_INACTIVE) == null) return; long l = (Long) req.getAttribute(MAX_INACTIVE); if (l > 0 && System.currentTimeMillis() - l > maxInactiveTime) { req.setAttribute(MAX_INACTIVE, (long) -1); logger.debug("IdleResourceInterceptor disconnecting {}", r); if (!AtmosphereResourceImpl.class.cast(r).isSuspended() || !AtmosphereResourceImpl.class.cast(r).isInScope()) { return; } Future<?> f = (Future<?>) req.getAttribute(HeartbeatInterceptor.HEARTBEAT_FUTURE); if (f != null) f.cancel(false); req.removeAttribute(HeartbeatInterceptor.HEARTBEAT_FUTURE); Object o = req.getAttribute(ASYNCHRONOUS_HOOK); req.setAttribute(ASYNCHRONOUS_HOOK, null); AsynchronousProcessor.AsynchronousProcessorHook h; if (o != null && AsynchronousProcessor.AsynchronousProcessorHook.class.isAssignableFrom( o.getClass())) { h = (AsynchronousProcessor.AsynchronousProcessorHook) o; h.closed(); } } } catch (Throwable e) { logger.warn("IdleResourceInterceptor", e); } } } }
/* * (non-Javadoc) * @see org.atmosphere.gwt.server.AtmosphereGwtHandler#doComet(org.atmosphere.gwt.server.GwtAtmosphereResource) */ @Override public int doComet(GwtAtmosphereResource resource) throws ServletException, IOException { HttpSession session = resource.getAtmosphereResource().getRequest().getSession(); if (session.getAttribute(BROADCASTERSESSIONKEY) == null) session.setAttribute(BROADCASTERSESSIONKEY, BroadcasterFactory.getDefault().get()); resource .getAtmosphereResource() .setBroadcaster((Broadcaster) session.getAttribute(BROADCASTERSESSIONKEY)); Broadcaster b = BroadcasterFactory.getDefault().lookup(GLOBALBROADCASTERID); if (b == null) { b = BroadcasterFactory.getDefault().get(GLOBALBROADCASTERID); } b.addAtmosphereResource(resource.getAtmosphereResource()); if (logger.isDebugEnabled()) { logger.debug( "Url: " + resource.getAtmosphereResource().getRequest().getRequestURL() + "?" + resource.getAtmosphereResource().getRequest().getQueryString()); } return NO_TIMEOUT; }
@GET @Path("scope") public SuspendResponse<String> suspendScopeRequestWithAPI(@PathParam("topic") Broadcaster b) throws ExecutionException, InterruptedException { SuspendResponse<String> r = new SuspendResponse.SuspendResponseBuilder<String>() .entity("bar") .broadcaster(broadcaster) .scope(Suspend.SCOPE.REQUEST) .outputComments(false) .resumeOnBroadcast(true) .period(5, TimeUnit.SECONDS) .build(); b.broadcast("foo").get(); return r; }
/** * Based on the {@link HttpServletRequest#getParameter} action value, decide if the connection * needs to be suspended (when the user logs in) or if the {@link Broadcaster} needs to be updated * by the user or by its follower. * * <p>There is one {@link Broadcaster} per suspended connection, representing the user account. * When one user B request to follow user A, the {@link AtmosphereResource} associated with user * B's {@link Broadcaster} is also added to user A {@link Broadcaster}. Hence when user A push * message ({@link Broadcaster#broadcast(Object)} all {@link AtmosphereResource} gets the {@link * AtmosphereResourceEvent}, which means user B will be updated when user A update its micro blog. * * <p>The suspended connection on the client side is multiplexed, e.g. messages sent by the server * are not only for a single component, but shared amongst several components. The client side * include a message board that is updated by notifying the owner of the {@link Broadcaster}. This * is achieved by calling {@link Broadcaster#broadcast(Object)} * * @param atmoResource An {@link AtmosphereResourceEvent} * @throws java.io.IOException */ public void onRequest(AtmosphereResource<HttpServletRequest, HttpServletResponse> atmoResource) throws IOException { HttpServletRequest request = atmoResource.getRequest(); HttpServletResponse response = atmoResource.getResponse(); String action = request.getParameter("action"); String sessionId = request.getSession().getId(); HttpSession session = request.getSession(); Broadcaster myBroadcasterFollower = (Broadcaster) session.getAttribute(sessionId); if (action != null) { if ("login".equals(action)) { response.setContentType("text/plain"); response.setCharacterEncoding("UTF-8"); String name = request.getParameter("name"); if (name == null) { logger.severe("Name cannot be null"); return; } session.setAttribute("name", name); myBroadcasterFollower.broadcast( BEGIN_SCRIPT_TAG + toJsonp("Welcome back", name) + END_SCRIPT_TAG); // Store the Broadcaster associated with this user so // we can retrieve it for supporting follower. atmoResource .getAtmosphereConfig() .getServletContext() .setAttribute(name, myBroadcasterFollower); } else if ("post".equals(action)) { String message = request.getParameter("message"); String callback = request.getParameter("callback"); if (message == null) { logger.severe("Message cannot be null"); return; } if (callback == null) { callback = "alert"; } if (myBroadcasterFollower != null) { myBroadcasterFollower.broadcast( "<script id='comet_" + counter++ + "'>" + "window.parent." + callback + "(" + message + ");</script>"); } else { throw new RuntimeException("Broadcaster was null"); } response.getWriter().println("ok"); } else if ("start".equals(action)) { String message = "{ message : 'Welcome'}"; response.setContentType("text/html;charset=ISO-8859-1"); atmoResource.suspend(); String callback = request.getParameter("callback"); if (callback == null) { callback = "alert"; } response .getWriter() .println( "<script id='comet_" + counter++ + "'>" + "window.parent." + callback + "(" + message + ");</script>"); response.getWriter().println(startingMessage); response.getWriter().flush(); // Use one Broadcaster per AtmosphereResource try { atmoResource.setBroadcaster(BroadcasterFactory.getDefault().get()); } catch (Throwable t) { throw new IOException(t); } // Create a Broadcaster based on this session id. myBroadcasterFollower = atmoResource.getBroadcaster(); session.setAttribute("atmoResource", atmoResource); session.setAttribute(sessionId, myBroadcasterFollower); } else if ("following".equals(action)) { response.setContentType("text/html"); String follow = request.getParameter("message"); String name = (String) session.getAttribute("name"); if (follow == null) { logger.severe("Message cannot be null"); return; } if (name == null) { logger.severe("Name cannot be null"); return; } Broadcaster outsiderBroadcaster = (Broadcaster) atmoResource.getAtmosphereConfig().getServletContext().getAttribute(follow); AtmosphereResource r = (AtmosphereResource) session.getAttribute("atmoResource"); if (outsiderBroadcaster == null) { myBroadcasterFollower.broadcast( BEGIN_SCRIPT_TAG + toJsonp("Invalid Twitter user ", follow) + END_SCRIPT_TAG, r); return; } outsiderBroadcaster.addAtmosphereResource(r); myBroadcasterFollower.broadcast( BEGIN_SCRIPT_TAG + toJsonp("You are now following ", follow) + END_SCRIPT_TAG, r); outsiderBroadcaster.broadcast( BEGIN_SCRIPT_TAG + toJsonp(name, " is now following " + follow) + END_SCRIPT_TAG); } } }
@POST @Path("programmaticDelayBroadcast") public String manualDelayBroadcast(@FormParam("message") String message) { broadcaster.delayBroadcast(message); return message; }
public static final void broadcast( final AtmosphereResource r, final AtmosphereResourceEvent e, final Broadcaster broadcaster) { AtmosphereRequest request = r.getRequest(); ContainerResponse cr = null; // Make sure only one thread can play with the ContainerResponse. Threading issue can arise if // there is a scheduler // or if ContainerResponse is associated with more than Broadcaster. cr = (ContainerResponse) request.getAttribute(FrameworkConfig.CONTAINER_RESPONSE); if (cr == null || !r.isSuspended() && !r.getAtmosphereResourceEvent().isResumedOnTimeout()) { if (cr == null) { logger.warn( "Unexpected state. ContainerResponse has been resumed. Caching message {} for {}", e.getMessage(), r.uuid()); } else { logger.warn("The AtmosphereResource {} hasn't been suspended yet.", r.uuid(), e); } if (DefaultBroadcaster.class.isAssignableFrom(broadcaster.getClass())) { DefaultBroadcaster.class.cast(broadcaster).cacheLostMessage(r, true); } AtmosphereResourceImpl.class.cast(r)._destroy(); return; } synchronized (cr) { try { // This is required when you change the response's type String m = null; if (request.getAttribute(FrameworkConfig.EXPECTED_CONTENT_TYPE) != null) { m = (String) request.getAttribute(FrameworkConfig.EXPECTED_CONTENT_TYPE); } if (m == null || m.equalsIgnoreCase("text/event-stream")) { if (cr.getHttpHeaders().getFirst(HttpHeaders.CONTENT_TYPE) != null) { m = cr.getHttpHeaders().getFirst(HttpHeaders.CONTENT_TYPE).toString(); } if (m == null || m.equalsIgnoreCase("application/octet-stream")) { m = r.getAtmosphereConfig().getInitParameter(ApplicationConfig.SSE_CONTENT_TYPE); if (m == null) { m = "text/plain"; } } } if (e.getMessage() instanceof Response) { cr.setResponse((Response) e.getMessage()); cr.getHttpHeaders().add(HttpHeaders.CONTENT_TYPE, m); cr.write(); try { cr.getOutputStream().flush(); } catch (IOException ex) { logger.trace("", ex); } } else if (e.getMessage() instanceof List) { for (Object msg : (List<Object>) e.getMessage()) { cr.setResponse(Response.ok(msg).build()); cr.getHttpHeaders().add(HttpHeaders.CONTENT_TYPE, m); cr.write(); } // https://github.com/Atmosphere/atmosphere/issues/169 try { cr.getOutputStream().flush(); } catch (IOException ex) { logger.trace("", ex); } } else { if (e.getMessage() == null) { logger.warn("Broadcasted message is null"); return; } cr.setResponse(Response.ok(e.getMessage()).build()); cr.getHttpHeaders().add(HttpHeaders.CONTENT_TYPE, m); cr.write(); try { cr.getOutputStream().flush(); } catch (IOException ex) { logger.trace("", ex); } } } catch (Throwable t) { boolean notifyAndCache = true; logger.trace( "Unexpected exception for AtmosphereResource {} and Broadcaster {}", r.uuid(), broadcaster.getID()); if (isJetty(r)) { for (StackTraceElement element : t.getStackTrace()) { if (element.getClassName().equals("java.io.BufferedWriter") && element.getMethodName().equals("flush")) { logger.trace("Workaround issue https://github.com/Atmosphere/atmosphere/issues/710"); notifyAndCache = false; } } } if (DefaultBroadcaster.class.isAssignableFrom(broadcaster.getClass())) { DefaultBroadcaster.class.cast(broadcaster).onException(t, r, notifyAndCache); } else { onException(t, r); } } finally { if (cr != null) { cr.setEntity(null); } Boolean resumeOnBroadcast = (Boolean) request.getAttribute(ApplicationConfig.RESUME_ON_BROADCAST); if (resumeOnBroadcast != null && resumeOnBroadcast) { String uuid = (String) request.getAttribute(AtmosphereFilter.RESUME_UUID); if (uuid != null) { if (request.getAttribute(AtmosphereFilter.RESUME_CANDIDATES) != null) { ((ConcurrentHashMap<String, AtmosphereResource>) request.getAttribute(AtmosphereFilter.RESUME_CANDIDATES)) .remove(uuid); } } r.getRequest().setAttribute(FrameworkConfig.CONTAINER_RESPONSE, null); r.resume(); } } } }
public ChannelPublisher(Broadcaster broadcaster, String channel) { this.broadcaster = broadcaster; this.channel = channel; broadcaster.addBroadcasterLifeCyclePolicyListener(this); }
protected void sendMessages(String topic, String message) { Broadcaster broadcaster = getBroadcaster(topic); if (broadcaster != null) { broadcaster.broadcast(message); } }
@Override public void execute(Broadcaster broadcaster) { broadcaster.addAtmosphereResource(resource); resource.getBroadcaster().broadcast("joined channel " + channel); }