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
- [Axis2] Implications of WSRM interfaces on Axis2 Clien... Paul Fremantle
- RE: [Axis2] Implications of WSRM interfaces on Ax... Glen Daniels
- Re: [Axis2] Implications of WSRM interfaces o... Eran Chinthaka
- Re: [Axis2] Implications of WSRM interfac... Paul Fremantle
- Re: [Axis2] Implications of WSRM inte... Paul Fremantle
- Re: [Axis2] Implications of WSRM interfac... Srinath Perera
- Re: [Axis2] Implications of WSRM interfac... Chamikara Jayalath
- Re: [Axis2] Implications of WSRM inte... Davanum Srinivas
- Re: [Axis2] Implications of WSRM... Sanjiva Weerawarana
- Re: [Axis2] Implications of ... Srinath Perera
- Re: [Axis2] Implications... Jaliya Ekanayake
