Product documentation Docs
    • English
    • Deutsch
    • 日本語
    • 한국어
    • Français
  • More Sites
    • Now Community
    • Developer Site
    • Knowledge Base
    • Product Information
    • ServiceNow.com
    • Training
    • Customer Success Center
    • ServiceNow Support Videos
  • Log in

Product documentation

  • Home
How search works:
  • Punctuation and capital letters are ignored
  • Special characters like underscores (_) are removed
  • Known synonyms are applied
  • The most relevant topics (based on weighting and matching to search terms) are listed first in search results
Topics are ranked in search results by how closely they match your search terms
  • A match on the entire phrase you typed
  • A match on part of the phrase you typed
  • A match on ALL of the terms in the phrase you typed
  • A match on ANY of the terms in the phrase you typed

Note: Matches in titles are always highly ranked.

  • Release version
    Table of Contents
    • Now Platform capabilities
Table of Contents
Choose your release version
    Home New York Now Platform Capabilities Now Platform capabilities Content Management System Configure Content Management sites Content blocks Content Management and the Apache Jelly engine

    Content Management and the Apache Jelly engine

    • Save as PDF Selected topic Topic & subtopics All topics in contents
    • Unsubscribe Log in to subscribe to topics and get notified when content changes.
    • Share this page

    Content Management and the Apache Jelly engine

    Apache Jelly is a Java-based and XML-based scripting and processing engine for turning XML into executable code.

    The Apache Jelly engine closely resembles XML and should be comfortable for developers familiar with JavaScript, XML, XHTML, or HTML. In theServiceNow instance, the Apache Jelly engine renders items such as forms, lists, and UI Pages. Apache Jelly code renders well within a dynamic content block, but can have issues when used in static blocks. You can use Jelly tags, calls, and statements, but HTML acts just like XHTML.

    <?xml version= "1.0" encoding= "utf-8" ?>
    <j:jelly trim = "false" xmlns:j = "jelly:core" xmlns:g = "glide" xmlns:j2 = "null" xmlns:g2 = "null" >
     
    	<j:if test = "${current_page.getName()=='Solutions'}" >
    	<h1 class = "page_name" > <b> <a href = "solutions.do?" title = "${gs.getMessage('Solutions')}" >${gs.getMessage('Solutions')}</a> </b> </h1>
    	<p class = "page_description" >
    	 	    ${current_page.getDescription()}
    	</p> <br />
    	</j:if>
    	<j:if test = "${current_page.getName()=='IT 3.0'}" >
    	   <h1 class = "page_name" > <b> <a href = "solutions.do?" title = "${gs.getMessage('Solutions')}" >${gs.getMessage('Solutions')}</a> </b> | ${current_page.getName()}</h1>
    	   <p class = "page_description" >
    	 	    ${current_page.getDescription()}
    		</p> <br />
    		</j:if>
    		</j:jelly>

    Ensure that all tags are closed. If the tag is not a naturally closing tag, then place a forward slash before the end bracket. For example, a <BR /> or an <IMG src="cms.png" />.

    If you are unfamiliar with Jelly scripting, review these topics:
    • Jelly tags
    • Extensions to Jelly syntax
    • Jelly escaping types

    Include the following tag with all Apache Jelly scripts.

    <j:jelly trim= "false" xmlns:j= "jelly:core" xmlns:g= "glide" xmlns:j2= "null" xmlns:g2= "null" >
    The tag looks complex, but keep the following information in mind.
    • Apache Jelly script uses multiple namespaces.
    • There are two types of prefixes in tags: j and g. The j prefix is used for tags that are natively part of Apache Jelly. The g prefix is used for tags that the ServiceNow platform created and is using for platform purposes.

    The j2 and g2 prefixes are just like j and g, except that they are processed in a second phase. The Apache Jelly script parser runs through each j and g tag respectively. For example:

    <j:jelly trim="false" xmlns:j="jelly:core" xmlns:g="glide" xmlns:j2="null" xmlns:g2="null">
    	<j:set var="jvar_phase1" value="Hello" />
    	<j2:set var="jvar_phase2" value="World" />
    	${jvar_phase1} $[jvar_phase2]
    </j:jelly>

    In phase 1, the parser runs through all the j and g tags. It then caches the result. Before it runs the second phase, it takes the j and g namespaces and moves the namespaces to the second phase. It looks something like the following code.

    <j:jelly trim="false" xmlns:j="jelly:core" xmlns:g="glide" xmlns:j2="jelly:core" xmlns:g2="glide">
    	<j2:set var="jvar_phase2" value="World" />
    	Hello $[jvar_phase2]
    </j:jelly>
    For subsequent calls of this script, only phase 2 is parsed.
    Note: If you plan to use phase 2 Jelly tags (g2 and j2) on the Content Type [content_type] or Dynamic Content [content_block_programmatic] tables, select the Two phase option on the content form.

    Another example is to create a report of all open incidents assigned to each group. For this purpose, you could use a report and save time, but it is a good example for learning Jelly. Start with the Jelly tag:

    <j:jelly trim= "false" xmlns:j= "jelly:core" xmlns:g= "glide" xmlns:j2= "null" xmlns:g2= "null" >
    </j:jelly>

    First, you need a list of open incidents. Use a g2:evaluate tag. The evaluate tag runs the script. Anything inside the tag is parsed like a business rule, so, for example, you can call global business rules, script includes, and gliderecord.

    <j:jelly trim="false" xmlns:j="jelly:core" xmlns:g="glide" xmlns:j2="null" xmlns:g2="null">
    	<g:evaluate var="jvar_groups" object="true">
    		var now_GR = new GlideRecord("sys_user_group");
    		gr.orderBy('name');
    		gr.query();
    		gr;
    	</g:evaluate>
    </j:jelly>

    This script is in phase 1 because frequent changes to incident assignment groups are not expected. Also notice the var attribute on the evaluate tag. This attribute specifies what variable is set from this block. At the end of the script, there is a gr on a line by itself. That last line is what sets the variable.

    You can omit the jvar_groups variable, but then all the variables in the evaluate tag become Apache Jelly variables. The object=true specifies that the variable is not a primitive data type. If object=true is omitted, the script would break because jvar_groups would only be able to hold items like integers and strings.

    After the evaluate tag, loop through these groups and find the incidents for each one.

    <j:jelly trim="false" xmlns:j="jelly:core" xmlns:g="glide" xmlns:j2="null" xmlns:g2="null">
    	<g:evaluate var="jvar_groups" object="true">
    		var now_GR = new GlideRecord("sys_user_group");
    		gr.orderBy('name');
    		gr.query();
    		gr;
    	</g:evaluate>
    	<table>
    		<tr>
    			<th>Name</th>
    			<th>Incidents</th>
    		</tr>
    		<j:while test="${jvar_groups.next()}">
    			<tr>
    				<td>${HTML:jvar_groups.getValue('name')}</td>
    				<td></td>
    			</tr>
    		</j:while>
    	</table>
    </j:jelly>
    You can include normal XML in the Apache Jelly script at any time. Since there is no namespace, the Apache Jelly script does not try to parse the XML tags. Notice the j:while loop. It is a normal while loop and can iterate through a GlideRecord object. Also notice that you output a value with ${HTML:jvar_groups.getValue('name')}. Here are the important elements:
    • The outer brackets, ${}, specify the output of the variable and the phase in which the variable is output: ${} means first phase, $[] means second phase.
    • HTML before the expression is for escaping the output. The expression jvar_groups.getValue('name') is being escaped for HTML. For other types of escaping, there are JS (Javascript), NS (No Script), and some other options.

    To select only one record and not iterate through many records, the code looks like the following example:

    <j:jelly trim="false" xmlns:j="jelly:core" xmlns:g="glide" xmlns:j2="null" xmlns:g2="null">
    	<g:evaluate var="jvar_groups" object="true">
    		var now_GR = new GlideRecord("sys_user_group");
    		gr.orderBy('name');
    		gr.query();
    		gr;
    	</g:evaluate>
    	<j:if test="${jvar_groups.next()}">
    		We found ${HTML:jvar_groups.getValue('name')}
    	</j:if>
    </j:jelly>
    • Content management and Jelly code examples

      Code examples

    Related tasks
    • Configure a content block
    • View CMS block tags
    Related reference
    • Types of content blocks

    Tags:

    Feedback
    On this page

    Previous topic

    Next topic

    • Contact Us
    • Careers
    • Terms of Use
    • Privacy Statement
    • Sitemap
    • © ServiceNow. All rights reserved.

    Release version
    Choose your release version

      Content Management and the Apache Jelly engine

      • Save as PDF Selected topic Topic & subtopics All topics in contents
      • Unsubscribe Log in to subscribe to topics and get notified when content changes.
      • Share this page

      Content Management and the Apache Jelly engine

      Apache Jelly is a Java-based and XML-based scripting and processing engine for turning XML into executable code.

      The Apache Jelly engine closely resembles XML and should be comfortable for developers familiar with JavaScript, XML, XHTML, or HTML. In theServiceNow instance, the Apache Jelly engine renders items such as forms, lists, and UI Pages. Apache Jelly code renders well within a dynamic content block, but can have issues when used in static blocks. You can use Jelly tags, calls, and statements, but HTML acts just like XHTML.

      <?xml version= "1.0" encoding= "utf-8" ?>
      <j:jelly trim = "false" xmlns:j = "jelly:core" xmlns:g = "glide" xmlns:j2 = "null" xmlns:g2 = "null" >
       
      	<j:if test = "${current_page.getName()=='Solutions'}" >
      	<h1 class = "page_name" > <b> <a href = "solutions.do?" title = "${gs.getMessage('Solutions')}" >${gs.getMessage('Solutions')}</a> </b> </h1>
      	<p class = "page_description" >
      	 	    ${current_page.getDescription()}
      	</p> <br />
      	</j:if>
      	<j:if test = "${current_page.getName()=='IT 3.0'}" >
      	   <h1 class = "page_name" > <b> <a href = "solutions.do?" title = "${gs.getMessage('Solutions')}" >${gs.getMessage('Solutions')}</a> </b> | ${current_page.getName()}</h1>
      	   <p class = "page_description" >
      	 	    ${current_page.getDescription()}
      		</p> <br />
      		</j:if>
      		</j:jelly>

      Ensure that all tags are closed. If the tag is not a naturally closing tag, then place a forward slash before the end bracket. For example, a <BR /> or an <IMG src="cms.png" />.

      If you are unfamiliar with Jelly scripting, review these topics:
      • Jelly tags
      • Extensions to Jelly syntax
      • Jelly escaping types

      Include the following tag with all Apache Jelly scripts.

      <j:jelly trim= "false" xmlns:j= "jelly:core" xmlns:g= "glide" xmlns:j2= "null" xmlns:g2= "null" >
      The tag looks complex, but keep the following information in mind.
      • Apache Jelly script uses multiple namespaces.
      • There are two types of prefixes in tags: j and g. The j prefix is used for tags that are natively part of Apache Jelly. The g prefix is used for tags that the ServiceNow platform created and is using for platform purposes.

      The j2 and g2 prefixes are just like j and g, except that they are processed in a second phase. The Apache Jelly script parser runs through each j and g tag respectively. For example:

      <j:jelly trim="false" xmlns:j="jelly:core" xmlns:g="glide" xmlns:j2="null" xmlns:g2="null">
      	<j:set var="jvar_phase1" value="Hello" />
      	<j2:set var="jvar_phase2" value="World" />
      	${jvar_phase1} $[jvar_phase2]
      </j:jelly>

      In phase 1, the parser runs through all the j and g tags. It then caches the result. Before it runs the second phase, it takes the j and g namespaces and moves the namespaces to the second phase. It looks something like the following code.

      <j:jelly trim="false" xmlns:j="jelly:core" xmlns:g="glide" xmlns:j2="jelly:core" xmlns:g2="glide">
      	<j2:set var="jvar_phase2" value="World" />
      	Hello $[jvar_phase2]
      </j:jelly>
      For subsequent calls of this script, only phase 2 is parsed.
      Note: If you plan to use phase 2 Jelly tags (g2 and j2) on the Content Type [content_type] or Dynamic Content [content_block_programmatic] tables, select the Two phase option on the content form.

      Another example is to create a report of all open incidents assigned to each group. For this purpose, you could use a report and save time, but it is a good example for learning Jelly. Start with the Jelly tag:

      <j:jelly trim= "false" xmlns:j= "jelly:core" xmlns:g= "glide" xmlns:j2= "null" xmlns:g2= "null" >
      </j:jelly>

      First, you need a list of open incidents. Use a g2:evaluate tag. The evaluate tag runs the script. Anything inside the tag is parsed like a business rule, so, for example, you can call global business rules, script includes, and gliderecord.

      <j:jelly trim="false" xmlns:j="jelly:core" xmlns:g="glide" xmlns:j2="null" xmlns:g2="null">
      	<g:evaluate var="jvar_groups" object="true">
      		var now_GR = new GlideRecord("sys_user_group");
      		gr.orderBy('name');
      		gr.query();
      		gr;
      	</g:evaluate>
      </j:jelly>

      This script is in phase 1 because frequent changes to incident assignment groups are not expected. Also notice the var attribute on the evaluate tag. This attribute specifies what variable is set from this block. At the end of the script, there is a gr on a line by itself. That last line is what sets the variable.

      You can omit the jvar_groups variable, but then all the variables in the evaluate tag become Apache Jelly variables. The object=true specifies that the variable is not a primitive data type. If object=true is omitted, the script would break because jvar_groups would only be able to hold items like integers and strings.

      After the evaluate tag, loop through these groups and find the incidents for each one.

      <j:jelly trim="false" xmlns:j="jelly:core" xmlns:g="glide" xmlns:j2="null" xmlns:g2="null">
      	<g:evaluate var="jvar_groups" object="true">
      		var now_GR = new GlideRecord("sys_user_group");
      		gr.orderBy('name');
      		gr.query();
      		gr;
      	</g:evaluate>
      	<table>
      		<tr>
      			<th>Name</th>
      			<th>Incidents</th>
      		</tr>
      		<j:while test="${jvar_groups.next()}">
      			<tr>
      				<td>${HTML:jvar_groups.getValue('name')}</td>
      				<td></td>
      			</tr>
      		</j:while>
      	</table>
      </j:jelly>
      You can include normal XML in the Apache Jelly script at any time. Since there is no namespace, the Apache Jelly script does not try to parse the XML tags. Notice the j:while loop. It is a normal while loop and can iterate through a GlideRecord object. Also notice that you output a value with ${HTML:jvar_groups.getValue('name')}. Here are the important elements:
      • The outer brackets, ${}, specify the output of the variable and the phase in which the variable is output: ${} means first phase, $[] means second phase.
      • HTML before the expression is for escaping the output. The expression jvar_groups.getValue('name') is being escaped for HTML. For other types of escaping, there are JS (Javascript), NS (No Script), and some other options.

      To select only one record and not iterate through many records, the code looks like the following example:

      <j:jelly trim="false" xmlns:j="jelly:core" xmlns:g="glide" xmlns:j2="null" xmlns:g2="null">
      	<g:evaluate var="jvar_groups" object="true">
      		var now_GR = new GlideRecord("sys_user_group");
      		gr.orderBy('name');
      		gr.query();
      		gr;
      	</g:evaluate>
      	<j:if test="${jvar_groups.next()}">
      		We found ${HTML:jvar_groups.getValue('name')}
      	</j:if>
      </j:jelly>
      • Content management and Jelly code examples

        Code examples

      Related tasks
      • Configure a content block
      • View CMS block tags
      Related reference
      • Types of content blocks

      Tags:

      Feedback

          Share this page

          Got it! Feel free to add a comment
          To share your product suggestions, visit the Idea Portal.
          Please let us know how to improve this content

          Check any that apply

          To share your product suggestions, visit the Idea Portal.
          Confirm

          We were unable to find "Coaching" in Jakarta. Would you like to search instead?

          No Yes
          • Contact Us
          • Careers
          • Terms of Use
          • Privacy Statement
          • Sitemap
          • © ServiceNow. All rights reserved.

          Subscribe Subscribed Unsubscribe Last updated: Tags: January February March April May June July August September October November December No Results Found Versions Search preferences successfully updated My release version successfully updated My release version successfully deleted An error has occurred. Please try again later. You have been unsubscribed from all topics. You are now subscribed to and will receive notifications if any changes are made to this page. You have been unsubscribed from this content Thank you for your feedback. Form temporarily unavailable. Please try again or contact  docfeedback@servicenow.com  to submit your comments. The topic you requested does not exist in the release. You were redirected to a related topic instead. The available release versions for this topic are listed There is no specific version for this documentation. Explore products Click to go to the page. Release notes and upgrades Click to open the dropdown menu. Delete Remove No selected version Reset This field is required You are already subscribed to this topic Attach screenshot The file you uploaded exceeds the allowed file size of 20MB. Please try again with a smaller file. Please complete the reCAPTCHA step to attach a screenshot
          Log in to personalize your search results and subscribe to topics
          No, thanks Login