KubeMQ
Client SDKsJavaHow-to guidesConnection

Close a KubeMQ Java Client

Properly close a KubeMQ Java SDK client connection to release server resources and avoid leaks on shutdown.

Overview

Closing a client isn't an afterthought — it tells the broker and your own process that this connection is done, so both sides release what they were holding for it. A KubeMQ client is more than a socket: it's a gRPC channel plus whatever subscriptions and in-flight sends it's servicing. Skip the close and those linger — subscriptions keep streaming, the channel stays open — and in long-running services (or test suites spinning up many clients) you leak connections until the process dies.

Every KubeMQ client class implements AutoCloseable, so try-with-resources is the idiomatic way to guarantee close() runs when the block exits, even on exception. Calling close() explicitly drains in-flight operations and releases the gRPC channel and any background threads.

Gotchas: the drain window is bounded, not unlimited, so a slow consumer can still lose the tail of a burst if you close mid-stream; a closed client is dead forever — no reconnect on the same instance, build a new one; and when a process owns several client types (PubSubClient, QueuesClient, CQClient), close them in reverse construction order so nothing gets routed to a channel that's already tearing down.

Prerequisites

  • KubeMQ server running on localhost:50000
  • Java SDK installed (implementation 'io.kubemq.sdk:kubemq-sdk-Java:3.1.1' (Gradle) or Maven dependency from Getting Started)

Code

CloseExample.java
package io.kubemq.example.connection;

import io.kubemq.sdk.common.ServerInfo;
import io.kubemq.sdk.pubsub.PubSubClient;
import io.kubemq.sdk.queues.QueuesClient;
import io.kubemq.sdk.cq.CQClient;

/**
 * Close Example
 *
 * Demonstrates proper client lifecycle management: creating, using,
 * and closing KubeMQ clients. Shows try-with-resources and explicit close patterns.
 */
public class CloseExample {

    private static final String ADDRESS = "localhost:50000";
    private static final String CLIENT_ID = "java-connection-close-client";

    public void tryWithResourcesExample() {
        System.out.println("=== Try-With-Resources Pattern ===\n");

        // Client auto-closes when leaving try block
        try (QueuesClient client = QueuesClient.builder()
                .address(ADDRESS)
                .clientId(CLIENT_ID + "-twr")
                .build()) {

            ServerInfo info = client.ping();
            System.out.println("Connected: " + info.getHost());
            System.out.println("Client will be auto-closed when leaving this block.\n");

        } catch (Exception e) {
            System.err.println("Error: " + e.getMessage());
        }

        System.out.println("Client has been automatically closed.\n");
    }

    public void explicitCloseExample() {
        System.out.println("=== Explicit Close Pattern ===\n");

        // Create client and close explicitly in finally block
        PubSubClient client = null;
        try {
            client = PubSubClient.builder()
                    .address(ADDRESS)
                    .clientId(CLIENT_ID + "-explicit")
                    .build();

            ServerInfo info = client.ping();
            System.out.println("Connected: " + info.getHost());

        } catch (Exception e) {
            System.err.println("Error: " + e.getMessage());
        } finally {
            if (client != null) {
                client.close();
                System.out.println("Client explicitly closed.\n");
            }
        }
    }

    public void multiClientCloseExample() {
        System.out.println("=== Multi-Client Close ===\n");

        // Create multiple clients and close in reverse order
        PubSubClient pubSubClient = null;
        QueuesClient queuesClient = null;
        CQClient cqClient = null;

        try {
            pubSubClient = PubSubClient.builder()
                    .address(ADDRESS).clientId(CLIENT_ID + "-pubsub").build();
            queuesClient = QueuesClient.builder()
                    .address(ADDRESS).clientId(CLIENT_ID + "-queues").build();
            cqClient = CQClient.builder()
                    .address(ADDRESS).clientId(CLIENT_ID + "-cq").build();

            System.out.println("Three clients created.");
            pubSubClient.ping();
            queuesClient.ping();
            cqClient.ping();
            System.out.println("All clients connected.\n");

        } catch (Exception e) {
            System.err.println("Error: " + e.getMessage());
        } finally {
            if (cqClient != null) { cqClient.close(); System.out.println("CQClient closed."); }
            if (queuesClient != null) { queuesClient.close(); System.out.println("QueuesClient closed."); }
            if (pubSubClient != null) { pubSubClient.close(); System.out.println("PubSubClient closed."); }
        }
    }

    public static void main(String[] args) {
        CloseExample example = new CloseExample();
        example.tryWithResourcesExample();
        example.explicitCloseExample();
        example.multiClientCloseExample();
        System.out.println("\nClose examples completed.");
    }
}

How It Works

  • All KubeMQ client classes implement AutoCloseable, so try-with-resources is the preferred pattern — the gRPC channel and any background threads are released automatically when the block exits, even on exception.
  • The explicit close() call in a finally block is the fallback for long-lived clients that outlive a single try scope (e.g., Spring beans or background workers).
  • When closing multiple clients, reverse-construction order (CQClient → QueuesClient → PubSubClient) avoids sending messages on a channel that is already shutting down.
  • close() is idempotent and safe to call multiple times.

Was this page helpful?

On this page