Skip to content

Java handlebars to replace a literal with slash

I want to use handlerbars (com.github.jknack) in java to replace values in a string as follows:

@Test
public void handlebarTest() throws IOException {
  var map = new HashMap<String, Object>();
  var input = "testing handlerbars {{ test }} - {{ foo/bar }}";
  var handlebars = new Handlebars();
  map.put("test","testValue");
  map.put("foo", new HashMap<>().put("bar", "fooValue")); //does not work
  map.put("foo/bar", "fooValue"); //does not work
  Template template = handlebars.compileInline(input);
  var result = template.apply(map);

  System.out.println(result);
}

The output of this test is: testing handlerbars testValue -

The expected output would be: testing handlerbars testValue - fooValue

The replacement works fine when the literal is simple ( {{ test }} ), but it does not work when the literal contains a slash( {{ foo/bar }}). Is there a way to just replace the string "foo/bar" with "fooValue" using handlebars?

Answer

The official HashMap documentation states the following about the return value of HashMap#put:

Returns: the previous value associated with key, or null if there was no mapping for key. (A null return can also indicate that the map previously associated null with key.)

That means that new HashMap<>().put("bar", "fooValue") will always evaluate to null.

In order to fix that, you could of course do the following:

var fooMap = new HashMap<String, String>();
fooMap.put("bar", "fooValue");
map.put("foo", fooMap);

However, since Java 9, there are static factory methods to the most common Collections (Set, List and Map). Using these new factory methods, you could replace new HashMap<>().put("bar", "fooValue") with Map.of("bar", "fooValue") which creates an immutable Map with one entry ("bar" -> "fooValue").

This should be working, so you can safely remove the line map.put("foo/bar", "fooValue"); // does not work.