2.3.34

Release date: 2024-12-22

Changes on the FTL side

  • GitHub PR-114: Added #on directive that's now recommended instead of #case inside #switch. It has no fall-through, so you need not, and must not use #break like you did with #case. Also, #on can have a list of matching values, so you can use <#on 1, 2, 3>Was 1-3 instead of <#case 1><#case 2><#case 3>Was 1-3<#break> See more here...

  • GitHub PR-111: Added new built-ins that allow handling empty or blank strings the same way as if they were missing values (Java null-s): stringOrMissing?blank_to_null, stringOrMissing?empty_to_null, stringOrMissing?trim_to_null. For example, if somewhere you had ${user.fullName!'Not specified'}, but then you realize that sometimes user.fullName is a blank string (and hence the default value is not used), you can write ${user.fullName?blank_to_null!'Not specified'}.

  • GitHub PR-119: Fixed bug if you set the incompatible_improvements setting to 2.3.34 or higher: [#sep], <#sep>, and <sep> were all interpreted as a call to the sep directive, regardless if the already established tag syntax was angle bracket or square bracket tags, or if the tag syntax was "strict" (requiring #) or not. With this fix enabled via incompatible_improvements, a sep tag with the tag syntax that doesn't match the configured/established tag syntax will be seen as just static text, just as it's done for any other FTL tags.

  • FREEMARKER-227: Fixed bug, where if classic_compatible mode was true (rarely used), then sequence built-ins, like seq?seq_contains(value), has failed with NullPointerException if values of incompatible types had to be compared. The intended behavior is to convert the values to string, and then compare them (to mimic the behavior of FreeMarker 1.x).

Changes on the Java side

  • GitHub PR-110: Using multi-release JAR format (JEP 238) to put Java 9 and Java 16 support files (freemarker.core._Java9Impl and _Java16Impl) into freemarker.jar. This means that they are now under META-INF/versions/9 and 16, instead of in the usual location together with Java 8 byte code class files. This was needed as some tools, like Maven Enforcer plugin, have seen them as problems otherwise. Also, now we don't look for the _JavaXImpl classes with Class.forName(String), instead we just refer them normally, as now Java will link to the proper variant according the multi-release JAR format. This can help if some environment doesn't support class loading on runtime (however, then you still will have problems with other optional features).