Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Review

Java Message Service (JMS) is wide spread and popular messaging java interfaceAPI. As far as JMS is standardized in JEE, the same application code can successfully work with different JMS implementations: WS MQ, Active MQ, Tibco, Joram, BEA WebLogic, OpenJMS.
CXF provides a transport that enables endpoints to use JMS queues and topics.

...

Implementing CXF client and service using JMS transport is trivial.
Basically, it is enough to configure two things in WSDL:
a) specify jms transport URI in binding element;
b) define jms address in port element.

WSDL binding and port should look like:

Code Block
borderStylesolid
<wsdl:binding name="Greeter_SOAPBinding" type="tns:Greeter">
        <soap:binding style="document" transport="http://cxf.apache.org/transports/jms"/>
…
</wsdl:binding>

<wsdl:service name="JMSGreeterService">
        <wsdl:port binding="tns:JMSGreeterPortBinding" name="GreeterPort">
            <jms:address
                destinationStyle="queue"
                jndiConnectionFactoryName="ConnectionFactory" 
jndiDestinationName="dynamicQueues/test.cxf.jmstransport.queue">
               <jms:JMSNamingProperty name="java.naming.factory.initial" value="org.apache.activemq.jndi.ActiveMQInitialContextFactory"/>
                  <jms:JMSNamingProperty name="java.naming.provider.url" value="tcp://localhost:61616"/>
           </jms:address>
        </wsdl:port>
 </wsdl:service>

CXF client clients and server servers implemented in java or using Spring configuration magically work for this WSDL (under the hood CXF selects correct JMS Conduit and Destination based on address URL).
Details are described in http://cxf.apache.org/docs/jms-transport.html.
CXF also delivers jms_pubsub and jms_pubsub examples illustrating using JMS transport with default settings for ActiveMQ.

...

Unfortunately there are two main scalability drawbacks in when using default JMS configuration:

...

Both aspects are critical for enterprise application applications and their implementation is not an easy task. Is there any solution? Yes: Spring JMS functionality and CXF Features. Let discuss them in detail.

...

CachingConnectionFactory provides sessions poolsession pooling, consumers and producers cache. Bellow is a sample configuration of CachingConnectionFactory:

...

As you can see it is possible to set the size of the session pool and switch on producers and consumers caching.

...

It is possible to define initial and maximal number of concurrent message consumer threads, cache level (3- cache consumers, 2 – cache session, 1 – no caching), specify message listener class (implementing MessageListener interface) and connection factory.
You can see that Spring provides solution for both mentioned scalability aspects. But how we can use it in CXF?

CXF Features

As far as the CXF JMS implementation is Spring based, based the Spring JMS classes the user can benefit from described Spring JMS functionality.
CXF provides a possibility allows to configure different Spring aspects in details of the JMS transport using Featuresthe JmsConfigFeature. A Feature is something that is able to customize a Server, Client, or Bus, typically adding capabilities. In our case we will add Feature a feature in wsjaxws:endpoint and wsjaxws:client to tune the JMS transport.

Server configuration

Code Block
borderStylesolid
<bean id="cachingConnectionFactory" class="org.springframework.jms.connection.CachingConnectionFactory">
	<property name="targetConnectionFactory">
		<bean class="org.apache.activemq.ActiveMQConnectionFactory">
			<property name="brokerURL" value="tcp://localhost:61616" />
		</bean>
	</property>
	<property name="sessionCacheSize" value="20"/>
	<property name="cacheConsumers" value="true"/>
</bean>

<bean id="jmsConfig" class="org.apache.cxf.transport.jms.JMSConfiguration"
		p:connectionFactory-ref="cachingConnectionFactory"
		p:cacheLevel="3" 
		p:concurrentConsumers="16"
		p:maxConcurrentConsumers="16"
		p:targetDestination="Q_HSC"
		p:wrapInSingleConnectionFactory="false"
	/>

<jaxws:endpoint id=" JMSGreeterService" address="jms://"
		implementor="#JMSGreeterServiceImpl">
		<jaxws:features>
			<bean class="org.apache.cxf.transport.jms.JMSConfigFeature">
				<p:jmsConfig-ref="jmsConfig">
			</bean>
		</jaxws:features>
</jaxws:endpoint>

You can see that the endpoint configuration containing contains the JMSConfigFeature feature that has a JMSConfiguration property.
JMSConfiguration supports all settings that we have seen in Spring DefaultMessageListenerContainer: cached connection factory with session pool size, number of concurrent consumers, cache level. All settings of JMSConfiguration are described in details in http://cxf.apache.org/docs/using-the-jmsconfigfeature.html.
Using this configuration the server application can be tuned to achieve optimal performance in our target environment.

Client configuration

...

It is possible to achieve scalability of a CXF client and service using Spring JMS functionality and the CXF JMS Configuration Feature.
It is not necessary to write any line of code, just configure and leverage already existing stuff.
Performance numbers regarding JMS transport are represented in Christian Schneider's article: http://www.liquid-reality.de/pages/viewpage.action?pageId=5865562

...