Thymeleaf : template might not exist or might not be accessible by any of the configured Template Resolvers - spring

I have this code:
private static final String EMAIL_INLINEIMAGE_TEMPLATE_NAME = "templateemail.html";
#Bean
public TemplateEngine emailTemplateEngine() {
templateEngine = new SpringTemplateEngine();
templateEngine.addTemplateResolver(this.htmlTemplateResolver());
)
templateEngine.setTemplateEngineMessageSource(this.messageSource);
return templateEngine;
}
private static ITemplateResolver htmlTemplateResolver() {
final ClassLoaderTemplateResolver templateResolver = new ClassLoaderTemplateResolver();
templateResolver.setOrder(Integer.valueOf(0));
templateResolver.setPrefix("classpath:/templates/");
templateResolver.setSuffix(".html");
templateResolver.setTemplateMode(TemplateResolver.DEFAULT_TEMPLATE_MODE);
templateResolver.setCharacterEncoding("UTF-8");
templateResolver.setCacheable(false);
return templateResolver;
}
public void sendEmail(String emailAddress, String title, String body, Locale local, String image) {
if (Boolean.parseBoolean(isEmailServiceActivated)) {
MimeMessage mimeMessage = mailSender.createMimeMessage();
MimeMessageHelper mailMsg = new MimeMessageHelper(mimeMessage);
try {
mailMsg.setFrom(EMAIL_USERNAME);
mailMsg.setTo(emailAddress);
mailMsg.setSubject(title);
// Prepare the evaluation context
ctx.setLocale(local);
ctx.setVariable("imageHeaderResourceName", HEADER_LOGO_IMAGE);
ctx.setVariable("body", body);
ctx.setVariable("imageResourceName", image);
final String htmlContent = this.templateEngine.process(new ClassPathResource(EMAIL_INLINEIMAGE_TEMPLATE_NAME).getPath(), ctx);
mailMsg.setText(htmlContent, true );
mailMsg.addInline(HEADER_LOGO_IMAGE, new ClassPathResource(HEADER_LOGO_IMAGE ) , PNG_MIME);
mailMsg.addInline(image, new ClassPathResource(image) , PNG_MIME);
} catch (MessagingException e) {
e.printStackTrace();
}
mailSender.send(mimeMessage);
}
}
I have templateemail.html file under /templates/ directory. when I launch the sending email method I have this exception :
org.thymeleaf.exceptions.TemplateInputException: Error resolving template "templateemail.html", template might not exist or might not be accessible by any of the configured Template Resolvers
I dont know if it's because the templateEngine can't find my file (I try even with tomcat absolute path and /bin directory but no way ) or I haven't configure the right Template Resolver.
Thank you very much for your help. I

It work now by deleting ".html" in the name of template (the file has the html extension)
private static final String EMAIL_INLINEIMAGE_TEMPLATE_NAME = "templateemail"

Note the non-cross-platform behavior that can occure: on Windows the CamelCase.html template was resolved, but not on Ubuntu linux! There I had to rename it to camelcase.html, all chars in lower case

I had the same issue recently. My problem was that my template had references to other templates that started with /.
For example:
<html ... th:include="/internal/layout-normal :: page"> <-- failed
<html ... th:include="internal/layout-normal :: page"> <-- worked
Both variants worked without problems when I run the application from IntelliJ. However, when packaged and run via java -jar the first line failed.
Removing the / solved the problem for me

Thymeleaf picks up the html files from resources/templates path by using the name of html file.
Hence in this case just removing .html extension from the filename would work!

Related

Spring boot ResourceUtils read file content is giving Path Traversal vulnerability

I am building a spring boot application where i need to read json files for my component tests. I have a utility method which takes the name of the file and reads the content using ResourceUtils. Here is the code:
public static String getContent(String path) throws IOException {
File file = ResourceUtils.getFile(MyTest.class.getResource(path));
String content = new String(Files.readAllBytes(file.toPath()));
return content;
}
The checkmarx is reporting the above code as "This may cause a Path
Traversal vulnerability."
How to fix this?
Thanks
See this example for path traversal vulnerability Path Traversal
To fix this change it something like
private static final String BASE_PATH ="/yourbasepath/somewherewherefileisstored";
public static String getContent(String path) throws IOException {
File file = new File(BASE_PATH, path);
if (file.getCanonicalPath().startsWith(BASE_PATH)){
String content = new String(Files.readAllBytes(file.toPath()));
return content;
}
else{
//throw some error
}
}

Spring Boot, Thymeleaf and strings

Hello I'm using spring boot 2.4.x and I want to use thymeleaf as my template engine.
I've added the thymeleaf starter and I've the following test
#Test
void name() {
StringTemplateResolver stringTemplateResolver = new StringTemplateResolver();
SpringTemplateEngine templateEngine = new SpringTemplateEngine();
templateEngine.addTemplateResolver(stringTemplateResolver);
Context ctx = new Context();
ctx.setVariable("franco", "prova");
String processedTemplate = templateEngine.process("<html>${franco}</html>", ctx);
Assertions.assertThat(processedTemplate).isEqualTo("<html>prova</html>");
}
but the templateEngine is not substituting the variable and the value of the processedTemplate variable is the same as the input string.
What's my fault?
Thank you
Thymeleaf won't process variables directly in HTML. You either have to use the text inlining syntax:
<html>[[${franco}]]</html>
or do it the standard way (which is to use attributes prefixed with th:) like this:
<html th:text="${franco}" />
or
<html><span th:text="${franco}" /></html>
(Also, as a side note StringTemplateResolver is the default resolver, so you don't have to configure it. Your complete code can look like this.)
#Test
void name() {
SpringTemplateEngine templateEngine = new SpringTemplateEngine();
Context ctx = new Context();
ctx.setVariable("franco", "prova");
String processedTemplate = templateEngine.process("<html>[[${franco}]]</html>", ctx);
Assertions.assertThat(processedTemplate).isEqualTo("<html>prova</html>");
}

How to Load templates from external folder using Thymeleaf

I'm working with spring boot and thymeleaf to generate Documents from html templates.
As the templates continuously changes, i want ti to load templates from an external just to add or remove templates from there instead of redeploy the application.
As a POC, when using /resources folder works fine.
This is the error:
Error resolving template "voucher", the template might not exist or might
not be accessible by any of the configured Template Resolvers
This is the context:
applycation.yml
spring:
thymeleaf:
prefix: file:///${PARAMETERS_DIRECTORY_TEMPLATES:/home/app/templates/}
check-template-location: true
suffix=: .html
mode: HTML
encoding: UTF-8
This is my Method:
Where templateName is the template filename and parameters is just a map who has the values to be replaced by the engine.
#Override
public String buildHtmlFromTemplate(String templateName, Map<String, String> parameters) {
TemplateEngine templateEngine = new TemplateEngine();
FileTemplateResolver templateResolver = new FileTemplateResolver ();
templateResolver.setOrder(templateEngine.getTemplateResolvers().size());
templateResolver.setCacheable(false);
templateResolver.setCheckExistence(true);
templateEngine.setTemplateResolver(templateResolver);
return templateEngine.process(templateName, this.resolveHtmlTemplateAttributesContext(parameters));
}
NOTE:
I removed tha applycation yml thymeleaf configs and implemented next code but the error persists.
#Override
public String buildHtmlFromTemplate(String templateName, Map<String, String> parameters) {
TemplateEngine templateEngine = new TemplateEngine();
FileTemplateResolver templateResolver = new FileTemplateResolver ();
templateResolver.setPrefix("/home/skeeter/templates/");
templateResolver.setSuffix(".html");
templateResolver.setTemplateMode("HTML");
templateResolver.setOrder(templateEngine.getTemplateResolvers().size());
templateResolver.setCharacterEncoding("UTF-8");
templateResolver.setCacheable(false);
templateResolver.setCheckExistence(true);
templateEngine.setTemplateResolver(templateResolver);
return templateEngine.process(templateName, this.resolveHtmlTemplateAttributesContext(parameters));
}
0
Curiously, the issue was solved using this code and the /usr/app/templates created with sudo.
I think it was only a permissions issue
.....
#Value("${parameters.directory.templates}")
private String templatesDirectory;
.....
#Override
public String buildHtmlFromTemplate(String templateName, Map<String, String> parameters) {
TemplateEngine templateEngine = new TemplateEngine();
FileTemplateResolver templateResolver = new FileTemplateResolver ();
templateResolver.setPrefix(templatesDirectory);
templateResolver.setSuffix(".html");
templateResolver.setTemplateMode("HTML");
templateResolver.setOrder(templateEngine.getTemplateResolvers().size());
templateResolver.setCharacterEncoding("UTF-8");
templateResolver.setCacheable(false);
templateResolver.setCheckExistence(true);
templateEngine.setTemplateResolver(templateResolver);
return templateEngine.process(templateName, this.resolveHtmlTemplateAttributesContext(parameters));
}
In my case I was using the ClassLoaderTemplateResolver, but after I changed it to FileTemplateResolver I can use the absolute path and it works fine.
Double check that you have read permissions in the directory where you have the templates.

spring boot calling thymeleaf template failed

im getting this error i searched on the same issues like mine on stack and i have foudn that i shouldn t put .html when calling it but im getting the same error :
`Caused by: org.thymeleaf.exceptions.TemplateInputException: Error resolving template "orderConfirmationEmailTemplate", template might not exist or might not be accessible by any of the configured Template Resolver`s
my mail constructor :
#Component
public class MailConstructor {
#Autowired
private Environment env;
#Autowired
private TemplateEngine templateEngine;
public SimpleMailMessage constructNewUserEmail(User user, String password) {
String message="\nPlease use the following credentials to log in and edit your personal information including your own password."
+ "\nUsername:"+user.getUsername()+"\nPassword:"+password;
SimpleMailMessage email = new SimpleMailMessage();
email.setTo(user.getEmail());
email.setSubject("Le's Bookstore - New User");
email.setText(message);
email.setFrom(env.getProperty("support.email"));
return email;
}
public MimeMessagePreparator constructOrderConfirmationEmail (User user, Order order, Locale locale) {
Context context = new Context();
context.setVariable("order", order);
context.setVariable("user", user);
context.setVariable("cartItemList", order.getCartItemList());
String text = templateEngine.process("orderConfirmationEmailTemplate.html", context);
MimeMessagePreparator messagePreparator = new MimeMessagePreparator() {
#Override
public void prepare(MimeMessage mimeMessage) throws Exception {
MimeMessageHelper email = new MimeMessageHelper(mimeMessage);
email.setTo(user.getEmail());
email.setSubject("Order Confirmation - "+order.getId());
email.setText(text,true);
email.setFrom(new InternetAddress("alaaeddinezammel1993#gmail.com"));
}
};
return messagePreparator;
}
and im calling it from rest service:
mailSender.send(mailConstructor.constructOrderConfirmationEmail(user, order, Locale.ENGLISH));
shoppingCartService.clearShoppingCart(shoppingCart);
and im putting the file .html under package in the project
In your question, the TemplateEngine is auto wired so I cannot see how it is configured but it in order to discover your template from the location com.bookstore.domain.security.templates the configuration should look something like this:
#Bean
public TemplateEngine templateEngine() {
final SpringTemplateEngine templateEngine = new SpringTemplateEngine();
templateEngine.addTemplateResolver(templateResolver());
return templateEngine;
}
private ITemplateResolver templateResolver() {
final ClassLoaderTemplateResolver templateResolver = new ClassLoaderTemplateResolver();
templateResolver.setPrefix(“/com/bookstore/domain/security/templates“);
templateResolver.setSuffix(".html");
…
return templateResolver;
}
In this code I am configuring the TemplateEngine in code, perhaps you are using XML. Regardless of how you are configuring the TemplateEngine, you are clearly using Spring to do so (since you inject it into your MailConstructor), the key point here is that regardless of how you configure it you need to tell it where to find your template and the way to do that is to invoke the ITemplateResolver's setPrefix() method.
Plenty more details in the article titled Sending email in Spring with Thymeleaf in the Thymeleaf docs.
actually with my configuration putted in my question i just put the .html file under file called templates under resources and it works the mail is sent , spring boot is apparently auto configured with this path without configuring the
templateResolver

jersey-freemarker

I'm developing a small tool based on jersey and freemarker, which will enable designers to test there freemarker templates, locally, using some mok-objects.
I'm sorry to write here, but I cant find any documentation about it except some code and javadocs.
To do that I did the following:
1 Dependencies:
<dependency>
<groupId>com.sun.jersey.contribs</groupId>
<artifactId>jersey-freemarker</artifactId>
<version>1.9</version>
</dependency>
2 Starting grizzly, telling where to find freemarker templates:
protected static HttpServer startServer() throws IOException {
System.out.println("Starting grizzly...");
Map<String, Object> params = new HashMap<String, Object>();
params.put("com.sun.jersey.freemarker.templateBasePath", "/");
ResourceConfig rc = new PackagesResourceConfig("resource.package");
rc.setPropertiesAndFeatures(params);
HttpServer server = GrizzlyServerFactory.createHttpServer(BASE_URI, rc);
server.getServerConfiguration().addHttpHandler(
new StaticHttpHandler("/libs"), "/libs");
return server;
}
3 Creates the root resource and binds freemarker files:
#Context ResourceConfig resourceConfig;
#Path("{path: ([^\\s]+(\\.(?i)(ftl))$)}")
public Viewable renderFtl (#PathParam("path") String path) throws IOException {
Viewable view = new Viewable("/"+path);
return view;
}
Everything works fine, except that freemarker files are not rendered. I have an empty white page, but file exists and debugger enter inside renderFtl method right.
Do you know how can I do that?
I read a lot of articles here and around the web, but old posts only or articles talking about spring integration and I don't want to integrate it because I don't need it.
I really like Jersey, I think is one of the most complete and power framework on java world, but anytime I try to find documentation on specific features or contribs libraries, I'm lost... There no escape from groups forums :)
Where can I find a complete documentation about it?
Tanks a lot David
Updates:
Trying to solve I understood I cannot use built-in jersey support, because it needs to use files placed in resources tree. So What I did is to build freemarker configuration, in test for now, directly #runtime and returns a StreamingOutput object:
#Path("{path: ([^\\s]+(\\.(?i)(ftl))$)}")
public StreamingOutput renderFtl (#PathParam("path") String path) throws Exception {
Configuration cfg = new Configuration();
// Specify the data source where the template files come from.
// Here I set a file directory for it:
cfg.setDirectoryForTemplateLoading(new File("."));
// Create the root hash
Map<String, Object> root = new HashMap<String, Object>();
Template temp = cfg.getTemplate(path);
return new FTLOutput(root, temp);
}
FTLOutput is here:
This is not a good code, but is for test only...
class FTLOutput implements StreamingOutput {
private Object root;
private Template t;
public FTLOutput(Object root, Template t) {
this.root = root;
this.t = t;
}
#Override
public void write(OutputStream output) throws IOException {
Writer writer = new OutputStreamWriter(output);
try {
t.process(root, writer);
writer.flush();
} catch (TemplateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
I have no errors evidence on debug and freemarker tells me that template is found and rendered, but jersey still no give me a result...
I really don't know why!
Why are you using Jersey 1.9? 1.11 is already out, you should update if you can
Have you seen "freemarker" sample from Jersey? It demonstrates simple usecase of using freemarker with jersey.
Where are your resources?
Templates are being found by calling [LastMatchedResourceClass].getResources(...), so if your templates are not accessible as resources, they can't be rendered correctly. you can checkout Jersey source and place some breakpoints into FreemarkerViewProcessor, it should tell you where exactly the problem is..

Resources