DataStax Fast JMS for Apache Pulsar standalone quick start

This quick start will get you up and running with a simple command-line Java JMS client that can talk to a local Pulsar installation. The client:

  1. Initializes a DataStax Fast JMS for Apache Pulsar queue.

  2. Attaches a message listener to that queue.

  3. Produces 10 messages that are then consumed and printed out in an onMessage callback.

Prerequisites

Install a Pulsar instance using Docker

To install a Docker Pulsar instance:

  1. Make sure you have Docker installed on your platform.

  2. Open a terminal and create a Pulsar Docker instance:

    docker run --name pulsar-jms-runner -p 8080:8080 -p 6650:6650 apachepulsar/pulsar:latest /pulsar/bin/pulsar standalone

    Results:

    Many status messages...
    
    14:57:50.996 [pulsar-web-68-11] INFO  org.eclipse.jetty.server.RequestLog - 127.0.0.1 - - [07/May/2021:14:57:50 +0000] "GET /admin/v2/persistent/public/functions/coordinate/stats?getPreciseBacklog=false&subscriptionBacklogSize=false HTTP/1.1" 200 1677 "-" "Pulsar-Java-v2.7.1" 3
    14:58:20.962 [pulsar-web-68-1] INFO  org.eclipse.jetty.server.RequestLog - 127.0.0.1 - - [07/May/2021:14:58:20 +0000] "GET /admin/v2/persistent/public/functions/coordinate/stats?getPreciseBacklog=false&subscriptionBacklogSize=false HTTP/1.1" 200 1677 "-" "Pulsar-Java-v2.7.1" 3
    14:58:50.926 [pulsar-web-68-12] INFO  org.eclipse.jetty.server.RequestLog - 127.0.0.1 - - [07/May/2021:14:58:50 +0000] "GET /admin/v2/persistent/public/functions/coordinate/stats?getPreciseBacklog=false&subscriptionBacklogSize=false HTTP/1.1" 200 1677 "-" "Pulsar-Java-v2.7.1" 3
    14:59:20.892 [pulsar-web-68-2] INFO  org.eclipse.jetty.server.RequestLog - 127.0.0.1 - - [07/May/2021:14:59:20 +0000] "GET /admin/v2/persistent/public/functions/coordinate/stats?getPreciseBacklog=false&subscriptionBacklogSize=false HTTP/1.1" 200 1677 "-" "Pulsar-Java-v2.7.1" 4
    14:59:50.857 [pulsar-web-68-3] INFO  org.eclipse.jetty.server.RequestLog - 127.0.0.1 - - [07/May/2021:14:59:50 +0000] "GET /admin/v2/persistent/public/functions/coordinate/stats?getPreciseBacklog=false&subscriptionBacklogSize=false HTTP/1.1" 200 1677 "-" "Pulsar-Java-v2.7.1" 3

You’ve now got a Pulsar instance up and running.

Leave the terminal running in the background.

Create your Maven configuration file

We’ll use Apache Maven to handle dependency management so you don’t have to manually download and install required libraries.

  1. Create a project directory in a convenient location.

  2. Save the following file as pom.xml in your project directory.

    <?xml version="1.0" encoding="UTF-8"?>
    <project>
      <modelVersion>4.0.0</modelVersion>
      <groupId>com.datastax.oss</groupId>
      <artifactId>pulsar-fast-jms-example</artifactId> (1)
      <packaging>jar</packaging>
      <version>1.0</version>
      <name>DataStax Fast JMS for Apache Pulsar (R) example</name>
      <description>A simple JMS client designed to test the DataStax Fast JMS for Apache Pulsar library.</description>
      <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <java.release.version>8</java.release.version>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
      </properties>
        <dependencies>
          <dependency>
            <groupId>com.datastax.oss</groupId>
            <artifactId>pulsar-jms-all</artifactId> (2)
            <version>1.0.0</version>
          </dependency>
          <dependency>
            <groupId>org.slf4j</groupId> (3)
            <artifactId>slf4j-simple</artifactId>
            <version>1.7.30</version>
          </dependency>
        </dependencies>
      <build>
        <plugins>
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-assembly-plugin</artifactId>
            <version>3.3.0</version>
            <configuration>
                <descriptorRefs>
                    <descriptorRef>jar-with-dependencies</descriptorRef> (4)
                </descriptorRefs>
                <archive>
                  <manifest>
                    <mainClass>example.StandaloneTest</mainClass> (5)
                  </manifest>
                </archive>
            </configuration>
            <executions>
                <execution>
                    <id>assemble-all</id>
                    <phase>package</phase>
                    <goals>
                        <goal>single</goal>
                    </goals>
                </execution>
            </executions>
          </plugin>
        </plugins>
      </build>
    </project>

Note the following elements:

  1. The main name for the compiled JAR file.

  2. The DataStax Fast JMS for Apache Pulsar dependency. In this case we’re using a "fat" JAR file, pulsar-jms-all, that includes all dependencies.

  3. The Log4J dependency.

  4. An additional descriptor appended to the JAR file name.

  5. The default package and class, example.StandaloneTest, so you can just run the JAR file without any additional specifications.

Create the standalone example app

To create the standalone example app:

  1. In the project directory you created above, create the following directory hierarchy, <project-directory>/src/main/java/example:

    cd <project-directory>
    mkdir -p /src/main/java/example
  2. Copy the following code into a file named StandaloneTest.java and save the file:

    package example;
    
    import com.datastax.oss.pulsar.jms.PulsarConnectionFactory;
    import javax.jms.JMSContext;
    import javax.jms.Message;
    import javax.jms.MessageListener;
    import javax.jms.Queue;
    import java.util.HashMap;
    import java.util.Map;
    
    public class StandaloneTest {
        public static void main(String ... args) throws Exception {
    
            String topic = "persistent://public/default/example-topic"; (1)
    
            Map<String, Object> properties = new HashMap<>(); (2)
    
            try (PulsarConnectionFactory factory = new PulsarConnectionFactory(properties); ){
                JMSContext context = factory.createContext();
                Queue queue = context.createQueue(topic); (3)
    
                // Listen for messages...
                context.createConsumer(queue).setMessageListener(new MessageListener() { (4)
                    @Override
                    public void onMessage(Message message) { (5)
                        try {
                            System.out.println("Received: " + message.getBody(String.class));
                        } catch (Exception err) {
                            err.printStackTrace();
                        }
                    }
                });
    
                for (int i = 0; i < 10; i++) { (6)
                    String message = "Hello world! " + i;
                    System.out.println("Sending: "+message);
                    context.createProducer().send(queue, message);
                }
    
                Thread.sleep(10000); (7)
            }
        }
    }

In the code example above, note the following points of interest:

  1. The topic URI the client will use to publish and consume messages. We’re using the default tenant and namespace here, but you can call the topic itself anything you like and it will be auto-created.

  2. Creates an empty properties hashmap. Refer to DataStax Fast JMS for Apache Pulsar configuration reference for additional DataStax Fast JMS for Apache Pulsar configuration options.

    You’ll need to override webServiceUrl if you’re not using the default Pulsar Docker instance in this example.
  3. Creates a DataStax Fast JMS for Apache Pulsar queue. For more information on mapping Pulsar to JMS concepts, see Mapping Pulsar concepts to JMS specifications.

  4. Creates a DataStax Fast JMS for Apache Pulsar consumer context using the createConsumer method…​

  5. …​ and initializes an onMessage callback to consume the messages as they arrive.

  6. Sends 10 "Hello World!" messages to the queue using the createProducer method.

  7. Sleeps for 10 seconds to make sure all of the messages are consumed.

Compile the application

To compile the sample application:

  1. Change to the <product_directory.

  2. Run the maven command:

    mvn clean install

    Results:

    Many status messages...
    
    [INFO] Installing /Users/john.francis/fast-jms/target/pulsar-fast-jms-example-1.0.jar to /Users/john.francis/.m2/repository/com/datastax/oss/pulsar-fast-jms-example/1.0/pulsar-fast-jms-example-1.0.jar
    [INFO] Installing /Users/john.francis/fast-jms/pom.xml to /Users/john.francis/.m2/repository/com/datastax/oss/pulsar-fast-jms-example/1.0/pulsar-fast-jms-example-1.0.pom
    [INFO] Installing /Users/john.francis/fast-jms/target/pulsar-fast-jms-example-1.0-jar-with-dependencies.jar to /Users/john.francis/.m2/repository/com/datastax/oss/pulsar-fast-jms-example/1.0/pulsar-fast-jms-example-1.0-jar-with-dependencies.jar
    [INFO] ------------------------------------------------------------------------
    [INFO] BUILD SUCCESS
    [INFO] ------------------------------------------------------------------------
    [INFO] Total time:  31.351 s
    [INFO] Finished at: 2021-05-07T11:11:02-05:00
    [INFO] ------------------------------------------------------------------------
The first time you compile the JAR file, Maven downloads all required dependencies. Subsequent runs will be much faster.

Run the example

To run the sample app, from the <product_directory:

java -jar target/pulsar-fast-jms-example-1.0-jar-with-dependencies.jar

Results:

Sending: Hello world! 0

... many status messages...

Sending: Hello world! 1
Sending: Hello world! 2
Received: Hello world! 0
Received: Hello world! 1
Sending: Hello world! 3
Received: Hello world! 2
Sending: Hello world! 4
Received: Hello world! 3
Sending: Hello world! 5
Sending: Hello world! 6
Received: Hello world! 4
Received: Hello world! 5
Sending: Hello world! 7
Received: Hello world! 6
Sending: Hello world! 8
Received: Hello world! 7
Sending: Hello world! 9
Received: Hello world! 8
Received: Hello world! 9
[pulsar-client-io-5-1] INFO org.apache.pulsar.client.impl.ConsumerImpl - [persistent://public/default/example-topic] [jms-queue] Closed consumer
[pulsar-client-io-5-1] INFO org.apache.pulsar.client.impl.ProducerImpl - [persistent://public/default/example-topic] [standalone-0-0] Closed Producer
[main] INFO org.apache.pulsar.client.impl.PulsarClientImpl - Client closing. URL: http://localhost:8080
[pulsar-client-io-5-1] INFO org.apache.pulsar.client.impl.ClientCnx - [id: 0xe43071e3, L:/127.0.0.1:65236 ! R:localhost/127.0.0.1:6650] Disconnected
You’ll find message 0 is produced at the very top of the output. It can get lost in the subsequent messages. Also, note that the messages are consumed asynchronously.

Terminate the Pulsar Docker instance

Once you’re done, you can use Ctrl-C to terminate the Pulsar Docker instance running in your terminal.

To delete the Pulsar Docker container:

  1. Get a list of all Docker containers and note the container ID (5116f0d16eb3 in the example):

    docker ps --all

    Results:

    CONTAINER ID   IMAGE                        COMMAND                  CREATED       STATUS                       PORTS                  NAMES
    5116f0d16eb3   apachepulsar/pulsar:latest   "/pulsar/bin/pulsar …"   2 hours ago   Exited (130) 2 minutes ago                          pulsar-jms-runner
    7ed5fc6c9776   cassandra:latest             "docker-entrypoint.s…"   7 days ago    Exited (143) 7 days ago                             my_cass
  2. Delete the container using the container ID:

    docker rm 5116f0d16eb3

    Results:

    5116f0d16eb3

Next