Understanding AtmosphereInterceptor - Atmosphere/atmosphere GitHub Wiki
Understanding AtmosphereInterceptor
Advanced topic. Interceptors let you customize the request/response pipeline. Most applications don't need custom interceptors —
@ManagedServiceinstalls the necessary ones automatically.
An AtmosphereInterceptor sits in the processing chain between the client and your handler. It can inspect, modify, or reject requests and responses.
Built-in Interceptors
These are installed automatically by @ManagedService:
| Interceptor | Purpose |
|---|---|
AtmosphereResourceLifecycleInterceptor |
Auto-suspends connections based on transport |
TrackMessageSizeInterceptor |
Prepends message length for guaranteed delivery |
HeartbeatInterceptor |
Sends periodic heartbeats to keep connections alive |
SuspendTrackerInterceptor |
Tracks suspended resources for cleanup |
ManagedServiceInterceptor |
Routes messages to @Message annotated methods |
Other useful interceptors:
| Interceptor | Purpose |
|---|---|
MDCInterceptor |
Populates SLF4J MDC with atmosphere.uuid, atmosphere.transport, atmosphere.broadcaster for structured logging |
RoomProtocolInterceptor |
Bridges atmosphere.js room protocol to server-side Rooms |
RoomInterceptor |
Auto-joins resources to rooms based on URL path |
BroadcastOnPostAtmosphereInterceptor |
Auto-broadcasts POST body to the Broadcaster |
CorsInterceptor |
Adds CORS headers |
MDCInterceptor — Structured Logging
MDCInterceptor sets SLF4J MDC keys on every request so log lines include Atmosphere context:
| MDC key | Value |
|---|---|
atmosphere.uuid |
The unique resource identifier |
atmosphere.transport |
Transport type (websocket, long-polling, sse, etc.) |
atmosphere.broadcaster |
Broadcaster ID the resource is attached to |
Logback pattern example:
%d{HH:mm:ss.SSS} [%thread] %-5level [uuid=%X{atmosphere.uuid} transport=%X{atmosphere.transport}] %logger{36} - %msg%n
MDC keys are automatically included as top-level fields in JSON layouts (logstash-logback-encoder, logback-contrib).
Writing a Custom Interceptor
public class LoggingInterceptor extends AtmosphereInterceptorAdapter {
@Override
public Action inspect(AtmosphereResource r) {
// Called before the handler
log.info("Request from {} via {}", r.uuid(), r.transport());
return Action.CONTINUE; // Proceed to next interceptor/handler
// return Action.CANCELLED; // Stop processing (e.g., reject request)
// return Action.SUSPEND; // Suspend the connection
}
@Override
public void postInspect(AtmosphereResource r) {
// Called after the handler
}
@Override
public void configure(AtmosphereConfig config) {
// Called once at startup
}
}
Registering Interceptors
Via @ManagedService
@ManagedService(path = "/chat",
interceptors = {LoggingInterceptor.class, RateLimitInterceptor.class})
public class Chat { /* ... */ }
These are appended to the default set — they don't replace it.
Via Annotation
@AtmosphereInterceptorService
public class LoggingInterceptor extends AtmosphereInterceptorAdapter {
// Auto-registered when annotation scanning is enabled
}
Programmatically
framework.interceptor(new LoggingInterceptor());
Interceptor Priority
Control execution order with PRIORITY:
public class EarlyInterceptor extends AtmosphereInterceptorAdapter {
@Override
public PRIORITY priority() {
return InvokationOrder.BEFORE_DEFAULT; // Run before defaults
// InvokationOrder.AFTER_DEFAULT // Run after defaults (default)
// InvokationOrder.FIRST_BEFORE_DEFAULT // Run first, before everything
}
}