Search code examples
javajavadocmustache

Implementing a lambda function with JMustache in java


I am following the documentation for JMustache: https://github.com/samskivert/jmustache. It says that we can call java functions and use them in Mustache templates. I have a lambda function like so

 Mustache.Lambda lookupInstance = new Mustache.Lambda() {
      public void execute (Template.Fragment frag, Writer out) throws IOException {
          out.write("<b>");
          frag.execute(out);
          out.write("</b>");
      }
    };

Then I have a template file that references the lambda like so

{{#myMethod}} is awesome.{{/myMethod}}

The output from the template is the following:

is awesome.

I was expecting

<b> is awesome.</b>

Can someone please help me figure out why the method isn't executing properly? I've been trying to debug this for quite some time now.It's odd that anything written to the Writer is ignored and that the frag.execute is the only thing working. What does that method do with the Writer? Is it ignored? Is there a different reference to write to inside of the frag?


Solution

  • The issue that I was running into was that Spring RestDocs uses Mustache as a transitive dependency. I had added JMustache to the pom.xml which was redundant. We can use a lambda function via the following

    @Override
      public void document(Operation operation) throws IOException {
        try {
        RestDocumentationContext context = (RestDocumentationContext) operation
            .getAttributes().get(RestDocumentationContext.class.getName());
    
        StandardWriterResolver writerResolver = new StandardWriterResolver(
            new RestDocumentationContextPlaceholderResolverFactory(),
            "UTF-8",
            new TemplateFormat() {
              @Override public String getId() { return outFileExt; }
              @Override public String getFileExtension() { return outFileExt; }
            });
       
        Map<String,Object> data = new HashMap<>(operation.getAttributes());
        data.put("myMethod", new MyMustacheLambda());
        
        
        TemplateEngine templateEngine = 
            (TemplateEngine) data
            .get(TemplateEngine.class.getName());
    
    
        try (Writer writer = writerResolver.resolve(
            operation.getName(), 
            outFileName,
            context)) {
          writer.append(templateEngine
                  .compileTemplate(this.templateName)
                  .render(data));
        }
        
        }
        catch (Throwable t) {
          t.printStackTrace();
        }
      }
    

    and implement the lambda function via

    import java.io.IOException;
    import java.io.Writer;
    import org.springframework.restdocs.mustache.Mustache.Lambda;
    import org.springframework.restdocs.mustache.Template.Fragment;
    
    public class MyMustacheLambda implements Lambda {
      
      @Override
      public void execute(Fragment fragment, Writer writer) throws IOException {
          String output = fragment.execute();
          writer.write("test");
      }
    
    }
    

    So we have to create a class that implements Lambda and overrides the execute method.