Quick example:
public class CommonSessionDelegate extends Delegate<Session>
{
public void sessionAttached(Session session, SessionAttached struct)
{}
public void sessionFlow(Session session, SessionFlow struct) {}
public void sessionFlowOk(Session session, SessionFlowOk struct) {}
public void sessionClose(Session session, SessionClose struct) {}
public void sessionClosed(Session session, SessionClosed struct) {}
public void sessionResume(Session session, SessionResume struct) {}
public void sessionPing(Session session, SessionPing struct) {}
public void sessionPong(Session session, SessionPong struct) {}
public void sessionSuspend(Session session, SessionSuspend struct) {}
public void sessionDetached(Session session, SessionDetached struct)
{}
}
I can't find the Invoker interface, so I'll just guess what it might be
like:
interface Invoker<Session>
{
public Session sessionOpen(SessionOpen struct);
public void sessionFlow(Session session, SessionFlow struct);
public void sessionFlowOk(Session session, SessionFlowOk struct);
public void sessionClose(Session session, SessionClose struct);
public void sessionClosed(Session session, SessionClosed struct);
public void sessionResume(Session session, SessionResume struct);
... and so on.
}
Really not bad as a low-level API. Allows for different 'Session'
implementations for different versions of the protocol. Allows for different
struct formats for different versions of the protocol.
There is also something I like about passing the arguments in structs,
rather than directly as arguments, which is that struct's can completely
hide their implementation. Could be held in Java fields, could just contain
a 'pointer' into a raw direct byte buffer. Keeps the way open for having a
native implementation where direct byte buffers are managed natively.
(Incidently I've been writing a prolog virtual machine in Java and C, I pass
byte code in direct byte buffers from a compiler in Java to the virtual
machine in C and it is a very good way of getting good performance over JNI.
There is also the fairly well known 3d flight simulator, using Java and
native C OpenGL calls, using direct byte buffers, for good performance 3d
rendering from Java)
All thats really needed to make this usable, is default code for the
ping/pong cycle, obeying flow requests, and so on, and some convenience code
to execute the common connection start, secure, tune, open conversation.
Code written against this API to extend or otherwise hook into the delegate,
to be notified of all protocol events, override/handle those that it is
interested in. Something akin to the Interceptor pattern is the first thing
that comes to mind...
Rupert
On 31/07/07, Rupert Smith <[EMAIL PROTECTED]> wrote:
>
> On 31/07/07, Arnaud Simon <[EMAIL PROTECTED]> wrote:
> >
> > Hi,
> >
> > I think that all agree about having a Qpid API. Now we may not agree
> > about the granularity level of such an API. I like to make several
> > points clear so we all speak about the same thing:
> > - We have introduced a common communication layer that will be used by
> > both broker and client implementations. I think that we all agree on
> > that layer.
> > - The aim was to isolate the JMS layer from this communication layer for
> > three main reasons: for shielding the JMS layer form specification
> > changes, for simplifying concurrent development efforts and for
> > achieving a certain level of plugability of our JMS layer.
> > - On the client side this communication layer has been exposed to the
> > JMS layer through what we call a Qpid API. This is the point where we
> > don't agree and the debate is about the granularity of this API.
> >
> > This API is currently a convenient way of isolating those three layers
> > and is NOT fixed. We however need a certain level of stability if we
> > want to eventually deliver a 1.1 client. So, the approach we went for
> > was to define a simple API that we would refine when developing the 1.1
> > client code base.
> >
> > I think that we all agree that this is a good thing to expose a specific
> >
> > QPID API even if THIS API does not have to be exposed as if. Another API
> > can be exposed on top of the communication layer and the current
> > interface can be kept private and only seen as a convenient way of
> > implementing JMS.
> >
> > So, all what I am saying is that we really need this debate and I
> > appreciate very much Rupert and Martin concerns about the current Qpid
> > API. But, this API is not finalized and can be replaced by another one
> > that is closer to the protocol (the current one would therefore be seen
> > as a convenient layer on top of the communication layer).
> >
> > Arnaud
>
>
> I was under the impression that the proposed API was the proposed Qpid API
> to be exposed as our published API. So thanks for explaining that it is of a
> temporary nature.
>
> Points above accepted, but if you are going to change this API, and it is
> what the JMS layer is built on top of, then it follows that the JMS layer
> will have to change, as it changes. So the isolation of the JMS layer from
> change, is negated by the argument that the proposed API is temporary.
>
> One of two things will happen, either what was proposed as a makeshift
> solution will become permanent, or the API and therefore the JMS layer will
> change too. I think that, especially if this API is implemented in all
> languages, the first option is far more likely to be followed; it will be
> too much effort to change it and attrition will set in.
>
> So how about working out what the low-level API will be now? The thing
> about APIs is, you rarely get more than one shot at designing them, and
> designing a really good one is not easy. Lets make damn sure we get it
> right.
>
> On the other hand, if there is an absence of time and will to work out a
> low-level API to expose now. You may as well put the JMS layer right on top
> of the comm layer anyway, seeing as it is only going to have to change.
>
> Right now, I'm looking at the API and thinking that its more of a
> 'nuisance' layer to implement JMS on top of (particularly translating
> exceptions, ugh), than a 'convenience' layer. On the other hand, the comm
> layer is intuitive and looks as though it will stand up to usage accross
> different protocol versions. You pass in frames at the bottom and get method
> calls out the top, or pass in method calls at the top and get frames out the
> bottom. I think I would be very tempted to focus on the Invoker and Delegate
> interfaces, as a good starting point for fleshing out a low-level API.
>
> Also, I think that the requirement to isolate against change is a bit of a
> red herring. The protocol is not evolving so rapidly that we cannot keep up,
> and when the protocol does change, it could be in semantically subtle ways
> that we cannot isolate ourselves from anyway. Best way to isolate against
> change is to use solid bottom up OO design, imho. Then at least you always
> have good code to re-use.
>
> Rupert