---
title: PingGateway expressions
description: Use expressions that conform to the Unified Expression Language in JSR-245 to specify configuration parameters as expressions in routes. The result of an expression must match the expected type.
component: pinggateway
version: 2026
page_id: pinggateway:reference:Expressions
canonical_url: https://docs.pingidentity.com/pinggateway/2026/reference/Expressions.html
revdate: 2025-08-26T18:26:39Z
section_ids:
  syntax: Syntax
  route_syntax: Route syntax
  immediate_and_deferred_evaluation_syntax: Immediate and deferred evaluation syntax
  operator_syntax: Operator syntax
  array_syntax: Array syntax
  map_syntax: Map syntax
  function_syntax: Function syntax
  method_syntax: Method syntax
  escape_syntax: Escape syntax
  configuration_expressions: Configuration expressions
  runtime-expression: Runtime expressions
  expressions-embedding: Embedded expressions
  expressions-extension: Extensions
  expressions-value-expression: L-value expressions
  expressions-operators: Operators
  expressions-dynamic-bindings: Dynamic bindings
  expressions-example: Examples
  immediate_evaluation_of_configuration_expressions: Immediate evaluation of configuration expressions
  deferred_evaluation_of_runtime_expressions: Deferred evaluation of runtime expressions
  immediate_and_deferred_evaluation_of_runtime_expressions: Immediate and deferred evaluation of runtime expressions
  example-expression-function: Expressions that use functions
---

# PingGateway expressions

Use expressions that conform to the Unified Expression Language in [JSR-245](https://www.jcp.org/en/jsr/detail?id=245) to specify configuration parameters as expressions in routes. The result of an expression must match the expected type.

Use expressions in routes for the following tasks:

* Evaluate object properties

  The following example returns the URI of the incoming request:

  ```
  ${request.uri}
  ```

* Call functions described in [PingGateway functions](Functions.html)

  Functions can be operands for operations and can yield parameters for other function calls.

  The following example uses the function `find` to test whether the request URI is on the `/home` path:

  ```
  ${find(request.uri.path, '^/home')}
  ```

* Call Java methods

  The following example uses the method Java `String.startsWith()` to test whether the request starts with `/home`:

  ```
  ${request.uri.path.startsWith("/home")}
  ```

* Retrieve Java system properties

  The following example yields the home directory of the user executing the PingGateway process:

  ```
  ${system['user.home']}
  ```

* Retrieve environment variables

  The following example yields the home directory of the user executing the PingGateway process:

  ```
  ${env['HOME']}
  ```

  The following example yields the path value of the `keystore.p12` file in the user's home directory. The result is just a String concatenation, there is no verification that the file actually exists:

  ```
  ${env['HOME']}/keystore.p12`
  ```

* Perform logical operations such as `and`, `or`, and `not`

  The following expression uses the operators `and` and `or` to determine where to dispatch a request. The expression is used in [Share JWT sessions between multiple instances of PingGateway](../installation-guide/jwtsession-using.html#jwtsession-sharesecrets):

  ```
  ${find(request.uri.path, '/webapp/browsing') and (contains(request.uri.query, 'one') or empty(request.uri.query))}
  ```

* Perform arbitrarily complex arithmetic, such as addition, substraction, division, and multiplication

  The following expression yields the URI port number incremented by four:

  ```
  ${request.uri.port + 4}
  ```

* Perform relational operations, such as numerical equality and inequality

  The following example is for a DispatchHandler condition, where the request is dispatched if it contains a form field with the attribute `answer` whose value is greater than `42`:

  ```json
  "bindings": [
    {
      "condition": "#{request.entity.form['answer'] > 42}",
      "handler": ...
    }
  ]
  ```

* Perform conditional operations of this form `<condition> ? <if-true> : <if-false>`

  The following example tests whether the request path starts with `/home`. If so, the request is directed to `home`; otherwise, it is directed to `not-home`:

  ```
  ${request.uri.path.startsWith('/home') ? 'home' : 'not-home' }
  ```

* Consume evaluated configuration tokens described in [JSON Evaluation](JsonEval.html) (runtime expressions only)

  The following example returns `true` if the configuration token `my.status.code` resolves to `200`:

  ```
  ${integer(&{my.status.code|404}) == 200}
  ```

Expressions access the environment through the implicit object `openig`. The object has the following properties:

* `instanceDirectory`: Path to the base location for PingGateway files.

  The default location is:

  * Linux

    `$HOME/.openig`

  * Windows

    `%appdata%\OpenIG\config`

* `configDirectory`: Path to the PingGateway configuration files.

  The default location is:

  * Linux

    `$HOME/.openig/config`

  * Windows

    `%appdata%\OpenIG\config`

* `temporaryDirectory`: Path to the PingGateway temporary files.

  The default location is:

  * Linux

    `$HOME/.openig/tmp`

  * Windows

    `%appdata%\OpenIG\tmp`

Learn how to change default values in [Change the base location of the PingGateway configuration](../configure/configure.html#configure-default-location).

## Syntax

Expression syntax must conform to Unified Expression Language described in [JSR-245](https://www.jcp.org/en/jsr/detail?id=245).

### Route syntax

Expressions in routes are enclosed in quotation marks, for example: `"${request.method}"` and `"#{expression}"`.

### Immediate and deferred evaluation syntax

Use the `${}` syntax for expressions to be evaluated at startup or when a route loads or reloads.

Use the `#{}` syntax for expressions to be evaluated later, when the evaluation result requires the request or response to be fully loaded.

### Operator syntax

AM uses the `.` and `[]` operators to access properties:

* Use `.` for the following tasks:

  * Access object properties, such as public fields and Java bean properties.

  * Invoke methods on an object.

  * Access map entries when the specified entry name doesn't contain reserved characters.

* Use `[]` to access indexed elements:

  * If the object is a collection, such as an array, set, or list, use `[i]` to access an element at position `i`.

  * If the object isn't a collection, such as an array, set, or list, use `['prop']` to access the property `'prop'`. This is equivalent to `.` notation. The following expressions are equivalent:

    ```
    ${request.method}
    ```

    ```
    ${request['method']}
    ```

  * If the object is a map, use `['name']` to access the entry with name `'name'`.

|   |                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| - | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|   | To access map entries containing characters that are also expression operators, prevent parsing exceptions by using `[]` instead of `.`For example, to access a map field containing a dash `-`, such as `dash-separated-name`, write the expression as:```
${data['dash-separated-name']}
```instead of:```
${data.dash-separated-name}
```In the second example, the dash `-` is interpreted as part of the String instead of as an expression operator. |

### Array syntax

The index of an element in an array is expressed as a number in brackets. For example, the following expression refers to the first `Content-Type` header value in a request:

```
${request.headers['Content-Type'][0]}
```

### Map syntax

The map key is expressed in brackets. For example, the following expression is an example of Map entry access:

```
system['prop.name']
```

If a property doesn't exist, the index reference yields a `null` (empty) value.

### Function syntax

Expressions can call built-in functions described in [PingGateway functions](Functions.html).

Use the syntax `${function(parameter, …​)}`, supplying one or more parameters to the function. For examples, refer to [Expressions that use functions](#example-expression-function).

Functions can be operands for operations and can yield parameters for other function calls.

### Method syntax

Use the syntax `${object.method()}` to call a method on the object instance.

If the object resolves to a String, then all methods in the `java.lang.String` class are usable.

For examples, refer to [Expressions that use functions](#example-expression-function).

### Escape syntax

The character `\` is treated as an escape character when followed by `${` or `\#{`.

For example, the expression `${true}` normally evaluates to `true`. To include the string `${true}` in an expression, write `\${true}`

When `\` is followed by any other character sequence, it isn't treated as an escape character.

## Configuration expressions

PingGateway evaluates configuration expressions at startup and when a route loads or reloads. Configuration expressions are always evaluated immediately and use the `${}` syntax.

Configuration expressions can refer to the following information:

* System heap properties

* Built-in functions listed in [PingGateway functions](Functions.html)

* Environment variables, `${env['variable']}`

* System properties, `${system['property']}`

* [ExpressionInstant](../_attachments/apidocs/org/forgerock/openig/el/ExpressionInstant.html)

Because configuration expressions are evaluated before requests are made, they can't refer to the runtime properties `request`, `response`, `context`, or `contexts`.

## Runtime expressions

PingGateway evaluates runtime expressions for each request and response, as follows:

* Immediate evaluation of runtime expressions

  If the expression consumes streamed content, for example, the content of a request or response, PingGateway blocks the executing thread until all the content is available.

  Runtime expressions whose evaluation is immediate are written with the `${}` syntax.

* Deferred evaluation of runtime expressions

  PingGateway waits until all streamed content is available before it evaluates the expression. Deferred evaluation doesn't block executing threads.

  Runtime expressions whose evaluation is deferred are written with the `#{}` syntax.

  When the `streamingEnabled` property in `admin.json` is `true`, expressions that consume streamed content **must** be written with `#` instead of `$`.

Runtime expressions can refer to the following information:

* System heap properties

* Built-in functions listed in [PingGateway functions](Functions.html)

* Environment variables

* System properties

* [ExpressionInstant](../_attachments/apidocs/org/forgerock/openig/el/ExpressionInstant.html)

* `attributes`: [org.forgerock.services.context.AttributesContext](../_attachments/apidocs/org/forgerock/services/context/AttributesContext.html) Map\<String, Object>, obtained from `AttributesContext.getAttributes()`. Learn more in [AttributesContext](AttributesContext.html).

* `context`: [org.forgerock.services.context.Context](../_attachments/apidocs/org/forgerock/services/context/Context.html) object.

* `contexts`: map\<string, context> object. Learn more in [PingGateway context reference](Contexts.html).

* `request`: [org.forgerock.http.protocol.Request](../_attachments/apidocs/org/forgerock/http/protocol/Request.html) object. Learn more in [Request](Request.html).

* `response`: [org.forgerock.http.protocol.Response](../_attachments/apidocs/org/forgerock/http/protocol/Response.html) object, available only when the expression is intended to be evaluated on the response flow. Learn more in [Response](Response.html).

* `session`: [org.forgerock.http.session.Session](../_attachments/apidocs/org/forgerock/http/session/Session.html) object, available only when the expression is intended to be evaluated for both request and response flow. Learn more in [SessionContext](SessionContext.html).

## Embedded expressions

Consider the following points when embedding expressions:

* System properties, environment variables, or function expressions can be embedded within expressions.

  The following example embeds an environment variable in the argument for a `read()` function. The value of `entity` is set to the contents of the file `$HOME/.openig/html/defaultResponse.html`, where `$HOME/.openig` is the instance directory:

  ```json
  "entity": "${read('&{ig.instance.dir}/html/defaultResponse.html')}"
  ```

* Expressions can't be embedded inside other expressions, as `${expression}`.

* Embedded elements can't be enclosed in `${}`.

## Extensions

PingGateway offers a plugin interface for extending expressions. See [Key extension points](../configure/extending.html#extension-points).

## L-value expressions

L-value expressions assign a value to the expression scope. For example, `"${session.gotoURL}"` assignes a value to the session attribute named `gotoURL`.

PingGateway ignores attempts to write to read-only values.

L-value expressions must be specified using immediate evaluation syntax; use `$` instead of `#`.

## Operators

The following operators are provided by Unified Expression Language:

* Index property value: `[]`, `.`

* Change precedence: `()`

* Arithmetic: `+` (binary), `-` (binary), `*`, `/`, `div`, `%`, `mod`, `-` (unary)

* Logical: `and`, `&&`, `or`, `||`, `not`, `!`

* Relational: `==`, `eq`, `!=`, `ne`, `<`, `lt`, `>`, `gt`, `⇐`, `le`, `>=`, `ge`

* Empty: `empty`\
  Use this prefix operator to determine whether a value is null or empty.

* Conditional: `?`, `:`

Operators have the following precedence, from highest to lowest, and from left to right:

* `[]` `.`

* `()`

* `-` (unary) `not` `!` `empty`

* `*` `/` `div` `%` `mod`

* `+` (binary) `-` (binary)

* `<` `>` `⇐` `>=` `lt` `gt` `le` `ge`

* `==` `!=` `eq` `ne`

* `&&` `and`

* `||` `or`

* `?` `:`

## Dynamic bindings

Configuration and runtime expressions can use [ExpressionInstant](../_attachments/apidocs/org/forgerock/openig/el/ExpressionInstant.html).

The current instant is `${now.epochSeconds}`.

To add or subtract a period of time to the instant, add one or more of the following time periods to the binding:

* `plusMillis(integer)`, `minusMillis(integer)`

* `plusSeconds(integer)`, `minusSeconds(integer)`

* `plusMinutes(integer)`, `minusMinutes(integer)`

* `plusHours(integer)`, `minusHours(integer)`

* `plusDays(integer)`, `minusDays(integer)`

The following example binding refers to 30 minutes after the current instant:

```none
${now.plusMinutes(30).epochSeconds}
```

The following example binding accesses the instant in RFC 1123 date format one day after the current instant:

```none
${now.plusDays(1).rfc1123}
```

For more examples, refer to the `template` property of [JwtBuilderFilter](JwtBuilderFilter.html) and the `attribute-name` property of [SetCookieUpdateFilter](SetCookieUpdateFilter.html).

## Examples

### Immediate evaluation of configuration expressions

The following example yields the value of a secret from a system property.

```json
{
  "passwordSecretId": "${system['keypass']}"
}
```

The following example yields a file from the home directory of the user running the PingGateway application server.

```json
{
  "url": "file://${env['HOME']}/keystore.p12"
}
```

The following example of a `temporaryStorage` object takes the value of the system property `storage.ref`, which must a be string equivalent to the name of an object defined in the heap:

```json
{
  "temporaryStorage": "${system['storage.ref']}"
}
```

### Deferred evaluation of runtime expressions

The following example is a Route condition, where the Route is accessed if the request contains json with the attribute `answer`, whose value is `42`.

PingGateway defers evaluation of the expression until it receives the entire body of the reqest, transfoms it to JSON view, and then introspects it for the attribute `answer`.

```json
{
  "condition": "#{request.entity.json['answer'] == 42}",
  "handler": ...
}
```

The following example expression is for a JwtBuilderFilter that uses the content of the request mapped as a string. PingGateway defers evaluation of the expression until it receives the entire body of the request:

```json
{
  "template": {
    "content": "#{request.entity.string}"
  }
}
```

### Immediate and deferred evaluation of runtime expressions

The following example expressions are for an AssignmentFilter that consumes an ID captured from a response.

PingGateway evaluates the first expression immediately to define the target.

It then defers evaluation of the second expression until it receives the entire body of the response.

```json
"onResponse": [
  {
    "target": "${response.headers['X-IG-FooBar']}",
    "value": "#{toString(response.entity.json['userId'])}"
  }
]
```

### Expressions that use functions

In the following example, `"timer"` is defined by an expression that recovers the environment variable `"ENABLE_TIMER"` and transforms it into a boolean. Similarly, `"numberOfRequests"` is defined by an expression that recovers the system property `"requestsPerSecond"` and transforms it into an integer:

```json
{
  "name": "throttle-simple-expressions1",
  "timer": "${bool(env['ENABLE_TIMER'])}",
  "baseURI": "https://app.example.com:8444",
  "condition": "${find(request.uri.path, '^/home/throttle-simple-expressions1')}",
  "handler": {
    "type": "Chain",
    "config": {
      "filters": [
        {
          "type": "ThrottlingFilter",
          "name": "ThrottlingFilter-1",
          "config": {
            "requestGroupingPolicy": "",
            "rate": {
              "numberOfRequests": "${integer(system['requestsPerSecond'])}",
              "duration": "10 s"
            }
          }
        }
      ],
      "handler": "ReverseProxyHandler"
    }
  }
}
```

Source: [00-throttle-simple-expressions1.json](../_attachments/config/routes/00-throttle-simple-expressions1.json)

If `"requestsPerSecond"=6` and `"ENABLE_TIMER"=true`, after the expressions are evaluated PingGateway views the example route as follows:

```json
{
  "name": "throttle-simple-expressions2",
  "timer": true,
  "baseURI": "https://app.example.com:8444",
  "condition": "${find(request.uri.path, '^/home/throttle-simple-expressions2')}",
  "handler": {
    "type": "Chain",
    "config": {
      "filters": [
        {
          "type": "ThrottlingFilter",
          "name": "ThrottlingFilter-1",
          "config": {
            "requestGroupingPolicy": "",
            "rate": {
              "numberOfRequests": 6,
              "duration": "10 s"
            }
          }
        }
      ],
      "handler": "ReverseProxyHandler"
    }
  }
}
```

Source: [00-throttle-simple-expressions2.json](../_attachments/config/routes/00-throttle-simple-expressions2.json)
