Hi, I have tried putting a case forward for three things. 1. Methods as classes, rather than exposed arguments.
Reason: Methods created by factories, allowing multi-version support (although Raphael points out that if the args change significantly then the protocol is changing too much between versions, so has gone for a different solution to the multi-version issue). Allows one implementation of methods as byte buffers, another as java fields, for in-vm transport. Keeps open possibility of native implementation. Allows pass-through processing, where method is never decoded or only partially decoded. Also, it might be possible to do faster serialization/deserialization, using a JVM tweaked at the byte code level. I believe that Terracotta (http://terracottatech.com/) gets up to such tricks. There is also an out-of-date project, http://www.eecs.harvard.edu/~mdw/proj/old/jaguar/, that does this sort of thing too, no idea but maybe the Terracotta folks got some ideas from there. 2. Full mapping of the protocol 1:1 onto the API. I agree that onMessage is the most frequently handled incoming method on the client side, but there is the rest of the protocol to consider too. The API just isn't low-level if it does not expose everything. 3. Use of the inverse symmetry of the API so that the outgoing interface that the client calls, is identical to the incoming interface that the broker routing layer implements. Comm layer can be completely bypassed, and a client can be directly welded onto the broker. I think I should add a fourth to this list: 4. Be language neutral, that is a suitable API for implementing in any of our target languages. Can assume target language is OO? Not sure I'd like to invent an API that equally well maps onto an OO as well as a functional language ;). To these ends, I have been playing around with the Stub that Raphael originally posted to this list. I am slowly getting an API into shape, on my laptop on the way to and from work on the train, but haven't really the time to dedicate to completing it yet. Here is a rough outline: Everything in the API is an interface first, the comm layer implements it. I like interfaces, because you can have multiple implementations. There is also a toy broker that implements some of the interfaces too, allowing direct connection of the client onto an in-vm broker. Every 'class' in the protocol has two interfaces in the API. One for the outgoing calls that the client may make to the broker, one for the calls the broker may make to the client. Every 'method' in the protocol has an interface. All the outgoing 'classes' are pulled together into a single interface, and all the incoming 'classes' are pulled together into a single interface that extends them all. The reason for splitting down on per-'class' basis, is in case someone wants to implement a delegate for just one 'class', rather than having to implement all methods. The were probably also be no-op abstract implementations, that can be extended to write delegates that handle just one 'method' event out of a 'class'. Methods are created by a method factory. Methods can be called in the context of a connection, or a session. The initial connection creation and session creation are performed by calling their 'open' methods. The comm layer implements both the incoming and outgoing 'classes', you have to ask the factory for the flavour you want depending on the context. For example the interface for the client to call the broker is called 'ProtocolBroker' (extends ClassSessionBroker, ClassMessageBroker, etc), and the one for the broker to call the client is 'ProtocolClient'.(extends ClassSessionClient, ClassMessageClient, etc). The factory allows you to register delegates, with the comm layer. When the comm layer receives incoming frames, it delegates the decoded method calls onto the delegate (I think just one delegate for the moment, rather than an interceptor pattern style chain, not sure, will probably have to do some kind of chain eventually, xwork/webwork may provide some inspiration for this). The 'toy' broker I have sketched out, implements ProtocolBroker. It also provides a protocol factory, this factory will throw an exception if you ask it to create a ProtocolClient, but it will give you a ProtocolBroker. So to write a client against the comm layer, ask its ProtocoFactory implementation for a ProtocolBroker. To write a client directly against the broker routing engine, ask its ProtocolFactory implementation for a ProtocolBroker. This is point 3 above, about the inverse symmetry of the interfaces. Some methods in the protocol require a response, but all are asynchronous. For this I am providing a pair of conversation interfaces, with wait for methods. So for example to open and attach a session, I do: ProtocolFactory factory = ... ProtocolBroker invoker = ... ConnectionContext connection = ... ProtoclClient delegate = factory.defaultClientDelegate(); MethodOpenSession = factory.getMethodFactory().createOpenSession(...); Conversation conversation = factory.createConversation(invoker, delegate); SessionContext session = conversation.openSession(connection, openSession); conversation.waitForSessionAttached(); Sorry, for being a bit light on the details. I don't have it in a state I am ready to release yet, also it is stuck on my laptop at the moment, as I can't connect my personal lap-top to the net at work, and my home server is down at the moment due to moving house. I will post it to the list, once it feels right to me. I have very successfully retro-fitted Raphael's stub onto my API, shifting things around a bit, but keeping essentially the same code. I just wanted to post to try and keep my ideas alive, as I think they are worthwhile, and I don't feel that the API at, http://cwiki.apache.org/confluence/display/qpid/Message+API+Design, satisfies any of my three criteria. The generated API for the comm layer does look to me like a good low-level API. One thing I would prefer to see though, is it implementing a set of interfaces. Also, for that set of interfaces not to use generics, primarily for backward support for java 1.4, or for non-parametric-polymorphic language implementation. I do agree with the comment that Raphael made on the meeting last week, that the push API for large messages, is better than a pull one. Simply because it will be more natural to write a pull utility on top of a push API, and a push API makes less assumptions about a threading model. However, the API at: http://cwiki.apache.org/confluence/display/qpid/Message+API+Design, looks very similar to me, to what is already available in JMS as javax.jms.StreamMessage? On 15/08/07, Rajith Attapattu <[EMAIL PROTECTED]> wrote: > > folks, > > I have captured the design notes for the new client API at > http://cwiki.apache.org/confluence/display/qpid/Message+API+Design > > This is to give a heads up on the direction we are talking. > I believe this is extremely close to the ideas we agreed on the dev list. > > Regards, > > Rajith >
