0

How can I make a callback after each message is successfully sent to JMS or fails?

val jmsSink = JmsSink.textSink(
    JmsSinkSettings(connectionFactory).withQueue("My_Queue")
)
Source(Stream.from(1))
    .map(_.toString)
    .runWith(jmsSink)

More Specific example

// creating a sourceQueue which is bound to jmsSink
val sourceQueue: SourceQueueWithComplete[String] =
    Source.queue[String](bufferSize, OverflowStrategy.backpressure)
        .to(jmsSink)
        .run()

The client is sending item to sourceQueue:

val result: Future[QueueOfferResult] = sourceQueue offer "my-item"

val result is the result of inserting the item into sourceQueue, it doesn't mean that it is sent to JMS yet. I need to trigger an event when the item has gone through the sink process, and inserted to JMS queue.

Feyyaz
  • 3,147
  • 4
  • 35
  • 50

1 Answers1

1

One approach to invoke a callback (if by "callback" you mean a function that returns Unit) for each successful message is to create a corresponding Source that subscribes to the same JMS queue, and use runForeach:

val jmsSink = JmsSink.textSink(
  JmsSinkSettings(connectionFactory).withQueue("My_Queue")
)

Source(...)
  .map(_.toString)
  .runWith(jmsSink)

val jmsSource = JmsSource(
  JmsSourceSettings(connectionFactory).withQueue("My_Queue")
)

jmsSource.runForeach(println)

The above example prints each message that is published to the queue via the sink.

As for errors, currently your stream will shut down if an exception is thrown. If, for example, in the event of a thrown exception you want to print the exception and resume the stream instead of terminating it, you could attach a supervision strategy to your original Source:

val decider: Supervision.Decider = {
  case e: Exception =>
    println(s"Exception thrown: ${e.getMessage}")
    Supervision.Resume
}

val flow = Flow[String]
  .withAttributes(ActorAttributes.supervisionStrategy(decider))

Source(...)
  .map(_.toString)
  .via(flow)
  .runWith(jmsSink)

val jmsSource = ...
Jeffrey Chung
  • 19,319
  • 8
  • 34
  • 54
  • Thanks for answering @chunjef. `jmsSource.runForeach(println)` would dequeue the item from queue, wouldn't it? I added some details to my question to clarify what exactly I need. – Feyyaz Dec 18 '17 at 15:35