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
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 totrue
. Its default isfalse
(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 itsincompatibleImprovements
set to 2.3.22 or higher (see how to set it here) (actually, what matters is that itsuseAdaptersForContainer
property is set totrue
, but that's the default with saidincompatibleImprovements
), FTL values made fromMap
-s andList
-s support?api
. Otherjava.util.Collections
also, ifDefaultObjectWrapper
'sforceLegacyNonListCollections
property is set tofalse
(default istrue
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 thefreemarker.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.
The evaluated expression sees the same variables (such as
locals) that are visible at the place of the invocation of
eval
. That is, it behaves similarly as if in
place of s?eval
you
had the value of
s
there. Except, it
can't use loop variable
built-ins that refer to a loop variable that was created
outside s
.
The configuration settings that affect the expression parsing
(like syntax) are coming from the Configuration
object, not from template that invokes
eval
.
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 sub variables, 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 parser a string as an FTL template, and returns
an user-defined directive that executes that template, just as if a
template with that content were include
-d
at that point. Example:
<#assign x=["a", "b", "c"]> <#assign templateSource = r"<#list x as y>${y}</#list>"> <#-- Note: That r was needed so that the ${y} is not interpreted above --> <#assign inlineTemplate = templateSource?interpret> <@inlineTemplate />
The output:
abc
As you can see, inlineTemplate
is a
user-defined directive that, when executed, runs the template whose
content is the value of templateSource
.
The configuration settings that affect the parsing (like tag
syntax and naming convention) are coming from the
Configuration
object, not from template that
calls interpret
. This also means that the
previously auto-detected tag syntax or auto-detected naming
convention don't effect the parsing of the interpreted template.
This is consistent with how the include
directive works.
The name of the template created by
interpret
is the name of the template that calls
interpret
, plus
"->anonymous_interpreted"
. For example, if the
template that calls the built-in is
"foo/bar.ftl"
, then the name of the resulting
template is
"foo/bar.ftl->anonymous_interpreted"
. Thus,
relative paths inside the interpreted template are relative to this
path (i.e., the base directory will be "foo"
),
and errors inside the interpreted template will point to this
generated template name.
For more helpful error messages, you can override the template
name part after the "->"
. For example, let's
say mailTemplateSource
comes from the
mail_template
database table, and in the case of
error, you want the error log to contain the database ID of the
failing template:
<#assign inlineTemplate = [mailTemplateSource, "mail_templates id=${mailTemplateId}"]?interpret>
As you can see, interpret
can be applied on
a sequence of two items, in which case the first item is the FTL
string to interpret, and the second items is the template name used
after the "->"
.
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:
<#-- Creates an user-defined directive be calling the parameterless constructor of the class --> <#assign word_wrapp = "com.acmee.freemarker.WordWrapperDirective"?new()> <#-- Creates an user-defined directive be calling the constructor with one numerical argument --> <#assign word_wrapp_narrow = "com.acmee.freemarker.WordWrapperDirective"?new(40)>
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:
${1305575275540?number_to_datetime} ${1305575275540?number_to_date} ${1305575275540?number_to_time}
The output will be something like this (depending on the current locale and time zone):
May 16, 2011 3:47:55 PM May 16, 2011 3:47:55 PM