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.