Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Change Mustache's compiler default null value

I have some issues overriding default configuration of Mustache for Spring MVC found here in my project.

My understanding is that mustache.java raises a MustacheException by default when the template founds a variable that is resolved to be null. I would like for the Mustache compiler to resolve such values as an empty String instead.

I tried using the nullValue(String nullValue) function to set the appropriate behavior as seen in the code below, but it doesn't seem to have any effect. I understand that the obvious solution is to set the phoneNumber attribute to an empty value, but I would really like to understand why this particular code doesn't work.

You'll find below the code I use to test this behavior, which includes an Employee entity that purposefully doesn't instantiate its phoneNumber member value in its constructor and the relevant code snippets.

pom.xml

<dependency>
  <groupId>com.github.sps.mustache</groupId>
  <artifactId>mustache-spring-view</artifactId>
  <version>1.3</version>
</dependency>
<!-- jmustache -->
<dependency>
  <groupId>com.samskivert</groupId>
  <artifactId>jmustache</artifactId>
  <version>1.10</version>
</dependency>
<!-- mustache.java -->
<dependency>
  <groupId>com.github.spullara.mustache.java</groupId>
  <artifactId>compiler</artifactId>
  <version>0.8.17</version>
</dependency>

Employee.java

public class Employee {

  protected String firstName;
  protected String lastName;
  protected String phoneNumber;

  public Employee() { }
  public Employee(firstName, lastName) {
    this.firstName = firstName;
    this.lastName = lastName;
  }

  // Getter and Setters for all attributes
}

getViewResolver

@Bean
public ViewResolver getViewResolver(ResourceLoader resourceLoader) {
  MustacheViewResolver mustacheViewResolver = new MustacheViewResolver();
  mustacheViewResolver.setPrefix("/src/main/resources/templates/");
  mustacheViewResolver.setSuffix(".html");
  mustacheViewResolver.setCache(false);
  mustacheViewResolver.setContentType("text/html;charset=utf-8");

  JMustacheTemplateLoader mustacheTemplateLoader = new JMustacheTemplateLoader();
  mustacheTemplateLoader.setResourceLoader(resourceLoader);

  JMustacheTemplateFactory mustacheTemplateFactory = new JMustacheTemplateFactory();
  mustacheTemplateFactory.setTemplateLoader(mustacheTemplateLoader);

  mustacheTemplateFactory.setCompiler(Mustache.compiler().nullValue(" "));

  mustacheViewResolver.setTemplateFactory(mustacheTemplateFactory);
  return mustacheViewResolver;
}

EmployeeController

@Autowired
private EmployeeRepository repository;

...

@RequestMapping(value = "/{id}", method = RequestMethod.GET)
public String viewEmployee(@PathVariable Long id, Model model) {
  model.addAttribute("employee", repository.findOne(id));
  return "employee_view";
}

employee_view.html

<!DOCTYPE html>
<html>
  <body>
  <ul>
    {{#employee}}
    <li> First Name: {{firstName}}
    <li> Last Name: {{lastName}}
    <li> Phone Number: {{phoneNumber}}
    {{/employee}}
  </ul>
  </body>
</html>
like image 557
eldruz Avatar asked Jun 04 '26 12:06

eldruz


1 Answers

I am using spring-boot.1.2.5.RELEASE now.

If you check out org.springframework.boot.autoconfigure.mustache.MustacheAutoConfiguration's source code (lines 73 ~ 78), you can tell defaultValue is not configurable.

May be you should make a new your own Spring Boot starter to fix it. Or you can use FreeMarker or Velocity instead it.

Or you can hack it with a BeanPostProcessor when ApplicationContext starts up.

Like this:

@Bean
public BeanPostProcessor mutacheHackerBeanPostProcessor() {
    return new BeanPostProcessor() {
        private static final String BEAN_NAME = "mustacheCompiler";

        @Override
        public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
            return bean;
        }

        @Override
        public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
            if (ClassUtils.isAssignable(bean.getClass(), Mustache.Compiler.class) || BEAN_NAME.equals(beanName)) {
                System.out.println("----------");
                System.out.println("hack ok!!!");
                System.out.println("----------");
                Mustache.Compiler compiler = (Mustache.Compiler) bean;
                return compiler.defaultValue("").nullValue("");
            }

            return bean;
        }
    };
}
like image 200
Zhuo YING Avatar answered Jun 06 '26 06:06

Zhuo YING



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!