-
-
Notifications
You must be signed in to change notification settings - Fork 761
Understanding ManagedService
jfarcand edited this page Feb 18, 2026
·
3 revisions
@ManagedService is the recommended way to build Atmosphere applications. It provides an annotation-driven programming model with automatic lifecycle management, message encoding/decoding, and dependency injection.
@ManagedService(path = "/chat") public class Chat { @Inject private BroadcasterFactory factory; @Inject private AtmosphereResource r; @Inject private AtmosphereResourceEvent event; @Ready public void onReady() { // Connection is suspended and ready to receive messages } @Disconnect public void onDisconnect() { if (event.isCancelled()) { // Unexpected disconnect } else if (event.isClosedByClient()) { // Client closed the connection } } @Message(encoders = {JacksonEncoder.class}, decoders = {JacksonDecoder.class}) public Message onMessage(Message message) { // Return value is broadcast to all connected clients return message; } @Heartbeat public void onHeartbeat(AtmosphereResourceEvent event) { // Client heartbeat received } }
When you annotate a class with @ManagedService, Atmosphere automatically installs:
| Component | Purpose |
|---|---|
UUIDBroadcasterCache |
Caches messages so reconnecting clients don't miss data |
AtmosphereResourceLifecycleInterceptor |
Manages connection suspend/resume lifecycle |
TrackMessageSizeInterceptor |
Guarantees complete message delivery |
HeartbeatInterceptor |
Keeps connections alive across proxies |
SuspendTrackerInterceptor |
Tracks suspended connections |
| Attribute | Type | Default | Description |
|---|---|---|---|
path |
String |
"/" |
URL mapping for this handler |
broadcaster |
Class |
DefaultBroadcaster.class |
Broadcaster implementation |
broadcasterCache |
Class |
UUIDBroadcasterCache.class |
Message cache implementation |
interceptors |
Class[] |
{} |
Additional interceptors (appended to defaults) |
broadcastFilters |
Class[] |
{} |
Message filters applied before broadcast |
listeners |
Class[] |
{} |
Event listeners for connection tracking |
atmosphereConfig |
String[] |
{} |
Key-value config (e.g. "org.atmosphere.cpr.maxInactiveActivity=120000") |
| Annotation | When Invoked | Typical Use |
|---|---|---|
@Ready |
Connection suspended and ready | Log connection, send welcome message |
@Disconnect |
Client disconnects | Clean up, notify others |
@Message |
Message received from Broadcaster | Process and optionally re-broadcast |
@Heartbeat |
Client heartbeat received | Logging, presence tracking |
| Annotation | Description |
|---|---|
@Get |
Handle HTTP GET (e.g. set response encoding) |
@Post |
Handle HTTP POST |
@Put |
Handle HTTP PUT |
@Delete |
Handle HTTP DELETE |
| Annotation | Target | Description |
|---|---|---|
@Singleton |
Class | Single instance shared across all connections |
@PathParam |
Field | Bind URI template variable (e.g. /chat/{room}) |
@DeliverTo |
Method | Control broadcast scope: RESOURCE, BROADCASTER, or ALL
|
@ManagedService classes support @Inject (Jakarta CDI) for:
@Inject private AtmosphereResource r; // Current connection @Inject private AtmosphereResourceEvent event; // Current event @Inject private BroadcasterFactory factory; // Create/lookup broadcasters @Inject @Named("/chat") private Broadcaster b; // Named broadcaster
The @Message annotation supports automatic type conversion:
// Encoder: converts your object to a String for the wire public class JacksonEncoder implements Encoder<Message, String> { @Inject private ObjectMapper mapper; @Override public String encode(Message m) { return mapper.writeValueAsString(m); } } // Decoder: converts incoming String to your object public class JacksonDecoder implements Decoder<String, Message> { @Inject private ObjectMapper mapper; @Override public Message decode(String s) { return mapper.readValue(s, Message.class); } } // Usage @Message(encoders = {JacksonEncoder.class}, decoders = {JacksonDecoder.class}) public Message onMessage(Message message) { return message; // Automatically decoded from JSON, re-encoded for broadcast }
Use @PathParam to capture URI variables:
@ManagedService(path = "/chat/{room}") public class Chat { @PathParam("room") private String roomName; @Ready public void onReady() { // roomName is populated from the URL // e.g. /chat/lobby → roomName = "lobby" } }
Each unique path creates a separate Broadcaster, so /chat/lobby and /chat/general have independent message streams.
Control who receives the return value of a @Message method:
@Message @DeliverTo(DeliverTo.DELIVER_TO.BROADCASTER) // All connections on this path public String onMessage(String message) { return "Echo: " + message; } @Message @DeliverTo(DeliverTo.DELIVER_TO.RESOURCE) // Only the sender public String onPrivateMessage(String message) { return "Only you see this"; }
Pass Atmosphere config via the atmosphereConfig attribute:
@ManagedService( path = "/chat", atmosphereConfig = { "org.atmosphere.cpr.maxInactiveActivity=120000", "org.atmosphere.websocket.maxTextMessageSize=65536" } )