Skip to Content
Technical Articles

Customized Scheduling for integrations in SAP Cloud Integration

Start Timer is the mechanism for self-triggered integrations in SAP Cloud Integration. 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.

19 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 Debashis,

       

      I see that you need two different schedules altogether for your case:

      • Run at 6PM IST Monday-Saturday

             

      • Run at 5:15 PM IST on Sunday

       

      There are two possible approaches to achieve this:

      Approach 1:

      1. Create one integration flow with your actual logic and expose it using a HTTP Sender or Process Direct Sender.
      2. Create two timer based integration flows with the above shown configurations which will invoke your master integration created in step 1.

      Approach 2:

      1. You can configure your scheduler to trigger your scenario every 5 min from 17:00 to 19:00 Hrs daily.
      2. Use the script router combination as shown in the blog with script setting the execute property true only when the current time satisfies your requirement.

      Both approaches should solve your problem. You can pick whichever suits your case.

       

      Regards,

      Apurva

  • 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 Poushali,

      Using the Script-Router combination you can achieve this as follow:

      1. Configure your scheduler to trigger your scenario every 1 Hr from 7 AM to 5 PM daily.
      2. Use the script to set the "execute" property true only when the current time satisfies your requirement.

      Regards,

      Apurva

  • 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.
    • Hi Chethan,

       

      From your question I understand that you want to configure the start time of the scheduler in your interface to 00:30 and then run every 1 Hr i.e., 00:30, 01:30, 02:30, 03:30 and so on.

      It is possible to achieve this with Script-Router combination as follows:

      1. Configure your scheduler to trigger every 30 mins for the required duration.
      2. In the script you need to check if the minutes component in the current time object is 30 as shown below.
        function runEvery30thMinuteOfAnHour(message) {
        	var dateObj = new Date();
                return (dateObj.getMinutes() === 30);
        }​

      This should give you the desired trigger pattern.

       

      Regards,

      Apurva

  • Hi Apurva,

    We have a requirement where we need to trigger Purchase Order Details (Create, Update or Delete) to a thirdy party via REST APIs, they want CPI to initiate the call for triggering the data from the S/4 HANA system is this achievable using the Timer Functionality.

    Appreciate your help.

    Regards,

    Sahaj

    • Hi Sahaj,

      If I understand your use case correctly you want to use a timer triggered scenario which fetches data from S/4 HANA and sends it to a third party REST API. This can be easily done in SAP Cloud Integration.

      For sending data to third party REST APIs you can use the HTTPS Receiver Adapter and for fetching data from S/4 HANA system you can use a request reply with the respective receiver adapter(based on the type of endpoint exposed by S/4 HANA system e.g., SOAP, HTTPS OData). You can configure and use the Timer step to schedule the triggering of this scenario. If you need a custom scheduling pattern you can follow the steps mentioned in this blog.

       

      Regards,

      Apurva