Sterling OMS Non TaskQ Agent
In this post we are going to see how to create non taskq based agent in Sterling OMS.
Before reading this post we suggest to read below blogs to get better understanding
Agent Server vs Integration Server
Sterling OMS Non TaskQ Agent
When to implement with Non TaskQ Agent ?
Task Q (YFS_AGENT_Q) based agents are good for processing order or shipment with particular transaction. For example Schedule Transaction (SCHEDULE.0001) for particular order executed as taskq based agent. For task q based agent we need to implement only executeTask() method. Implementation of getJobs() method taken care by the product.
Task Q based transaction good when you have one of following key
- OrderHeaderKey
- OrderReleaseKey
- ReceiptHeaderKey
- ShipmentGroupKey
- ShipmentKey
- WorkOrderKey
Non Task Q agents are good for processing records which does have relationship order or shipment. For example an custom table purge has to be implemented as Non Task Q agent. For non task q based agent we need to implement getJob() and executeJob() methods.
Requirement :
- New custom table should be created with given data structure
- Should have option to run purge any given time or particular time interval (N Minutes)
- Should retain N number of days records and remove remaining records
Steps involved in creating Non Task Q Agent ?
- Create new custom table
- Create 5 Services to access Extended Database API
- Create Test Records into database by calling Create Service
- Create java Class which extends YCPBaseAgent and overrides getJobs() and executeJob() methods
package com.oms94.agent;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.List;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import com.oms94.util.XMLUtil;
import com.yantra.interop.japi.YIFApi;
import com.yantra.interop.japi.YIFClientFactory;
import com.yantra.ycp.japi.util.YCPBaseAgent;
import com.yantra.yfc.dom.YFCDocument;
import com.yantra.yfc.dom.YFCElement;
import com.yantra.yfs.japi.YFSEnvironment;
public class CustomPersonInfoPurgeAgent extends YCPBaseAgent {
protected static YIFApi api = null;
public List<Document> getJobs(YFSEnvironment env, Document criteria,
Document lastMessageCreated) throws Exception {
System.out.println("getJobs method:start");
String sLastPersonInfoKey = null;
List<Document> listDocuments = new ArrayList<Document>();
if(criteria != null){
System.out.println("getJobs:criteria:" + XMLUtil.getStringFromDocument(criteria));
}
if(lastMessageCreated != null){
System.out.println("getJobs:lastMessageCreated:" +
XMLUtil.getStringFromDocument(lastMessageCreated));
if (lastMessageCreated != null) {
YFCElement element = YFCDocument.getDocumentFor(lastMessageCreated)
.getDocumentElement();
sLastPersonInfoKey = element.getAttribute("PersonInfoKey");
}
} else {
System.out.println("getJobs:lastMessageCreated:null");
}
Element criteriaElement = criteria.getDocumentElement();
Document personInfoList = getApi().executeFlow(env, "getXYZPersonInfoList",
createXYZPersonInfoListInput(criteriaElement.getAttribute("RetentionDays"),
criteriaElement.getAttribute("NumRecordsToBuffer"), sLastPersonInfoKey));
NodeList nodeList = XMLUtil.getNodeList(personInfoList, "/PersonInfoList/PersonInfo");
if(nodeList != null) {
String personInfoKey = null;
for(int i=0;i<nodeList.getLength();i++) {
Element element = (Element)nodeList.item(i);
personInfoKey = element.getAttribute("PersonInfoKey");
if(personInfoKey != null) {
listDocuments.add(createPersonInfoDocument(personInfoKey));
}else {
System.out.println("personInfoKey returned null");
}
}
}
System.out.println("getJobs method:end");
return listDocuments;
}
private static Document createPersonInfoDocument(String personInfoKey) {
YFCElement organization = YFCDocument.createDocument("PersonInfo")
.getDocumentElement();
organization.setAttribute("PersonInfoKey", personInfoKey);
return organization.getOwnerDocument().getDocument();
}
@Override
public void executeJob(YFSEnvironment env, Document msgToProcess) throws Exception {
System.out.println("executeJob method:start");
if(msgToProcess != null) {
System.out.println("executeJob: " + XMLUtil.getStringFromDocument(msgToProcess));
getApi().executeFlow(env, "deleteXYZPersonInfo",msgToProcess);
}
System.out.println("executeJob method:end");
}
private Document createXYZPersonInfoListInput(String retentionDays, String numRecordsToBuffer, String sLastPersonInfoKey) {
YFCElement personInfoList = YFCDocument.createDocument("PersonInfoList")
.getDocumentElement();
if(numRecordsToBuffer != null && numRecordsToBuffer.length() >0) {
personInfoList.setAttribute("MaximumRecords", numRecordsToBuffer);
}
personInfoList.setAttribute("CreatetsQryType", "DATERANGE");
personInfoList.setAttribute("FromCreatets", getDateWithDaysAdded("365")); // Consider last year as start date
personInfoList.setAttribute("ToCreatets", getDateWithDaysAdded(retentionDays)); // current date - retentionDays
if(sLastPersonInfoKey != null && sLastPersonInfoKey.length() >0) {
personInfoList.setAttribute("PersonInfoKey", sLastPersonInfoKey);
personInfoList.setAttribute("PersonInfoKeyQryType", "GT"); // How to use > value
}
YFCElement orderBy = personInfoList.createChild("OrderBy").createChild("Attribute");//How to add OrderBy in complex query
orderBy.setAttribute("Name", "PersonInfoKey");
orderBy.setAttribute("Desc", "N");
System.out.println("createXYZPersonInfoListInput:" + XMLUtil.getStringFromDocument(personInfoList.getOwnerDocument().getDocument()));
return personInfoList.getOwnerDocument().getDocument();
}
private String getDateWithDaysAdded(String daysToAdd) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
Calendar currentCal = new GregorianCalendar();
if(daysToAdd != null && !"0".equals(daysToAdd)) {
currentCal.add(Calendar.DATE, Integer.parseInt(daysToAdd) * -1);
}
String sNewDate = sdf.format(currentCal.getTime());
return sNewDate;
}
protected YIFApi getApi() throws Exception {
if(api == null) {
api = YIFClientFactory.getInstance().getLocalApi();
}
return api;
}
}
- Create New Time Triggered Transaction by selecting “Do not derive from an abstract transaction”
- Enter Java Class name (com.oms94.agent.CustomerPersonInfoPurgeAgent) under “Time Triggered” tab
- Create New Agent Server (Non Task Q Based) with name as “XYZPersonInfoPurge”
- Create New Queue in Weblogic server with name XYZPersonInfoPurge
- Configure Runtime Properties as shown below
- Configure Criteria Parameters as shown below
- Start Agent Server
- agentserver.cmd XYZPersonInfoPurge
- Trigger message : Required only when schedule trigger message checkbox not selected
- triggeragent.cmd XYZ_PERSON_INFO_PURGE
XML Messages into Queue
| Message Name | XML Message | Remarks |
| Trigger Message | <Message FlowName=”XYZ_PERSON_INFO_PURGE” TransactionKey=”20180210002704206907″> <AgentDetails> <MessageXml Action=”Get” NumRecordsToBuffer=”5″ RetentionDays=”2″/> </AgentDetails> </Message> |
NumRecordsToBuffer and RetentionDays from Criteria Configuration |
| First Get Job Method | Trigger message received into getJobs() | |
| N+1 Get Job Method | <Message FlowName=”XYZ_PERSON_INFO_PURGE” TransactionKey=”20180210002704206907″> <AgentDetails> <MessageXml Action=”Get” NumRecordsToBuffer=”2″ RetentionDays=”2″/> </AgentDetails> <LastMessage LastMessagesAdded=”2″> <PersonInfo PersonInfoKey=”2018021019400339207404″/> </LastMessage> </Message> |
<LastMessage> added after adding N number of execute messages.
Last fetched execute message PersonInfoKey been added in LastMessage |
| Execute Job Method | <?xml version=”1.0″ encoding=”UTF-8″?> <PersonInfo PersonInfoKey=”2018021000574424207023″/> |
We will create another post to explain in detail how getJobs() and executeJob() methods works.
Interview Questions
What are all the different ways to do trigger message ?
- Agent Criteria Run time parameters, Select “Schedule Trigger message” checkbox and enter time for automatic trigger
- triggeragent.cmd <Criteria Parameter>
- By calling triggerAgent standard API with transaction name
How multi-thread works in case of non-task-q based implementation ?
- getJobs() : Always single thread; lock created using YFS_OBJECT_LOCK table entry
- executeJob() : Multiple Thread; Thread count based on configuration
Is it possible to override the criteria parameters when using triggerAgent ?
- Only for few transactions (Example : RTAM) user can override the criteria parameters from command line
What happens when triggerAgent been called with Criteria Name and agent server is not running ?
- Trigger message generated and stays in queue (As per agent runtime properties configuration)
- Next time when agent server starts, trigger message fired
Non-TaskQ based agent supports multi-thread and multiple-instances ?
- Yes, multi-thread and multiple-instance supported by Non-TaskQ based agent








Please explain how a taskq agent works as well. During creation , schedule and other transaction how the taskq table gets populated and how is the available date maintained.
Sure will update same in another post. thanks for your comment
Thank you. Getting to learn a lot from here.
Really helpful.
Sneha,
Thanks lot for your response and support. Lets share and learn together. Happy Learning
The article is good.
Can you please post about thread behavior for both task and non task q based agents
Kavi,
Agent Server : getJobs() — always single threaded and executeJobs() multiThreaded
Integration Server : For every thread count new object will be created
Hope this helps. Happy Learning !!!
How does record come into yfs_taskQ table for a custom agent. Where do we configure that?
Ankit,
Below post has answer to your question.
http://activekite.com/2017/11/12/sterling-oms-taskq-based-agent-server/
you can use manageTaskQueue API to create record into yfs_task_q table. Or it has to be part of pipeline transaction
Pingback: Sterling OMS How to override Agent Criteria parameter runtime ? - Learn IBM Sterling Order Management System
A getJobs thread holds a lock for a particular criteria in yfs_object_lock table? How can we know an agent has locked it currently from the table?
Hi,
Really sorry for delayed response.
This table lock happens very quickly and get released faster. If you try to run SQL command in database for update;
select * from yfs_object_lock where
if lock already taken, above command will fails. This way you can easily find any lock occurred or not.
Hope helps !!!
NodeList nodeList = XMLUtil.getNodeList(personInfoList, “/PersonInfoList/PersonInfo”);
PersonInfo element is not there in the personInfoList Document. Is this some error?
personInfo element is not there means you don’t have record in the database. Can you please query the table and find if any record found ? You can use API tester to find if any record present or not.
HI,
Can you please explain getJob() and exceutejob() in details Please
Shared you link in email with detailed explanation. Please review and let us know any question.
HI,
Can you please explain getJob() and exceutejob() in details Please
HI,
Can you please explain getJob() and exceutejob() in details Please