You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@velocity.apache.org by cb...@apache.org on 2026/09/25 15:25:16 UTC

(velocity-site) branch main updated: Port 2.5 docs changes to the 'devel' section

This is an automated email from the ASF dual-hosted git repository.

asf-gitbox-commits pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/velocity-site.git


The following commit(s) were added to refs/heads/main by this push:
     new fb2c3bca Port 2.5 docs changes to the 'devel' section
fb2c3bca is described below

commit fb2c3bca8fec3241f5494767c6b711b453044112
Author: Claude Brisson <cl...@renegat.net>
AuthorDate: Fri Sep 25 17:25:10 2026 +0200

    Port 2.5 docs changes to the 'devel' section
---
 src/content/engine/devel/configuration.mdtext   |  45 ++++++---
 src/content/engine/devel/developer-guide.mdtext |   2 +
 src/content/engine/devel/index.mdtext           |   5 +-
 src/content/engine/devel/upgrading.mdtext       |  27 ++++++
 src/content/engine/devel/user-guide.mdtext      | 118 ++++++++++++------------
 src/content/engine/devel/vtl-reference.mdtext   |  44 ++++-----
 6 files changed, 143 insertions(+), 98 deletions(-)

diff --git a/src/content/engine/devel/configuration.mdtext b/src/content/engine/devel/configuration.mdtext
index ace74f02..a92fbb01 100644
--- a/src/content/engine/devel/configuration.mdtext
+++ b/src/content/engine/devel/configuration.mdtext
@@ -18,7 +18,7 @@ The properties key names have been reviewed in Engine 2.1. Old names are still f
 
 ## Configuration Summary Tree
 
-The following tree gathers all non deprecated configuration properties with their default values.
+The following tree gathers all configuration properties with their default values. None of these defaults is deprecated, except `runtime.strict_math = false` (see below).
 
     :::properties
     context. +-- scope_control. +-- define = false
@@ -48,8 +48,7 @@ The following tree gathers all non deprecated configuration properties with thei
                   |                       +-- instance = *Java Object instance*
                   +-- uberspect.class = org.apache.velocity.util.introspection.UberspectImpl
     
-    parser. +-- allow_hyphen_in_identifiers = false
-            +-- pool. +-- class = org.apache.velocity.runtime.ParserPoolImpl
+    parser. +-- pool. +-- class = org.apache.velocity.runtime.ParserPoolImpl
             |         +-- size = 20
             +-- space_gobbling = lines
     
@@ -67,6 +66,7 @@ The following tree gathers all non deprecated configuration properties with thei
                            +-- log_when_found = true
     
     runtime. +-- custom_directives = *classname*, *classname* ...
+             +-- deprecation.warn = true
              +-- immutable_ranges = true
              +-- interpolate_string_literals = true
              +-- log. +-- instance = *Java Object instance*
@@ -88,6 +88,21 @@ The following tree gathers all non deprecated configuration properties with thei
                  +-- library. +-- autoreload = false
                               +-- path = velocimacros.vtl 
 
+### Deprecated Settings
+
+The following settings are deprecated since 2.5, in preparation for the next major version. Each of them logs a warning at engine initialization, unless `runtime.deprecation.warn` is set to false.
+
+    :::properties
+    parser. +-- allow_hyphen_in_identifiers = true
+            +-- class = *classname*
+    
+    runtime. +-- immutable_ranges = false
+             +-- strict_math = false      (the default value: set it to true)
+    
+    velocimacro. +-- enable_bc_mode = true
+
+The pre-2.1 property names are deprecated as well, see the [**table of correspondance**](configuration-property-changes-in-2.1.html).
+
 ## Logging
 
 **`runtime.log.instance`** = *Java Object instance*
@@ -165,7 +180,7 @@ Be aware that it can have a (probably very) small performance impact.
 
 **`directive.parse.max_depth = 10`**
 
-> Defines the allowable parse depth for a template. A template may #parse() another template which itself may have a #parse() directive.  This value prevents runaway #parse() recursion.
+> Defines the allowable nesting depth of `#parse()` and, since 2.5, `#evaluate()`. A template may #parse() another template which itself may have a #parse() directive, and evaluated VTL may itself contain `#evaluate()` or `#parse()`; the two directives share the same nesting stack, so a mixed chain counts together. Once the limit is reached the directive renders nothing and an error is logged instead of the recursion running until the thread's stack is exhausted. A value of 0 or less mea [...]
 
 ### custom directives
 
@@ -240,7 +255,7 @@ The following resource management configuration keys only apply to the default R
 
 **`velocimacro.library.path = velocimacros.vtl `**
 
-> *Multi-valued key.  Will accept CSV for value.* Filename(s) of Velocimacro library to be loaded when the Velocity Runtime engine starts.  These Velocimacros are accessable to all templates.  The file is assumed to be relative to the root of the file loader resource path. If the default (<code>velocimacro.vtl</code> since 2.1) is not found, the old default (<code>VM_global_library.vm</code>) is also searched for.
+> *Multi-valued key.  Will accept CSV for value.* Filename(s) of Velocimacro library to be loaded when the Velocity Runtime engine starts.  These Velocimacros are accessable to all templates.  The file is assumed to be relative to the root of the file loader resource path. If the default (<code>velocimacros.vtl</code> since 2.1) is not found, the old default (<code>VM_global_library.vm</code>) is also searched for. *Deprecated since 2.5*: the old default name `VM_global_library.vm` is no [...]
 
 **`velocimacro.inline.allow = true`**
 
@@ -262,7 +277,7 @@ The following resource management configuration keys only apply to the default R
 
 > When set to true, will throw a `ParseErrorException` when parsing a template containing a macro with an invalid number of arguments. Is set to false by default to maintain backwards compatibility with templates written before this feature became available.
 
-**`velocimacro.enable_bc_mode = false`**
+**`velocimacro.enable_bc_mode = false`** *(deprecated since 2.5)*
 
 > This flag enables Velocimacro backward compatible mode. It has two effects:
 > 
@@ -279,7 +294,7 @@ The following resource management configuration keys only apply to the default R
 >         #macro( display $foo ) $foo #end
 >         #set( $foo = 'hello' )
 >         #display()
-> will display `$foo`. When B.C. mode is enabled, Velocity will mimic the 1.x behavior which is to use the global context value, that is render `hello`.
+> will display `$foo`. When B.C. mode is enabled, Velocity will mimic the 1.x behavior which is to use the global context value, that is render `hello`. *Deprecated since 2.5*, without replacement: the next major version does not provide this compatibility mode (the 2.0 behaviours above are the only ones); enabling it emits a startup warning.
 
 **`velocimacro.body_reference = false`**
 
@@ -303,15 +318,21 @@ The following resource management configuration keys only apply to the default R
 
 ## Ranges
 
-**`runtime.immutable_ranges = true`**
+**`runtime.immutable_ranges = true`** *(deprecated since 2.5)*
 
-> Controls whether the `java.util.List` object return by the VTL range operator [ *a* .. *b* ] is an immutable list (the default since Velocity 2.1) or a mutable list backed by a `java.util.ArrayList` object.
+> Controls whether the `java.util.List` object return by the VTL range operator [ *a* .. *b* ] is an immutable list (the default since Velocity 2.1) or a mutable list backed by a `java.util.ArrayList` object. *Deprecated since 2.5*: ranges are always immutable in the next major version; setting this key to `false` emits a startup warning.
 
 ## Math
 
 **`runtime.strict_math = false`**
 
-> Affects all math operations in VTL. If changed to true, this will cause Velocity to throw a MathException whenever one side of a math operation has a null value (e.g. `#set( $foo = $null * 5 )`) or when trying to divide by zero.  If this value is left `false`, then rendering will continue and that math operation will be ignored.
+> Affects all math operations in VTL. If changed to true, this will cause Velocity to throw a MathException whenever one side of a math operation has a null value (e.g. `#set( $foo = $null * 5 )`) or when trying to divide by zero.  If this value is left `false`, then rendering will continue and that math operation will be ignored. *Deprecated since 2.5*: the lenient behaviour is going away — the next major version always enforces strict math — so leaving this value `false` emits a startu [...]
+
+## Deprecation Warnings
+
+**`runtime.deprecation.warn = true`**
+
+> When true, logs a warning for the VTL syntax constructs and configuration options that are deprecated in preparation for the next major version: a backslash right before the closing quote of a double-quoted string (use a single-quoted string), the `parser.allow_hyphen_in_identifiers` option, and lenient math (`runtime.strict_math = false`, warned once at initialization). On by default; set it to false to silence them while a template base is being migrated. See the [upgrading guide](up [...]
 
 ## Parser Configuration
 
@@ -323,9 +344,11 @@ The following resource management configuration keys only apply to the default R
 
 > This property is used by the default pooling implementation to set the number of parser instances that Velocity will create at startup and keep in a pool.  The default of 20 parsers should be more than enough for most uses.  In the event that Velocity does run out of parsers, it will indicate so in the log, and dynamically create overflow instances as needed.  Note that these extra parsers will not be added to the pool, and will be discarded after use.  This will result in very slow op [...]
 
-**`parser.allow_hyphen_in_identifiers = false`**
+**`parser.allow_hyphen_in_identifiers = false`** *(deprecated since 2.5)*
 
 > This is a backward compatibility option, false by default, which allows the '**`-`**' character inside variable identifiers (available since 2.1). If enabled, be warned that you will have to surround the mathematical minus sign with spaces for it to be correctly interpreted.
+>
+> *Deprecated since 2.5*: a hyphenated identifier such as `$foo-bar` cannot be expressed in the next major version. Enabling this option emits a startup warning when `runtime.deprecation.warn` is on.
 
 ## Event Handlers
 
diff --git a/src/content/engine/devel/developer-guide.mdtext b/src/content/engine/devel/developer-guide.mdtext
index b374fbf4..1f894d98 100644
--- a/src/content/engine/devel/developer-guide.mdtext
+++ b/src/content/engine/devel/developer-guide.mdtext
@@ -1638,6 +1638,8 @@ Then, in the target project, you have to specify which parser to use from within
 
 For instance, you may want to replace `#` with `%` because the target language (markdown for instance) already makes use of the `#` symbol.
 
+*Deprecated since 2.5*: the `parser.class` property is deprecated. The next major version keeps the capability by letting an application plug in a lexer, and this property has no effect there; the `$` character will not be configurable at all any more (`#`, `@` and `*` will), so a custom parser relying on `parser.char.dollar` has no future equivalent. The 2.x mechanism above keeps working in 2.x, and a 2.x custom parser class is not reusable there.
+
 ## Summary
 
 We hope this brief guide was a helpful introduction to using Velocity in your Java projects, and thank you for you interest in Velocity.  We welcome any and all comments you may have about this documentation and the Velocity template engine itself.
diff --git a/src/content/engine/devel/index.mdtext b/src/content/engine/devel/index.mdtext
index 68472ebe..13f7e0af 100644
--- a/src/content/engine/devel/index.mdtext
+++ b/src/content/engine/devel/index.mdtext
@@ -8,11 +8,12 @@ You can check the [Velocity Template Language (VTL) reference](vtl-reference.htm
 
 ## Where do I get releases?
 
-The current stable release version is version 2.4.1.
+The current stable release version is version 2.5.
 
 The release distribution is available as a combined source/binary distribution in `tar.gz` and `zip` formats, and can be downloaded through the [Apache Mirror system](/download.cgi).
 
-The Velocity jars are also available through the [central Maven repository](https://search.maven.org/artifact/org.apache.velocity/velocity-engine-core/2.4.1/jar).
+The Velocity Engine jars are also available through the [Central Maven repository](
+https://central.sonatype.com/search?q=velocity-engine).
 
 Older releases are archived at the [Apache Velocity archives](http://archive.apache.org/dist/velocity/engine/).
 
diff --git a/src/content/engine/devel/upgrading.mdtext b/src/content/engine/devel/upgrading.mdtext
index 55b14411..0e6d03ff 100644
--- a/src/content/engine/devel/upgrading.mdtext
+++ b/src/content/engine/devel/upgrading.mdtext
@@ -42,6 +42,33 @@ To maximize backward compatibility of the last Velocity 2.x with Velocity 1.x, b
 
 Also, please note that since version 2.1, Velocity requires Java JDK 1.8+ for building and Java JRE 1.8+ at runtime.
 
+## Upgrading from Velocity 2.4.1 to Velocity 2.5
+
+### Behavior / API Changes
+
++ **Spring support modules reorganized.** The `spring-velocity-support` artifact now targets the current, Jakarta-based Spring framework (Spring 6.x and 7.x) on Java 17. Although this is a minor Velocity release, it is a *major* upgrade for that module, which jumps from Spring 5 to Spring 6/7. Applications still on **Spring 5.x / Java 8** must switch their dependency to the new `spring5-velocity-support` artifact.
++ New `introspector.restrict.methods` property to restrict only specific method calls in the secure introspector. By default it now blocks `VelocityEngine.init()` and `VelocityEngine.reset()`.
++ `Map.size()` is now invoked instead of any provided `size` property. Templates that defined a `size` property on a map-like object and expected it to shadow the method will see a behavior change.
++ `DatabaseObjectsFactory` is deprecated in favor of `PreparedStatementsFactory`, alongside a connection-leak fix in `DataSourceResourceLoader`.
++ `#evaluate()` now honours the nesting depth limit of `directive.parse.max_depth` (default 10). Both `#parse` and ` #evaluate` push on the same template name stack, so a chain mixing them counts as a whole.
++ Resource names are normalized before a loader sees them: `.` and `..` segments are resolved, and a name that would climb above a configured resource root (`../secret.txt`) is refused as not found.
++ `SecureUberspector` forbids a template to reach a class's static methods through `$value.getClass()` or `$value.class`.
++ Custom parser: the `parser.class` property is deprecated: the next major version will use a pluggable lexer instead, so the [custom parser building process](developer-guide.html#customizing-the-vtl-parser) will provide an equivalent way of customizing the parsing, with one caveat, though: the `$` character will no longer be configurable at all in the next major version, only `#`, `@` and `*` will, so a parser built with `parser.char.dollar` has no future equivalent.
++ SecureUberspector now honours the configured type conversion handler.
+
+### VTL Changes
+
+#### Syntax and configuration deprecations (preparing for the next major version)
+
+- corner case: support for an interpolated double-quoted string ending with `\` is deprecated.
+- the `velocimacro.enable_bc_mode = true` configuration is deprecated (it allowed null or missing macro arguments to render caller's bare references instead of the macro definition ones, after trying to resolve missing arguments from the caller context).
+- the implicit loading of the 1.x macro libraries file `VM_global_library.vm` is deprecated. Use `velocimacros.vtl` or make its path explicit in the configuration.
+- the `runtime.immutable_ranges = false` configuration is deprecated.
+- the `runtime.strict_math = false` configuration is deprecated. Note that `false` is still the default value for 2.5, so relying on the default value *will* produce a deprecation warning.
+- the `parser.allow_hyphen_in_identifiers` configuration is deprecated.
+
+All the corresponding deprecation warning messages can be turned off with `runtime.deprecation.warn = false`.
+
 ## Upgrading from Velocity 2.3 to Velocity 2.4.1
 
 ### Behavior / API Changes
diff --git a/src/content/engine/devel/user-guide.mdtext b/src/content/engine/devel/user-guide.mdtext
index 1f3ee1c9..07a8374d 100644
--- a/src/content/engine/devel/user-guide.mdtext
+++ b/src/content/engine/devel/user-guide.mdtext
@@ -31,13 +31,14 @@ You could embed the following VTL statement in the web page:
     :::html+velocity
     <html>
       <body>
-        Hello $customer.Name!
+        $title
+        Hello ${customer.Name}!
         <table>
         #foreach( $mud in $mudsOnSpecial )
           #if ( $customer.hasPurchased($mud) )
             <tr>
               <td>
-                $flogger.getPromo( $mud )
+                ${flogger.getPromo( $mud )}
               </td>
             </tr>
           #end
@@ -63,7 +64,7 @@ This VTL statement, like all VTL statements, begins with the *#* character and c
 
 The *#* character is followed by a directive, *set*. The *set* directive uses an expression (enclosed in brackets) -- an equation that assigns a *value* to a *variable*. The variable is listed on the left hand side and its value on the right hand side; the two are separated by an *=* character.
 
-In the example above, the variable is *$a* and the value is *Velocity*. This variable, like all references, begins with the *$* character. String values are always enclosed in quotes, either single or double quotes.  Single quotes will ensure that the quoted value will be assigned to the reference as is.  Double quotes allow you to use velocity references and directives to interpolate, such as "Hello $name", where the *$name* will be replaced by the current value before that string liter [...]
+In the example above, the variable is *$a* and the value is *Velocity*. This variable, like all references, begins with the *$* character. References can also be expressions, surrounded by curly braces after the *$*: *${a.toUpperCase()}*. String values are always enclosed in quotes, either single or double quotes.  Single quotes will ensure that the quoted value will be assigned to the reference as is.  Double quotes allow you to use velocity references and directives to interpolate, suc [...]
  
  
 The following rule of thumb may be useful to better understand how Velocity works: **References begin with *$* and are used to get something. Directives begin with *#* and are used to do something.**
@@ -161,61 +162,63 @@ The output will be the same for all instances of *$foo* that follow this directi
 
 ### Properties
 
-The second flavor of VTL references are properties, and properties have a distinctive format. The shorthand notation consists of a leading *$* character followed a VTL Identifier, followed by a dot character (".") and another VTL Identifier. These are examples of valid property references in the VTL:
+The second flavor of VTL references are properties, and properties have a distinctive format. A property reference is a leading *$* character then an expression enclosed by *{* and *}*: a VTL Identifier, a dot character (".") and another VTL Identifier. These are examples of valid property references in the VTL:
 
     :::velocity
-    $customer.Address
-    $purchase.Total
+    ${customer.Address}
+    ${purchase.Total}
+
+Note that Velocity also supports the *informal* notation *$customer.Address*, as long as there is no ambiguity with the surrounding context.
 
-Take the first example, *$customer.Address*. It can have two meanings. It can mean, Look in the hashtable identified as *customer* and return the value associated with the key *Address*. But *$customer.Address* can also be referring to a method (references that refer to methods will be discussed in the next section); *$customer.Address* could be an abbreviated way of writing *$customer.getAddress()*. When your page is requested, Velocity will determine which of these two possibilities ma [...]
+Take the first example, *${customer.Address}*. It can have two meanings. It can mean, Look in the hashtable identified as *customer* and return the value associated with the key *Address*. But it can also be referring to a method (references that refer to methods will be discussed in the next section); *${customer.Address}* could be an abbreviated way of writing *${customer.getAddress()}*. When your page is requested, Velocity will determine which of these two possibilities makes sense,  [...]
 
 ### Methods
 
-A method is defined in the Java code and is capable of doing something useful, like running a calculation or arriving at a decision. Methods are references that consist of a leading "$" character followed a VTL Identifier, followed by a VTL *Method Body*. A VTL Method Body consists of a VTL Identifier followed by an left parenthesis character ("("), followed by an optional parameter list, followed by right parenthesis character (")"). These are examples of valid method references in the VTL:
+A method is defined in the Java code and is capable of doing something useful, like running a calculation or arriving at a decision. Methods are references that consist of a leading "$" character then an expression enclosed by *{* and *}*: a VTL Identifier, followed by a VTL *Method Body*. A VTL Method Body consists of a VTL Identifier followed by an left parenthesis character ("("), followed by an optional parameter list, followed by right parenthesis character (")"). These are examples [...]
 
     :::velocity
-    $customer.getAddress()
-    $purchase.getTotal()
-    $page.setTitle( "My Home Page" )
-    $person.setAttributes( ["Strange", "Weird", "Excited"] )
+    ${customer.getAddress()}
+    ${purchase.getTotal()}
+    ${page.setTitle( "My Home Page" )}
+    ${person.setAttributes( ["Strange", "Weird", "Excited"] )}
 
-The first two examples -- *$customer.getAddress()* and *$purchase.getTotal()* -- may look similar to those used in the Properties section above, *$customer.Address* and *$purchase.Total*. If you guessed that these examples must be related some in some fashion, you are correct!
+The first two examples -- *${customer.getAddress()}* and *${purchase.getTotal()}* -- may look similar to those used in the Properties section above, *${customer.Address}* and *${purchase.Total}*. If you guessed that these examples must be related some in some fashion, you are correct!
 
-VTL Properties can be used as a shorthand notation for VTL Methods. The Property *$customer.Address* has the exact same effect as using the Method *$customer.getAddress()*. It is generally preferable to use a Property when available. The main difference between Properties and Methods is that you can specify a parameter list to a Method.
+VTL Properties can be used as a shorthand notation for VTL Methods. The Property *${customer.Address}* has the exact same effect as using the Method *${customer.getAddress()}*. It is generally preferable to use a Property when available. The main difference between Properties and Methods is that you can specify a parameter list to a Method.
 
-The shorthand notation can be used for the following Methods
+The property shorthand can be used for the following Methods
 
     :::velocity
-    $sun.getPlanets()
-    $annelid.getDirt()
-    $album.getPhoto()
+    ${sun.getPlanets()}
+    ${annelid.getDirt()}
+    ${album.getPhoto()}
 
 We might expect these methods to return the names of planets belonging to the sun, feed our earthworm, or get a photograph from an album. Only the long notation works for the following Methods.
 
     :::velocity
-    $sun.getPlanet( ["Earth", "Mars", "Neptune"] )
+    ${sun.getPlanet( ["Earth", "Mars", "Neptune"] )}
     ## Can't pass a parameter list with $sun.Planets
-    
-    $sisyphus.pushRock()
+
+    ${sisyphus.pushRock()}
     ## Velocity assumes I mean $sisyphus.getRock()
-    
-    $book.setTitle( "Homage to Catalonia" )
+
+    ${book.setTitle( "Homage to Catalonia" )}
     ## Can't pass a parameter
 
 All array references are treated as if they are fixed-length lists. This means that you can call java.util.List methods and properties on array references.  So, if you have a reference to an array (let's say this one is a String[] with three values), you can do:
 
     :::velocity
-    $myarray.isEmpty() or $myarray.empty
-    $myarray.size()
-    $myarray.get(2)
-    $myarray.set(1, 'test')
+    ${myarray.isEmpty()} or ${myarray.empty}
+    ${myarray.size()}
+    ${myarray.get(2)}
+    ${myarray.set(1, 'test')}
 
-Velocity also supports vararg methods. A method like `azpublic void setPlanets(String... planets)` or even just `public void setPlanets(String[] planets)` can now accept any number of arguments when called in a template.
+Velocity also supports vararg methods. A method like `public void setPlanets(String... planets)` or even just `public void setPlanets(String[] planets)` can now accept any number of arguments when called in a template.
 
     :::velocity
-    $sun.setPlanets('Earth', 'Mars', 'Neptune')
-    $sun.setPlanets('Mercury')
-    $sun.setPlanets()
+    ${sun.setPlanets('Earth', 'Mars', 'Neptune')}
+    ${sun.setPlanets('Mercury')}
+    ${sun.setPlanets()}
     ## Will just pass in an empty, zero-length array
 
 As of Velocity 2.0, method calls now provides implicit conversions between all Java basic builtin types: numbers, booleans and strings.
@@ -244,21 +247,21 @@ The final value resulting from each and every reference (whether variable, prope
 
 ### Index Notation
 
-Using the notation of the form `$foo[0]` can be used to access a given index of an object.  This form is synonymous with calling the get(Object) method on a given object i.e, `$foo.get(0)`, and provides essentially a syntactic shorthand for such operations. Since this simply calls the get method all of the following are valid uses:
+Using the notation of the form `${foo[0]}` can be used to access a given index of an object.  This form is synonymous with calling the get(Object) method on a given object i.e, `$foo.get(0)`, and provides essentially a syntactic shorthand for such operations. Since this simply calls the get method all of the following are valid uses:
 
     :::velocity
-    $foo[0]       ## $foo takes in an Integer look up
-    $foo[$i]      ## Using another reference as the index   
-    $foo["bar"]   ## Passing a string where $foo may be a Map
+    ${foo[0]}       ## $foo takes in an Integer look up
+    ${foo[$i]}      ## Using another reference as the index
+    ${foo["bar"]}   ## Passing a string where $foo may be a Map
 
 The bracketed syntax also works with Java arrays since Velocity wraps arrays in an access object that provides a `get(Integer)` method which returns the specified element.
 
 The bracketed syntax is valid anywhere `.get` is valid, for example:
 
     :::velocity
-    $foo.bar[1].junk
-    $foo.callMethod()[1]
-    $foo["apple"][4]
+    ${foo.bar[1].junk}
+    ${foo.callMethod()[1]}
+    ${foo["apple"][4]}
     
 A reference can also be set using index notation, for example:
 
@@ -271,16 +274,14 @@ The specified element is set with the given value. Velocity tries first the 'set
 
 ## Formal Reference Notation
 
-Shorthand notation for references was used for the examples listed above, but there is also a formal notation for references, which is demonstrated below:
+We have already used the formal `${ }` notation for property and method references, where it is the recommended form since Velocity 2.5:
 
     :::velocity
     ${mudSlinger}
     ${customer.Address}
     ${purchase.getTotal()}
 
-In almost all cases you will use the shorthand notation for references, but in some cases the formal notation is required for correct processing.
-
-Suppose you were constructing a sentence on the fly where *$vice* was to be used as the base word in the noun of a sentence. The goal is to allow someone to choose the base word and produce one of the two following results: "Jack is a pyromaniac." or "Jack is a kleptomaniac.". Using the shorthand notation would be inadequate for this task. Consider the following example:
+The braces are also useful for a *plain* variable whenever it sits directly adjacent to text. Suppose you were constructing a sentence on the fly where *$vice* was to be used as the base word in the noun of a sentence. The goal is to allow someone to choose the base word and produce one of the two following results: "Jack is a pyromaniac." or "Jack is a kleptomaniac.". The brace-less notation would be inadequate for this task. Consider the following example:
 
     :::velocity
     Jack is a $vicemaniac.
@@ -292,15 +293,6 @@ There is ambiguity here, and Velocity assumes that *$vicemaniac*, not *$vice*, i
 
 Now Velocity knows that *$vice*, not *$vicemaniac*, is the reference. Formal notation is often useful when references are directly adjacent to text in a template.
 
-## Alternate values
-
-Formal reference notations can also be used to provide an *alternate value* whenever the boolean evaluation of a reference is false.
-
-    :::velocity
-    My name is ${name|'John Doe'}
-
-If $name is null, empty, false or zero (see [Conditionals](#conditionals)), then the altername string `'John Doe'` will be displayed.
-
 ## Quiet Reference Notation
 
 When Velocity encounters an undefined reference, its normal behavior is to output the image of the reference. For example, suppose the following reference appears as part of a VTL template.
@@ -320,6 +312,16 @@ Formal and quiet reference notation can be used together, as demonstrated below.
     :::html+velocity
     <input type="text" name="email" value="$!{email}"/>
 
+## Alternate Values
+
+A reference can name an alternate value, rendered in its place when the reference is null, false, zero or empty:
+
+    :::html+velocity
+    <input type="text" name="email" value="${email|'nobody@example.com'}"/>
+    Hello ${customer.name|$anonymous}!
+
+The alternate value is any valid VTL expression, evaluated only when needed. It can only be written in the formal notation, `${ ... }`, and combines with the quiet notation: `$!{email|$fallback}` renders nothing when both are unset.
+
 ## Strict Rendering Mode
 
 The strict rendering mode is activated by setting the velocity configuration property 'runtime.strict_mode.enable' to true.  The general intent of this setting is to make Velocity behave more strictly in cases that are undefined or ambiguous, similar to a programming language, which may be more appropriate for some uses of Velocity. In such undefined or ambiguous cases Velocity will throw an exception.  The following discussion outlines the cases in which strict behavior is different fro [...]
@@ -337,9 +339,9 @@ In the following examples $bar is defined but $foo is not, and all these stateme
 Also, The following statements show examples in which Velocity will throw an exception when attempting to call methods or properties that do not exist. In these examples $bar contains an object that defines a property 'foo' which returns a string, and 'retnull' which returns null.
 
     :::velocity
-    $bar.bogus          ## $bar does not provide property bogus, Exception
-    $bar.foo.bogus      ## $bar.foo does not provide property bogus, Exception
-    $bar.retnull.bogus  ## cannot call a property on null, Exception</pre>
+    ${bar.bogus}          ## $bar does not provide property bogus, Exception
+    ${bar.foo.bogus}      ## $bar.foo does not provide property bogus, Exception
+    ${bar.retnull.bogus}  ## cannot call a property on null, Exception</pre>
 
 In general strict rendering mode behavior is true for all situations in which references are used except for a special case within the #if directive.  If a reference is used within a #if or #elseif directive without any methods or properties, and if it is not being compared to another value, then undefined references are allowed.  This behavior provides an easy way to test if a reference is defined before using it in a template.  In the following example where $foo is not defined the sta [...]
 
@@ -382,7 +384,7 @@ Now that you are familiar with references, you can begin to apply them effective
 
 These examples illustrate alternative uses for the same references. Velocity takes advantage of Java's introspection and bean features to resolve the reference names to both objects in the Context as well as the objects methods. It is possible to embed and evaluate references almost anywhere in your template.
 
-Velocity, which is modelled on the Bean specifications defined by Sun Microsystems, is case sensitive; however, its developers have strove to catch and correct user errors wherever possible. When the method *getFoo()* is referred to in a template by `$bar.foo`, Velocity will first try `$getfoo`. If this fails, it will then try `$getFoo`. Similarly, when a template refers to `$bar.Foo`, Velocity will try *$getFoo()* first and then try *getfoo()*.
+Velocity, which is modelled on the Bean specifications defined by Sun Microsystems, is case sensitive; however, its developers have strove to catch and correct user errors wherever possible. When the method *getFoo()* is referred to in a template by `${bar.foo}`, Velocity will first try `getfoo`. If this fails, it will then try `getFoo`. Similarly, when a template refers to `${bar.Foo}`, Velocity will try *getFoo()* first and then try *getfoo()*.
 
 Note: *References to instance variables in a template are not resolved.* Only references to the attribute equivalents of JavaBean getter/setter methods are resolved (i.e. `$foo.Name` does resolve to the class Foo's `getName()` instance method, but not to a public `Name` instance variable of Foo).
 
@@ -614,7 +616,7 @@ Lets say that *$allProducts* is a Hashtable. If you wanted to retrieve the key v
     :::html+velocity
     <ul>
     #foreach( $key in $allProducts.keySet() )
-        <li>Key: $key -> Value: $allProducts.get($key)</li>
+        <li>Key: $key -> Value: ${allProducts.get($key)}</li>
     #end
     </ul>
 
@@ -623,7 +625,7 @@ Velocity provides an easy way to get the loop counter so that you can do somethi
     :::html+velocity
     <table>
     #foreach( $customer in $customerList )
-        <tr><td>$foreach.count</td><td>$customer.Name</td></tr>
+        <tr><td>${foreach.count}</td><td>${customer.Name}</td></tr>
     #end
     </table>
 
@@ -653,7 +655,7 @@ If you want to stop looping in a foreach from within your template, you can now
         #if( $foreach.count > 5 )
             #break
         #end
-        $customer.Name
+        ${customer.Name}
     #end
 
 ### Include
diff --git a/src/content/engine/devel/vtl-reference.mdtext b/src/content/engine/devel/vtl-reference.mdtext
index 41b2864a..1f473daf 100644
--- a/src/content/engine/devel/vtl-reference.mdtext
+++ b/src/content/engine/devel/vtl-reference.mdtext
@@ -18,63 +18,53 @@ In the following syntax references, *identifier* refers to:
 
 that is, a letter or an underscore followed by any number of letters, numbers and underscores.
 
-If the `parser.allow_hyphen_in_identifiers` configuration value is set to true, then the **-** hyphen is also allowed in identifiers (and must be surrounded by spaces to be interpreted as an arithmetic minus operator).
+If the `parser.allow_hyphen_in_identifiers` configuration value is set to true (*deprecated since 2.5*), then the **-** hyphen is also allowed in identifiers (and must be surrounded by spaces to be interpreted as an arithmetic minus operator).
 
 ### Variables
 
 Notation:
 
-**$** <span class="blue">[</span> **!** <span class="blue">]</span> <span class="blue">[</span> **{** <span class="blue">]</span> *identifier* <span class="blue">[</span> <span class="blue">[</span> **|** *alternate value* <span class="blue">]</span> **}** <span class="blue">]</span>
-
-Usage:
-
-+ *alternate value*: alternate expression to use if the reference is null, empty, false or zero
+**$** <span class="blue">[</span> **!** <span class="blue">]</span> <span class="blue">[</span> **{** <span class="blue">]</span> *identifier* <span class="blue">[</span> **}** <span class="blue">]</span>
 
 Examples:
 
 + Shorthand notation: `$mudSlinger_9`
-+ Silent Shorthand notation: `$!mudSlinger_9`
++ Silent shorthand notation: `$!mudSlinger_9`
 + Formal notation: `${mudSlinger_9}`
-+ Silent Formal notation: `$!{mudSlinger_9}`
-+ Alternate value: `${mudSlinger_9|$otherWheels}`
-
-*Note that for backward compatibility reasons, it's possible to enable '**`-`**' as a valid character in variables identifiers, [see the parser configuration section](configuration.html#parser-configuration).*
++ Silent formal notation: `$!{mudSlinger_9}`
++ Formal notation with an alternate value: `${mudSlinger_9|$otherWheels}` — rendered when the reference is null, false, zero or empty; the right-hand side is any valid VTL expression
 
 ### Properties
 
 Notation:
 
-**$** <span class="blue">[</span> **{** <span class="blue">]</span> *identifier* **.** *identifier* <span class="blue">[</span> <span class="blue">[</span> **|** *alternate value* <span class="blue">]</span> **}** <span class="blue">]</span>
-
-Usage:
-
-+ *alternate value*: alternate expression to use if the property is null, empty, false or zero
+**${** *identifier* **.** *identifier* **}**
 
 Examples:
 
-+ Regular Notation: `$customer.Address`
-+ Formal Notation: `${purchase.Total}`
-+ Alternate Value: `${person.name|'John Doe'}`
++ Formal notation: `${customer.Address}`
++ Formal notation: `${purchase.Total}`
++ Informal notation: `$customer.Address`
++ With an alternate value: `${person.name|'John Doe'}`
 
 ### Methods
 
 Notation:
 
-**$** <span class="blue">[</span> **{** <span class="blue">]</span> *identifier* **.** *identifier* **(** <span class="blue">[</span> *parameter list...* <span class="blue">]</span> **)** <span class="blue">[</span> <span class="blue">[</span> **|** *alternate value* <span class="blue">]</span> **}** <span class="blue">]</span>
+**${** *identifier* **.** *identifier* **(** <span class="blue">[</span> *parameter list...* <span class="blue">]</span> **)** **}**
 
 Usage:
 
-+ *alternate value*: alternate expression to use if the method returns null, empty, false or zero
-+ *parameter list*: optional coma-separated list of expressions
++ *parameter list*: optional comma-separated list of expressions
 
 Examples:
 
-+ Regular Notation: `$customer.getAddress()`
-+ Formal Notation: `${purchase.getTotal()}`
-+ Regular Notation with Parameter List: `$page.setTitle( "My Home Page" )`
-+ Alternate value: `${page.getTitle()|'Blank Page'}`
++ Formal notation: `${customer.getAddress()}`
++ Formal notation with parameter list: `${page.setTitle( "My Home Page" )}`
++ Informal notation: `$customer.getAddress()` (formal notation is preferred)
++ With an alternate value: `${page.getTitle()|'Blank Page'}`
 
-VTL Properties can be used as a shorthand notation for VTL Methods that take *get* and *set*. Either *$object.getMethod()* or *$object.setMethod()* can be abbreviated as *$object.Method*. It is generally preferable to use a Property when available. The main difference between Properties and Methods is that you can specify a parameter list to a Method.
+VTL Properties can be used as a shorthand notation for VTL Methods that take *get* and *set*. Either *${object.getMethod()}* or *${object.setMethod()}* can be abbreviated as *${object.Method}*. It is generally preferable to use a Property when available. The main difference between Properties and Methods is that you can specify a parameter list to a Method.
 
 Each method argument can be any valid VTL expression.