Chapter 17. Using SOAP over JMS
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.
Publishing and consuming SOAP/JMS services differ from SOAP/HTTP services in the following ways:
- SOAP/JMS service addressed are specified using a special JMS URI
- you must use the Apache CXF specific factory objects to use SOAP/JMS endpoints
JMS URIs
JMS endpoints use a JMS URI as defined in the URI Scheme for JMS 1.0. Example 17.1, “JMS URI syntax” shows the syntax for a JMS URI.
Example 17.1. JMS URI syntax
jms:variant:destination?options
Table 17.1, “JMS URI variants” describes the available variants for the JMS URI.
Variant | Description |
---|---|
jndi | Specifies that the destination is a JNDI name for the target destination. When using this variant, you must provide the configuration for accessing the JNDI provider. |
topic | Specifies that the destination is the name of the topic to be used as the target destination. The string provided is passed into Session.createTopic() to create a representation of the destination. |
queue | Specifies that the destination is the name of the queue to be used as the target destination. The string provided is passed into Session.createQueue() to create a representation of the destination. |
Table 17.2, “JMS properties settable as URI options” shows the URI options.
Property | Default | Description |
---|---|---|
deliveryMode | PERSISTENT | Specifies whether to use JMS PERSISTENT or NON_PERSISTENT message semantics. In the case of PERSISTENT delivery mode, the JMS broker stores messages in persistent storage before acknowledging them; whereas NON_PERSISTENT messages are kept in memory only. |
replyToName |
Explicitly specifies the reply destination to appear in the
JMSReplyTo header. Setting this property is recommended for applications that have request-reply semantics because the JMS provider will assign a temporary reply queue if one is not explicitly set.
The value of this property has an interpretation that depends on the variant specified in the JMS URI:
| |
priority | 4 | Specifies the JMS message priority, which ranges from 0 (lowest) to 9 (highest). |
timeToLive | 0 | Time (in milliseconds) after which the message will be discarded by the JMS provider. 0 represents an infinite lifetime. |
jndiConnectionFactoryName | Specifies the JNDI name of the JMS connection factory. | |
jndiInitialContextFactory | Specifies the fully qualified Java class name of the JNDI provider (which must be of javax.jms.InitialContextFactory type). Equivalent to setting the java.naming.factory.initial Java system property. | |
jndiURL | Specifies the URL that initializes the JNDI provider. Equivalent to setting the java.naming.provider.url Java system property. |
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 17.2, “Publishing a SOAP/JMS service”.
Example 17.2. Publishing a SOAP/JMS service
1String address = "jms:jndi:dynamicQueues/test.cxf.jmstransport.queue3" + "?jndiInitialContextFactory" + "=org.apache.activemq.jndi.ActiveMQInitialContextFactory" + "&jndiConnectionFactoryName=ConnectionFactory" + "&jndiURL=tcp://localhost:61500"; Hello implementor = new HelloImpl(); 2JaxWsServerFactoryBean svrFactory = new JaxWsServerFactoryBean(); svrFactory.setServiceClass(Hello.class); 3svrFactory.setAddress(address); 4svrFactory.setTransportId(JMSSpecConstants.SOAP_JMS_SPECIFICIATION_TRANSPORTID); svrFactory.setServiceBean(implementor); svrFactory.create();
The code in Example 17.2, “Publishing a SOAP/JMS service” does the following:
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 17.3, “Consuming a SOAP/JMS service”.
Example 17.3. Consuming a SOAP/JMS service
// Java public void invoke() throws Exception { 1 String address = "jms:jndi:dynamicQueues/test.cxf.jmstransport.queue3" + "?jndiInitialContextFactory" + "=org.apache.activemq.jndi.ActiveMQInitialContextFactory" + "&jndiConnectionFactoryName=ConnectionFactory&jndiURL=tcp://localhost:61500"; 2 JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean(); 3 factory.setAddress(address); 4 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 17.3, “Consuming a SOAP/JMS service” does the following: