Migrating to Velocity 1.5

Confluence trunk development (2.8) will be based on Velocity 1.5. The migration to the latest version of Velocity brings with it some issues that Confluence developers need to be aware of.

Word tokens are no longer valid as the first argument to Velocimacros

In Velocity 1.4, the velocimacro syntax was changed to prevent the use of work tokens as the first argument to most directives (except for defining the macro itself). This makes the following, common webwork structure fail to parse in Velocity 1.4 and beyond.

#bodytag (Select "label=$theLabel" "name='extraLevelName'" "list=levelTypes" "theme='notable'")

This means that you must quote the first argument to make it a proper string.

#bodytag ("Select" "label=$theLabel" "name='extraLevelName'" "list=levelTypes" "theme='notable'")

For these directives to work correctly with the new syntax a patched version of Webwork 2.1 is also required. Confluence now depends on this custom version of Webwork 2.1.

When the old syntax is used, the following error will be produced (but with a different line, column and vm file):

org.apache.velocity.exception.ParseErrorException: Invalid arg #0 in directive at line 37, column 41 of /templates/publishingconfiguration.vm

Multi-line comments behave strangely in Velocimacros

Due to an apparent bug in Velocity 1.5 VELOCITY-537, multi-line comments in Velocimacros can cause ParseExceptions. Multi-line macro comments have mainly been used in Confluence to control the output of extraneous whitespace during the rendering of a macro. To work around this issue a new #trim() directive has been introduced that can be used to strip whitespace from macro rendering. This unfortunately introduces a slight overhead to rendering as whitespace must be trimmed in every execution at runtime rather than stripped by the lexer at template parsing time.

Using comments to control whitespace
#macro (globalLogoBlock)#*
    *##if ($settingsManager.getGlobalSettings().isDisableLogo())#* render nothing
        *#<a href="$req.contextPath/homepage.action"><img src="#logo("")" align="absmiddle" border="0"></a>#*
Using the trim directive to control whitespace
#macro (globalLogoBlock)
    #if ($settingsManager.getGlobalSettings().isDisableLogo())
        <a href="$req.contextPath/homepage.action"><img src="#logo("")" align="absmiddle" border="0"></a>

We'll be able to revert to the previous method once VELOCITY-537 is fixed and integrated, although it's arguable that the new directive makes for more maintainable macros.

Exceptions from method executions in macro parameters are no longer swallowed

Due to another bug in Velocity 1.3, exceptions that occur during a method execution in a macro parameter evaluation were swallowed silently; the return value of such executions was null. Velocity 1.5 contains a fix for this which means its likely that we are going to run into situations where pages which previously worked regardless of broken method calls are going to fail with a MethodInvocationException. There's only one correct solution here: fix the broken method calls as we find them.

Equality test operator is more strict

In previous versions of Velocity testing for equality using just a single = worked. This has been made stricter in Velocity 1.5; you must use == otherwise a ParseException will be thrown.

Backwards compatibility with Velocity templates used in existing themes and plugins

We realise that some of the changes that Velocity 1.5 brings to Confluence could cause annoying compatibility problems and lots of work for plugin maintainers, particulary the new Velocimacro syntax requirements. Confluence 2.8 will load all plugin templates using a special resource loader which will attempt to automatically fix loaded templates to work with the new Velocity engine (com.atlassian.confluence.util.velocity.Velocity13CompatibleResourceLoader). This does add some additional overhead to plugin loading (the template is adjusted once at load time and then cached) but it will ease the burden on plugin developers during this transitional period.

It is still a good idea for plugin authors to use the new Velocimacro syntax; updating your templates can be made easier by looking for the info messages logged by the resource loader whenever it finds incompatible syntax.

Found incompatible Velocity 1.5 syntax in resource: [resource name]; [template fragment]

Dynamically loaded plugins only

For performance reasons, the compatibility layer is only applied to dynamically loaded plugins. Plugins loaded through WEB-INF/lib will not have the compatibility processing applied.

Was this page helpful?

Have a question about this article?

See questions about this article

Powered by Confluence and Scroll Viewport