The first is configuring the JMS resources for scalability and the second is configuring the messaging engines for highly availability.
For this configuration, we are assuming the following already exists:
UI cluster (uicluster) containing two members
IF cluster (ifcluster) containing two members
CRON cluster (croncluster) containing two member
Below is a simple diagram depicting the solution outlined here:
Below is the list of steps used to configure WebSphere
- 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 two messaging engines for the IF continuous inbound queue (one per cluster member for load distribution) and one for each cluster for accessing the sequential queues. This means we will have a total of four messaging engines, so we will need four empty databases or schemas for this configuration prior to 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 four empty databases or schemas, proceed to the next step.
- Create JDBC Provider for your database which we will use for your messaging engines’ persistent storage.
The example below is for Oracle:
- Launch a browser and open the WebSphere Administrative Console by typing the following: https://<dmgr_host_name>:9043/ibm/console
- Click Resources > JDBC > JDBC Providers
- From the Scope drop-down list select Cell=ctgCell01
- Click New.
- Enter/select the following information
- Database Type Select Oracle
- Provider type Select Oracle JDBC Driver
- Implementation type Select XA data source
- Name Enter oraclexa
- Click Next
- Leave Directory location blank
- Click Next
- Click Finish
- Click Save
- Click OK
- Click oraclexa to open the dialog box.
- Change the Class Path to a local path containing a copy of the jar file from the Maximo installation folder/lib/ojdbc6.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.
- Click Ok
- Click Save
- Now we need to create data sources for each messaging engine. Since there are four messaging engines required for this configuration (two for the partitioned continuous queue and one each for the remaining clusters), we will need to create four data sources (one for each database used by each messaging engine for persistent storage). If you create four schemas in a single database, you can create only one data source and four authentication aliases (one for each 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, I created a single data source and four authentication aliases (one per schema user):
Click Resources > JDBC > Data sources
- From the Scope drop-down list select Cell= ctgCell01
- Click New.
- Enter the following information
- Data source Name Enter oraclexads
- JNDI Name Enter jdbc/oraclexads
- Component-managed authentication alias Select (none)
- Click Next
- Select an existing JDBC provider oraclexa
- Click Next
- Enter the JDBC URL information using the format shown below:
- 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>
- Click Next
- Click Finish
- Click Save
- Click oraclexads to open the dialog box
- Click on JAAS - J2C authentication data
- Click New.
- Enter the user information for the first schema
- Alias Enter me1
- User ID Enter me1
- Password Enter <PASSWORD>
- Click OK
- Click Save
- Click Resources > JDBC > Data sources > oraclexads
- Select ctgCellManager01/me1 for Component-managed authentication alias
- Click OK
- Click Save
- Using the steps from 12 to 17, create four remaining schemas and save the changes.
The end result will be a total of four authentication aliases created using the following aliases:
me1
me2
me3
me4
- Test your data source connection. Once successful, proceed to the next step.
- Creating the JMS Bus
- Click Service Integration > Buses to open the Buses dialog
- Click New to create a new bus
- Enter mifjmsbus as the name of the new bus
- Deselect the Bus security check box
- Click Next
- Click Finish
- Click Save
- Adding Clusters to the service integration bus
Add the UI Cluster to the bus
- From the WebSphere Administrative Console, click Service Integration > Buses
- Click mifjmsbus
- Under Topology on the right, click Bus members.
- In the Buses > mifjmsbus > Bus members dialog box, click Add
- Click the Cluster drop-down arrow, and select the cluster uicluster to add to the bus, and then click Next
- Check that the Data Store radio button is selected, and then click Next
- Check that the Use existing data store radio button is selected
- Enter the following information
- Data source JNDI name Enter jdbc/oraclexads
- Schema name Enter me1
- Authentication alias Select ctgCellManager01/me1
- Create tables <checked>
- Click Next
- Click Finish
- Click Save
Add the Cron Cluster to the bus
- From the WebSphere Administrative Console, click Service Integration > Buses
- Click mifjmsbus
- Under Topology, click Bus members
- In the Buses > mifjmsbus > Bus members dialog box, click Add
- Click the Cluster drop-down arrow, and select the cluster croncluster and then click Next
- Check that the Data Store radio button is selected, and then click Next
- Check that the Use existing data store radio button is selected
- Enter the following information
- Data source JNDI name Enter jdbc/oraclexads
- Schema name Enter me2
- Authentication alias Select ctgCellManager01/me2
- Create tables <checked>
- Click Finish
- Click Save
- Click OK
Add the IF Cluster to the bus
- From the WebSphere Administrative Console, click Service Integration > Buses
- Click mifjmsbus
- Under Topology, click Bus members.
- In the Buses > mifjmsbus > Bus members dialog box, click Add
- Click the Cluster drop-down arrow, and select the cluster ifcluster to add to the bus, and then click Next
- Check that the Data Store radio button is selected, and then click Next
- Check that the Use existing data store radio button is selected
- Enter the following information
- Data source JNDI name Enter jdbc/oraclexads
- Schema name Enter me3
- Authentication alias Select ctgCellManager01/me3
- Create tables <checked>
- Click Finish
- Click Save
Add a second messaging engine for the ifcluster for partitioning the continuous inbound queue
- Under Buses/mifjmsbus>bus members, select ifcluster
- Then select Scalability with high availability
- Then click on Messaging Engines
- Then click Add messaging engine button
- Choose Data Store and click next
- Enter the following information
- Data source JNDI name Enter jdbc/oraclexads
- Schema name Enter me4
- Authentication alias Select ctgCellManager01/me4
- Create tables <checked>
- Click Next
- Click Finish
- Click Save
- Modify the messaging engine policies
- Navigate to Service Integration > Buses and select mifjmsbus
- On the right, select Bus Members
- Click on ifcluster
- Select the radio button for Scalability and High Availability
- Save
- Next, Navigate back to the mifjmsbus and on the right side of the screen, select Messaging Engine Policy Maintenance
- Click on the first of the two messaging engines in the list
- Ensure that Fallback and Preferred Servers Only check boxes are checked
- On the right side of the screen, click Preferred Servers
- Add both ifcluster server instances to the list of preferred servers in the order they appear
- Navigate back to your mifjmsbus and on the right side of the screen, select Messaging Engine Policy Maintenance
- Click on the second of the two messaging engines
- Ensure that Fallback and Preferred Servers Only check boxes are checked
- On the right side of the screen, click Preferred Servers
- Add both ifcluster server instances in the opposite order as done in step 10
- Save
- Creating the partitioned destination for the continuous inbound (CQINBD) queue
- From the WebSphere Administrative Console, click Service Integration > Buses
- Click mifjmsbus
- Click Destinations under Destination resources on the right
- Click New
- Leave Queue radio button checked as the destination type, and click Next
- Type CQINBD in the Identifier field then click Next
- Select the Bus Member pull-down and choose cluster ifcluster as the bus member
- Click Next to open the confirm queue creation dialog box
- Review your selections, then click Finish
- Navigate again to Buses > intjmsbus > Destinations, then click CQINBD
- Click Specify as the Exception destination value
- Enter CQINERRBD as the Exception destination value
- Change the Maximum failed deliveries value to 5
- Click Apply
- Click Save
- Creating the destination for the sequential inbound (SQINBD)
- From the WebSphere Administrative Console, click Service Integration > Buses
- Click mifjmsbus
- Click Destinations under Destination on the right side of the screen
- Click New
- Leave Queue checked as the destination type, and click Next
- Enter SQINBD in the Identifier, then click Next
- Select the Bus Member pull-down and choose cluster croncluster
- Click Next
- Review your selections, then click Finish
- Navigate the path Buses > mifjmsbus > Destinations, then click SQINBD
- Click None as the Exception destination value.
- Click Apply
- Click Save
NOTE:the sequential inbound queue is being assigned to the croncluster because this queue is sequential and therefore must not be partitioned.If we were to assign it to the ifcluster where we have two messaging engines created, the queue would become partitioned and would no longer be considered a sequential queue.This is important when message order is required and is the reason we assigned the sequential queue to the cron cluster.
- Creating the destination for the sequential outbound (SQOUTBD) queue
- From the WebSphere Administrative Console, click Service Integration > Buses
- Click mifjmsbus
- Click Destinations under Destination resources on the right side of the screen
- Click New
- Leave Queue checked as the destination type, and click Next
- Enter SQOUTBD in the Identifier field, then click Next
- Select the Bus Member pull-down and choose cluster uicluster as the bus member
- Click Next
- Click Finish
- Navigate to Buses > mifjmsbus > Destinations, then click SQOUTBD
- Click None as the Exception destination value
- Click Apply
- Click Save
- Creating the destination for the inbound error queue (CQINERRBD) queue
- From the WebSphere Administrative Console, click Service Integration > Buses
- Click mifjmsbus
- Click Destinations under Destination resources on the right side of the screen
- Click New
- Leave Queue checked as the destination type, and click Next
- Enter CQINERRBD in the Identifier field, then click Next
- Select the Bus Member pull-down and choose Cluster ifcluster
- Click Next
- Click Finish
- Navigate to Buses > mifjmsbus > Destinations, then click CQINERRBD
- Click Specify as the Exception destination value
- Enter CQINBD as the Exception destination value
- Change the Maximum failed deliveries value to 5
- Click Apply
- Click Save
- Creating the JMS connection factory
- From the WebSphere Administrative Console, click Resources → JMS → Connection factories.
- From the Scope drop-down list select Cell=ctgCell01
- Click New
- Verify that the Default Messaging Provider is selected and click OK
- Enter the following information, and then click OK
- Name Enter intjmsconfact
- JNDI name Enter jms/maximo/int/cf/intcf
- Bus name Select mifjmsbus
- Click Save
- Creating the continuous inbound (CQIN) JMS queue
- From the WebSphere Administrative Console, click Resources > JMS > Queues
- From the Scope drop-down list, select Cell=ctgCell01
- Click New
- Verify that the Default Messaging Provider is selected and click OK
- Enter the following information, and click OK
- Name Enter CQIN
- JNDI name Enter jms/maximo/int/queues/cqin
- Bus name Select mifjmsbus
- Queue name Select CQINBD
- Uncheck the check box “Restrict messages to the local queue point if a queue point is configured on the connected messaging engine”
- Select the radio button “Do not prefer a local queue point over other queue points”
- Select the radio button “Messages may be sent to different queue points”
- Select the radio button “Message on all queue points are visible”
- Click OK
- Click Save
- Creating the sequential inbound (SQIN) JMS queue
- From the WebSphere Administrative Console, click Resources > JMS > Queues
- From the Scope drop-down list, select Cell=ctgCell01
- Click New
- Verify that the Default Messaging Provider is selected and click OK
- Enter the following information, and click OK
- Name Enter SQIN
- JNDI name Enter jms/maximo/int/queues/sqin
- Bus name Select mifjmsbus
- Queue name Select SQINBD
- Click OK
- Click Save
- Creating the sequential outbound (SQOUT) JMS queue
- From the WebSphere Administrative Console, click Resources > JMS > Queues
- From the Scope drop-down list, select Cell=ctgCell01
- Click New
- Verify that the Default Messaging Provider is selected and click OK
- Enter the following information, and click OK
- Name Enter SQOUT
- JNDI name Enter jms/maximo/int/queues/sqout
- Bus name Select mifjmsbus
- Queue name Select SQOUTBD
- Click OK
- Click Save
- Creating the error (CQINERR) JMS queue
- From the WebSphere Administrative Console, click Resources > JMS > Queues
- From the Scope drop-down list, select Cell=ctgCell01
- Click New
- Verify that the Default Messaging Provider is selected and click OK
- Enter the following information, and click OK
- Name Enter CQINERR
- JNDI name Enter jms/maximo/int/queues/cqinerr
- Bus name Select intjmsbus
- Queue name Select CQINERRBD
- Uncheck the check box “Restrict messages to the local queue point if a queue point is configured on the connected messaging engine”
- Select the radio button “Do not prefer a local queue point over other queue points”
- Select the radio button “Messages may be sent to different queue points”
- Select the radio button “Message on all queue points are visible”
- Click OK
- Click Save
- Creating JMS activation specification for the continuous inbound queue (CQIN)
- From the WebSphere Administrative Console, click Resources → JMS → Activation Specifications
- From the Scope drop-down list, select Cell=ctgCell01
- Click New
- Click OK
- Enter the following information, and then click OK
- Name intjmsact
- JNDI name intjmsact
- Destination type Queue
- Destination JNDI name jms/maximo/int/queues/cqin
- Bus name mifjmsbus
- Target Significance: Required
- Maximum batch size 10
- Maximum concurrent endpoints 5
- Check the checkbox “Always activate MDB in all servers”
- Click OK
- Click Save
- Creating JMS activation specification for the inbound error queue (CQINERR)
- From the WebSphere Administrative Console, click Resources > JMS > Activation Specifications.
- From the Scope drop-down list, select Cell=ctgCell01
- Click New. to complete the General Properties section for the new JMS activation specification.
- Click OK
- Enter the following information, and click OK.
- Name Enter intjmsacterr.
- JNDI name Enter intjmsacterr
- Destination type Enter Queue
- Destination JNDI name jms/maximo/int/queues/cqinerr
- Bus name mifjmsbus
- Target Significance: Required
- Maximum batch size 1
- Maximum concurrent endpoints 10
- Check the checkbox “Always activate MDB in all servers”
- Click OK
- Click Save
- Modify the ejb-jar.xml and ibm-ejb-jar-bnd.xmi to enable the Message Driven Beans for the Integration Framework maximo.ear file.
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
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.
- 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, each running their own messaging engine and connecting to their respective queue points associated with the partitioned continuous queue. Each server receives messages on their local queue points by way of the WebSphere workload manager. Messages received from the other messaging engines will be fairly evenly distributed to both queue points. Additional ifcluster members can be added using the same method described above to further distribute the load of incoming messages.
All crontasks should be configured to run in croncluster with the exception of JMSQSEQCONSUMER.SEQQOUT. This cron task should be configured to run in the uicluster where the queue point for this queue has been assigned. This ensures that the queue point is available when users are able to log into uicluster and that messages will be delivered to their destinations regardless of the status of any of the servers in ifcluster or croncluster.
The mxe.crontask.donotrun property can be specified in the maximo.properties file for each cluster to simplify the configuration. Below is an example of what I configured:
Uicluster maximo.properties:
mxe.crontask.dorun=JMSQSEQCONSUMER.SEQQOUT
Ifcluster maximo.properties:
mxe.crontask.donotrun=all
Croncluster maximo.properties:
mxe.crontask.donotrun=JMSQSEQCONSUMER.SEQQOUT
20. Rebuild and redeploy the maximo.ear for each cluster
21. Putting it all together
Reference Link : https://www.ibm.com/support/pages/jms-messaging-high-availability-scalability-and-maximo-integration-framework-using-single-service-integration-bus
Additional information about how the policy maintenance in WebSphere works is included:
https://www.ibm.com/support/knowledgecenter/SSEQTJ_8.5.5/com.ibm.websphere.nd.doc/ae/cjt1004_.html
https://www.ibm.com/support/knowledgecenter/SSEQTJ_8.5.5/com.ibm.websphere.nd.doc/ae/cjt0011_.html