Skip to content
jfarcand edited this page Feb 21, 2026 · 2 revisions

Kotlin DSL

Atmosphere 4.0 includes an optional atmosphere-kotlin module that provides an idiomatic Kotlin DSL for building AtmosphereHandler instances and coroutine extensions for non-blocking broadcast and write operations.

Dependency

<dependency>
    <groupId>org.atmosphere</groupId>
    <artifactId>atmosphere-kotlin</artifactId>
    <version>4.0.1</version>
</dependency>

Handler DSL

The atmosphere { } builder creates an AtmosphereHandler with lambda callbacks instead of verbose anonymous classes:

import org.atmosphere.kotlin.atmosphere

val handler = atmosphere {
    onConnect { resource ->
        println("${resource.uuid()} connected via ${resource.transport()}")
        resource.broadcaster.broadcast("${resource.uuid()} joined")
    }

    onMessage { resource, message ->
        resource.broadcaster.broadcast(message)
    }

    onDisconnect { resource ->
        resource.broadcaster.broadcast("${resource.uuid()} left")
    }

    onTimeout { resource ->
        println("${resource.uuid()} timed out")
    }
}

// Register with the framework
framework.addAtmosphereHandler("/chat", handler)

Available callbacks

Callback When it fires
onConnect Client connects (GET request, resource is suspended)
onMessage Message received (POST request, body parsed as String)
onDisconnect Client disconnects or connection closed
onTimeout Resource times out
onResume Resource is resumed

All callbacks are optional — only implement what you need.

Coroutine Extensions

The module provides suspending extension functions that bridge Atmosphere's blocking Future.get() calls into Kotlin structured concurrency:

import org.atmosphere.kotlin.broadcastSuspend
import org.atmosphere.kotlin.writeSuspend

Broadcaster.broadcastSuspend(message)

Suspends until broadcast delivery completes:

suspend fun handleMessage(broadcaster: Broadcaster, message: String) {
    broadcaster.broadcastSuspend(message)
    println("Delivered to all connected clients")
}

Broadcaster.broadcastSuspend(message, resource)

Targeted broadcast to a specific resource:

suspend fun directMessage(broadcaster: Broadcaster, resource: AtmosphereResource, message: String) {
    broadcaster.broadcastSuspend(message, resource)
}

AtmosphereResource.writeSuspend(data)

Write directly to a resource (String or ByteArray):

suspend fun respond(resource: AtmosphereResource) {
    resource.writeSuspend("Hello from a coroutine")
    resource.writeSuspend(byteArrayOf(0x01, 0x02))
}

All extensions use withContext(Dispatchers.IO) internally to avoid blocking the caller's coroutine dispatcher.

Usage with Spring Boot

Use the DSL to programmatically register handlers in a Spring Boot application:

@Configuration
class AtmosphereConfig {

    @Bean
    fun customizeFramework(): AtmosphereFrameworkCustomizer {
        return AtmosphereFrameworkCustomizer { framework ->
            framework.addAtmosphereHandler("/notifications", atmosphere {
                onConnect { resource ->
                    resource.suspend()
                }
                onMessage { resource, message ->
                    resource.broadcaster.broadcast(message)
                }
            })
        }
    }
}

Note: For most use cases, the annotation-driven approach with @ManagedService or @RoomService is simpler. The Kotlin DSL is best for dynamic handler registration, testing, or when you prefer a programmatic style over annotations.

See Also

Clone this wiki locally