Workflow not creating work item

Which IIQ version are you inquiring about?

8.4

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

Hi all, I have a custom quicklink workflow and I would like to have a work item created for users to refer back to once they have submitted the quicklink form. However, currently everything is working but I noticed there is no work item created. Pasted my code below. Would appreciate any help. Thank you.

<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE Workflow PUBLIC "sailpoint.dtd" "sailpoint.dtd">
<Workflow explicitTransitions="true" name="Self Service View Workflow - Public Officer">
  <!-- Define all required variables -->
  <Variable input="true" name="launcher"/>
  <Variable name="email"/>
  <Variable name="mobileNumber"/>
  <Variable name="ruleResult"/>
  <Variable initializer="false" name="isValid"/>
  <Variable initializer="new java.util.ArrayList()" name="validationErrors"/>
  <Variable initializer="true" name="transient"/>

  <Step icon="Start" name="Start" posX="36" posY="82">
  <Transition to="Display Form"/>
</Step>
<Step icon="Default" name="Display Form" posX="128" posY="84">
  <Approval name="Account Invite" owner="script:return context.getUserName();" return="email,mobile" send="">
    <Form name="Account Invite">
      <Attributes>
        <Map>
          <entry key="pageTitle" value="Create Account"/>
		  <entry key="errors" value="ref:validationErrors"/>
        </Map>
      </Attributes>
      <Section name="User Details ">
		<Field displayName="Email" name="email" type="string" required="true" helpKey="Valid email address should follow">
		<ValidationScript>
        <Source>
            import sailpoint.object.*;
            import sailpoint.tools.GeneralException;
            import org.apache.commons.lang.StringUtils;
            import sailpoint.tools.Message;
            import java.util.List;
            import java.util.Arrays;
            import java.util.regex.Pattern;

            Message msg = new Message();
            
            if (email != null @and !StringUtils.isEmpty(email.trim())) {
                String emailValue = email.trim();
                
                String domain = emailValue.substring(emailValue.lastIndexOf("@") + 1).toLowerCase();

                List validDomains = Arrays.asList("*****");

                if (!validDomains.contains(domain)) {
                    msg.setKey("Email domain '" + domain + "' is not allowed. Please ensure email domain is @****");
                    return msg;
                }
                
            }
            return null;
        </Source>
    </ValidationScript>
		</Field>
		<Field displayName="Mobile Number" name="mobile" type="string" required="true" helpKey="Valid mobile number should follow ">
		<ValidationScript>
        <Source>
		import sailpoint.object.*;
            import sailpoint.tools.GeneralException;
            import org.apache.commons.lang.StringUtils;
            import sailpoint.tools.Message;
            import java.util.List;
            import java.util.Arrays;
            import java.util.regex.Pattern;

            Message msg = new Message();
            if (mobile != null &amp;&amp; !StringUtils.isEmpty(mobile.trim())) {
    // Remove all spaces from the phone number
    String phoneValue = mobile.trim().replaceAll("\\s+", "");
    
    // Regex pattern for +65-8xxxxxxx or +65-9xxxxxxx
    String phonePattern = "^\\+65-[89]\\d{7}$";
    
    if (!Pattern.matches(phonePattern, phoneValue)) {
        msg.setKey("Invalid phone number format. Phone number must be in format");
        return msg;
    }
}
            return null;
        </Source>
    </ValidationScript>
		</Field>
      </Section>
      <Button action="next" label="Submit"/>
      <Button action="back" label="Back"/>
    </Form>
  </Approval>
  <Transition to="Execute Rule">
    <Script>
      <Source> boolean result =false; if(lastApprovalState.equalsIgnoreCase("Finished")){ result = true; } return result;</Source>
    </Script>
  </Transition>
</Step>
<Step action="rule:Account Invite" icon="Default" name="Execute Rule" posX="255" posY="140" resultVariable="response">
  <Transition to="Confirmation step"/>
</Step>
<Step icon="Default" name="Confirmation step" posX="255" posY="140">
<Arg name="response" value="ref:response"/>
<Script>
<Source> 
import javax.faces.application.FacesMessage;

List currentMessages = httpSession.getAttribute("sailpoint.web.PageCodeBase.sessionMessages");
List myMessages = new ArrayList();

int statusCode = (Integer) response.get("statusCode");

if (statusCode == 200) {
    FacesMessage myMessage = new FacesMessage(
        FacesMessage.SEVERITY_INFO,
        "Account Invite sent successfully.",
        "Account Invite sent successfully."
    );
    myMessages.add(myMessage);
} else {
    FacesMessage myMessage = new FacesMessage(
        FacesMessage.SEVERITY_ERROR,  // Changed to ERROR for unsuccessful cases
        "Account Invite failed to send. Please refer to email sent for more details.",
        "Account Invite failed to send. Please refer to email sent for more details."
    );
    myMessages.add(myMessage);
}

httpSession.setAttribute("sailpoint.web.PageCodeBase.sessionMessages", myMessages);
</Source> 
</Script>
<Transition to="Stop"/>
</Step>
  <Step icon="Stop" name="Stop" posX="342" posY="76"/>
</Workflow>

I see few issues with your code. can you please add top section like this and try.

<?xml version='1.0' encoding='UTF-8'?>

<!DOCTYPE Workflow PUBLIC "sailpoint.dtd" "sailpoint.dtd">

<Workflow explicitTransitions="true" name="Self Service View Workflow - Public Officer" type="LCMProvisioning">
  
  <Variable input="true" name="launcher"/>
  <Variable name="email"/>
  <Variable name="mobileNumber"/>
  <Variable name="ruleResult"/>
  <Variable initializer="false" name="isValid"/>
  <Variable initializer="new java.util.ArrayList()" name="validationErrors"/>
  <Variable initializer="true" name="transient"/>
  <Variable name="identityName" initializer="script:return launcher;"/>
  <Variable name="flow" initializer="AccountInvite"/>
  <Variable name="trace" initializer="false"/>


<Variable name="workItemId"/>
  <Variable name="workItemName" initializer="Account Invite Request"/>
  <Variable name="workItemDescription"/>
  <Variable name="workItemPriority" initializer="Normal"/>
  <Variable name="workItemType" initializer="Form"/>
  <Variable name="workItemState"/>
  <Variable name="workItemComments"/>

<Step icon="Start" name="Start" posX="36" posY="82">
    <Transition to="Display Form"/>
  </Step>

<Step icon="Default" name="Display Form" posX="128" posY="84">
    <Approval name="Account Invite" 
              owner="script:return context.getUserName();" 
              return="email,mobile" 
              send=""
              workItemType="Form"
              workItemDescription="Account Invite Request"
              workItemPriority="Normal">
      
      <WorkItemConfig>
        <NotificationEmailTemplateRef>
          <Reference class="sailpoint.object.EmailTemplate" name="Work Item Assignment"/>
        </NotificationEmailTemplateRef>
      </WorkItemConfig>

and the above code on top of below and try

<Form name="Account Invite">

Hello @shijingg

When a user submits the form, the workitem gets deleted. If you want to view the workitems even after submitting them, you need to enable the work item archive for the type ‘Form’, but it saves all the workitems of type ‘Form’ which is not recommended.

Hi Naveen,

I tested the code but still don’t see the work item created. I did not add the portion for
Work Item Assignment email because there is not business need.

 <WorkItemConfig>
        <NotificationEmailTemplateRef>
          <Reference class="sailpoint.object.EmailTemplate" name="Work Item Assignment"/>
        </NotificationEmailTemplateRef>
      </WorkItemConfig>

Please help me to see what am I missing?

<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE Workflow PUBLIC "sailpoint.dtd" "sailpoint.dtd">
<Workflow explicitTransitions="true" name="Self Service View Workflow" type="LCMProvisioning">
  <!-- Define all required variables -->
  <Variable input="true" name="launcher"/>
  <Variable name="email"/>
  <Variable name="mobileNumber"/>
  <Variable name="ruleResult"/>
  <Variable initializer="false" name="isValid"/>
  <Variable initializer="new java.util.ArrayList()" name="validationErrors"/>
  <Variable initializer="true" name="transient"/>
  <Variable name="identityName" initializer="script:return launcher;"/>
  <Variable name="flow" initializer="AccountInvite"/>
  <Variable name="trace" initializer="false"/>
  
  <Variable name="workItemId"/>
  <Variable name="workItemName" initializer="Account Invite"/>
  <Variable name="workItemDescription"/>
  <Variable name="workItemPriority" initializer="Normal"/>
  <Variable name="workItemType" initializer="Form"/>
  <Variable name="workItemState"/>
  <Variable name="workItemComments"/>

  <Step icon="Start" name="Start" posX="36" posY="82">
  <Transition to="Display Form"/>
</Step>
<Step icon="Default" name="Display Form" posX="128" posY="84">
  <Approval name="Account Invite" owner="script:return context.getUserName();" return="email,mobile" send="" workItemType="Form" workItemDescription="Account Invite">
    <Form name="Account Invite">
      <Attributes>
        <Map>
          <entry key="pageTitle" value="Create Account"/>
		  <entry key="errors" value="ref:validationErrors"/>
        </Map>
      </Attributes>
      <Section name="User Details ">
		<Field displayName="Email" name="email" type="string" required="true" helpKey="Valid email address should follow ****">
		<ValidationScript>
        <Source>
            import sailpoint.object.*;
            import sailpoint.tools.GeneralException;
            import org.apache.commons.lang.StringUtils;
            import sailpoint.tools.Message;
            import java.util.List;
            import java.util.Arrays;
            import java.util.regex.Pattern;

            Message msg = new Message();
            
            if (email != null @and !StringUtils.isEmpty(email.trim())) {
                String emailValue = email.trim();
                
                String domain = emailValue.substring(emailValue.lastIndexOf("@") + 1).toLowerCase();

                List validDomains = Arrays.asList("****");

                if (!validDomains.contains(domain)) {
                    msg.setKey("Email domain '" + domain + "' is not allowed. Please ensure email domain is *****");
                    return msg;
                }
                
            }
            return null;
        </Source>
    </ValidationScript>
		</Field>
		<Field displayName="Mobile Number" name="mobile" type="string" required="true" helpKey="Valid mobile number should follow *****">
		<ValidationScript>
        <Source>
		import sailpoint.object.*;
            import sailpoint.tools.GeneralException;
            import org.apache.commons.lang.StringUtils;
            import sailpoint.tools.Message;
            import java.util.List;
            import java.util.Arrays;
            import java.util.regex.Pattern;

            Message msg = new Message();
            if (mobile != null &amp;&amp; !StringUtils.isEmpty(mobile.trim())) {
    // Remove all spaces from the phone number
    String phoneValue = mobile.trim().replaceAll("\\s+", "");
    
    // Regex pattern for +65-8xxxxxxx or +65-9xxxxxxx
    String phonePattern = "^\\+65-[89]\\d{7}$";
    
    if (!Pattern.matches(phonePattern, phoneValue)) {
        msg.setKey("Invalid phone number format. Phone number must be in format ****");
        return msg;
    }
}
            return null;
        </Source>
    </ValidationScript>
		</Field>
      </Section>
      <Button action="next" label="Submit"/>
      <Button action="back" label="Back"/>
    </Form>
  </Approval>
  <Transition to="Execute Rule">
    <Script>
      <Source> boolean result =false; if(lastApprovalState.equalsIgnoreCase("Finished")){ result = true; } return result;</Source>
    </Script>
  </Transition>
</Step>
<Step action="rule:Account Invite" icon="Default" name="Execute Rule" posX="255" posY="140" resultVariable="response">
  <Transition to="Confirmation step"/>
</Step>
<Step icon="Default" name="Confirmation step" posX="255" posY="140">
<Arg name="response" value="ref:response"/>
<Script>
<Source> 
import javax.faces.application.FacesMessage;

List currentMessages = httpSession.getAttribute("sailpoint.web.PageCodeBase.sessionMessages");
List myMessages = new ArrayList();

int statusCode = (Integer) response.get("statusCode");

if (statusCode == 200) {
    FacesMessage myMessage = new FacesMessage(
        FacesMessage.SEVERITY_INFO,
        "Account Invite sent successfully.",
        "Account Invite sent successfully."
    );
    myMessages.add(myMessage);
} else {
    FacesMessage myMessage = new FacesMessage(
        FacesMessage.SEVERITY_ERROR,  // Changed to ERROR for unsuccessful cases
        "Account Invite failed to send. Please refer to email sent for more details.",
        "Account Invite failed to send. Please refer to email sent for more details."
    );
    myMessages.add(myMessage);
}

httpSession.setAttribute("sailpoint.web.PageCodeBase.sessionMessages", myMessages);
</Source> 
</Script>
<Transition to="Stop"/>
</Step>
  <Step icon="Stop" name="Stop" posX="342" posY="76"/>
</Workflow>

Apologies, I did not read the requirement properly. The reason why it’s not creating work items because you have the transient variable set to true . This tells SailPoint not to persist the workflow as a work item.

Can you please set it to false and try it. It should work. Please use your original code, which you shared and make the changes there.

if this resolved your issue, please mark this as Solution.

If more assistance needed, you can ping me directly. I have messaged you there as well.

Hi Naveen, setting transient = false causes the whole workflow to not execute. Any other possible solutions?

Hi @shijingg ,

Could you please explain your requirement clearly, is the form work item not getting created for the user to enter details or you want to view the form workitem after user submits the form.

If you remove the transient variable in workflow and enable the work item archive of type form, then you can see the submitted work item in work item archives (but it stores all the workitems of type Form which is not recommended).

I have verified your workflow code, work item is getting created.

Hi, I would want to view the work item in the work item archive post submission of the form. Currently, there is no more trail of the work item after I submit the form.

Could you advise how this can be done? “enable the work item archive of type form“?

Hi @shijingg ,

you can enable the work item archive of type form in Gear Icon → Global Settings → IdentityIQ Configuration → WorkItems → WorkItem Archives.

In the work item Archives select form, to enable the work item archives of type form, but it archives all the work items of type form not only this form workitem

I checked my settings and it has already been set up.

Could you please verify, if the transient variable is set to true in the workflow, if the transient variable is true in the workflow, then work item archive won’t be created.

If the transient variable is true in workflow, then try setting the transient variable to false. And verify if the work item archive is getting created or not.

The error you’re encountering is because the workflow is trying to serialize the httpSession object, which is not serializable. When you set transient="false" , SailPoint tries to persist the workflow state, but the session object cannot be persisted.

If you want to use httpsession in your workflow, I just playes around. Can you see if it works.

Please set the transient variable set to true and use the below code. It is working, and i can see form in workitem archive. I have just added few testing lines, you can remove those one.

I have attached the screenshot of workitem archive

<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE Workflow PUBLIC "sailpoint.dtd" "sailpoint.dtd">
<Workflow created="" explicitTransitions="true" id="

" modified="" name="Self Service View Workflow - Public Officer" significantModified="">
  <Variable input="true" name="launcher"/>
  <Variable name="email"/>
  <Variable name="mobile"/>
  <Variable name="response"/>
  <Variable name="statusCode"/>
  <Variable initializer="false" name="isValid"/>
  <Variable initializer="new java.util.ArrayList()" name="validationErrors"/>
  <Variable initializer="false" name="transient"/>
  <Step icon="Start" name="Start" posX="36" posY="82">
    <Transition to="Display Form"/>
  </Step>
  <Step icon="Default" name="Display Form" posX="128" posY="84">
    <Approval name="Account Invite Request" owner="script:return launcher;" return="email,mobile">
      <AfterScript>
        <Source>
          // Mark the approval as complete to archive the work item
          if (approval != null) {
              approval.setComplete(true);
          }
        </Source>
      </AfterScript>
      <Form name="Account Invite">
        <Attributes>
          <Map>
            <entry key="errors" value="ref:validationErrors"/>
            <entry key="pageTitle" value="Create Account"/>
          </Map>
        </Attributes>
        <Section name="User Details">
          <Field displayName="Email" helpKey="Valid email address should follow format: user@domain.com" name="email" required="true" type="string">
            <ValidationScript>
              <Source>
                import sailpoint.object.*;
                import sailpoint.tools.GeneralException;
                import org.apache.commons.lang.StringUtils;
                import sailpoint.tools.Message;
                import java.util.List;
                import java.util.Arrays;
                import java.util.regex.Pattern;

                Message msg = new Message();
                
                if (email != null &amp;&amp; !StringUtils.isEmpty(email.trim())) {
                    String emailValue = email.trim();
                    
                    // Validate email format first
                    String emailPattern = "^[A-Za-z0-9+_.-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}$";
                    if (!Pattern.matches(emailPattern, emailValue)) {
                        msg.setKey("Invalid email format. Please enter a valid email address (e.g., user@domain.com)");
                        return msg;
                    }
                    
                    // Extract and check domain
                    String domain = emailValue.substring(emailValue.lastIndexOf("@") + 1).toLowerCase();

                    // Add your allowed domains here
                    List validDomains = Arrays.asList(
                        "transport.gov.sg",
                        "transport.com",
                        "transport.com.sg",
                        "example.com"
                    );

                    if (!validDomains.contains(domain)) {
                        msg.setKey("Email domain '" + domain + "' is not allowed. Allowed domains: @transport.gov.sg, @transport.com, @transport.com.sg");
                        return msg;
                    }
                }
                return null;
              </Source>
            </ValidationScript>
          </Field>
          <Field displayName="Mobile Number" helpKey="Valid mobile number should follow format: +65-8xxxxxxx or +65-9xxxxxxx" name="mobile" required="true" type="string">
            <ValidationScript>
              <Source>
                import sailpoint.object.*;
                import sailpoint.tools.GeneralException;
                import org.apache.commons.lang.StringUtils;
                import sailpoint.tools.Message;
                import java.util.regex.Pattern;

                Message msg = new Message();
                if (mobile != null &amp;&amp; !StringUtils.isEmpty(mobile.trim())) {
                    // Remove all spaces from the phone number
                    String phoneValue = mobile.trim().replaceAll("\\s+", "");
                    
                    // Regex pattern for +65-8xxxxxxx or +65-9xxxxxxx
                    String phonePattern = "^\\+65-[89]\\d{7}$";
                    
                    if (!Pattern.matches(phonePattern, phoneValue)) {
                        msg.setKey("Invalid phone number format. Phone number must be in format: +65-8xxxxxxx or +65-9xxxxxxx");
                        return msg;
                    }
                }
                return null;
              </Source>
            </ValidationScript>
          </Field>
        </Section>
        <Button action="next" label="Submit"/>
        <Button action="cancel" label="Cancel"/>
      </Form>
    </Approval>
    <Transition to="Execute Rule">
      <Script>
        <Source>
          // Only proceed if form was submitted (not cancelled)
          return "next".equals(approval.getState());
        </Source>
      </Script>
    </Transition>
    <Transition to="Stop">
      <Script>
        <Source>
          // Go to stop if cancelled
          return "cancel".equals(approval.getState());
        </Source>
      </Script>
    </Transition>
  </Step>
  <Step action="rule:Account Invite" icon="Default" name="Execute Rule" posX="255" posY="140" resultVariable="response">
    <Transition to="Set Confirmation Message"/>
  </Step>
  <Step icon="Default" name="Set Confirmation Message" posX="255" posY="200">
    <Script>
      <Source>
        import javax.faces.application.FacesMessage;
        
        try {
            // Get status code
            statusCode = (Integer) response.get("statusCode");
            
            // Set session message if httpSession is available
            if (httpSession != null) {
                List myMessages = new ArrayList();
                
                if (statusCode == 200) {
                    FacesMessage myMessage = new FacesMessage(
                        FacesMessage.SEVERITY_INFO,
                        "Account Invite sent successfully for " + email,
                        "Account Invite sent successfully."
                    );
                    myMessages.add(myMessage);
                } else {
                    FacesMessage myMessage = new FacesMessage(
                        FacesMessage.SEVERITY_ERROR,
                        "Account Invite failed to send for " + email,
                        "Account Invite failed to send. Please refer to email sent for more details."
                    );
                    myMessages.add(myMessage);
                }
                
                httpSession.setAttribute("sailpoint.web.PageCodeBase.sessionMessages", myMessages);
            }
            
            // Log for audit trail
            log.info("Account Invite Request Completed - Email: " + email + ", Mobile: " + mobile + ", Status: " + statusCode);
            
        } catch (Exception e) {
            log.error("Error setting confirmation message: " + e.getMessage());
        }
      </Source>
    </Script>
    <Transition to="Stop"/>
  </Step>
  <Step icon="Stop" name="Stop" posX="342" posY="76"/>
</Workflow>

Hi @shijingg ,

Is your issue resolved now?? by using the above code.

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