Chapter 13. Using SOAP Over JMS
Abstract
Apache CXF implements the W3C standard SOAP/JMS transport. This standard is intended to provide a more robust alternative to SOAP/HTTP services. Apache CXF applications using this transport should be able to interoperate with applications that also implement the SOAP/JMS standard. The transport is configured directly in an endpoint’s WSDL.
NOTE: Support for the JMS 1.0.2 APIs has been removed in CXF 3.0. If you are using RedHat JBoss Fuse 6.2 or higher (includes CXF 3.0), your JMS provider must support the JMS 1.1 APIs.
13.1. Basic configuration
Overview
The SOAP over JMS protocol is defined by the World Wide Web Consortium(W3C) as a way of providing a more reliable transport layer to the customary SOAP/HTTP protocol used by most services. The Apache CXF implementation is fully compliant with the specification and should be compatible with any framework that is also compliant.
This transport uses JNDI to find the JMS destinations. When an operation is invoked, the request is packaged as a SOAP message and sent in the body of a JMS message to the specified destination.
To use the SOAP/JMS transport:
- Specify that the transport type is SOAP/JMS.
- Specify the target destination using a JMS URI.
- Optionally, configure the JNDI connection.
- Optionally, add additional JMS configuration.
Specifying the JMS transport type
You configure a SOAP binding to use the JMS transport when specifying the WSDL binding. You set the soap:binding
element’s transport
attribute to http://www.w3.org/2010/soapjms/
. Example 13.1, “SOAP over JMS binding specification” shows a WSDL binding that uses SOAP/JMS.
Example 13.1. SOAP over JMS binding specification
<wsdl:binding ... > <soap:binding style="document" transport="http://www.w3.org/2010/soapjms/" /> ... </wsdl:binding>
Specifying the target destination
You specify the address of the JMS target destination when specifying the WSDL port for the endpoint. The address specification for a SOAP/JMS endpoint uses the same soap:address
element and attribute as a SOAP/HTTP endpoint. The difference is the address specification. JMS endpoints use a JMS URI as defined in the URI Scheme for JMS 1.0. Example 13.2, “JMS URI syntax” shows the syntax for a JMS URI.
Example 13.2. JMS URI syntax
jms:variant:destination?options
Table 13.1, “JMS URI variants” describes the available variants for the JMS URI.
Variant | Description |
---|---|
jndi | Specifies that the destination name is a JNDI queue name. When using this variant, you must provide the configuration for accessing the JNDI provider. |
jndi-topic | Specifies that the destination name is a JNDI topic name. When using this variant, you must provide the configuration for accessing the JNDI provider. |
queue |
Specifies that the destination is a queue name resolved using JMS. The string provided is passed into |
topic |
Specifies that the destination is a topic name resolved using JMS. The string provided is passed into |
The options portion of a JMS URI are used to configure the transport and are discussed in Section 13.2, “JMS URIs”.
Example 13.3, “SOAP/JMS endpoint address” shows the WSDL port entry for a SOAP/JMS endpoint whose target destination is looked up using JNDI.
Example 13.3. SOAP/JMS endpoint address
<wsdl:port ... > ... <soap:address location="jms:jndi:dynamicQueues/test.cxf.jmstransport.queue" /> </wsdl:port>
Configuring JNDI and the JMS transport
The SOAP/JMS provides several ways to configure the JNDI connection and the JMS transport:
13.2. JMS URIs
Overview
When using SOAP/JMS, a JMS URI is used to specify the endpoint’s target destination. The JMS URI can also be used to configure JMS connection by appending one or more options to the URI. These options are detailed in the IETF standard, URI Scheme for Java Message Service 1.0. They can be used to configure the JNDI system, the reply destination, the delivery mode to use, and other JMS properties.
Syntax
As shown in Example 13.4, “Syntax for JMS URI options”, you can append one or more options to the end of a JMS URI by separating them from the destination’s address with a question mark(?
). Multiple options are separated by an ampersand(&
). Example 13.4, “Syntax for JMS URI options” shows the syntax for using multiple options in a JMS URI.
Example 13.4. Syntax for JMS URI options
jms:variant:jmsAddress?option1=value1&option2=value2&_optionN_=valueN
JMS properties
Table 13.2, “JMS properties settable as URI options” shows the URI options that affect the JMS transport layer.
Property | Default | Description |
---|---|---|
| [Optional] A string value that is prefixed to all correlation IDs that the conduit creates. The selector can use it to listen for replies. | |
|
|
Specifies whether to use JMS |
| [Optional] Specifies the client identifier for the connection. This property is used to associate a connection with a state that the provider maintains on behalf of the client. This enables subsequent subscribers with the same identity to resume the subscription in the state that the preceding subscriber left it. | |
| [Optional] Specifies the name of the subscription. | |
|
| Specifies the JMS message type used by CXF. Valid values are:
|
| [Optional] Specifies the password for creating the connection. Appending this property to the URI is discouraged. | |
|
| Specifies the JMS message priority, which ranges from 0 (lowest) to 9 (highest). |
|
| Specifies the time, in milliseconds, the client will wait for a reply when request/reply exchanges are used. |
|
| [Deprecated in CXF 3.0] Specifies whether the transport should reconnect when exceptions occur. As of 3.0, the transport will always reconnect when an exception occurs. |
|
[Optional] Specifies the reply destination for queue messages. The reply destination appears in the The value of this property is interpreted according to the variant specified in the JMS URI:
| |
|
| Specifies the transaction type. Valid values are:
|
|
|
Specifies the time, in milliseconds, after which the JMS provider will discard the message. A value of |
| [Optional] Specifies the reply destination for topic messages. The value of this property is interpreted according to the variant specified in the JMS URI:
| |
|
| Specifies whether the conduit’s UUID will be used as the prefix for all correlation IDs.
As all conduits are assigned a unique UUID, setting this property to |
| [Optional] Specifies the username to use to create the connection. |
JNDI properties
Table 13.3, “JNDI properties settable as URI options” shows the URI options that can be used to configure JNDI for this endpoint.
Property | Description |
---|---|
| Specifies the JNDI name of the JMS connection factory. |
|
Specifies the fully qualified Java class name of the JNDI provider (which must be of |
|
Specifies the name of the JTA transaction manager that will be searched for in Spring, Blueprint, or JNDI. If a transaction manager is found, JTA transactions will be enabled. See the |
|
Specifies the URL that initializes the JNDI provider. Equivalent to setting the |
Additional JNDI properties
The properties, java.naming.factory.initial
and java.naming.provider.url
, are standard properties, which are required to initialize any JNDI provider. Sometimes, however, a JNDI provider might support custom properties in addition to the standard ones. In this case, you can set an arbitrary JNDI property by setting a URI option of the form jndi-PropertyName
.
For example, if you were using SUN’s LDAP implementation of JNDI, you could set the JNDI property, java.naming.factory.control
, in a JMS URI as shown in Example 13.5, “Setting a JNDI property in a JMS URI”.
Example 13.5. Setting a JNDI property in a JMS URI
jms:queue:FOO.BAR?jndi-java.naming.factory.control=com.sun.jndi.ldap.ResponseControlFactory
Example
If the JMS provider is not already configured, it is possible to provide the requisite JNDI configuration details in the URI using options (see Table 13.3, “JNDI properties settable as URI options”). For example, to configure an endpoint to use the Apache ActiveMQ JMS provider and connect to the queue called test.cxf.jmstransport.queue
, use the URI shown in Example 13.6, “JMS URI that configures a JNDI connection”.
Example 13.6. JMS URI that configures a JNDI connection
jms:jndi:dynamicQueues/test.cxf.jmstransport.queue ?jndiInitialContextFactory=org.apache.activemq.jndi.ActiveMQInitialContextFactory &jndiConnectionFactoryName=ConnectionFactory &jndiURL=tcp://localhost:61616
Publishing a service
The JAX-WS standard publish()
method cannot be used to publish a SOAP/JMS service. Instead, you must use the Apache CXF’s JaxWsServerFactoryBean
class as shown in Example 13.7, “Publishing a SOAP/JMS service”.
Example 13.7. Publishing a SOAP/JMS service
String address = "jms:jndi:dynamicQueues/test.cxf.jmstransport.queue3" + "?jndiInitialContextFactory" + "=org.apache.activemq.jndi.ActiveMQInitialContextFactory" + "&jndiConnectionFactoryName=ConnectionFactory" + "&jndiURL=tcp://localhost:61500"; Hello implementor = new HelloImpl(); JaxWsServerFactoryBean svrFactory = new JaxWsServerFactoryBean(); svrFactory.setServiceClass(Hello.class); svrFactory.setAddress(address); svrFactory.setTransportId(JMSSpecConstants.SOAP_JMS_SPECIFICIATION_TRANSPORTID); svrFactory.setServiceBean(implementor); svrFactory.create();
The code in Example 13.7, “Publishing a SOAP/JMS service” does the following:
Creates the JMS URI representing t he endpoint’s address.
Instantiates a JaxWsServerFactoryBean
to publish the service.
Sets the address
field of the factory bean with the JMS URI of the service.
Specifies that the service created by the factory will use the SOAP/JMS transport.
Consuming a service
The standard JAX-WS APIs cannot be used to consume a SOAP/JMS service. Instead, you must use the Apache CXF’s JaxWsProxyFactoryBean
class as shown in Example 13.8, “Consuming a SOAP/JMS service”.
Example 13.8. Consuming a SOAP/JMS service
// Java public void invoke() throws Exception { String address = "jms:jndi:dynamicQueues/test.cxf.jmstransport.queue3" + "?jndiInitialContextFactory" + "=org.apache.activemq.jndi.ActiveMQInitialContextFactory" + "&jndiConnectionFactoryName=ConnectionFactory&jndiURL=tcp://localhost:61500"; JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean(); factory.setAddress(address); factory.setTransportId(JMSSpecConstants.SOAP_JMS_SPECIFICIATION_TRANSPORTID); factory.setServiceClass(Hello.class); Hello client = (Hello)factory.create(); String reply = client.sayHi(" HI"); System.out.println(reply); }
The code in Example 13.8, “Consuming a SOAP/JMS service” does the following:
Creates the JMS URI representing t he endpoint’s address.
Instantiates a JaxWsProxyFactoryBean
to create the proxy.
Sets the address
field of the factory bean with the JMS URI of the service.
Specifies that the proxy created by the factory will use the SOAP/JMS transport.
13.3. WSDL extensions
Overview
You can specify the basic configuration of the JMS transport by inserting WSDL extension elements into the contract, either at binding scope, service scope, or port scope. The WSDL extensions enable you to specify the properties for bootstrapping a JNDI InitialContext
, which can then be used to look up JMS destinations. You can also set some properties that affect the behavior of the JMS transport layer.
SOAP/JMS namespace
the SOAP/JMS WSDL extensions are defined in the http://www.w3.org/2010/soapjms/
namespace. To use them in your WSDL contracts add the following setting to the wsdl:definitions
element:
<wsdl:definitions ... xmlns:soapjms="http://www.w3.org/2010/soapjms/" ... >
WSDL extension elements
Table 13.4, “SOAP/JMS WSDL extension elements” shows all of the WSDL extension elements you can use to configure the JMS transport.
Element | Default | Description |
---|---|---|
|
Specifies the fully qualified Java class name of the JNDI provider. Equivalent to setting the | |
|
Specifies the URL that initializes the JNDI provider. Equivalent to setting the | |
|
Specifies an additional property for creating the JNDI | |
| Specifies the JNDI name of the JMS connection factory. | |
|
|
Specifies whether to use JMS |
|
[Optional] Specifies the reply destination for queue messages. The reply destination appears in the The value of this property is interpreted according to the variant specified in the JMS URI:
| |
|
| Specifies the JMS message priority, which ranges from 0 (lowest) to 9 (highest). |
|
|
Time, in milliseconds, after which the JMS provider will discard the message. A value of |
Configuration scopes
The WSDL elements placement in the WSDL contract effect the scope of the configuration changes on the endpoints defined in the contract. The SOAP/JMS WSDL elements can be placed as children of either the wsdl:binding
element, the wsdl:service
element, or the wsdl:port
element. The parent of the SOAP/JMS elements determine which of the following scopes the configuration is placed into.
- Binding scope
-
You can configure the JMS transport at the binding scope by placing extension elements inside the
wsdl:binding
element. Elements in this scope define the default configuration for all endpoints that use this binding. Any settings in the binding scope can be overridden at the service scope or the port scope. - Service scope
-
You can configure the JMS transport at the service scope by placing extension elements inside a
wsdl:service
element. Elements in this scope define the default configuration for all endpoints in this service. Any settings in the service scope can be overridden at the port scope. - Port scope
-
You can configure the JMS transport at the port scope by placing extension elements inside a
wsdl:port
element. Elements in the port scope define the configuration for this port. They override the defaults of the same extension elements defined at the service scope or at the binding scope.
Example
Example 13.9, “WSDL contract with SOAP/JMS configuration” shows a WSDL contract for a SOAP/JMS service. It configures the JNDI layer in the binding scope, the message delivery details in the service scope, and the reply destination in the port scope.
Example 13.9. WSDL contract with SOAP/JMS configuration
<wsdl:definitions ... xmlns:soapjms="http://www.w3.org/2010/soapjms/" ... > ... <wsdl:binding name="JMSGreeterPortBinding" type="tns:JMSGreeterPortType"> ... <soapjms:jndiInitialContextFactory> org.apache.activemq.jndi.ActiveMQInitialContextFactory </soapjms:jndiInitialContextFactory> <soapjms:jndiURL>tcp://localhost:61616</soapjms:jndiURL> <soapjms:jndiConnectionFactoryName> ConnectionFactory </soapjms:jndiConnectionFactoryName> ... </wsdl:binding> ... <wsdl:service name="JMSGreeterService"> ... <soapjms:deliveryMode>NON_PERSISTENT</soapjms:deliveryMode> <soapjms:timeToLive>60000</soapjms:timeToLive> ... <wsdl:port binding="tns:JMSGreeterPortBinding" name="GreeterPort"> <soap:address location="jms:jndi:dynamicQueues/test.cxf.jmstransport.queue" /> <soapjms:replyToName> dynamicQueues/greeterReply.queue </soapjms:replyToName> ... </wsdl:port> ... </wsdl:service> ... </wsdl:definitions>
The WSDL in Example 13.9, “WSDL contract with SOAP/JMS configuration” does the following:
Declares the namespace for the SOAP/JMS extensions.
Configures the JNDI connections in the binding scope.
Sets the JMS delivery style to non-persistent and each message to live for one minute.
Specifies the target destination.
Configures the JMS transport so that reply messages are delivered on the greeterReply.queue
queue.