java - Is there a way to call utility method in TEXT Thymeleaf template? - Stack Overflow

I have application aimed to transform API responses into human-readable text. For that purpose I call d

I have application aimed to transform API responses into human-readable text. For that purpose I call data from 3rd parties, build the model from it and run template against context through .thymeleaf.TemplateEngine.

Example:

public Optional<String> process(String template, Map<String, Object> model) {
        Context thymeleafContext = new Context();
        thymeleafContext.setVariables(model);

        try {
            return Optional.of(templateEngine.process(template, thymeleafContext););
        } catch (TemplateProcessingException e) {
            log.error(e.getMessage());
        }

        return Optional.empty();
    }

For that purpose I have a number of plaintext Thymeleaf templates .thymeleaf.templatemode.TemplateMode#TEXT (keep note this) placed into separate .txt files.

Let's assume I have template like this: Born year: [[${bornYear}}]]. Now I need to cast the value of bornYear variable into specific pattern. For that purpose I have utility method like this

public class Utils {

    private Utils() {}

    public static String cast(String source, String pattern) {
        return "<implement me>";
    }
}

and I assume I can execute this utility method in the template. However I can not make it possible, at least I get exception on template processing.

What I tried:

  • Template Born year: [[${Utils.cast(bornYear, 'dd-MM-yyyy')}]].
  • Template Born year: [[${T(com.example.Utils).cast(bornYear, 'dd-MM-yyyy')}]]. This leads to .thymeleaf.exceptions.TemplateProcessingException: Instantiation of new objects and access to static classes or parameters is forbidden in this context.
  • Define Utils as Spring Bean and adjust template in a way Born year: [[${utils.cast(bornYear, 'dd-MM-yyyy')}]] or Born year: [[${@utils.cast(bornYear, 'dd-MM-yyyy')}]]. This leads to Caused by: .springframework.expression.spel.SpelEvaluationException: EL1057E: No bean resolver registered in the context to resolve access to bean 'Utils'.

TemplateResolver configuration:

@Bean
public ClassLoaderTemplateResolver templateResolve() {
    ClassLoaderTemplateResolver templateResolver = new ClassLoaderTemplateResolver();
    templateResolver.setPrefix("templates/");
    templateResolver.setSuffix(".txt");
    templateResolver.setTemplateMode(TemplateMode.TEXT);
    templateResolver.setCharacterEncoding("UTF-8");
    templateResolver.setOrder(1);
    templateResolver.setCheckExistence(true);

    return templateResolver;
}

My questions are:

  1. Is that possible to call custom code considering I do use TemplateMode.TEXT?
  2. If yes, how to do it in a right way?
  3. Any suggestions?

Thank you in advance!

I have application aimed to transform API responses into human-readable text. For that purpose I call data from 3rd parties, build the model from it and run template against context through .thymeleaf.TemplateEngine.

Example:

public Optional<String> process(String template, Map<String, Object> model) {
        Context thymeleafContext = new Context();
        thymeleafContext.setVariables(model);

        try {
            return Optional.of(templateEngine.process(template, thymeleafContext););
        } catch (TemplateProcessingException e) {
            log.error(e.getMessage());
        }

        return Optional.empty();
    }

For that purpose I have a number of plaintext Thymeleaf templates .thymeleaf.templatemode.TemplateMode#TEXT (keep note this) placed into separate .txt files.

Let's assume I have template like this: Born year: [[${bornYear}}]]. Now I need to cast the value of bornYear variable into specific pattern. For that purpose I have utility method like this

public class Utils {

    private Utils() {}

    public static String cast(String source, String pattern) {
        return "<implement me>";
    }
}

and I assume I can execute this utility method in the template. However I can not make it possible, at least I get exception on template processing.

What I tried:

  • Template Born year: [[${Utils.cast(bornYear, 'dd-MM-yyyy')}]].
  • Template Born year: [[${T(com.example.Utils).cast(bornYear, 'dd-MM-yyyy')}]]. This leads to .thymeleaf.exceptions.TemplateProcessingException: Instantiation of new objects and access to static classes or parameters is forbidden in this context.
  • Define Utils as Spring Bean and adjust template in a way Born year: [[${utils.cast(bornYear, 'dd-MM-yyyy')}]] or Born year: [[${@utils.cast(bornYear, 'dd-MM-yyyy')}]]. This leads to Caused by: .springframework.expression.spel.SpelEvaluationException: EL1057E: No bean resolver registered in the context to resolve access to bean 'Utils'.

TemplateResolver configuration:

@Bean
public ClassLoaderTemplateResolver templateResolve() {
    ClassLoaderTemplateResolver templateResolver = new ClassLoaderTemplateResolver();
    templateResolver.setPrefix("templates/");
    templateResolver.setSuffix(".txt");
    templateResolver.setTemplateMode(TemplateMode.TEXT);
    templateResolver.setCharacterEncoding("UTF-8");
    templateResolver.setOrder(1);
    templateResolver.setCheckExistence(true);

    return templateResolver;
}

My questions are:

  1. Is that possible to call custom code considering I do use TemplateMode.TEXT?
  2. If yes, how to do it in a right way?
  3. Any suggestions?

Thank you in advance!

Share Improve this question asked Nov 19, 2024 at 16:09 Anton RusakouAnton Rusakou 151 silver badge4 bronze badges
Add a comment  | 

2 Answers 2

Reset to default 0

The way I would do this is...

  1. Change utils to be a regular object:

     public class Utils {
         public String cast(String source, String pattern) {
             return "<implement me>";
         }
     }
    
  2. Always put a utils onto your model:

     public Optional<String> process(String template, Map<String, Object> model) {
         Context thymeleafContext = new Context();
         model.put("utils", new Utils());
         thymeleafContext.setVariables(model);
    
  3. In your template, use it like this:

    Born year: [[${utils.cast(bornYear, 'dd-MM-yyyy')}]]
    

Another way you can do this, when instantiating your context add a ThymeleafEvaluationContext like this. You will have to get access to your Spring ApplicationContext as well.

public Optional<String> process(String template, Map<String, Object> model) {
    Context thymeleafContext = new Context();
    context.setVariable(ThymeleafEvaluationContext.THYMELEAF_EVALUATION_CONTEXT_CONTEXT_VARIABLE_NAME, new ThymeleafEvaluationContext(applicationContext, null));
    thymeleafContext.setVariables(model);

Then if you've annotated your utils class with @Component and made sure it is in a package that is being scanned by your configuration:

@Component
public class Utils {
    public String cast(String source, String pattern) {
        return "<implement me>";
    }
}

You will be able to access Beans in your templates like this:

Born year: [[${@utils.cast(bornYear, 'dd-MM-yyyy')}]]

To call a utility method within a TEXT Thymeleaf template, you need to expose the utility class (or its methods) as part of the context variables so that Thymeleaf can recognize and use it.

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1742414999a4439571.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信