views:

87

answers:

2

As the topic depicts, I'm interested in the canonical java way to resend a message if the destination doesn't send an acknowledement message within a specific time frame.

I could come up with a couple of alternatives, but im not sure i like them.

E.g. (pseudo code/describition)

start a new Thread and check some "external condition" if the ACK has arrived. If no ACK has arrived, resend the message and sleep for a specific time. When the ACK arrived kill/stop the "resender-thread"? (java.lang.Thread.stop() is deprecated)

A, to some extent better solution, would be to use the java.util.concurrent ExecutorService for better thread handling.

+2  A: 

If there is a "canonical" way to do reliable messaging in Java, it might be to use a JMS provider. Providing robust message delivery is tricky, sharing many of the same problems as solutions with the support of ACID transactions in a database. You need to be able to do things like atomically send a message and update a database in the same transaction, or make sure your message is sent, even if the power lost in the middle of a transmission, you should definitely consider JMS.

However, if JMS is overkill, I'd just use a ScheduledExecutorService to schedule the "sending" task. Schedule one transmission right away, and then schedule the retries at some fixed rate. When the job is scheduled, a Future is returned. Pass this to the acknowledgment listener. If an acknowledgment is received, cancel the "sender" task.

Future<?> f = scheduler.scheduleAtFixedRate(sender, 0, 20, TimeUnit.MINUTES);
...
/* Somewhere else, when acknowledgment is received... */
f.cancel();

You'll probably want to include a maximum number of tries counter in the "sender" task.

erickson
+1 for mentioning JMS ... I'm assuming the OP is doing some sort of school assignment
kdgregory
+1  A: 

You don't give a lot of details regarding your messaging service, so the following is complete speculation, if I were to implement my own messaging service (which I wouldn't).

The first step is to have a central point for sending messages, associated with a specific message channel -- in JMS, think Queue or Topic. I'd store the original message in a way that it can be easily restored -- say, a Map keyed by the tuple of message ID and receiver. I'd also create a "timeout" object, which holds the expected timeout of the message along with that key, and add the timeout object to a PriorityQueue.

If the message gets acked before timeout, it gets removed from the resend Map. A separate thread reads the timeout queue at regular intervals, and checks for the presence of the messages in the resend map. If the message is still there, it gets sent again and a new timeout object gets created.

Yes, you'd need a new thread to handle the resends. You'd probably also want a separate thread to process ACKs. Which means there will be multi-thread contention on the resend map, so you'll want to pick an appropriate data structure (ie, ConcurrentHashMap).

And then there's all sorts of issues regarding persistence ...

kdgregory
thanks, I was hoping for answers like yours and ericksons
Schildmeijer