Null Pointer in Customization Rule

Which IIQ version are you inquiring about?

Version 8.2

Share all details related to your problem, including any error messages you may have received.

I am working on a Web service integration that needs the customization rule to show in the UI when an account is disabled or enabled. I have the below code, however I’m running into a Null Pointer error. The thing is, the past configuration used Employee ID as a schema attribute, but I want to now use AssociateId. I beleve this is why I am getting this error. Does anyone have any insight on this?

Code:

import java.util.ArrayList; import java.util.Map; import java.util.HashMap; import sailpoint.connector.Connector; import sailpoint.object.Link; import sailpoint.object.Application; import sailpoint.object.Identity; import sailpoint.object.ResourceObject; import org.apache.log4j.Logger; import org.apache.log4j.Level;

log.warn(“Starting rule”);

Logger log = Logger.getLogger(“BillingCenter.customization.rule”);
String isActive = object.getStringAttribute (“["Active"]”);

log.warn("Retrieved Active: " + isActive);

if ( (null != isActive) && (“true”.equalsIgnoreCase(isActive))){
object.put(“IIQDisabled”, true);
} else {
object.put(“IIQDisabled”, false);
}

return object;

Error:
The application script threw an exception: java.lang.NullPointerException: Null Pointer in Method Invocation BSF info: User Status Check - BC at line: 0 column: columnNo
Identity attribute [AssociateID] was not found.: {associateID=null, Active=false, AuthorityProfile=null, FirstName=Default, UserRoles=, LastName=Owner, UserGroups=[Default Root Group]}

This is preventing me from running the Account aggregation task within SailPoint.

1 Like

AssociateID appears to be coming back as null in your account response. This is truly where the error is coming from. Essentially, the error means it cannot process the account because it needs the Identity Attribute value that you told it to look for, and it cannot find it based on your current config.

Make sure you Account Aggregation response mapping is set up properly to pull in AssociateID from your HTTP response and that the schema attribute you map in the response mapping matches the actual schema attribute you define for AssociateID (case sensitive). And lastly make sure your schema Identity Attribute has that same correct reference so everything flows properly.

3 Likes

Hi Alyson,
I see 3 issues here

First of all - in the error you showed

Error:
The application script threw an exception: java.lang.NullPointerException: Null Pointer in Method Invocation BSF info: User Status Check - BC at line: 0 column: columnNo
Identity attribute [AssociateID] was not found.: {associateID=null, Active=false, AuthorityProfile=null, FirstName=Default, UserRoles=, LastName=Owner, UserGroups=[Default Root Group]}

you see sailpoint is expecting attribute [AssociateID] while in resultset you have attribute associateID - As Patrick mentioned - you have to change the identity attribute in the schema to match what you get from the aggregation. Also [] brackets are not needed most probably.

Second issue is that even if you change the identity attribute name - it will still cause problems as you see associateID is null in your resultset so I would check if you have correct response mapping for this attribute in the operation definition.

That leads to third issue which is

String isActive = object.getStringAttribute (“["Active"]”);

That should be this instead:

String isActive = object.getStringAttribute (“Active”);
4 Likes

A couple more notes:

Never call your logger log. There’s already a passed in logger called log. I call my custom Logger alog also define your Logger before your first use.

Second, use of alog.warn or alog.error for debugging is not good practice. Rather, either put the elements into your log4j2.properties file or do an alog.setLevel(Level.DEBUG) and then use alog.debug statements, that way when you go to production you can just comment out the setLevel line.

Third, your logger hierarchy is backwards. Go from most general to most specific, you are doing this backwards.

I also see inappropriate quote marks in the message, hopefully you are not copy pasting from a Word document, it converts everything to smart quotes and you want simple quotes. And what goes into the getStringAttribute call needs to be spelled and capitalized exactly as it’s found in the schema definition.

Finally, kudos for using Yodaspeak for your string compare but please don’t use Yodaspeak for your null check. Never do if (null == or if(null != always do it the other way around. I have seen NPEs for when people do this for null checks. It’s rare but I have seen it.

Your call is going to be object.getStringAttribute(“Active”) and that’s it. Not even sure how your call even passed the compiler it’s not an actual valid method argument.

Hope this helps a little.

1 Like

@mercury @kjakubiak Thank you both for the feedback! I did some modifications based on the notes you provided.
I have verified that AssociateId is consistent within the schema and attributes. I also updated the loggers to follow best practices.
It still seems to be failing on the null pointer of “AssociateId is not found”, but the code it states, if not null =true, else= false.
Not sure what I am missing here.

Code:

Blockquote
Import
import java.util.ArrayList;
import java.util.Map;
import java.util.HashMap;
import sailpoint.connector.Connector;
import sailpoint.object.Link;
import sailpoint.object.Application;
import sailpoint.object.Identity;
import sailpoint.object.ResourceObject;
import org.apache.log4j.Logger;
import org.apache.log4j.Level;
Logger alog = Logger.getLogger(“sentry.clBillingCenter.customization.rule”);
alog.setLevel(Level.DEBUG);
alog.debug(“Starting rule”);
String isActive = object.getStringAttribute(“Active”);
if ( (isActive != null) && (“true”.equalsIgnoreCase(isActive))){
object.put(“IIQDisabled”, true);
} else {
object.put(“IIQDisabled”, false);
}
return object;

Error:
Exception during aggregation. Reason: java.lang.RuntimeException: sailpoint.connector.ConnectorException: The application script threw an exception: java.lang.NullPointerException: Null Pointer in Method Invocation BSF info: Sentry User Status Check - BC at line: 0 column: columnNo
2024-01-02 08:43:42 ERROR QuartzScheduler_Worker-3 sailpoint.connector.AbstractConnector:1194 - Identity attribute [AssociateId] was not found.

Logs:
2024-01-02 08:43:42 ERROR QuartzScheduler_Worker-3 sailpoint.connector.webservices.v2.WebServiceFacadeV2:2127 - Error while RO transformation - Identity attribute [AssociateId] was not found.: {Active=false, AuthorityProfile=null, FirstName=Default, UserRoles=, AssociateId=null, LastName=User, UserGroups=[Default]}

Would it be possible for you to add here the application XML? That would help us to troubleshoot. Also if you could add sample payload you are getting from the app that would be fantastic.

Agree. The issue is not with your customization rule. Do you ever see the initial log entry? If not then you are not getting to that point.

WebServices connectors are especially difficult, I have been working on these for 5 years and each one still provides challenges.

I looked at your error again. It appears that your decoding of the response does not include AssociateID OR that the record you are getting back from your REST call is not pulling in this value. Either way, because likely you have this as the identity attribute (native identity) the record can’t be aggregated. You need to pull this with Postman to verify the response, and then look at your response mapping to make sure it is interpreted properly.

I am not seeing the initial logger. Below is the Aggregation portion of the connector.

          <entry key="afterRule"/>
          <entry key="beforeRule"/>
          <entry key="body">
            <value>
              <Map>
                <entry key="bodyFormData"/>
                <entry key="bodyFormat" value="raw"/>
                <entry key="jsonBody"/>
              </Map>
            </value>
          </entry>
          <entry key="contextUrl" value="/retrieveUsers"/>
          <entry key="curlCommand"/>
          <entry key="curlEnabled">
            <value>
              <Boolean></Boolean>
            </value>
          </entry>
          <entry key="customAuthUrl"/>
          <entry key="header"/>
          <entry key="httpMethodType" value="GET"/>
          <entry key="operationType" value="Account Aggregation"/>
          <entry key="paginationSteps" value="$CL_limit$ = 100&#xD;&#xA;TERMINATE_IF $RECORDS_COUNT$ &lt; $CL_limit$&#xD;&#xA;$CL_offset$= $CL_offset$ + $CL_limit$&#xD;&#xA;$endpoint.fullUrl$ = $application.baseUrl$ +&quot;/retrieveUsers?offset=&quot; + $CL_offset$ "/>
          <entry key="pagingInitialOffset">
            <value>
              <Integer>0</Integer>
            </value>
          </entry>
          <entry key="pagingSize">
            <value>
              <Integer>100</Integer>
            </value>
          </entry>
          <entry key="parentEndpointName"/>
          <entry key="resMappingObj">
            <value>
              <Map>
                <entry key="Active" value="Active"/>
                <entry key="AssociateId" value="AssociateId"/>
                <entry key="AuthorityProfile" value="AuthorityProfile"/>
                <entry key="FirstName" value="FirstName"/>
                <entry key="LastName" value="LastName"/>
                <entry key="UserGroups" value="UserGroups"/>
                <entry key="UserRoles" value="UserRoles"/>
              </Map>
            </value>
          </entry>
          <entry key="responseCode">
            <value>
              <List>
                <String>2**</String>
              </List>
            </value>
          </entry>
          <entry key="rootPath" value="$.activeUsers"/>
          <entry key="sequenceNumberForEndpoint" value="2"/>
          <entry key="uniqueNameForEndPoint" value="Account Aggregation"/>
          <entry key="xpathNamespaces"/>
        </Map>

Can you also get payload from postman?

Yeah. You need to populate the jsonBody with your decoding scheme. You are lucky to have any data come through.

It’s a get operation ro aggregate accounts so json body can (and in most cases should) be empty

I dont have Postman set up for this.

I have done similar integration in the past and the body of the Account Aggregation endpoint did not have any body. I dont see the option in the UI to add a body.

That’s fine to not have body in get operation. My suspicion is that there’s either missmatch between the payload you are getting from the endpoint and your response mappings or the payload does not xontain all attributes you expect.

That’s why it would be great to see what you get from the endpoint directly.

You are correct. I found that the request was using AssociateID and not AssociateId.
Appreciate you taking time to look into this.

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