2.3.26 (incubating at Apache)

Release date: 2017-03-25

This is a stable, final release. The "incubating" suffix is required by the Apache Software Foundation until the project becomes a fully accepted (graduated) Apache project.

Changes on the FTL side

  • Added node?next_sibling and node?previous_sibling to move sideways in a node trees (see reference...). This works with XML DOM nodes, or with any custom TemplateNodeModelEx implementations.

  • Added new @@ keys to XML DOM models: @@next_sibling_element, @@previous_sibling_element. These get the sibling node if that's an element, with the extra that they silently skip any whitespace text and comment and processing instruction between them. (See more about @@ keys here...)

  • Bug fixed (FREEMARKER-42): ?first now works with FTL collections (things that can be listed but doesn't support getting items by index), not only with sequences. The practical importance of this is that ?first now always works on Java Set-s (which is useful for Set-s with well defined ordering), while earlier it has failed depending on the object_wrapper configuration setting.

Changes on the Java side

  • FREEMARKER-24: Added workaround (not enabled by default) to expose Java 8 default methods (and the bean properties they define) to templates, despite that java.beans.Introspector (the official JavaBeans introspector) ignores them, at least as of JRE 1.8.0_66. To enable this workaround, either increase the value of the incompatibleImprovements constructor argument of DefaultObjectWrapper or BeansWrapper the used to 2.3.26, or set its treatDefaultMethodsAsBeanMembers setting to true. Note that if you leave the object_wrapper setting of the Configuration on its default, it's enough to increase the incompatibleImprovements setting of the Configuration to 2.3.26, as that's inherited by the default object_wrapper.

  • Added the freemarker.template.TemplateNodeModelEx interface which extends the TemplateNodeModel instance with two methods, TemplateNodeModelEx getNextSibling() and TemplateNodeModelEx getPreviousSibling() methods. This is required by node?next_sibling and node?previous_sibling in the templates. This new interface is already implemented by the standard W3C DOM node wrapper of FreeMarker.

  • Made + operator when adding two hashes significantly faster (be removing the overhead caused be throwing and then catching an exception).

  • Better error messages when someone tries to get an invalid @@... subvariable of an XML DOM node. (Now it's not issued by the XPath implementation, which just sees it as a syntactical error.)

  • Added Configuration.isXxxExplictlySet and Configuration.unsetXxx methods for the Configuration settings: locale, time_zone, default_encoding. (This can be utilized in frameworks to detect if the application has missed setting these. The backward compatible default values are often unwanted, as they are the default locale, time zone and file encoding of the Java environment.)

  • The locale and default_encoding configuration settings now supports the special "JVM default" value when set from Java .properties file, or via Configuration.setSettings(Properties), or via the #setting directive. Earlier only the time_zone setting has supported this value.

  • Bug fixed: The OSGi Bundle-RequiredExecutionEnvironment entry in META-INF/MANIFEST.MF has incorrectly stated that the minimum required version is J2SE-1.4, while it's in fact J2SE-1.5. Also the highest utilized version was raised to JavaSE-1.8.

  • Bug fixed: If the incompatible_improvements setting is set to 2.3.26 (or higher), exp?interpret always gets the parser-related settings from the template that it's called from. Earlier, sometimes it got those from the topmost (main) template instead. Similarly, the generated name of the template that ?interpret creates will always refer to the template where's it's called from.

  • Bug fixed: MultiTemplateLoader, when it's in sticky mode (the default), and the TemplateLoader that was successfully used for a given name last time doesn't find the template now (let's call it the sticked TemplateLoader), and thus MultiTemplateLoader falls back to trying all the TemplateLoader-s in order, will now skip the sticked TemplateLoader, as that was already attempted in the same MultiTemplateLoader.findTemplateSource invocation.

  • Bug fixed: NodeModel.mergeAdjacentText(Node) didn't merged all adjacent text nodes, only pairs of adjacent text nodes. (Luckily this method is hardly ever used, and the more often used NodeModel.simplify(Node) was working correctly.)

  • Performance improvements in the static utility methods of NodeModel: simplify(Node), mergeAdjacentText(Node), removeComments(Node), removePIs(Node).

  • Added warning to the JavaDoc of NodeModel.parse methods to inform users about the possibility of XML External Entity (XXE) attacks if the source XML (not a template) comes from untrusted source. This is just an XML fact (i.e., that in an XML you can have external entities and they can be exploited), and has no much to do with FreeMarker. Also note that FreeMarker itself never calls NodeModel.parse; these are merely convenience methods that some applications directly call themselves to create a NodeModel from an XML file. As this method encapsulates the call to the platform XML parser, we thought it's better to point this risk out.

  • DefaultObjectWrapper, only with its incompatible_improvements set to 2.3.26 (see how here...), wraps java.util.Enumeration-s into freemarker.template.DefaultEnumerationAdapter (a new class) instead of into freemarker.ext.beans.EnumerationModel (as far as useAdaptersForContainers is true, which is the default). This adapter is cleaner than EnumerationModel as it only implements the minimally required FTL type, which avoids some ambiguous situations. (Note that Java API methods aren't exposed anymore as subvariables; if you really need them, you can use ?api).

  • DefaultIteratorAdapter now supports ?api. It was an oversight that it didn't.

  • Configuration.setSetting(String, String) and setSettings now allows null value for template_loader (because Configuration.setTemplateLoader(null) is also allowed for a while.).

  • The freemarker.template.TemplateCollectionModelEx interface and is not experimental anymore, so now it has backward compatibility guarantees. Note that the TemplateCollectionModelEx.contains(TemplateModel) method was removed from it.

  • freemarker.template.DefaultNonListCollectionAdapter class is not experimental anymore, so now it has backward compatibility guarantees.

  • BeansWrapperConfiguration.classIntrospectorFactory is not a protected field anymore, but a private one. Especially as the class of that field (ClassIntrospectorBuilder) was package private, it's pretty much sure that nobody depends on this field.

  • Various smaller code cleanups.

Other changes

  • FREEMARKER-17: Removed the Servlet- and JSP-related *.dtd files to simplify licensing. We can operate without them as before, as validation with them was disabled earlier too. At this point, everything in the source code of the FreeMarker engine, and everything in the produced freemarker.jar was created inside the FreeMarker project.

  • FREEMARKER-27: Moved some content from the NOTICES files over to the LICENSE file, to follow the Apache Incubator guidelines closer.

  • Various smaller JavaDoc improvements.