-
-
Notifications
You must be signed in to change notification settings - Fork 755
Getting Started with Quarkus
Build a real-time chat application with Atmosphere and Quarkus 3.21+.
- JDK 21+
- Maven 3.9+
<properties>
<quarkus.version>3.31.3</quarkus.version>
<maven.compiler.release>21</maven.compiler.release>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-bom</artifactId>
<version>${quarkus.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.atmosphere</groupId>
<artifactId>atmosphere-quarkus-extension</artifactId>
<version>4.0.1</version>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-undertow</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-websockets</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-jackson</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-maven-plugin</artifactId>
<version>${quarkus.version}</version>
<extensions>true</extensions>
<executions>
<execution>
<goals><goal>build</goal></goals>
</execution>
</executions>
</plugin>
</plugins>
</build>In application.properties:
quarkus.atmosphere.packages=com.example.chatThe extension auto-configures the AtmosphereServlet and handles build-time annotation scanning.
| Property | Default | Description |
|---|---|---|
quarkus.atmosphere.packages |
(none) | Packages to scan for annotations |
quarkus.atmosphere.servlet-path |
/atmosphere/* |
Servlet URL mapping |
quarkus.atmosphere.session-support |
false |
Enable HttpSession support |
quarkus.atmosphere.heartbeat-interval-in-seconds |
(default) | Heartbeat frequency |
The code is identical to other deployment models — @ManagedService works the same everywhere:
@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
}
@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;
}
}You also need a Message class and JacksonEncoder/JacksonDecoder — these are identical to the Spring Boot guide. See Getting Started with Spring Boot for the full code.
Place atmosphere.js in src/main/resources/META-INF/resources/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/META-INF/resources/javascript/Create src/main/resources/META-INF/resources/index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Atmosphere 4.0 Chat — Quarkus</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 — Quarkus</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/META-INF/resources/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 quarkus:devOpen http://localhost:8080 and start chatting!
The Quarkus extension supports GraalVM native compilation:
mvn package -Dnative
./target/atmosphere-quarkus-chat-4.0.1-runnerThe extension registers all Atmosphere classes for reflection at build time, so native images work out of the box.
The Quarkus extension differs from other deployment models in how it initializes:
-
Build time —
AtmosphereProcessorscans for@ManagedService,@RoomService, and other Atmosphere annotations, registering classes for reflection -
Build time — JSR-356 WebSocket endpoints are registered via
AtmosphereRecorder -
Runtime —
QuarkusAtmosphereServletinitializes the framework with the pre-scanned annotation map -
Runtime —
QuarkusAtmosphereObjectFactorydelegates bean creation to the Arc CDI container
This build-time processing is what makes Quarkus startup fast and native-image compatible.
@RoomService works out of the box — the extension scans it at build time alongside @ManagedService:
@RoomService(path = "/chat/{roomId}", maxHistory = 50)
public class ChatRoom {
@Message(encoders = {JacksonEncoder.class}, decoders = {JacksonDecoder.class})
public Message onMessage(Message message) {
return message;
}
}See Understanding @RoomService for the full annotation reference.
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:
export LLM_MODE=remote # or "local" for Ollama
export LLM_MODEL=gemini-2.5-flash # or gpt-4o, llama3.2, etc.
export LLM_API_KEY=your-keySee AI / LLM Streaming for the full guide, including adapter integration and virtual room members.