As a follow up to my posting below.

QMF2 is indeed broken by Java changes in Qpid 0.20 and my hunch around somebody messing with how Content-Type amqp/list is encoded and decoded does indeed look to be "the smoking gun".

I added some debug code to my getObjects() and I was hitherto receiving a BytesMessage, which did need some decoding to retrieve the List, but now it is receiving a MapMessage.

I've only started looking, but doing:

MapMessage m = (MapMessage)response;
for (Enumeration e = m.getMapNames() ; e.hasMoreElements() ;)
{
    String key = (String)e.nextElement();
System.out.println("key = " + key);
}

indicates (for the "broker" object) "key = 0"

Which is suggesting that Lists now seem to be encoded in MapMessages with keys that are indices :'( .



To be fair Rajith Attapattu did post on this subject at the end of August:

http://qpid.2158936.n2.nabble.com/JMS-ListMessage-support-tp7581434.html

and perhaps I *should* have taken more notice, however it was a single posting and pretty inconclusive, so I don't thing that it was unreasonable for me to park it in "things to look at once the QMF stuff is released" given where I was trying to focus my spare time.


IMHO this is *exactly* the sort of thing that acts as a "/quod erat demonstrandum/" to Gordon Sim's posting on "mailing lists and fragmented communication", 'cause I'd have got a *whole lot more* animated about the subject if I'd have thought that this stuff was going to actually make it in to a release (see below!!).....

Have I just missed where the release notes communicated this, or is this a change that hasn't been communicated to "users" (aside from Rajith's posting)??



I have to say that IMHO whilst the BytesMessage stuff (and the associated decoding) "wasn't exactly ideal" I think that the way MapMessage has been used here using String keys as indices feels pretty hideous too :-(

There was some talk too in Rajith's post around "Make the list message accessible via the MapMessage and StreamMessage interfaces" I'm not sure if this has been done, but TBH I'm not sure that I like StreamMessage any better!!



At the risk of coming over a bit anally retentive.......Here's what I should have taken the time to respond to http://qpid.2158936.n2.nabble.com/JMS-ListMessage-support-tp7581434.html with:


I don't actually like MapMessage a whole lot more than any of the above. I think that even for exposing amqp/map its use is flawed for (at least) two reasons: 1) MapMessage is frankly a hideous interface that should have been kicked into touch years ago by Sun. The particular axe I've got to grind with it is that there's this thing called java.util.Map which has been around since Java 1.2, so it's spectacularly unhelpful to have a different interface for Maps transported via JMS. Among other things It really bugs me having to use Enumerations and not being able to use foreach.

It's even more irksome becase QMF often comprises Maps of Maps, so the top level Map ends up being a MapMessage and the rest end up being java.util.Map. It's not at all elegant and frankly I ended up writing a "getMap(final Message message)" method that populates a java.util.Map with the messageProperties and Map values so I'd get at least some consistency.

2) Possibly the main reason using MapMessage is flawed though is because the JMS Spec says: "A |MapMessage| object is used to send a set of name-value pairs. The names are |String| objects, and the values are *primitive data types in the Java programming language*", that's right "primitive data types". To be fair it then goes on to include byte[] in the list and it *does* include a getObject() and setObject(), but the JavaDoc explicitly says "This method works only for the objectified primitive object types (|Integer|, |Double|, |Long| ...), |String| objects, and byte arrays. ".


So the bottom line is then that encoding java.util.Map and java.util.List into javax.jms.MapMessage (which are clearly necessary for QMF plus a whole load of other things) *explicitly* breaks the JMS specification (as well as having a really hideous interface).

As for StreamMessage that says:
"A |StreamMessage| object is used to send a stream of primitive types in the Java programming language" and the writeObject() method JavaDoc says "This method works only for the objectified primitive object types (|Integer|, |Double|, |Long| ...), |String| objects, and byte arrays. ". So again explicitly primitive types.


I've said the following a couple of times on the Qpid Users mailing list, but nobody has yet bitten, hopefully this issue might start the discussion again....

IMHO the *only* correct way to expose amqp/map or amqp/list in JMS in a way that doesn't break the JMS specification is to use javax.jms.ObjectMessage.

ObjectMessage says:

"
An |ObjectMessage| object is used to send a message that contains a serializable object in the Java programming language ("Java object"). It inherits from the |Message| interface and adds a body containing a single reference to an object. Only |Serializable| Java objects can be used.

If a collection of Java objects must be sent, one of the |Collection| classes provided since JDK 1.2 can be used.

"
The last paragraph is particularly interesting and is suggesting to me that this is exactly what is being implicitly suggested by Sun/Oracle as the preferred way of passing Collections of various sorts via JMS.


Now to be fair things were perhaps more awkward in older versions of Qpid when the AMQP Content-Type wasn't getting exposed in JMS, but even without being able to use the Content-Type to avoid speculating casting and instanceof it still seems preferable. The Content-Type however can add value and make the whole thing completely consistent and well specified.



Sorry that this has gone on somewhat, and I apologise for not contributing these thoughts when Rajith originally mentioned this (in retrospect it would probably have saved me quite some work).

I hope that I've managed to convince the community that:
a) javax.jms.ObjectMessage is the "one true" JMS specification compliant way of exposing amqp/map and amqp/list b) that there's not a huge gulf between "developers" and "users" and some of the choices can have big impacts particularly where "messing with interfaces" in a not massively well controlled manner is concerned.

Food for thought???

I'll make a start getting the QMF2 stuff working with the Qpid 0.20 changes. Now that I know what I'm up against it's not especially difficult, but Lists are used in a few places so I'll probably spend a bit of time trying to make sure I've covered it all off and trying to ensure I've abstracted sufficiently from the underlying JMS Message type so that it won't be too hard to accommodate ObjectMessage if (when???) things move to that.


And Rajith, if any of the stuff above comes across as me having a go at you it's *really* not my intention. I hope it doesn't come across like that, but emails can come across in ways not intended so I want to make that clear up front! I really should have put all of this stuff in a response to your post, I'm afraid I was just trying to keep focus on my GUI. A flawed decision on my part as it turns out :-D

I'll keep you posted.
Frase


On 26/01/13 11:32, Fraser Adams wrote:
Gripes so far...... I'm afraid it looks like 0.20 has broken QMF on Java.

I've built the main qpid-all.jar and pointed my CLASSPATH at it and unfortunately "fings is well broke, innit?" :-(

It's lower level than the GUI stuff as none of the QMF2 stuff is working and my QpidConfig port reports "No broker QmfConsoleData returned". My initial suspicion is still that somebody has messed around with how AMQP list messages are deserialised in Java, but I'll need to dig around a bit :-(

On a more minor (and I'd assume unrelated) note I see the following on every Java Client I've fired up so far:

log4j:WARN No appenders could be found for logger (org.apache.qpid.jndi.PropertiesFileInitialContextFactory).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.


Odd that it's just that one class

I haven't built the C++ broker/client yet and the Java glitch seems to concur with what Gordon saw last week (it looks like a change between 0.18 and 0.20 as when he used 0.18 jars and pointed at a 0.20 broker things worked fine) so Java looks like the place to go digging.

I'll keep you posted.

Regards,
Frase.


On 23/01/13 15:30, Justin Ross wrote:
The Apache Qpid community is pleased to announce the immediate
availability of Apache Qpid 0.20.

Apache Qpid (http://qpid.apache.org) is a cross-platform enterprise
messaging solution which implements the Advanced Message Queuing
Protocol (AMQP, http://www.amqp.org).  It provides brokers written in
C++ and Java, along with clients for C++, Java JMS, .Net, Python,
Ruby, and Perl.

Qpid 0.20 is available from our website:

      http://qpid.apache.org/download.html

The 0.20 release includes many bug fixes and improvements.  We
recommend that all users upgrade.  A comprehensive list of changes in
the 0.20 release is available here:

      http://qpid.apache.org/release_notes_0.20.html

Thanks to all the users and contributors who have helped to improve
Apache Qpid.

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]



Reply via email to