Skip to content
CMO & CTO
CMO & CTO

Closing the Bridge Between Marketing and Technology, By Luis Fernandez

  • Digital Experience
    • Experience Strategy
    • Experience-Driven Commerce
    • Multi-Channel Experience
    • Personalization & Targeting
    • SEO & Performance
    • User Journey & Behavior
  • Marketing Technologies
    • Analytics & Measurement
    • Content Management Systems
    • Customer Data Platforms
    • Digital Asset Management
    • Marketing Automation
    • MarTech Stack & Strategy
    • Technology Buying & ROI
  • Software Engineering
    • Software Engineering
    • Software Architecture
    • General Software
    • Development Practices
    • Productivity & Workflow
    • Code
    • Engineering Management
    • Business of Software
    • Code
    • Digital Transformation
    • Systems Thinking
    • Technical Implementation
  • About
CMO & CTO

Closing the Bridge Between Marketing and Technology, By Luis Fernandez

Separating Content and Presentation with FreeMarker

Posted on December 23, 2007October 17, 2025 By Luis Fernandez

The web is buzzing with new frameworks and shiny toys. Rails keeps the volume up, Facebook apps are everywhere, and in Java land teams are split between JSF, Spring MVC, and Struts 2. In the middle of that mix there is one topic that keeps showing up in client calls and late night chats with friends who ship sites for a living. How do we separate content and presentation without turning views into a mess? My short answer these days is FreeMarker. It is small, sharp, and it respects the boundary between what the page says and how the page looks.

Definitions so we speak the same language

  • FreeMarker: a Java template engine that takes a template file and a data model, then spits out text. Usually HTML, but it can be email, XML, JSON, you name it.
  • Template: an FTL file with placeholders like ${user.name} and simple control tags for if and list.
  • Data model: a Map or bean graph you build in Java and pass to the template.
  • Separation of content and presentation: content comes from your data model, presentation lives in the template, business rules stay in Java. No business logic in the view.
  • MVC view layer: where FreeMarker sits when you use it with Spring MVC, Struts 2, or a tiny custom servlet.

Examples you can paste and run

Base layout with blocks

<#macro layout title>
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>${title}</title>
  </head>
  <body>
    <header><h1>${title}</h1></header>
    <main><#nested/></main>
    <footer>Powered by FreeMarker</footer>
  </body>
</html>
</#macro>

<@layout title="Latest Articles">
  <#if articles?has_content>
    <ul>
      <#list articles as a>
        <li>
          <a href="${a.url}">${a.title}</a>
          <small>by ${a.author} on ${a.date?string("yyyy MMM dd")}</small>
        </li>
      </#list>
    </ul>
  <#else>
    <p>Nothing to see yet.</p>
  </#if>
</@layout>

Java side with plain servlet style code

Configuration cfg = new Configuration();
cfg.setClassForTemplateLoading(getClass(), "/templates");
cfg.setDefaultEncoding("UTF-8");
cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);

Template tpl = cfg.getTemplate("list.ftl");

Map<String,Object> model = new HashMap<>();
model.put("articles", articleService.latest());

StringWriter out = new StringWriter();
tpl.process(model, out);

response.setContentType("text/html; charset=UTF-8");
response.getWriter().write(out.toString());

Spring MVC setup for FreeMarkerViewResolver

<bean id="freemarkerConfig"
      class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
  <property name="templateLoaderPath" value="/WEB-INF/ftl"/>
  <property name="defaultEncoding" value="UTF-8"/>
</bean>

<bean class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">
  <property name="suffix" value=".ftl"/>
  <property name="contentType" value="text/html; charset=UTF-8"/>
</bean>

That is the full round trip. Data in Java, presentation in FreeMarker, clean HTML out. No scriptlets, no tag soup.

Counterexamples that bite

Mixing logic into JSP turns into spaghetti fast.

<%-- bad idea --%>
<ul>
<% for (Article a : articleService.latest()) { %>
  <li><a href="<%= a.getUrl() %>"><%= a.getTitle() %></a></li>
<% } %>
</ul>

Business rules in templates is another trap. Prices and discounts belong in Java.

<#-- still a bad idea even if it works -->
<#assign total = 0 />
<#list cart.items as i>
  <#assign total = total + i.price * i.qty />
</#list>
<#if user.isVip>
  <#assign total = total * 0.9 />
</#if>
Total: ${total}

Do that math in Java, expose total in the model, and let the template just print it. Templates should read like a story.

Decision rubric for your project

  • Team skills: if your team writes clean HTML and prefers simple tags and macros, FreeMarker fits. If the team lives in JSP tag libs and already has a pile of them, staying with JSP may be simpler.
  • Framework fit: Struts 2 ships with FreeMarker views out of the box. Spring MVC plays nice with it too. If you are all in on JSF with component trees, FreeMarker is not the right tool.
  • Null safety and strictness: FreeMarker can complain loudly when a variable is missing. That saves time. Set RETHROW in dev and you catch mistakes early.
  • Reuse: Macros and includes make headers, footers, and repeated widgets easy to share. If your pages repeat patterns a lot, you win here.
  • Internationalization: It prints whatever you give it. Keep messages in resource bundles and pass resolved strings or use a small helper to fetch them in templates.
  • Performance: Templates are cached in memory and they are fast. The heavy lifting is usually your data fetch, not FreeMarker.
  • Tooling: You can edit FTL in any text editor. There are plugins for popular IDEs that add syntax color and basic checks.

Lesson learned from the trenches

Keep the contract clean. Java prepares data, FreeMarker renders it. Name your templates after the thing they show, not the controller that serves them. Put shared macros in a common file and include them from every page. Turn on strict mode in development so missing values do not sneak into production. Write a tiny unit test that loads a template with a fake model and asserts the important bits. It takes five minutes and catches silly mistakes.

The bigger picture is simple. Good separation makes teams faster. Designers can tweak markup without reading service code. Developers can change business rules without touching templates. FreeMarker keeps that wall in place without being noisy or bossy. If your project needs a clean view layer for a Java web app, give it a try this week. It plays nice with Spring, Struts 2, and plain servlets. It keeps content and presentation apart, which is the win we want.

Software Architecture Software Engineering

Post navigation

Previous post
Next post
  • Digital Experience (94)
    • Experience Strategy (19)
    • Experience-Driven Commerce (5)
    • Multi-Channel Experience (9)
    • Personalization & Targeting (21)
    • SEO & Performance (10)
  • Marketing Technologies (92)
    • Analytics & Measurement (14)
    • Content Management Systems (45)
    • Customer Data Platforms (4)
    • Digital Asset Management (8)
    • Marketing Automation (6)
    • MarTech Stack & Strategy (10)
    • Technology Buying & ROI (3)
  • Software Engineering (310)
    • Business of Software (20)
    • Code (30)
    • Development Practices (52)
    • Digital Transformation (21)
    • Engineering Management (25)
    • General Software (82)
    • Productivity & Workflow (30)
    • Software Architecture (85)
    • Technical Implementation (23)
  • 2025 (12)
  • 2024 (8)
  • 2023 (18)
  • 2022 (13)
  • 2021 (3)
  • 2020 (8)
  • 2019 (8)
  • 2018 (23)
  • 2017 (17)
  • 2016 (40)
  • 2015 (37)
  • 2014 (25)
  • 2013 (28)
  • 2012 (24)
  • 2011 (30)
  • 2010 (42)
  • 2009 (25)
  • 2008 (13)
  • 2007 (33)
  • 2006 (26)

Ab Testing Adobe Adobe Analytics Adobe Target AEM agile-methodologies Analytics architecture-patterns CDP CMS coding-practices content-marketing Content Supply Chain Conversion Optimization Core Web Vitals customer-education Customer Data Platform Customer Experience Customer Journey DAM Data Layer Data Unification documentation DXP Individualization java Martech metrics mobile-development Mobile First Multichannel Omnichannel Personalization product-strategy project-management Responsive Design Search Engine Optimization Segmentation seo spring Targeting Tracking user-experience User Journey web-development

©2025 CMO & CTO | WordPress Theme by SuperbThemes