1

Why velocity gives the following output for the string

VelocityContext vc = new VelocityContext();
vc.put("foo", "bar");
String inString = "THis is ${{foo}} and this is ${foo}.Hello and ${foo}-Hello";

StringWriter sw = new StringWriter();
ve.evaluate(vc, sw, "Tag", inString);

Output:

THis is ${{} and this is bar.Hello and bar-Hello 

I was expecting it would either print ${{foo}} or {bar}, why ${{}? Would double curly act as escape character?

I'm using this under strict reference mode set as true. And I neither see an exception nor I see it print it as is and that's what is confusing me.

Ori Marko
  • 56,308
  • 23
  • 131
  • 233
vinod ep
  • 51
  • 1
  • 7

2 Answers2

0

Velocity Variables or VTL Identifier

Must start with an alphabetic character (a .. z or A .. Z). The rest of the characters are limited to the following types of characters:

  • alphabetic (a .. z, A .. Z)
  • numeric (0 .. 9)
  • hyphen ("-")
  • underscore ("_")

You are using Formal Reference Notation as ${varName}

${{foo}} - so velocity try to get variable {foo} which is invalid VTL Identifier so it doesn't try to load the variable.

It probably then try to reference it as a JSON map {"a":"b"} and failed again, probably only { is accepted, so you remain with:

${{}

I tested your template in new velocity 2.0 and this issue isn't reproduce (in strict or non strict mode) Output:

THis is ${{foo}} and this is bar.Hello and bar-Hello 

So you have now a reason to upgrade to velocity 2.0.

Ori Marko
  • 56,308
  • 23
  • 131
  • 233
  • Sorry I forgot to mention strict reference mode, I'm under strict reference mode and it doesn't throw exception for this case. Neither does it print {foo}, so is the source of my confusion – vinod ep Nov 01 '17 at 17:34
0

Well, you made me look into the code and I'm not sure if I understood it correctly. The problem seems to be that in ${...}, the xxx is treated as an ASTReference, which then gets tokenized differently than a standalone string "{bar}". Specifically, it get tokenized into 3 tokens {, bar and }. Then the engine tries to find the so-called root of the reference (in ${x}, the root is x), does not recognize the pattern and goes into a fallback reference type RUNT, which says that the first token, i.e. "{" matters. This way "{bar}" becomes "{".

In other words, the expression ${{bar}} does not make sense and Velocity fails to throw an error here. In other nonsensical combinations like ${[bar]} it actually throws an error.

David Vonka
  • 511
  • 4
  • 14
  • Agreed, I rely on Velocity's strict reference mode to sort of validate that no weird identifiers are left un-replaced . With this behavior, I will have to validate separately for this case if it happens to be. That sucks – vinod ep Nov 04 '17 at 23:21