Skip to content

Getting Started with Spring Boot

jfarcand edited this page Feb 18, 2026 · 7 revisions

Getting Started with Spring Boot 4.0

Build a real-time chat application with Atmosphere and Spring Boot 4.0 in minutes.

Prerequisites

  • JDK 21+
  • Maven 3.9+

1. Create the Project

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.0</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>

2. Configure

In application.yml:

atmosphere:
  packages: com.example.chat

That's it — the starter auto-configures the AtmosphereServlet mapped to /atmosphere/*.

Available Properties

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

3. Create the Chat Service

@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.

4. Create the Message Class

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
}

5. Create Encoder and Decoder

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); }
    }
}

6. Create the Application

@SpringBootApplication
public class ChatApplication {
    public static void main(String[] args) {
        SpringApplication.run(ChatApplication.class, args);
    }
}

7. Add the Client

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 = '';
    });
});

8. Run

mvn spring-boot:run

Open http://localhost:8080 and start chatting!

Adding Rooms

See the Spring Boot Chat + Rooms sample for a complete example using RoomManager, presence events, and a REST API for room listing. Also see Understanding Rooms.

Actuator Integration

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.

Spring Beans Integration

The AtmosphereFramework is available as a Spring bean. You can inject it to configure rooms, interceptors, or access the BroadcasterFactory programmatically:

@Configuration
public class RoomsConfig {
    private final AtmosphereFramework framework;

    public RoomsConfig(AtmosphereFramework framework) {
        this.framework = framework;
    }

    @Bean
    public RoomManager roomManager() {
        return RoomManager.getOrCreate(framework);
    }
}

Clone this wiki locally