blob: 0f2d096992175386f6f6cba92c55cc55d1b32699 [file] [log] [blame]
<!doctype html>
<!-- Generated by FreeMarker/Docgen from DocBook -->
<html lang="en" class="page-type-section">
<head prefix="og: http://ogp.me/ns#">
<meta charset="utf-8">
<title>Using FreeMarker with servlets - Apache FreeMarker Manual</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="format-detection" content="telephone=no">
<meta property="og:site_name" content="Apache FreeMarker Manual">
<meta property="og:title" content="Using FreeMarker with servlets">
<meta property="og:locale" content="en_US">
<meta property="og:url" content="https://freemarker.apache.org/docs/pgui_misc_servlet.html">
<link rel="canonical" href="https://freemarker.apache.org/docs/pgui_misc_servlet.html">
<link rel="icon" href="favicon.png" type="image/png">
<link rel="stylesheet" type="text/css" href="https://fonts.googleapis.com/css?family=Roboto:500,700,400,300|Droid+Sans+Mono">
<link rel="stylesheet" type="text/css" href="docgen-resources/docgen.min.css?1707770044859">
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/cookie-bar/cookiebar-latest.min.js"></script>
</head>
<body itemscope itemtype="https://schema.org/Code">
<meta itemprop="url" content="https://freemarker.apache.org/docs/">
<meta itemprop="name" content="Apache FreeMarker Manual">
<!--[if lte IE 9]>
<div class="oldBrowserWarning" style="display: block">
Unsupported web browser - Use a modern browser to view this website!
</div>
<![endif]--> <div class="oldBrowserWarning">
Unsupported web browser - Use a modern browser to view this website!
</div>
<div class="header-top-bg"><div class="site-width header-top"><div id="hamburger-menu" role="button"></div> <div class="logo">
<a href="https://freemarker.apache.org" role="banner"><img itemprop="image" src="logo.png" alt="FreeMarker"></a> </div>
<ul class="tabs"><li><a href="https://freemarker.apache.org/">Home</a></li><li class="current"><a href="index.html">Manual</a></li><li><a class="external" href="api/index.html">Java API</a></li></ul><ul class="secondary-tabs"><li><a class="tab icon-heart" href="https://freemarker.apache.org/contribute.html" title="Contribute"><span>Contribute</span></a></li><li><a class="tab icon-bug" href="https://issues.apache.org/jira/projects/FREEMARKER" title="Report a Bug"><span>Report a Bug</span></a></li><li><a class="tab icon-download" href="https://freemarker.apache.org/freemarkerdownload.html" title="Download"><span>Download</span></a></li></ul></div></div><div class="header-bottom-bg"><div class="site-width search-row"><a href="index.html" class="navigation-header">Manual</a><div class="navigation-header"></div><form method="get" class="search-form" action="search-results.html"><fieldset><legend class="sr-only">Search form</legend><label for="search-field" class="sr-only">Search query</label><input id="search-field" name="q" type="search" class="search-input" placeholder="Search" spellcheck="false" autocorrect="off" autocomplete="off"><button type="submit" class="search-btn"><span class="sr-only">Search</span></button></fieldset></form></div><div class="site-width breadcrumb-row"> <div class="breadcrumbs">
<ul class="breadcrumb" itemscope itemtype="http://schema.org/BreadcrumbList"><li class="step-0" itemprop="itemListElement" itemscope itemtype="http://schema.org/ListItem"><a class="label" itemprop="item" href="index.html"><span itemprop="name">Apache FreeMarker Manual</span></a></li><li class="step-1" itemprop="itemListElement" itemscope itemtype="http://schema.org/ListItem"><a class="label" itemprop="item" href="pgui.html"><span itemprop="name">Programmer&#39;s Guide</span></a></li><li class="step-2" itemprop="itemListElement" itemscope itemtype="http://schema.org/ListItem"><a class="label" itemprop="item" href="pgui_misc.html"><span itemprop="name">Miscellaneous</span></a></li><li class="step-3" itemprop="itemListElement" itemscope itemtype="http://schema.org/ListItem"><a class="label" itemprop="item" href="pgui_misc_servlet.html"><span itemprop="name">Using FreeMarker with servlets</span></a></li></ul> </div>
<div class="bookmarks" title="Bookmarks"><span class="sr-only">Bookmarks:</span><ul><li><a href="alphaidx.html">Alpha. index</a></li><li><a href="gloss.html">Glossary</a></li><li><a href="dgui_template_exp.html#exp_cheatsheet">Expressions</a></li><li><a href="ref_builtins_alphaidx.html">?builtins</a></li><li><a href="ref_directive_alphaidx.html">#directives</a></li><li><a href="ref_specvar.html">.spec_vars</a></li><li><a href="app_faq.html">FAQ</a></li></ul></div></div></div> <div class="main-content site-width">
<div class="content-wrapper">
<div id="table-of-contents-wrapper" class="col-left">
<script>var breadcrumb = ["Apache FreeMarker Manual","Programmer\'s Guide","Miscellaneous","Using FreeMarker with servlets"];</script>
<script src="toc.js?1707770044859"></script>
<script src="docgen-resources/main.min.js?1707770044859"></script>
</div>
<div class="col-right"><div class="page-content"><div class="page-title"><div class="pagers top"><a class="paging-arrow previous" href="pgui_misc_logging.html"><span>Previous</span></a><a class="paging-arrow next" href="pgui_misc_secureenv.html"><span>Next</span></a></div><div class="title-wrapper">
<h1 class="content-header header-section1" id="pgui_misc_servlet" itemprop="headline">Using FreeMarker with servlets</h1>
</div></div><div class="page-menu">
<div class="page-menu-title">Page Contents</div>
<ul><li><a class="page-menu-link" href="#pgui_misc_servlet_model2" data-menu-target="pgui_misc_servlet_model2">Using FreeMarker for "Model 2"</a></li><li><a class="page-menu-link" href="#pgui_misc_servlet_include" data-menu-target="pgui_misc_servlet_include">Including content from other web application
resources</a></li><li><a class="page-menu-link" href="#autoid_63" data-menu-target="autoid_63">Using JSP custom tags in FTL</a></li><li><a class="page-menu-link" href="#autoid_64" data-menu-target="autoid_64">Embed FTL into JSP pages</a></li></ul> </div><a name="topic.servlet"></a><p>In a fundamental sense, using FreeMarker in the web application
space is no different from anywhere else; FreeMarker writes its output
to a <code class="inline-code">Writer</code> that you pass to the
<code class="inline-code">Template.process</code> method, and it does not care if
that <code class="inline-code">Writer</code> prints to the console or to a file or
to the output stream of <code class="inline-code">HttpServletResponse</code>.
FreeMarker knows nothing about servlets and Web; it just merges Java
object with template files and generates text output from them. From
here, it is up to you how to build a Web application around
this.</p><p>But, probably you want to use FreeMarker with some already
existing Web application framework. Many frameworks rely on the
"Model 2" architecture, where JSP pages handle
presentation. If you use such a framework (for example, <a href="http://jakarta.apache.org/struts">Apache Struts</a>),
then read on. For other frameworks please refer to the documentation
of the framework.</p>
<h2 class="content-header header-section2" id="pgui_misc_servlet_model2">Using FreeMarker for "Model 2"</h2>
<p>Many frameworks follow the strategy that the HTTP request is
dispatched to user-defined "action" classes that put
data into <code class="inline-code">ServletContext</code>,
<code class="inline-code">HttpSession</code> and
<code class="inline-code">HttpServletRequest</code> objects as attributes, and
then the request is forwarded by the framework to a JSP page (the
view) that will generate the HTML page using the data sent with the
attributes. This is often referred as Model 2.</p>
<p class="center-img"> <img src="figures/model2sketch.png" alt="Figure"> </p>
<p>With these frameworks you can simply use FTL files instead of
JSP files. But, since your servlet container (Web application
server), unlike with JSP files, does not know out-of-the-box what to
do with FTL files, a little extra configuring is needed for your Web
application:</p>
<div class="orderedlist"><ol type="1">
<li>
<p>Copy <code class="inline-code">freemarker.jar</code> (from the
<code class="inline-code">lib</code> directory of the FreeMarker distribution)
into the <code class="inline-code">WEB-INF/lib</code> directory of your Web
application.</p>
</li>
<li>
<p>Insert the following section to the
<code class="inline-code">WEB-INF/web.xml</code> file of your Web application
(and adjust it if required):</p>
</li>
</ol></div>
<div class="code-block role-unspecified">
<pre class="code-block-body">&lt;servlet&gt;
&lt;servlet-name&gt;freemarker&lt;/servlet-name&gt;
&lt;servlet-class&gt;<strong>freemarker.ext.servlet.FreemarkerServlet</strong>&lt;/servlet-class&gt;
&lt;!--
Init-param documentation:
<a href="https://freemarker.apache.org/docs/api/freemarker/ext/servlet/FreemarkerServlet.html">https://freemarker.apache.org/docs/api/freemarker/ext/servlet/FreemarkerServlet.html</a>
--&gt;
&lt;!-- FreemarkerServlet settings: --&gt;
&lt;init-param&gt;
&lt;param-name&gt;TemplatePath&lt;/param-name&gt;
&lt;param-value&gt;/&lt;/param-value&gt;
&lt;/init-param&gt;
&lt;init-param&gt;
&lt;param-name&gt;NoCache&lt;/param-name&gt;
&lt;param-value&gt;true&lt;/param-value&gt;
&lt;/init-param&gt;
&lt;init-param&gt;
&lt;param-name&gt;ResponseCharacterEncoding&lt;/param-name&gt;
&lt;!-- Use the output_encoding setting of FreeMarker: --&gt;
&lt;param-value&gt;fromTemplate&lt;/param-value&gt;
&lt;/init-param&gt;
&lt;init-param&gt;
&lt;param-name&gt;ExceptionOnMissingTemplate&lt;/param-name&gt;
&lt;!-- true =&gt; HTTP 500 on missing template, instead of HTTP 404. --&gt;
&lt;param-value&gt;true&lt;/param-value&gt;
&lt;/init-param&gt;
&lt;!-- FreeMarker engine settings: --&gt;
&lt;init-param&gt;
&lt;param-name&gt;incompatible_improvements&lt;/param-name&gt;
&lt;param-value&gt;2.3.27&lt;/param-value&gt;
&lt;!--
Recommended to set to a high value.
See: https://freemarker.apache.org/docs/pgui_config_incompatible_improvements.html
--&gt;
&lt;/init-param&gt;
&lt;init-param&gt;
&lt;param-name&gt;template_exception_handler&lt;/param-name&gt;
&lt;!-- Use &quot;html_debug&quot; during development! --&gt;
&lt;param-value&gt;rethrow&lt;/param-value&gt;
&lt;/init-param&gt;
&lt;init-param&gt;
&lt;param-name&gt;template_update_delay&lt;/param-name&gt;
&lt;!-- Use 0 during development! Consider what value you need otherwise. --&gt;
&lt;param-value&gt;30 s&lt;/param-value&gt;
&lt;/init-param&gt;
&lt;init-param&gt;
&lt;param-name&gt;default_encoding&lt;/param-name&gt;
&lt;!-- The encoding of the template files: --&gt;
&lt;param-value&gt;UTF-8&lt;/param-value&gt;
&lt;/init-param&gt;
&lt;init-param&gt;
&lt;param-name&gt;output_encoding&lt;/param-name&gt;
&lt;!-- The encoding of the template output; Note that you must set
&quot;ResponseCharacterEncodring&quot; to &quot;fromTemplate&quot; for this to work! --&gt;
&lt;param-value&gt;UTF-8&lt;/param-value&gt;
&lt;/init-param&gt;
&lt;init-param&gt;
&lt;param-name&gt;locale&lt;/param-name&gt;
&lt;!-- Influences number and date/time formatting, etc. --&gt;
&lt;param-value&gt;en_US&lt;/param-value&gt;
&lt;/init-param&gt;
&lt;init-param&gt;
&lt;param-name&gt;number_format&lt;/param-name&gt;
&lt;param-value&gt;0.##########&lt;/param-value&gt;
&lt;/init-param&gt;
&lt;load-on-startup&gt;1&lt;/load-on-startup&gt;
&lt;/servlet&gt;
&lt;servlet-mapping&gt;
&lt;servlet-name&gt;freemarker&lt;/servlet-name&gt;
&lt;url-pattern&gt;<strong>*.ftl</strong>&lt;/url-pattern&gt;
&lt;!-- HTML and XML auto-escaped if incompatible_improvements &gt;= 2.3.24: --&gt;
&lt;url-pattern&gt;<strong>*.ftlh</strong>&lt;/url-pattern&gt;
&lt;url-pattern&gt;<strong>*.ftl</strong>x&lt;/url-pattern&gt;
&lt;/servlet-mapping&gt;
<em>...</em>
&lt;!--
Prevent the visiting of MVC Views from outside the servlet container.
RequestDispatcher.forward/include should, and will still work.
Removing this may open security holes!
--&gt;
&lt;security-constraint&gt;
&lt;web-resource-collection&gt;
&lt;web-resource-name&gt;FreeMarker MVC Views&lt;/web-resource-name&gt;
&lt;url-pattern&gt;*.ftl&lt;/url-pattern&gt;
&lt;url-pattern&gt;*.ftlh&lt;/url-pattern&gt;
&lt;url-pattern&gt;*.ftlx&lt;/url-pattern&gt;
&lt;/web-resource-collection&gt;
&lt;auth-constraint&gt;
&lt;!-- Nobody is allowed to visit these directly. --&gt;
&lt;/auth-constraint&gt;
&lt;/security-constraint&gt;</pre> </div>
<p>After this, you can use FTL files (<code class="inline-code">*.ftl</code>)
in the same manner as JSP (<code class="inline-code">*.jsp</code>) files. (Of
course you can choose another extension besides
<code class="inline-code">ftl</code>; it is just the convention)</p>
<div class="callout note">
<strong class="callout-label">Note:</strong>
<p>How does it work? Let&#39;s examine how JSP-s work. Many servlet
container handles JSP-s with a servlet that is mapped to the
<code class="inline-code">*.jsp</code> request URL pattern. That servlet will
receive all requests where the request URL ends with
<code class="inline-code">.jsp</code>, find the JSP file based on the request
URL, and internally compiles it to a <code class="inline-code">Servlet</code>,
and then call the generated servlet to generate the page. The
<code class="inline-code">FreemarkerServlet</code> mapped here to the
<code class="inline-code">*.ftl</code> URL pattern does the same, except that
FTL files are not compiled to <code class="inline-code">Servlet</code>-s, but to
<code class="inline-code">Template</code> objects, and then the
<code class="inline-code">process</code> method of <code class="inline-code">Template</code>
will be called to generate the page.</p>
</div>
<p><a name="topic.servlet.scopeAttr"></a>For example, instead
of this JSP file (note that it heavily uses Struts tag-libs to save
designers from embedded Java monsters):</p>
<div class="code-block role-template">
<div class="code-block-label">Template</div><pre class="code-block-body">&lt;%@ taglib uri=&quot;/WEB-INF/struts-bean.tld&quot; prefix=&quot;bean&quot; %&gt;
&lt;%@ taglib uri=&quot;/WEB-INF/struts-logic.tld&quot; prefix=&quot;logic&quot; %&gt;
&lt;html&gt;
&lt;head&gt;&lt;title&gt;Acmee Products International&lt;/title&gt;
&lt;body&gt;
&lt;h1&gt;Hello &lt;bean:write name=&quot;user&quot;/&gt;!&lt;/h1&gt;
&lt;p&gt;These are our latest offers:
&lt;ul&gt;
&lt;logic:iterate name=&quot;latestProducts&quot; id=&quot;prod&quot;&gt;
&lt;li&gt;&lt;bean:write name=&quot;prod&quot; property=&quot;name&quot;/&gt;
for &lt;bean:write name=&quot;prod&quot; property=&quot;price&quot;/&gt; Credits.
&lt;/logic:iterate&gt;
&lt;/ul&gt;
&lt;/body&gt;
&lt;/html&gt;</pre> </div>
<p>you can use this FTL file (use <code class="inline-code">ftl</code> file
extension instead of <code class="inline-code">jsp</code>):</p>
<div class="code-block role-template">
<div class="code-block-label">Template</div><pre class="code-block-body">&lt;html&gt;
&lt;head&gt;&lt;title&gt;Acmee Products International&lt;/title&gt;
&lt;body&gt;
&lt;h1&gt;Hello ${user}!&lt;/h1&gt;
&lt;p&gt;These are our latest offers:
&lt;ul&gt;
&lt;#list latestProducts as prod&gt;
&lt;li&gt;${prod.name} for ${prod.price} Credits.
&lt;/#list&gt;
&lt;/ul&gt;
&lt;/body&gt;
&lt;/html&gt;</pre> </div>
<div class="callout warning">
<strong class="callout-label">Warning!</strong>
<p>In FreeMarker <code class="inline-code">&lt;html:form
action=&quot;/query&quot;&gt;<em class="code-color">...</em>&lt;/html:form&gt;</code>
is just static text, so it is printed to the output as is, like
any other XML or HTML markup. JSP tags are just FreeMarker
directives, nothing special, so you <em>use FreeMarker
syntax</em> for calling them, not JSP syntax:
<code class="inline-code">&lt;@html.form
action=&quot;/query&quot;&gt;<em class="code-color">...</em>&lt;/@html.form&gt;</code>.
Note that in the FreeMarker syntax you <em>don&#39;t use
<code class="inline-code">${<em class="code-color">...</em>}</code> in
parameters</em> as in JSP, and you <em>don&#39;t quote the
parameter values</em>. So this is
<em>WRONG</em>:</p>
<div class="code-block role-template">
<div class="code-block-label">Template</div><pre class="code-block-body">&lt;#-- WRONG: --&gt;
&lt;@my.jspTag color=&quot;${aVariable}&quot; name=&quot;aStringLiteral&quot;
width=&quot;100&quot; height=${a+b} /&gt;</pre> </div>
<p>and this is good:</p>
<div class="code-block role-template">
<div class="code-block-label">Template</div><pre class="code-block-body">&lt;#-- Good: --&gt;
&lt;@my.jspTag color=aVariable name=&quot;aStringLiteral&quot;
width=100 height=a+b /&gt;</pre> </div>
</div>
<p>In both templates, when you refer to <code class="inline-code">user</code>
and <code class="inline-code">latestProduct</code>, it will first try to find a
variable with that name that was created in the template (like
<code class="inline-code">prod</code>; if you master JSP: a page scope attribute).
If that fails, it will try to look up an attribute with that name in
the <code class="inline-code">HttpServletRequest</code>, and if it is not there
then in the <code class="inline-code">HttpSession</code>, and if it still doesn&#39;t
find it then in the <code class="inline-code">ServletContext</code>. In the case
of FTL this works because <code class="inline-code">FreemarkerServlet</code>
builds the data-model from the attributes of the mentioned 3
objects. That is, in this case the root hash is not a
<code class="inline-code">java.util.Map</code> (as it was in some example codes in
this manual), but
<code class="inline-code">ServletContext</code>+<code class="inline-code">HttpSession</code>+<code class="inline-code">HttpServletRequest</code>;
FreeMarker is pretty flexible about what the data-model is. So if
you want to put variable <code class="inline-code">&quot;name&quot;</code> into the
data-model, then you call
<code class="inline-code">servletRequest.setAttribute(&quot;name&quot;, &quot;Fred&quot;)</code>; this
is the logic of Model 2, and FreeMarker adapts itself to it.</p>
<p><code class="inline-code">FreemarkerServlet</code> also puts 3 hashes into
the data-model, by which you can access the attributes of the 3
objects directly. The hash variables are:
<code class="inline-code">Request</code>, <code class="inline-code">Session</code>,
<code class="inline-code">Application</code> (corresponds to
<code class="inline-code">ServletContext</code>). It also exposes another hash
named <code class="inline-code">RequestParameters</code> that provides access to
the parameters of the HTTP request.</p>
<p><code class="inline-code">FreemarkerServlet</code> has various init-params.
It can be set up to load templates from an arbitrary directory, from
the classpath, or relative to the Web application directory. You can
set the charset used for templates, the default locale used by
templates, what object wrapper do you want to use, etc.</p>
<p><code class="inline-code">FreemarkerServlet</code> is easily tailored to
special needs through subclassing. Say, if you need to have
additional variables available in your data-model for all templates,
subclass the servlet and override the
<code class="inline-code">preTemplateProcess()</code> method to shove any
additional data you need into the model before the template gets
processed. Or subclass the servlet, and set these globally available
variables as <a href="pgui_config_sharedvariables.html">shared
variables</a> in the <code class="inline-code">Configuration</code>.</p>
<p>For more information please read the Java API documentation of
the class.</p>
<h2 class="content-header header-section2" id="pgui_misc_servlet_include">Including content from other web application
resources</h2>
<p>You can use the <code class="inline-code">&lt;@include_page
path=&quot;...&quot;/&gt;</code> custom directive provided by the
<code class="inline-code">FreemarkerServlet</code> (since 2.3.15) to include the
contents of another web application resource into the output; this
is often useful to integrate output of JSP pages (living alongside
the FreeMarker templates in the same web server) into the FreeMarker
template output. Using:</p>
<div class="code-block role-template">
<div class="code-block-label">Template</div><pre class="code-block-body">&lt;@include_page path=&quot;path/to/some.jsp&quot;/&gt;</pre> </div>
<p>is identical to using this tag in JSP:</p>
<div class="code-block role-template">
<div class="code-block-label">Template</div><pre class="code-block-body">&lt;jsp:include page=&quot;path/to/some.jsp&quot;&gt;</pre> </div>
<div class="callout note">
<strong class="callout-label">Note:</strong>
<p><code class="inline-code">&lt;@include_page ...&gt;</code> is not to be
confused with <code class="inline-code">&lt;#include ...&gt;</code>, as the last
is for including FreeMarker templates without involving the
Servlet container. An <code class="inline-code">&lt;#include ...&gt;</code>-ed
template shares the template processing state with the including
template, such as the data-model and the template-language
variables, while <code class="inline-code">&lt;@include_page ...&gt;</code>
starts an independent HTTP request processing.</p>
</div>
<div class="callout note">
<strong class="callout-label">Note:</strong>
<p>Some Web Application Frameworks provide their own solution
for this, in which case you possibly should use that instead. Also
some Web Application Frameworks don&#39;t use
<code class="inline-code">FreemarkerServlet</code>, so
<code class="inline-code">include_page</code> is not available.</p>
</div>
<p>The path can be relative or absolute. Relative paths are
interpreted relative to the URL of the current HTTP request (one
that triggered the template processing), while absolute paths are
absolute in the current servlet context (current web application).
You can not include pages from outside the current web application.
Note that you can include any page, not just a JSP page; we just
used page with path ending in <code class="inline-code">.jsp</code> as an
illustration.</p>
<p>In addition to the <code class="inline-code">path</code> parameter, you can
also specify an optional parameter named
<code class="inline-code">inherit_params</code> with a boolean value (defaults to
true when not specified) that specifies whether the included page
will see the HTTP request parameters of the current request or
not.</p>
<p>Finally, you can specify an optional parameter named
<code class="inline-code">params</code> that specifies new request parameters that
the included page will see. In case inherited parameters are passed
too, the values of specified parameters will get prepended to the
values of inherited parameters of the same name. The value of
<code class="inline-code">params</code> must be a hash, with each value in it
being either a string, or a sequence of strings (if you need
multivalued parameters). Here&#39;s a full example:</p>
<div class="code-block role-template">
<div class="code-block-label">Template</div><pre class="code-block-body">&lt;@include_page path=&quot;path/to/some.jsp&quot; inherit_params=true params={&quot;foo&quot;: &quot;99&quot;, &quot;bar&quot;: [&quot;a&quot;, &quot;b&quot;]}/&gt;</pre> </div>
<p>This will include the page
<code class="inline-code">path/to/some.jsp</code>, pass it all request parameters
of the current request, except for &quot;foo&quot; and &quot;bar&quot;, which will be
set to &quot;99&quot; and multi-value of &quot;a&quot;, &quot;b&quot;, respectively. In case the
original request already had values for these parameters, the new
values will be prepended to the existing values. I.e. if &quot;foo&quot; had
values &quot;111&quot; and &quot;123&quot;, then it will now have values &quot;99&quot;, &quot;111&quot;,
&quot;123&quot;.</p>
<p><span class="marked-for-programmers">It is in fact possible to pass
non-string values for parameter values within
<code class="inline-code">params</code>. Such a value will be converted to a
suitable Java object first (i.e. a Number, a Boolean, a Date, etc.),
and then its Java <code class="inline-code">toString()</code> method will be used
to obtain the string value. It is better to not rely on this
mechanism, though, and instead explicitly ensure that parameter
values that aren&#39;t strings are converted to strings on the template
level where you have control over formatting using the
<code class="inline-code">?string</code> and <code class="inline-code">?c</code> built-ins.
</span></p>
<h2 class="content-header header-section2" id="autoid_63">Using JSP custom tags in FTL</h2>
<p><code class="inline-code">FreemarkerServlet</code> puts the
<code class="inline-code">JspTaglibs</code> hash into the data-model, which you
can use to access JSP taglibs. The JSP custom tags will be
accessible as plain user-defined directives, and the custom EL
functions (since FreeMarker 2.3.22) as methods. For example, for
this JSP file:</p>
<div class="code-block role-template">
<div class="code-block-label">Template</div><pre class="code-block-body">&lt;%@ page contentType=&quot;text/html;charset=ISO-8859-2&quot; language=&quot;java&quot;%&gt;
&lt;%@ taglib prefix=&quot;e&quot; uri=&quot;/WEB-INF/example.tld&quot; %&gt;
&lt;%@ taglib prefix=&quot;oe&quot; uri=&quot;/WEB-INF/other-example.tld&quot; %&gt;
&lt;%@ taglib prefix=&quot;c&quot; uri=&quot;http://java.sun.com/jsp/jstl/core&quot; %&gt;
&lt;%@ taglib prefix=&quot;fn&quot; uri=&quot;http://java.sun.com/jsp/jstl/functions&quot; %&gt;
&lt;%-- Custom JSP tags and functions: --%&gt;
&lt;e:someTag numParam=&quot;123&quot; boolParam=&quot;true&quot; strParam=&quot;Example&quot; anotherParam=&quot;${someVar}&quot;&gt;
...
&lt;/e:someTag&gt;
&lt;oe:otherTag /&gt;
${e:someELFunction(1, 2)}
&lt;%-- JSTL: --%&gt;
&lt;c:if test=&quot;${foo}&quot;&gt;
Do this
&lt;/c:if&gt;
&lt;c:choose&gt;
&lt;c:when test=&quot;${x == 1}&quot;&gt;
Do this
&lt;/c:when&gt;
&lt;c:otherwise&gt;
Do that
&lt;/c:otherwise&gt;
&lt;/c:choose&gt;
&lt;c:forEach var=&quot;person&quot; items=&quot;${persons}&quot;&gt;
${person.name}
&lt;/c:forEach&gt;
${fn:trim(bar)}</pre> </div>
<p>the about equivalent FTL is:</p>
<div class="code-block role-template">
<div class="code-block-label">Template</div><pre class="code-block-body">&lt;#assign e=JspTaglibs[&quot;/WEB-INF/example.tld&quot;]&gt;
&lt;#assign oe=JspTaglibs[&quot;/WEB-INF/other-example.tld&quot;]&gt;
&lt;#-- Custom JSP tags and functions: --#&gt;
&lt;@e.someTag numParam=123 boolParam=true strParam=&quot;Example&quot; anotherParam=someVar&gt;
...
&lt;/@e.someTag&gt;
&lt;@oe.otherTag /&gt;
${e.someELFunction(1, 2)}
&lt;#-- JSTL - Instead, use native FTL constructs: --&gt;
&lt;#if foo&gt;
Do this
&lt;/#if&gt;
&lt;#if x == 1&gt;
Do this
&lt;#else&gt;
Do that
&lt;/#if&gt;
&lt;#list persons as person&gt;
${person.name}
&lt;/#list&gt;
${bar?trim}</pre> </div>
<div class="callout note">
<strong class="callout-label">Note:</strong>
<p>Parameter values don&#39;t use quotation and
<code class="inline-code">&quot;${<em class="code-color">...</em>}&quot;</code> like in
JSP. See more explanation later.</p>
</div>
<div class="callout note">
<strong class="callout-label">Note:</strong>
<p><code class="inline-code">JspTaglibs</code> is not a core FreeMarker
feature; it only exists when the template is called through the
<code class="inline-code">FreemarkerServlet</code>. That&#39;s because JSP
tags/functions assume a servlet environment (FreeMarker doesn&#39;t),
plus some Servlet concepts have to be emulated in the special
FreeMarker data-model that <code class="inline-code">FreemarkerServlet</code>
builds. Many modern frameworks use FreeMarker on a pure way, not
through <code class="inline-code">FreemarkerServlet</code>.</p>
</div>
<p>Since JSP custom tags are written to operate in JSP
environment, they assume that variables (often referred as
"beans" in JSP world) are stored in 4 scopes: page
scope, request scope, session scope and application scope. FTL has
no such notation (the 4 scopes), but
<code class="inline-code">FreemarkerServlet</code> provides emulated JSP
environment for the custom JSP tags, which maintains correspondence
between the "beans" of JSP scopes and FTL variables.
For the custom JSP tags, the request, session and application scopes
are exactly the same as with real JSP: the attributes of the
<code class="inline-code">javax.servlet.ServletContext</code>,
<code class="inline-code">HttpSession</code> and <code class="inline-code">ServletRequest</code>
objects. From the FTL side you see these 3 scopes together as the
data-model, as it was explained earlier. The page scope corresponds
to the FTL global variables (see the <a href="ref_directive_global.html#ref.directive.global"><code>global</code>
directive</a>). That is, if you create a variable with the
<code class="inline-code">global</code> directive, it will be visible for the
custom tags as page scope variable through the emulated JSP
environment. Also, if a JSP-tag creates a new page scope variable,
the result will be the same as if you create a variable with the
<code class="inline-code">global</code> directive. Note that the variables in the
data-model are not visible as page-scope attributes for the JSP
tags, despite that they are globally visible, since the data-model
corresponds to the request, session and application scopes, not the
page-scope.</p>
<p>On JSP pages you quote all attribute values, it does not mater
if the type of the parameter is string or boolean or number. But
since custom tags are accessible in FTL templates as user-defined
FTL directives, you have to use the FTL syntax rules inside the
custom tags, not the JSP rules. So when you specify the value of an
"attribute", then on the right side of the
<code class="inline-code">=</code> there is an <a href="dgui_template_exp.html">FTL expression</a>. Thus,
<em>you must not quote boolean and numerical parameter
values</em> (e.g. <code class="inline-code">&lt;@tiles.insert
page=&quot;/layout.ftl&quot; flush=true/&gt;</code>), or they are
interpreted as string values, and this will cause a type mismatch
error when FreeMarker tries to pass the value to the custom tag that
expects non-string value. Also note that, naturally, you can use any
FTL expression as attribute value, such as variables, calculated
values, etc. (e.g. <code class="inline-code">&lt;@tiles.insert page=layoutName
flush=foo &amp;&amp; bar/&gt;</code>).</p>
<p>FreeMarker does not rely on the JSP support of the servlet
container in which it is run when it uses JSP taglibs since it
implements its own lightweight JSP runtime environment. There is
only one small detail to pay attention to: to enable the FreeMarker
JSP runtime environment to dispatch events to JSP taglibs that
register event listeners in their TLD files, you should add this to
the <code class="inline-code">WEB-INF/web.xml</code> of your Web
application:</p>
<div class="code-block role-unspecified">
<pre class="code-block-body">&lt;listener&gt;
&lt;listener-class&gt;freemarker.ext.jsp.EventForwarding&lt;/listener-class&gt;
&lt;/listener&gt;</pre> </div>
<p>Note that you can use JSP taglibs with FreeMarker even if the
servlet container has no native JSP support, just make sure that the
<code class="inline-code">javax.servlet.jsp.*</code> packages for JSP 2.0 (or
later) are available to your Web application.</p>
<p>As of this writing, JSP features up to JSP 2.1 are
implemented, except the &quot;tag files&quot; feature of JSP 2 (i.e., custom
JSP tags <em>implemented</em> in JSP language). The tag
files had to be compiled to Java classes to be usable under
FreeMarker.</p>
<p><code class="inline-code">JspTaglibs[<em class="code-color">uri</em>]</code>
will have to find the TLD for the URI specified, just like JSP&#39;s
<code class="inline-code">@taglib</code> directive has to. For this, it implements
the TLD discovery mechanism described in the JSP specification. See
more there, but in a nutshell, it searches TLD-s in
<code class="inline-code">WEB-INF/web.xml</code> <code class="inline-code">taglib</code>
elements, at <code class="inline-code">WEB-INF/**/*.tld</code>, and in
<code class="inline-code">WEB-INF/lib/*.{jar,zip}/META-INF/**/*.tld</code>.
Additionally, it can discover TLD-s that are visible for the class
loader even if they are outside the WAR structure, when you set that
up with the <code class="inline-code">MetaInfTldSources</code> and/or
<code class="inline-code">ClasspathTlds</code>
<code class="inline-code">FreemarkerServlet</code> init-params (since 2.3.22). See
the Java API documentation of <code class="inline-code">FreemarkerServlet</code>
for the description of these. It&#39;s also possible to set these from
Java system properties, which can be handy when you want to change
these in the Eclipse run configuration without modifying the
<code class="inline-code">web.xml</code>; again, see the
<code class="inline-code">FreemarkerServlet</code> API docs.
<code class="inline-code">FreemarkerServlet</code> also recognizes the
<code class="inline-code">org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern</code>
servlet context attribute, and adds the entries from it to
<code class="inline-code">MetaInfTldSources</code>.</p>
<h2 class="content-header header-section2" id="autoid_64">Embed FTL into JSP pages</h2>
<p>There is a taglib that allows you to put FTL fragments into
JSP pages. The embedded FTL fragment can access the attributes
(Beans) of the 4 JSP scopes. You can find a working example and the
taglib in the FreeMarker distribution.</p>
<div class="bottom-pagers-wrapper"><div class="pagers bottom"><a class="paging-arrow previous" href="pgui_misc_logging.html"><span>Previous</span></a><a class="paging-arrow next" href="pgui_misc_secureenv.html"><span>Next</span></a></div></div></div></div> </div>
</div>
<div class="site-footer"><div class="site-width"><div class="footer-top"><div class="col-left sitemap"><div class="column"><h3 class="column-header">Overview</h3><ul><li><a href="https://freemarker.apache.org/">What is FreeMarker?</a></li><li><a href="https://freemarker.apache.org/freemarkerdownload.html">Download</a></li><li><a href="app_versions.html">Version history</a></li><li><a href="app_faq.html">FAQ</a></li><li><a itemprop="license" href="app_license.html">License</a></li><li><a href="https://privacy.apache.org/policies/privacy-policy-public.html">Privacy policy</a></li></ul></div><div class="column"><h3 class="column-header">Often used / Reference</h3><ul><li><a href="https://try.freemarker.apache.org/">Try template online</a></li><li><a href="dgui_template_exp.html#exp_cheatsheet">Expressions cheatsheet</a></li><li><a href="ref_directive_alphaidx.html">#directives</a></li><li><a href="ref_builtins_alphaidx.html">?built_ins</a></li><li><a href="ref_specvar.html">.special_vars</a></li><li><a href="api/freemarker/core/Configurable.html#setSetting-java.lang.String-java.lang.String-">Configuration settings</a></li></ul></div><div class="column"><h3 class="column-header">Community</h3><ul><li><a href="https://github.com/apache/freemarker">Github project page</a></li><li><a href="https://issues.apache.org/jira/projects/FREEMARKER">Report a bug</a></li><li><a href="https://freemarker.apache.org/report-security-vulnerabilities.html">Report security vulnerability</a></li><li><a href="https://stackoverflow.com/questions/ask?tags=freemarker">Get help on StackOverflow</a></li><li><a href="https://twitter.com/freemarker">Announcements on Twitter</a></li><li><a href="https://freemarker.apache.org/mailing-lists.html">Discuss on mailing lists</a></li></ul></div></div><div class="col-right"><ul class="social-icons"><li><a class="github" href="https://github.com/apache/freemarker">Github</a></li><li><a class="twitter" href="https://twitter.com/freemarker">Twitter</a></li><li><a class="stack-overflow" href="https://stackoverflow.com/questions/ask?tags=freemarker">Stack Overflow</a></li></ul><a class="xxe" href="http://www.xmlmind.com/xmleditor/" rel="nofollow" title="Edited with XMLMind XML Editor"><span>Edited with XMLMind XML Editor</span></a></div></div><div class="footer-bottom"> <p class="last-generated">
Last generated:
<time itemprop="dateModified" datetime="2024-02-12T20:34:04Z" title="Monday, February 12, 2024 at 8:34:04 PM Greenwich Mean Time">2024-02-12 20:34:04 GMT</time>, for Freemarker 2.3.32 </p>
<p class="copyright">
© <span itemprop="copyrightYear">1999</span>–2024
<a itemtype="http://schema.org/Organization" itemprop="copyrightHolder" href="https://apache.org/">The Apache Software Foundation</a>. Apache FreeMarker, FreeMarker, Apache Incubator, Apache, the Apache FreeMarker logo are trademarks of The Apache Software Foundation. All other marks mentioned may be trademarks or registered trademarks of their respective owners. </p>
</div></div></div></body>
</html>