Sterling OMS Non TaskQ Agent

By | 03/07/2018

Sterling OMS Non TaskQ Agent

In this post we are going to see how to create non taskq based agent in Sterling OMS.

Sterling OMS Non TaskQ Agent

Before reading this post we suggest to read below blogs to get better understanding

Agent Server vs Integration Server

Task Q based agent example

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

XYZ_PERSON_INFO

  • 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”

create new transaction

  • Enter Java Class name (com.oms94.agent.CustomerPersonInfoPurgeAgent) under “Time Triggered” tab

New transaction

  • Create New Agent Server (Non Task Q Based) with name as “XYZPersonInfoPurge”

Creating new non task-q based server

weblogic queue configuration

  • Configure Runtime Properties as shown below

Agent Critera Details

  • Configure Criteria Parameters as shown below

Critera Parameter Configuration

  • 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 ?

  1. Agent Criteria Run time parameters, Select “Schedule Trigger message” checkbox and enter time for automatic trigger
  2. triggeragent.cmd <Criteria Parameter>
  3. 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

Register with us to get more updates

OMS Interview Questions

17 thoughts on “Sterling OMS Non TaskQ Agent

  1. Sneha

    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.

    Reply
    1. admin Post author

      Sure will update same in another post. thanks for your comment

      Reply
      1. Sneha

        Thank you. Getting to learn a lot from here.
        Really helpful.

        Reply
        1. admin Post author

          Sneha,
          Thanks lot for your response and support. Lets share and learn together. Happy Learning

          Reply
  2. kaviarasu

    The article is good.

    Can you please post about thread behavior for both task and non task q based agents

    Reply
    1. admin Post author

      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 !!!

      Reply
  3. Ankit

    How does record come into yfs_taskQ table for a custom agent. Where do we configure that?

    Reply
  4. Pingback: Sterling OMS How to override Agent Criteria parameter runtime ? - Learn IBM Sterling Order Management System

  5. Chetan

    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?

    Reply
    1. admin Post author

      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
      select * from yfs_object_lock where for update;

      if lock already taken, above command will fails. This way you can easily find any lock occurred or not.

      Hope helps !!!

      Reply
  6. Mukesh

    NodeList nodeList = XMLUtil.getNodeList(personInfoList, “/PersonInfoList/PersonInfo”);
    PersonInfo element is not there in the personInfoList Document. Is this some error?

    Reply
    1. admin Post author

      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.

      Reply
  7. pallawi

    HI,
    Can you please explain getJob() and exceutejob() in details Please

    Reply
    1. admin Post author

      Shared you link in email with detailed explanation. Please review and let us know any question.

      Reply
      1. Me

        HI,
        Can you please explain getJob() and exceutejob() in details Please

        Reply
  8. Chandana

    HI,
    Can you please explain getJob() and exceutejob() in details Please

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *