The native JMS provider - Writing the WSDL extension
Overview
The WSDL extensions for the Java Message Service (JMS) are identified with the namespace prefix jms. For example, <jms:binding>.
- Operations
The supported operations are either one-way operations (send for JMS point-to-point messaging, or publish for JMS publish and subscribe messaging) or request-response operations (send and receive for JMS point-to-point messaging). The WSDL operations therefore specify either an input message only, or an input and an output message.
- Fault messages
Operations that describe message interfaces with a native JMS binding do not have fault messages. No assumptions are made about the message schema or the semantics of message properties, therefore no distinction can be made between output and fault messages.
- Setting the JMS message body type
You use the <jms:binding> extension to specify the JMS message body type
where messageBodyType is either ObjectMessage or TextMessage.<wsdl:binding ... > <jms:binding type="messageBodyType" /> ... </wsdl:binding>- Specifying the parts to use for the input and output messages
For JMS text messages and JMS object messages created from one or more WSDL message parts, you use the <jms:input> and <jms:output> extensions to specify the message parts to use for the JMS messages:
<wsdl:input ... > <jms:input parts="part1 part2 ..." /> </wsdl:input> <wsdl:output ... > <jms:output parts="part1 part2 ..." /> </wsdl:output>In the next example, the WSDL message has just one part that contains the complete message body. This message body might result from a mapping of some other representation (see Mapping data types).
<wsdl:input ... > <jms:input parts="part1" /> </wsdl:input>If no parts are defined, then all the message parts are used.
- Mapping data types
You use the <format> extensions to map data types:
<wsdl:binding ... > <jms:binding type="..." /> <format:typeMapping encoding="Java" style="Java"> <format:typeMap typeName="..." formatType="targetType"/> </format:typemapping> ... </wsdl:binding>The value of targetType is dependent on the JMS message body type (see Setting the JMS message body type). For JMS object messages, the target data type implements the java.io.Serializable class. For JMS text messages, the target data type is always java.lang.String.
The <format> extensions are also used in other bindings that deal with Java interfaces.
- Setting the JMS headers and properties
JMS does not make assumptions about message headers. For example, if the JMS provider is MQSeries then each JMS message carries an RFH2 header. However one can access data in this message header indirectly, by getting and setting JMS message properties.
When you want your application to pass a property into the Web Services Invocation Framework (WSIF) as a part on the WSIF message, you use a <jms:property> tag. When you want to hard code an actual property value into the WSDL, you use a <jms:propertyValue> tag. The <jms:propertyValue> tag contains a specification of a literal value and its associated XML schema type.
We can specify <jms:property> and <jms:propertyValue> extensions within the <wsdl:input> tag in the binding operation, and also within the <jms:address> tag. For the<wsdl:output> tag in the binding operation, one can only specify the <jms:property> extension. Property values that are set in the <jms:property> tag take precedence over values set in the <<jms:propertyValue> tag, and property values that are set in the binding operation (in the <input> and <output> tags) take precedence over values set in the <jms:address> tag.
Here is an example of the <jms:property> and <jms:propertyValue> tags nested within the <input> and <output> tags:
<wsdl:input ... > <jms:property name="propertyName" part="partName" /> <jms:propertyValue name="propertyName" type="xsdType" value="actualValue" /> </wsdl:input> <wsdl:output ... > <jms:property name="propertyName" part="partName" /> </wsdl:output>where propertyName identifies the JMS property that is associated with the header field, and partName identifies the message part that is associated with the property.
The JMS property identified by propertyName can be user-defined, or it can be one of the following predefined JMS message header fields:
Value Java type JMSMessageId java.lang.String JMSTimeStamp long JMSCorrelationId byte [ ] or java.lang.String JMSReplyTo javax.jms.Destination JMSDestination javax.jms.Destination JMSDeliveryMode int JMSRedelivered boolean JMSType java.lang.String JMSExpiration long JMSTimeToLive long See the JMS specification for restrictions that apply when setting JMS header field values. Attempts to set restricted values are ignored.
For application-defined JMS message properties, the Java types used in the native JMS binding implementation (used for calls to the corresponding JMS methods) are derived from the XML schema type in the abstract interface (<wsdl:part> tag), and from the type mapping information in the format binding (<format:typemap> tag).
- Handling transactions
Independent of other JMS properties, the asynchronous processing of request-response operations has implications for callers running in a transaction scope. The send request part and the receive response part are separated into two transactions, because the send needs to be committed in order for the request message to become visible. Implementations that process WSDL for asynchronous request-response operations (such as WSIF) must therefore take the following additional actions:
- They must ensure that the send request transaction returns a correlation ID to the user, and provides a callback with which users can pass in the response message to process the receive response transaction.
- They might implement their own response message "listener" in order to recognize the arrival of response messages, and to manage the correlation to the request message.
Example
The JMS text message contains a java.lang.String. In this example, the WSDL message contains only one part that represents the whole message body:
<!-- Example 1: JMS Text Message --> <wsdl:definitions ... > <!-- simple or complex types for input and output message --> <wsdl:types> ... </wsdl:types> <wsdl:message name="JmsOperationRequest"> ... </wsdl:message> <wsdl:message name="JmsOperationResponse"> ... </wsdl:message> <wsdl:portType name="JmsPortType"> <wsdl:operation name="JmsOperation"> <wsdl:input name="Request" message="tns:JmsOperationRequest"/> <wsdl:output name="Response" message="tns:JmsOperationResponse"/> </wsdl:operation> </wsdl:portType> <wsdl:binding name="JmsBinding" type="JmsPortType"> <jms:binding type="TextMessage" /> <format:typemapping style="Java" encoding="Java"> <format:typemap name="xsd:String" formatType="String" /> </format:typemapping> <wsdl:operation name="JmsOperation"> <wsdl:input message="JmsOperationRequest"> <jms:input parts="requestMessageBody" /> </wsdl:input> <wsdl:output message="JmsOperationResponse"> <jms:output parts="responseMessageBody" /> </wsdl:output> </wsdl:operation> </wsdl:binding> <wsdl:service name="JmsService"> <wsdl:port name="JmsPort" binding="JmsBinding"> <jms:address destinationStyle="queue" jndiConnectionFactoryName="myQCF" jndiDestinationName="myDestination"/> </wsdl:port> </wsdl:service> </wsdl:definitions>As an extension to the previous JMS message example, the following example WSDL describes a request-response operation in which specific JMS property values of the request and response message are set for the request message and retrieved from the response message.
The JMS properties in the request message are set according to the values in the input message. Likewise, selected JMS properties of the response message are copied to the corresponding values of the output message. The direction of the mapping is determined by the appearance of the <jms:property> tag in the input or output section, respectively.
<!-- Example 2: JMS Message with JMS Properties --> <wsdl:definitions ... > <!-- simple or complex types for input and output message --> <wsdl:types> ... </wsdl:types> <wsdl:message name="JmsOperationRequest"> <wsdl:part name="myInt" type="xsd:int"/> ... </wsdl:message> <wsdl:message name="JmsOperationResponse"> <wsdl:part name="myString" type="xsd:String"/> ... </wsdl:message> <wsdl:portType name="JmsPortType"> <wsdl:operation name="JmsOperation"> <wsdl:input name="Request" message="tns:JmsOperationRequest"/> <wsdl:output name="Response" message="tns:JmsOperationResponse"/> </wsdl:operation> </wsdl:portType> <wsdl:binding name="JmsBinding" type="JmsPortType"> <!-- the JMS message type may be any of the above --> <jms:binding type="..." /> <format:typemapping style="Java" encoding="Java"> <format:typemap name="xsd:int" formatType="int" /> ... </format:typemapping> <wsdl:operation name="JmsOperation"> <wsdl:input message="JmsOperationRequest"> <jms:property message="tns:JmsOperationRequest" parts="myInt" /> <jms:propertyValue name="myLiteralString" type="xsd:string" value="Hello World" /> ... </wsdl:input> <wsdl:output message="JmsOperationResponse"> <jms:property message="tns:JmsOperationResponse" parts="myString" /> ... </wsdl:output> </wsdl:operation> </wsdl:binding> <wsdl:service name="JmsService"> <wsdl:port name="JmsPort" binding="JmsBinding"> <jms:address destinationStyle="queue" jndiConnectionFactoryName="myQCF" jndiDestinationName="myDestination"/> </wsdl:port> </wsdl:service> </wsdl:definitions>
Related Tasks
The JMS providers - Configuring the client and server
See Also
JMS message header: The TimeToLive property reference