KubeMQ
IntegrationsSpring BootTutorials

Getting Started with Spring Boot

Add the KubeMQ starter, configure it, and run your first end-to-end publish-and-subscribe example in a Spring Boot app.

The KubeMQ Spring Boot starter brings auto-configuration, a KubeMQTemplate for sending, and annotation-driven listeners to any Spring Boot application. This guide walks you from an empty project to a running app that publishes and receives events end-to-end against a local broker.

Getting started

Prerequisites

You need the following installed:

RequirementVersion
Java17+
Spring Boot3.2.0+
DockerAny recent version (for a local broker)

The starter talks to KubeMQ over gRPC only, so no HTTP connector or extra port is required for this guide.

Start KubeMQ

Run KubeMQ in Docker. The gRPC port 50000 is the only port the Spring Boot starter uses:

docker run -d \  --name kubemq \  -p 50000:50000 \  -e KUBEMQ_TOKEN=YOUR_LICENSE_KEY \  europe-docker.pkg.dev/kubemq/images/kubemq:next

This matches the starter's default — KubeMQProperties.address is localhost:50000 out of the box, so a broker on the local machine needs no extra configuration.

Port 50000 is the native gRPC port used by all KubeMQ SDKs. The Spring Boot integration is built on the KubeMQ Java SDK, so it connects directly over gRPC rather than the shared HTTP server.

Add the Dependency

Add the starter to your build. It is published under the io.kubemq group, version 1.0.0.

build.gradle.kts
dependencies {
    implementation("io.kubemq:kubemq-spring-boot-starter:1.0.0")
}
pom.xml
<dependency>
    <groupId>io.kubemq</groupId>
    <artifactId>kubemq-spring-boot-starter</artifactId>
    <version>1.0.0</version>
</dependency>

The starter is a dependency aggregator — adding it pulls in the auto-configuration module, the KubeMQTemplate, listener annotations, health, and metrics.

Configure application.yml

Configure the broker address and a client identifier under the kubemq prefix. Because this example is a non-web app, also set spring.main.web-application-type: none:

src/main/resources/application.yml
spring:
  application:
    name: kubemq-example-events-basic-pubsub
  main:
    web-application-type: none

kubemq:
  address: ${KUBEMQ_ADDRESS:localhost:50000}
  client-id: spring-events-basic-pubsub

The ${KUBEMQ_ADDRESS:localhost:50000} placeholder lets you override the broker address with an environment variable in other environments while defaulting to your local Docker broker. The client-id is sent with every request and identifies this application to the broker.

Send a Message

Inject KubeMQTemplate into any Spring bean and call sendEvent(channel, payload). The template serializes the payload and publishes a fire-and-forget event:

OrderService.java
import io.kubemq.spring.boot.autoconfigure.template.KubeMQTemplate;
import org.springframework.stereotype.Service;

@Service
public class OrderService {

    private final KubeMQTemplate template;

    public OrderService(KubeMQTemplate template) {
        this.template = template;
    }

    public void placeOrder(Order order) {
        template.sendEvent("orders", order);
    }
}

sendEvent is overloaded — you can pass a Map<String, String> of tags as a third argument, and sendEventAsync returns a CompletableFuture<Void> for non-blocking sends.

Receive a Message

Annotate a method with @KubeMQEventListener to subscribe to one or more channels. The method receives an EventMessageReceived; call getBody() to read the raw payload bytes:

BasicPubSubListener.java
package io.kubemq.spring.boot.examples.events;

import io.kubemq.sdk.pubsub.EventMessageReceived;
import io.kubemq.spring.boot.autoconfigure.listener.KubeMQEventListener;
import java.nio.charset.StandardCharsets;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

@Component
public class BasicPubSubListener {

    private static final Logger log = LoggerFactory.getLogger(BasicPubSubListener.class);

    @KubeMQEventListener(channels = "spring-events.basic-pubsub")
    public void onEvent(EventMessageReceived event) {
        byte[] body = event.getBody();
        String text = body != null ? new String(body, StandardCharsets.UTF_8) : "<empty>";
        log.info("Received event: channel={} body={}", event.getChannel(), text);
    }
}

The channels attribute accepts one or more channel names and supports SpEL expressions and property placeholders (for example channels = "${kubemq.channels.orders}").

Run and Observe

Start your application. The listener subscribes on startup, the publisher sends three events to spring-events.basic-pubsub, and both sides log to the console. You should see interleaved Published and Received lines:

INFO  Received event: channel=spring-events.basic-pubsub body=Hello KubeMQ #1
INFO  Published event to spring-events.basic-pubsub: Hello KubeMQ #1
INFO  Received event: channel=spring-events.basic-pubsub body=Hello KubeMQ #2
INFO  Published event to spring-events.basic-pubsub: Hello KubeMQ #2
INFO  Received event: channel=spring-events.basic-pubsub body=Hello KubeMQ #3
INFO  Published event to spring-events.basic-pubsub: Hello KubeMQ #3
INFO  Basic pub/sub example completed.

Events are fire-and-forget: the listener must be subscribed before a message is sent, otherwise that message is not delivered. The example inserts a short warm-up delay before publishing so the subscription is established first.

Java vs Kotlin

The starter is fully usable from Java with YAML configuration. The optional kubemq-spring-boot-starter-kotlin module adds a configuration DSL and coroutine-friendly suspend extensions.

Configure with application.yml and send with the blocking sendEvent:

OrderService.java
@Service
public class OrderService {

    private final KubeMQTemplate template;

    public OrderService(KubeMQTemplate template) {
        this.template = template;
    }

    public void placeOrder(Order order) {
        template.sendEvent("orders", order);
    }
}

Configure programmatically with the kubemq { } DSL by exposing it as a bean:

KubeMQConfig.kt
import io.kubemq.spring.boot.kotlin.KubeMQConfigurerDsl
import io.kubemq.spring.boot.kotlin.kubemq
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration

@Configuration
class KubeMQConfig {

    @Bean
    fun kubemqConfigurer(): KubeMQConfigurerDsl = kubemq {
        address = "localhost:50000"
        clientId = "spring-kotlin-dsl-config"
    }
}

Send from a coroutine with the sendEventSuspend extension, which suspends until the underlying async send completes:

CoroutinePublishRunner.kt
import io.kubemq.spring.boot.autoconfigure.template.KubeMQTemplate
import io.kubemq.spring.boot.kotlin.sendEventSuspend
import kotlinx.coroutines.runBlocking
import org.springframework.boot.ApplicationArguments
import org.springframework.boot.ApplicationRunner
import org.springframework.stereotype.Component

@Component
class CoroutinePublishRunner(private val template: KubeMQTemplate) : ApplicationRunner {

    override fun run(args: ApplicationArguments) {
        runBlocking {
            template.sendEventSuspend("spring-kotlin.coroutine-publish", "Coroutine event")
        }
    }
}

Was this page helpful?

On this page