Quick Start Guide to Apache Pulsar with Docker Compose and Easy Spring Pulsar

This article walks through installing a local Apache Pulsar cluster with Docker Compose, using Pulsar Manager for administration, demonstrates native Java producer and consumer code, and introduces the Easy Spring Pulsar annotation library for concise Spring Boot integration.

Architect Practice
Architect Practice
Architect Practice
Quick Start Guide to Apache Pulsar with Docker Compose and Easy Spring Pulsar

1. Installing Pulsar with Docker Compose

Use Docker Compose to launch a local Pulsar cluster that includes Zookeeper, BookKeeper, a Pulsar broker, and optionally Pulsar Manager. The required containers are defined in a docker-compose.yml file.

version: '3'
networks:
  pulsar:
    driver: bridge
services:
  zookeeper:
    image: apachepulsar/pulsar:3.0.0
    container_name: zookeeper
    restart: on-failure
    networks:
      - pulsar
    volumes:
      - ./data/zookeeper:/pulsar/data/zookeeper
    environment:
      - metadataStoreUrl=zk:zookeeper:2181
      - PULSAR_MEM=-Xms256m -Xmx256m -XX:MaxDirectMemorySize=256m
    command: >
      bash -c "bin/apply-config-from-env.py conf/zookeeper.conf && \
               bin/generate-zookeeper-config.sh conf/zookeeper.conf && \
               exec bin/pulsar zookeeper"
    healthcheck:
      test: ["CMD", "bin/pulsar-zookeeper-ruok.sh"]
      interval: 10s
      timeout: 5s
      retries: 30
  pulsar-init:
    container_name: pulsar-init
    hostname: pulsar-init
    image: apachepulsar/pulsar:3.0.0
    networks:
      - pulsar
    command: >
      bin/pulsar initialize-cluster-metadata \
        --cluster cluster-a \
        --zookeeper zookeeper:2181 \
        --configuration-store zookeeper:2181 \
        --web-service-url http://broker:8080 \
        --broker-service-url pulsar://broker:6650
    depends_on:
      zookeeper:
        condition: service_healthy
  bookie:
    image: apachepulsar/pulsar:3.0.0
    container_name: bookie
    restart: on-failure
    networks:
      - pulsar
    environment:
      - clusterName=cluster-a
      - zkServers=zookeeper:2181
      - metadataServiceUri=metadata-store:zk:zookeeper:2181
      - advertisedAddress=bookie
      - BOOKIE_MEM=-Xms512m -Xmx512m -XX:MaxDirectMemorySize=256m
    command: bash -c "bin/apply-config-from-env.py conf/bookkeeper.conf && exec bin/pulsar bookie"
    depends_on:
      zookeeper:
        condition: service_healthy
      pulsar-init:
        condition: service_completed_successfully
    volumes:
      - ./data/bookkeeper:/pulsar/data/bookkeeper
  broker:
    image: apachepulsar/pulsar:3.0.0
    container_name: broker
    hostname: broker
    restart: on-failure
    networks:
      - pulsar
    environment:
      - metadataStoreUrl=zk:zookeeper:2181
      - zookeeperServers=zookeeper:2181
      - clusterName=cluster-a
      - managedLedgerDefaultEnsembleSize=1
      - managedLedgerDefaultWriteQuorum=1
      - managedLedgerDefaultAckQuorum=1
      - advertisedAddress=broker
      - advertisedListeners=external:pulsar://127.0.0.1:6650
      - PULSAR_MEM=-Xms512m -Xmx512m -XX:MaxDirectMemorySize=256m
    depends_on:
      zookeeper:
        condition: service_healthy
      bookie:
        condition: service_started
    ports:
      - "6650:6650"
      - "8080:8080"
    command: bash -c "bin/apply-config-from-env.py conf/broker.conf && exec bin/pulsar broker"
  manager:
    hostname: manager
    container_name: manager
    image: apachepulsar/pulsar-manager:v0.4.0
    ports:
      - "9527:9527"
      - "7750:7750"
    depends_on:
      - broker
    volumes:
      - "./data/:/data:z"
    environment:
      REDIRECT_HOST: "http://127.0.0.1"
      REDIRECT_PORT: "9527"
      DRIVER_CLASS_NAME: "org.postgresql.Driver"
      URL: "jdbc:postgresql://127.0.0.1:5432/pulsar_manager"
      USERNAME: "pulsar"
      PASSWORD: "pulsar"
      LOG_LEVEL: "DEBUG"
    networks:
      - pulsar

Start the stack with docker-compose up -d, verify the containers using docker ps, then create a Pulsar Manager admin account via curl commands. Access the manager UI at http://127.0.0.1:9527, create a new environment, and associate the Service URL ( pulsar://broker:6650) and Bookie URL with the cluster.

2. Native Java Client Examples

Producer example using the Pulsar Java client:

package com.example.springboot.pulsar;

import lombok.extern.slf4j.Slf4j;
import org.apache.pulsar.client.api.*;

@Slf4j
public class MyProducer {
    public static void main(String[] args) {
        String serviceUrl = "pulsar://localhost:6650";
        PulsarClient pulsarClient = null;
        Producer<String> producer = null;
        try {
            pulsarClient = PulsarClient.builder()
                .serviceUrl(serviceUrl)
                .build();
            producer = pulsarClient.newProducer(Schema.STRING)
                .producerName("produce-test")
                .topic("my-topic")
                .create();
            producer.send("hello world!");
            log.info("send success");
        } catch (PulsarClientException e) {
            throw new RuntimeException(e);
        } finally {
            try {
                pulsarClient.close();
                producer.close();
            } catch (PulsarClientException e) {
                throw new RuntimeException(e);
            }
        }
    }
}

Consumer example using the Pulsar Java client:

package com.example.springboot.pulsar;

import lombok.extern.slf4j.Slf4j;
import org.apache.pulsar.client.api.*;

@Slf4j
public class MyConsumer {
    public static void main(String[] args) {
        String serviceUrl = "pulsar://localhost:6650";
        PulsarClient pulsarClient = null;
        Consumer<String> consumer = null;
        try {
            pulsarClient = PulsarClient.builder()
                .serviceUrl(serviceUrl)
                .build();
            consumer = pulsarClient.newConsumer(Schema.STRING)
                .consumerName("consumer-test")
                .topic("my-topic")
                .subscriptionName("my-sub")
                .subscribe();
            Message<String> message = consumer.receive();
            String content = message.getValue();
            consumer.acknowledge(message);
            log.info("content:{}", content);
        } catch (PulsarClientException e) {
            throw new RuntimeException(e);
        } finally {
            try {
                pulsarClient.close();
                consumer.close();
            } catch (PulsarClientException e) {
                throw new RuntimeException(e);
            }
        }
    }
}

3. Annotation‑Based Development with Easy Spring Pulsar

Easy Spring Pulsar is a lightweight Spring Boot component that simplifies Pulsar usage through annotations such as @ConsumerHandler, @ProducerHandler, and @Subscription. Add the Maven dependency and configure the server URL:

com.allen.component:easy-spring-pulsar:${version}
pulsar:
  server:
    url: pulsar://localhost:6650
  common:
    env: dev

Consumer implementation using annotations:

@Slf4j
@ConsumerHandler(name = "order-consumer", topic = "order-created")
public class OrderConsumer implements CustomerConsumer {
    @Override
    @Subscription
    public void receive(DomainMessage eventMessage) {
        log.info("收到订单创建消息:{}", GsonUtil.toJson(eventMessage));
        // process order logic
    }
}

Producer implementation using annotations:

@Slf4j
@ProducerHandler(name = "order-producer", topic = "order-created")
public class OrderProducer implements CustomerProducer {
    public void createOrder(Order order) throws PulsarClientException {
        OrderCreatedMessage message = new OrderCreatedMessage();
        message.setData(order);
        message.setTimestamp(System.currentTimeMillis());
        Producer<String> producer = getProducer();
        String msg = serialize(message);
        log.info("发送订单创建消息:{}", msg);
        producer.send(msg);
    }
}

Compared with the raw API, Easy Spring Pulsar offers concise code, automatic connection handling, clear separation of business and messaging logic, environment‑aware topic isolation, and type‑safe generic message bodies.

Source Code Insights

The component’s core consists of PulsarBeanPostProcessor (detects annotated beans), PulsarInitializer (creates and manages producers/consumers), and the annotation definitions themselves. These classes leverage Spring’s BeanPostProcessor mechanism to register beans at runtime.

Conclusion

Apache Pulsar provides a robust distributed messaging backbone for micro‑service architectures. By combining Docker‑Compose‑based local deployment with the Easy Spring Pulsar annotation library, developers can quickly prototype and then scale production‑grade messaging with minimal boilerplate.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

javaspring-bootMessage QueueAnnotationApache PulsarDocker Compose
Architect Practice
Written by

Architect Practice

Committed to sharing tech and documenting ideas.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.