CINXE.COM

JEXL – Apache Commons JEXL Overview

<!DOCTYPE html> <!-- | Generated by Apache Maven Doxia at 06 June 2024 | Rendered using Apache Maven Fluido Skin 1.3.0 --> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <head> <meta charset="iso-8859-1" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="Date-Revision-yyyymmdd" content="20240606" /> <meta http-equiv="Content-Language" content="en" /> <title>JEXL &#x2013; Apache Commons JEXL Overview</title> <link rel="stylesheet" href="./css/bootstrap.min.css" type="text/css" /> <link rel="stylesheet" href="./css/site.css" type="text/css" /> <link rel="stylesheet" href="./css/print.css" media="print" /> <script type="text/javascript" src="./js/jquery.min.js"></script> <script type="text/javascript" src="./js/bootstrap.min.js"></script> <script type="text/javascript" src="./js/prettify.min.js"></script> <script type="text/javascript" src="./js/site.js"></script> </head> <body class="composite"> <a href="https://commons.apache.org/" id="bannerLeft" title="Apache Commons logo"> <img class="logo-left" src=" ./images/commons-logo.png " alt="Apache Commons logo"/> </a> <a href="index.html" id="bannerRight"> <img class="logo-right" src=" images/jexl-logo-white.png " alt="Apache Commons JEXL"/> </a> <div class="clear"></div> <div class="navbar"> <div class="navbar-inner"> <div class="container-fluid"> <a class="brand" href="https://commons.apache.org/proper/commons-jexl/">Apache Commons JEXL &trade;</a> <ul class="nav"> <li id="publishDate">Last Published: 06 June 2024</li> <li class="divider">|</li> <li id="projectVersion">Version: 3.4.0</li> </ul> <div class="pull-right"> <ul class="nav"> <li> <a href="https://www.apachecon.com/" class="externalLink" title="ApacheCon"> ApacheCon</a> </li> <li> <a href="https://www.apache.org" class="externalLink" title="Apache"> Apache</a> </li> <li> <a href="../../" title="Commons"> Commons</a> </li> </ul> </div> </div> </div> </div> <div class="container-fluid"> <table class="layout-table"> <tr> <td class="sidebar"> <div class="well sidebar-nav"> <ul class="nav nav-list"> <li class="nav-header">JEXL</li> <li class="none active"> <a href="index.html" title="Overview"> Overview</a> </li> <li class="none"> <a href="relnotes34.html" title="Release Notes"> Release Notes</a> </li> <li class="none"> <a href="apidocs/index.html" title="Javadoc 3.4"> Javadoc 3.4</a> </li> <li class="none"> <a href="javadocs/apidocs-2.1.1/index.html" title="Javadoc 2.1.1"> Javadoc 2.1.1</a> </li> <li class="none"> <a href="javadocs/apidocs-1.1/index.html" title="Javadoc 1.1"> Javadoc 1.1</a> </li> <li class="none"> <a href="download_jexl.cgi" title="Download"> Download</a> </li> <li class="none"> <a href="reference/index.html" title="Reference"> Reference</a> </li> </ul> <ul class="nav nav-list"> <li class="nav-header"><i class="icon-cog"></i>Development</li> <li class="none"> <a href="mail-lists.html" title="Mailing Lists"> Mailing Lists</a> </li> <li class="none"> <a href="issue-tracking.html" title="Issue Tracking"> Issue Tracking</a> </li> <li class="none"> <a href="scm.html" title="Source Repository"> Source Repository</a> </li> <li class="none"> <a href="building.html" title="Building"> Building</a> </li> <li class="none"> <a href="apidocs/index.html" title="Javadoc (SVN latest)"> Javadoc (SVN latest)</a> </li> </ul> <ul class="nav nav-list"> <li class="nav-header"><i class="icon-info-sign"></i>Project Documentation</li> <li class="expanded"> <a href="project-info.html" title="Project Information"> Project Information</a> <ul> <li class="none active"> <a href="index.html" title="About"> About</a> </li> <li class="none"> <a href="summary.html" title="Summary"> Summary</a> </li> <li class="none"> <a href="team.html" title="Team"> Team</a> </li> <li class="none"> <a href="scm.html" title="Source Code Management"> Source Code Management</a> </li> <li class="none"> <a href="issue-management.html" title="Issue Management"> Issue Management</a> </li> <li class="none"> <a href="mailing-lists.html" title="Mailing Lists"> Mailing Lists</a> </li> <li class="none"> <a href="dependency-info.html" title="Dependency Information"> Dependency Information</a> </li> <li class="none"> <a href="dependency-management.html" title="Dependency Management"> Dependency Management</a> </li> <li class="none"> <a href="dependencies.html" title="Dependencies"> Dependencies</a> </li> <li class="none"> <a href="dependency-convergence.html" title="Dependency Convergence"> Dependency Convergence</a> </li> <li class="none"> <a href="ci-management.html" title="CI Management"> CI Management</a> </li> <li class="none"> <a href="distribution-management.html" title="Distribution Management"> Distribution Management</a> </li> </ul> </li> <li class="collapsed"> <a href="project-reports.html" title="Project Reports"> Project Reports</a> </li> </ul> <ul class="nav nav-list"> <li class="nav-header">Commons</li> <li class="none"> <a href="../../" title="Home"> Home</a> </li> <li class="none"> <a href="https://www.apache.org/licenses/" class="externalLink" title="License"> License</a> </li> <li class="collapsed"> <a href="../../components.html" title="Components"> Components</a> </li> <li class="collapsed"> <a href="../../sandbox/index.html" title="Sandbox"> Sandbox</a> </li> <li class="collapsed"> <a href="../../dormant/index.html" title="Dormant"> Dormant</a> </li> </ul> <ul class="nav nav-list"> <li class="nav-header">General Information</li> <li class="none"> <a href="../../security.html" title="Security"> Security</a> </li> <li class="none"> <a href="../../volunteering.html" title="Volunteering"> Volunteering</a> </li> <li class="none"> <a href="../../patches.html" title="Contributing Patches"> Contributing Patches</a> </li> <li class="none"> <a href="../../building.html" title="Building Components"> Building Components</a> </li> <li class="none"> <a href="../../commons-parent-pom.html" title="Commons Parent POM"> Commons Parent POM</a> </li> <li class="none"> <a href="../../build-plugin/index.html" title="Commons Build Plugin"> Commons Build Plugin</a> </li> <li class="none"> <a href="../../release-plugin/index.html" title="Commons Release Plugin"> Commons Release Plugin</a> </li> <li class="none"> <a href="../../site-publish.html" title="Site Publication"> Site Publication</a> </li> <li class="none"> <a href="../../releases/index.html" title="Releasing Components"> Releasing Components</a> </li> <li class="none"> <a href="https://cwiki.apache.org/confluence/display/commons/FrontPage" class="externalLink" title="Wiki"> Wiki</a> </li> </ul> <ul class="nav nav-list"> <li class="nav-header">ASF</li> <li class="none"> <a href="https://www.apache.org/foundation/how-it-works.html" class="externalLink" title="How the ASF works"> How the ASF works</a> </li> <li class="none"> <a href="https://www.apache.org/foundation/getinvolved.html" class="externalLink" title="Get Involved"> Get Involved</a> </li> <li class="none"> <a href="https://www.apache.org/dev/" class="externalLink" title="Developer Resources"> Developer Resources</a> </li> <li class="none"> <a href="https://www.apache.org/foundation/policies/conduct.html" class="externalLink" title="Code of Conduct"> Code of Conduct</a> </li> <li class="none"> <a href="https://privacy.apache.org/policies/privacy-policy-public.html" class="externalLink" title="Privacy"> Privacy</a> </li> <li class="none"> <a href="https://www.apache.org/foundation/sponsorship.html" class="externalLink" title="Sponsorship"> Sponsorship</a> </li> <li class="none"> <a href="https://www.apache.org/foundation/thanks.html" class="externalLink" title="Thanks"> Thanks</a> </li> </ul> </div> <div id="poweredBy"> <a href="https://www.apache.org/events/current-event.html" title="ApacheCon" class="builtBy"> <img class="builtBy" alt="ApacheCon" src="https://www.apache.org/events/current-event-125x125.png" /> </a> <a href="https://maven.apache.org/" title="Maven" class="builtBy"> <img class="builtBy" alt="Maven" src="https://maven.apache.org/images/logos/maven-feather.png" /> </a> </div> </td> <td class="content"> <section> <h2><a name="Java_Expression_Language_.28JEXL.29"></a>Java Expression Language (JEXL)</h2> <p> JEXL is a library intended to facilitate the implementation of dynamic and scripting features in applications and frameworks written in Java. </p> <p> JEXL implements an Expression Language based on some extensions to the JSTL Expression Language supporting most of the constructs seen in shell-script or ECMAScript. <br /> Its goal is to expose scripting features usable by technical operatives or consultants working with enterprise platforms. In many use cases, JEXL allows end-users of an application to code their own scripts or expressions and ensure their execution within controlled functional constraints. </p> <p> The library exposes a small footprint API - the <a href="apidocs/org/apache/commons/jexl3/package-summary.html#usage">core features</a> fit in 3 classes and 10 methods - that can be used in various conditions: </p> <ul> <li>Scripting features: <ul> <li>Your application lets (advanced) users evaluate or define some simple expressions like computation formulas.</li></ul> </li> <li>Module or component configuration: <ul> <li>Your application has configuration files (eventually generated by a design module) consumed by the end-user module that would benefit from variables and expressions. </li> <li>When it would be convenient to use IOC but overall complexity doesn't require (or can't depend upon) a full-blown library (Spring, Guice...). </li> </ul> </li> <li>Loose-coupling of interfaces and implementations or duck-typing: <ul> <li>You have optional classes that your code cant consider as compilation dependencies.</li> <li>You have to integrate and call &quot;legacy&quot; code or use components that you don't want to strongly depend upon.</li> </ul> </li> <li>Simple template capabilities: <ul> <li>Your application has basic template requirements and JSPs or Velocity would be overkill or too inconvenient to deploy.</li></ul> </li> </ul> <p> JEXL name stands for Java EXpression Language, a simple expression language originally inspired by Apache Velocity and the Expression Language defined in the JavaServer Pages Standard Tag Library version 1.1 (JSTL) and JavaServer Pages version 2.0 (JSP). JEXL 2.0 added features inspired by <a class="externalLink" href="https://en.wikipedia.org/wiki/Unified_Expression_Language">Unified EL</a>. The syntax is now close to a mix of ECMAScript and &quot;shell-script&quot; making it easy to master by technical operatives or consultants. The objects exposed and their behavior obviously need to be documented though... </p> <p> The API and the expression language exploit Java-beans naming patterns through introspection to expose property getters and setters. It also considers public class fields as properties and allows to invoke any accessible method. </p> </section> <section> <h2><a name="A_Detailed_Example"></a>A Detailed Example</h2> <p> To create expressions and scripts, a <a href="apidocs/org/apache/commons/jexl3/JexlEngine.html">JexlEngine</a> is required. To instantiate one, a <a href="apidocs/org/apache/commons/jexl3/JexlBuilder.html">JexlBuilder</a> is needed to describe the allowed <a href="apidocs/org/apache/commons/jexl3/introspection/JexlPermissions.html">JexlPermissions</a> and <a href="apidocs/org/apache/commons/jexl3/JexlFeatures.html">JexlFeatures</a> that will determine which classes and methods scripts can access and call and which syntactic elements scripts are allowed to use. Do not overlook this configuration aspect, especially the permissions since <b>security of your application</b> might depend on it. Once built, the JEXL engine should be stored, shared and reused. It is thread-safe ; so are the scripts during evaluation. </p> <p> When evaluating expressions, JEXL merges an <a href="apidocs/org/apache/commons/jexl3/JexlExpression.html">JexlExpression</a> or a <a href="apidocs/org/apache/commons/jexl3/JexlScript.html">JexlScript</a> with a <a href="apidocs/org/apache/commons/jexl3/JexlContext.html">JexlContext</a>. In its simplest form, a script is created using <a href="apidocs/org/apache/commons/jexl3/JexlEngine.html#createScriptjava.lang.String">JexlEngine#createExpression()</a>, passing a String containing valid JEXL syntax. A simple JexlContext can be created by instantiating a <a href="apidocs/org/apache/commons/jexl3/MapContext.html">MapContext</a>; a map of variables that will be internally wrapped can be optionally provided through its constructor. </p> <p> JEXL's intention is a tight integration with its hosting platform; the scripting syntax is very close to JScript but leverages (potentially) any public class or method that Java exposes. How tight and how rich this integration is up to you; deriving JEXL API classes - most notably JexlPermissions, JexlContext, JexlArithmetic - are the means to that end. </p> <p>The following example illustrate these aspects. It uses a specific set of permissions to allow using URI class and a tailored context to expose streams in a convenient manner.</p> <div> <div> <pre style="text-align: left; border: 1px dashed #008DEF; line-height: 18px; padding: 15px; font-size: 13px; font-family:'Courier New', Courier, monospace; overflow: auto;"><span style="color:#3F5FBF">/** * A test around scripting streams. */</span> <span style="font-weight:bold;color:#7B0052;">public</span> <span style="font-weight:bold;color:#7B0052;">class</span> StreamTest <span style="font-weight:bold;color:#D3171B">{</span> <span style="color:#3F5FBF">/** Our engine instance. */</span> <span style="font-weight:bold;color:#7B0052;">private</span> <span style="font-weight:bold;color:#7B0052;">final</span> JexlEngine jexl; <span style="font-weight:bold;color:#7B0052;">public</span> StreamTest() <span style="font-weight:bold;color:#D3171B">{</span> <span style="color:#3F7F5F">// Restricting features; no loops, no side effects </span> JexlFeatures features = <span style="font-weight:bold;color:#7B0052;">new</span> JexlFeatures() .loops(<span style="font-weight:bold;color:#7B0052;">false</span>) .sideEffectGlobal(<span style="font-weight:bold;color:#7B0052;">false</span>) .sideEffect(<span style="font-weight:bold;color:#7B0052;">false</span>); <span style="color:#3F7F5F">// Restricted permissions to a safe set but with URI allowed </span> JexlPermissions permissions = <span style="font-weight:bold;color:#7B0052;">new</span> ClassPermissions(java.net.URI.class); <span style="color:#3F7F5F">// Create the engine </span> jexl = <span style="font-weight:bold;color:#7B0052;">new</span> JexlBuilder().features(features).permissions(permissions).create(); <span style="font-weight:bold;color:#D3171B">}</span> <span style="color:#3F5FBF">/** * A MapContext that can operate on streams. */</span> <span style="font-weight:bold;color:#7B0052;">public</span> <span style="font-weight:bold;color:#7B0052;">static</span> <span style="font-weight:bold;color:#7B0052;">class</span> StreamContext <span style="font-weight:bold;color:#7B0052;">extends</span> MapContext <span style="font-weight:bold;color:#D3171B">{</span> <span style="color:#3F5FBF">/** * This allows using a JEXL lambda as a mapper. * @param stream the stream * @param mapper the lambda to use as mapper * @return the mapped stream */</span> <span style="font-weight:bold;color:#7B0052;">public</span> Stream&lt;?&gt; map(Stream&lt;?&gt; stream, <span style="font-weight:bold;color:#7B0052;">final</span> JexlScript mapper) <span style="font-weight:bold;color:#D3171B">{</span> <span style="font-weight:bold;color:#7B0052;">return</span> stream.map( x -&gt; mapper.execute(this, x)); <span style="font-weight:bold;color:#D3171B">}</span> <span style="color:#3F5FBF">/** * This allows using a JEXL lambda as a filter. * @param stream the stream * @param filter the lambda to use as filter * @return the filtered stream */</span> <span style="font-weight:bold;color:#7B0052;">public</span> Stream&lt;?&gt; filter(Stream&lt;?&gt; stream, <span style="font-weight:bold;color:#7B0052;">final</span> JexlScript filter) <span style="font-weight:bold;color:#D3171B">{</span> <span style="font-weight:bold;color:#7B0052;">return</span> stream.filter(x -&gt; x =! <span style="font-weight:bold;color:#7B0052;">null</span> &amp;&amp; TRUE.equals(filter.execute(this, x))); <span style="font-weight:bold;color:#D3171B">}</span> <span style="font-weight:bold;color:#D3171B">}</span> @Test <span style="font-weight:bold;color:#7B0052;">public</span> <span style="font-weight:bold;color:#7B0052;">void</span> testURIStream() <span style="font-weight:bold;color:#7B0052;">throws</span> Exception <span style="font-weight:bold;color:#D3171B">{</span> <span style="color:#3F7F5F">// let's assume a collection of uris need to be processed and transformed to be simplified ; </span> <span style="color:#3F7F5F">// we want only http/https ones, only the host part and forcing an https scheme </span> List&lt;URI&gt; uris = Arrays.asList( URI.create(<span style="color:#2A00FF">&quot;http://user@www.apache.org:8000?qry=true&quot;</span>), URI.create(<span style="color:#2A00FF">&quot;https://commons.apache.org/releases/prepare.html&quot;</span>), URI.create(<span style="color:#2A00FF">&quot;mailto:henrib@apache.org&quot;</span>) ); <span style="color:#3F7F5F">// Create the test control, the expected result of our script evaluation </span> List&lt;?&gt; control = uris.stream() .map(uri -&gt; uri.getScheme().startsWith(<span style="color:#2A00FF">&quot;http&quot;</span>)? <span style="color:#2A00FF">&quot;https://&quot;</span> + uri.getHost() : <span style="font-weight:bold;color:#7B0052;">null</span>) .filter(x -&gt; x != <span style="font-weight:bold;color:#7B0052;">null</span>) .collect(Collectors.toList()); Assert.assertEquals(2, control.size()); <span style="color:#3F7F5F">// Create scripts: </span> <span style="color:#3F7F5F">// uri is the name of the variable used as parameter; the beans are exposed as properties </span> <span style="color:#3F7F5F">// note the starts-with operator =^ </span> <span style="color:#3F7F5F">// note that uri is also used in the back-quoted string that performs variable interpolation </span> JexlScript mapper = jexl.createScript(<span style="color:#2A00FF">&quot;uri.scheme =^ 'http'? `https://${uri.host}` : null&quot;</span>, <span style="color:#2A00FF">&quot;uri&quot;</span>); <span style="color:#3F7F5F">// using the bang-bang / !! - JScript like - is the way to coerce to boolean in the filter </span> JexlScript transform = jexl.createScript( <span style="color:#2A00FF">&quot;list.stream().map(mapper).filter(x -&gt; !!x).collect(Collectors.toList())&quot;</span>, <span style="color:#2A00FF">&quot;list&quot;</span>); <span style="color:#3F7F5F">// Execute scripts: </span> JexlContext sctxt = <span style="font-weight:bold;color:#7B0052;">new</span> StreamContext(); <span style="color:#3F7F5F">// expose the static methods of Collectors; java.util.* is allowed by permissions </span> sctxt.set(<span style="color:#2A00FF">&quot;Collectors&quot;</span>, Collectors.class); <span style="color:#3F7F5F">// expose the mapper script as a global variable in the context </span> sctxt.set(<span style="color:#2A00FF">&quot;mapper&quot;</span>, mapper); Object transformed = transform.execute(sctxt, uris); Assert.assertTrue(transformed <span style="font-weight:bold;color:#7B0052;">instanceof</span> List&lt;?&gt;); Assert.assertEquals(control, transformed); <span style="font-weight:bold;color:#D3171B">}</span> <span style="font-weight:bold;color:#D3171B">}</span></pre></div> </div> </section> <section> <h2><a name="Extensions_to_JSTL_Expression_Language"></a>Extensions to JSTL Expression Language</h2> <p> JEXL attempts to bring some of the lessons learned by the Velocity community about expression languages in templating to a wider audience. <a class="externalLink" href="https://commons.apache.org/jelly">Commons Jelly</a> needed Velocity-ish method access, it just had to have it. </p> <p> It must be noted that JEXL is <b>not</b> a compatible implementation of EL as defined in JSTL 1.1 (JSR-052) or JSP 2.0 (JSR-152). For a compatible implementation of these specifications, see the <a class="externalLink" href="https://commons.apache.org/el">Commons EL</a> project. </p> <p> While JEXL 3.3 is now closer to JScript (without prototypes), its roots are the expression language defined in JSTL and its has improved upon its syntax in a few areas: </p> <ul> <li>Support for invocation of any accessible method (see example above).</li> <li>Support for setting/getting any accessible public field.</li> <li>A general <span class="literal">new()</span> method allowing to instantiate objects.</li> <li>A general <span class="literal">size()</span> method, which works on: <ul> <li><span class="literal">String</span> - returns length</li> <li><span class="literal">Map</span> - returns number of keys</li> <li><span class="literal">List</span> - returns number of elements.</li> </ul> </li> <li>A general <span class="literal">empty()</span> method, which works on Collections and Strings.</li> <li>Support for the ternary operator 'a ? b : c' - and its GNU-C / &quot;Elvis&quot; variant 'a ?: c'.</li> <li>Support for the Perl-like regex matching operators '=~' and '!~'</li> <li>Support for the CSS3-inspired 'startsWith' and 'endsWith' operators '=^' and '=$'</li> <li>Support for user-defined functions.</li> <li>Misc : '+' has been overloaded to be use as a String concatenation operator</li> </ul> </section> <section> <h2><a name="Related_Resources"></a>Related Resources</h2> <p> JEXL is not a product of the Java Community Process (JCP), but it provides a similar expression syntax. For more information about JSP 2.0 EL and JSTL 1.1 EL: </p> <ul> <li> <a class="externalLink" href="http://www.oracle.com/technetwork/java/index-jsp-138231.html">JSP 2.0</a> is covered by Java Specification Requests (JSR) <a class="externalLink" href="http://www.jcp.org/en/jsr/detail?id=152">JSR-152: JavaServer Pages 2.0 Specification</a>. </li> <li> Apache has an implementation of the expression language for JSP 2.0, called <a class="externalLink" href="https://commons.apache.org/el/index.html">EL</a> </li> <li> <a class="externalLink" href="http://www.oracle.com/technetwork/java/index-jsp-135995.html">JSTL 1.1</a> is covered by <a class="externalLink" href="http://jcp.org/en/jsr/detail?id=52">JSR 52: A Standard Tag Library for JavaServer Pages</a>. See the <a class="externalLink" href="http://docs.oracle.com/javaee/5/jstl/1.1/docs/tlddocs/">JSTL API</a>. </li> <li>Apache has a <a class="externalLink" href="http://tomcat.apache.org/taglibs/standard/">JSTL Implementation</a>.</li> </ul> <section> <h3><a name="Velocity"></a>Velocity</h3> <p> <a class="externalLink" href="http://velocity.apache.org/">Apache Velocity</a> implements a similar expression language. </p> <p> In particular the <a class="externalLink" href="http://velocity.apache.org/engine/devel/user-guide.html#References">References</a> section of the User Guide has some good information on properties and method which correlate directly to JEXL. </p> </section> </section> <section> <h2><a name="Anyone_Using_It_Yet.3F"></a>Anyone Using It Yet?</h2> <ul> <li> <a class="externalLink" href="https://commons.apache.org/configuration">Commons Configuration</a> </li> <li> <a class="externalLink" href="https://commons.apache.org/scxml">Commons SCXML</a> </li> <li> <a class="externalLink" href="https://commons.apache.org/jelly">Jelly</a> </li> </ul> </section> </td> </tr> </table> </div> <div class="footer"> <p>Copyright &copy; 2001-2024 <a href="https://www.apache.org/">The Apache Software Foundation</a>. All Rights Reserved.</p> <div class="center">Apache Commons, Apache Commons JEXL, Apache, the Apache feather logo, and the Apache Commons project logos are trademarks of The Apache Software Foundation. All other marks mentioned may be trademarks or registered trademarks of their respective owners.</div> </div> </body> </html>

Pages: 1 2 3 4 5 6 7 8 9 10