This topic provides common usage examples for custom Java automation plug-ins.
External Custom Java Automator that Changes the OSM Task Status
Using OrderDataUpdate Elements to Pass Order Modification Data
A basic internal custom Java automator has the following characteristics:
The name of the custom automation package. For example:
package com.mslv.oms.sample.atm_frame;
Import statements required for this custom automation plug-in. For example:
import com.mslv.oms.automation.plugin.*; import com.mslv.oms.automation.*; import java.rmi.*;
An arbitrary class name that extends AbstractAutomator. For the automation framework to call an internal custom Java automator, the plug-in must extend the AbstractAutomator class. This class resides in the com.mslv.automation.plugin package. For example:
public class MyPlugin extends AbstractAutomator {
The required run method, as dictated by the parent class, AbstractAutomator
protected void run(String inputXML, AutomationContext context) throws com.mslv.oms.automation.AutomationException {
Cast the AutomationContext object to the TaskContext object. This example assumes that the custom automation plug-in is triggered by an automated task, so the code is expecting the context input an argument to be an instance of the TaskContext object.
TaskContext taskContext = (TaskContext)context;
Note:
You can use the TaskContext object to do many things, such as complete the task, suspend it, and so on. For more information about this class, see the OSM Javadocs.Call a method on the TaskContext object to retrieve the task name.
String taskName = taskContext.getTaskMnemonic();
Add any require business logic.
this.performAutomation(taskname);
The following example shows the minimal amount of code required for a custom automation plug-in to run. This example assumes that it is triggered by an automated task.
package com.mslv.oms.sample.atm_frame; import com.mslv.oms.automation.plugin.*; import com.mslv.oms.automation.*; import java.rmi.*; public class MyPlugin extends AbstractAutomator { protected void run(String inputXML, AutomationContext context) throws com.mslv.oms.automation.AutomationException { try { TaskContext taskContext = (TaskContext)context; String taskName = taskContext.getTaskMnemonic(); this.performAutomation(taskname); catch(RemoteException ex) { throw new AutomationException(ex); } catch(AutomationException x) { throw x; } } }
A basic internal custom Java sender has the following characteristics:
The name of the custom automation package. For example:
package com.mslv.oms.sample.atm_frame;
Import statements required for this custom automation plug-in. For example:
import com.mslv.oms.automation.plugin.*; import com.mslv.oms.automation.*; import java.rmi.*;
An arbitrary class name that extends AbstractSendAutomator. For the automation framework to call an internal custom Java sender, the plug-in must extend the AbstractSendAutomator class. This class resides in the com.mslv.automation.plugin package. For example:
public class MyPlugin extends AbstractSendAutomator {
The required run method, as dictated by the parent class, AbstractSendAutomator
protected void run(String inputXML, AutomationContext context) throws com.mslv.oms.automation.AutomationException {
Cast the AutomationContext object to the TaskContext object. This example assumes that the custom automation plug-in is triggered by an automated task, so the code is expecting the context input an argument to be an instance of the TaskContext object.
TaskContext taskContext = (TaskContext)context;
Note:
You can use the TaskContext object to do many things, such as complete the task, suspend it, and so on. For more information about this class, see the OSM Javadocs.Call a method on the TaskContext object to retrieve the task name.
String taskName = taskContext.getTaskMnemonic();
Sets the text for the outbound message, which is sent to the external message queue defined by the automation definition. The custom code does not establish a connection to an external system or send the message; the automation framework handles the connection and sends the message upon completion of the makeRequest method.
outboundMessage.setText("Received task event for task = " + taskName);}
Note:
OSM provides outboundMessage in the OSM automation framework as a JMS message with text content. If you require other message formats or protocols, do not use outboundMessage. You must implement an internal custom java automator or helper class with the required code.The following example shows the minimal amount of code required for a custom automation plug-in that sends data to run. This example assumes that it is triggered by an automated task.
package com.mslv.oms.sample.atm_frame; import com.mslv.oms.automation.plugin.*; import com.mslv.oms.automation.*; import javax.jms.TextMessage; import java.rmi.*; public class MyPlugin extends AbstractSendAutomator { protected void makeRequest(String inputXML, AutomationContext context, TextMessage outboundMessage) throws com.mslv.oms.automation.AutomationException { try { TaskContext taskContext = (TaskContext)context; String taskName = taskContext.getTaskMnemonic(); // optional - You can use this code if you want to define your own correlation ID rather than an autogenerated correlation ID. Correlator correlator = getCorrelator(context); correlator.add(createCustomCorrelationId(taskContext)); outboundMessage.setText("Received task event for task = " + taskName);} catch(javax.jms.JMSException ex) { throw new AutomationException(ex); } catch(RemoteException x) { throw new AutomationException(x); } } private String createCustomCorrelationId(TaskContext taskContext) { // Create a custom correlation ID using task name and unique order history ID // Actual correlation calculation depends on solution logic String corrId = taskContext.getTaskMnemonic() + "-" + String.valueOf(taskContext.getOrderHistoryId()); return corrId; } }
A basic external custom Java automator that changes the OSM task status has the following characteristics:
The name of the custom automation package. For example:
package com.mslv.oms.sample.atm_frame;
Import statements required for this custom automation plug-in. For example:
import com.mslv.oms.automation.plugin.*; import com.mslv.oms.automation.*; import java.rmi.*;
An arbitrary class name that extends AbstractAutomator. For the automation framework to call an external custom Java sender, the plug-in must extend the AbstractAutomator class. This class resides in the com.mslv.automation.plugin package. The name reflects that this example is an external event receiver, receiving information from ASAP. For example:
public class AsapResponseHandler extends AbstractAutomator {
The required run method, as dictated by the parent class, AbstractAutomator.
public void run(String inputXML, AutomationContext task) throws AutomationException {
Cast the AutomationContext object to the TaskContext object. This example assumes that the custom automation plug-in is triggered by an automated task, so the code is expecting the context input an argument to be an instance of the TaskContext object.
TaskContext taskContext = (TaskContext)context;
Note:
You can use the TaskContext object to do many things, such as complete the task, suspend it, and so on. For more information about this class, see the OSM Javadocs.Call a method on the TaskContext object to retrieve the task name.
String taskName = taskContext.getTaskMnemonic();
Logs the information regarding the response that the plug-in is handling. AtmFrameCatalogLogger is available to this example plug-in based on the package in which the plug-in resides. You must replace this with your own solution logic.
AtmFrameCatalogLogger.logTaskEventResponse (taskName,tctx.getOrderId(),tctx.getOrderHistoryId(),inputXML);
Note:
The automation framework keeps track of the order ID and the order history ID of the task that triggered the automation. There are two ways you can get the Order History ID:By parsing the inputXML
By calling the TaskContext.getOrderHistoryId method as shown in this example.
In most cases, these return the same order history ID. However, if you use automation to handle task events, the order history ID obtained from:
Parsing the inputXML returns the order history ID as it was when the task was generated
Calling the TaskContext.getOrderHistoryID method returns the order history ID as it is now (current)
Update the task status by calling a method on the TaskContext object.
tctx.completeTaskOnExit("activation_successful"); }
The following example shows an external custom automator that updates the OSM task status. This example assumes that the automation definition is an external event receiver that is receiving a message from ASAP, and that it is triggered by an automated task.
package com.mslv.oms.sample.atm_frame; import com.mslv.oms.automation.plugin.*; import com.mslv.oms.automation.*; import java.rmi.*; public class AsapResponseHandler extends AbstractAutomator { public void run(String inputXML, AutomationContext task) throws AutomationException { try { TaskContext tctx = (TaskContext)task; String taskName = tctx.getTaskMnemonic(); AtmFrameCatalogLogger.logTaskEventResponse (taskName,tctx.getOrderId(),tctx.getOrderHistoryId(),inputXML); tctx.completeTaskOnExit("activation_successful"); } catch(RemoteException ex) { throw new AutomationException(ex); } catch(AutomationException x) { throw x; } } }
If an automated task sends data to an external system and the external system sends a response back, you may need to update OSM with the data received from the external system.
The following example shows how to update data in OSM. The code is an example of updating OSM with data received from Oracle Communications Unified Inventory Management (UIM) when calling the server extension FRDemo.AssignFacilities.
package com.mslv.oms.sample.atm_frame; import com.mslv.oms.automation.plugin.*; import com.mslv.oms.automation.*; import java.rmi.*; import java.util.*; import java.io.*; import java.net.*; import org.xml.sax.*; import org.w3c.dom.*; import javax.xml.parsers.*; public class UIMResponseHandler extends AbstractAutomator { public void run( String inputXML, AutomationContext task) throws AutomationException { try { TaskContext tctx = (TaskContext)task; String taskName = tctx.getTaskMnemonic(); AtmFrameCatalogLogger.logTaskEventResponse (taskName,tctx.getOrderId(),tctx.getOrderHistoryId(),inputXML); // Using the data returned from UIM, update the OSM order data String updateXml = generateOMSUpdateString(inputXML); tctx.updateOrderData(updateXml); // Complete the OSM task with the correct status tctx.completeTaskOnExit( "success" ); } catch(OrderUpdateException ex) { throw new AutomationException( ex ); } catch(RemoteException ex) { throw new AutomationException( ex ); } catch(AutomationException x ) { throw x; } } static private String generateOMSUpdateString(String inputXML) { StringBuffer osmUpdate = new StringBuffer(""); try { osmUpdate = new StringBuffer ("<OrderDataUpdate xmlns=\"http://www.w3.org/2001/XMLSchema\""+ " xmlns:xs=\"http://www.w3.org/2001/XMLSchema\"" + " xmlns:odu=\"http://www.oracle.com/OMS/OrderDataUpdate\/"/" + " targetNameSpace=\"http://www.oracle.com/OMS/OrderDataUpdate\/">"); // Use updates from UIM to update OSM osmUpdate.append("<AddMandatory>true</AddMandatory>"); DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance(); DocumentBuilder parser = docBuilderFactory.newDocumentBuilder(); Document doc = parser.parse(new StringBufferInputStream(inputXML)); Element root = doc.getDocumentElement(); root.normalize(); NodeList a_site_list = root.getElementsByTagName("a_site information"); NodeList a_site_data = a_site_list.item(0).getChildNodes(); for(int i=0;i<a_site_data.getLength();i++) { Element e = (Element)a_site_data.item(i); osmUpdate.append("<Add path=\"/a_site_information/"); osmUpdate.append(e.getTagName()); osmUpdate.append("\">"); osmUpdate.append(e.getFirstChild().getNodeValue()); osmUpdate.append("</Add>"); } NodeList z_site_list = root.getElementsByTagName("z_site_information"); NodeList z_site_data = z_site_list.item(0).getChildNodes(); for(int i=0;i<a_site_data.getLength();i++) { Element e = (Element)a_site_data.item(i); osmUpdate.append("<Add path=\"/z_site_information/"); osmUpdate.append(e.getTagName()); osmUpdate.append("\">"); osmUpdate.append(e.getFirstChild().getNodeValue()); osmUpdate.append("</Add>"); } osmUpdate.append("</OrderDataUpdate>"); System.out.println(omsUpdate.toString()); } catch(Exception e) { System.out.println(e.getMessage()); } return omsUpdate.toString(); } }
The following code snippets from this example show:
How to display where OSM data is updated, using XML input to describe which data nodes to update.
tctx.updateOrderData(updateXml);
How to build the OrderDataUpdate XML string to update the data in OSM using data garnered by parsing the UIM XML. See "Using OrderDataUpdate Elements to Pass Order Modification Data". This differs for every order template and every external system. This code represents the translation step where you convert the data from the format of an external system to the format that OSM expects.
static private String generateOMSUpdateString(String inputXML) { StringBuffer osmUpdate = new StringBuffer(""); try { osmUpdate = new StringBuffer ("<OrderDataUpdate xmlns=\"http://www.w3.org/2001/XMLSchema\""+ " xmlns:xs=\"http://www.w3.org/2001/XMLSchema\"" + " xmlns:odu=\"http://www.oracle.com/OMS/OrderDataUpdate\/"/" + " targetNameSpace=\"http://www.oracle.com/OMS/OrderDataUpdate\/">"); // Use updates from UIM to update OSM osmUpdate.append("<AddMandatory>true</AddMandatory>"); DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance(); DocumentBuilder parser = docBuilderFactory.newDocumentBuilder(); Document doc = parser.parse(new StringBufferInputStream(inputXML)); Element root = doc.getDocumentElement(); root.normalize(); NodeList a_site_list = root.getElementsByTagName("a_site information"); NodeList a_site_data = a_site_list.item(0).getChildNodes(); for(int i=0;i<a_site_data.getLength();i++) { Element e = (Element)a_site_data.item(i); osmUpdate.append("<Add path=\"/a_site_information/"); osmUpdate.append(e.getTagName()); osmUpdate.append("\">"); osmUpdate.append(e.getFirstChild().getNodeValue()); osmUpdate.append("</Add>"); } NodeList z_site_list = root.getElementsByTagName("z_site_information"); NodeList z_site_data = z_site_list.item(0).getChildNodes(); for(int i=0;i<a_site_data.getLength();i++) { Element e = (Element)a_site_data.item(i); osmUpdate.append("<Add path=\"/z_site_information/"); osmUpdate.append(e.getTagName()); osmUpdate.append("\">"); osmUpdate.append(e.getFirstChild().getNodeValue()); osmUpdate.append("</Add>"); } osmUpdate.append("</OrderDataUpdate>"); System.out.println(omsUpdate.toString()); } catch(Exception e) { System.out.println(e.getMessage()); } return omsUpdate.toString(); }
The structure of the XML document to update OSM data is as follows:
<OrderDataUpdate xmlns=\"http://www.w3.org/2001/XMLSchema\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" xmlns:odu=\"http://www.oracle.com/OMS/OrderDataUpdate\/" targetNameSpace=\"http://www.oracle.com/OMS/OrderDataUpdate\/"> <AddMandatory>true</AddMandatory> <Add path=\"/service_details/new_number\">98765</Add> <Update path=\"/customer_details/service_address/street\">55 Updated St</Update> <Delete path=\"/service_details/current_account_number\"></Delete> </OrderDataUpdate>
This example illustrates adding a data node (Add path), updating a data node (Update path), and deleting a data node (Delete path).
How to specify a mandatory parameter. If set to true, the following rules apply:
osmUpdate.append("<AddMandatory>true</AddMandatory>");
If you delete a mandatory node, AddMandatory replaces the node and populates it with the default value.
If the update is missing a mandatory node, AddMandatory adds the missing node and populates it with the default value.
Note:
If you add a mandatory field, but do not include a value, AddMandatory will not add a default value and the request will generate an error-error code 200.You use OrderDataUpdate XML elements to pass data add, modify and delete data nodes in an order.
OrderDataUpdate elements can be passed as a parameter to updateOrderData(). XSL translations whose results are passed to setUpdateOrder() must be in OrderDataUpdate format. See the OSM Javadocs for details on both methods. You can also pass OrderDataUpdate format elements to the DataChange Web Service (see the SDK schema OrderManagementWS.xsd) and UpdateOrder.request XML API call (see the SDK schema oms-xmlapi.xsd).
For update and delete operations on multi-instance nodes, you must specify the order node index as it exists in the input XML. Specify the order node index as "[@index='index_value']" where index_value is the order node index.
The following example shows how to specify the addition of an order node with OrderDataUpdate. The path attribute identifies the parent node under which to add the element:
<OrderDataUpdate> <Add path="/"> <ProvisioningOrderResponse> <OrderInformation> <OrderNumber>1238723</OrderNumber> </OrderInformation> </ProvisioningOrderResponse> </Add> </OrderDataUpdate>
The following example shows a combined update and delete operation on a multi-instance node using OrderDataUpdate. In Delete attributes, the path attribute identifies the data to delete. In Update attributes, the path attribute identifies the data to update. Indexes are required on Update and Delete attributes when modifying multi-instance nodes. Note how the order node index values are specified in the Update and Delete attributes.
<OrderDataUpdate> <Delete path="/client_info/address[@index='80132']/city" /> <Update path="/client_info/address[@index='76579']/city">Newark</Update> <Update path="/customer_details/service_address/street">55 Updated St</Update>" <Delete path="/service_details/current_account_number"></Delete> </OrderDataUpdate>
See "External Custom Java Automator that Updates Order Data" for an example in which OrderDataUpdate XML data is created dynamically within Java code and passed to UpdateOrderData().
The schema for OrderDataUpdate is as follows:
<?xml version="1.0" encoding="UTF-8"?> <schema targetNamespace="http:// www.metasolv.com/OMS/OrderDataUpdate" xmlns:odu="http://www.metasolv.com/ OMS/OrderDataUpdate" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"> <element name="OrderDataUpdate"> <complexType> <choice maxOccurs="unbounded"> <element ref="odu:Add"/> <element ref="odu:Delete"/> <element ref="odu:Update"/> </choice> </complexType> </element> <element name="Add"> <annotation> <documentation>It contains a node to be added. The path attribute identifies the parent node under which to add the element.</documentation> </annotation> <complexType> <sequence> <any/> </sequence> <attribute name="path" type="string" use="required"/> </complexType> </element> <element name="Delete"> <annotation> <documentation>It contains a node to be deleted. The path attribute identifies the node to delete.</documentation> </annotation> <complexType> <attribute name="path" type="string" use="required"/> </complexType> </element> <element name="Update"> <annotation> <documentation>It contains a node to update. The path attribute identifies the node to update.</documentation> </annotation> <complexType> <simpleContent> <extension base="string"> <attribute name="path" type="string" use="required"/> </extension> </simpleContent> </complexType> </element> </schema>
Automation simplifies the process of sending messages to external systems. The automation framework does the following:
Assumes the protocol is JMS. The products (Siebel, OSM, UIM, ASAP, IP Service Activator) all have JMS APIs.
Takes care of establishing and maintaining the various JMS connections.
Constructs the JMS messages, setting the required message properties.
Guarantees delivery of the message and handles any errors or exceptions. It retries until the message is delivered.
Automatic message correlation.
Poison message handling.
An OSM event that is sent to an external system follows this process flow:
OSM runs an automation that triggers an automation plug-in.
Internally, the automation framework maps the plug-in, using the automationMap.xml configuration, onto custom business logic and calls the makeRequest method on the custom automator class.
The makeRequest method performs some business logic and sets the content of the outbound message.
The automation framework adds properties to the outbound message to aid in correlating external system responses to requests.
The automation framework uses information from the automationMap.xml to send the JMS message to the JMS queue representing the external system.
The following example shows a custom automation plug-in that sends data to an external system.
package com.mslv.oms.sample.atm_frame; import com.mslv.oms.automation.plugin.*; import com.mslv.oms.automation.*; import javax.jms.TextMessage; import java.rmi.*; public class ObjectelPlugin extends AbstractSendAutomator { protected void makeRequest(String inputXML, AutomationContext context, TextMessage outboundMessage) throws com.mslv.oms.automation.AutomationException { try { TaskContext taskContext = (TaskContext)context; String taskName = taskContext.getTaskMnemonic(); AtmFrameCatalogLogger.logTaskEvent(taskName, taskContext.getOrderId(), taskContext.getOrderHistoryId(), inputXML); // // Set the outgoing message // String xmlRequest = "<Message type=\"ni\"><iLibPlus:findFunctionalPortOnLocation.Request xmlns:iLibPlus=\"http://www.oracle.com/objectel\/"><location><DS><AG2ObjectID>189438</AG2ObjectID><AG2ParentID>189428</AG2ParentID><CLLIX>XML.CO.1</CLLIX><SiteName>XML.CO.1</SiteName></DS></location><feType>PP</feType><portType>$FEP</portType><selectionMethod>LOAD_BALANCE</selectionMethod><portSelectionAttribName><string>AG2ObjectID</string><string>AG2ParentID</string><string>AG2PortLabel</string></portSelectionAttribName><portSelectionAttribValue><string>189508</string><string>189478</string><string>F-31-OC-48</string></portSelectionAttribValue><portUpdateAttribName/><portUpdateAttribValue/></iLibPlus:findFunctionalPortOnLocation.Request></Message>"; outboundMessage.setText( xmlRequest ); } catch( javax.jms.JMSException x ) { throw new AutomationException( x ); } catch(RemoteException ex){ throw new AutomationException( ex ); } } }
The following code snippets from this example show:
how to generate an output XML string. In this example it is hard coded. In a business case you would use business logic to transform OSM data into what the external system expects
String xmlRequest = "<Message type=\"ni\"><iLibPlus:findFunctionalPortOnLocation.Request xmlns:iLibPlus=\"http://www.oracle.com/objectel\/"><location><DS><AG2ObjectID>189438</AG2ObjectID><AG2ParentID>189428</AG2ParentID><CLLIX>XML.CO.1</CLLIX><SiteName>XML.CO.1</SiteName></DS></location><feType>PP</feType><portType>$FEP</portType><selectionMethod>LOAD_BALANCE</selectionMethod><portSelectionAttribName><string>AG2ObjectID</string><string>AG2ParentID</string><string>AG2PortLabel</string></portSelectionAttribName><portSelectionAttribValue><string>189508</string><string>189478</string><string>F-31-OC-48</string></portSelectionAttribValue><portUpdateAttribName/><portUpdateAttribValue/></iLibPlus:findFunctionalPortOnLocation.Request></Message>";
how to set the output data:
outboundMessage.setText( xmlRequest );
How this code does not establish a connection to an external system or send a message. After the data is set in the code, the message is automatically sent upon exit of the makeRequest method.
In Message Property Correlation, the following steps describe how responses from external systems are handled.
The plug-in populates the message content.
The plug-in sets a property on the outbound JMS message, with name of the value set for correlationproperty in the automationMap.xml file, and a value decided by the business logic. For example, you could use this to correlate on a reference number.
If the value of the correlationproperty in the automationMap.xml file is set to the value JMSCorrelationID, the plug-in is not required to set the property on the outbound message (as described in Step 2). The automation framework does this automatically.
The automation framework saves the message properties set for each message with the event information.
The automation framework sets the replyTo property on the JMS message.
The external system copies the properties on the request message to the response message.
The external system sends the message to the reply queue specified in the automationMap.xml file.
The automation framework uses the configuration in the automationMap.xml file to map messages from external systems to plug-ins. The plug-ins are automators written by system integrators. Configuration of an automator for receiving messages from an external system are defined within Design Studio and saved to the automationMap.xml file.
The automation framework uses the message properties of the response, plus the correlation information saved in step four above, to reload a Context for the response message.
The run method of the external system automator is called and is passed the Context created in step 9.
The automator performs business logic, such as completing the task.
The following example shows a custom automation plug-in that handles and processes response messages from an external system.
package com.mslv.oms.sample.atm_frame; import com.mslv.oms.automation.plugin.*; import com.mslv.oms.automation.*; import java.rmi.*; public class UIMResponseHandler extends AbstractAutomator { public void run( String inputXML, AutomationContext task) throws AutomationException { try { TaskContext tctx = (TaskContext)task; tctx.completeTaskOnExit( "success" ); } catch(RemoteException ex){ throw new AutomationException( ex ); } catch(AutomationException x ) { throw x; } } }
This automation plug-in does not need to send JMS messages to any system, so it extends AbstractAutomator and is intended to process Task automation responses, so it casts the Context to a TaskContext then completes the task.
The following example shows what the external system is expected to do for the message property correlation to work.
public void sendMessage(Message originalMessage) { try { // // Set up the JMS connections // QueueConnectionFactory connectionFactory = (QueueConnectionFactory)jndiCtx.lookup(connectionFactoryName); QueueConnection queueConnection = connectionFactory.createQueueConnection(); QueueSession queueSession = queueConnection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE); Queue replyQueue = (Queue)originalMessage.getJMSReplyTo(); QueueSender queueSender = queueSession.createSender(replyQueue); // // Create the message // TextMessage textMessage = queueSession.createTextMessage(((TextMessage)originalMessage).getText()); textMessage.setStringProperty("MESSAGE_NAME","ActivationResponse"); textMessage.setJMSCorrelationID(originalMessage.getJMSCorrelationID()); // // Send the message // queueSender.send(textMessage, javax.jms.DeliveryMode.PERSISTENT, javax.jms.Message.DEFAULT_PRIORITY, 1800000); } catch(javax.jms.JMSException ex){ ex.printStackTrace(); } catch(javax.naming.NamingException ex){ ex.printStackTrace(); } }
The following code snippets from this example show:
how the external system chooses which JMS destination to send the reply to.
Queue replyQueue = (Queue)originalMessage.getJMSReplyTo(); QueueSender queueSender = queueSession.createSender(replyQueue);
the external system setting a property that identifies the nature of the JMS message. This implies that the automation was defined with a message property selector select statement that matches these parameters.
textMessage.setStringProperty("MESSAGE_NAME","ActivationResponse");
the external system echoing the correlation information onto the reply message. This implies that the automation was defined to correlate based on JMSCorrelationID.
textMessage.setJMSCorrelationID(originalMessage.getJMSCorrelationID());