Error Referencing Value from Form in Report

Which IIQ version are you inquiring about?

Version 8.3

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

Hello,

I’m implementing a report and I want to allow the user to select multiple types of identities (employee, partner, service, corporate), and both active and inactive identities.

For that I created a form that is referenced in the <ReportForm>:

<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE Form PUBLIC "sailpoint.dtd" "sailpoint.dtd">
<Form hidden="true" name="Form-IdentityTypeAndStatusFilter" type="Report">
	<Section columns="2" label="rept_identity_roles_section_props" name="Identity Attributes">
		<Field columnSpan="1" displayName="Identity Type" multi="true" name="identityType" type="string" value="ref:identityType">
			<AllowedValuesDefinition>
				<Value>
					<List>
						<String>employee</String>
						<String>partner</String>
						<String>service</String>
						<String>corporate</String>
					</List>
				</Value>
			</AllowedValuesDefinition>
		</Field>
		<Field columnSpan="1" displayName="Identity Status" multi="true" name="indentityInactive" type="string" value="ref:identityInactive">
			<AllowedValuesDefinition>
				<Value>
					<List>
						<String>active</String>
						<String>inactive</String>
					</List>
				</Value>
			</AllowedValuesDefinition>
		</Field>
	</Section>
</Form>

In the report I specified two parameters that should receive the values from the report:

<DataSource defaultSort="name" objectType="Identity" type="Filter">
	<QueryParameters>
		<Parameter argument="identityType">
			<QueryScript>
				<Source><![CDATA[
				import sailpoint.object.Filter;
				log.error("[Form-type] value: " + value);

				List filterTypes = new LinkedList();

				List types = value;
				for (String type: types)
					filterTypes.add(Filter.eq("identity.type", type));
				
				queryOptions.addFilter(Filter.or(filterTypes));

				return queryOptions;]]>
				</Source>
			</QueryScript>
		</Parameter>
		<Parameter argument="identityInactive">
			<QueryScript>
				<Source><![CDATA[
				import sailpoint.object.Filter;
				log.error("[Form-inactive] value: " + value);

				List filterTypes = new LinkedList();

				List types = value;
				for (String type: types)
					filterTypes.add(Filter.eq("identity.inactive", type.equals("inactive")));
				
				queryOptions.addFilter(Filter.or(filterTypes));
				
				return queryOptions;]]>
				</Source>
			</QueryScript>
		</Parameter>
	</QueryParameters>
</DataSource>

The issue is that the value in the report isn’t being populated with the ones introduced in the form. The value in the report is null.

Do you have any hints that could help address the problem?

Hi @brunoocarvalho,

Which data source do you have?

Il you can see this topic; in one of my post you can find a file called task.xml, it a good example for this kind of use of report:

1 Like

The Data Source was formatted incorrectly, so it wasn’t being displayed.
This is what I’m using:

<DataSource defaultSort="name" objectType="Identity" type="Filter">

and now it works?

basically, you need to use a datasource(java,hql or filter) for the identities and a queryscript for filtering them, something like this:


in this case I used an HQL query and in the query script I added other filter based on the arguments(the arguments comes from a form)

1 Like

After following your example this is what I have:

<DataSource defaultSort="name" objectType="Identity" type="Filter">
	<QueryParameters>
		<Parameter argument="identityType"/>
		<Parameter argument="identityInactive"/>
	</QueryParameters>
	<QueryScript>
		<Source><![CDATA[
				import sailpoint.object.Filter;
				
				List filterTypes = new LinkedList();
				List types = args.get("identityType");
				for (String type: types)
					filterTypes.add(Filter.eq("type", type));
				
				queryOptions.addFilter(Filter.or(filterTypes));

				List filterStatus = new LinkedList();
				List statusL = args.get("identityInactive");
				for (String status: statusL)
					filterStatus.add(Filter.eq("inactive", status.equals("inactive")));
				
				queryOptions.addFilter(Filter.or(filterStatus));
				
				return queryOptions;]]>
		</Source>
	</QueryScript>
</DataSource>

The report is executing but it isn’t filtering Identities, every Identity is being displayed.

Is there something wrong with the QueryScript that would prevent the filters from being applied?

Hi @brunoocarvalho,

if you want a report with inactive employee for example, you need use the “and” operation instead of “or”.

Also, you are not checking the null/empty status of arguments. Its a good practice controll every variable could be null or empty.

PS check every possible case, both arg are empties, only one is empty ecc…
Also, in advanced analytics->Advanced search you can build you filter:


and click on view/edit file source to look the filter code and check if its the same of you code

1 Like

Hello @enistri_devo, thanks for the reply :smiley:

What I want to do is to allow the selection of multiple values for the selected attributes.

So I would want the user to be able to select identities with type employee, or with type partner, or to select both types.

For the identity status is the same. The user should be able to select inactive identities, or active identities, or both.

In Advanced Analytics, it looks like this:

Would it be possible to achieve this behavior? Maybe what’s missing is “anding” these two conditions?

But from what I understand, when multiple filters are added to the QueryOptions they are “anded”. Is this wrong?

Also, I added some logs to the QueryScript, but they are not being displayed. Is there a way to see these logs?

For logs you can try with system.out.println and it could be displayed in catalina.out or better if you use logfactory:

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

Log log = LogFactory.getLog("nameAppender");
log.info("-------------- logs --------------");

for this, you need create an appender or use one already exist.

Also, if logs are not displayed it was because this is not execute and we need search the reason.

I will do some test tomorrow and check where is the problem

1 Like

I tried using both alternatives, but none of them worked :confused:

I also noticed I didn’t change the signature of the report to match the parameters, so I updated it to the following:

<Signature>
	<Inputs>
		<Argument name="identityType" type="string">
			<Description>rept_input_user_report_inactive</Description>
		</Argument>
		<Argument name="identityInactive" type="string">
			<Description>rept_input_user_report_inactive</Description>
		</Argument>
	</Inputs>
</Signature>

But after fixing the signature I’m getting a NullPointer error:

sailpoint.tools.GeneralException: NullPointerException
	at sailpoint.persistence.HibernatePersistenceManager.countObjects(HibernatePersistenceManager.java:2753)
	at sailpoint.persistence.ClassPersistenceManager.countObjects(ClassPersistenceManager.java:358)
	at sailpoint.server.InternalContext.countObjects(InternalContext.java:918)
	at sailpoint.reporting.datasource.ProjectionDataSource.getSizeEstimate(ProjectionDataSource.java:61)
	at sailpoint.reporting.JasperCsvWriter.write(JasperCsvWriter.java:96)
	at sailpoint.reporting.LiveReportExecutor.execute(LiveReportExecutor.java:275)
	at sailpoint.api.TaskManager.runSync(TaskManager.java:909)
	at sailpoint.api.TaskManager.runSync(TaskManager.java:724)
	at sailpoint.scheduler.JobAdapter.execute(JobAdapter.java:128)
	at org.quartz.core.JobRunShell.run(JobRunShell.java:202)
	at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:573)
Caused by: sailpoint.tools.GeneralException: NullPointerException
	at sailpoint.persistence.HibernatePersistenceManager.mapSearchAttributes(HibernatePersistenceManager.java:2602)
	at sailpoint.persistence.HibernatePersistenceManager.orderAndOptimize(HibernatePersistenceManager.java:2495)
	at sailpoint.persistence.HibernatePersistenceManager.countObjects(HibernatePersistenceManager.java:2727)
	... 10 more
Caused by: java.lang.NullPointerException

I added null validations to the lists received in the script, but the exception is still being thrown.

Could the Signature not matching the QueryParameters be the cause of the logs not showing?

Also, do you have any clue why the NullPointerException is being thrown?

I find the solution, sorry for delay but its a long time I dont work on report(the dark side of SP :sweat_smile:)

<TaskDefinition executor="sailpoint.reporting.LiveReportExecutor" name="Report" progressMode="Percentage" resultAction="Rename" subType="Custom Reports" template="true" type="LiveReport">
  <Attributes>

    <Map>

      <entry key="report">

        <value>

          <LiveReport title="Account Group Membership Report">

            <DataSource type="Hql">

              <Query>  from Link l, IdentityEntitlement ie,ManagedAttribute ma,Identity identity left outer join identity.manager m 

          where ie.value = ma.value and ie.application.name = ma.application.name and  ie.name = ma.attribute

          and l.application.name = ie.application.name and l.nativeIdentity  = ie.nativeIdentity and l.identity.id = identity.id
              </Query>
<QueryParameters>

                <Parameter argument="identityType" property="identityType"/>
                </QueryParameters>
              <QueryScript>

                <Source>
                      

                            String scriptCriteria ="";
                            List<String>  identityType = new ArrayList();
                            identityType = args.get("identityType");

                            if (identityType != null &amp;&amp; !identityType.isEmpty()){
                               scriptCriteria =  " identity.type  in( :identityType ) ";
                            }
                            if (!scriptCriteria.isEmpty())

                                 query+= " and " + scriptCriteria;

                            return query;

                        </Source>

              </QueryScript>

            </DataSource>
            <ReportForm>
              <Reference class="sailpoint.object.Form" name="Form-IdentityTypeAndStatusFilter"/>
            </ReportForm>
            <Columns>
              <ReportColumnConfig field="extended1" header="extended1" property="identity.extended1" sortable="true" width="80"/>
              <ReportColumnConfig field="identity" header="name" property="identity.name" sortable="true" width="80/">

            </Columns>
          </LiveReport>
        </value>
      </entry>
    </Map>
  </Attributes>
  <RequiredRights>
    <Reference class="sailpoint.object.SPRight" name="FullAccessAccountGroupMembershipReport"/>
  </RequiredRights>
  <Signature>
    <Inputs>
      <Argument multi="true" name="identityType" type="string"/>
      <Argument multi="true" name="identityInactive" type="string"/>
    </Inputs>
  </Signature>
</TaskDefinition>

I did this template with query. Using your form I read the arguments and use them in a query script. In this case I use only the identityType but you can add the part for identityInactive, add colums acc…
For the query I put some things like manager, managedattribute and identityentitlement; you can add or remove elements

1 Like