Special Variable Reference - Apache FreeMarker Manual

Unsupported web browser - Use a modern browser to view this website!

- Home
- Manual
- Java API

- Contribute
- Report a Bug
- Download

Manual
Previous Next

# Special Variable Reference

Special variables are variables defined by the FreeMarker engine itself. To access them, you use the `.variable_name` syntax. For example, you can't write simply `version`; you have to write `.version`.

Note:

As of FreeMarker 2.3.23, you can use camel case instead of snake case for special variable names, like `dataModel` instead of `data_model`. But know that then within the same template, FreeMarker will enforce the usage of camel case for all identifiers that are part of the template language (user defined names are not affected).

The supported special variables are:

- `args` (since 2.3.30): Used inside the `macro` and `function` directives, it returns all arguments of the current invocation of the macro or function. This allows processing all the arguments in an uniform way (like pass them to the `with_args` built-in). Further details:
  - When used inside a macro, `.args` is always a hash that maps the parameter names to the parameter values. That's so even if the macro was called with positional arguments, as the parameter names are declared by the `macro` directive. But when used inside a function, `.args` is always a sequence of the argument values. That's because functions can only be called with positional arguments, so the parameter names declared inside the `function` directive aren't relevant.
  - For arguments that have a default value (as `b` in `<#macro m1 a b=0>`), if the caller of the macro or function has omitted that argument (as in `<@m1 a=1 />`), `.args` will contain the default value for that argument (`{'a': 1, 'b': 0}`).
  - If there's a catch-all argument, like `others` in `<#macro m2 a, b, others...>`, then `.args` will contain the elements in the the catch-all parameter directly, and won't contain the declared catch-all parameter (`others`) itself. So for `<@m2 a=1 b=2 c=3 d=4 />` it will be `{'a': 1, 'b': 2, 'c': 3, 'd': 4}`, and not `{'a': 1, 'b': 2, 'others': {'c':3, 'd': 4}}`.
  - If a macro has a catch-all parameter, and the actual catch-all argument is not empty, and the macro uses `.args` somewhere, it can only be called with named arguments (like `<@m a=1 b=2 />`), and not with positional arguments (like `<@m 1 2 />`). That's because for macros `.args` is always a hash, but if the arguments are positional, the catch-all arguments won't have names, so it's impossible to put them into the hash.
  - `.args` is initialized immediately when the macro or function is called, and so it doesn't reflect changes made later on the local variables that correspond to the arguments. (However, if the argument value is a mutable object, and the objects itself is mutated, `.args` will contain the mutated object. Setting an argument variable with the `local` directive doesn't mutate the object.)
  - `.args` must occur inside a `macro` or `function` directive on the source code level, or else it's a template parsing error. So you can't use it in a template fragment that you insert dynamically into a macro or function (like via the `include` directive, `eval` built-in, or `interpret` built-in). That's because the `macro` or `function` has to know if it contains `.args` earlier than it's called.
  - For macros, the order of elements in the `.args` hash is the same as the order in which the parameters were declared in the `macro` directive, and not the order the caller has used. Except, catch-all arguments will use the order that the caller used. (For functions and methods, as it only support positional arguments, the parameter order of on the caller side is the same as the parameter order in the `function` directive or Java method, so there's no doubt there.)
- `auto_esc` (since 2.3.24): Boolean value that tells if auto-escaping (based on output format) is on or off at the place where this variable is referred (resolved statically). This is not affected by the deprecated `escape` directive. This only deals with automatic escaping based on the output format mechanism.
- `caller_template_name` (available since FreeMarker 2.3.28): Returns the name (path) of the template from which the current macro or function was called. It's mostly useful if you want to resolve paths relative to the caller template (see an example here). To serve that purpose better, if the caller template is nameless, this will be an empty string (not a missing value). Reading this variable will cause error if you aren't inside a macro or function call. In particular, directives and "methods" implemented in Java will not influence the value of this variable; it's only for macros and functions implemented in templates. (`TemplateDirectiveModel` implementations can get similar information via the `freemarker.core.DirectiveCallPlace` object.)
- `current_template_name`: The name of the template where we are now (available since FreeMarker 2.3.23). This can be missing (`null`) if the template was created on-the-fly in Java (via `new Template(null, ...)`), rather than loaded from a backing store by name (via `cfg.getTemplate(name, ...)`). Migration notice: If you replace the deprecated `template_name` with this, note that the later is a 0-length string instead of missing (`null`) if the template has no name, so you might want to write `current_template_name!''` in legacy templates.
- `data_model`: A hash that you can use to access the data-model directly. That is, variables you did with `global` directive are not visible here.
- `error` (available since FreeMarker 2.3.1): This variable accessible in the body of the `recover` directive, where it stores the error message of the error we recover from.
- `globals`: A hash that you can use to access the globally accessible variables: the data-model and the variables created with `global` directive. Note that variables created with `assign` or `macro` are not globals, thus they never hide the variables when you use `globals`.
- `incompatible_improvements` (since FreeMarker 2.3.24): The `incompatible_improvements` setting of the current FreeMarker configuration, as a string.
- `lang`: Returns the language part of the current value of the locale setting. For example if `.locale` is `en_US`, then `.lang` is `en`.
- `locale`: Returns the current value of the locale setting. This is a string, for example `en_US`. For more information about locale strings see the `setting` directive.
- `locale_object` (available since FreeMarker 2.3.21): Returns the current value of the locale setting as a `java.util.Locale` object, rather than as a string. This meant to be used instead of `.locale` when you want to pass it as a `java.util.Locale` object to a Java method. (The `Locale` object will be wrapped according the `object_wrapper` setting value. Whether you can actually pass this value to a Java method as a `Locale` object depends on the object wrapper, but an object wrapper that let you call Java methods directly is very unlikely to not support that.)
- `locals`: A hash that you can use to access the local variables (the variables created with the `local` directive, and the parameters of macro).
- `main`: A hash that you can use to access the main namespace. Note that global variables like the variables of data-model are not visible through this hash.
- `main_template_name`: The name of the top level template (available since FreeMarker 2.3.23). (In Java, this is the template for which `Template.process` was called.) This can be missing (`null`) if the template was created on-the-fly in Java (via `new Template(null, ...)`), rather than loaded from a backing store by name (via `cfg.getTemplate(name, ...)`). Migration notice: If you replace the deprecated `template_name` with this, note that the later is a 0-length string instead of missing (`null`) if the template has no name, so you might want to write `main_template_name!''` in legacy templates.
- `namespace`: A hash that you can use to access the current namespace. Note that global variables like the variables of data-model are not visible through this hash.
- `node` (alias `current_node` for historical reasons): The node you are currently processing with the visitor pattern (i.e. with the `visit`, `recurse`, ...etc. directives). Also, it initially stores the root node when you use the FreeMarker XML Ant task.
- `now`: Returns the current date-time. Usage examples: "`Page generated: ${.now}`", "`Today is ${.now?date}`", "`The current time is ${.now?time}`".
- Returns the name of the current output format. This value is never missing/null. It's maybe the string `"undefined"`, which is just the name of the default output format.
- `output_encoding` (available since FreeMarker 2.3.1): Returns the name of the current output charset. This special variable is not existent if the framework that encapsulates FreeMarker doesn't specify the output charset for FreeMarker. (Programmers can read more about charset issues here...)
- `get_optional_template`: This is a method that's used when you need to include or import a template that's possibly missing, and you need to handle that case on some special way. More details...
- `pass`: This is a macro that does nothing. It has no parameters. Mostly used as no-op node handler in XML processing.
- `template_name`: Don't use it, because its behavior is strange when macros are used; use `current_template_name` or `main_template_name` instead (see migration notices there). Gives the name of the main template, or if we are running an included or imported template, the name of that template. When calling macros, it becomes rather confusing: the macro call won't change the value of this special variable, but when `nested` is called, it changes it to the name of the template that belongs to the current namespace. (Available since FreeMarker 2.3.14.)
- `url_escaping_charset` (available since FreeMarker 2.3.1): If exists, it stores the name of the charset that should be used for URL escaping. If this variable doesn't exist that means that nobody has specified what charset should be used for URL encoding yet. In this case the `url` built-in uses the charset specified by the `output_encoding` special variable for URL encoding; custom mechanism may follow the same logic. (Programmers can read more about charset issues here...)
- `output_format` (since 2.3.24): The name of output format at the place where this variable is referred (resolved statically), such as `"HTML"`, `"XML"`, `"RTF"`, `"plainText"`, `"undefined"`, etc. (The available names can be extended by the programmers, by the `registered_custom_output_formats` setting.)
- `vars`: Expression `.vars.foo` returns the same variable as expression `foo`. It's useful if for some reasons you have to use square bracket syntax, since that works only for hash sub variables, so you need an artificial parent hash. For example, to read a top-level variable that has a strange name that would confuse FreeMarker, you can write `.vars["A strange name!"]`. Or, to access a top-level variable with dynamic name given with variable `varName` you can write `.vars[varName]`. Note that the hash returned by `.vars` does not support `?keys` and `?values`.
- `version`: Returns the FreeMarker version number as string, for example `2.2.8`. This can be used to check which FreeMarker version does your application use, but note that this special variable does not exist prior to the 2.3.0 or 2.2.8 versions. The version number of non-final releases contains dash and further info after the numbers, like in 2.3.21-nightly_20140726T151800Z.
- `time_zone` (exists since FreeMarker 2.3.31): The current value of the `time_zone` setting, as a string. This is the ID of the time zone, like `GMT+01:00`, or `America/Los_Angeles`.

## Using get_optional_template

This special variable is used when you need to include or import a template that's possibly missing, and you need to handle that case on some special way. It a method (so you meant to call it) that has the following parameters:

1. The name of the template (can be relative or absolute), like `"/commonds/footer.ftl"`; similar to the first parameter of the `include` directive. Required, string.

2. An optional hash of options, like `{ 'parse': false, 'encoding': 'UTF-16BE' }`. The valid keys are `encoding` and `parse`. The meaning of these are the same as of the similarly named `include` directive parameters.

This method returns a hash that contains the following entries:

- `exists`: A boolean that tells if the template was found.

- `include`: A directive that, when called, includes the template. Calling this directive is similar to calling the `include` directive, but of course with this you spare looking up the template again. This directive has no parameters, nor nested content. If `exists` is `false`, this key will be missing; see later how can this be utilized with the `exp!default` operator.

- `import`: A method that, when called, imports the template, and returns the namespace of the imported template. Calling this method is similar to calling the `import` directive, but of course with this you spare looking up the template again, also, it doesn't assign the namespace to anything, just returns it. The method has no parameters. If `exists` is `false`, this key will be missing; see later how can this be utilized with the `exp!default` operator.

When this method is called (like `.get_optional_template('some.ftl')`), it immediately loads the template if it exists, but doesn't yet process it, so it doesn't have any visible effect yet. The template will be processed only when `include` or `import` members of the returned structure is called. (Of course, when we say that it loads the template, it actually looks it up in the template cache, just like the `include` directive does.)

While it's not an error if the template is missing, it's an error if it does exist but still can't be loaded due to syntactical errors in it, or due to some I/O error.

Note:

If the template fails with "I/O error when trying to load optional template" when the template is missing, that's often because your application uses a custom `freemarker.cache.TemplateLoader` implementation, which incorrectly (against the API documentation) throws an `IOException` in the `findTemplateSource` method instead of returning `null` if a template is not found. If it's so, the Java programmers need to fix that. Another possibility is of course that it was indeed not possible to tell if the template exists or not due to some technical issues, in which case stopping with error is the correct behavior. See the cause `IOException` in the Java stack trace to figure out which case it is.

Example, in which depending on if `some.ftl` exists, we either print "Template was found:" and the include the template as `<#include 'some.ftl'>` would, otherwise it we print "Template was missing.":

Template

    <#assign optTemp = .get_optional_template('some.ftl')>
    <#if optTemp.exists>
      Template was found:
      <@optTemp.include />
    <#else>
      Template was missing.
    </#if>

Example, in which we try to include `some.ftl`, but if that's missing then we try to include `some-fallback.ftl`, and if that's missing too then we call the `ultimateFallback` macro instead of including anything (note the `!`-s after the `include`-s; they belong to the `exp!default` operator):

Template

    <#macro ultimateFallback>
      Something
    </#macro>

    <@(
      .get_optional_template('some.ftl').include!
      .get_optional_template('some-fallback.ftl').include!
      ultimateFallback
    ) />

Example, which behaves like `<#import 'tags.ftl' as tags>`, except that if `tags.ftl` is missing, then it creates an empty `tags` hash:

Template

    <#assign tags = (.get_optional_template('tags.ftl').import())!{}>

Previous Next