Recently I have connected Smallworld™ Business Integrator (SBI) release 4.1 to Tibco EMS™ 7.0.1 using JNDI.
I will layout the steps to take, mostly from the Smallworld perspective. Even if you are using a different SBI release or just want to connect to Tibco without SBI, you will find valuable information here.
I assume you installed SBI and configured it. After that, execute the following steps:
Get the jar files
To connect to Tibco EMS you will need 2 jar files from the Tibco EMS™ installation: tibjms.jar and j2ee.jar. The last one is part of the Oracle Java™ Enterprise Edition.
This xml file will contain all SBI need to know to connect to Tibco. This xml file is part of the SBI_Config module resources.
These are the settings:
<sbi_config> <default default="yes"> <gis> <!--this section is ignored for this document--> </gis> <sap> <logon> <!-- Not necessary because we are using Tibco to log into SAP. --> </logon> <!-- The sap version being used. --> <property name="sap_version" value="erp2005"/> <!-- The transport exemplar to use for the Tibco EMS connection --> <property name="transport_exemplar" value="pl_jms_xrfc_transport" type="symbol"/> <!--The settings for the Tibco EMS connection --> <pl_jms_xrfc_transport> <!-- The connection options for the message bus, as required by jms_user.new(). --> <property name="connection_options" type="list"> <item value="force_new" type="symbol"/> <item value="yes" type="boolean"/> <!-- Disable tracing for debugging. Increase the value to get more debugging information on the prompt--> <item value="trace" type="symbol"/> <item value="0" type="int"/> <!-- The name of the connection factory that will lookedup in JNDI --> <item value="queue_connection_factory" type="symbol"/> <item value="QueueConnectionFactory"/> <!-- The username to log into the Tibco connection factory--> <item value="username"/> <item value="FactoryUser"/> <!-- The password to log into the Tibco connection factory--> <item value="password"/> <item value="FactoryPassword"/> <!-- The username to log into JNDI--> <item value="security_principal"/> <item value="JNDIUser"/> <!-- The password to log into JNDI--> <item value="security_credentials"/> <item value="JNDIPassworld"/> <!-- We only connect using queues so the topic connection is not needed --> <!-- <item value="topic_connection_factory" type="symbol"/> --> <!-- <item value="NutUsed"/> --> <!-- The name of the initial context factory in JNDI--> <item value="initial_context_factory" type="symbol"/> <item value="com.tibco.tibjms.naming.TibjmsInitialContextFactory"/> <!-- The URL of the Tibco provider--> <item value="provider_url" type="symbol"/> <item value="tcp://server:portnumber"/> </property> <!-- The classpath to include the 3 mandatory jar files. --> <property name="classpath" type="list"> <item value="%SMALLWORLD_GIS%\sw_core\resources\base\java\lib\extern.jar"/> <item value="%SBI_TIBCO_PRODUCT_DIR%\lib\j2ee.jar"/> <item value="%SBI_TIBCO_PRODUCT_DIR%\lib\tibjms.jar"/> </property> <!-- The options used by a server for listening to the message bus.--> <property name="input_channel_options" type="list"> <!-- The timeout when listening to the bus. Make sure it matches with the time_to_live settings from Tibco. Otherwise you will have stopped listening but Tibco could still be sending the message a bit later.--> <item value="timeout" type="symbol"/> <item value="30000" type="int"/> </property> <!-- The options used to send messages/requests to the message bus.--> <property name="output_channel_options" type="list"> <!-- Defines how long the message lives on the bus.--> <item value="time_to_live" type="symbol"/> <item value="120000" type="int"/> </property> <property name="sap_input_queue_name" value="NOT_USED"/> <!-- The queue we are working with--> <property name="sap_output_queue_name" value="SMALLWORLD_QUEUE"/> <property name="gis_input_queue_name" value="NOT_USED"/> </pl_jms_xrfc_transport> </sap> </default> </sbi_config>
This should be sufficient to connect to Tibco EMS, but I ran into 2 problems that needed fixing in Smallworld™.
- The classpath in the config file did not handle environment variables. Hardcoding is no option so this needs fixing.
- The exemplar pl_jms_queue works with 2 ids: jms_input_id and jms_output_id. These id’s are used to somehow filter the queue. In our case Tibco EMS did not supply the values and the TIBCO consultants had no idea where the ids were for. I simply hacked out the ids and this worked well.
The fix file “tibco_jms_fix.magik” is attached. tibco_jms_fix.magik
The following issues were discussed and decided with the Tibco consultants.
- We are using one Tibco queue to communicate with SAP. Another option was to create a queue for every SAP call, but this is not supported from SBI. This means that in Tibco there will the one queue that will diverse to many other queues for each SAP call.
- Make the Tibco queue static, not dynamic. SBI did not handle dynamic queue’s.
- Automatically commit in Tibco. SBI does not send commit or rollback commands so this needs to happen in Tibco.
- Beware of language settings. Make sure that Tibco logs into SAP with the language settings that are used by the SAP front-end users. Some values in SAP are language dependent. For example the description of a FunctionalLocation is language dependent. If Tibco logs into SAP with language setting EN and the SAP user logs in with language NL (dutch) then the user does not see the description that was set by Tibco.
Screenshots of the Tibco configuration
To get an idea of the way stuff works in the Tibco configuration I have included some screenshots of it.
This is the main process that listens to the main queue from SBI and then spawn subprocesses to invoke SAP requests.
This is one of the sub-processes that handles an individual SAP call.
You can test the configuration by requesting the description of a functional location in SAP. In this example it is a high pressure gasstation with number “HD-00052”.
_block # Open a connection to SAP con << plsl_connection.new() # Create a session ses << con.logon() # Fetch an object obj << ses.get_for_id("FunctionalLocation", "HD-00052") # Fetch the description v << obj.get_value_for("descript") show(v) # Close the connection con.close() _endblock $
This should do the trick. Good luck!