-
-
Notifications
You must be signed in to change notification settings - Fork 761
Getting Started with Spring Boot
Build a real-time chat application with Atmosphere and Spring Boot 4.0 in minutes.
- JDK 21+
- Maven 3.9+
Start from spring-boot-starter-parent 4.0.2 and add the Atmosphere starter:
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>4.0.2</version> </parent> <dependencies> <dependency> <groupId>org.atmosphere</groupId> <artifactId>atmosphere-spring-boot-starter</artifactId> <version>4.0.1</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>jakarta.inject</groupId> <artifactId>jakarta.inject-api</artifactId> <version>2.0.1</version> </dependency> <!-- For JSON encoding/decoding --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> </dependency> </dependencies>
In application.yml:
atmosphere: packages: com.example.chat
That's it — the starter auto-configures the AtmosphereServlet mapped to /atmosphere/*.
| Property | Default | Description |
|---|---|---|
atmosphere.servlet-path |
/atmosphere/* |
Servlet URL mapping |
atmosphere.packages |
(none) | Packages to scan for annotations |
atmosphere.session-support |
false |
Enable HttpSession support |
atmosphere.websocket-support |
(auto) | Force WebSocket on/off |
atmosphere.heartbeat-interval-in-seconds |
(default) | Heartbeat frequency |
atmosphere.broadcaster-class |
(default) | Custom Broadcaster implementation |
atmosphere.broadcaster-cache-class |
(default) | Custom BroadcasterCache |
atmosphere.init-params |
{} |
Additional servlet init parameters |
@ManagedService(path = "/atmosphere/chat", atmosphereConfig = "org.atmosphere.cpr.maxInactiveActivity=120000") public class Chat { @Inject private AtmosphereResource r; @Inject private AtmosphereResourceEvent event; @Ready public void onReady() { // Connection is ready to receive messages } @Disconnect public void onDisconnect() { if (event.isClosedByClient()) { // Client closed the connection } } @Message(encoders = {JacksonEncoder.class}, decoders = {JacksonDecoder.class}) public Message onMessage(Message message) { return message; // Broadcast to all connected clients } }
See Understanding @ManagedService for the full annotation reference.
public class Message { private String message; private String author; private long time; public Message() { this("", ""); } public Message(String author, String message) { this.author = author; this.message = message; this.time = System.currentTimeMillis(); } // Getters and setters }
public class JacksonEncoder implements Encoder<Message, String> { @Inject private ObjectMapper mapper; @Override public String encode(Message m) { try { return mapper.writeValueAsString(m); } catch (IOException e) { throw new RuntimeException(e); } } } public class JacksonDecoder implements Decoder<String, Message> { @Inject private ObjectMapper mapper; @Override public Message decode(String s) { try { return mapper.readValue(s, Message.class); } catch (IOException e) { throw new RuntimeException(e); } } }
@SpringBootApplication public class ChatApplication { public static void main(String[] args) { SpringApplication.run(ChatApplication.class, args); } }
Place atmosphere.js in src/main/resources/static/javascript/. You can grab the latest build from
atmosphere.js releases or install via npm:
npm install atmosphere.js@5 cp node_modules/atmosphere.js/dist/atmosphere.js src/main/resources/static/javascript/
Create src/main/resources/static/index.html:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Atmosphere 4.0 Chat</title> <script src="javascript/atmosphere.js"></script> <style> body { font-family: sans-serif; max-width: 600px; margin: 40px auto; } #messages { height: 300px; overflow-y: auto; border: 1px solid #ccc; padding: 10px; margin-bottom: 10px; } #messages p { margin: 4px 0; } #input { width: 100%; padding: 8px; font-size: 14px; } </style> </head> <body> <h2>Atmosphere 4.0 Chat</h2> <div id="messages"></div> <input id="input" placeholder="Enter your name, then start chatting..." disabled /> <script src="javascript/app.js"></script> </body> </html>
Create src/main/resources/static/javascript/app.js:
document.addEventListener('DOMContentLoaded', async () => { const messages = document.getElementById('messages'); const input = document.getElementById('input'); let author = null; function addMessage(text) { const p = document.createElement('p'); p.textContent = text; messages.appendChild(p); messages.scrollTop = messages.scrollHeight; } const subscription = await atmosphere.atmosphere.subscribe( { url: `${location.protocol}//${location.host}/atmosphere/chat`, transport: 'websocket', fallbackTransport: 'long-polling', trackMessageLength: true, contentType: 'application/json' }, { open: (response) => { addMessage(`Connected via ${response.transport}. Enter your name:`); input.disabled = false; input.focus(); }, message: (response) => { const body = response.responseBody.trim(); if (body.length <= 1) return; // heartbeat try { const msg = JSON.parse(body); addMessage(`${msg.author}: ${msg.message}`); } catch (e) { /* ignore */ } }, close: () => addMessage('Disconnected.'), error: () => addMessage('Connection error.') } ); input.addEventListener('keydown', (e) => { if (e.key !== 'Enter' || !input.value.trim()) return; if (!author) author = input.value.trim(); subscription.push(JSON.stringify({ author: author, message: input.value.trim() })); input.value = ''; }); });
mvn spring-boot:run
Open http://localhost:8080 and start chatting!
The starter automatically scans @RoomService annotations and exposes a RoomManager bean — no manual configuration needed:
@RoomService(path = "/chat/{roomId}", maxHistory = 50) public class ChatRoom { @Message(encoders = {JacksonEncoder.class}, decoders = {JacksonDecoder.class}) public Message onMessage(Message message) { return message; } }
You can also inject RoomManager directly into any Spring component:
@RestController public class RoomController { private final RoomManager roomManager; public RoomController(RoomManager roomManager) { this.roomManager = roomManager; } @GetMapping("/api/rooms") public List<Map<String, Object>> listRooms() { return roomManager.rooms().stream() .map(room -> Map.of("name", room.name(), "members", room.members().size())) .toList(); } }
See Understanding @RoomService for the full annotation reference and Understanding Rooms for the programmatic API.
The starter includes optional health and metrics support:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency>
management: endpoints: web: exposure: include: health,metrics endpoint: health: show-details: always
This exposes an Atmosphere health indicator at /actuator/health and Micrometer metrics at /actuator/metrics:
| Metric | Description |
|---|---|
atmosphere.connections.active |
Currently connected clients |
atmosphere.connections.total |
Total connections since startup |
atmosphere.messages.broadcast |
Messages broadcast |
atmosphere.messages.delivered |
Messages delivered to clients |
atmosphere.broadcasters.active |
Active Broadcasters |
atmosphere.rooms.active |
Active Rooms |
atmosphere.rooms.members |
Room membership count |
atmosphere.cache.size |
BroadcasterCache entries |
atmosphere.cache.hits / misses / evictions
|
Cache performance |
atmosphere.backpressure.drops / disconnects
|
Backpressure events |
A ready-to-import Grafana dashboard is available at samples/shared-resources/grafana/atmosphere-dashboard.json. It includes panels for connections, message rates, broadcast latency (p50/p95/p99), room members, cache performance, and backpressure.
The starter auto-exposes the following Spring beans:
| Bean | Description |
|---|---|
AtmosphereFramework |
The core framework instance |
RoomManager |
Singleton room manager (auto-created) |
You can inject either into your Spring components:
@Service public class NotificationService { private final AtmosphereFramework framework; private final RoomManager roomManager; public NotificationService(AtmosphereFramework framework, RoomManager roomManager) { this.framework = framework; this.roomManager = roomManager; } }
The Atmosphere AI module adds real-time LLM token streaming over WebSocket. Add the dependency:
<dependency> <groupId>org.atmosphere</groupId> <artifactId>atmosphere-ai</artifactId> <version>4.0.1</version> </dependency>
Configure via environment variables or application.yml:
llm: mode: ${LLM_MODE:remote} model: ${LLM_MODEL:gemini-2.5-flash} api-key: ${LLM_API_KEY:${GEMINI_API_KEY:}}
See AI / LLM Streaming for the full guide, including Spring AI and LangChain4j adapter integration.