Question & Answer
Question
What is the procedure to manually create JMS resources used by the Integration Framework?
Answer
In previous versions of Maximo, the Maximo clustering configuration used for the Integration Framework typically contained separate buses – one bus for each of the UI and MIF clusters – to avoid affecting the user experience in terms of performance while loading data into Maximo. This was often complicated and had drawbacks when it came to high availability and simplicity of the configuration.
Often times, the clusters designated as IF or CRON may need to be able to access the sequential outbound queues, and users may need to access the inbound continuous or sequential queues from the UI cluster.
To make the JMS resources accessible from all clusters to avoid the complication of creating duplicate JMS resources for just such scenarios, the following configuration is designed to contain a single service integration bus, and all resources are visible to all cluster members regardless which cluster each server resides in.
For this configuration, we are assuming the following clusters already exist:
UI cluster (uicluster) containing two members
IF cluster (ifcluster) containing two members
CRON cluster (croncluster) containing two members
Below is a simple diagram depicting the solution outlined here:
Below is the list of steps used to configure WebSphere Application Server:
1. To accomplish load distribution and visibility of the JNDI objects throughout the WebSphere cell, we will need several messaging Engines. We will also need a database for each messaging engine. In this configuration, we will have a messaging engine for each of the three clusters for accessing the sequential queues. This means we will have a total of three messaging engines, so we will need three empty databases or schemas for this configuration before proceeding. These databases will be used only by the messaging engines and will not be used by the Maximo application. The owner of the database must have permissions to create tables.
Remember that no two messaging engines can share the same schema for their persistent storage, so each messaging engine must have its own persistent storage location.
Once you have three empty databases or schemas, proceed to the next step.
2. Create a JDBC Provider for your database which we will use for your messaging engines’ persistent storage.
The example below is for Oracle:
1. Launch a browser and open the WebSphere administrative console by typing the following: https://<dmgr_host_name>:9043/ibm/console
2. Click Resources > JDBC > JDBC Providers
3. From the Scope drop-down list select Cell=ctgCell01
4. Click New.
5. Enter/select the following information
- Database Type Select Oracle
- Provider type Select Oracle JDBC Driver
- Implementation type Select XA data source
- Name Enter oraclexa
6. Click Next
7. Leave Directory location blank
8. Click Next
9. Click Finish
10. Click Save
11. Click OK
12. Click oraclexa to open the dialog box.
13. Change the class path to a local path containing a copy of the JAR file from the Maximo installation folder/lib/oraclethin.jar
Note that this file must be placed in the same location on each node.This can be a mount point or UNC path as well as a local location that the WebSphere JVM user has access to.
AVOID TROUBLE: Do not place database driver files in the WebSphere Installation/lib folder.
14. Click OK
15. Click Save
3. Now we need to create data sources for each messaging engine. Since there are three messaging engines required for this configuration we will need to create three data sources (one for each database used by each messaging engine for persistent storage). If you create three schemas in a single database, you will need to create only one data source and three authentication aliases (one for each db/schema user). The number of data sources you create will depend on which database vendor you are using and your database configuration. In the example below, we create a single data source and three authentication aliases (one per schema user):
Click Resources > JDBC > Data sources
- URL Enter jdbc:oracle:thin:@<hostname.domain.com>:1521:<yourdbname>
- Data store helper class name Select Oracle11g data store helper
- data source in container managed persistence (CMP) <Checked>
- Alias Enter me1
- User ID Enter me1
- Password Enter <PASSWORD>
me1
me2
me3
22. Test your data source connection. Once successful, proceed to the next step.
4. Creating the JMS Bus
5. Adding Clusters to the service integration bus
Add the UI Cluster to the bus
1. From the WebSphere administrative console, click Service Integration > Buses
2. Click mifjmsbus
3. Under Topology on the right, click Bus members.
4. In the Buses > mifjmsbus > Bus members dialog box, click Add
5. Click the Cluster drop-down arrow, and select the cluster uicluster to add to the bus, and then click Next
6. Check that the data store radio button is selected, and then click Next
7. Check that the Use existing data store radio button is selected
8. Enter the following information
- Data source JNDI name Enter jdbc/oraclexads
- Schema name Enter me1
- Authentication alias Select ctgCellManager01/me1
- Create tables <checked>
9. Click Next
10. Click Finish
11. Click Save
Add the Cron Cluster to the bus
- Data source JNDI name Enter jdbc/oraclexads
- Schema name Enter me2
- Authentication alias Select ctgCellManager01/me2
- Create tables <checked>
Add the IF Cluster to the bus
- Data source JNDI name Enter jdbc/oraclexads
- Schema name Enter me3
- Authentication alias Select ctgCellManager01/me3
- Create tables <checked>
6. Creating the destination for the continuous inbound (CQINBD) queue
- Click Specify as the Exception destination value
- Enter CQINERRBD as the Exception destination value
- Change the Maximum failed deliveries value to 5
7. Creating the destination for the sequential inbound (SQINBD)
- Navigate the path Buses > mifjmsbus > Destinations, then click SQINBD
8. Creating the destination for the sequential outbound (SQOUTBD) queue
- Navigate to Buses > mifjmsbus > Destinations, then click SQOUTBD
- Click None as the Exception destination value
9. Creating the destination for the inbound error queue (CQINERRBD) queue
- Click Specify as the Exception destination value
- Enter CQINERRBD as the Exception destination value
- Change the Maximum failed deliveries value to 5
10. Creating the JMS connection factory
- Name Enter intjmsconfact
- JNDI name Enter jms/maximo/int/cf/intcf
- Bus name Select mifjmsbus
11. Creating the continuous inbound (CQIN) JMS queue
- Name Enter CQIN
- JNDI name Enter jms/maximo/int/queues/cqin
- Bus name Select mifjmsbus
- Queue name Select CQINBD
12. Creating the sequential inbound (SQIN) JMS queue
- Name Enter SQIN
- JNDI name Enter jms/maximo/int/queues/sqin
- Bus name Select mifjmsbus
- Queue name Select SQINBD
13. Creating the sequential outbound (SQOUT) JMS queue
- Name Enter SQOUT
- JNDI name Enter jms/maximo/int/queues/sqout
- Bus name Select mifjmsbus
- Queue name Select SQOUTBD
14. Creating the error (CQINERR) JMS queue
- Name Enter CQINERR
- JNDI name Enter jms/maximo/int/queues/cqinerr
- Bus name Select mifjmsbus
- Queue name Select CQINERRBD
15. Creating JMS activation specification for the continuous inbound queue (CQIN)
- Name intjmsact
- JNDI name intjmsact
- Destination type Queue
- Destination JNDI name jms/maximo/int/queues/cqin
- Bus name mifjmsbus
- Maximum concurrent endpoints 5
- Maximum batch size 10
- Check “Always activate MDB in all servers”
16. Creating JMS activation specification for the inbound error queue (CQINERR)
- Name Enter intjmsacterr.
- JNDI name Enter intjmsacterr
- Destination type Enter Queue
- Destination JNDI name jms/maximo/int/queues/cqinerr
- Bus name mifjmsbus
- Maximum batch size 10
- Maximum concurrent endpoints 5
- Check the checkbox “Always activate MDB in all servers”
17. Enable the Message Driven beans for the Integration Framework maximo.ear file. To do so, modify the ejb-jar.xml and ibm-ejb-jar-bnd.xmi files.
Open the file /opt/IBM/SMP/maximo/applications/maximo/mboejb/ejbmodule/META-INF/ejb-jar.xml
The file contains two sections that have Message Driven beans (MDBs) commented out and will look like the contents below:
<!-- MEA MDB <message-driven id="MessageDriven_JMSContQueueProcessor_1"> <ejb-name>JMSContQueueProcessor-1</ejb-name> <ejb-class>psdi.iface.jms.JMSContQueueProcessor</ejb-class> <transaction-type>Container</transaction-type> <message-destination-type>javax.jms.Queue</message-destination-type> <env-entry> <env-entry-name>MESSAGEPROCESSOR</env-entry-name> <env-entry-type>java.lang.String </env-entry-type> <env-entry-value>psdi.iface.jms.QueueToMaximoProcessor</env-entry-value> </env-entry> </message-driven> --> <!-- MEA MDB for error queue <message-driven id="MessageDriven_JMSContQueueProcessor_2"> <ejb-name>JMSContQueueProcessor-2</ejb-name> <ejb-class>psdi.iface.jms.JMSContQueueProcessor</ejb-class> <transaction-type>Container</transaction-type> <message-destination-type>javax.jms.Queue</message-destination-type> <env-entry> <env-entry-name>MESSAGEPROCESSOR</env-entry-name> <env-entry-type>java.lang.String </env-entry-type> <env-entry-value>psdi.iface.jms.QueueToMaximoProcessor</env-entry-value> </env-entry> <env-entry> <env-entry-name>MDBDELAY</env-entry-name> <env-entry-type>java.lang.Long </env-entry-type> <env-entry-value>30000</env-entry-value> </env-entry> <env-entry> <env-entry-name>ERRORQUEUE</env-entry-name> <env-entry-type>java.lang.String </env-entry-type> <env-entry-value>1</env-entry-value> </env-entry> </message-driven> --> <!-- MEA MDB <container-transaction> <method> <ejb-name>JMSContQueueProcessor-1</ejb-name> <method-name>*</method-name> </method> <trans-attribute>Required</trans-attribute> </container-transaction> --> <!-- MEA MDB for error queue <container-transaction> <method> <ejb-name>JMSContQueueProcessor-2</ejb-name> <method-name>*</method-name> </method> <trans-attribute>Required</trans-attribute> </container-transaction> -->
Uncomment the MDBs. Uncommented, the MDBs will look like the following:
<!-- MEA MDB --> <message-driven id="MessageDriven_JMSContQueueProcessor_1"> <ejb-name>JMSContQueueProcessor-1</ejb-name> <ejb-class>psdi.iface.jms.JMSContQueueProcessor</ejb-class> <transaction-type>Container</transaction-type> <message-destination-type>javax.jms.Queue</message-destination-type> <env-entry> <env-entry-name>MESSAGEPROCESSOR</env-entry-name> <env-entry-type>java.lang.String </env-entry-type> <env-entry-value>psdi.iface.jms.QueueToMaximoProcessor</env-entry-value> </env-entry> </message-driven> <!-- MEA MDB for error queue --> <message-driven id="MessageDriven_JMSContQueueProcessor_2"> <ejb-name>JMSContQueueProcessor-2</ejb-name> <ejb-class>psdi.iface.jms.JMSContQueueProcessor</ejb-class> <transaction-type>Container</transaction-type> <message-destination-type>javax.jms.Queue</message-destination-type> <env-entry> <env-entry-name>MESSAGEPROCESSOR</env-entry-name> <env-entry-type>java.lang.String </env-entry-type> <env-entry-value>psdi.iface.jms.QueueToMaximoProcessor</env-entry-value> </env-entry> <env-entry> <env-entry-name>MDBDELAY</env-entry-name> <env-entry-type>java.lang.Long </env-entry-type> <env-entry-value>30000</env-entry-value> </env-entry> <env-entry> <env-entry-name>ERRORQUEUE</env-entry-name> <env-entry-type>java.lang.String </env-entry-type> <env-entry-value>1</env-entry-value> </env-entry> </message-driven> <!-- MEA MDB --> <container-transaction> <method> <ejb-name>JMSContQueueProcessor-1</ejb-name> <method-name>*</method-name> </method> <trans-attribute>Required</trans-attribute> </container-transaction> <!-- MEA MDB for error queue --> <container-transaction> <method> <ejb-name>JMSContQueueProcessor-2</ejb-name> <method-name>*</method-name> </method> <trans-attribute>Required</trans-attribute> </container-transaction>
Open the file /opt/IBM/SMP/maximo/applications/maximo/mboejb/ejbmodule/META-INF/ibm-ejb-jar-bnd.xmi. The file contains a section that has Message Driven beans (MDBs) commented out and will look like the contents below:
<!-- MEA MDB <ejbBindings xmi:type="ejbbnd:MessageDrivenBeanBinding" xmi:id="MessageDrivenBeanBinding_1" activationSpecJndiName="intjmsact"> <enterpriseBean xmi:type="ejb:MessageDriven" href="META-INF/ejb-jar.xml#MessageDriven_JMSContQueueProcessor_1"/> </ejbBindings> --> <!-- MEA MDB for error queue <ejbBindings xmi:type="ejbbnd:MessageDrivenBeanBinding" xmi:id="MessageDrivenBeanBinding_1" activationSpecJndiName="intjmsacterr"> <enterpriseBean xmi:type="ejb:MessageDriven" href="META-INF/ejb-jar.xml#MessageDriven_JMSContQueueProcessor_2"/> </ejbBindings> -->
Uncomment the MDBs so they look like the following:
<!-- MEA MDB --> <ejbBindings xmi:type="ejbbnd:MessageDrivenBeanBinding" xmi:id="MessageDrivenBeanBinding_1" activationSpecJndiName="intjmsact"> <enterpriseBean xmi:type="ejb:MessageDriven" href="META-INF/ejb-jar.xml#MessageDriven_JMSContQueueProcessor_1"/> </ejbBindings> <!-- MEA MDB for error queue --> <ejbBindings xmi:type="ejbbnd:MessageDrivenBeanBinding" xmi:id="MessageDrivenBeanBinding_1" activationSpecJndiName="intjmsacterr"> <enterpriseBean xmi:type="ejb:MessageDriven" href="META-INF/ejb-jar.xml#MessageDriven_JMSContQueueProcessor_2"/> </ejbBindings>
NOTE: the MDBs are only to be uncommented for the IF ear. For the UI and CRON maximo ear files, the MDBs are commented out in both the ejb-jar.xml and the ibm-ejb-jar-bnd.xmi.
18. Which cron tasks should run where?
Now that we have three clusters, and all of our JMS resources have been created and the MDBs deployed, we will need to set properties to control where cron tasks will run.
Here are a list of cron tasks that we will need to consider:
JMSQSEQCONSUMER.SEQQOUT
JMSQSEQCONSUMER.SEQQIN
IFACETABLECONSUMER
FLATFILECONSUMER
XMLFILECONSUMER
All other cron tasks
The Message Driven beans will only be deployed to ifcluster and will be activated in both server instances in this cluster.
All cron tasks should be configured to run in the croncluster with the exception of integration related crontask instances. The cron task JMSQSEQCONSUMER.SEQQOUT should be configured to run in the uicluster, where the sqout queue point for this queue has been assigned. This ensures that the queue point is available when users are able to log into the uicluster and messages will be delivered to their destination regardless of the status of any of the servers in ifcluster or croncluster.
The JMSQSEQCONSUMER.SEQQIN, IFACETABLECONSUMER, FLATFILECONSUMER, XMLFILECONSUMER crontask instances should be configured to run in the ifcluster, where the cqin, cqinerr, and sqin queue points have been assigned. This keeps inbound message processing on the mifcluster and will have no dependency on the uicluster or croncluster.
The mxe.crontask.donotrun or mxe.crontask.dorun properties can be specified in the maximo.properties file for each cluster to simplify the configuration. Below is an example of what would be configured:
uicluster maximo.properties:
mxe.crontask.dorun=JMSQSEQCONSUMER.SEQQOUT
ifcluster maximo.properties:
mxe.crontask.dorun=JMSQSEQCONSUMER.SEQQIN, IFACETABLECONSUMER.instancename, FLATFILECONSUMER.instancename,XMLFILECONSUMER.instancename
croncluster maximo.properties:
mxe.crontask.donotrun=JMSQSEQCONSUMER.SEQQOUT,IFACETABLECONSUMER.instancename, FLATFILECONSUMER.instancename,XMLFILECONSUMER.instancename,JMSQSEQCONSUMER.SEQQIN
NOTE: Be sure to replace your crontask instance name with the actual name of your crontask instance.
19. Rebuild and redeploy the maximo.ear for each cluster
Putting it all together
Now that we have configured the system, how does it work? Here is a high level description of how data might be retrieved from the Maximo interface tables associated with an external system, sent to the continuous inbound queue.
- Data is entered into the interface table associated with a Maximo enterprise service and external system, then the mxin_inter_trans queue table
- The IFACETABLECONSUMER crontask runs in croncluster and picks up the messages from the interface table and routes them to ifcluster since that is where the queue point destination is hosted for both the continuous and sequential inbound queues
- The message driven beans running in the ifcluster members pick up the messages in the continuous queue and process them into Maximo. If the messages are routed to the sequential inbound queue, the JMSQSEQCONSUMER.SEQQIN crontask instance will pick up the messages and process them into Maximo.
When data is saved by a user in Maximo which triggers an event to write the message to the sequential outbound queue, the message is written to the sequential outbound queue point assigned to the uicluser. The sequential outbound crontask JMSQSEQCONSUMER.SEQQOUT which also runs on uicluster will pick up the messages and deliver them to the respective external system endpoints.
If croncluster runs an escalation that causes an event to trigger an outbound message to the sequential outbound queue, since croncluster is a member of the same bus, it can access the sequential outbound queue point assigned to uicluster, even if the uicluster is down, due to store and forward behavior. The same is true for the ifcluster in that it will have access to the sequential outbound queue if needed without additional configuration required. If croncluster and ifcluster are both down, uicluster will continue to function independently from the others allowing users to continue working and sending data to external systems without interruption.
For any questions regarding this configuration, contact IBM Support.
Was this topic helpful?
Document Information
Modified date:
18 November 2021
UID
swg21989836