Symmetric operators in FreshMarker: reverse dispatch for X op Y

When you write ${date + 3} in a template, TemplateLocalDate knows how to add an integer. When you write ${3 + date}, the roles are swapped: the number is on the left, and TemplateNumber has never heard of dates. Historically FreshMarker only dispatched operators on the left operand, which meant that a new type could never opt into being the right operand of an operator without patching every other type. This post walks through the design and implementation of the new symmetric operator dispatch that fixes exactly that.

The ~~ Operator: Formatted Concatenation in FreshMarker

FreshMarker has introduced the ~ operator, which concatenates values with a space. With FreshMarker 3.0.0, ~~ is introduced: the same concept, but this time non-textual primitives are passed through the configured formatter before concatenation—numbers, dates, and other primitives thus appear exactly as they do in the rest of the template. The Problem with Simple Concatenation FreshMarker has … Read more

Phase 2: schema-aware typed compilation in FreshMarker

The previous post looked at the Stage 1 (untyped) compiler and finished with an honest observation: Stage 1 removes fragment-dispatch overhead but still evaluates every expression through TemplateObject. This third and final post explains how the Stage 2 compiler uses a TemplateTypeSchema to emit raw Java that talks directly to your data model — and how that unlocks the ~2.5× AOT speedup from the benchmark chart in the first post.

Nested Directives with Default Content

Macro-based templates often need a sensible default body for the common case, while still allowing customization at the call site. FreshMarker 3.0.0 will support exactly that: <#nested/> can carry inline fallback content that renders automatically when no caller body is provided.

This article explains how the feature is implemented, from grammar to runtime, and includes a design note on one carefully chosen trade-off.

The PooledTemplateProcessor

Memory management is a major challenge when it comes to improving the performance of Java applications. When many objects are created, memory must be allocated for them; these objects must be managed and eventually deleted, and their memory released. This comes at a cost, and an application that consistently works with fresh objects will suffer from reduced performance.

With Freshmarker 2.7.0, the PooledTemplateProcessor has been added, which guarantees a performance boost in template processing; however, this comes at the cost of compromises elsewhere.

FreshMarker 2.7.0 – New Release!

After two months of development, I’m pleased to announce the release of FreshMarker version 2.7.0. This time, the focus was on functional hash processing, more flexible formatting, and a major step toward a more consistent template syntax. Overall, it’s a well-rounded mix of new expression capabilities and improved code quality in templates. New Features Deprecation … Read more

The End of Loose Tag End

While designing a new feature, I once again stumbled upon a feature of the template language that I haven’t liked for a long time. The syntax of the directives is modeled after HTML elements, not XML elements. As long as you don’t want to change the syntax of the template language, this isn’t a problem. But if you have a great idea for a new feature, you’re in for a world of trouble.

Partial Reduction of Range Lists

One of the most useful optimizations in FreshMarker is partial reduction: templates can be partially evaluated in advance if part of the model is already known. Until now, however, partial reduction had a blind spot—List directives with ranges (1..4, 4..1, 1..) were ignored during reduction and passed through as simple, non-reducing fragments. This changes with version 2.7.0.