I've been thinking about how Sandesha and Axis 2 should interact and how people can code to Axis2 with the idea in mind that they might be reliable later. I've just been asked a couple of times how can the code find out if a message has been delivered.

This is an interesting issue. I used to believe it that RM shouldn't have any impact on the Axis2 client api in normal usage, because I want to be able to turn on or off WSRM without having to change my application code.

But there are some aspects that require some interaction with the application. The first one is knowing how to associate messages with a particular reliable sequence. For example, I may have multiple stubs running in an application server on behalf of multiple clients. I could aggregate all the requests into a single sequence, which will be more efficient in terms of the protocol, and the overhead of managing large numbers of sequences. But if the endpoint is doing ordered delivery, it now may end up holding up messages from one client while messages for another are delivered, which might not be the desired behaviour.

Sandesha uses a simple idea called a SequenceKey. The key is simply a marker that the application code can use to help create the right underlying sequences. If there are multiple stubs or Call objects that use the same SequenceKey, then as long as they are targeted at the same endpoint, Sandesha will aggregate them into the same sequence. On the other hand, if you have two stubs with different SequenceKeys going to the same endpoint, they will each have their own sequence.

I think this is a great model, it is simple and clean and effective. In fact I think it is so good, that we should always code this way - even if we aren't using RM yet. If the SequenceKey Constant was in the base Axis2 ClientAPI, we could code now with this in mind, so when we want RM, just flick the switch. Of course if you don't set a SequenceKey, the Sandesha can have a default behaviour.

The same applies to the idea of a LastMessage. Sandesha lets you mark a message as being the last in a sequence. This is something that generally only the application designer can know, so again I think it would be great to promote the LastMessage constant onto the standard ClientAPI.

The final issue is letting the application know how the RM delivery is getting on. In general we would like to trust that every message is delivered successfully, but things happen. There will be occasions where timeliness is also important. I see two potential approaches for this. The first is to expose via a management interface a view of the whole sequence. So in Java, we could make the sequence manageable via JMX. And if we make the SequenceKey part of that management, then the application could use it to help map from the application logic into the underlying sequence.

However, there is a more fundamental model, which is when I've made a non-blocking call, I want to know whether that made it through. And in fact this is something that is useful even without RM. Take a simple HTTP case: if the call is truly non-blocking, it could execute the initial send on a new thread, and then I will want to know whether there was an HTTP 202 return or some other. I may also want to know other information from a non-blocking call - such as the messageId that was allocated to the outbound message.

So this also seems to be a model we could promote to the base Call API in Axis2 (and elsewhere).

Currently the Axis2 API is
void invokeNonBlocking(op, element, callback)

My suggestion is to add a new return parameter:
MessageTracker invokeNonBlocking(op, element, callback)

The MessageTracker would only track the outgoing message - the callback object tracks the response.

A simple interface might be something like:
public interface MessageTracker {
     public boolean isAcked();
     public String getMessageID();
     public boolean isReliable();
     public boolean isUndeliverable();
}

The isAcked() is fairly clear. If this was a non-reliable interaction, this would just indicate that there was a 202 from the server. In the reliable instance this would indicate the message had been acked.

The isUndeliverable() would indicate that the message will never be delivered. In the case of non-reliable, this would be where there was a fault on the send. In the case of reliable, this would mean the sequence was terminated or closed before this message was acked.

The isReliable() could be used to find out if some reliable messaging standard is in use, to help make sense of the ack state.

And as I point out earlier, this could be useful even for non-reliable requests, because we could make the nonBlocking call not even wait for the request to be sent, and still track whether it succeeded.

Paul

PS This is a slightly modified version of a blog entry http://www.bloglines.com/blog/paulfremantle?id=16

Reply via email to