blob: 12c245a10b66a343d959e3f5cacfb2b6e5c7b9a0 [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>Namespaces - 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="Namespaces">
<meta property="og:locale" content="en_US">
<meta property="og:url" content="https://freemarker.apache.org/docs/dgui_misc_namespace.html">
<link rel="canonical" href="https://freemarker.apache.org/docs/dgui_misc_namespace.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="dgui.html"><span itemprop="name">Template Author&#39;s Guide</span></a></li><li class="step-2" itemprop="itemListElement" itemscope itemtype="http://schema.org/ListItem"><a class="label" itemprop="item" href="dgui_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="dgui_misc_namespace.html"><span itemprop="name">Namespaces</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","Template Author\'s Guide","Miscellaneous","Namespaces"];</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="dgui_misc_var.html"><span>Previous</span></a><a class="paging-arrow next" href="dgui_misc_autoescaping.html"><span>Next</span></a></div><div class="title-wrapper">
<h1 class="content-header header-section1" id="dgui_misc_namespace" itemprop="headline">Namespaces</h1>
</div></div><div class="page-menu">
<div class="page-menu-title">Page Contents</div>
<ul><li><a class="page-menu-link" href="#autoid_23" data-menu-target="autoid_23">Creating a library</a></li><li><a class="page-menu-link" href="#autoid_24" data-menu-target="autoid_24">Writing the variables of imported namespaces</a></li><li><a class="page-menu-link" href="#autoid_25" data-menu-target="autoid_25">Namespaces and data-model</a></li><li><a class="page-menu-link" href="#autoid_26" data-menu-target="autoid_26">The life-cycle of namespaces</a></li><li><a class="page-menu-link" href="#autoid_27" data-menu-target="autoid_27">Auto-importing</a></li></ul> </div><p>When you run templates, you have a (possibly empty) set of
variables that you have created with <code class="inline-code">assign</code> and
<code class="inline-code">macro</code> and <code class="inline-code">function</code> directives
(see in the <a href="dgui_misc_var.html">previous chapter</a>). A
set of template-made variables like that is called a <strong>namespace</strong>. In simple cases you use only one
namespace, the <strong>main namespace</strong>.
Whenever you define a variable in the main template (macros and
functions are also variables, mind you), or in templates <a href="ref_directive_include.html#ref.directive.include"><code>include</code>-d</a> in
it, that&#39;s where the variable are created. The key property of a
namespace is that the variable name uniquely identifies a value in it
(i.e, you can&#39;t have multiple variables in it with the same name in
the same namespace).</p><p>Sometimes you want to build reusable collection of macros,
functions, and other variables, which we call a <strong>library</strong>. It&#39;s important that a library can use
its own namespace, to avoid accidental name clashes. Consider, you may
have many names in that library, and you intend to use the library in
many templates, maybe even reuse it in several projects. It becomes
impractical to keep track of where the library used in another
template accidentally hides variables from the data-model, or what
names you shouldn&#39;t assign to in the template to avoid overwriting the
variables of the library. If you have multiple libraries used in the
same template, this becomes even harder to track. So you should use a
separate namespace for the variables of each library.</p>
<h2 class="content-header header-section2" id="autoid_23">Creating a library</h2>
<p>Here&#39;s a simple library, which contains a
<code class="inline-code">copyright</code> macro and a <code class="inline-code">mail</code>
string:</p>
<div class="code-block role-template">
<div class="code-block-label">Template</div><pre class="code-block-body">&lt;#macro copyright date&gt;
&lt;p&gt;Copyright (C) ${date} Someone. All rights reserved.&lt;/p&gt;
&lt;/#macro&gt;
&lt;#assign mail = &quot;user@example.com&quot;&gt;</pre> </div>
<p>Save this into the <code class="inline-code">lib/example.ftl</code> file
(inside the directory where you store the templates). Then create a
template, let&#39;s say, <code class="inline-code">some_web_page.ftl</code>, and use
the library in it:</p>
<div class="code-block role-template">
<div class="code-block-label">Template</div><pre class="code-block-body">&lt;#<strong>import</strong> &quot;/lib/example.ftl&quot; as <strong>e</strong>&gt;
Some Web page...
&lt;@<strong>e</strong>.copyright date=&quot;1999-2002&quot;/&gt;
${<strong>e</strong>.mail}</pre> </div>
<div class="code-block role-output">
<div class="code-block-label">Output</div><pre class="code-block-body">Some Web page...
&lt;p&gt;Copyright (C) 1999-2002 Someone. All rights reserved.&lt;/p&gt;
user@example.com</pre> </div>
<p>Note the <a href="ref_directive_import.html#ref.directive.import"><code>import</code>
directive</a> above, and the subsequent usage of the
"<code class="inline-code">e</code>" variable.
<code class="inline-code">import</code> is similar to the perhaps already familiar
<a href="ref_directive_include.html#ref.directive.include"><code>include</code>
directive</a>, but it will create an empty namespace and will run
<code class="inline-code">lib/example.ftl</code> in that namespace. So
<code class="inline-code">lib/example.ftl</code> will find itself in a clean
world, where only the variables of the data-models are visible (and
the globals), and will create its two variables
(<code class="inline-code">copyright</code> and <code class="inline-code">mail</code>) in this
clean namespace. But you will need to access those two variables
from another namespace (the main namespace), thus, the
<code class="inline-code">import</code> directive creates a hash variable
(<code class="inline-code">e</code> in this case) to access the namespace it has
created . That variable is in the namespace that the
<code class="inline-code">import</code>-ing template uses, and acts as a window to
the namespace of the imported library.</p>
<p>To demonstrate that the two namespaces are separate, consider
the example below. Replace <code class="inline-code">lib/example.ftl</code> with
this:</p>
<div class="code-block role-template">
<div class="code-block-label">Template</div><pre class="code-block-body">&lt;#macro copyright date&gt;
&lt;p&gt;Copyright (C) ${date} Someone. All rights reserved.
&lt;br&gt;Email: <strong>${mail}</strong>&lt;/p&gt;
&lt;/#macro&gt;
&lt;#assign mail = &quot;user@example.com&quot;&gt;</pre> </div>
<p>and <code class="inline-code">some_web_page.ftl</code> with this:</p>
<div class="code-block role-template">
<div class="code-block-label">Template</div><pre class="code-block-body">&lt;#import &quot;/lib/example.ftl&quot; as e&gt;
<strong>&lt;#assign mail=&quot;other@example.com&quot;&gt;</strong>
&lt;@e.copyright date=&quot;1999-2002&quot;/&gt;
${e.mail}
${mail}</pre> </div>
<div class="code-block role-output">
<div class="code-block-label">Output</div><pre class="code-block-body"> &lt;p&gt;Copyright (C) 1999-2002 Someone. All rights reserved.
&lt;br&gt;Email: <strong>user@example.com</strong>&lt;/p&gt;
user@example.com
other@example.com</pre> </div>
<p>As you can see, the <code class="inline-code">mail</code> variable assigned
in <code class="inline-code">some_web_page.ftl</code> is separate from the
<code class="inline-code">mail</code> variable assigned in the imported
library.</p>
<h2 class="content-header header-section2" id="autoid_24">Writing the variables of imported namespaces</h2>
<p>Sometimes you want to create or replace a variable in an
imported namespace. You can do that with the
<code class="inline-code">assign</code> directive and its
<code class="inline-code">namespace</code> parameter:</p>
<div class="code-block role-template">
<div class="code-block-label">Template</div><pre class="code-block-body">&lt;#import &quot;/lib/example.ftl&quot; as e&gt;
${e.mail}
&lt;#assign mail=&quot;other@example.com&quot; <strong>in e</strong>&gt;
${e.mail}</pre> </div>
<div class="code-block role-output">
<div class="code-block-label">Output</div><pre class="code-block-body">user@example.com
other@example.com</pre> </div>
<h2 class="content-header header-section2" id="autoid_25">Namespaces and data-model</h2>
<p>The variables of the data-model are visible from everywhere.
For example, if you have a variable called <code class="inline-code">user</code>
in the data-model, <code class="inline-code">lib/example.ftl</code> will access
that, exactly like <code class="inline-code">some_web_page.ftl</code> does:</p>
<div class="code-block role-template">
<div class="code-block-label">Template</div><pre class="code-block-body">&lt;#macro copyright date&gt;
&lt;p&gt;Copyright (C) ${date} <strong>${user}</strong>. All rights reserved.&lt;/p&gt;
&lt;/#macro&gt;</pre> </div>
<p>Assuming <code class="inline-code">user</code> is "John
Doe":</p>
<div class="code-block role-template">
<div class="code-block-label">Template</div><pre class="code-block-body">&lt;#import &quot;/lib/my_test.ftl&quot; as my&gt;
User is: ${user}
&lt;@my.copyright date=&quot;1999-2002&quot;/&gt;</pre> </div>
<div class="code-block role-output">
<div class="code-block-label">Output</div><pre class="code-block-body">User is: John Doe
&lt;p&gt;Copyright (C) 1999-2002 John Doe. All rights reserved.&lt;/p&gt;</pre> </div>
<p>Don&#39;t forget that the variables in the namespace (the
variables you create with <code class="inline-code">assign</code>,
<code class="inline-code">macro</code>, and <code class="inline-code">function</code>
directives) have precedence over the variables of the data-model
when you are in that namespace. So generally, if a library is
interested in a data-model variable, it doesn&#39;t assign to the same
name.</p>
<div class="callout note">
<strong class="callout-label">Note:</strong>
<p>In some unusual applications you want to create variables in
the template that are visible from all namespaces, exactly like
the variables of the data-model. While templates can&#39;t change the
data-model, it&#39;s possible to achieve similar effect with the
<code class="inline-code">global</code> directive; see the <a href="ref_directive_global.html#ref.directive.global">reference</a>.</p>
</div>
<h2 class="content-header header-section2" id="autoid_26">The life-cycle of namespaces</h2>
<p>A namespace is identified by the path used in the
<code class="inline-code">import</code> directive (after it was normalized to an
absolute path). If you try to <code class="inline-code">import</code> with
equivalent paths for multiple times, it will create the namespace
and run the template for only the first invocation of
<code class="inline-code">import</code>. The later <code class="inline-code">import</code>-s
with equivalent paths will just assign the same namespace to the
variable specified after the <code class="inline-code">as</code> keyword. For
example:</p>
<div class="code-block role-template">
<div class="code-block-label">Template</div><pre class="code-block-body">&lt;#import &quot;/lib/example.ftl&quot; as e&gt;
&lt;#import &quot;/lib/example.ftl&quot; as e2&gt;
&lt;#import &quot;/lib/example.ftl&quot; as e3&gt;
${e.mail}, ${e2.mail}, ${e3.mail}
&lt;#assign mail=&quot;other@example.com&quot; in e&gt;
${e.mail}, ${e2.mail}, ${e3.mail}</pre> </div>
<div class="code-block role-output">
<div class="code-block-label">Output</div><pre class="code-block-body">user@example.com, user@example.com, user@example.com
other@example.com, other@example.com, other@example.com</pre> </div>
<p>As you access the same namespace through <code class="inline-code">e</code>,
<code class="inline-code">e2</code>, and <code class="inline-code">e3</code>, the
<code class="inline-code">email</code> has changed in all of them at once. The
practical importance of this is that when you import the same
library in multiple templates, only one namespace will be
initialized and created for the library, which will be shared by all
the importing templates.</p>
<p>Note that namespaces are not hierarchical; it doesn&#39;t mater
what namespace are you in when <code class="inline-code">import</code> creates
another namespace. For example, when you <code class="inline-code">import</code>
namespace N2 while you are in name space N1, N2 will not be inside
N1. N1 just gets the same N2 that you get if you
<code class="inline-code">import</code> N2 when you are in the main
namespace.</p>
<p>Each <a href="gloss.html#gloss.templateProcessingJob">template
processing job</a> has its own private set of namespaces. Each
template processing job is a separate universe that exists only for
the short period while the main template is rendered, and then it
vanishes with all its populated namespaces. Thus, whenever we say
that "<code class="inline-code">import</code> is called for the first
time", we always mean the first time within the lifespan of a
single template processing job.</p>
<h2 class="content-header header-section2" id="autoid_27">Auto-importing</h2>
<p>When you have to import the same libraries again and again in
many templates, know that the Java programmers (or whoever is
responsible for configuring FreeMarker) can specify auto-imports,
which are imports that are automatically done in all templates. Auto
imports can also be configured to be "lazy" (since
FreeMarker 2.3.25), which means that they are only done when the
imported library is actually used in the template. See the Java API
documentation for more details: <a href="https://freemarker.apache.org/docs/api/freemarker/template/Configuration.html#setAutoImports-java.util.Map-">Configuration.setAutoImports</a>,
<a href="https://freemarker.apache.org/docs/api/freemarker/template/Configuration.html#setLazyAutoImports-java.lang.Boolean-">Configuration.setLazyAutoImports</a>.</p>
<div class="bottom-pagers-wrapper"><div class="pagers bottom"><a class="paging-arrow previous" href="dgui_misc_var.html"><span>Previous</span></a><a class="paging-arrow next" href="dgui_misc_autoescaping.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>