Dynamic Form in Workflow

Problem

I am trying to setup a dynamic form inside of a workflow but somehow the fields i am trying to set are not appearing. I don’t know if the issue is the use of the InterceptorScript or something else. Everything else works fine: I get the form, the different display-types work but the dynamic extending of the form just won’t work.

Here is the part which sits directly on the approval step:

      <InterceptorScript>
        <Source>
        	import sailpoint.object.Form;
          import sailpoint.object.Form.Section;
          import sailpoint.object.Field;
          import sailpoint.object.ObjectConfig;
          import sailpoint.object.ObjectAttribute;

          if(!"startApproval".equals(method)) return;
          
          //Get Form and make a copy
          //Form form = context.getObjectByName(Form.class, "Edit Template");
          Form form = approval.getForm();
          Form formCopy = form.derive(context);
          context.decache(form);

          EmailTemplate t = context.getObjectById(EmailTemplate.class, templateId);
          List arguments = t.getSignature().getArguments();

          Section argumentsSection = new Section();
          argumentsSection.setName("templateArguments");
					argumentsSection.setDisplayName("Template Variables");
          formCopy.add(argumentsSection);
          
          for (Argument argument : arguments) {
            Field field = new Field();
            field.setName(argument.getName());
            field.setValue(argument.getDefaultValue());
            field.setDisplayName(argument.getDisplayName());
            field.setColumnSpan(1);

            argumentsSection.add(field);
          }
          
          if(item == null) {
          	approval.setForm(formCopy);
          } else {
          	item.setForm(formCopy);
          }
        </Source>
      </InterceptorScript>
    </Approval>

And for reference here is the whole workflow:

<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE Workflow PUBLIC "sailpoint.dtd" "sailpoint.dtd">
<Workflow created="1750401514742" explicitTransitions="true" id="c0a80110978b154081978c0f7cf50052" modified="1750841206238" name="Edit Email Template" significantModified="1750841206238" type="Subprocess">
  <Variable initializer="string:true" name="transient"/>
  <Variable name="description"/>
  <Variable name="subject"/>
  <Variable name="templateId"/>
  <Variable name="templateName"/>
  <Variable name="mainBodyHtml"/>
  <Variable name="mainBodyPlain"/>
  <Variable name="mainBodyCompiled"/>
  <Variable name="argDefaults"/>
  <Variable initializer="string:false" name="newTemplate"/>
  <Variable input="true" name="requester"/>
  <Variable initializer="string:true" name="enableColorControls"/>
  <Variable initializer="string:false" name="trace"/>
  <Step icon="Start" name="Start" posX="20" posY="20">
    <Transition to="Select Email Template"/>
  </Step>
  <Step icon="Default" name="Select Email Template" posX="115" posY="20">
    <Approval name="Select Email Template" owner="ref:requester" return="templateId,newTemplate" send="">
      <AfterScript>
        <Source>
    import sailpoint.object.EmailTemplate;
    if(!"new".equals(templateId)) {
      EmailTemplate t=context.getObjectById(EmailTemplate.class, templateId);
      if(t!=null) {
        workflow.put("templateName", t.getName());
      }
    }
        </Source>
      </AfterScript>
      <Arg name="workItemType" value="Generic"/>
      <Form name="Select Email Template">
        <Attributes>
          <Map>
            <entry key="pageTitle" value="Select Email Template"/>
            <entry key="windowWith" value="2000"/>
          </Map>
        </Attributes>
        <Button action="next" label="Next"/>
        <Button action="cancel" label="Cancel"/>
        <Section>
          <Field displayName="Template" name="templateId" type="string" value="new">
            <AllowedValuesDefinition>
              <Script>
                <Source>
import sailpoint.object.EmailTemplate;
import sailpoint.object.QueryOptions;
     
List items=new ArrayList();
ArrayList item=new ArrayList();
item.add("new");
item.add("-- Create new email template --");
items.add(item);
                  
QueryOptions qo = new QueryOptions(); 
qo.setOrderBy("name");           

Iterator it = context.search(EmailTemplate.class, qo, "name,id");                   
while ( (null != it) &amp;&amp; (it.hasNext()) ) {
   Object [] thisTemplate = it.next();
   String templateName = thisTemplate[0];
   String templateId = thisTemplate[1];
   item=new ArrayList();
   item.add(templateId);
   item.add(templateName);
   items.add(item);
}
return items;
                </Source>
              </Script>
            </AllowedValuesDefinition>
          </Field>
        </Section>
      </Form>
    </Approval>
    <Arg name="requester" value="ref:requester"/>
    <Transition to="Edit Template"/>
  </Step>
  <Step icon="Default" name="Edit Template" posX="238" posY="20">
    <Approval name="Edit Template" owner="ref:requester" return="templateName,description,subject,mainBodyPlain,mainBodyHtml,templateType" send="templateName,newTemplate,templateId,enableColorControls">
      <Arg name="workItemType" value="Generic"/>
      <Form name="Edit Template">
        <Attributes>
          <Map>
            <entry key="labelAlign" value="top"/>
            <entry key="pageTitle" value="Edit Template"/>
            <entry key="windowWidth" value="1200"/>
          </Map>
        </Attributes>
        <Button action="next" label="Save"/>
        <Button action="cancel" label="Cancel"/>
        <Section name="nameSection">
          <Field displayName="Template Name" name="templateName" required="true" type="string">
            <Attributes>
              <Map>
                <entry key="readOnly">
                  <value>
                    <Script>
                      <Source>  
if ("new".equals(templateId)) {
   form.setPageTitle("Create Template");
   return false;
} else {
   return true;
}
                      </Source>
                    </Script>
                  </value>
                </entry>
                <entry key="width" value="1500"/>
              </Map>
            </Attributes>
            <Script>
              <Source>return templateName;</Source>
            </Script>
            <ValidationScript>
              <Source>
import sailpoint.object.EmailTemplate;
if ("new".equals(templateId)) {                 
   if (null != value &amp;&amp; null != context.getObjectByName(EmailTemplate.class, value)) {
      return "A template with that name already exists.";
   }
}
               </Source>
            </ValidationScript>
          </Field>
        </Section>
        <Section name="emailSection">
          <Field displayName="Subject" name="subject" required="true" type="string">
            <Attributes>
              <Map>
                <entry key="width" value="1500"/>
              </Map>
            </Attributes>
            <Script>
              <Source>import sailpoint.object.EmailTemplate;
if("new".equals(templateId)) return "";
EmailTemplate t=context.getObjectById(EmailTemplate.class, templateId);

return t.getSubject();</Source>
            </Script>
          </Field>
          <Field displayName="Template Type" filterString="" name="templateType" postBack="true" type="string">
            <AllowedValuesDefinition>
              <Value>
                <List>
                  <String>HTML</String>
                  <String>Plain Text</String>
                  <String>Compiled</String>
                </List>
              </Value>
            </AllowedValuesDefinition>
            <Script>
              <Source>import sailpoint.object.EmailTemplate;
               
if("new".equals(templateId)) return "HTML";
EmailTemplate t=context.getObjectById(EmailTemplate.class, templateId);
String body = t.getBody();
if (body == null) { 
   return "HTML";
}
                
if (body.toLowerCase().contains("&lt;html")) {
   return "HTML";
} else {
   return "Plain Text";           
}
              </Source>
            </Script>
          </Field>
          <Field displayName="Message Body" displayType="textarea" dynamic="true" name="mainBodyHtml" type="other">
            <Attributes>
              <Map>
                <entry key="enableColors">
                  <value>
                    <Script>
                      <Source>
                         return Boolean.valueOf(enableColorControls);
                      </Source>
                    </Script>
                  </value>
                </entry>
                <entry key="height" value="500"/>
                <entry key="hidden">
                  <value>
                    <Script>
                      <Source>
                         if (null != templateType &amp;&amp; templateType.equalsIgnoreCase("HTML")) {
                            return false;
                         } else {
                            return true;
                         }  
                         </Source>
                    </Script>
                  </value>
                </entry>
                <entry key="width" value="1500"/>
                <entry key="xtype" value="htmleditor"/>
              </Map>
            </Attributes>
            <Script>
              <Source>
import sailpoint.object.EmailTemplate;
import org.apache.commons.lang.StringEscapeUtils;
            
if("new".equals(templateId)) return "&lt;br>"; // Need to return something to prevent it displaying "null"
EmailTemplate t=context.getObjectById(EmailTemplate.class, templateId);
String body = t.getBody();
if (body == null)
   return "&lt;br>";
body = StringEscapeUtils.unescapeHtml(body);

return body;           
              </Source>
            </Script>
          </Field>
          <Field displayName="Message Body" displayType="textarea" dynamic="true" name="mainBodyPlain" type="string">
            <Attributes>
              <Map>
                <entry key="height" value="500"/>
                <entry key="hidden">
                  <value>
                    <Script>
                      <Source>
                         if (null != templateType &amp;&amp; templateType.equalsIgnoreCase("Plain Text")) {
                            return false;
                         } else {
                            return true;
                         }  
                         </Source>
                    </Script>
                  </value>
                </entry>
                <entry key="width" value="1500"/>
              </Map>
            </Attributes>
            <Script>
              <Source>import sailpoint.object.EmailTemplate;

if("new".equals(templateId)) return "";
EmailTemplate t=context.getObjectById(EmailTemplate.class, templateId);
String body = t.getBody();
if (body == null)
   return "";

return body; 
              </Source>
            </Script>
          </Field>
          <Field displayName="Message Body" displayType="label" dynamic="true" name="mainBodyCompiled" type="other">
            <Attributes>
              <Map>
                <entry key="anchor" value="none"/>
                <entry key="contentIsEscaped" value="true"/>
                <entry key="enableColors">
                  <value>
                    <Script>
                      <Source>
                         return Boolean.valueOf(enableColorControls);
                      </Source>
                    </Script>
                  </value>
                </entry>
                <entry key="height" value="500"/>
                <entry key="hidden">
                  <value>
                    <Script>
                      <Source>
                         if (null != templateType &amp;&amp; templateType.equalsIgnoreCase("Compiled")) {
                            return false;
                         } else {
                            return true;
                         }  
                         </Source>
                    </Script>
                  </value>
                </entry>
                <entry key="width" value="1500"/>
                <entry key="xtype" value="htmleditor"/>
              </Map>
            </Attributes>
            <Script>
              <Source>
                // lets render the compiled template
                
                import com.iiq.common.helper.CustomEmailRenderer;
                import sailpoint.object.EmailOptions;
                import sailpoint.object.EmailTemplate;
								import org.apache.commons.lang.StringEscapeUtils;
            
								if("new".equals(templateId)) return "&lt;br>"; // Need to return something to prevent it displaying "null"
								
                EmailTemplate t=context.getObjectById(EmailTemplate.class, templateId);
                EmailOptions options = new EmailOptions();
                
								return CustomEmailRenderer.compileEmailBody(context, t, options);
              </Source>
            </Script>
          </Field>
        </Section>
        <Section name="descriptionSection">
          <Field displayName="Template Description" displayType="textarea" name="description" type="string">
            <Attributes>
              <Map>
                <entry key="width" value="1500"/>
              </Map>
            </Attributes>
            <Script>
              <Source>import sailpoint.object.EmailTemplate;
if("new".equals(templateId)) return "";
EmailTemplate t=context.getObjectById(EmailTemplate.class, templateId);

return t.getDescription();</Source>
            </Script>
          </Field>
        </Section>
        <Section name="availableVariablesSection" type="text">
          <Field displayName="" name="availableVariables" readOnly="true">
            <Attributes>
              <Map>
                <entry key="width" value="1500"/>
              </Map>
            </Attributes>
            <Script>
              <Source>
import sailpoint.object.Argument;
import sailpoint.object.EmailTemplate;
import sailpoint.object.Signature;

String variableText = "";
if("new".equals(templateId)) {
   field.setHidden(true);
   return null;
}
                
EmailTemplate t=context.getObjectById(EmailTemplate.class, templateId);
Signature sig = t.getSignature();
if (null != sig) {
   List args = sig.getArguments();
   if (null != args &amp;&amp; !args.isEmpty()) {
      for (Argument arg : args) {
         String lineText = "&lt;b>$" + arg.getName() + "&lt;/b>: " + arg.getDescription();
         if (variableText == "") {
            variableText = "&lt;p>&lt;b>Variables available in this template&lt;/b>&lt;br>&lt;br>" + lineText;
         } else {       
            variableText = variableText + "&lt;br>" + lineText;
         }
      }
   }
}
       
return variableText;

              </Source>
            </Script>
          </Field>
        </Section>
        <Section name="warningSection" type="text">
          <Field displayName="" name="warning" readOnly="true">
            <Attributes>
              <Map>
                <entry key="fieldStyle">
                  <value>
                    <Attributes>
                      <Map>
                        <entry key="color" value="red"/>
                        <entry key="fontWeight" value="bold"/>
                      </Map>
                    </Attributes>
                  </value>
                </entry>
              </Map>
            </Attributes>
            <Script>
              <Source>
String version = sailpoint.Version.getVersion();
String patchLevel = sailpoint.Version.getPatchLevel();
if (patchLevel.equals(""))
   patchLevel = "GA";
boolean problemVersion = false;
if (version.equals("7.0")) {
  if ( patchLevel.equals("GA") || patchLevel.equals("p1") || patchLevel.equals("p2") || patchLevel.equals("p3") || patchLevel.equals("p4") || patchLevel.equals("p5") ) {
     problemVersion = true;                 
  }
}
if ( version.equals("7.1") &amp;&amp; patchLevel.equals("GA") ) {
  problemVersion = true;                 
}

if (problemVersion) {
  return "Your current version of IdentityIQ (" + version + patchLevel + ") has a known issue that causes line endings in form field data to be removed.  This can cause problems with the formatting of the email template.  To avoid this you should patch your installation to 7.0p6, 7.1p1 or higher.";
} else {
   field.setHidden(true);    
   return null;
}
              </Source>
            </Script>
          </Field>
        </Section>
      </Form>
      <InterceptorScript>
        <Source>
        	import sailpoint.object.Form;
          import sailpoint.object.Form.Section;
          import sailpoint.object.Field;
          import sailpoint.object.ObjectConfig;
          import sailpoint.object.ObjectAttribute;

          if(!"startApproval".equals(method)) return;
          
          //Get Form and make a copy
          //Form form = context.getObjectByName(Form.class, "Edit Template");
          Form form = approval.getForm();
          Form formCopy = form.derive(context);
          context.decache(form);

          EmailTemplate t = context.getObjectById(EmailTemplate.class, templateId);
          List arguments = t.getSignature().getArguments();

          Section argumentsSection = new Section();
          argumentsSection.setName("templateArguments");
					argumentsSection.setDisplayName("Template Variables");
          formCopy.add(argumentsSection);
          
          for (Argument argument : arguments) {
            Field field = new Field();
            field.setName(argument.getName());
            field.setValue(argument.getDefaultValue());
            field.setDisplayName(argument.getDisplayName());
            field.setColumnSpan(1);

            argumentsSection.add(field);
          }
          
          if(item == null) {
          	approval.setForm(formCopy);
          } else {
          	item.setForm(formCopy);
          }
        </Source>
      </InterceptorScript>
    </Approval>
    <Transition to="Save Template" when="next"/>
  </Step>
  <Step icon="Default" name="Save Template" posX="344" posY="20">
    <Script>
      <Source>import sailpoint.object.EmailTemplate;
import org.apache.commons.lang.StringEscapeUtils;
EmailTemplate et=null;
if("new".equals(templateId)) {
  et=new EmailTemplate();
  et.setName(templateName);
} else {
  et=context.getObjectById(EmailTemplate.class, templateId);
}
et.setDescription(description);
et.setSubject(subject);

String template;
if (templateType !=null &amp;&amp; templateType.equalsIgnoreCase("HTML")) {
   template = "\n&lt;html>\n&lt;body>\n" + mainBodyHtml + "\n&lt;/body>\n&lt;/html>\n";
   // The htmleditor control puts everything on the same line, so add some
   // line spacings between tags to make it a little easier on the eye.
   template = template.replace(">&lt;", ">\n&lt;");
} else {
   template = mainBodyPlain;
}        
et.setBody(template);
context.saveObject(et);
context.commitTransaction();
        </Source>
    </Script>
    <Transition to="Stop"/>
  </Step>
  <Step icon="Stop" name="Stop" posX="439" posY="20"/>
</Workflow>

I see you have some issues with you code in the Interceptor Script
You are missing the following import statements
import sailpoint.object.EmailTemplate;
import sailpoint.object.Argument;
You are also trying to set displayName on Form.Section. There is no such method and you can remove the following line.
//argumentsSection.setDisplayName(“Template Variables”);

1 Like

Hi there
Yea, that was the issue which caused the execution to fail. In the meantime, I realized there is another issue as well though: from my understanding I am generating a “fully qualified” copy of the original form and setting that as the new form of the approval, however when I hit save it seems as if it snaps back to the original form for a split second (for example when i change the text in the main body it shows the old non-altered text) and then it leaves the workflow, but nothing is actually persisted. The workflow worked fine before I started to add in that dynamic form creation so I am pretty certain that some form/workflow intrinsic behavior, which I am not aware off, is causing this issue. Any idea what it could be?

<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE Workflow PUBLIC "sailpoint.dtd" "sailpoint.dtd">
<Workflow created="1750401514742" explicitTransitions="true" id="c0a80110978b154081978c0f7cf50052" modified="1750848656644" name="Edit Email Template" significantModified="1750848656644" type="Subprocess">
  <Variable initializer="string:true" name="transient"/>
  <Variable name="description"/>
  <Variable name="subject"/>
  <Variable name="templateId"/>
  <Variable name="templateName"/>
  <Variable name="mainBodyHtml"/>
  <Variable name="mainBodyPlain"/>
  <Variable name="mainBodyCompiled"/>
  <Variable name="argDefaults"/>
  <Variable initializer="string:false" name="newTemplate"/>
  <Variable input="true" name="requester"/>
  <Variable initializer="string:true" name="enableColorControls"/>
  <Variable initializer="string:false" name="trace"/>
  <Step icon="Start" name="Start" posX="20" posY="20">
    <Transition to="Select Email Template"/>
  </Step>
  <Step icon="Default" name="Select Email Template" posX="115" posY="20">
    <Approval name="Select Email Template" owner="ref:requester" return="templateId,newTemplate" send="">
      <AfterScript>
        <Source>
    import sailpoint.object.EmailTemplate;
    if(!"new".equals(templateId)) {
      EmailTemplate t=context.getObjectById(EmailTemplate.class, templateId);
      if(t!=null) {
        workflow.put("templateName", t.getName());
      }
    }
        </Source>
      </AfterScript>
      <Arg name="workItemType" value="Generic"/>
      <Form name="Select Email Template">
        <Attributes>
          <Map>
            <entry key="pageTitle" value="Select Email Template"/>
            <entry key="windowWith" value="2000"/>
          </Map>
        </Attributes>
        <Button action="next" label="Next"/>
        <Button action="cancel" label="Cancel"/>
        <Section>
          <Field displayName="Template" name="templateId" type="string" value="new">
            <AllowedValuesDefinition>
              <Script>
                <Source>
import sailpoint.object.EmailTemplate;
import sailpoint.object.QueryOptions;
     
List items=new ArrayList();
ArrayList item=new ArrayList();
item.add("new");
item.add("-- Create new email template --");
items.add(item);
                  
QueryOptions qo = new QueryOptions(); 
qo.setOrderBy("name");           

Iterator it = context.search(EmailTemplate.class, qo, "name,id");                   
while ( (null != it) &amp;&amp; (it.hasNext()) ) {
   Object [] thisTemplate = it.next();
   String templateName = thisTemplate[0];
   String templateId = thisTemplate[1];
   item=new ArrayList();
   item.add(templateId);
   item.add(templateName);
   items.add(item);
}
return items;
                </Source>
              </Script>
            </AllowedValuesDefinition>
          </Field>
        </Section>
      </Form>
    </Approval>
    <Arg name="requester" value="ref:requester"/>
    <Transition to="Edit Template"/>
  </Step>
  <Step icon="Default" name="Edit Template" posX="238" posY="20">
    <Approval name="Edit Template" owner="ref:requester" return="templateName,description,subject,mainBodyHtml,templateType,argDefaults" send="templateName,newTemplate,templateId,enableColorControls">
      <AfterScript>
        <Source>
          log.error("Hello from after script");
          log.error(approval.getReturn());
        </Source>
      </AfterScript>
      <Arg name="workItemType" value="Generic"/>
      <Form name="Edit Template">
        <Attributes>
          <Map>
            <entry key="labelAlign" value="top"/>
            <entry key="pageTitle" value="Edit Template"/>
            <entry key="windowWidth" value="1200"/>
          </Map>
        </Attributes>
        <Button action="next" label="Save"/>
        <Button action="cancel" label="Cancel"/>
        <Section name="nameSection">
          <Field displayName="Template Name" name="templateName" required="true" type="string">
            <Attributes>
              <Map>
                <entry key="readOnly">
                  <value>
                    <Script>
                      <Source>  
if ("new".equals(templateId)) {
   form.setPageTitle("Create Template");
   return false;
} else {
   return true;
}
                      </Source>
                    </Script>
                  </value>
                </entry>
                <entry key="width" value="1500"/>
              </Map>
            </Attributes>
            <Script>
              <Source>return templateName;</Source>
            </Script>
            <ValidationScript>
              <Source>
import sailpoint.object.EmailTemplate;
if ("new".equals(templateId)) {                 
   if (null != value &amp;&amp; null != context.getObjectByName(EmailTemplate.class, value)) {
      return "A template with that name already exists.";
   }
}
               </Source>
            </ValidationScript>
          </Field>
        </Section>
        <Section name="emailSection">
          <Field displayName="Subject" name="subject" required="true" type="string">
            <Attributes>
              <Map>
                <entry key="width" value="1500"/>
              </Map>
            </Attributes>
            <Script>
              <Source>import sailpoint.object.EmailTemplate;
if("new".equals(templateId)) return "";
EmailTemplate t=context.getObjectById(EmailTemplate.class, templateId);

return t.getSubject();</Source>
            </Script>
          </Field>
          <Field displayName="Template Type" filterString="" name="templateType" postBack="true" type="string">
            <AllowedValuesDefinition>
              <Value>
                <List>
                  <String>HTML</String>
                  <String>Plain Text</String>
                  <String>Compiled</String>
                </List>
              </Value>
            </AllowedValuesDefinition>
            <Script>
              <Source>import sailpoint.object.EmailTemplate;
               
if("new".equals(templateId)) return "HTML";
EmailTemplate t=context.getObjectById(EmailTemplate.class, templateId);
String body = t.getBody();
if (body == null) { 
   return "HTML";
}
                
if (body.toLowerCase().contains("&lt;html")) {
   return "HTML";
} else {
   return "Plain Text";           
}
              </Source>
            </Script>
          </Field>
          <Field displayName="Message Body" displayType="textarea" name="mainBodyHtml" type="other">
            <Attributes>
              <Map>
                <entry key="enableColors">
                  <value>
                    <Script>
                      <Source>
                         return Boolean.valueOf(enableColorControls);
                      </Source>
                    </Script>
                  </value>
                </entry>
                <entry key="height" value="500"/>
                <entry key="hidden">
                  <value>
                    <Script>
                      <Source>
                         if (null != templateType &amp;&amp; templateType.equalsIgnoreCase("HTML")) {
                            return false;
                         } else {
                            return true;
                         }  
                         </Source>
                    </Script>
                  </value>
                </entry>
                <entry key="width" value="1500"/>
                <entry key="xtype" value="htmleditor"/>
              </Map>
            </Attributes>
            <Script>
              <Source>
import sailpoint.object.EmailTemplate;
import org.apache.commons.lang.StringEscapeUtils;
            
if("new".equals(templateId)) return "&lt;br>"; // Need to return something to prevent it displaying "null"
EmailTemplate t=context.getObjectById(EmailTemplate.class, templateId);
String body = t.getBody();
if (body == null)
   return "&lt;br>";
body = StringEscapeUtils.unescapeHtml(body);

return body;           
              </Source>
            </Script>
          </Field>
          <Field displayName="Message Body" displayType="textarea" name="mainBodyPlain" type="string">
            <Attributes>
              <Map>
                <entry key="height" value="500"/>
                <entry key="hidden">
                  <value>
                    <Script>
                      <Source>
                         if (null != templateType &amp;&amp; templateType.equalsIgnoreCase("Plain Text")) {
                            return false;
                         } else {
                            return true;
                         }  
                         </Source>
                    </Script>
                  </value>
                </entry>
                <entry key="width" value="1500"/>
              </Map>
            </Attributes>
            <Script>
              <Source>import sailpoint.object.EmailTemplate;

if("new".equals(templateId)) return "";
EmailTemplate t=context.getObjectById(EmailTemplate.class, templateId);
String body = t.getBody();
if (body == null)
   return "";

return body; 
              </Source>
            </Script>
          </Field>
          <Field displayName="Message Body" displayType="label" dynamic="true" name="mainBodyCompiled" type="other">
            <Attributes>
              <Map>
                <entry key="anchor" value="none"/>
                <entry key="contentIsEscaped" value="true"/>
                <entry key="enableColors">
                  <value>
                    <Script>
                      <Source>
                         return Boolean.valueOf(enableColorControls);
                      </Source>
                    </Script>
                  </value>
                </entry>
                <entry key="height" value="500"/>
                <entry key="hidden">
                  <value>
                    <Script>
                      <Source>
                         if (null != templateType &amp;&amp; templateType.equalsIgnoreCase("Compiled")) {
                            return false;
                         } else {
                            return true;
                         }  
                      </Source>
                    </Script>
                  </value>
                </entry>
                <entry key="width" value="1500"/>
                <entry key="xtype" value="htmleditor"/>
              </Map>
            </Attributes>
            <Script>
              <Source>
                // lets render the compiled template
                
                import com.iiq.common.helper.CustomEmailRenderer;
                import sailpoint.object.EmailOptions;
                import sailpoint.object.EmailTemplate;
								import org.apache.commons.lang.StringEscapeUtils;
            
								if("new".equals(templateId)) return "&lt;br>"; // Need to return something to prevent it displaying "null"
								
                EmailTemplate t=context.getObjectById(EmailTemplate.class, templateId);
                EmailOptions options = new EmailOptions();
                
								return CustomEmailRenderer.compileEmailBody(context, t, options);
              </Source>
            </Script>
          </Field>
        </Section>
        <Section name="descriptionSection">
          <Field displayName="Template Description" displayType="textarea" name="description" type="string">
            <Attributes>
              <Map>
                <entry key="width" value="1500"/>
              </Map>
            </Attributes>
            <Script>
              <Source>import sailpoint.object.EmailTemplate;
if("new".equals(templateId)) return "";
EmailTemplate t=context.getObjectById(EmailTemplate.class, templateId);

return t.getDescription();</Source>
            </Script>
          </Field>
        </Section>
        <Section name="availableVariablesSection" type="text">
          <Field displayName="" name="availableVariables" readOnly="true">
            <Attributes>
              <Map>
                <entry key="width" value="1500"/>
              </Map>
            </Attributes>
            <Script>
              <Source>
import sailpoint.object.Argument;
import sailpoint.object.EmailTemplate;
import sailpoint.object.Signature;

String variableText = "";
if("new".equals(templateId)) {
   field.setHidden(true);
   return null;
}
                
EmailTemplate t=context.getObjectById(EmailTemplate.class, templateId);
Signature sig = t.getSignature();
if (null != sig) {
   List args = sig.getArguments();
   if (null != args &amp;&amp; !args.isEmpty()) {
      for (Argument arg : args) {
         String lineText = "&lt;b>$" + arg.getName() + "&lt;/b>: " + arg.getDescription();
         if (variableText == "") {
            variableText = "&lt;p>&lt;b>Variables available in this template&lt;/b>&lt;br>&lt;br>" + lineText;
         } else {       
            variableText = variableText + "&lt;br>" + lineText;
         }
      }
   }
}
       
return variableText;

              </Source>
            </Script>
          </Field>
        </Section>
        <Section name="warningSection" type="text">
          <Field displayName="" name="warning" readOnly="true">
            <Attributes>
              <Map>
                <entry key="fieldStyle">
                  <value>
                    <Attributes>
                      <Map>
                        <entry key="color" value="red"/>
                        <entry key="fontWeight" value="bold"/>
                      </Map>
                    </Attributes>
                  </value>
                </entry>
              </Map>
            </Attributes>
            <Script>
              <Source>
String version = sailpoint.Version.getVersion();
String patchLevel = sailpoint.Version.getPatchLevel();
if (patchLevel.equals(""))
   patchLevel = "GA";
boolean problemVersion = false;
if (version.equals("7.0")) {
  if ( patchLevel.equals("GA") || patchLevel.equals("p1") || patchLevel.equals("p2") || patchLevel.equals("p3") || patchLevel.equals("p4") || patchLevel.equals("p5") ) {
     problemVersion = true;                 
  }
}
if ( version.equals("7.1") &amp;&amp; patchLevel.equals("GA") ) {
  problemVersion = true;                 
}

if (problemVersion) {
  return "Your current version of IdentityIQ (" + version + patchLevel + ") has a known issue that causes line endings in form field data to be removed.  This can cause problems with the formatting of the email template.  To avoid this you should patch your installation to 7.0p6, 7.1p1 or higher.";
} else {
   field.setHidden(true);    
   return null;
}
              </Source>
            </Script>
          </Field>
        </Section>
      </Form>
      <InterceptorScript>
        <Source>
        	import sailpoint.object.Form;
          import sailpoint.object.Form.Section;
          import sailpoint.object.Field;
          import sailpoint.object.Argument;
          import sailpoint.object.ObjectConfig;
          import sailpoint.object.ObjectAttribute;
          import sailpoint.object.EmailTemplate;
          import sailpoint.object.Workflow;
          
          log.error(approval.getForm().getName());
          
          if("postAssimilation".equals(method)) {
          	log.error("we reached post assimilation");
          	argDefaults = new HashMap();
          }

          if(!"startApproval".equals(method)) return;
          
          log.error("Hello from Start Approval");
          
          //Get Form and make a copy
          //Form form = context.getObjectByName(Form.class, "Edit Template");
          Form form = approval.getForm();
          Form formCopy = form.derive(context);
          formCopy.setName("New Form");
          
          context.decache(form);

          EmailTemplate t = context.getObjectById(EmailTemplate.class, templateId);
          List arguments = t.getSignature().getArguments();

          Section argumentsSection = new Section();
          argumentsSection.setName("templateArguments");
          formCopy.add(argumentsSection);
          
          for (Argument argument : arguments) {
            Field field = new Field();
            field.setName(argument.getName());
            field.setValue(argument.getDefaultValue());
            field.setColumnSpan(1);

            argumentsSection.add(field);
          }
          
          if(item == null) {
          	approval.setForm(formCopy);
          	log.error("we are an approval!");      
          } else {
          	item.setForm(formCopy);
          	log.error("we are an item!");
          }
          
          log.error("Passed through the script!");
        </Source>
      </InterceptorScript>
    </Approval>
    <Transition to="Save Template" when="approved"/>
  </Step>
  <Step icon="Default" name="Save Template" posX="344" posY="20">
    <Script>
      <Source>
				import sailpoint.object.EmailTemplate;
        import org.apache.commons.lang.StringEscapeUtils;
        EmailTemplate et=null;
        
        log.error("Hello from" + argDefaults);
        
        if("new".equals(templateId)) {
          et=new EmailTemplate();
          et.setName(templateName);
        } else {
        	et=context.getObjectById(EmailTemplate.class, templateId);
        }
        
        et.setDescription(description);
        et.setSubject(subject);

        String template;
        if (templateType !=null &amp;&amp; templateType.equalsIgnoreCase("HTML")) {
          template = "\n&lt;html>\n&lt;body>\n" + mainBodyHtml + "\n&lt;/body>\n&lt;/html>\n";
          // The htmleditor control puts everything on the same line, so add some
          // line spacings between tags to make it a little easier on the eye.
          template = template.replace(">&lt;", ">\n&lt;");
        } else {
        	template = mainBodyPlain;
        }        
        et.setBody(template);
        context.saveObject(et);
        context.commitTransaction();
        </Source>
    </Script>
    <Transition to="Stop"/>
  </Step>
  <Step icon="Stop" name="Stop" posX="439" posY="20"/>
</Workflow>

I found the issue, which was plainly related to how I was saving the template. Additionally i realized that creating a copy of the form in that specific case doesn’t really make sense since its anyway just transient. So yea, issue resolved. Going to leave this here for future reference:

<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE Workflow PUBLIC "sailpoint.dtd" "sailpoint.dtd">
<Workflow created="1750401514742" explicitTransitions="true" id="c0a80110978b154081978c0f7cf50052" modified="1750929424219" name="Edit Email Template" significantModified="1750929424219" type="Subprocess">
  <Variable initializer="string:true" name="transient"/>
  <Variable name="description"/>
  <Variable name="subject"/>
  <Variable name="templateId"/>
  <Variable name="templateName"/>
  <Variable name="mainBodyHtml"/>
  <Variable name="mainBodyPlain"/>
  <Variable name="mainBodyCompiled"/>
  <Variable name="argDefaults"/>
  <Variable initializer="string:false" name="newTemplate"/>
  <Variable input="true" name="requester"/>
  <Variable initializer="string:true" name="enableColorControls"/>
  <Variable initializer="string:false" name="trace"/>
  <Step icon="Start" name="Start" posX="20" posY="20">
    <Transition to="Select Email Template"/>
  </Step>
  <Step icon="Default" name="Select Email Template" posX="115" posY="20">
    <Approval name="Select Email Template" owner="ref:requester" return="templateId,newTemplate" send="">
      <AfterScript>
        <Source>
          import sailpoint.object.EmailTemplate;
          if(!"new".equals(templateId)) {
            EmailTemplate t=context.getObjectById(EmailTemplate.class, templateId);
            if(t!=null) {
              workflow.put("templateName", t.getName());
            }
          }
        </Source>
      </AfterScript>
      <Arg name="workItemType" value="Generic"/>
      <Form name="Select Email Template">
        <Attributes>
          <Map>
            <entry key="pageTitle" value="Select Email Template"/>
            <entry key="windowWith" value="2000"/>
          </Map>
        </Attributes>
        <Button action="next" label="Next"/>
        <Button action="cancel" label="Cancel"/>
        <Section>
          <Field displayName="Template" name="templateId" type="string" value="new">
            <AllowedValuesDefinition>
              <Script>
                <Source>
                  import sailpoint.object.EmailTemplate;
                  import sailpoint.object.QueryOptions;

                  List items=new ArrayList();
                  ArrayList item=new ArrayList();
                  item.add("new");
                  item.add("-- Create new email template --");
                  items.add(item);

                  QueryOptions qo = new QueryOptions(); 
                  qo.setOrderBy("name");           

                  Iterator it = context.search(EmailTemplate.class, qo, "name,id");                   
                  while ( (null != it) &amp;&amp; (it.hasNext()) ) {
                     Object [] thisTemplate = it.next();
                     String templateName = thisTemplate[0];
                     String templateId = thisTemplate[1];
                     item=new ArrayList();
                     item.add(templateId);
                     item.add(templateName);
                     items.add(item);
                  }
                  return items;
                </Source>
              </Script>
            </AllowedValuesDefinition>
          </Field>
        </Section>
      </Form>
    </Approval>
    <Arg name="requester" value="ref:requester"/>
    <Transition to="Edit Template"/>
  </Step>
  <Step icon="Default" name="Edit Template" posX="238" posY="20">
    <Approval name="Edit Template" owner="ref:requester" return="templateName,description,subject,mainBodyHtml,mainBodyPlain,templateType,argDefaults" send="templateName,newTemplate,templateId,enableColorControls">
      <Arg name="workItemType" value="Generic"/>
      <Form name="Edit Template">
        <Attributes>
          <Map>
            <entry key="labelAlign" value="top"/>
            <entry key="pageTitle" value="Edit Template"/>
            <entry key="windowWidth" value="1200"/>
          </Map>
        </Attributes>
        <Button action="next" label="Save"/>
        <Button action="cancel" label="Cancel"/>
        <Section name="nameSection">
          <Field displayName="Template Name" name="templateName" required="true" type="string">
            <Attributes>
              <Map>
                <entry key="readOnly">
                  <value>
                    <Script>
                      <Source>  
                        if ("new".equals(templateId)) {
                        	form.setPageTitle("Create Template");
                        	return false;
                        } else {
                        	return true;
                        }
                      </Source>
                    </Script>
                  </value>
                </entry>
                <entry key="width" value="1500"/>
              </Map>
            </Attributes>
            <Script>
              <Source>return templateName;</Source>
            </Script>
            <ValidationScript>
              <Source>
                import sailpoint.object.EmailTemplate;
                if ("new".equals(templateId)) {                 
                	if (null != value &amp;&amp; null != context.getObjectByName(EmailTemplate.class, value)) {
                		return "A template with that name already exists.";
                	}
                }
               </Source>
            </ValidationScript>
          </Field>
        </Section>
        <Section name="emailSection">
          <Field displayName="Subject" name="subject" required="true" type="string">
            <Attributes>
              <Map>
                <entry key="width" value="1500"/>
              </Map>
            </Attributes>
            <Script>
              <Source>
                import sailpoint.object.EmailTemplate;
                if("new".equals(templateId)) return "";
                EmailTemplate t=context.getObjectById(EmailTemplate.class, templateId);

                return t.getSubject();
              </Source>
            </Script>
          </Field>
          <Field displayName="Template Type" name="templateType" postBack="true" type="string">
            <AllowedValuesDefinition>
              <Value>
                <List>
                  <String>HTML</String>
                  <String>Plain Text</String>
                  <String>Compiled</String>
                </List>
              </Value>
            </AllowedValuesDefinition>
            <Script>
              <Source>
                import sailpoint.object.EmailTemplate;
               
                if("new".equals(templateId)) return "HTML";
                EmailTemplate t=context.getObjectById(EmailTemplate.class, templateId);
                String body = t.getBody();
                
                if (body == null) { 
                   return "HTML";
                }

                if (body.toLowerCase().contains("&lt;html")) {
                   return "HTML";
                } else {
                   return "Plain Text";           
                }
              </Source>
            </Script>
          </Field>
          <Field displayName="Message Body" displayType="textarea" dynamic="true" name="mainBodyHtml" type="other">
            <Attributes>
              <Map>
                <entry key="enableColors">
                  <value>
                    <Script>
                      <Source>
                         return Boolean.valueOf(enableColorControls);
                      </Source>
                    </Script>
                  </value>
                </entry>
                <entry key="height" value="500"/>
                <entry key="hidden">
                  <value>
                    <Script>
                      <Source>
                         if (null != templateType &amp;&amp; templateType.equalsIgnoreCase("HTML")) {
                            return false;
                         } else {
                            return true;
                         }  
                         </Source>
                    </Script>
                  </value>
                </entry>
                <entry key="width" value="1500"/>
                <entry key="xtype" value="htmleditor"/>
              </Map>
            </Attributes>
            <Script>
              <Source>
                import sailpoint.object.EmailTemplate;
                import org.apache.commons.lang.StringEscapeUtils;

                if("new".equals(templateId)) return "&lt;br>"; // Need to return something to prevent it displaying "null"
                EmailTemplate t=context.getObjectById(EmailTemplate.class, templateId);
                String body = t.getBody();
                if (body == null)
                   return "&lt;br>";
                body = StringEscapeUtils.unescapeHtml(body);

                return body;           
              </Source>
            </Script>
          </Field>
          <Field displayName="Message Body" displayType="textarea" dynamic="true" name="mainBodyPlain" type="string">
            <Attributes>
              <Map>
                <entry key="height" value="500"/>
                <entry key="hidden">
                  <value>
                    <Script>
                      <Source>
                         if (null != templateType &amp;&amp; templateType.equalsIgnoreCase("Plain Text")) {
                            return false;
                         } else {
                            return true;
                         }  
                         </Source>
                    </Script>
                  </value>
                </entry>
                <entry key="width" value="1500"/>
              </Map>
            </Attributes>
            <Script>
              <Source>
                import sailpoint.object.EmailTemplate;

                if("new".equals(templateId)) return "";
                EmailTemplate t=context.getObjectById(EmailTemplate.class, templateId);
                String body = t.getBody();
                if (body == null)
                   return "";

                return body; 
              </Source>
            </Script>
          </Field>
          <Field displayName="Message Body" displayType="label" dynamic="true" name="mainBodyCompiled" type="other">
            <Attributes>
              <Map>
                <entry key="anchor" value="none"/>
                <entry key="contentIsEscaped" value="true"/>
                <entry key="enableColors">
                  <value>
                    <Script>
                      <Source>
                         return Boolean.valueOf(enableColorControls);
                      </Source>
                    </Script>
                  </value>
                </entry>
                <entry key="height" value="500"/>
                <entry key="hidden">
                  <value>
                    <Script>
                      <Source>
                         if (null != templateType &amp;&amp; templateType.equalsIgnoreCase("Compiled")) {
                            return false;
                         } else {
                            return true;
                         }  
                      </Source>
                    </Script>
                  </value>
                </entry>
                <entry key="width" value="1500"/>
                <entry key="xtype" value="htmleditor"/>
              </Map>
            </Attributes>
            <Script>
              <Source>
                // lets render the compiled template
                
                import com.iiq.common.helper.CustomEmailRenderer;
                import sailpoint.object.EmailOptions;
                import sailpoint.object.EmailTemplate;
								import org.apache.commons.lang.StringEscapeUtils;
            
								if("new".equals(templateId)) return "&lt;br>"; // Need to return something to prevent it displaying "null"
								
                EmailTemplate t=context.getObjectById(EmailTemplate.class, templateId);
                EmailOptions options = new EmailOptions();
                
								return CustomEmailRenderer.compileEmailBody(context, t, options);
              </Source>
            </Script>
          </Field>
        </Section>
        <Section name="descriptionSection">
          <Field displayName="Template Description" displayType="textarea" name="description" type="string">
            <Attributes>
              <Map>
                <entry key="width" value="1500"/>
              </Map>
            </Attributes>
            <Script>
              <Source>
                import sailpoint.object.EmailTemplate;
                if("new".equals(templateId)) return "";
                EmailTemplate t=context.getObjectById(EmailTemplate.class, templateId);

                return t.getDescription();
              </Source>
            </Script>
          </Field>
        </Section>
      </Form>
      <InterceptorScript>
        <Source>
        	import sailpoint.object.Form;
          import sailpoint.object.Form.Section;
          import sailpoint.object.Field;
          import sailpoint.object.Argument;
          import sailpoint.object.ObjectConfig;
          import sailpoint.object.ObjectAttribute;
          import sailpoint.object.EmailTemplate;
          import sailpoint.object.Workflow;
          
          log.error(approval.getForm().getName());
          
          if("postAssimilation".equals(method)) {
          	log.error("we reached post assimilation");
          	argDefaults = new HashMap();
          }

          if(!"startApproval".equals(method)) return;
          
          log.error("Hello from Start Approval");
          
          //Get the form        
          Form form = approval.getForm();
        
          EmailTemplate t = context.getObjectById(EmailTemplate.class, templateId);
          List arguments = t.getSignature().getArguments();

          Section argumentsSection = new Section();
          argumentsSection.setName("templateArguments");
          form.add(argumentsSection);
          
          for (Argument argument : arguments) {
            Field field = new Field();
            field.setName(argument.getName());
            field.setValue(argument.getDefaultValue());
            field.setColumnSpan(1);

            argumentsSection.add(field);
          }
          
          if(item == null) {
          	context.saveObject(form);
          	approval.setForm(form);
          	log.error("we are an approval!");      
          } else {
          	item.setForm(form);
          	log.error("we are an item!");
          }
          
          log.error("Passed through the script!");
        </Source>
      </InterceptorScript>
    </Approval>
    <Transition to="Save Template" when="approved"/>
  </Step>
  <Step icon="Default" name="Save Template" posX="344" posY="20">
    <Script>
      <Source>
				import sailpoint.object.EmailTemplate;
        import org.apache.commons.lang.StringEscapeUtils;
        EmailTemplate et=null;
        
        log.error("Hello from" + argDefaults);
        log.error("Main Body HTML: " + mainBodyHtml);
        log.error("Main Body Plain: " + mainBodyPlain);
        
        if("new".equals(templateId)) {
          et=new EmailTemplate();
          et.setName(templateName);
        	log.error("Created a new template");
        } else {
        	et=context.getObjectById(EmailTemplate.class, templateId);
        }
        
        et.setDescription(description);
        et.setSubject(subject);

        String template;
        if (templateType !=null &amp;&amp; templateType.equalsIgnoreCase("HTML")) {
          template = "\n&lt;html>\n&lt;body>\n" + mainBodyHtml + "\n&lt;/body>\n&lt;/html>\n";
          // The htmleditor control puts everything on the same line, so add some
          // line spacings between tags to make it a little easier on the eye.
          template = template.replace(">&lt;", ">\n&lt;");
        } else {
        	template = mainBodyPlain;
        }
        
        log.error("Template text: " + template);
        log.error("Email Template: " + et);
        
        // save guard
        if(template == null || template.isEmpty()) return;
        
        et.setBody(template);
        context.saveObject(et);
        context.commitTransaction();
        </Source>
    </Script>
    <Transition to="Stop"/>
  </Step>
  <Step icon="Stop" name="Stop" posX="439" posY="20"/>
</Workflow>

1 Like

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