Rupert Smith wrote:
I think this is heading in the right direction ;)

I'm not sure about the need for a MessageSender (especially not one bound to
a queue!). At this level it would seem quite suitable just to call
methodTransfer.

Also worth noting is the reverse symmetry of the Invoker/Delegate
interfaces. Delegate is the incoming interface for the client, but the
outgoing one for the broker. Might it be possible to use the same interfaces
in both, albeit from opposite perspectives?

I can understand why the Invoker/Delegate include all methods in all
'classes' in the protocol. It makes it easier to write the stub, and
provides version specific implementations that only respond to the methods
relevant to a version.

We can work out what is the best way to present the methods as an API, all
in one big class/interface seems too unweildy. So I think you are doing the
right thing, filtering to expose the methods by 'class'.

One big difference between the outgoing and incoming interfaces, is the way
method arguments are presented.

In ClientSession:
    public void messageBody(byte[] src) throws QpidException

In SessionDelegate:
    public void queueBind(Session session, QueueBind struct) {}

The arguments are exposed directly in the ClientSession one, but as opaque
structs in the incoming one. For the reasons I gave earlier, about the
possibility of wrapping direct buffers, and exposing method structs as
opaque interfaces on top of them, might it be an idea to make the outgoing
interface take strucs as arguments instead?

A quick example, supposing I receive a message as a MessageTransfer struc. I
could send it back out again as a MessageTransfer struc. If the struc is
really a wrapper on a byte buffer, no or minimal decoding/recoding could be
done on the buffer.

This is just an idea, it makes the API somewhat less wieldy, by requiring
the use of a factory to create strucs before calling methods. But more
flexible as the same factory interface can be used, that provides versioned
strucs.

I think we actually have both options right now. The methods on the invoker are essentially just syntactic sugar that provides a convenient means to construct an object, fill it out, and send it on it's way. Each method on the invoker follows this template:

public void <methodName>(<methodArgs>)
{
    invoke(getFactory().newMethodName(<methodArgs>));
}

Where invoke is just an abstract method:

  abstract void invoke(Method method);

If I happened to have an already constructed <MethodName> object that I, e.g. read in off the wire, I could just pass it directly into the invoke(...) method, and we could of course make the generated implementations of each <MethodName> object be smart enough to only decode/reencode on demand.

--Rafael

Reply via email to