Using JMS Transport
Objectives and Prerequisites
This sample demonstrates the use of JMS transport in WSO2 MB.
Apache Axis2 supports a JMS transport layer in addition to the existing HTTP transport. This allows Web service clients and servers to communicate via JMS queues and topics instead of HTTP connections. Both one-way and synchronous two-way requests are supported.Â
Some of the benefits of using JMS as an alternative to HTTP are as follows:
- Request and response messages are sent by way of reliable messaging.
- One-way requests allow client and server to be more loosely-coupled (the server does not have to be active when the client sends the one-way request).
- One-way requests can be sent to multiple servers simultaneously through the use of topics.
To access a web service on the JMS transport, the corresponding WSDL document should include a JMS binding and a SOAP address which specify a JMS endpoint URL string. A JMS binding is simply a wsdl:binding element which contains a wsdlsoap:binding element whose transport attribute ends in soap/jms, rather than the normal soap/http value. In addition to the JMS binding, a wsdl:port element which references the JMS binding should be included in the wsdl:service element within the WSDL document. This wsdl:port element should contain a wsdlsoap:address element whose location attribute specifies a JMS endpoint URL string.
You also need to decide on the names and types of JMS objects that the application uses. For example, you must decide whether the web service will receive its requests from a queue or a topic, and whether to use a secure destination (queue or topic). Finally, the names for your destination, connection factory, and listener port must be decided. The following list provides an example of the names used for the sample MessageReceiveService web service:
 |  |
---|---|
Queue | MessageReceiveService, JNDI name:Â MessageReceiveService |
QueueConnectionFactory | amqp://admin:admin@clientid/carbon?brokerlist='tcp://localhost:5672' JNDI name:Â QueueConnectionFactory |
Creating a Simple Service
Following java class with its two operations are hosted in Axis2 server as a web service.
/* * Copyright (c) 2005-2010, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. * * WSO2 Inc. licenses this file to you under the Apache License, * Version 2.0 (the "License"); you may not use this file except * in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ Â public class MessageReceiveService { public void receive(String message) { System.out.println("Got the message ==> " + message); } public String echo(String message) { System.out.println("Got the message ==> " + message); return message; } }
The following file is used as the WSDL of the service. Note how JMS bindings are defined. The receive operation is an "in only" operation having only an input message. But, echo is an "in-out" operation with an output message as well as an input message. Â
<?xml version="1.0" encoding="UTF-8"?> <wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:ns1="http://org.apache.axis2/xsd" xmlns:ns="http://transport.sample.org" xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl" xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" targetNamespace="http://transport.sample.org"> <wsdl:types> <xs:schema attributeFormDefault="qualified" elementFormDefault="unqualified" targetNamespace="http://transport.sample.org"> <xs:element name="receive"> <xs:complexType> <xs:sequence> <xs:element minOccurs="0" name="message" nillable="true" type="xs:string"/> </xs:sequence> </xs:complexType> </xs:element> <xs:element name="echo"> <xs:complexType> <xs:sequence> <xs:element minOccurs="0" name="message" nillable="true" type="xs:string"/> </xs:sequence> </xs:complexType> </xs:element> <xs:element name="echoResponse"> <xs:complexType> <xs:sequence> <xs:element minOccurs="0" name="return" nillable="true" type="xs:string"/> </xs:sequence> </xs:complexType> </xs:element> </xs:schema> </wsdl:types> <wsdl:message name="echoRequest"> <wsdl:part name="parameters" element="ns:echo"/> </wsdl:message> <wsdl:message name="echoResponse"> <wsdl:part name="parameters" element="ns:echoResponse"/> </wsdl:message> <wsdl:message name="receiveRequest"> <wsdl:part name="parameters" element="ns:receive"/> </wsdl:message> <wsdl:portType name="MessageReceiveServicePortType"> <wsdl:operation name="echo"> <wsdl:input message="ns:echoRequest" wsaw:Action="urn:echo"/> <wsdl:output message="ns:echoResponse" wsaw:Action="urn:echoResponse"/> </wsdl:operation> <wsdl:operation name="receive"> <wsdl:input message="ns:receiveRequest" wsaw:Action="urn:receive"/> </wsdl:operation> </wsdl:portType> <wsdl:binding name="MessageReceiveServiceSoap11Binding" type="ns:MessageReceiveServicePortType"> <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/> <wsdl:operation name="echo"> <soap:operation soapAction="urn:echo" style="document"/> <wsdl:input> <soap:body use="literal"/> </wsdl:input> <wsdl:output> <soap:body use="literal"/> </wsdl:output> </wsdl:operation> <wsdl:operation name="receive"> <soap:operation soapAction="urn:receive" style="document"/> <wsdl:input> <soap:body use="literal"/> </wsdl:input> </wsdl:operation> </wsdl:binding> <wsdl:binding name="MessageReceiveServiceSoap12Binding" type="ns:MessageReceiveServicePortType"> <soap12:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/> <wsdl:operation name="echo"> <soap12:operation soapAction="urn:echo" style="document"/> <wsdl:input> <soap12:body use="literal"/> </wsdl:input> <wsdl:output> <soap12:body use="literal"/> </wsdl:output> </wsdl:operation> <wsdl:operation name="receive"> <soap12:operation soapAction="urn:receive" style="document"/> <wsdl:input> <soap12:body use="literal"/> </wsdl:input> </wsdl:operation> </wsdl:binding> <wsdl:service name="MessageReceiveService"> <wsdl:port name="MessageReceiveServiceJmsSoap11Endpoint" binding="ns:MessageReceiveServiceSoap11Binding"> <soap:address location="jms:/MessageReceiveService?transport.jms.DestinationType=queue&transport.jms.ContentTypeProperty=Content-Type&java.naming.provider.url=conf/jndi.properties&java.naming.factory.initial=org.wso2.andes.jndi.PropertiesFileInitialContextFactory&transport.jms.ConnectionFactoryType=queue&transport.jms.ConnectionFactoryJNDIName=QueueConnectionFactory"/> </wsdl:port> <wsdl:port name="MessageReceiveServiceJmsSoap12Endpoint" binding="ns:MessageReceiveServiceSoap12Binding"> <soap12:address location="jms:/MessageReceiveService?transport.jms.DestinationType=queue&transport.jms.ContentTypeProperty=Content-Type&java.naming.provider.url=conf/jndi.properties&java.naming.factory.initial=org.wso2.andes.jndi.PropertiesFileInitialContextFactory&transport.jms.ConnectionFactoryType=queue&transport.jms.ConnectionFactoryJNDIName=QueueConnectionFactory"/> </wsdl:port> </wsdl:service> </wsdl:definitions>
Axi2 Configurations
The axis2.xml file, which configures the axis2 server on which the above service is hosted, should be enabled with JMS transport as follows.
<transportReceiver name="jms" class="org.apache.axis2.transport.jms.JMSListener"> <parameter name="default" locked="false"> <parameter name="java.naming.factory.initial" locked="false">org.wso2.andes.jndi.PropertiesFileInitialContextFactory</parameter> <parameter name="java.naming.provider.url" locked="false">conf/jndi.properties</parameter> <parameter name="transport.jms.ConnectionFactoryJNDIName" locked="false">QueueConnectionFactory</parameter> <parameter name="transport.jms.ConnectionFactoryType" locked="false">queue</parameter> </parameter> </transportReceiver>
<transportSender name="jms" class="org.apache.axis2.transport.jms.JMSSender"/>
Message Broker Bindings
The conf/jndi.properties file contains all the JMS bindings (Queue/QueueConnectionFactory) mentioned above.
connectionfactory.QueueConnectionFactory=amqp://admin:admin@clientid/carbon?brokerlist='tcp://localhost:5672' queue.MessageReceiveService=MessageReceiveService
Note that WSO2 Message Broker should be running at localhost port 5672 as per this sample.
Start Axis2 Server
Axis2 server is started with the configurations specified above. It hosts the above MessageReceiveService service.
private AxisServer axisServer; public void start(){ try { ConfigurationContext configurationContext = ConfigurationContextFactory.createConfigurationContextFromFileSystem(null,"conf/axis2.xml"); this.axisServer = new AxisServer(); this.axisServer.setConfigurationContext(configurationContext); this.axisServer.deployService(MessageReceiveService.class.getName()); try { Thread.sleep(2000); } catch (InterruptedException e) { } } catch (AxisFault axisFault) { axisFault.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } }
Send a Message
Once the server is up, using axis2_client.xml as the config file, a ConfigurationContext can be created and a message can be sent to MessageReceiveService service. Note that the "in-only" message is sent first followed by the "in-out" message. Client stub is generated from the above WSDL using WSDL-To-Java tool (when complied using $CARBON_HOME/Samples/jmstransport/build.xml, Apache Ant will be used).
Using WSO2 MB management console, you can see how the MessageReceiveService queue is created. Refer to Managing Queues for more information on browsing queues through the management console.
public void sendMessage(){ try { ConfigurationContext configurationContext = ConfigurationContextFactory.createConfigurationContextFromFileSystem(null, "conf/axis2_client.xml"); MessageReceiveServiceStub stub = new MessageReceiveServiceStub(configurationContext,"http://localhost:8080/axis2/services/MessageReceiveService.MessageReceiveServiceHttpSoap11Endpoint/"); //first send the inonly message stub.receive("Test message to receive "); // inout message String response = stub.echo("Test message to echo"); System.out.println("Response ==> " + response); try { Thread.sleep(10000); } catch (InterruptedException e) { e.printStackTrace(); } } catch (AxisFault axisFault) { axisFault.printStackTrace(); } catch (java.rmi.RemoteException e) { e.printStackTrace(); } }
The complete sample code demonstrating the scenario is as follows:
/* * Copyright (c) 2005-2010, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. * * WSO2 Inc. licenses this file to you under the Apache License, * Version 2.0 (the "License"); you may not use this file except * in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ import org.apache.axis2.AxisFault; import org.apache.axis2.context.ConfigurationContext; import org.apache.axis2.context.ConfigurationContextFactory; import org.apache.axis2.engine.AxisServer; import org.sample.transport.stub.MessageReceiveServiceStub; public class JMSTransportClient { private AxisServer axisServer; public void start(){ try { ConfigurationContext configurationContext = ConfigurationContextFactory.createConfigurationContextFromFileSystem(null,"conf/axis2.xml"); this.axisServer = new AxisServer(); this.axisServer.setConfigurationContext(configurationContext); this.axisServer.deployService(MessageReceiveService.class.getName()); try { Thread.sleep(2000); } catch (InterruptedException e) { } } catch (AxisFault axisFault) { axisFault.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } } public void stop(){ try { this.axisServer.stop(); } catch (AxisFault axisFault) { axisFault.printStackTrace(); } } public void sendMessage(){ try { ConfigurationContext configurationContext = ConfigurationContextFactory.createConfigurationContextFromFileSystem(null, "conf/axis2_client.xml"); MessageReceiveServiceStub stub = new MessageReceiveServiceStub(configurationContext,"http://localhost:8080/axis2/services/MessageReceiveService.MessageReceiveServiceHttpSoap11Endpoint/"); //first send the inonly message stub.receive("Test message to receive "); // inout message String response = stub.echo("Test message to echo"); System.out.println("Response ==> " + response); try { Thread.sleep(10000); } catch (InterruptedException e) { e.printStackTrace(); } } catch (AxisFault axisFault) { axisFault.printStackTrace(); } catch (java.rmi.RemoteException e) { e.printStackTrace(); } } public static void main(String[] args) { JMSTransportClient jmsTransportClient = new JMSTransportClient(); jmsTransportClient.start(); jmsTransportClient.sendMessage(); jmsTransportClient.stop(); } }