Hi Ted,
That's great - I must admit I was getting a bit paranoid as I've not had any feedback on this.

I think that it is quite a way ahead of the C++ QMF2 stuff, unless things have changed recently the C++ QMF2 stuff didn't seem to follow the QMF2 API at all, though clearly it was using the QMF2 protocol.

I'd tend to agree with yourself and the others that it's a good idea to separate QMF from the Qpid namespace and consider QMF to be a separate and layered capability that adds value to Qpid. That's exactly the case with the Java API implementation, which is really to all intents and purposes just a JMS application.

My one reservation is that if QMF got separated there may be a danger that it could become a bit of a second class citizen, I'd be very keen to avoid that happening. As it happens one of the reasons I started down the path of the Java QMF2 API implementation was because the original Java QMF stuff seemed very broken (and it was mentioned that it was not supported/maintained and up for removal from the code base). Given my experience with the QMF2 stuff I suspect where the original Java QMF stuff is most likely to be broken is in the String handling. I've mentioned in several threads lots of nasty interoperability issues due to C++ binary strings (as opposed to utf8 encoded strings), which get mapped into byte[]. I've put in a lot of defensive coding to cater for this.

Another thing that my implementation added to the QMF2 API was overloaded methods on addConnection() so I can add additional information to the address that gets created e.g.

_console.addConnection(connection, " ; {link: {name:'big-payload-console', x-declare: {arguments: {'qpid.policy_type': ring, 'qpid.max_size': 500000000}}}}");

This adds to the generality of QMF2, the idea here is that the QMF2 Agent and Console simply become a message based service invocation framework, with all of the Agent/Method etc. discovery built in. Using the extended addConnection() I can send large payloads. I can also set explicit names so, for example if I had a service that may take a very long time to process I can actually set it up so responses are delivered down a named persistent queue so in theory my console could go away and come back later to retrieve the asynchronous response.

On a (related) aside I've also written a patch for the broker to support QMF2 query requests for types other than OBJECT see:

https://issues.apache.org/jira/browse/QPID-3696


When I was working on this patch it uncovered a couple of bugs in the QMF2 API that I'm in the process of fixing. In actual fact they relate to a bit of defensive coding that needed to be added where if a schema Map got returned without a _properties or _methods key I got a null pointer exception. In theory this shouldn't happen as they are mandatory properties but I got bitten as I was putting together the broker patch so it's right to add some checks. My actual finished broker patch doesn't cause this problem as I've made sure that I included all of the mandatory properties.

One other issue that I've uncovered is that if I do a getObjects() where there are lots of objects (I think > 100) then the broker actually sends multiple messages with everyone but the last makred with a "partial" header. I only noticed this when I was writing the query patch so I need to add support for this to the QMF2 API. It's actually what I'm working on at the moment so I'll update the Jira when I've added this stuff in.

It would be good if you could have a play with this stuff, I've been working on it most weekends since June so there's quite a lot of it. I think that I've covered most of the obvious gotchas, but clearly with this much code there are bound to be bugs.

Cheers,
Frase



On 04/01/12 13:53, Ted Ross wrote:
Frase,

Sorry for my delayed response to this. I've fallen a little behind on the users list.

Thank you for this contribution. From your description, it looks as though it's a little ahead of the C++ counterpart! A Java implementation of QMF2 is very desirable and valuable so it should find its way into the code base so it can become part of the released software.

I'm going to send an email to dev and users later today to propose that we separate QMF from the Qpid namespace (i.e. consider QMF to be a separate and layered capability that adds value to Qpid) and it looks like your Java implementation should be included as well.

-Ted

On 12/11/2011 10:52 AM, Fraser Adams wrote:
Hello All,
By way of giving something back to the Qpid community I've (finally) got my implementation of the QMF2 API (which for those not already familiar is described here https://cwiki.apache.org/qpid/qmfv2-api-proposal.html) into a form that is hopefully generally usable.

It's taken a bit longer than I'd have liked, but I've spent the time adding some example tools that are based on the API. Hopefully these tools are useful, at the very least they provide a fair illustration of the QMF2 API including such things as method invocation and Query Subscription.

There's quite a lot of if (just short of 100 classes including tests and tools) so I've zipped it up and attached it to a Jira.

https://issues.apache.org/jira/browse/QPID-3675

Note that there are some quirks, especially if you use a version of Qpid < 0.12. Older versions require a patch to allow the app-id property name to be set. The patch is included in the distro and the shell scripts that launch the tests and tools add the patch jar to the front of the class path. I've tested with Qpid 0.8, 0.10 and 0.12.

Note too that some of the features won't work with Qpid 0.8. In particular the QMF2 create and delete methods weren't added until Qpid 0.10 so the add queue/add binding etc. features of QpidConfig won't work with Qpid 0.8, similarly for QpidCtrl.

The code contains a fair amount of comment and JavaDoc so hopefully is should be fairly easy to use.

I certainly can't guarantee it'll be bug free :-D but I've tried reasonably hard to break things, so at the very least it should be robust enough to be usable. ConnectionAudit and QpidQueueStats seem to reconnect and survive broker restarts pretty well.

This is the first release of a QMF2 API Implementation for Java.

Features:

   * Full Implementation of QMF2 Console, Agent and AgentExternal.
   * Supports QMF2 Query Subscriptions on Agent/AgentExternal
     implementations.
   * Emulates QMF2 Query Subscriptions on the Console side for the
     broker ManagementAgent by
     intercepting _data indications and filtering against QmfQuery.
     This is necessary as the
     ManagemetAgent doesn't yet support QMF2 style Query Subscriptions.
   * Console supports Agent discovery via findAgent() method, which can
     support partial matches,
     which is useful because the full Agent name has a UUID
     representing the "instance" so it's hard
     to know the full name.
   * QmfQuery supports regex matching.
   * Supports QMF2 WorkItem Event model and in addition supports an
     alternative QmfEventListener
Event model, which is rather more like the JMS MessageListener model.

Example Tools Provided:

   * ConnectionAudit: Audits connections to one or more Qpid message
     brokers against a whitelist.
   * ConnectionLogger: A QMF2 class used to provide information about
     connections made to a broker.
   * QpidConfig: QpidConfig is a fairly "literal" Java port of the
     python qpid-config tool. Uses pure
     QMF2 for adding/deleting queues, exchanges & bindings this
     provides useful illustration of how
     to do these things using the ManagementAgent method calls.
   * QpidCtrl: A tool to allow QMF2 methods to be invoked from the
     command line.
   * QpidPrintEvents: Collect and print events from one or more Qpid
     message brokers.
   * QpidQueueStats: Collect and print queue statistics. This is a
     rewrite of the Python version and
     illustrates the use of QuerySubscriptions (via the Console side
     emulation)to subscribe to
     objects on the ManagementAgent.
   * QueueFuse: QueueFuse provides protection to message producers from
     consumers who can't consume
     messages fast enough.

A couple of utility classes are provided too:

   * GetOpt: Is an implementation of the Python GetOpt, which makes
     command line parsing a bit less of a pain.
   * ConnectionHelper: Provides support for a variety of different URL
     formats. As it happens the C++ AMQP URL, the Java ConnectionURL
     and the Python tool "BrokerURL" are all slightly different.
     ConnectionHelper tries to support them all as well as a prototype
     for the proposed new AMQP URL
     https://cwiki.apache.org/qpid/url-format-proposal.html. It's
     obviously still possible to create JMS Connections for QMF2 via
     JNDI, but ConnectionHelper makes it a bit easier for command line
     based tools where we may want to connect to lots of different
     broker instances.


I hope that this is useful, I certainly find it useful as I need to do a lot with broker management info.

It'll be really nice if this makes it into an official Qpid release at some point.

Enjoy!!
Best Regards,
Frase


---------------------------------------------------------------------
Apache Qpid - AMQP Messaging Implementation
Project:      http://qpid.apache.org
Use/Interact: mailto:users-subscr...@qpid.apache.org



---------------------------------------------------------------------
Apache Qpid - AMQP Messaging Implementation
Project:      http://qpid.apache.org
Use/Interact: mailto:users-subscr...@qpid.apache.org



---------------------------------------------------------------------
Apache Qpid - AMQP Messaging Implementation
Project:      http://qpid.apache.org
Use/Interact: mailto:users-subscr...@qpid.apache.org

Reply via email to