Developing SOAP over JMS Web-Services using TIBCO BusinessWorks and Designer

Version of Designer: 5.5.2.2

Version of TIBCO EMS: 4.4.3

Some time ago I did a post about developing web-services using TIBCO BusinessWorks. In this post I would like to discuss how to develop a web-service which uses JMS as the SOAP transport instead of HTTP. The problem with developing a web-service bound to a JMS Queue instead of an HTTP transport, is that it can be used only in a homogeneous TIBCO environment.  In other words we need to have TIBCO at both (client and server) ends if we are using a web-service bound to a JMS Queue.

This is so because the WSDL representation of the binding is proprietary to TIBCO (more on this later) as there is no agreed standard for binding SOAP to JMS. Although when I was digging around I did find a ‘working draft’ at W3.org for SOAP over JMS  (http://www.w3.org/TR/soapjms/) so something is being done to plug this gap!

Why all this hassle for SOAP over JMS you ask? Why not stick with good old SOAP over HTTP? Well simply because JMS transport is whole lot more robust and can be scaled up easily without affecting QoS etc.

Introducing the Example

The web-service we are going to create in this example is a relatively simple one. It will take in two integers and return their sum. A fairly simple example but this post is about using SOAP over JMS so that is what we will concentrate on.

The schema for the request and response messages is given below:

<?xml version="1.0" encoding="UTF-8"?>

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
	 xmlns="http://www.tibco.com/schemas/WebServiceTest/Schema/Schema.xsd"
	 targetNamespace="http://www.tibco.com/schemas/WebServiceTest/Schema/Schema.xsd"
	 elementFormDefault="qualified"
	 attributeFormDefault="unqualified">
	<xs:element name="add">                   <!-- Request - two integers a and b to be added -->
		<xs:complexType>
			<xs:sequence>
				<xs:element name="a" type="xs:int"/>
				<xs:element name="b" type="xs:int"/>
			</xs:sequence>
		</xs:complexType>
	</xs:element>
	<xs:element name="result" type="xs:int"/>  <!-- Response - the sum of a and b -->
</xs:schema>
Now the next thing we need to do is to setup the Service Resource. I won't go into the details of how it is done as I have already covered most of the steps in a different post

The reason I don’t need to go into details is because web-services are designed to decouple the operation from the ways of accessing that operation (i.e. the binding). Obviously as binding = message format + transport AND each operation can have different bindings, the only thing that will be different when setting up the Service Resource will be the Binding Section. Furthermore as we are still using SOAP as the message format the only difference that you will see in the Service Resource, as compared to SOAP over HTTP configuration, will be in the Transport sub-tab (see image below).

 

Service Resource SOAP over JMS



In the Transport sub-tab, if instead of selecting a HTTP connection, a JMS connection is selected in the Transport box (see image above), then you will get options to setup the JMS transport.

Setting up the JMS Transport

Setting up the Transport in case of JMS is bit more involved than HTTP. For the sake of clarity we will use Queues for our web-service instead of Topics. There are four main things to setup once you have selected a JMS connection in the Transport box. These settings are similar to those in the JMS activities such as JMS Queue Sender.

1) JMS Destination – the queue or topic which will contain the JMS message carrying the SOAP as payload.

2) JMS Destination Type – Queue or Topic (depending on what kind of interaction is required).

3) JMS Message Type – Text or Bytes message – we go for Text in the example so that we can examine the SOAP message being sent over the EMS.

4) Acknowledgement Mode – Auto for the example otherwise all the standard and TIBCO EMS specific options are available for selection.

If you select ‘Topic’ as the JMS Destination Type then you can also decide which of the Operations have a ‘durable subscription’.

That is the only difference in changing from SOAP over HTTP to SOAP over JMS as far as the Service Resource is concerned.

Looking at the WSDL

Once everything is setup navigate to the WSDL Source tab in the Service Resource configuration to look at the WSDL which has been generated for the web-service.

<?xml version="1.0" encoding="UTF-8"?>
<!--Created by TIBCO WSDL-->
<wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:tns="http://xmlns.example.com/1301947961037" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:jms="http://www.tibco.com/namespaces/ws/2004/soap/binding/JMS" xmlns:jndi="http://www.tibco.com/namespaces/ws/2004/soap/apis/jndi" xmlns:ns0="http://www.tibco.com/schemas/WebServiceTest/Schema/Schema.xsd" name="Untitled" targetNamespace="http://xmlns.example.com/1301947961037">
    <wsdl:types>
        <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns="http://www.tibco.com/schemas/WebServiceTest/Schema/Schema.xsd" targetNamespace="http://www.tibco.com/schemas/WebServiceTest/Schema/Schema.xsd" elementFormDefault="qualified" attributeFormDefault="unqualified">
            <xs:element name="add">
                <xs:complexType>
                    <xs:sequence>
                        <xs:element name="a" type="xs:int"/>
                        <xs:element name="b" type="xs:int"/>
                    </xs:sequence>
                </xs:complexType>
            </xs:element>
            <xs:element name="result" type="xs:int"/>
        </xs:schema>
    </wsdl:types>
    <wsdl:service name="JMSAddService">
        <wsdl:port name="AddPortEndpoint1" binding="tns:AddPortEndpoint1Binding">
            <soap:address location=""/>
            <jndi:context>
                <jndi:property name="java.naming.provider.url" type="java.lang.String">tibjmsnaming://localhost:7222</jndi:property>
                <jndi:property name="java.naming.factory.initial" type="java.lang.String">com.tibco.tibjms.naming.TibjmsInitialContextFactory</jndi:property>
            </jndi:context>
            <jms:connectionFactory>QueueConnectionFactory</jms:connectionFactory>
            <jms:targetAddress destination="queue">inQueue</jms:targetAddress>
        </wsdl:port>
    </wsdl:service>
    <wsdl:portType name="AddPort">
        <wsdl:operation name="AddOperation">
            <wsdl:input message="tns:InMessage"/>
            <wsdl:output message="tns:OutMessage"/>
        </wsdl:operation>
    </wsdl:portType>
    <wsdl:binding name="AddPortEndpoint1Binding" type="tns:AddPort">
        <soap:binding style="document" transport="http://www.tibco.com/namespaces/ws/2004/soap/binding/JMS"/>
        <jms:binding messageFormat="Text"/>
        <wsdl:operation name="AddOperation">
            <soap:operation style="document" soapAction="/Connections/JMSAddService.serviceagent/AddPortEndpoint2/AddOperation" soapActionRequired="true"/>
            <wsdl:input>
                <soap:body use="literal" parts="part1"/>
            </wsdl:input>
            <wsdl:output>
                <soap:body use="literal" parts="part1"/>
            </wsdl:output>
        </wsdl:operation>
    </wsdl:binding>
    <wsdl:message name="InMessage">
        <wsdl:part name="part1" element="ns0:add"/>
    </wsdl:message>
    <wsdl:message name="OutMessage">
        <wsdl:part name="part1" element="ns0:result"/>
    </wsdl:message>
</wsdl:definitions>

Let get back to the issue of lack of standards for SOAP over JMS and why we need TIBCO at both ends.

For that we need to focus down into the Binding and Service elements of the WSDL.

Looking at the Service element (see below), where the method of connecting to the web-service is defined. We find that it contains information about the EMS server (from the Connection resource we set in the Transport box) as well as the queue name we set in the Transport sub-tab.

  <wsdl:service name="JMSAddService">
        <wsdl:port name="AddPortEndpoint1" binding="tns:AddPortEndpoint1Binding">
            <soap:address location=""/>
            <jndi:context>
                <jndi:property name="java.naming.provider.url" type="java.lang.String">tibjmsnaming://localhost:7222</jndi:property>
                <jndi:property name="java.naming.factory.initial" type="java.lang.String">com.tibco.tibjms.naming.TibjmsInitialContextFactory</jndi:property>
            </jndi:context>
            <jms:connectionFactory>QueueConnectionFactory</jms:connectionFactory>
            <jms:targetAddress destination="queue">inQueue</jms:targetAddress>
        </wsdl:port>
    </wsdl:service>
We also find two strange new namespaces being used - jms and jndi. Let us see what these namespace prefixes stand for. Scroll right up to the top of the WSDL and you will see the following entries:
xmlns:jms="http://www.tibco.com/namespaces/ws/2004/soap/binding/JMS" 
xmlns:jndi="http://www.tibco.com/namespaces/ws/2004/soap/apis/jndi" 
These two namespaces have been defined by TIBCO so they are internal and are not 'standardized' as are other namespaces in the WSDL such as xs ( xmlns:xs="http://www.w3.org/2001/XMLSchema") for the schema in Types  or soap (xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap12/") for SOAP related properties in Binding.
Thus if you are a non-TIBCO client you will have no idea what jms:targetAddress element means in the WSDL. 
Once there is a standard for SOAP over JMS then instead of TIBCO specific namespaces we will see a prefix like soapjms with the definition xmlns:soapjms = "http://www.w3.org/2010/soapjms/" [1] .
Next we look at the Binding element (see below). Here also we find the TIBCO specific JMS namespace as well as SOAP over JMS transport definition (in bold).

<wsdl:binding name="AddPortEndpoint1Binding" type="tns:AddPort">
        <soap:binding style="document" transport="http://www.tibco.com/namespaces/ws/2004/soap/binding/JMS"/>
    <jms:binding messageFormat="Text"/>
        <wsdl:operation name="AddOperation">
            <soap:operation style="document" soapAction="/Connections/JMSAddService.serviceagent/AddPortEndpoint2/AddOperation" soapActionRequired="true"/>
            <wsdl:input>
                <soap:body use="literal" parts="part1"/>
            </wsdl:input>
            <wsdl:output>
                <soap:body use="literal" parts="part1"/>
            </wsdl:output>
        </wsdl:operation>
    </wsdl:binding>

Again once we have a standardized way of binding SOAP to JMS then instead of the TIBCO specific listing in transport attribute we will have something like http://www.w3.org/2010/soapjms/&#8221;[1].

If we compare the Service and Binding elements above to those in the same web-service but using HTTP instead of JMS we that all namespaces being used to define the connection and binding properties are standardized. That is what makes SOAP over HTTP web-services independent of vendors and implementation languages.

Next we test the web-service. Make sure you save the WSDL Source (i.e. the concrete WSDL) so that our test client can use it.

Testing

To test the web-service we will create a client using BusinessWorks. We will use a SOAP Request Reply activity to test the web-service. The images below show how to configure the activity to access the web-service.

SOAP Request Reply JMS Config Main Pane

In the configuration simply select the namespace from the concrete WSDL file we saved for the client. As we are using TIBCO to create the client once you set the WSDL everything will be auto-populated. Go to the Transport Details tab (see below) and there you will see the JNDI and JMS sub-tabs which have also been auto-populated from the WSDL. This is so because TIBCO understands the jms and jndi namespaces and knows what to do with the information in the WSDL.

JNDI Sub-tab:

JNDI Sub-tab in Transport Details

 

JMS Sub-tab:
JMS Sub-tab in Transport Details

After loading the WSDL and saving the changes the SOAP Request Reply activity will ask you for an input (the two integers to be added).

Test JMS Input

Save everything and load the relevant processes. On starting the test you should see the Request being fired. If you monitor the relevant queue you will see a message being posted on the queue. The message will be consumed by the web-service and it will return the result back to the queue which in turn will be consumed by the client and you will see the output in the process. As we provided ‘3’ and ‘4’ as the two integers to be added in the input (see image above) the result we get is ‘7’ (see below).

 

<?xml version = "1.0" encoding = "UTF-8"?>
<outputMessage>
	<ns0:result xmlns:SOAP-ENV = "http://www.w3.org/2003/05/soap-envelope" xmlns:ns0 = "http://www.tibco.com/schemas/WebServiceTest/Schema/Schema.xsd">7</ns0:result>
</outputMessage>
If you want to take a look at the actual messages being sent in the JMS Message you can always stop the server before sending the request or after sending the request stop the client. The request or response message will remain in the queue and you can view the content (as we are using JMS Message Type of Text) by browsing the queue.
That is the end of the tutorial. Let me know if I have made any mistakes or if you have any suggestions.
Thank you for reading!



	

How to: Quickly Edit Global Variables in TIBCO BW Designer

Version of Designer used: 5.5.2.2

Global Variables (GVs) are one of the most important bits of any BusinessWorks project. Every project will have at least one set of GVs, usually to store certain settings centrally. GVs also allow those settings to be changed on a running application without having to re-archive and re-deploy it.

A common usage scenario (which I will be using as an example as well) for GVs is to store connection settings for the EMS server. Basic set of connection settings for say a JMS Connection resource would be the Username and Password information and the JNDI information.

As it is very important to structure the GVs properly for easy reference and maintainability you should make good use of Groups. A common way of structuring GVs is to use the location path as a group.

For example if your JMS Connection resource is in /MyProject/Connections/JMS/ folder then you would create three groups. A main group for all the project GVs called MyProject, below that a sub-group for all Connections in your project and below that a group for all JMS connections and so on.

But if you have tried to use the GV editor in Designer and have been frustrated with forever expanding and collapsing nodes, re-sizing the window and not being able to copy-paste stuff then you will know what a nightmare it is to create complex group hierarchies. Don’t you wish you could just edit an XML file and create those GVs instead of using the built-in GV editor in Designer.

Fear not though, there is a quicker and easier way of  creating and edition GVs (otherwise no point in writing this post 😉

Lets start with a blank canvas so as to say. Open up the Designer and navigate to the Global Variables tab (see image below). Click the yellow pencil button to bring up the dreaded built-in GV editor.

Global Variables in Designer and the Global Variable Editor

Let us say we want to create a complex hierarchy of groups and values but we want to do it without getting frustrated with the built-in GV editor. It is possible to achieve this using the Windows Explorer (or the Linux equivalent) along with a text-editor (even Notepad will do but I prefer Notepad++ as it has XML support).

Basic Concept

Before we start the editing process it is important to understand how the GVs are stored in a project. One would have thought there would be a file with the GV hierarchy and values which we could edit. That thought is partially correct.

The main thing to understand is that every GV Group is a folder within the Global Variable root folder (more on this later). Furthermore every GV is an entry in a simple text file within the folder of the Group it belongs to.

Locate the Global Variable Root Folder

Open up your Windows Explorer and navigate to your TIBCO Designer Workspace folder. There navigate to the project for which you want to create GVs. Within the project folder there should be a folder called ‘defaultVars’. This is the ‘root’ folder for your global variables.

In the example the project name is WebServiceTest and  the path is: [TIBCO Workspace Folder]\WebServiceTest\defaultVars 

DefaultVars.substvar File

Within the ‘defaultVars’ folder you will find a file named defaultVars.substvar. This file can be opened in any text-editor and it contains all GVs belonging to the ‘root’ Group.

If you open this file in a text-editor you will find that it contains XML data. For the above set of GVs (see image) in the ‘root’ Group you will see entries like:

                 <globalVariable>
			<name>JmsProviderUrl</name>
			<value>tcp://localhost:7222</value>
			<deploymentSettable>true</deploymentSettable>
			<serviceSettable>false</serviceSettable>
			<type>String</type>
			<modTime>1282736878059</modTime>
		</globalVariable>
		<globalVariable>
			<name>JmsSslProviderUrl</name>
			<value>ssl://localhost:7243</value>
			<deploymentSettable>true</deploymentSettable>
			<serviceSettable>false</serviceSettable>
			<type>String</type>
			<modTime>1282736877974</modTime>
		</globalVariable>
		<globalVariable>
			<name>RemoteRvDaemon</name>
			<value></value>
			<deploymentSettable>true</deploymentSettable>
			<serviceSettable>false</serviceSettable>
			<type>String</type>
			<modTime>1282736878048</modTime>
		</globalVariable>

 

From the above listing we can see that each GV has its own globalVariable element. There are several child elements present for each global variable:

Name – is the ‘name’ of the GV which is also displayed in the Global Variable tree (see figure above).

Value – is the actual value of the GV.

DeploymentSettable – GV can be set during deployment.

ServiceSettable – GV is settable at per service level. Used for TIBCO Adapter archives.

Type – Data type of the GV. Possible data types: String, Integer, Password and Boolean.

ModTime – Time GV was modified.

So the root variable JmsProviderUrl is represented as:

                 <globalVariable>
			<name>JmsProviderUrl</name>
			<value>tcp://localhost:7222</value>
			<deploymentSettable>true</deploymentSettable>
			<serviceSettable>false</serviceSettable>
			<type>String</type>
			<modTime>1282736878059</modTime>
		</globalVariable>

Example Now if we want to create a new set of GVs for a JMS connection with the location WebServiceTest/Connections/JMS then we need to first create the folder structure within the root folder which will give us the corresponding Groups in the Global Variables tab. The folder structure will now look like below: Folder Structure for GV Next we need to add some GVs to the JMS group. To do this go down to the JMS sub-folder and in there create a defaultVars.substvar to store the GVs. Make sure the extension of the file is .substvar. Next open this file in a text-editor and add the following tags:

<repository xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" xmlns = "http://www.tibco.com/xmlns/repo/types/2002">
	<globalVariables>
	</globalVariables>
</repository>

All variables will be defined within the globalVariables tag.

Next we create two GVs one for storing the EMS username (JMS_Username) and one for storing the password (JMS_Password) as below:

<repository xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" xmlns = "http://www.tibco.com/xmlns/repo/types/2002">
	<globalVariables>
                <globalVariable>
			<name>JMS_Username</name>
			<value>User</value>
			<deploymentSettable>true</deploymentSettable>
			<serviceSettable>false</serviceSettable>
			<type>String</type>
			<modTime>1282736878069</modTime>
		</globalVariable>
                <globalVariable>
			<name>JMS_Password</name>
			<value>Password</value>
			<deploymentSettable>true</deploymentSettable>
			<serviceSettable>false</serviceSettable>
			<type>Password</type>
			<modTime>1282736878069</modTime>
		</globalVariable>
	</globalVariables>
</repository>

Save and close the file. Then close and reopen the project in Designer (required to refresh the Global Variable tab).

After reopening the project if you go to the GV tab you will see the following:

ResultAs you can see the two GVs we created in the file are now ready for use. Also notice each of the folders we created within the defaultVars root folder is shown as a Group.

Using this method you can also copy-paste GVs for things like JMS Queue Receiver and Senders to create separate set of GVs for different processes and/or services.

Example project: http://www.fisheyefocus.com/GVTest.zip

Overview with the created GVs on the left hand side and the JMS connection using one of the GVs on the right hand side:
Test Project - Global Variable

The project running:
Test Project - Running

Testing Web-Services in TIBCO Designer Using SOAP UI and Basic Authentication

Versions of software used:

TIBCO BusinessWorks Designer 5.5.2.2

SOAP UI 3.0.1

A quick round of testing within the Designer before packaging the project and deploying anything on a full scale test setup is always a good idea.

So you have just designed and implemented your first web-service in TIBCO Designer. But what about testing it from outside the TIBCO environment with a non-TIBCO client? After all the point of web-services is to be independent of implementation!

There are several ways of doing this. You could quickly create a client in your language of choice, especially with modern IDEs supporting auto-client generation from the WSDL file. Or you could use a software like SOAP UI and do everything in SOAP without bothering with the SOAP-to-Language API.

Now as such it is VERY EASY to test a web-service running under TIBCO Designer with SOAP UI:

1) Save the WSDL generated by TIBCO (how to save will depend on whether you are using a SOAP Event Source Starter Activity or a Service Resource for your Web-Service).

2) Start SOAP UI and create a new project.

3) It will ask for the WSDL associated with the Web-Service that you want to test, supply the saved WSDL.

4) Click OK and default SOAP requests for all operations will be created by SOAP UI.

 

Things get a bit complicated when it comes to testing Web-Services which require authentication. This is so because TIBCO leaves authentication with the BusinessWorks Administrator and credentials are defined in the domain (which makes sense). Then how can we check web-services with authentication without needing to package and deploy them?

There is an easy way, especially if you are using basic authentication.

Setting Web-Service to use Basic Authentication

To enable basic authentication in a Service Resource (see image below) you will need to go to the Endpoint Bindings tab within the Service for which you want to set the basic authentication. Select a SOAP endpoint for which you want to setup the authentication. This will give you two tabs, one for Transport and one for SOAP details.

Within the Transport tab you will find a check-box titled ‘Use Basic Authentication’. Select it to use basic authentication.

Basic Authentication in Service Resource

 

To achieve the same in a SOAP Event Source starter activity just go to the Transport Details tab within the configuration and you will see a similar ‘Use Basic Authentication’ checkbox.

One word of warning: once you select basic authentication your web-service clients will NOT work till you finish the next step and add a valid username and password to the request.

Enable Authentication in Designer

Now that your web-service is setup for using basic-authentication, you need to setup TIBCO Designer to authenticate incoming requests.

To do this copy tibco\tra\domain\[Domain Name]\AuthorizationDomain.properties to  tibco\tra\5.5 (x.x is the version number of the installed TRA, in my case it was version 5.5).

Found this solution here: http://eai.ittoolbox.com/groups/technical-functional/tibco-l/bw-http-basic-authentication-2526019

 

Testing

Final step is to test the web-service using basic authentication.

If you try and invoke the web-service without copying the properties file and without supplying the username and password you will get an ‘Internal Error’ response.

If you try and invoke the web-service without a username or password (irrespective of whether you copied the properties file or not) you will get a ‘This request requires HTTP authentication’ error response.

Once the properties file has been copied to the correct location the only thing that is left is to supply the username and password in the request.

In SOAP UI, navigate to the request generated for the web-service being tested. In the bottom left hand side there will be a Request Properties box (see image below). Scroll till you see the option for Username and Password. Enter the details for the username defined in the properties file (UserID property) and execute the request. This time if all is well then you should get the correct response from the web-service.

SOAP UI Basic Authentication Test
SOAP UI Basic Authentication Test

If you don’t get the correct response make sure you restart SOAP UI and Designer after copying the file.

Always remember to test your web-service WITHOUT basic authentication BEFORE testing with it. This will ensure there is nothing fundamentally wrong with the web-service.

You do not need to refresh the WSDL file for the web-service after enabling/disabling basic authentication. This is because basic-authentication operates at the level of the HTTP request and does not affect the SOAP content which is a payload of the request. Therefore basic authentication is available for HTTP transport only and not for JMS.