Help with velocity in transform

I have a transform for calculating the cloudLifecycleState, that ultimately relies on a velocity script for the value returned. All states are returned normally except “inactive” when rescinded = true. In these cases, the transform errors out with:

There was an exception while calculating the value for this attribute. Error during transformation for attribute: cloudLifecycleState (Transform ID: Calculate LCS ) Cause: Error rendering template: [the velocity script]

I’m quite sure I’m missing something really dumb, but I confirmed that the IS_RESCINDED attribute is from right source, spelled correctly, does in fact give ‘true’ as a string in the account schema (not a boolean), etc. I also initially had the evaluation for “inactive” all in one statement to be cleaner, but that wasn’t working so I separated them out in the below:

{
    "id": "[redacted]",
    "name": "Calculate LCS ",
    "type": "static",
    "attributes": {
        "isItInactive": {
            "attributes": {
                "firstDate": {
                    "attributes": {
                        "input": {
                            "attributes": {
                                "values": [
                                    {
                                        "type": "accountAttribute",
                                        "attributes": {
                                            "sourceName": "Workday",
                                            "attributeName": "TERMINATION_DATE"
                                        }
                                    },
                                    "12/31/2999"
                                ]
                            },
                            "type": "firstValid"
                        },
                        "inputFormat": "MM/dd/yyyy",
                        "outputFormat": "ISO8601"
                    },
                    "type": "dateFormat"
                },
                "secondDate": "now",
                "operator": "lte",
                "positiveCondition": "inactive",
                "negativeCondition": "notTerminated"
            },
            "type": "dateCompare"
        },
        "isItActive": {
            "attributes": {
                "firstDate": {
                    "type": "dateMath",
                    "attributes": {
                        "expression": "-7d",
                        "roundUp": true,
                        "input": {
                            "attributes": {
                                "input": {
                                    "attributes": {
                                        "values": [
                                            {
                                                "attributes": {
                                                    "attributeName": "HIREDATE",
                                                    "sourceName": "Workday"
                                                },
                                                "type": "accountAttribute"
                                            },
                                            "12/31/2999"
                                        ]
                                    },
                                    "type": "firstValid"
                                },
                                "inputFormat": "MM/dd/yyyy",
                                "outputFormat": "ISO8601"
                            },
                            "type": "dateFormat"
                        }
                    }
                },
                "secondDate": "now",
                "operator": "lte",
                "positiveCondition": "active",
                "negativeCondition": "notActive"
            },
            "type": "dateCompare"
        },
        "isItDelete": {
            "attributes": {
                "firstDate": {
                    "attributes": {
                        "input": {
                            "attributes": {
                                "values": [
                                    {
                                        "type": "reference",
                                        "attributes": {
                                            "id": "Woodward - Extension 8 Validation"
                                        }
                                    },
                                    {
                                        "type": "dateFormat",
                                        "attributes": {
                                            "inputFormat": "ISO8601",
                                            "outputFormat": "MM/dd/yyyy",
                                            "input": {
                                                "type": "dateMath",
                                                "attributes": {
                                                    "expression": "+30d/d",
                                                    "roundUp": true,
                                                    "input": {
                                                        "type": "dateFormat",
                                                        "attributes": {
                                                            "inputFormat": "MM/dd/yyyy",
                                                            "outputFormat": "ISO8601",
                                                            "input": {
                                                                "attributes": {
                                                                    "attributeName": "TERMINATION_DATE",
                                                                    "sourceName": "Workday"
                                                                },
                                                                "type": "accountAttribute"
                                                            }
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    },
                                    "12/31/2999"
                                ]
                            },
                            "type": "firstValid"
                        },
                        "inputFormat": "MM/dd/yyyy",
                        "outputFormat": "ISO8601"
                    },
                    "type": "dateFormat"
                },
                "secondDate": "now",
                "operator": "lte",
                "positiveCondition": "isItDelete",
                "negativeCondition": "NO"
            },
            "type": "dateCompare"
        },
        "LOA": {
            "type": "firstValid",
            "attributes": {
                "values": [
                    {
                        "attributes": {
                            "sourceName": "Workday",
                            "attributeName": "ON_LEAVE"
                        },
                        "type": "accountAttribute"
                    },
                    {
                        "type": "static",
                        "attributes": {
                            "value": "NA"
                        }
                    }
                ]
            }
        },
        "RESCINDED": {
            "type": "firstValid",
            "attributes": {
                "values": [
                    {
                        "attributes": {
                            "sourceName": "Workday",
                            "attributeName": "IS_RESCINDED"
                        },
                        "type": "accountAttribute"
                    },
                    {
                        "type": "static",
                        "attributes": {
                            "value": "NA"
                        }
                    }
                ]
            }
        },
        "LCS": {
            "type": "identityAttribute",
            "attributes": {
                "name": "cloudLifecycleState"
            }
        },
        "STATUS": {
            "type": "accountAttribute",
            "attributes": {
                "sourceName": "Workday",
                "attributeName": "ACTIVE"
            }
        },
        "requiresPeriodicRefresh": true,
        "value": "#if($LOA=='1')loa#elseif($LCS=='adminleave')adminleave#elseif(($isItActive=='active') && ($STATUS=='1'))active#elseif(($isItInactive=='inactive') && ($STATUS=='0') && ($isItDelete=='NO'))inactive#elseif(($RESCINDED=='true') && ($STATUS=='0') && ($isItDelete=='NO'))inactive#elseif(($isItInactive=='inactive') && ($isItDelete=='isItDelete') && ($STATUS=='0'))delete#end"
    },
    "internal": false
}

Any thoughts on how to get rescinded users reporting as inactive as expected? Thank you!!

I recommend creating a duplicate transform that writes to a test Identity Attribute, but just write out the variable values.

You should then be able to pull that data on all users. If you have it comma separated, you could pull it into a spreadsheet or use some scripting to throw it into a table and evaluate differences of the variables across all users to find any gaps in the data.

In your schema on workday is it showing the value as a string?

You say your Rescinded status isn’t working as expected; please share the relevant attributes for the failing cases.

There’s lots of edge cases you don’t account for in the logic as laid out, so you should add a catch-all LCS called “dataError” (#{else}dataError right before the #end) that can alert all SailPoint admins when people land here.

Also, just as a stylistic choice, try to be more consistent with your positiveCondition/negativeCondition values - you go from inactive/notTerminated to active/notActive to isItDelete/NO to [account attribute values]/NA. stick with descriptive variable names and then say true/false/NA.

Appreciate the cleanup advice! I agree the code hygiene on here is lacking a bit. An example of an identity getting the error has these attributes currently:

Workday TERMINATION_DATE (string) is null
Workday HIREDATE is null
Reference attribute “Woodward - Extension 8 Validation” is a transform returning ““ (an empty string)
Workday ON_LEAVE (string) is null
Workday IS_RESCINDED (string) = “true”
Identity cloudLifecycleState (string) is null
Workday ACTIVE (string) = “0”

Yes, confirmed the attribute is a string in the Workday schema. I tried your suggestion on using a copy of the transform to write an identity attribute to see the variable outputs, ex.

"value": "$LOA,$LCS,$isItActive,$STATUS,$isItInactive,$isItDelete,$RESCINDED"

The $RESCINDED variable specifically does seem to be the issue- if I preview an identity where IS_RESCINDED is null, I properly see “NA” for the $RESCINDED output. But an identity where IS_RESCINDED=true, it errors out with that “Error rendering template” message.

Can you please check in the preview for respective user which has been rescinded in WORKDAY whether you are getting individual function values as required? for the condition –>

(($RESCINDED==‘true’) && ($STATUS==‘0’) && ($isItDelete==‘NO’))

In my case, I have used $RESCINDED.equals(\“true\”) but that should not make any difference.

When rescinded is true ,will receive termination date as null.in isItDelete logic you are adding 30days to terminationdate which is null. update this logic

@widen9739 ,
Let me give you a weird approach to try.

Instead of reading the “IS_RESCINDED” attribute directly from Workday, put it in a identity attribute first, lets say you created an identity attribute called “isRescindedValueFromWorkday“.

Now, in your transform, you read this Identity attribute instead of using the account attribute.

I once had such issue related to a Date account attribute, and doing this weird thing somehow solved the issue for me.

Good luck, hope this works.

Thank you,
Vaibhav

Thanks for the suggestion! I gave this a shot, as I actually already had an Identity attribute pulling that value. It gives the same error in the transform though.

1 Like

So I’ve gotten somewhere with this by removing the first if statement

#if($LCS==‘adminleave’)adminleave

This was causing the issue with my rescinded accounts because somewhere in this mess their LCS had become null, and the transform was erroring on processing $LCS as a null value. Now rescinded accounts are getting the “inactive” LCS we expect. But any account that we’d expect to go all the way through the logic and end up with the “catchall” LCS are still erroring at the $RESCINDED evaluation.

"#if(($isItActive=='active') && ($STATUS=='1'))active#elseif(($isItInactive=='inactive') && ($STATUS=='0') && ($isItDelete=='NO'))inactive#elseif(($isItInactive=='inactive') && ($isItDelete=='isItDelete') && ($STATUS=='0'))delete#elseif(($RESCINDED=='true') && ($STATUS=='0') && ($isItDelete=='NO'))inactive#{else}catchall#end"

I suppose I was expecting “$LCS==’adminleave’” and “$RESCINDED==’true’” to evaluate to false if those variables are null, but instead Sailpoint seems to just freak out when the variables are null. What’s the proper way to handle null variables in the velocity script?

@widen9739 it is as follows,
lets say we want to check if $LCS is null OR not, then we do as follows

#if($LCS) ‘LCS is NOT null‘ #else ‘LCS is NULL‘ #end

You can squeeze in this check in the existing if else structure.

Thank you,
Vaibhav

Reference : Apache Velocity Engine - User Guide

I’ve tried that, but I still get errors. Ex. for the RESCINDED part I now have

#elseif(($RESCINDED) && ($STATUS=='0') && ($isItDelete=='NO'))inactive

For a user where $RESCINDED=true that works fine, but for users where $RESCINDED is null, I get the rendering error. I confirmed it’s the $RESCINDED part specifically because if I take it out and just have

#elseif(($STATUS=='0') && ($isItDelete=='NO'))inactive

It works fine.

@widen9739 could you try once something like this ?

#if(($isItActive==‘active’) && ($STATUS==‘1’))active#elseif(($isItInactive==‘inactive’) && ($STATUS==‘0’) && ($isItDelete==‘NO’))inactive#elseif(($isItInactive==‘inactive’) && ($isItDelete==‘isItDelete’) && ($STATUS==‘0’))delete#else#if($RESCINDED)#if(($RESCINDED==‘true’) && ($STATUS==‘0’) && ($isItDelete==‘NO’))inactive#end#else catchcall#end#end

I had an Ask an Architect session where we looked over the velocity script. They added null checks to every if statement, ex.

if($isItActive && $isItActive == ‘active’ && $STATUS && $STATUS == ‘1’)active

As I mentioned earlier in this thread, the null checks themselves were causing failures before, so I don’t think this was the actual fix.

They also modified every variable definition that called an identityAttribute to be a firstValid so it would still get some sort of output if it was null. I was already doing that with RESCINDED but not with LOA.

So either that fixed it, or this was a bug that silently got fixed. Idk but it’s all working now. Thanks everyone for the help!!

This topic was automatically closed 60 days after the last reply. New replies are no longer allowed.