Jiri/Rajith/Gordon,
I'm getting *deeply* concerned by this thread.

I've already raised pretty vigorously my views that interoperability should be the default position. It has been some time since I looked but I seem to recall reading that in AMQP "String" is defined as UTF-8 so that IMHO makes things pretty clear that the C++ etc. runtimes should be defaulting strings to UTF-8. i get the C++ "but strings are just byte arrays" thing, but to be fair from an interoperability perspective I tend to take the perspective that property types should be limited to a similar range to JMS. If binary properties have to be supported then that should be the exception case with a specific method call (preferably prefixed with nonInterop or somesuch) used to make it clear to clients that what they are doing could break things.

That said I'm particularly concerned by Rajith's posting "

The getPropertyNames() will not return properties who's values are not
legal as per the JMS spec.
If you have properties with types like list, map or UUID it will not
show up in the list. However you could still retrieve them using
getObjectProperty().
Also if you print the message you will not see them.

If you do a getStringProperty on  a byte[] it will throw an exception.
If you do a getStringProperty on  a list or map it will just return
you the toString()
"
I've got some sympathy with trying to keep to the JMS spec, but whilst there remain general interoperability issues this is a risky strategy (risky for product users) as you could well start to break things.

As I've said in a previous post I've had to work around some things - in my case I'm doing a lot of QMF and most of the "strings" sent by the c++ broker ManagementAgent end up as byte[] values stored in a Map. However more significantly I've also had a couple of Agents including the sample Agent in "/qpid-0.10/cpp/bindings/qmf2/examples/cpp" send properties (e.g. qmf.opcode etc.) as byte[]

I'm pretty worried that you're comment "If you do a getStringProperty on a byte[] it will throw an exception."

What I *actually* do is (within my MessageListener):
String agentName = QmfData.getString(message.getObjectProperty("qmf.agent")); String content = QmfData.getString(message.getObjectProperty("qmf.content")); String opcode = QmfData.getString(message.getObjectProperty("qmf.opcode"));

Where QmfData.getString() includes my defensive type testing code covered in the thread below.

This approach isn't ideal, but at least it works for 0.8 and 0.10 pleeeeeaaaassssseee tell me that you've not "fixed" things such that I can't actually retrieve agent/content/opcode (they are a bit critical for QMF2 as I'm sure you know!!) - notice I'm using getObjectProperty not getStringProperty.

I've not had a chance to test with 0.12 yet as I've been trying hard to complete the Java QMF2 API implementation, but I shall be most upset if this fix to make things JMS pure has shot my code down in flames.

I'm really interested in thoughts on this - and reassurance that you've not broken things for me, or what the new workaround is - I've already had to do some evil casting to Qpid specific types to get and set the content-type.

Regards,
Frase



Jiri Krutil wrote:
Rajith

I think this makes perfect sense from the JMS point of view and it also
works fine if all peers are Java clients.

What I find quite surprising and unfortunate is that if a C++ client sends a
message to a Java client, the string message properties set by the C++
client are not visible by default for the Java client. (They only become
visible if the C++ client sets the property encoding to "utf8".)

IMHO this should work by default, especially if both client libraries are
from the same vendor.
(Not sure if it would be better to make the C++ client use the utf8 encoding
by default, or to change the Java client to map byte[] properties to
Strings.)

Regards
Jiri



On Tue, Sep 20, 2011 at 5:29 PM, Rajith Attapattu <[email protected]>wrote:

On Thu, Sep 15, 2011 at 2:34 PM, Fraser Adams
<[email protected]> wrote:
Hi Jiri
Out of curiosity have you looked at the type of the property. In other
words
if you get the property and do a
myProperty.getClass().getCanonicalName().
I'll bet that it'll come back as a byte array rather than a String. I
believe that if you have control of the C++ client you might be able to
set
the encoding to UTF-8 but if not...

I've seen this loads as I've been implementing a Java implementation of
the
QMF2 API. Frankly it's a pain in the backside. I've resorted to defensive
programming in my class that extracts String properties from headers and
Map
messages as I've had some Agents send Strings and some byte[].
Fraser, this is fixed now from 0.12 release onwards.
See https://issues.apache.org/jira/browse/QPID-2930 for details.

The getPropertyNames() will not return properties who's values are not
legal as per the JMS spec.
If you have properties with types like list, map or UUID it will not
show up in the list. However you could still retrieve them using
getObjectProperty().
Also if you print the message you will not see them.

If you do a getStringProperty on  a byte[] it will throw an exception.
If you do a getStringProperty on  a list or map it will just return
you the toString() which is not useful IMO and for consistency we
should throw an exception just like we do for byte[].
For UUID at least it makes sense, and you will get a toString()
representation of the UUID.

We now allow some AMQP specific properties to be retrieved via the
getStringProperty method using custom property names.
Ex. app-id using "x-amqp-0-10.app-id"
     routing-key using "x-amqp-0-10.routing-key"
     userid using "JMSXUserID"

Regards,

Rajith
  /**
   * There seem to be some inconsistencies where string properties are
sometimes returned as byte[] and
   * sometimes as Strings. It seems to vary depending on the Agent and
getting it wrong results in
   * ClassCastExceptions which is clearly unfortunate.
   *
   * This is basically a helper method to check the type of a property
and
return the most "appropriate"
   * String representation for it.
   *
   * @param p a property in Object form
   * @return the most appropriate String representation of the property
   */
  public static String getString(Object p) {
      if (p == null) {
          return "";
      }
      if (p instanceof String) {
          return (String)p;
      }
      if (p instanceof byte[]) {
          return new String((byte[])p);
      }
      return p.toString();
  }

My personal view is that the C++ client runtime should default to sending
string properties as UTF-8 encoded as this makes the default behaviour
interoperable. There might be a small performance gain from not doing
that,
but in an end to end system of systems I suspect the difference is very
small and worth paying for interoperability. One could always have a flag
to
switch off this behaviour, but I'd prefer Strings to be UTF-8 encoded as
a
default (all IMHO of course).

Hope this helps you out
Frase



Jiri Krutil wrote:
Hi

When sending messages from a C++ client and receiving them in a Java
client,
we are having problems with custom message properties in the message
header.
String message properties set on the C++ sender side are not visible in
the
receiving Java app. Other property types seem to be processed fine.

The C++ client is messaging v0.7, the Java client is 0.10.

Any ideas?

Cheers
Jiri


---------------------------------------------------------------------
Apache Qpid - AMQP Messaging Implementation
Project:      http://qpid.apache.org
Use/Interact: mailto:[email protected]


---------------------------------------------------------------------
Apache Qpid - AMQP Messaging Implementation
Project:      http://qpid.apache.org
Use/Interact: mailto:[email protected]





---------------------------------------------------------------------
Apache Qpid - AMQP Messaging Implementation
Project:      http://qpid.apache.org
Use/Interact: mailto:[email protected]

Reply via email to