Interface Producer<T>

All Superinterfaces:
AutoCloseable, Closeable

@Public @Stable public interface Producer<T> extends Closeable
Producer is used to publish messages on a topic.

A single producer instance can be used across multiple threads.

  • Method Details

    • getTopic

      String getTopic()
      Returns:
      the topic which producer is publishing to
    • getProducerName

      String getProducerName()
      Returns:
      the producer name which could have been assigned by the system or specified by the client
    • send

      MessageId send(T message) throws PulsarClientException
      Sends a message.

      This call will be blocking until is successfully acknowledged by the Pulsar broker.

      Use newMessage() to specify more properties than just the value on the message to be sent.

      Parameters:
      message - a message
      Returns:
      the message id assigned to the published message
      Throws:
      PulsarClientException.TimeoutException - if the message was not correctly received by the system within the timeout period
      PulsarClientException.AlreadyClosedException - if the producer was already closed
      PulsarClientException
    • sendAsync

      CompletableFuture<MessageId> sendAsync(T message)
      Send a message asynchronously.

      When the producer queue is full, by default this method will complete the future with an exception PulsarClientException.ProducerQueueIsFullError

      See ProducerBuilder.maxPendingMessages(int) to configure the producer queue size and ProducerBuilder.blockIfQueueFull(boolean) to change the blocking behavior.

      Use newMessage() to specify more properties than just the value on the message to be sent.

      Note: The returned future is completed in the internal network I/O thread. If a callback that takes a long time to complete is registered on the future, it can negatively impact the internal network processing.

      For example, consider the following code snippet:
      
       Producer<byte[]> producer1 = client.newProducer().topic("topic1").create();
       CompletableFuture<MessageId> future = producer.sendAsync("hello".getBytes());
       future.thenAccept(__ -> {
           try {
               Thread.sleep(1000 * 3600L); // Simulates a long-running task (1 hour)
           } catch (InterruptedException ignored) {
           }
       });
       future.get();
       Producer<byte[]> producer2 = client.newProducer().topic("topic2").create();
       

      In this example, the creation of `producer2` could be blocked for 1 hour. This behavior might seem counter-intuitive, but it occurs because the callback registered on the `future` is executed immediately in the single network I/O thread after the `future` is completed. While the callback is running (e.g., sleeping for 1 hour), the I/O thread is unable to process any other network responses from the broker, causing a bottleneck.

      In addition, invoking any synchronous APIs within the callback of an asynchronous operation will lead to a deadlock. For example:

      
       producer.sendAsync("msg-1".getBytes()).thenAccept(__ -> producer.send("msg-2".getBytes()));
       

      In the example above, the synchronous `send` method is called within the callback of the asynchronous `sendAsync` method. This will cause a deadlock because the I/O thread responsible for completing the `sendAsync` operation is blocked waiting for the synchronous `send` method to complete. As a result, "msg-2" will never be sent, and the I/O thread will remain blocked indefinitely. This can have a cascading effect, impacting all producers and consumers created by the same PulsarClient.

      To avoid issues above, you should ensure that callbacks are executed in a separate thread or executor. This can be achieved by using the `xxxAsync` APIs, such as:

      These methods allow you to specify an executor for the callback, ensuring that the network I/O thread remains unblocked. Alternatively, you can ensure that the callback logic is lightweight and completes quickly.

      Parameters:
      message - a byte array with the payload of the message
      Returns:
      a future that can be used to track when the message will have been safely persisted
    • flush

      void flush() throws PulsarClientException
      Flush all the messages buffered in the client and wait until all messages have been successfully persisted.
      Throws:
      PulsarClientException
      Since:
      2.1.0
      See Also:
    • flushAsync

      CompletableFuture<Void> flushAsync()
      Flush all the messages buffered in the client and wait until all messages have been successfully persisted.
      Returns:
      a future that can be used to track when all the messages have been safely persisted.
      Since:
      2.1.0
      See Also:
    • newMessage

      TypedMessageBuilder<T> newMessage()
      Create a new message builder.

      This message builder allows to specify additional properties on the message. For example:

      
       producer.newMessage()
             .key(messageKey)
             .value(myValue)
             .property("user-defined-property", "value")
             .send();
       
      Returns:
      a typed message builder that can be used to construct the message to be sent through this producer
    • newMessage

      <V> TypedMessageBuilder<V> newMessage(Schema<V> schema)
      Create a new message builder with schema, not required same parameterized type with the producer.
      Returns:
      a typed message builder that can be used to construct the message to be sent through this producer
      See Also:
    • newMessage

      TypedMessageBuilder<T> newMessage(Transaction txn)
      Create a new message builder with transaction.

      After the transaction commit, it will be made visible to consumer.

      After the transaction abort, it will never be visible to consumer.

      Returns:
      a typed message builder that can be used to construct the message to be sent through this producer
      Since:
      2.7.0
      See Also:
    • newMessage

      <V> TypedMessageBuilder<V> newMessage(Schema<V> schema, Transaction txn)
      Create a new message builder with transaction and schema, not required same parameterized type with the producer.

      After the transaction commit, it will be made visible to consumer.

      After the transaction abort, it will never be visible to consumer.

      Returns:
      a typed message builder that can be used to construct the message to be sent through this producer
      See Also:
    • getLastSequenceId

      long getLastSequenceId()
      Get the last sequence id that was published by this producer.

      This represent either the automatically assigned or custom sequence id (set on the TypedMessageBuilder) that was published and acknowledged by the broker.

      After recreating a producer with the same producer name, this will return the last message that was published in the previous producer session, or -1 if there no message was ever published.

      Returns:
      the last sequence id published by this producer
    • getStats

      ProducerStats getStats()
      Get statistics for the producer.
      • numMsgsSent : Number of messages sent in the current interval
      • numBytesSent : Number of bytes sent in the current interval
      • numSendFailed : Number of messages failed to send in the current interval
      • numAcksReceived : Number of acks received in the current interval
      • totalMsgsSent : Total number of messages sent
      • totalBytesSent : Total number of bytes sent
      • totalSendFailed : Total number of messages failed to send
      • totalAcksReceived: Total number of acks received
      Returns:
      statistic for the producer or null if ProducerStatsRecorderImpl is disabled.
    • close

      void close() throws PulsarClientException
      Close the producer and releases resources allocated.

      No more writes will be accepted from this producer. Waits until all pending write request are persisted. In case of errors, pending writes will not be retried.

      Specified by:
      close in interface AutoCloseable
      Specified by:
      close in interface Closeable
      Throws:
      PulsarClientException.AlreadyClosedException - if the producer was already closed
      PulsarClientException
    • closeAsync

      CompletableFuture<Void> closeAsync()
      Close the producer and releases resources allocated.

      No more writes will be accepted from this producer. Waits until all pending write request are persisted. In case of errors, pending writes will not be retried.

      Returns:
      a future that can used to track when the producer has been closed
    • isConnected

      boolean isConnected()
      Returns:
      Whether the producer is currently connected to the broker
    • getLastDisconnectedTimestamp

      long getLastDisconnectedTimestamp()
      Returns:
      The last disconnected timestamp of the producer
    • getNumOfPartitions

      int getNumOfPartitions()
      Returns:
      the number of partitions per topic.