peacetrue
peacetrue

Reputation: 319

velocity Implementing nested variable resolution

I want to generate controller layer code through velocity. I generate a mapping method:

@ResponseBody
@PostMapping(value = "\\${peacetrue.${moduleName}.urls.add}")
public ${ModuleName}VO add(${ModuleName}Add params) {
    logger.info("add record[{}]", params);
    return ${moduleName}Service.add(params);
}

and then I got exception:

{DomainName}Controller.java.vm[line 18, column 39]
Was expecting one of:
    "[" ...
    "|" ...
    "}" ...
    "}" ...

Then I wrote a unit test:

    @Test
    public void translate() {
        Velocity.init();

        Map<String, Object> singletonMap = Collections.singletonMap("foo", "bar");
        StringWriter stringWriter = new StringWriter();
        Velocity.evaluate(new VelocityContext(singletonMap), stringWriter, "log", "$foo");
        Assert.assertEquals("bar", stringWriter.toString());
        stringWriter = new StringWriter();
        Velocity.evaluate(new VelocityContext(singletonMap), stringWriter, "log", "\\${com.${foo}.name}");
        Assert.assertEquals("${com.bar.name}", stringWriter.toString());
    }

So what should i do?

Upvotes: 0

Views: 370

Answers (2)

peacetrue
peacetrue

Reputation: 319

it can be achieved with implementation 'org.apache.velocity.tools:velocity-tools-generic:3.0'

   @Test
    public void translate() {
        VelocityEngine engine = new VelocityEngine();
        engine.init();

        Map<String, Object> singletonMap = Collections.singletonMap("foo", "bar");
        StringWriter stringWriter = new StringWriter();
        Velocity.evaluate(new VelocityContext(singletonMap), stringWriter, "log", "$foo");
        Assert.assertEquals("bar", stringWriter.toString());

        stringWriter = new StringWriter();
        ToolManager manager = new ToolManager(true, true);
        manager.setVelocityEngine(engine);
        manager.configure(getEasyFactoryConfiguration());
        ToolContext context = manager.createContext();
        context.put("foo","bar");
        Velocity.evaluate(context, stringWriter, "log", "${esc.d}{com.${foo}.name}");
        Assert.assertEquals("${com.bar.name}", stringWriter.toString());
    }

    private EasyFactoryConfiguration getEasyFactoryConfiguration() {
        EasyFactoryConfiguration config = new EasyFactoryConfiguration();
        config.toolbox("application").tool(EscapeTool.class);
        return config;
    }

Upvotes: 0

Claude Brisson
Claude Brisson

Reputation: 4130

You can use the #evaluate() directive like this (at least since v1.7):

@PostMapping("#evaluate("\$peacetrue.${moduleName}.urls.add")")

or (for prior versions) like this:

@PostMapping("#set($d='$')#evaluate("${d}peacetrue.${moduleName}.urls.add")")

Or if the EscapeTool is present in the context :

@PostMapping("#evaluate("${esc.dollar}peacetrue.${moduleName}.urls.add")")

Or if $peacetrue has a standard getter for the module (like .getFoo() or get('foo') as a Map) :

@PostMapping("$peacetrue.get($moduleName).urls.add")

Upvotes: 1

Related Questions