Skip to Content

Customized Scheduling for integrations with CPI

Start Timer is the mechanism for self-triggered integrations in CPI. With its many inbuilt configurations, there still are scenarios that the present offers fails to provide. This blog utilizes the power of Scripts and Router in demonstrating how custom schedule configurations can be accomplished in a simple way.

How?

“Execute on last day of every month” is once such trigger scenario which we will achieve using a combination of JavaScript step and a Router step. The scenario is quite simple where a reminder mail should be sent to a user on last day of every month.

Let’s model this scenario step by step as follows:

  1. Drag and Drop a Start Timer step into the Integration Process.
  1. Configure it to run Daily (as our scenario is having date as the filtering parameter).
  2. Put a Script step in the Integration Process and connect Timer to Script (Here we are using JavaScript but either of the two i.e., JavaScript or GroovyScript can be used whichever the user is comfortable with).
    importClass(com.sap.gateway.ip.core.customdev.util.Message);
    importClass(java.util.HashMap);
    
    /**
     * [Default Generated Function]
     * @param  {[object]} message [The message being transferred]
     */
    function processData(message) {
        var dateObj = new Date();
        var currentDate = dateObj.getDate();
        if (dateObj && currentDate === getLastDateOfTheMonth(dateObj.getMonth(), dateObj.getYear())) {
            return getMessage(message, true);
        }
        return getMessage(message, false);    
    }
    
    /**
     * [Get message to be passed on from script step]
     * @param  {[object]}  message [The message being transferred]
     * @param  {[boolean]} custom  [Specifes if the day is the Last day or not]
     */
    function getMessage(message, custom) {
        //body
        var body = message.getBody();
        message.setBody(body + " modified from js");
        //headers  
        var map = message.getHeaders();
        var value = map.get("oldHeader");
        message.setHeader("oldHeader", value + "modified");
        message.setHeader("newHeader", "newHeader");
                   //properties 
        map = message.getProperties();
        value = map.get("oldProperty");
        message.setProperty("oldProperty", value + "modified");
        message.setProperty("newProperty", "newProperty");
        if(!custom) {
          message.setProperty("execute", custom);
        }
        return message;
    }
    
    function getLastDateOfTheMonth(month, year) {
        var d = new Date(year, (month + 1), 0);
        return d.getDate();
    }​
  3. Modify the existing script to add a header/property by the name “execute” (any name can be given here) with value “false” (again this can have any value that you would like to use as truth value) when the current day is not the last day of the month. Don not set any header/property in case the current day is last day of the month. The code implementation depends on the user. For reference purpose the following JavaScript snippet can be used.
  4. Save the Script and now add a Router step to the flow and connect the Script step to the Router.
  5. The Router will have two outgoing branches:
    • First branch will be the default branch and name it some interpretable name (we are using “Execute”).
    • For the Second branch provide some interpretable name (we are using “DoNotExecute”) and configure ‘Expression Type’ as ‘Non-XML’ and provide the condition as “${property.execute} = ‘false’” or “${header.execute} = ‘false’”  (depending on whichever you have used in Script with correct name).
  6. Connect the “DoNotExecute” branch to an End Message step.
  7. Connect the “Execute” branch to the process you want to execute on Last Day of Every Month. (A process call can be used to call another Integration process containing the actual logic to be implemented). Here we connect it to and End Message which is connected to a Receiver via Mail Adapter as we need to send the mail on Last Day of Every Month. Sample overview of the scenario is as shown below.
  8. Save the scenario and deploy it.

The above example can be followed and modified by the users as per requirement to achieve new custom trigger configurations.

On similar lines, I tried a few more scenarios that came to my mind which involve and are listed below:

S. No. Scenario Code Snippet
1. Run every even week in a month.
function runEveryEvenWeekInAMonth(message) {
    var dateObj = new Date();
    if(getWeekNumberForTheMonth(dateObj)%2 !== 0) {
        return processData(message, true);
    }
    return processData(message, false);
}

function getWeekNumberForTheMonth(dateObj) {
    var date = dateObj.getDate();
    var day = dateObj.getDay();
    return Math.ceil((date - 1 - day) / 7); 
}
2. Run every odd week in a month.
function runEveryOddWeekInAMonth(message) {
    var dateObj = new Date();
    if(getWeekNumberForTheMonth(dateObj)%2 === 0) {
        return processData(message, true);
    }
    return processData(message, false);
}

function getWeekNumberForTheMonth(dateObj) {
    var date = dateObj.getDate();
    var day = dateObj.getDay();
    return Math.ceil((date - 1 - day) / 7); 
}​
3. Run on 45th minute of every hour.
function runEvery45thMinuteOfAnHour(message) {
	var dateObj = new Date();
	if((dateObj.getMinutes()%45) === 0) {
		return true;
	} else {
		return false;
	}
}
4. Run on Weekends.
function runOnWeekends(message) {
	var dateObj = new Date();
	var day = dateObj.getDay();
	if(day === 0 || day === 6) {
		return true;
	} else {
		return false;
	} 
}
5. Run on Weekdays.
function runOnWeekdays(message) {
	var dateObj = new Date();
	var day = dateObj.getDay();
	if(day !== 0 && day !== 6) {
		return true;
	} else {
		return false;
	} 
}
6. Run on Last Weekday of the Month
function getLastWeekdayOfTheMonth(year, month) {
	var dateObj = new Date(year, (month + 1), 0);
	var day = dateObj.getDay();
	if (day > 0 && day < 6) {
		return dateObj;
	} else {
		if (day === 6) {
			return dateObj.setDate(dateObj.getDate() - 1);
		} else {
			return dateObj.setDate(dateObj.getDate() - 2);
		}
	}
}

 

Therefore, by using a combination of Scheduler, a Script and a Router we can easily achieve trigger scenarios which are otherwise not possible to achieve via using Scheduler only.

14 Comments
You must be Logged on to comment or reply to a post.
  • Hi,

    Please correct the logic for:

     

    Run on Weekdays.
    function runOnWeekdays(message) {
    	var dateObj = new Date();
    	var day = dateObj.getDay();
    	if(day !== 0 && day !== 6) {
    		return true;
    	} else {
    		return false;
    	} 
    }

     

    😉

  • Hi Apurva Apurva Sahay ,

    Thanks a lot for sharing the information. I have a requirement same as this but there are times were we want to run the package manually like middle of the month based on user request. How that can be handled with this routing logic setup ?

    thanks and regards,

    Murugavel

  • Hi Apurna, thank you for sharing.

    My requirement is to run the iflow:

    -every 10 min between 06:00 am – 08:00 am in time zone UTC+10

    -every hour between 08:00 am – 06:am in time zone UTC+10

    Hence 2 intervals within a day.

    Is this achievable using the script? Otherwise I can only think of copying the iFlow for the second schedule.

    Thank you for any suggestion.

     

     

    • Hi Sunny,

       

      There are multiple ways to achieve this behavior.

      You can put your main integration logic in a local integration process which will be called only when the condition in the scripts is satisfied.

      Also could you please clarify if the second schedule “Execute every hour between 08:00 am – 06:am in time zone UTC+10” is every hour between 08:00 am and 06:00 pm or 06:00 am next day ?

       

      Thanks

  • Hi Apurva,

    Thanks much for sharing the information!

    I have a requirement to schedule it once on quarterly basis on a particular day of every Quarter. How this can be handled.

    Thanks,

    Ezhil.

    • Hi Ezhil,

       

      You can configure the scheduler to run Monthly and in the script you can check the current month and if it is the quarter month you can return “execute” as true else it will be false.

       

      Hope this helps.

       

       

  • Hi Apurva,

    We have requirement to run the iflow daily at 6 PM IST from Monday – Saturday, and at 5:15 PM IST only on Sundays.

    Can you please suggest the best way to achieve this ?

    Regards,

    Debashis

  • Hi Apurva Sahay,

    Thank you for sharing. We have a requirement to run the iflow :

    Monday – 7AM, 8AM, 9AM, 10AM, 11AM, 12PM and 4PM

    Tuesday to Sunday – 7AM.

    Can you please help how to handle this.

    Thanks & Regards,

    Poushali Bhandari

  • Hi Apurva,

    Thanks for this useful info.

    I have a requirement where the interface should execute at the 30th Minute.  In CPI, currently we don’t have 30 min interval option.

    If we choose to run the interface every hour, the first execution happens at 00:00. Instead of this it should run 00:30, 01:30, 02:30 so on.. Could you please let me know if this can be achieved.

     

    First%20Run%20of%20the%20interface%20should%20happen%20at%200030%20instead%20of%200000%20We%20do%20not%20have%20a%20standard%20option%20in%20CPI%20for%20this.

    First Run of the interface should happen at 0030 instead of 0000 We do not have a standard option in CPI for this.

    /
    First%20Run%20of%20the%20interface%20should%20happen%20at%200030%20instead%20of%200000%20We%20do%20not%20have%20a%20standard%20option%20in%20CPI%20for%20this.