Author |
Message
|
sfari |
Posted: Wed Oct 24, 2007 7:04 am Post subject: XML in JMSTextMessage or JMSBytesMessage |
|
|
Centurion
Joined: 15 Apr 2003 Posts: 144
|
Hello,
I am using two different WebService Products. Both of them are sending SOAP over MQ in different ways. So they are not interoperable
- One product sends XML data within MQSTR messages (JMSTextMsg) setting the CCSID to the correct value (tests showed UTF- .
- The other sends XML data within a Format less binary message (JMSBytesMsg).
We internally used to send XML over binary messages. Now I think that was not a very good idea, the way with the MQSTR and the correct CCSID looks quite resonable to me. What is the correct or better way?
Gruss
Silvano |
|
Back to top |
|
 |
JLRowe |
Posted: Wed Oct 24, 2007 12:06 pm Post subject: |
|
|
 Yatiri
Joined: 25 May 2002 Posts: 664 Location: South East London
|
Use a TextMessage. JMS will use the MQSTR format and UTF-8 encoding. |
|
Back to top |
|
 |
jefflowrey |
Posted: Wed Oct 24, 2007 12:36 pm Post subject: |
|
|
Grand Poobah
Joined: 16 Oct 2002 Posts: 19981
|
XML is text. _________________ I am *not* the model of the modern major general. |
|
Back to top |
|
 |
sfari |
Posted: Thu Oct 25, 2007 7:32 am Post subject: |
|
|
Centurion
Joined: 15 Apr 2003 Posts: 144
|
Yes I am just recognizing, that it seems to be the right way to use MQSTR.
The reason for using binary was to avoid any kind of unwanted code page translation.
So can you tell me, is it the only correct way to send XML via MQSTR?
Thanks for your answers! |
|
Back to top |
|
 |
Vitor |
Posted: Thu Oct 25, 2007 7:36 am Post subject: |
|
|
 Grand High Poobah
Joined: 11 Nov 2005 Posts: 26093 Location: Texas, USA
|
sfari wrote: |
So can you tell me, is it the only correct way to send XML via MQSTR? |
Unless you have packed data in a CDATA section. Which is not an especially good idea. _________________ Honesty is the best policy.
Insanity is the best defence. |
|
Back to top |
|
 |
Cyrille Le Clerc |
Posted: Mon Nov 05, 2007 2:12 am Post subject: |
|
|
Novice
Joined: 23 May 2007 Posts: 12 Location: France
|
The javax.jms.Message javadoc states that the TextMessage should be used to send XML content :
Quote: |
A TextMessage object's message body contains a java.lang.String object. This message type can be used to transport plain-text messages, and XML messages. |
However, it is a bit paradoxical because a text message is a group of chars ; it does not deal with the encoding. Encoding is involved when you want to convert chars into bytes (e.g. to store/transport text messages in a file, a DB, a MOM message, etc).
On the other side, XML messages hold their encoding (<?xml version="1.0" encoding="UTF-8"?>) and thus should be seen as streams of bytes. We can see this in the java-xml apis. The javax.xml.transform.Result offers a StreamResult but no WriterResult.
So, what should we do with this 'beautiful' theory ?
First, add a javax.jms.XmlMessage to our JMS wishlist and let the implementor deal with encodings
Second, I prefer to use TextMessage even if it is dangerous and I manually keep in sync the "encoding" attribute of the XML message with the CCSID of my message asking everybody (developers & admins) to be very careful about MQ charset conversions that must always be associated with an update of the "encoding" attribute of the xml message.
To force the synchronization of the ccsid with the "encoding" attribute, I use the com.ibm.mq.jms.JMSC.CHARSET_PROPERTY JMS property.
Here is a pattern to keep XML "encoding" attribute and CCSID in sync :
Code: |
javax.xml.transform.Source xmlSource = ...; // the XML Source ; e.g. StreamSource, JaxbSource, etc
String encoding = ...; // e.g. UTF-8, ISO-8859-1, etc
int ccsid = ...; // ccsid associated with encoding ; e.g. 1208, 819, etc
// SERIALIZE XML WITH THE GIVEN ENCODING
Transformer identityTransformer = TransformerFactory.newInstance().newTransformer();
identityTransformer.setOutputProperty(OutputKeys.ENCODING, encoding);
ByteArrayOutputStream out = new ByteArrayOutputStream();
identityTransformer.transform(xmlSource, new StreamResult(out));
String serializedXml = out.toString(encoding);
// CREATE XML MESSAGE WITH ENCODING AND CCSID IN SYNC
Message xmlMessage = session.createTextMessage(serializedXml);
xmlMessage.setStringProperty(JMSC.CHARSET_PROPERTY, String.valueOf(ccsid));
// SEND MESSAGE
MessageProducer messageProducer = session.createProducer(queue);
messageProducer.send(xmlMessage);
|
Detailed sample available here (see testSendXmlMessageIso88591() and testSendXmlMessageUtf8() ):
http://xebia-france.googlecode.com/svn/trunk/messaging/messaging-demo/src/main/java/fr/xebia/jms/mq/WebsphereMqTest.java
Note that we developed an IbmCharsetUtils class to convert ccsid to java charsets.
Hope this help,
Cyrille _________________ Cyrille Le Clerc
cyrille@cyrilleleclerc.com
cleclerc@xebia.fr
http://blog.xebia.fr
Last edited by Cyrille Le Clerc on Sun Nov 11, 2007 9:18 am; edited 1 time in total |
|
Back to top |
|
 |
Cyrille Le Clerc |
Posted: Tue Nov 06, 2007 10:28 am Post subject: JMS Message types used by JMS transports of SOAP libraries |
|
|
Novice
Joined: 23 May 2007 Posts: 12 Location: France
|
Hello,
Here is a short review of the JMS Message types used by leading Java JAXWS (ie SOAP) implementations for their JMS Transport :
* JAXWS-RI (aka JAXWS Reference Implementation) only supports BytesMessage. See com.sun.xml.ws.transport.jms.client.JMSClientTransport
* Apache CXF (merge of XFire and IONA Celtix) can use TextMessage (default type), BytesMessage or ObjectMessage (to transport a serialized bytes array). See org.apache.cxf.transport.jms.JMSTransportBase
* Apache Axis2 can use TextMessage (default type) or BytesMessage. See org.apache.axis2.transport.jms.JMSSender
At the end of the day,
* Every modern Java SOAP implementation support BytesMessage.
* TextMessage is the default for Axis2 and CXF but is not supported by JAXWS-RI.
* JAXWS-RI, the reference implementation, is 'slightly' paradoxical to not support TextMessage when the JMS javadoc talks about TextMessage to handle XML .
* I always have the same wish for JMS 2 : JCP, please add XmlMessage.
Hope this helps even if the panorama doesn't give a clear answer,
Cyrille _________________ Cyrille Le Clerc
cyrille@cyrilleleclerc.com
cleclerc@xebia.fr
http://blog.xebia.fr
Last edited by Cyrille Le Clerc on Sun Nov 11, 2007 9:19 am; edited 1 time in total |
|
Back to top |
|
 |
fjb_saper |
Posted: Tue Nov 06, 2007 3:24 pm Post subject: |
|
|
 Grand High Poobah
Joined: 18 Nov 2003 Posts: 20756 Location: LI,NY
|
I completely understand you.
However you are limiting the message to specific implementations of SOAP/XML that always expect the message to be in UTF-8 and as such it matters little if TextMessage or BytesMessage.
Now look at a cobol implementation where the codeset might be 37 or 500 and need a translation... Which layer is going to make this translation???
For us techies we will reply MQ of Course, provided we got a text message from the sender. We will then know how to transform the message from ccsid 1208 to ccsid 500 and vice / versa...
Enjoy  _________________ MQ & Broker admin |
|
Back to top |
|
 |
Cyrille Le Clerc |
Posted: Wed Nov 07, 2007 10:20 am Post subject: |
|
|
Novice
Joined: 23 May 2007 Posts: 12 Location: France
|
Hello,
I did a small shortcut on my apporach :
My preferred solution to send XML messages over JMS is to drive the XML encoding from the Queue's CCSID : the MQ admins specify specify the CCSID [1] and the java code forces the XML encoding according to this given ccsid (that we discover via (MQQueue) queue).getCCSID()) [2]. And I prefer TextMessage to BytesMessage to be friendly with apps that feel uncomfortable with bytes-to-char translations.
If this solution does not work, I like the idea of having as many "good xml&mq citizens" applications as possible a to use an ESB/EAI approach to adapt the messages for the applications that have xml|mq difficulties. Hopefully, these applications that have difficulties will evolve one day and become good citizens
Does this approach make sense for the translation use case you gave ?
For SOAP, I feel it really worth using an on-the-shelf SOAP library that deals with the marshalling/unmarshalling and encoding stuff and this library would, I guess, prefer UTF-8 that is the default encoding for XML. However, I don't know if there are such kind of soap libraries for cobol like languages. Forgive me, I am mostly a Java guy
In fact, I see more SOAP as a black box protocol rather than plain XML.
I feel the SOAP libraries should deal with transport issues and their underlying encoding. Extending Axis2, CXF or JAXWS-RI to specify the xml encoding seems pretty complex to develop and would be expensive to maintain.
Cyrille
[1] The MQAdmin can specify the ccsid via the QueueManager config, the JMS websphere config, etc.
[2] I use a IbmCharsetUtils.java util class to find the encoding associated with the ccsid.
Code: |
// Sample that gets the CCSID from the MQQueue config and force the xml encoding to fit this ccsid
javax.xml.transform.Source xmlSource = ...; // the XML Source ; e.g. StreamSource, JaxbSource, etc
int ccsid = ((MQQueue) queue).getCCSID(); // e.g. 1208, 819, 307 etc
String encoding = IbmCharsetUtils.getCharsetName(ccsid); // e.g. UTF-8, ISO-8859-1, cs-ebcdic-cp-us, etc
// SERIALIZE XML WITH THE GIVEN ENCODING
Transformer identityTransformer = TransformerFactory.newInstance().newTransformer();
identityTransformer.setOutputProperty(OutputKeys.ENCODING, encoding);
ByteArrayOutputStream out = new ByteArrayOutputStream();
identityTransformer.transform(xmlSource, new StreamResult(out));
String serializedXml = out.toString(encoding);
// CREATE XML MESSAGE WITH ENCODING AND CCSID IN SYNC
Message xmlMessage = session.createTextMessage(serializedXml);
xmlMessage.setStringProperty(JMSC.CHARSET_PROPERTY, String.valueOf(ccsid));
// SEND MESSAGE
MessageProducer messageProducer = session.createProducer(queue);
messageProducer.send(xmlMessage);
|
_________________ Cyrille Le Clerc
cyrille@cyrilleleclerc.com
cleclerc@xebia.fr
http://blog.xebia.fr
Last edited by Cyrille Le Clerc on Sun Nov 11, 2007 9:22 am; edited 1 time in total |
|
Back to top |
|
 |
JLRowe |
Posted: Thu Nov 08, 2007 3:11 am Post subject: |
|
|
 Yatiri
Joined: 25 May 2002 Posts: 664 Location: South East London
|
I have worked with the SonicMQ product in the past, and indeed it has an XMLTextMessage in its api that extends javax.jms.TextMessage. A very sensible extension. |
|
Back to top |
|
 |
Cyrille Le Clerc |
Posted: Thu Nov 08, 2007 10:01 am Post subject: |
|
|
Novice
Joined: 23 May 2007 Posts: 12 Location: France
|
Sonic MQ's XMLMessage is a nice direction to ease XML usage with JMS and Sonic Software should have a chair at the JMS JSR-914's expert group .
However, I regret they still associate XML with text (ie encoded chars) rather than handling pure XML message (i.e. a javax.xml.transform.Source) ; this would let let the JMS implementation decide how to serialize this XML (with possibility to change it by apis) [1].
My wish would be an extension of javax.jms.Message that handle a javax.xml.transform.Source and offer serialization properties similar to the javax.xml.transform.OutputKeys we have on the javax.xml.transform.Transformer
It could look like this XmlMessage.java :
Code: |
/**
* JMS {@link Message} with support for XML {@link Source}.
*/
public interface XmlMessage extends javax.jms.Message {
/**
* Sets the XML {@link Source} containing this message's data.
*
* @throws JMSException
* If the JMS provider fails to set the xml source due to some internal error.
* @exception MessageNotWriteableException
* If the message is in read-only mode.
*/
void setSource(javax.xml.transform.Source xmlSource) throws JMSException;
/**
* Gets the {@link Source} containing this message's data. The default value is
* <code>null</code>.
*
* @return The <code>source</code> containing the message's data
*
* @exception JMSException
* If the JMS provider fails to get the xml source due to some internal error.
*/
javax.xml.transform.Source getSource() throws JMSException;
/**
* Set an output property that will be in effect for the {@link Source} serialization.
*
* Serialization occurs during the {@link MessageProducer#send(Message)} invocation.
*
* Typical usage would be to define an encoding with OutputKeys.ENCODING property.
*
* @see <a href="http://www.w3.org/TR/xslt#output">XSL Transformations (XSLT) Version 1.0</a>
* @see javax.xml.transform.OutputKeys
* @see javax.xml.transform.Transformer#setOutputProperty(String, String)
*/
void setOutputProperty(String name, String value) throws IllegalArgumentException;
/**
* ...
* @see javax.xml.transform.Transformer#getOutputProperties()
*/
Properties getOutputProperties();
/**
* ...
* @see javax.xml.transform.Transformer#getOutputProperty(String)
*/
String getOutputProperty(String name) throws IllegalArgumentException;
/**
* ...
* @see javax.xml.transform.Transformer#setOutputProperties(Properties)
*/
void setOutputProperties(Properties oformat);
}
|
It is just an humble wish and I hope the next JMS specification will do something for us
Cyrille
[1] Sources : Soniq MQ 7.5 Application Programming Guide and Soniq MQ 5.0 javadoc. Unfortunately, I did not find SoniqMQ 7.5 javadoc on the web but 5.0 javadoc seems to be consistent the the programming guide. _________________ Cyrille Le Clerc
cyrille@cyrilleleclerc.com
cleclerc@xebia.fr
http://blog.xebia.fr |
|
Back to top |
|
 |
Cyrille Le Clerc |
Posted: Sun Nov 11, 2007 9:13 am Post subject: Ongoing spec : SOAP over Java Message Service 1.0 RC1 |
|
|
Novice
Joined: 23 May 2007 Posts: 12 Location: France
|
I just found this SOAP over Java Message Service 1.0 RC1 ongoing specification.
This specification has been initiated by BEA, IBM, Sonic and Tibco through an informal note written in Oct 2006 and announced in Jan 2007 on Axis Dev mailing list. Unfortunately, I couldn't find any public activity on this spec since the 01/2007 announcement.
It is interesting to note that this specification only supports JMS BytesMessage to transport SOAP messages.
However, we must remember that plain old XML and SOAP messages do NOT handle binary data in the same way : plain old XML messages use xsd:base64Binary or xsd:hexBinary types to hold the binary data in the XML tree when SOAP use performances optimized mechanisms like SOAP Message Transmission Optimization Mechanism (MTOM).
As a conclusion, we can expect that BytesMessage will be the most widely used JMS message type to transport SOAP messages even if this type is less friendly than TextMessage for programming languages/platforms that handle XML messages as text.
But this does not mean that BytesMessage is the smartest JMS message type for plain old XML documents. IMHO, TextMessage is very compelling to be friendly for programming languages / platforms that have difficulties to handle byte-to-char transformations.
Hope this help,
Cyrille
Extract from SOAP over Java Message Service 1.0 RC1 :
Quote: |
...
2.4 The JMS Message Body
The contents of the JMS Message body MUST be the SOAP payload as a JMS BytesMessage. ... . The encoding will depend on whether the payload is simply a SOAP Envelope or whether there are any attachments, and the JMS "Content-type" header (sec 3.3) will reflect this appropriately.
In the case of a message without any attachments, the JMS Message Body will contain the properly encoded bytes of the XML SOAP message, and nothing else. In this case the Content-type will be "text/xml" (for SOAP 1.1) or "application/soap+xml" (for SOAP 1.2).
In the case that there are attachments, the JMS Message Body will contain a multipart MIME message. The first thing encountered in byte stream MUST be the MIME boundary for the start of the first part - what MIME Part One [RFC 2045] section 2.5 calls a "Body Part". The message will be encoded using SOAP Messages with Attachments [SwA] or XOP [SOAP11-MTOM] [SOAP12-MTOM], in either case with a Content-type of "multipart/related".
...
|
_________________ Cyrille Le Clerc
cyrille@cyrilleleclerc.com
cleclerc@xebia.fr
http://blog.xebia.fr |
|
Back to top |
|
 |
fjb_saper |
Posted: Sun Nov 11, 2007 3:37 pm Post subject: |
|
|
 Grand High Poobah
Joined: 18 Nov 2003 Posts: 20756 Location: LI,NY
|
It makes sense that with the attachments the only possible message is a bytes message as it reduces drastically the size of the message (Otherwise any bytes array would need to be represented by its hex value in chars...)
So the bytes message does make sense. Keep in mind however that it expects the sending and receiving system's soap implementation to have the necessary CCSID converters that you get for free with a Text message.
Enjoy  _________________ MQ & Broker admin |
|
Back to top |
|
 |
zpat |
Posted: Mon Nov 12, 2007 1:42 am Post subject: |
|
|
 Jedi Council
Joined: 19 May 2001 Posts: 5866 Location: UK
|
We send XML as format MQSTR and use BASE64 to encode any binary attachments. This allows messages to be processed by any platform using MQGET with CONVERT. This preserves MQ's platform independence and allows loose coupling of applications. |
|
Back to top |
|
 |
|