<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>BeanShell on IAMDevBox</title><link>https://www.iamdevbox.com/tags/beanshell/</link><description>Recent content in BeanShell on IAMDevBox</description><image><title>IAMDevBox</title><url>https://www.iamdevbox.com/IAMDevBox.com.jpg</url><link>https://www.iamdevbox.com/IAMDevBox.com.jpg</link></image><generator>Hugo -- 0.146.0</generator><language>en-us</language><lastBuildDate>Thu, 20 Aug 2026 22:18:49 -0400</lastBuildDate><atom:link href="https://www.iamdevbox.com/tags/beanshell/index.xml" rel="self" type="application/rss+xml"/><item><title>SailPoint IdentityIQ BeanShell Rules, Workflows, and Tasks: A Developer's Guide</title><link>https://www.iamdevbox.com/posts/sailpoint-identityiq-beanshell-rules-workflows-tasks-developer-guide/</link><pubDate>Thu, 20 Aug 2026 10:00:00 +0000</pubDate><guid>https://www.iamdevbox.com/posts/sailpoint-identityiq-beanshell-rules-workflows-tasks-developer-guide/</guid><description>SailPoint IdentityIQ BeanShell rules, workflows, and tasks explained: rule types, SailPointContext API, workflow approvals, task executors, and iiq console.</description><content:encoded><![CDATA[<p>SailPoint IdentityIQ ships with three extension points where you write code: <strong>rules</strong> (BeanShell scripts that compute a value), <strong>workflows</strong> (XML state machines that orchestrate multi-step processes), and <strong>tasks</strong> (scheduled jobs that operate on data in bulk). Almost every IdentityIQ customization you will ever build fits into one of those three. This guide covers what each one is for, the API you use inside them, and the failure modes that cost new IdentityIQ developers the most time.</p>
<p>If you are coming from a different IAM platform, the closest analogue is scripted customization in ForgeRock — see our <a href="/posts/forgerock-am-script-customization-a-practical-guide/">ForgeRock AM script customization guide</a> for a comparison of how the two platforms approach the same problem.</p>
<h2 id="choosing-the-right-extension-point">Choosing the Right Extension Point</h2>
<p>Before writing anything, pick the correct mechanism. Choosing wrong is the most expensive mistake in IdentityIQ development, because migrating logic from a rule to a workflow later means rewriting it entirely.</p>
<table>
  <thead>
      <tr>
          <th>You need to&hellip;</th>
          <th>Use</th>
          <th>Runs</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Transform an attribute value</td>
          <td>Rule</td>
          <td>Synchronously, in-process</td>
      </tr>
      <tr>
          <td>Match an account to an identity</td>
          <td>Correlation Rule</td>
          <td>During aggregation</td>
      </tr>
      <tr>
          <td>Decide who approves a request</td>
          <td>Workflow</td>
          <td>Asynchronously, may pause for days</td>
      </tr>
      <tr>
          <td>Process every identity in bulk</td>
          <td>Task</td>
          <td>On a schedule</td>
      </tr>
      <tr>
          <td>Modify data on its way to a target system</td>
          <td>Provisioning Rule</td>
          <td>During provisioning</td>
      </tr>
  </tbody>
</table>
<p>The dividing line between a rule and a workflow is <strong>whether the logic can pause</strong>. A rule runs start to finish in a single thread and returns one value. If your logic needs to wait for a human, it must be a workflow.</p>
<h2 id="beanshell-the-language-identityiq-actually-runs">BeanShell: The Language IdentityIQ Actually Runs</h2>
<p>IdentityIQ rules are written in BeanShell, a scripting language that interprets Java syntax at runtime. This is the single most important thing to understand about IdentityIQ development, because BeanShell&rsquo;s differences from Java cause the majority of production rule failures.</p>
<h3 id="what-beanshell-does-not-support">What BeanShell Does Not Support</h3>
<p>BeanShell implements Java syntax as of roughly Java 1.4. The following will fail:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#75715e">// GENERICS — not supported. This throws a parse error.</span>
</span></span><span style="display:flex;"><span>List<span style="color:#f92672">&lt;</span>String<span style="color:#f92672">&gt;</span> names <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> ArrayList<span style="color:#f92672">&lt;</span>String<span style="color:#f92672">&gt;</span>();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// Correct: use raw types</span>
</span></span><span style="display:flex;"><span>List names <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> ArrayList();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// LAMBDAS and streams — not supported</span>
</span></span><span style="display:flex;"><span>names.<span style="color:#a6e22e">stream</span>().<span style="color:#a6e22e">filter</span>(n <span style="color:#f92672">-&gt;</span> n.<span style="color:#a6e22e">startsWith</span>(<span style="color:#e6db74">&#34;a&#34;</span>));
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// Correct: use an explicit loop</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">for</span> (<span style="color:#66d9ef">int</span> i <span style="color:#f92672">=</span> 0; i <span style="color:#f92672">&lt;</span> names.<span style="color:#a6e22e">size</span>(); i<span style="color:#f92672">++</span>) {
</span></span><span style="display:flex;"><span>    String n <span style="color:#f92672">=</span> (String) names.<span style="color:#a6e22e">get</span>(i);
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> (n.<span style="color:#a6e22e">startsWith</span>(<span style="color:#e6db74">&#34;a&#34;</span>)) { <span style="color:#75715e">/* ... */</span> }
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// ANNOTATIONS — not supported</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">@Override</span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">public</span> String <span style="color:#a6e22e">toString</span>() { }
</span></span></code></pre></div><h3 id="loose-typing-hides-bugs-until-runtime">Loose Typing Hides Bugs Until Runtime</h3>
<p>BeanShell lets you declare variables without a type. This is convenient and dangerous:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#75715e">// Both are legal in BeanShell</span>
</span></span><span style="display:flex;"><span>String name <span style="color:#f92672">=</span> identity.<span style="color:#a6e22e">getName</span>();
</span></span><span style="display:flex;"><span>name <span style="color:#f92672">=</span> identity.<span style="color:#a6e22e">getName</span>();
</span></span></code></pre></div><p>Because the script is interpreted, a misspelled method name compiles fine and fails only when that specific branch executes. A rule that works in your test case can fail six months later the first time an identity hits an untested code path. Two defenses matter:</p>
<ol>
<li><strong>Always declare types explicitly.</strong> It does not make BeanShell check them at parse time, but it documents intent and catches cast errors sooner.</li>
<li><strong>Validate rules before deploying.</strong> The iiq console has a syntax checker — see the console section below.</li>
</ol>
<h3 id="null-safety-is-entirely-your-job">Null Safety Is Entirely Your Job</h3>
<p>IdentityIQ getters return <code>null</code> constantly. An identity may have no manager, a link may have no attribute, an application may not be assigned. Defensive null checks are not optional:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#f92672">import</span> sailpoint.object.Identity;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>Identity manager <span style="color:#f92672">=</span> identity.<span style="color:#a6e22e">getManager</span>();
</span></span><span style="display:flex;"><span>String managerEmail <span style="color:#f92672">=</span> <span style="color:#66d9ef">null</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">if</span> (manager <span style="color:#f92672">!=</span> <span style="color:#66d9ef">null</span>) {
</span></span><span style="display:flex;"><span>    managerEmail <span style="color:#f92672">=</span> manager.<span style="color:#a6e22e">getStringAttribute</span>(<span style="color:#e6db74">&#34;email&#34;</span>);
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">if</span> (managerEmail <span style="color:#f92672">==</span> <span style="color:#66d9ef">null</span> <span style="color:#f92672">||</span> managerEmail.<span style="color:#a6e22e">trim</span>().<span style="color:#a6e22e">length</span>() <span style="color:#f92672">==</span> 0) {
</span></span><span style="display:flex;"><span>    managerEmail <span style="color:#f92672">=</span> <span style="color:#e6db74">&#34;identity-governance@example.com&#34;</span>;  <span style="color:#75715e">// fallback</span>
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">return</span> managerEmail;
</span></span></code></pre></div><h2 id="rules-the-most-common-extension-point">Rules: The Most Common Extension Point</h2>
<p>A rule is a <code>Rule</code> object stored in the database, containing a BeanShell script and a declared type. The type determines <strong>which arguments IdentityIQ passes in</strong>, and this is where most confusion lives — every rule type receives a different set of variables.</p>
<h3 id="anatomy-of-a-rule">Anatomy of a Rule</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-xml" data-lang="xml"><span style="display:flex;"><span><span style="color:#75715e">&lt;?xml version=&#39;1.0&#39; encoding=&#39;UTF-8&#39;?&gt;</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">&lt;!DOCTYPE Rule PUBLIC &#34;sailpoint.dtd&#34; &#34;sailpoint.dtd&#34;&gt;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">&lt;Rule</span> <span style="color:#a6e22e">language=</span><span style="color:#e6db74">&#34;beanshell&#34;</span> <span style="color:#a6e22e">name=</span><span style="color:#e6db74">&#34;Example Manager Email Rule&#34;</span> <span style="color:#a6e22e">type=</span><span style="color:#e6db74">&#34;IdentityAttribute&#34;</span><span style="color:#f92672">&gt;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&lt;Description&gt;</span>
</span></span><span style="display:flex;"><span>    Returns the manager&#39;s email address, falling back to a governance mailbox.
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&lt;/Description&gt;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&lt;Signature</span> <span style="color:#a6e22e">returnType=</span><span style="color:#e6db74">&#34;String&#34;</span><span style="color:#f92672">&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&lt;Inputs&gt;</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&lt;Argument</span> <span style="color:#a6e22e">name=</span><span style="color:#e6db74">&#34;identity&#34;</span> <span style="color:#a6e22e">type=</span><span style="color:#e6db74">&#34;sailpoint.object.Identity&#34;</span><span style="color:#f92672">/&gt;</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&lt;Argument</span> <span style="color:#a6e22e">name=</span><span style="color:#e6db74">&#34;context&#34;</span> <span style="color:#a6e22e">type=</span><span style="color:#e6db74">&#34;sailpoint.api.SailPointContext&#34;</span><span style="color:#f92672">/&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&lt;/Inputs&gt;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&lt;/Signature&gt;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&lt;Source&gt;</span><span style="color:#75715e">&lt;![CDATA[
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">    import sailpoint.object.Identity;
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">    if (identity == null) {
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">        return null;
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">    }
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">    Identity manager = identity.getManager();
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">    if (manager == null) {
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">        return &#34;identity-governance@example.com&#34;;
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">    }
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">    return manager.getStringAttribute(&#34;email&#34;);
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">  ]]&gt;</span><span style="color:#f92672">&lt;/Source&gt;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">&lt;/Rule&gt;</span>
</span></span></code></pre></div><p>Three details matter here:</p>
<ul>
<li><strong>The <code>&lt;Source&gt;</code> must be wrapped in <code>CDATA</code>.</strong> Without it, any <code>&lt;</code>, <code>&gt;</code>, or <code>&amp;</code> in your code breaks the XML parse.</li>
<li><strong>The <code>type</code> attribute is not cosmetic.</strong> It controls the input arguments and where the rule appears in the UI dropdowns.</li>
<li><strong><code>&lt;Signature&gt;</code> is documentation, not enforcement.</strong> BeanShell does not validate arguments against it. Declaring an argument that IdentityIQ does not actually pass yields <code>null</code> at runtime, not an error.</li>
</ul>
<h3 id="rule-types-you-will-actually-write">Rule Types You Will Actually Write</h3>
<p>IdentityIQ defines dozens of rule types. In practice, a small handful cover most work:</p>
<p><strong>BuildMap</strong> — Runs once per row of incoming data during aggregation, converting a raw record into a <code>Map</code> of attributes. Required by the JDBC connector, and used heavily with delimited-file connectors. The <code>record</code> variable holds the incoming data:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#f92672">import</span> java.util.HashMap;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>HashMap resultMap <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> HashMap();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">for</span> (<span style="color:#66d9ef">int</span> i <span style="color:#f92672">=</span> 0; i <span style="color:#f92672">&lt;</span> cols.<span style="color:#a6e22e">size</span>(); i<span style="color:#f92672">++</span>) {
</span></span><span style="display:flex;"><span>    String colName <span style="color:#f92672">=</span> (String) cols.<span style="color:#a6e22e">get</span>(i);
</span></span><span style="display:flex;"><span>    Object value <span style="color:#f92672">=</span> record.<span style="color:#a6e22e">get</span>(colName);
</span></span><span style="display:flex;"><span>    resultMap.<span style="color:#a6e22e">put</span>(colName, value);
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// Derive a value that does not exist in the source</span>
</span></span><span style="display:flex;"><span>String status <span style="color:#f92672">=</span> (String) resultMap.<span style="color:#a6e22e">get</span>(<span style="color:#e6db74">&#34;EMP_STATUS&#34;</span>);
</span></span><span style="display:flex;"><span>resultMap.<span style="color:#a6e22e">put</span>(<span style="color:#e6db74">&#34;isActive&#34;</span>, <span style="color:#e6db74">&#34;1&#34;</span>.<span style="color:#a6e22e">equals</span>(status) <span style="color:#f92672">?</span> <span style="color:#e6db74">&#34;true&#34;</span> : <span style="color:#e6db74">&#34;false&#34;</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">return</span> resultMap;
</span></span></code></pre></div><p><strong>Correlation</strong> — Decides which identity an account belongs to when a simple attribute match is not enough. Returns a <code>Map</code> naming the identity attribute to match on:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#f92672">import</span> java.util.HashMap;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>HashMap result <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> HashMap();
</span></span><span style="display:flex;"><span>String employeeId <span style="color:#f92672">=</span> (String) account.<span style="color:#a6e22e">getAttribute</span>(<span style="color:#e6db74">&#34;employeeNumber&#34;</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">if</span> (employeeId <span style="color:#f92672">!=</span> <span style="color:#66d9ef">null</span> <span style="color:#f92672">&amp;&amp;</span> employeeId.<span style="color:#a6e22e">length</span>() <span style="color:#f92672">&gt;</span> 0) {
</span></span><span style="display:flex;"><span>    <span style="color:#75715e">// Strip a legacy prefix before matching</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> (employeeId.<span style="color:#a6e22e">startsWith</span>(<span style="color:#e6db74">&#34;E-&#34;</span>)) {
</span></span><span style="display:flex;"><span>        employeeId <span style="color:#f92672">=</span> employeeId.<span style="color:#a6e22e">substring</span>(2);
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>    result.<span style="color:#a6e22e">put</span>(<span style="color:#e6db74">&#34;identityAttributeName&#34;</span>, <span style="color:#e6db74">&#34;employeeId&#34;</span>);
</span></span><span style="display:flex;"><span>    result.<span style="color:#a6e22e">put</span>(<span style="color:#e6db74">&#34;identityAttributeValue&#34;</span>, employeeId);
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">return</span> result;
</span></span></code></pre></div><p><strong>IdentityAttribute</strong> — Computes a value for an identity attribute during the Identity Refresh task. Receives <code>identity</code> and, for some configurations, <code>link</code>.</p>
<p><strong>Provisioning / BeforeProvisioning / AfterProvisioning</strong> — Modify a <code>ProvisioningPlan</code> on its way to a target system. The canonical use case is translating IdentityIQ&rsquo;s values into whatever encoding the target expects — for instance converting <code>&quot;Full&quot;</code> to the numeric code <code>1</code>.</p>
<p><strong>Certification</strong> — Filter or pre-decide certification items, typically to auto-approve low-risk entitlements so reviewers only see what matters.</p>
<blockquote>
<p><strong>Find the exact arguments for any rule type</strong> in <code>IdentityIQ_HOME/WEB-INF/config/examplerules.xml</code>. This file contains a working example of every rule type with its real input arguments, and it is more reliable than the documentation for this specific question.</p></blockquote>
<h3 id="rule-libraries-prevent-copy-paste-sprawl">Rule Libraries Prevent Copy-Paste Sprawl</h3>
<p>Do not duplicate helper logic across twenty rules. Put shared functions in a rule of type <code>null</code> and reference it:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-xml" data-lang="xml"><span style="display:flex;"><span><span style="color:#f92672">&lt;Rule</span> <span style="color:#a6e22e">language=</span><span style="color:#e6db74">&#34;beanshell&#34;</span> <span style="color:#a6e22e">name=</span><span style="color:#e6db74">&#34;Example Rule Library&#34;</span> <span style="color:#a6e22e">type=</span><span style="color:#e6db74">&#34;null&#34;</span><span style="color:#f92672">&gt;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&lt;Source&gt;</span><span style="color:#75715e">&lt;![CDATA[
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">    public static String normalizeDepartment(String raw) {
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">        if (raw == null) return &#34;UNKNOWN&#34;;
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">        return raw.trim().toUpperCase().replaceAll(&#34;[^A-Z0-9]&#34;, &#34;_&#34;);
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">    }
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">  ]]&gt;</span><span style="color:#f92672">&lt;/Source&gt;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">&lt;/Rule&gt;</span>
</span></span></code></pre></div><p>Then in any consuming rule:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-xml" data-lang="xml"><span style="display:flex;"><span><span style="color:#f92672">&lt;Rule</span> <span style="color:#a6e22e">language=</span><span style="color:#e6db74">&#34;beanshell&#34;</span> <span style="color:#a6e22e">name=</span><span style="color:#e6db74">&#34;Department Attribute Rule&#34;</span> <span style="color:#a6e22e">type=</span><span style="color:#e6db74">&#34;IdentityAttribute&#34;</span><span style="color:#f92672">&gt;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&lt;ReferencedRules&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&lt;Reference</span> <span style="color:#a6e22e">class=</span><span style="color:#e6db74">&#34;sailpoint.object.Rule&#34;</span> <span style="color:#a6e22e">name=</span><span style="color:#e6db74">&#34;Example Rule Library&#34;</span><span style="color:#f92672">/&gt;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&lt;/ReferencedRules&gt;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&lt;Source&gt;</span><span style="color:#75715e">&lt;![CDATA[
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">    return normalizeDepartment(identity.getStringAttribute(&#34;dept&#34;));
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">  ]]&gt;</span><span style="color:#f92672">&lt;/Source&gt;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">&lt;/Rule&gt;</span>
</span></span></code></pre></div><h2 id="the-sailpointcontext-api">The SailPointContext API</h2>
<p><code>SailPointContext</code> is your handle to the database. Nearly every rule receives it as <code>context</code>. Four operations cover most usage:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#f92672">import</span> sailpoint.object.Identity;
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> sailpoint.object.Application;
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> sailpoint.object.Filter;
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> sailpoint.object.QueryOptions;
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> java.util.Iterator;
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> java.util.List;
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> java.util.ArrayList;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// 1. Fetch a single object by name</span>
</span></span><span style="display:flex;"><span>Identity user <span style="color:#f92672">=</span> context.<span style="color:#a6e22e">getObjectByName</span>(Identity.<span style="color:#a6e22e">class</span>, <span style="color:#e6db74">&#34;jdoe&#34;</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// 2. Fetch by ID</span>
</span></span><span style="display:flex;"><span>Application app <span style="color:#f92672">=</span> context.<span style="color:#a6e22e">getObjectById</span>(Application.<span style="color:#a6e22e">class</span>, appId);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// 3. Query with filters</span>
</span></span><span style="display:flex;"><span>QueryOptions qo <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> QueryOptions();
</span></span><span style="display:flex;"><span>qo.<span style="color:#a6e22e">addFilter</span>(Filter.<span style="color:#a6e22e">eq</span>(<span style="color:#e6db74">&#34;inactive&#34;</span>, <span style="color:#66d9ef">new</span> Boolean(<span style="color:#66d9ef">false</span>)));
</span></span><span style="display:flex;"><span>qo.<span style="color:#a6e22e">addFilter</span>(Filter.<span style="color:#a6e22e">like</span>(<span style="color:#e6db74">&#34;department&#34;</span>, <span style="color:#e6db74">&#34;Engineering&#34;</span>, Filter.<span style="color:#a6e22e">MatchMode</span>.<span style="color:#a6e22e">START</span>));
</span></span><span style="display:flex;"><span>List identities <span style="color:#f92672">=</span> context.<span style="color:#a6e22e">getObjects</span>(Identity.<span style="color:#a6e22e">class</span>, qo);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e">// 4. Save changes — BOTH calls are required</span>
</span></span><span style="display:flex;"><span>user.<span style="color:#a6e22e">setAttribute</span>(<span style="color:#e6db74">&#34;riskTier&#34;</span>, <span style="color:#e6db74">&#34;HIGH&#34;</span>);
</span></span><span style="display:flex;"><span>context.<span style="color:#a6e22e">saveObject</span>(user);
</span></span><span style="display:flex;"><span>context.<span style="color:#a6e22e">commitTransaction</span>();
</span></span></code></pre></div><h3 id="use-projection-queries-for-bulk-reads">Use Projection Queries for Bulk Reads</h3>
<p><code>context.getObjects()</code> hydrates every full object into memory. Against a large identity cube this will exhaust the heap. When you only need a few fields, use a projection query, which returns an iterator over <code>Object[]</code> rows and streams results:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#f92672">import</span> sailpoint.object.QueryOptions;
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> sailpoint.object.Identity;
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> java.util.Iterator;
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> java.util.ArrayList;
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> java.util.List;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>QueryOptions qo <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> QueryOptions();
</span></span><span style="display:flex;"><span>qo.<span style="color:#a6e22e">addFilter</span>(Filter.<span style="color:#a6e22e">eq</span>(<span style="color:#e6db74">&#34;inactive&#34;</span>, <span style="color:#66d9ef">new</span> Boolean(<span style="color:#66d9ef">false</span>)));
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>List props <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> ArrayList();
</span></span><span style="display:flex;"><span>props.<span style="color:#a6e22e">add</span>(<span style="color:#e6db74">&#34;id&#34;</span>);
</span></span><span style="display:flex;"><span>props.<span style="color:#a6e22e">add</span>(<span style="color:#e6db74">&#34;name&#34;</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>Iterator it <span style="color:#f92672">=</span> context.<span style="color:#a6e22e">search</span>(Identity.<span style="color:#a6e22e">class</span>, qo, props);
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">int</span> count <span style="color:#f92672">=</span> 0;
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">while</span> (it.<span style="color:#a6e22e">hasNext</span>()) {
</span></span><span style="display:flex;"><span>    Object<span style="color:#f92672">[]</span> row <span style="color:#f92672">=</span> (Object<span style="color:#f92672">[]</span>) it.<span style="color:#a6e22e">next</span>();
</span></span><span style="display:flex;"><span>    String id <span style="color:#f92672">=</span> (String) row<span style="color:#f92672">[</span>0<span style="color:#f92672">]</span>;
</span></span><span style="display:flex;"><span>    String name <span style="color:#f92672">=</span> (String) row<span style="color:#f92672">[</span>1<span style="color:#f92672">]</span>;
</span></span><span style="display:flex;"><span>    count<span style="color:#f92672">++</span>;
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">return</span> <span style="color:#e6db74">&#34;Processed &#34;</span> <span style="color:#f92672">+</span> count <span style="color:#f92672">+</span> <span style="color:#e6db74">&#34; identities&#34;</span>;
</span></span></code></pre></div><p>For long-running loops, call <code>context.decache()</code> periodically to clear the Hibernate session, or memory will grow until the task fails.</p>
<h2 id="workflows-orchestrating-processes-that-pause">Workflows: Orchestrating Processes That Pause</h2>
<p>A workflow is an XML state machine. It exists because rules cannot wait. When a user requests access and a manager must approve it, the process may sit idle for days — the workflow persists to a <code>WorkflowCase</code> row and resumes when the approval arrives, surviving application restarts.</p>
<h3 id="steps-and-transitions">Steps and Transitions</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-xml" data-lang="xml"><span style="display:flex;"><span><span style="color:#f92672">&lt;Workflow</span> <span style="color:#a6e22e">name=</span><span style="color:#e6db74">&#34;Example Access Request Approval&#34;</span> <span style="color:#a6e22e">type=</span><span style="color:#e6db74">&#34;LCMProvisioning&#34;</span><span style="color:#f92672">&gt;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&lt;Variable</span> <span style="color:#a6e22e">name=</span><span style="color:#e6db74">&#34;identityName&#34;</span> <span style="color:#a6e22e">input=</span><span style="color:#e6db74">&#34;true&#34;</span><span style="color:#f92672">/&gt;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&lt;Variable</span> <span style="color:#a6e22e">name=</span><span style="color:#e6db74">&#34;plan&#34;</span> <span style="color:#a6e22e">input=</span><span style="color:#e6db74">&#34;true&#34;</span><span style="color:#f92672">/&gt;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&lt;Variable</span> <span style="color:#a6e22e">name=</span><span style="color:#e6db74">&#34;approvalDecision&#34;</span><span style="color:#f92672">/&gt;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&lt;Step</span> <span style="color:#a6e22e">name=</span><span style="color:#e6db74">&#34;Start&#34;</span> <span style="color:#a6e22e">icon=</span><span style="color:#e6db74">&#34;Start&#34;</span><span style="color:#f92672">&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&lt;Transition</span> <span style="color:#a6e22e">to=</span><span style="color:#e6db74">&#34;Evaluate Risk&#34;</span><span style="color:#f92672">/&gt;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&lt;/Step&gt;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&lt;Step</span> <span style="color:#a6e22e">name=</span><span style="color:#e6db74">&#34;Evaluate Risk&#34;</span> <span style="color:#a6e22e">resultVariable=</span><span style="color:#e6db74">&#34;riskLevel&#34;</span><span style="color:#f92672">&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&lt;Script&gt;</span><span style="color:#75715e">&lt;![CDATA[
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">      import sailpoint.object.Identity;
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">      Identity id = context.getObjectByName(Identity.class, identityName);
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">      if (id != null &amp;&amp; id.getScore() != null &amp;&amp; id.getScore().intValue() &gt; 500) {
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">          return &#34;HIGH&#34;;
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">      }
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">      return &#34;LOW&#34;;
</span></span></span><span style="display:flex;"><span><span style="color:#75715e">    ]]&gt;</span><span style="color:#f92672">&lt;/Script&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&lt;Transition</span> <span style="color:#a6e22e">to=</span><span style="color:#e6db74">&#34;Manager Approval&#34;</span> <span style="color:#a6e22e">when=</span><span style="color:#e6db74">&#39;riskLevel == &#34;HIGH&#34;&#39;</span><span style="color:#f92672">/&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&lt;Transition</span> <span style="color:#a6e22e">to=</span><span style="color:#e6db74">&#34;Auto Approve&#34;</span><span style="color:#f92672">/&gt;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&lt;/Step&gt;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&lt;Step</span> <span style="color:#a6e22e">name=</span><span style="color:#e6db74">&#34;Manager Approval&#34;</span><span style="color:#f92672">&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&lt;Approval</span> <span style="color:#a6e22e">mode=</span><span style="color:#e6db74">&#34;serial&#34;</span> <span style="color:#a6e22e">owner=</span><span style="color:#e6db74">&#34;script:...&#34;</span><span style="color:#f92672">&gt;</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&lt;Arg</span> <span style="color:#a6e22e">name=</span><span style="color:#e6db74">&#34;workItemDescription&#34;</span> <span style="color:#a6e22e">value=</span><span style="color:#e6db74">&#34;Approve access request&#34;</span><span style="color:#f92672">/&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&lt;/Approval&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&lt;Transition</span> <span style="color:#a6e22e">to=</span><span style="color:#e6db74">&#34;Provision&#34;</span><span style="color:#f92672">/&gt;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&lt;/Step&gt;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&lt;Step</span> <span style="color:#a6e22e">name=</span><span style="color:#e6db74">&#34;Auto Approve&#34;</span><span style="color:#f92672">&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&lt;Transition</span> <span style="color:#a6e22e">to=</span><span style="color:#e6db74">&#34;Provision&#34;</span><span style="color:#f92672">/&gt;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&lt;/Step&gt;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&lt;Step</span> <span style="color:#a6e22e">name=</span><span style="color:#e6db74">&#34;Provision&#34;</span> <span style="color:#a6e22e">action=</span><span style="color:#e6db74">&#34;call:provisionProject&#34;</span><span style="color:#f92672">&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&lt;Transition</span> <span style="color:#a6e22e">to=</span><span style="color:#e6db74">&#34;Stop&#34;</span><span style="color:#f92672">/&gt;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&lt;/Step&gt;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&lt;Step</span> <span style="color:#a6e22e">name=</span><span style="color:#e6db74">&#34;Stop&#34;</span> <span style="color:#a6e22e">icon=</span><span style="color:#e6db74">&#34;Stop&#34;</span><span style="color:#f92672">/&gt;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">&lt;/Workflow&gt;</span>
</span></span></code></pre></div><p>Key mechanics:</p>
<ul>
<li><strong><code>&lt;Transition&gt;</code> order matters.</strong> They are evaluated top to bottom and the first matching <code>when</code> wins. Always place a bare <code>&lt;Transition&gt;</code> last as the default branch, or the workflow will dead-end.</li>
<li><strong><code>resultVariable</code></strong> captures a step&rsquo;s return value into a workflow variable usable by later steps and transition conditions.</li>
<li><strong>Variables marked <code>input=&quot;true&quot;</code></strong> are supplied by the caller. Everything else starts null.</li>
</ul>
<h3 id="debugging-workflows">Debugging Workflows</h3>
<p>Workflows fail silently more often than rules do, because a failed transition simply stops the case. Two techniques:</p>
<ol>
<li><strong>Enable workflow trace.</strong> Add <code>&lt;Arg name=&quot;trace&quot; value=&quot;true&quot;/&gt;</code> to the workflow, and step-by-step execution prints to stdout — usually <code>catalina.out</code> on Tomcat.</li>
<li><strong>Inspect the stuck case.</strong> In the iiq console: <code>list WorkflowCase</code> then <code>checkout WorkflowCase &quot;&lt;name&gt;&quot; /tmp/case.xml</code> to see exactly which step it halted on and the state of every variable.</li>
</ol>
<h2 id="tasks-scheduled-bulk-operations">Tasks: Scheduled Bulk Operations</h2>
<p>Tasks are <code>TaskDefinition</code> objects run on a schedule. The built-ins cover most needs — <strong>Account Aggregation</strong> pulls accounts from a source, <strong>Identity Refresh</strong> recalculates attributes, roles, and risk scores across the identity cube.</p>
<p>When you need behaviour the built-ins do not provide, write a custom task executor in Java (not BeanShell) by implementing <code>TaskExecutor</code>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#f92672">package</span> com.example.iiq.task;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> sailpoint.api.SailPointContext;
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> sailpoint.object.Attributes;
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> sailpoint.object.TaskResult;
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> sailpoint.object.TaskSchedule;
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> sailpoint.task.AbstractTaskExecutor;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">DormantAccountTask</span> <span style="color:#66d9ef">extends</span> AbstractTaskExecutor {
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">private</span> <span style="color:#66d9ef">boolean</span> terminated <span style="color:#f92672">=</span> <span style="color:#66d9ef">false</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">execute</span>(SailPointContext context, TaskSchedule schedule,
</span></span><span style="display:flex;"><span>                        TaskResult result, Attributes args) <span style="color:#66d9ef">throws</span> Exception {
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">int</span> threshold <span style="color:#f92672">=</span> args.<span style="color:#a6e22e">getInt</span>(<span style="color:#e6db74">&#34;dormantDays&#34;</span>, 90);
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">int</span> processed <span style="color:#f92672">=</span> 0;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#75715e">// ... query and process identities, checking terminated each iteration</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        result.<span style="color:#a6e22e">setAttribute</span>(<span style="color:#e6db74">&#34;identitiesProcessed&#34;</span>, <span style="color:#66d9ef">new</span> Integer(processed));
</span></span><span style="display:flex;"><span>        result.<span style="color:#a6e22e">setAttribute</span>(<span style="color:#e6db74">&#34;dormantThreshold&#34;</span>, <span style="color:#66d9ef">new</span> Integer(threshold));
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">public</span> <span style="color:#66d9ef">boolean</span> <span style="color:#a6e22e">terminate</span>() {
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">this</span>.<span style="color:#a6e22e">terminated</span> <span style="color:#f92672">=</span> <span style="color:#66d9ef">true</span>;
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">return</span> <span style="color:#66d9ef">true</span>;
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Compile this into a JAR, drop it in <code>IdentityIQ_HOME/WEB-INF/lib/</code>, restart the application server, and register it with a <code>TaskDefinition</code> XML pointing at the class name.</p>
<p><strong>Always honour <code>terminate()</code>.</strong> A task that ignores it cannot be stopped from the UI, and an administrator&rsquo;s only remaining option is restarting the application server.</p>
<h2 id="the-iiq-console">The iiq Console</h2>
<p>The console is where you deploy, inspect, and debug. Launch it from <code>IdentityIQ_HOME/WEB-INF/bin</code>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>./iiq console          <span style="color:#75715e"># Linux/macOS</span>
</span></span><span style="display:flex;"><span>iiq.bat console        <span style="color:#75715e"># Windows</span>
</span></span></code></pre></div><p>It requires the System Administrator capability and authenticates as <code>spadmin</code> by default. The commands you will use constantly:</p>



<div class="goat svg-container ">
  
    <svg
      xmlns="http://www.w3.org/2000/svg"
      font-family="Menlo,Lucida Console,monospace"
      
        viewBox="0 0 568 105"
      >
      <g transform='translate(8,16)'>
<text text-anchor='middle' x='0' y='4' fill='currentColor' style='font-size:1em'>&gt;</text>
<text text-anchor='middle' x='0' y='20' fill='currentColor' style='font-size:1em'>&gt;</text>
<text text-anchor='middle' x='0' y='36' fill='currentColor' style='font-size:1em'>&gt;</text>
<text text-anchor='middle' x='0' y='52' fill='currentColor' style='font-size:1em'>&gt;</text>
<text text-anchor='middle' x='0' y='68' fill='currentColor' style='font-size:1em'>&gt;</text>
<text text-anchor='middle' x='0' y='84' fill='currentColor' style='font-size:1em'>&gt;</text>
<text text-anchor='middle' x='16' y='4' fill='currentColor' style='font-size:1em'>i</text>
<text text-anchor='middle' x='16' y='20' fill='currentColor' style='font-size:1em'>c</text>
<text text-anchor='middle' x='16' y='36' fill='currentColor' style='font-size:1em'>l</text>
<text text-anchor='middle' x='16' y='52' fill='currentColor' style='font-size:1em'>g</text>
<text text-anchor='middle' x='16' y='68' fill='currentColor' style='font-size:1em'>r</text>
<text text-anchor='middle' x='16' y='84' fill='currentColor' style='font-size:1em'>w</text>
<text text-anchor='middle' x='24' y='4' fill='currentColor' style='font-size:1em'>m</text>
<text text-anchor='middle' x='24' y='20' fill='currentColor' style='font-size:1em'>h</text>
<text text-anchor='middle' x='24' y='36' fill='currentColor' style='font-size:1em'>i</text>
<text text-anchor='middle' x='24' y='52' fill='currentColor' style='font-size:1em'>e</text>
<text text-anchor='middle' x='24' y='68' fill='currentColor' style='font-size:1em'>u</text>
<text text-anchor='middle' x='24' y='84' fill='currentColor' style='font-size:1em'>a</text>
<text text-anchor='middle' x='32' y='4' fill='currentColor' style='font-size:1em'>p</text>
<text text-anchor='middle' x='32' y='20' fill='currentColor' style='font-size:1em'>e</text>
<text text-anchor='middle' x='32' y='36' fill='currentColor' style='font-size:1em'>s</text>
<text text-anchor='middle' x='32' y='52' fill='currentColor' style='font-size:1em'>t</text>
<text text-anchor='middle' x='32' y='68' fill='currentColor' style='font-size:1em'>l</text>
<text text-anchor='middle' x='32' y='84' fill='currentColor' style='font-size:1em'>r</text>
<text text-anchor='middle' x='40' y='4' fill='currentColor' style='font-size:1em'>o</text>
<text text-anchor='middle' x='40' y='20' fill='currentColor' style='font-size:1em'>c</text>
<text text-anchor='middle' x='40' y='36' fill='currentColor' style='font-size:1em'>t</text>
<text text-anchor='middle' x='40' y='68' fill='currentColor' style='font-size:1em'>e</text>
<text text-anchor='middle' x='40' y='84' fill='currentColor' style='font-size:1em'>n</text>
<text text-anchor='middle' x='48' y='4' fill='currentColor' style='font-size:1em'>r</text>
<text text-anchor='middle' x='48' y='20' fill='currentColor' style='font-size:1em'>k</text>
<text text-anchor='middle' x='48' y='52' fill='currentColor' style='font-size:1em'>I</text>
<text text-anchor='middle' x='56' y='4' fill='currentColor' style='font-size:1em'>t</text>
<text text-anchor='middle' x='56' y='20' fill='currentColor' style='font-size:1em'>o</text>
<text text-anchor='middle' x='56' y='36' fill='currentColor' style='font-size:1em'>R</text>
<text text-anchor='middle' x='56' y='52' fill='currentColor' style='font-size:1em'>d</text>
<text text-anchor='middle' x='56' y='68' fill='currentColor' style='font-size:1em'>"</text>
<text text-anchor='middle' x='64' y='20' fill='currentColor' style='font-size:1em'>u</text>
<text text-anchor='middle' x='64' y='36' fill='currentColor' style='font-size:1em'>u</text>
<text text-anchor='middle' x='64' y='52' fill='currentColor' style='font-size:1em'>e</text>
<text text-anchor='middle' x='64' y='68' fill='currentColor' style='font-size:1em'>M</text>
<text text-anchor='middle' x='72' y='4' fill='currentColor' style='font-size:1em'>/</text>
<text text-anchor='middle' x='72' y='20' fill='currentColor' style='font-size:1em'>t</text>
<text text-anchor='middle' x='72' y='36' fill='currentColor' style='font-size:1em'>l</text>
<text text-anchor='middle' x='72' y='52' fill='currentColor' style='font-size:1em'>n</text>
<text text-anchor='middle' x='72' y='68' fill='currentColor' style='font-size:1em'>y</text>
<text text-anchor='middle' x='80' y='4' fill='currentColor' style='font-size:1em'>p</text>
<text text-anchor='middle' x='80' y='36' fill='currentColor' style='font-size:1em'>e</text>
<text text-anchor='middle' x='80' y='52' fill='currentColor' style='font-size:1em'>t</text>
<text text-anchor='middle' x='88' y='4' fill='currentColor' style='font-size:1em'>a</text>
<text text-anchor='middle' x='88' y='20' fill='currentColor' style='font-size:1em'>R</text>
<text text-anchor='middle' x='88' y='52' fill='currentColor' style='font-size:1em'>i</text>
<text text-anchor='middle' x='88' y='68' fill='currentColor' style='font-size:1em'>R</text>
<text text-anchor='middle' x='96' y='4' fill='currentColor' style='font-size:1em'>t</text>
<text text-anchor='middle' x='96' y='20' fill='currentColor' style='font-size:1em'>u</text>
<text text-anchor='middle' x='96' y='52' fill='currentColor' style='font-size:1em'>t</text>
<text text-anchor='middle' x='96' y='68' fill='currentColor' style='font-size:1em'>u</text>
<text text-anchor='middle' x='104' y='4' fill='currentColor' style='font-size:1em'>h</text>
<text text-anchor='middle' x='104' y='20' fill='currentColor' style='font-size:1em'>l</text>
<text text-anchor='middle' x='104' y='52' fill='currentColor' style='font-size:1em'>y</text>
<text text-anchor='middle' x='104' y='68' fill='currentColor' style='font-size:1em'>l</text>
<text text-anchor='middle' x='112' y='4' fill='currentColor' style='font-size:1em'>/</text>
<text text-anchor='middle' x='112' y='20' fill='currentColor' style='font-size:1em'>e</text>
<text text-anchor='middle' x='112' y='68' fill='currentColor' style='font-size:1em'>e</text>
<text text-anchor='middle' x='120' y='4' fill='currentColor' style='font-size:1em'>t</text>
<text text-anchor='middle' x='120' y='52' fill='currentColor' style='font-size:1em'>j</text>
<text text-anchor='middle' x='120' y='68' fill='currentColor' style='font-size:1em'>"</text>
<text text-anchor='middle' x='128' y='4' fill='currentColor' style='font-size:1em'>o</text>
<text text-anchor='middle' x='128' y='20' fill='currentColor' style='font-size:1em'>"</text>
<text text-anchor='middle' x='128' y='52' fill='currentColor' style='font-size:1em'>d</text>
<text text-anchor='middle' x='136' y='4' fill='currentColor' style='font-size:1em'>/</text>
<text text-anchor='middle' x='136' y='20' fill='currentColor' style='font-size:1em'>M</text>
<text text-anchor='middle' x='136' y='52' fill='currentColor' style='font-size:1em'>o</text>
<text text-anchor='middle' x='144' y='4' fill='currentColor' style='font-size:1em'>r</text>
<text text-anchor='middle' x='144' y='20' fill='currentColor' style='font-size:1em'>y</text>
<text text-anchor='middle' x='144' y='52' fill='currentColor' style='font-size:1em'>e</text>
<text text-anchor='middle' x='152' y='4' fill='currentColor' style='font-size:1em'>u</text>
<text text-anchor='middle' x='160' y='4' fill='currentColor' style='font-size:1em'>l</text>
<text text-anchor='middle' x='160' y='20' fill='currentColor' style='font-size:1em'>R</text>
<text text-anchor='middle' x='168' y='4' fill='currentColor' style='font-size:1em'>e</text>
<text text-anchor='middle' x='168' y='20' fill='currentColor' style='font-size:1em'>u</text>
<text text-anchor='middle' x='176' y='4' fill='currentColor' style='font-size:1em'>s</text>
<text text-anchor='middle' x='176' y='20' fill='currentColor' style='font-size:1em'>l</text>
<text text-anchor='middle' x='184' y='4' fill='currentColor' style='font-size:1em'>.</text>
<text text-anchor='middle' x='184' y='20' fill='currentColor' style='font-size:1em'>e</text>
<text text-anchor='middle' x='192' y='4' fill='currentColor' style='font-size:1em'>x</text>
<text text-anchor='middle' x='192' y='20' fill='currentColor' style='font-size:1em'>"</text>
<text text-anchor='middle' x='200' y='4' fill='currentColor' style='font-size:1em'>m</text>
<text text-anchor='middle' x='208' y='4' fill='currentColor' style='font-size:1em'>l</text>
<text text-anchor='middle' x='208' y='20' fill='currentColor' style='font-size:1em'>/</text>
<text text-anchor='middle' x='216' y='20' fill='currentColor' style='font-size:1em'>t</text>
<text text-anchor='middle' x='224' y='20' fill='currentColor' style='font-size:1em'>m</text>
<text text-anchor='middle' x='232' y='20' fill='currentColor' style='font-size:1em'>p</text>
<text text-anchor='middle' x='240' y='20' fill='currentColor' style='font-size:1em'>/</text>
<text text-anchor='middle' x='248' y='20' fill='currentColor' style='font-size:1em'>r</text>
<text text-anchor='middle' x='256' y='20' fill='currentColor' style='font-size:1em'>.</text>
<text text-anchor='middle' x='264' y='20' fill='currentColor' style='font-size:1em'>x</text>
<text text-anchor='middle' x='272' y='20' fill='currentColor' style='font-size:1em'>m</text>
<text text-anchor='middle' x='280' y='20' fill='currentColor' style='font-size:1em'>l</text>
<text text-anchor='middle' x='304' y='4' fill='currentColor' style='font-size:1em'>#</text>
<text text-anchor='middle' x='304' y='20' fill='currentColor' style='font-size:1em'>#</text>
<text text-anchor='middle' x='304' y='36' fill='currentColor' style='font-size:1em'>#</text>
<text text-anchor='middle' x='304' y='52' fill='currentColor' style='font-size:1em'>#</text>
<text text-anchor='middle' x='304' y='68' fill='currentColor' style='font-size:1em'>#</text>
<text text-anchor='middle' x='304' y='84' fill='currentColor' style='font-size:1em'>#</text>
<text text-anchor='middle' x='320' y='4' fill='currentColor' style='font-size:1em'>d</text>
<text text-anchor='middle' x='320' y='20' fill='currentColor' style='font-size:1em'>e</text>
<text text-anchor='middle' x='320' y='36' fill='currentColor' style='font-size:1em'>e</text>
<text text-anchor='middle' x='320' y='52' fill='currentColor' style='font-size:1em'>p</text>
<text text-anchor='middle' x='320' y='68' fill='currentColor' style='font-size:1em'>e</text>
<text text-anchor='middle' x='320' y='84' fill='currentColor' style='font-size:1em'>s</text>
<text text-anchor='middle' x='328' y='4' fill='currentColor' style='font-size:1em'>e</text>
<text text-anchor='middle' x='328' y='20' fill='currentColor' style='font-size:1em'>x</text>
<text text-anchor='middle' x='328' y='36' fill='currentColor' style='font-size:1em'>n</text>
<text text-anchor='middle' x='328' y='52' fill='currentColor' style='font-size:1em'>r</text>
<text text-anchor='middle' x='328' y='68' fill='currentColor' style='font-size:1em'>x</text>
<text text-anchor='middle' x='328' y='84' fill='currentColor' style='font-size:1em'>h</text>
<text text-anchor='middle' x='336' y='4' fill='currentColor' style='font-size:1em'>p</text>
<text text-anchor='middle' x='336' y='20' fill='currentColor' style='font-size:1em'>p</text>
<text text-anchor='middle' x='336' y='36' fill='currentColor' style='font-size:1em'>u</text>
<text text-anchor='middle' x='336' y='52' fill='currentColor' style='font-size:1em'>i</text>
<text text-anchor='middle' x='336' y='68' fill='currentColor' style='font-size:1em'>e</text>
<text text-anchor='middle' x='336' y='84' fill='currentColor' style='font-size:1em'>o</text>
<text text-anchor='middle' x='344' y='4' fill='currentColor' style='font-size:1em'>l</text>
<text text-anchor='middle' x='344' y='20' fill='currentColor' style='font-size:1em'>o</text>
<text text-anchor='middle' x='344' y='36' fill='currentColor' style='font-size:1em'>m</text>
<text text-anchor='middle' x='344' y='52' fill='currentColor' style='font-size:1em'>n</text>
<text text-anchor='middle' x='344' y='68' fill='currentColor' style='font-size:1em'>c</text>
<text text-anchor='middle' x='344' y='84' fill='currentColor' style='font-size:1em'>w</text>
<text text-anchor='middle' x='352' y='4' fill='currentColor' style='font-size:1em'>o</text>
<text text-anchor='middle' x='352' y='20' fill='currentColor' style='font-size:1em'>r</text>
<text text-anchor='middle' x='352' y='36' fill='currentColor' style='font-size:1em'>e</text>
<text text-anchor='middle' x='352' y='52' fill='currentColor' style='font-size:1em'>t</text>
<text text-anchor='middle' x='352' y='68' fill='currentColor' style='font-size:1em'>u</text>
<text text-anchor='middle' x='360' y='4' fill='currentColor' style='font-size:1em'>y</text>
<text text-anchor='middle' x='360' y='20' fill='currentColor' style='font-size:1em'>t</text>
<text text-anchor='middle' x='360' y='36' fill='currentColor' style='font-size:1em'>r</text>
<text text-anchor='middle' x='360' y='68' fill='currentColor' style='font-size:1em'>t</text>
<text text-anchor='middle' x='360' y='84' fill='currentColor' style='font-size:1em'>r</text>
<text text-anchor='middle' x='368' y='36' fill='currentColor' style='font-size:1em'>a</text>
<text text-anchor='middle' x='368' y='52' fill='currentColor' style='font-size:1em'>a</text>
<text text-anchor='middle' x='368' y='68' fill='currentColor' style='font-size:1em'>e</text>
<text text-anchor='middle' x='368' y='84' fill='currentColor' style='font-size:1em'>e</text>
<text text-anchor='middle' x='376' y='4' fill='currentColor' style='font-size:1em'>a</text>
<text text-anchor='middle' x='376' y='20' fill='currentColor' style='font-size:1em'>f</text>
<text text-anchor='middle' x='376' y='36' fill='currentColor' style='font-size:1em'>t</text>
<text text-anchor='middle' x='376' y='52' fill='currentColor' style='font-size:1em'>n</text>
<text text-anchor='middle' x='376' y='84' fill='currentColor' style='font-size:1em'>c</text>
<text text-anchor='middle' x='384' y='4' fill='currentColor' style='font-size:1em'>n</text>
<text text-anchor='middle' x='384' y='20' fill='currentColor' style='font-size:1em'>o</text>
<text text-anchor='middle' x='384' y='36' fill='currentColor' style='font-size:1em'>e</text>
<text text-anchor='middle' x='384' y='68' fill='currentColor' style='font-size:1em'>a</text>
<text text-anchor='middle' x='384' y='84' fill='currentColor' style='font-size:1em'>e</text>
<text text-anchor='middle' x='392' y='20' fill='currentColor' style='font-size:1em'>r</text>
<text text-anchor='middle' x='392' y='52' fill='currentColor' style='font-size:1em'>o</text>
<text text-anchor='middle' x='392' y='84' fill='currentColor' style='font-size:1em'>n</text>
<text text-anchor='middle' x='400' y='4' fill='currentColor' style='font-size:1em'>o</text>
<text text-anchor='middle' x='400' y='36' fill='currentColor' style='font-size:1em'>o</text>
<text text-anchor='middle' x='400' y='52' fill='currentColor' style='font-size:1em'>b</text>
<text text-anchor='middle' x='400' y='68' fill='currentColor' style='font-size:1em'>r</text>
<text text-anchor='middle' x='400' y='84' fill='currentColor' style='font-size:1em'>t</text>
<text text-anchor='middle' x='408' y='4' fill='currentColor' style='font-size:1em'>b</text>
<text text-anchor='middle' x='408' y='20' fill='currentColor' style='font-size:1em'>r</text>
<text text-anchor='middle' x='408' y='36' fill='currentColor' style='font-size:1em'>b</text>
<text text-anchor='middle' x='408' y='52' fill='currentColor' style='font-size:1em'>j</text>
<text text-anchor='middle' x='408' y='68' fill='currentColor' style='font-size:1em'>u</text>
<text text-anchor='middle' x='416' y='4' fill='currentColor' style='font-size:1em'>j</text>
<text text-anchor='middle' x='416' y='20' fill='currentColor' style='font-size:1em'>e</text>
<text text-anchor='middle' x='416' y='36' fill='currentColor' style='font-size:1em'>j</text>
<text text-anchor='middle' x='416' y='52' fill='currentColor' style='font-size:1em'>e</text>
<text text-anchor='middle' x='416' y='68' fill='currentColor' style='font-size:1em'>l</text>
<text text-anchor='middle' x='416' y='84' fill='currentColor' style='font-size:1em'>w</text>
<text text-anchor='middle' x='424' y='4' fill='currentColor' style='font-size:1em'>e</text>
<text text-anchor='middle' x='424' y='20' fill='currentColor' style='font-size:1em'>v</text>
<text text-anchor='middle' x='424' y='36' fill='currentColor' style='font-size:1em'>e</text>
<text text-anchor='middle' x='424' y='52' fill='currentColor' style='font-size:1em'>c</text>
<text text-anchor='middle' x='424' y='68' fill='currentColor' style='font-size:1em'>e</text>
<text text-anchor='middle' x='424' y='84' fill='currentColor' style='font-size:1em'>a</text>
<text text-anchor='middle' x='432' y='4' fill='currentColor' style='font-size:1em'>c</text>
<text text-anchor='middle' x='432' y='20' fill='currentColor' style='font-size:1em'>i</text>
<text text-anchor='middle' x='432' y='36' fill='currentColor' style='font-size:1em'>c</text>
<text text-anchor='middle' x='432' y='52' fill='currentColor' style='font-size:1em'>t</text>
<text text-anchor='middle' x='432' y='84' fill='currentColor' style='font-size:1em'>r</text>
<text text-anchor='middle' x='440' y='4' fill='currentColor' style='font-size:1em'>t</text>
<text text-anchor='middle' x='440' y='20' fill='currentColor' style='font-size:1em'>e</text>
<text text-anchor='middle' x='440' y='36' fill='currentColor' style='font-size:1em'>t</text>
<text text-anchor='middle' x='440' y='68' fill='currentColor' style='font-size:1em'>i</text>
<text text-anchor='middle' x='440' y='84' fill='currentColor' style='font-size:1em'>n</text>
<text text-anchor='middle' x='448' y='20' fill='currentColor' style='font-size:1em'>w</text>
<text text-anchor='middle' x='448' y='36' fill='currentColor' style='font-size:1em'>s</text>
<text text-anchor='middle' x='448' y='52' fill='currentColor' style='font-size:1em'>a</text>
<text text-anchor='middle' x='448' y='68' fill='currentColor' style='font-size:1em'>n</text>
<text text-anchor='middle' x='448' y='84' fill='currentColor' style='font-size:1em'>i</text>
<text text-anchor='middle' x='456' y='52' fill='currentColor' style='font-size:1em'>s</text>
<text text-anchor='middle' x='456' y='68' fill='currentColor' style='font-size:1em'>t</text>
<text text-anchor='middle' x='456' y='84' fill='currentColor' style='font-size:1em'>n</text>
<text text-anchor='middle' x='464' y='20' fill='currentColor' style='font-size:1em'>o</text>
<text text-anchor='middle' x='464' y='36' fill='currentColor' style='font-size:1em'>o</text>
<text text-anchor='middle' x='464' y='68' fill='currentColor' style='font-size:1em'>e</text>
<text text-anchor='middle' x='464' y='84' fill='currentColor' style='font-size:1em'>g</text>
<text text-anchor='middle' x='472' y='20' fill='currentColor' style='font-size:1em'>r</text>
<text text-anchor='middle' x='472' y='36' fill='currentColor' style='font-size:1em'>f</text>
<text text-anchor='middle' x='472' y='52' fill='currentColor' style='font-size:1em'>X</text>
<text text-anchor='middle' x='472' y='68' fill='currentColor' style='font-size:1em'>r</text>
<text text-anchor='middle' x='472' y='84' fill='currentColor' style='font-size:1em'>s</text>
<text text-anchor='middle' x='480' y='52' fill='currentColor' style='font-size:1em'>M</text>
<text text-anchor='middle' x='480' y='68' fill='currentColor' style='font-size:1em'>a</text>
<text text-anchor='middle' x='488' y='20' fill='currentColor' style='font-size:1em'>m</text>
<text text-anchor='middle' x='488' y='36' fill='currentColor' style='font-size:1em'>a</text>
<text text-anchor='middle' x='488' y='52' fill='currentColor' style='font-size:1em'>L</text>
<text text-anchor='middle' x='488' y='68' fill='currentColor' style='font-size:1em'>c</text>
<text text-anchor='middle' x='496' y='20' fill='currentColor' style='font-size:1em'>i</text>
<text text-anchor='middle' x='496' y='68' fill='currentColor' style='font-size:1em'>t</text>
<text text-anchor='middle' x='504' y='20' fill='currentColor' style='font-size:1em'>g</text>
<text text-anchor='middle' x='504' y='36' fill='currentColor' style='font-size:1em'>c</text>
<text text-anchor='middle' x='504' y='68' fill='currentColor' style='font-size:1em'>i</text>
<text text-anchor='middle' x='512' y='20' fill='currentColor' style='font-size:1em'>r</text>
<text text-anchor='middle' x='512' y='36' fill='currentColor' style='font-size:1em'>l</text>
<text text-anchor='middle' x='512' y='68' fill='currentColor' style='font-size:1em'>v</text>
<text text-anchor='middle' x='520' y='20' fill='currentColor' style='font-size:1em'>a</text>
<text text-anchor='middle' x='520' y='36' fill='currentColor' style='font-size:1em'>a</text>
<text text-anchor='middle' x='520' y='68' fill='currentColor' style='font-size:1em'>e</text>
<text text-anchor='middle' x='528' y='20' fill='currentColor' style='font-size:1em'>t</text>
<text text-anchor='middle' x='528' y='36' fill='currentColor' style='font-size:1em'>s</text>
<text text-anchor='middle' x='528' y='68' fill='currentColor' style='font-size:1em'>l</text>
<text text-anchor='middle' x='536' y='20' fill='currentColor' style='font-size:1em'>i</text>
<text text-anchor='middle' x='536' y='36' fill='currentColor' style='font-size:1em'>s</text>
<text text-anchor='middle' x='536' y='68' fill='currentColor' style='font-size:1em'>y</text>
<text text-anchor='middle' x='544' y='20' fill='currentColor' style='font-size:1em'>o</text>
<text text-anchor='middle' x='552' y='20' fill='currentColor' style='font-size:1em'>n</text>
</g>

    </svg>
  
</div>
<p><code>checkout</code> plus <code>import</code> is the migration path between environments. Export from dev, commit the XML to version control, import into test.</p>
<h2 id="logging-and-debugging">Logging and Debugging</h2>
<p>Configure logging in <code>IdentityIQ_HOME/WEB-INF/classes/log4j2.properties</code>. IdentityIQ picks up changes to this file automatically within roughly 60 seconds — <strong>no application restart required</strong>, which is the single biggest time-saver in IdentityIQ debugging.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-properties" data-lang="properties"><span style="display:flex;"><span><span style="color:#75715e"># Namespace your rule logging so you can raise it without drowning in output</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">logger.customrules.name</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">com.example.iiq</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">logger.customrules.level</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">debug</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># Useful built-in loggers</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">logger.connector.name</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">sailpoint.connector</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">logger.connector.level</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">debug</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">logger.workflow.name</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">sailpoint.workflow</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">logger.workflow.level</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">debug</span>
</span></span></code></pre></div><p>Inside a rule:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#f92672">import</span> org.apache.log4j.Logger;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>Logger log <span style="color:#f92672">=</span> Logger.<span style="color:#a6e22e">getLogger</span>(<span style="color:#e6db74">&#34;com.example.iiq.correlation&#34;</span>);
</span></span><span style="display:flex;"><span>log.<span style="color:#a6e22e">debug</span>(<span style="color:#e6db74">&#34;Correlating account: &#34;</span> <span style="color:#f92672">+</span> account.<span style="color:#a6e22e">getNativeIdentity</span>());
</span></span></code></pre></div><p>Never use <code>System.out.println()</code> in production rules. It writes to the container log with no level control, no namespace, and no way to disable it without a code change and restart.</p>
<h2 id="deployment-practices-that-prevent-outages">Deployment Practices That Prevent Outages</h2>
<p><strong>Version-control the XML, not the database.</strong> IdentityIQ objects live in the database, which makes them invisible to Git by default. Export every custom rule, workflow, and task definition with <code>checkout</code> and commit the XML. Without this, a database refresh silently destroys work.</p>
<p><strong>Never edit rules in production through the UI.</strong> The debug pages allow direct object editing, which creates changes that exist in exactly one environment and are lost on the next deployment.</p>
<p><strong>Test correlation rules against real edge cases</strong> — accounts with null employee IDs, duplicate IDs, service accounts that should match nothing. A correlation rule that throws an exception aborts the entire aggregation run, not just the one account.</p>
<p><strong>Keep rules short.</strong> A rule doing substantial work belongs in a compiled Java class in <code>WEB-INF/lib/</code>, called from a thin BeanShell wrapper. You get compile-time type checking, real unit tests, and a debugger.</p>
<h2 id="where-this-fits-in-broader-identity-governance">Where This Fits in Broader Identity Governance</h2>
<p>Rules, workflows, and tasks are the mechanics. What you build with them is governance — access certification, joiner-mover-leaver automation, separation-of-duties enforcement. For the strategic layer above this code, see our guide to <a href="/posts/identity-governance-in-the-zero-trust-era-achieving-dynamic-privileged-access-management-with-cyberark-and-sailpoint/">identity governance in the Zero Trust era</a>, and for where the platform is heading, <a href="/posts/sailpoint-extends-identity-governance-to-ai-agents-techinformed/">SailPoint&rsquo;s extension of governance to AI agents</a>.</p>
<p>The infrastructure underneath — the Java runtime, the MySQL schema your queries hit, and the shell scripts that automate deployment — is covered in the companion article on <a href="/posts/sailpoint-identityiq-java-mysql-shell-scripting-guide/">Java, MySQL, and shell scripting for SailPoint IdentityIQ</a>.</p>
]]></content:encoded></item></channel></rss>