-
-
Notifications
You must be signed in to change notification settings - Fork 755
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.chatThat'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:runOpen 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: alwaysThis 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.