Understanding Broadcaster - Atmosphere/atmosphere GitHub Wiki

Understanding Broadcaster

The Broadcaster is Atmosphere's pub/sub message bus. It delivers messages to all suspended AtmosphereResource connections that have been added to it.

For most applications, you won't interact with Broadcaster directly โ€” @ManagedService handles it automatically. This page is useful when you need to customize message delivery or build advanced patterns.

How It Works

Client A โ”€โ”€โ”
            โ”œโ”€โ”€ Broadcaster โ”€โ”€โ”ฌโ”€โ”€ Client A (receives)
Client B โ”€โ”€โ”ค    "/chat"       โ”œโ”€โ”€ Client B (receives)
            โ”‚                  โ””โ”€โ”€ Client C (receives)
Client C โ”€โ”€โ”˜
  1. Each @ManagedService(path = "/chat") creates a Broadcaster with ID /chat
  2. When a client connects, its AtmosphereResource is added to the Broadcaster
  3. When @Message returns a value, it's broadcast to all resources on that Broadcaster
  4. Messages pass through BroadcastFilters before delivery
  5. Undelivered messages are stored in the BroadcasterCache for reconnecting clients

Using Broadcaster Directly

Injection

@ManagedService(path = "/chat")
public class Chat {

    @Inject
    @Named("/chat")
    private Broadcaster broadcaster;

    @Inject
    private BroadcasterFactory factory;

    @Ready
    public void onReady() {
        // Broadcast to everyone on this path
        broadcaster.broadcast("A new user joined!");

        // Look up any broadcaster by ID
        Broadcaster other = factory.lookup("/notifications", true);
        other.broadcast("New user in chat");
    }
}

Key Methods

// Broadcasting
broadcaster.broadcast(message);                    // To all members
broadcaster.broadcast(message, resource);          // Exclude one resource
broadcaster.broadcast(message, Set.of(r1, r2));    // To specific resources only

// Delayed / scheduled
broadcaster.delayBroadcast(message, 5, TimeUnit.SECONDS);
broadcaster.scheduleFixedBroadcast(message, 10, TimeUnit.SECONDS);

// Resource management
broadcaster.addAtmosphereResource(resource);
broadcaster.removeAtmosphereResource(resource);
broadcaster.getAtmosphereResources();              // All connected resources

BroadcasterCache

The cache stores messages that were broadcast while a client was disconnected (e.g., during a long-polling reconnect cycle). When the client reconnects, cached messages are delivered automatically.

@ManagedService uses UUIDBroadcasterCache by default โ€” no configuration needed.

Custom Cache

@ManagedService(path = "/chat", broadcasterCache = MyCache.class)
public class Chat { /* ... */ }

Implement the BroadcasterCache interface:

public interface BroadcasterCache {
    void start();
    void stop();
    void cleanup();

    // Store a message during broadcast
    CacheMessage addToCache(String broadcasterId, String uuid, BroadcastMessage message);

    // Retrieve cached messages for a reconnecting client
    List<Object> retrieveFromCache(String broadcasterId, String uuid);
}

BroadcastFilter

Filters transform or reject messages before they reach clients. Use them for content transformation, sanitization, or selective delivery.

Creating a Filter

public class ProfanityFilter implements BroadcastFilter {
    @Override
    public BroadcastAction filter(String broadcasterId, Object originalMessage, Object message) {
        String text = message.toString();
        if (containsProfanity(text)) {
            return new BroadcastAction(ACTION.ABORT);     // Drop the message
        }
        String cleaned = sanitize(text);
        return new BroadcastAction(ACTION.CONTINUE, cleaned); // Transform
    }
}

BroadcastAction

Action Effect
CONTINUE Pass message to next filter (optionally transformed)
ABORT Drop the message entirely
SKIP Skip remaining filters, deliver as-is

Registering Filters

// Via annotation
@ManagedService(path = "/chat", broadcastFilters = {ProfanityFilter.class})
public class Chat { /* ... */ }

// Or via annotation on the filter class itself
@BroadcasterFilterService
public class ProfanityFilter implements BroadcastFilter { /* ... */ }

Per-Resource Filters

For filters that need access to the target resource (e.g., to filter differently per user), implement PerRequestBroadcastFilter:

public class RoleFilter implements PerRequestBroadcastFilter {
    @Override
    public BroadcastAction filter(String broadcasterId,
                                   AtmosphereResource r,
                                   Object originalMessage,
                                   Object message) {
        // Access r.getRequest() for session/auth info
        if (isAdmin(r)) {
            return new BroadcastAction(ACTION.CONTINUE, message);
        }
        return new BroadcastAction(ACTION.CONTINUE, redact(message));
    }

    @Override
    public BroadcastAction filter(String broadcasterId,
                                   Object originalMessage,
                                   Object message) {
        return new BroadcastAction(ACTION.CONTINUE, message);
    }
}

BroadcasterListener

Listen to Broadcaster lifecycle events:

@BroadcasterListenerService
public class MyListener implements BroadcasterListener {
    public void onPostCreate(Broadcaster b) { /* new broadcaster */ }
    public void onComplete(Broadcaster b) { /* broadcast delivered */ }
    public void onPreDestroy(Broadcaster b) { /* broadcaster shutting down */ }
    public void onAddAtmosphereResource(Broadcaster b, AtmosphereResource r) { /* client joined */ }
    public void onRemoveAtmosphereResource(Broadcaster b, AtmosphereResource r) { /* client left */ }
    public void onMessage(Broadcaster b, Deliver deliver) { /* message queued */ }
}

Broadcaster vs. Room

Feature Broadcaster Room
Level Low-level High-level
Identity Path-based ID Named group
Presence Manual tracking Built-in events
Direct messaging Manual UUID lookup room.sendTo(memberId, msg)
Message history Via BroadcasterCache room.enableHistory(n)
Client protocol Manual Built into atmosphere.js

For most chat/collaboration apps, prefer Rooms. Use Broadcaster directly when you need fine-grained control over message delivery.

โš ๏ธ **GitHub.com Fallback** โš ๏ธ