KubeMQ
IntegrationsSpring BootHow-to guides

Configure Connection, TLS, and Observability

Tune the gRPC connection, enable TLS/mTLS and auth tokens, and wire up health checks and Micrometer metrics.

Every KubeMQ Spring Boot setting is bound under the kubemq.* prefix from KubeMQProperties and resolved at startup by the auto-configuration. This guide walks the connection settings you will tune most often — broker address and client identity, gRPC timeouts and keep-alive, TLS/mTLS, auth tokens, per-environment profiles, and the health, metrics, and tracing surfaces — using the exact property names and defaults the starter ships with.

All snippets assume the starter is on the classpath:

build.gradle.kts
dependencies {
    implementation("io.kubemq:kubemq-spring-boot-starter:1.0.0")
}

And a broker to connect to — the gRPC API listens on 50000, the shared HTTP/REST and dashboard endpoints on 9090:

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

Prerequisites

  • kubemq-spring-boot-starter on the classpath, in a Spring Boot 3.2.0+ application (see Getting Started with Spring Boot)
  • The broker above running and reachable
  • spring-boot-starter-actuator and a Micrometer registry (for example micrometer-registry-prometheus) added if you use the Health or Metrics & Tracing sections below

Connection Basics

The four top-level properties establish which broker the application talks to and who it is. kubemq.enabled is the master switch for the entire auto-configuration — set it to false to disable KubeMQ wiring without removing the dependency (useful for tests or environments where the broker is absent).

application.yml
kubemq:
  enabled: true                # master switch; default true
  address: localhost:50000     # broker gRPC address, host:port
  client-id: my-service        # sent with every request; empty = SDK generates a UUID
  auth-token: ${KUBEMQ_AUTH_TOKEN:}  # JWT/OIDC token; never hardcode

The defaults from KubeMQProperties are address: localhost:50000, an empty client-id (the SDK generates a UUID per process), and an empty auth-token. Externalize the address with a placeholder so the same artifact runs against any broker, exactly as the connection-auth-token example does:

connection-auth-token/application.yml
spring:
  application:
    name: kubemq-example-connection-auth-token
  main:
    web-application-type: none

kubemq:
  # Broker address (override with KUBEMQ_ADDRESS env var)
  address: ${KUBEMQ_ADDRESS:localhost:50000}
  # Unique client identifier for this example
  client-id: spring-connection-auth-token
  # WARNING: Never commit auth tokens to source control. Use environment variables only.
  auth-token: ${KUBEMQ_AUTH_TOKEN:}

Give every service a stable, descriptive client-id. It shows up in broker-side dashboards and connection metadata, which makes diagnosing "who is connected" far easier than reading randomly generated UUIDs.

Connection Tuning

The kubemq.connection.* block (bound to KubeMQProperties.Connection) controls the gRPC channel itself: the request timeout, the maximum inbound message size, and keep-alive ping behaviour. The defaults are tuned for typical workloads.

application.yml
kubemq:
  connection:
    timeout: 30s              # default 30s — per-request gRPC deadline
    max-receive-size: 100MB   # default 100MB — max inbound message size
    keep-alive:
      time: 30s               # default 30s — interval between keep-alive pings
      timeout: 10s            # default 10s — wait for a ping ack before failing

Prop

Type

Durations accept Spring's ISO-style suffixes (30s, 2m, 500ms) and DataSize accepts 100MB, 512KB, and similar. Raise max-receive-size if you publish payloads larger than 100 MB; shorten keep-alive.time if you sit behind a proxy that aggressively closes idle connections.

TLS and mTLS

TLS is configured under kubemq.tls.* (bound to KubeMQProperties.Tls) and is disabled by default. There are two postures:

  • One-way (server) TLS — the client verifies the broker's certificate against a CA bundle. Set enabled: true and ca-cert-file (plus cert-file if your broker requires the client to present one).
  • Mutual TLS (mTLS) — both sides authenticate. Provide cert-file and key-file for the client identity, and ca-cert-file to verify the broker.
connection-tls/application.yml
kubemq:
  address: ${KUBEMQ_ADDRESS:localhost:50000}
  client-id: spring-connection-tls
  tls:
    enabled: true
    cert-file: ${KUBEMQ_TLS_CERT:/path/to/client.crt}
    ca-cert-file: ${KUBEMQ_TLS_CA_CERT:/path/to/ca.crt}
    # Ensure the broker certificate SAN matches the hostname in kubemq.address.
connection-mtls/application.yml
kubemq:
  address: ${KUBEMQ_ADDRESS:localhost:50000}
  client-id: spring-connection-mtls
  tls:
    enabled: true
    cert-file: ${KUBEMQ_TLS_CERT:/path/to/client.crt}
    key-file: ${KUBEMQ_TLS_KEY:/path/to/client.key}
    ca-cert-file: ${KUBEMQ_TLS_CA_CERT:/path/to/ca.crt}
    # Ensure the broker certificate SAN matches the hostname in kubemq.address.

Prop

Type

The broker certificate's SAN must match the hostname in kubemq.address, and hostname verification should never be disabled in production. Keep certificate and key paths out of source control — point them at mounted secrets or environment-resolved paths.

Auth Tokens

kubemq.auth-token carries a JWT or OIDC token that the broker validates on connect. It is sent with every request alongside the client-id. Because it is a credential, resolve it from the environment and never write the literal value into a committed file:

application.yml
kubemq:
  address: ${KUBEMQ_ADDRESS:localhost:50000}
  client-id: my-service
  auth-token: ${KUBEMQ_AUTH_TOKEN:}
Provide the token at runtime
export KUBEMQ_AUTH_TOKEN="$(cat /var/run/secrets/kubemq/token)"
java -jar my-service.jar

An empty auth-token (the default) means the application connects without presenting a token — appropriate only when the broker does not enforce authentication.

Profile-Based Configuration

Use Spring profiles to keep per-environment settings in application-{profile}.yml. The autoconfigure-profiles example ships a base file plus dev, staging, and prod overlays. The base file selects the active profile and holds shared defaults:

application.yml
spring:
  profiles:
    active: ${SPRING_PROFILES_ACTIVE:dev}

kubemq:
  address: ${KUBEMQ_ADDRESS:localhost:50000}
  client-id: spring-autoconfigure-profiles

Each overlay layers only what changes for that environment:

application-dev.yml
kubemq:
  address: ${KUBEMQ_ADDRESS:localhost:50000}
  client-id: spring-profiles-dev

logging:
  level:
    io.kubemq: DEBUG
application-staging.yml
kubemq:
  address: staging-broker:50000
  client-id: spring-profiles-staging
application-prod.yml
kubemq:
  address: ${KUBEMQ_ADDRESS:prod-broker:50000}
  client-id: spring-profiles-prod
  tls:
    # Set paths via env in production — never commit key material or PEM files.
    enabled: ${KUBEMQ_TLS_ENABLED:true}
    ca-cert-file: ${KUBEMQ_TLS_CA_CERT:}
    cert-file: ${KUBEMQ_TLS_CERT:}
    key-file: ${KUBEMQ_TLS_KEY:}

Activate a profile with --spring.profiles.active=prod or the SPRING_PROFILES_ACTIVE environment variable.

Health

The starter contributes two Actuator surfaces, both backed by pings to all three KubeMQ SDK clients (PubSubClient, QueuesClient, CQClient). They are configured under kubemq.health.* (bound to KubeMQProperties.Health).

application.yml
kubemq:
  health:
    enabled: true             # default true
    timeout: 5s               # default 5s — per-ping deadline
    cache-duration: 15s       # default 15s — reuse the last result within this window

management:
  endpoints:
    web:
      exposure:
        include: health,info
  endpoint:
    health:
      show-details: when-authorized

KubeMQHealthIndicator rolls up into the standard Spring Boot /actuator/health endpoint: UP with host and version details when every client responds to a ping, DOWN with the failing exception type otherwise. Results are cached for cache-duration so frequent probes do not flood the broker, and each ping is bounded by timeout.

The dedicated KubeMQEndpoint exposes /actuator/kubemq, which probes the three clients individually and reports a per-client breakdown:

GET /actuator/kubemq
{
  "status": "connected",
  "clients": {
    "pubsub": { "status": "connected", "host": "kubemq-host", "version": "2.x.x", "errorType": null },
    "queues": { "status": "connected", "host": "kubemq-host", "version": "2.x.x", "errorType": null },
    "cq":     { "status": "connected", "host": "kubemq-host", "version": "2.x.x", "errorType": null }
  }
}

The top-level status is connected only when all three clients are connected; if any client fails its ping it is marked disconnected (with the exception type in errorType) and the aggregate becomes degraded. Expose the endpoint by adding kubemq to the management exposure list:

application.yml
management:
  endpoints:
    web:
      exposure:
        include: health,info,kubemq

show-details: always and exposing Actuator endpoints without authentication are for local development only. In production use when-authorized with Spring Security, or bind the management port to loopback.

Metrics & Tracing

The starter integrates with Micrometer in two complementary ways, controlled by separate switches.

kubemq.metrics.* (bound to KubeMQProperties.Metrics) governs the kubemq.connection.state gauge, registered by KubeMQMetricsAutoConfiguration when kubemq.metrics.enabled is true (the default). The gauge probes all three clients and caches the result for scrape-interval so scraping does not overload the broker — it reads 1.0 when connected and 0.0 when not.

kubemq.template.observation-enabled (bound to KubeMQProperties.Template, default true) drives Micrometer Observation instrumentation on the KubeMQTemplate send path and the listener receive path, producing timers, counters, and — when a tracer is present — distributed traces.

observability-micrometer/application.yml
management:
  endpoints:
    web:
      exposure:
        include: health,prometheus,metrics
  metrics:
    export:
      prometheus:
        enabled: true

kubemq:
  address: ${KUBEMQ_ADDRESS:localhost:50000}
  client-id: spring-observability-micrometer
  metrics:
    enabled: true             # default true — registers kubemq.connection.state gauge
    scrape-interval: 30s      # default 30s — gauge probe caching window
  template:
    observation-enabled: true # default true — send/receive Observation instrumentation

Add the Actuator and a registry to the project to scrape these meters:

build.gradle.kts
dependencies {
    implementation("io.kubemq:kubemq-spring-boot-starter:1.0.0")
    implementation("org.springframework.boot:spring-boot-starter-web")
    implementation("org.springframework.boot:spring-boot-starter-actuator")
    implementation("io.micrometer:micrometer-registry-prometheus")
}

Prop

Type

Kotlin DSL Alternative

The Kotlin starter (kubemq-spring-boot-starter-kotlin) adds a type-safe configuration DSL. Expose a KubeMQConfigurerDsl bean built with the kubemq { } builder to set the address, identity, TLS, and connection tuning programmatically instead of in YAML:

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
import java.time.Duration

@Configuration
class KubeMQConfig {
    @Bean
    fun kubemqConfigurer(): KubeMQConfigurerDsl = kubemq {
        address = "broker.example.com:50000"
        clientId = "my-service"
        tls {
            enabled = true
            certFile = "/certs/client.pem"
            keyFile = "/certs/client-key.pem"
            caCertFile = "/certs/ca.pem"
        }
        connection {
            timeout = Duration.ofSeconds(15)
        }
    }
}

The tls { } and connection { } blocks map one-to-one onto the same KubeMQProperties.Tls and KubeMQProperties.Connection fields shown above. For Kotlin services that drive suspend-function listeners, kubemq.kotlin.dispatcher selects the coroutine dispatcher (default, io, or unconfined; default default):

application.yml
kubemq:
  kotlin:
    dispatcher: io   # default | io | unconfined

Graceful Shutdown & Reconnection

kubemq.listener.shutdown-timeout (default 30s, on KubeMQProperties.Listener) bounds how long the listener infrastructure waits for in-flight work to finish during shutdown. Combined with Spring's lifecycle hooks (SmartLifecycle, @PreDestroy), it lets a service drain cleanly on SIGTERM:

application.yml
kubemq:
  listener:
    shutdown-timeout: 30s   # default 30s — wait for in-flight work before stopping

Reconnection is handled automatically by the underlying SDK clients. To observe or react to connection state changes, register a ConnectionStateListener on an injected client:

ReconnectionRunner.java
@PostConstruct
public void registerConnectionStateListener() {
    pubSubClient.addConnectionStateListener(new ConnectionStateListener() {
        @Override public void onConnected()        { log.info("Connection established"); }
        @Override public void onDisconnected()     { log.warn("Connection lost — reconnecting automatically"); }
        @Override public void onReconnecting(int attempt) { log.info("Reconnection attempt #{}", attempt); }
        @Override public void onReconnected()      { log.info("Reconnection successful — subscriptions recovered"); }
        @Override public void onClosed()           { log.info("Connection closed"); }
    });
}

When a listener throws, provide a KubeMQErrorHandler bean to centralize error handling instead of relying on the default logging:

ReconnectionErrorConfig.java
@Configuration
public class ReconnectionErrorConfig {
    @Bean
    public KubeMQErrorHandler kubemqErrorHandler() {
        return new KubeMQErrorHandler() {
            @Override
            public void handleError(Throwable t) {
                log.error("KubeMQ listener error [{}]: {}", t.getClass().getSimpleName(), t.getMessage());
            }
        };
    }
}

Full Property Reference

This guide covers the connection, security, and observability properties you tune most often. For the complete list of kubemq.* properties — including the per-pattern listener settings (kubemq.listener.queues.*, commands, queries) — see the Configuration Reference; for the KubeMQTemplate API and annotations, see the API Reference.

Was this page helpful?

On this page