The support issue came in as "Schedules Running On Wrong Days". After some back and forth, the problem was that workflows were converting dates to determine if they should run or not, and were running on the wrong days.
The customer had a collection of jobs that needed to run on specific days of the month and/or year. The pattern was both beyond the reoccurance capabilities of BAO's internal scheduler, and frequent enough that it would have taken defining 20+ schedules in the module and that wasn't going to scale.
They solved this by creating one daily schedule for each job and having the job check to see if it should continue running that day. They created a module configuration item with XML of the form:
<dates> <day>0101</day> <day>0401</day> <day>0701</day> <day>1001</day> </dates>
(Theirs was way bigger, but you get the idea.)
The process called by the scheduler started with a utility process that converted "now" from the Utility Activity into a string of the form "mmdd". The main process then did an Xpath transform to compare the "now" string to the values in the XML in the config item, and if a match was found, it would return "true". When "true", a subsequent Switch activity would allow the process to actually run, otherwise it would just stop immediately. They didn't need to even return the <day> element of the XML, because just the fact a match was found was enough.
The date comparison was done via an Xpath transform in the form of:
This worked perfectly in BAO Development Studio, but once activated on the grid it sometimes ran on days it wasn't supposed to. The job had run when it should have on January 1st, but had run incorrectly again on January 4th. They opened a support ticket with BMC Customer Support and we dived in to figure out what the problem was.
The root cause of this issue was the use of the contains() Xpath function.
Xpath functions generally operate on an "input document" that may be all or part of a XML document. The "." is used to signify "here". Where "here" is, depends on the context. When used, like in this instance, the "." turns into the whole XML that was fed in. But the contains function operates against values only, so all the XML elements were stripped out, leaving just the string "0101040107011001" to compare against. Doing the replacement on the contains function above, it actually looked like this to BAO:
This is going to return true on the days expected, but also on "0104", "0107", "0110" and "1010".
The solution is to change the Xpath to look at lines first, and search within them second. This can be done by doing a search for the day elements, and then picking only the one that has the date in it that matches $[now]. We still use the contains function, but we use it in the ordinal to only choose the line with the right day in it. That transform looks like:
When $[now] is "0101", this will return:
When $[now] is "0104", it will return
You can sexy the transform up some, to come up with a true/false result:
string-length(//day[contains(., '$[now]')]) > 0
There are other transforms that can be used, but I'll leave them to the Teeming Millions.