Seldom used and expert built-ins
Page Contents
These are the built-ins that normally you should not use, but in exceptional situations (debugging, advanced macros) they can be useful. If you need to use these in your normal page templates, you may revisit the data-model so you don't need to use these.
api, has_api
Note
These built-ins exists since FreeMarker 2.3.22
value?api provides access to the API (usually, the Java API) of value, like value?api.someJavaMethod(), if the value itself supports this extra feature. This meant to be used rarely, when you need to call a Java method of an object, but the simplistic view of the value that FreeMarker exposes to the templates hides that, and there's no equivalent built-in either. For example, when you have Map that you put into the data-model (and you are using the default object wrapper), myMap.myMethod() in a template basically translates to ((Method) myMap.get("myMethod")).invoke(...) in Java, thus you can't call myMethod. If, however, you write myMap?api.myMethod() instead, that means myMap.myMethod() in Java.
You should avoid using api, and rely on the capabilities of the FTL types and the related built-ins as far as possible. For example, don't use users?api.size(), but users?size. The variation that uses ?api is more verbose, slower, more easily breaks when FreeMarker configuration settings are changed, and most importantly, more prone to break as the technical details of the data-model changes. For example, if users is changed from a List to an array, users?size will keep working, while users?api.size() will break.
Avoid calling methods that modify an object (especially Map-s and Collection-s) or that aren't thread safe from other reasons. Templates usually aren't expected to modify the objects exposed to them, just to display them. Thus the application may passes some objects to multiple (possibly concurrent) template processings.
The api built-in is not everywhere available, some requirements has to be met:
-
The api_builtin_enabled configuration setting must be set to true. Its default is false (at least as of 2.3.22) for not lowering the security of existing applications.
-
The value itself has to support it. We are talking about the value as the template sees it, which is created from the original object (that's coming from the data-model or from a Java method return value) value via object wrapping. Hence, this depends on the object_wrapper FreeMarker configuration setting, and on the class of the wrapped (the original) object:
-
When the object wrapper is a DefaultObjectWrapper with its incompatibleImprovements set to 2.3.22 or higher (see how to set it here) (actually, what matters its that its useAdaptersForContainer property is set to true, but that's the default with said incompatibleImprovements), FTL values made from Map-s and List-s support ?api. Other java.util.Collections also, if DefaultObjectWrapper's forceLegacyNonListCollections property is set to false (default is true for better out-of-the-box backward compatibility).
-
When wrapped with pure BeansWrapper, all values support ?api. But again, avoid using it if there's another solution.
-
Custom TemplateModel-s can support ?api by implementing the freemarker.template.TemplateModelWithAPISupport interface.
-
Using ?api when it's not allowed in the configuration or when the value doesn't support it will abort template processing with error.
Whether a value supports ?api can be checked like value?has_api, which returns a boolean value. Note that the result of ?has_api isn't influenced by the api_builtin_enabled setting.
byte, double, float, int, long, short
Returns a SimpleNumber which contains the same value as the original variable, but uses java.lang.Type for the internal representation of the value. This is useful if a method is overloaded, or if a TemplateModel unwrapper has problem with automatically choosing the suitable java.lang.* type. Note that since version 2.3.9 the unwrapper has been improved substantially, so you will hardly ever need to use these built-ins to convert between numerical types, except for resolving ambiguity in overloaded method invocation.
The long built-in can also be used with date, time and date-time values to get the value as java.util.Date.getTime() would return. This is useful if you have to call a Java methods that expect a timestamp as a long. This conversion is not automatic.
eval
This built-in evaluates a string as an FTL expression. For example "1+2"?eval returns number 3.
has_content
It is true if the variable exists (and isn't Java null) and is not ``empty'', otherwise it is false. The meaning of ``empty'' depends on the concrete case. This follows intuitive common-sense ideas. The following are empty: a string with 0 length, sequence or hash with no subvariables, a collection which has passed the last element. If the value is not a string or sequence or hash or collection, then it counts as non-empty if it's a number or a date or a boolean (e.g. 0 and false are not empty), otherwise it counts as empty. Note that when your data-model implements multiple template model interfaces you may get unexpected results. However, when in doubt you can use always use expr!?size > 0 or expr!?length > 0 instead of expr?has_content.
This buit-in is exceptional in that you can use the parentheses trick like with the default value operator. That is, you can write both product.color?has_content and (product.color)?has_content. The first doesn't handle the case when product is missing, the last does.
interpret
This built-in interprets a string as a FTL template, and returns an user-defined directive that - when applied to any block - executes the template just as if it was included at that point. Example:
| |||
The output:
| |||
As you can see, inlineTemplate is a user-defined directive that, when executed, runs the template that was generated on-the-fly using the interpret.
You can also apply this built-in to a two-element sequence. In this case the first element of the sequence is the template source, and the second element is a name for the inline template. It can be useful to give an explicit name to the inline template for debugging purposes. So, you could have written:
| |||
as well in the above template. Note that giving the inline template a name has no immediate effect - it is only useful as an extra bit of information if you get an error report.
is_...
These built-ins check the type of a variable, and returns true or false depending on the type. The list of is_... built-ins:
Built-in | Returns true if the value is a ... |
---|---|
is_string | string |
is_number | number |
is_boolean | boolean |
is_date | Don't use it! Same as is_date_like, use that instead. Later may changes meaning to date_only. |
is_date_like | date-like, means either date, time or date-time, or date-like with unknown precise type (since FreeMarker 2.3.21) |
is_date_only | date (no time of the day part) (since FreeMarker 2.3.21) |
is_time | time (no year-month-day part) (since FreeMarker 2.3.21) |
is_datetime | date-time (contains both year-month-day and time of the day) |
is_unknown_date_like | date-like where we don't know if it's a date or a time or a date-time |
is_method | method |
is_transform | transform |
is_macro | macro or function (yes, also for function; a historical glitch) |
is_hash | hash (including extended hash) |
is_hash_ex | extended hash (supports ?keys and ?values) |
is_sequence | sequence |
is_collection | collection (including extended collection) |
is_collection_ex | extended collection (supports ?size) |
is_enumerable | sequence or collection |
is_indexable | sequence |
is_directive | Whatever kind of directive (for example a macro, or TemplateDirectiveModel, TemplateTransformModel, etc.), or function (a historical glitch) |
is_node | node |
namespace
This built-in returns the namespace (i.e. the ``gate'' hash to the namespace) associated with a macro or function variable. You can use it with macros and functions only.
new
This is to create a variable of a certain TemplateModel implementation.
On the left side of ? you specify a string, the full-qualified class name of a TemplateModel implementation. The result is a method variable that calls the constructor, and returns the new variable.
Example:
| |||
For more information about how the constructor parameters are unwrapped and how overloaded constructor is chosen, read: Programmer's Guide/Miscellaneous/Bean wrapper
This built-in can be a security concern because the template author can create arbitrary Java objects and then use them, as far as they implement TemplateModel. Also the template author can trigger static initialization for classes that don't even implement TemplateModel. You can (since 2.3.17) restrict the classes accessible with this built-in using Configuration.setNewBuiltinClassResolver(TemplateClassResolver) or the new_builtin_class_resolver setting. See the Java API docs for more information. If you are allowing not-so-much-trusted users to upload templates then you should definitely look into this topic.
number_to_date, number_to_time, number_to_datetime
These are used to convert a number (usually a Java long) to a date, time or date-time, respectively. This does them same as new java.util.Date(long) in Java, that is, the number is interpreted as the milliseconds passed since the epoch. The number can be anything and of any type as far as its value fits into a long. If the number isn't a whole number, it will be rounded to whole with half-up rule. This conversion is not automatic.
Example:
| |||
The output will be something like this (depending on the current locale and time zone):
| |||