Reputation: 10761
I have problem defining a ClassLoaderTemplateResolver
for emails and one ServletContextTemplateResolver
for web views. I getting the following error when trying to send emails:
HTTP Status 500 - Request processing failed; nested exception is
org.thymeleaf.exceptions.TemplateProcessingException: Resource resolution by ServletContext with
org.thymeleaf.resourceresolver.ServletContextResourceResolver can only be performed when context
implements org.thymeleaf.context.IWebContext [current context: org.thymeleaf.context.Context]
My WebMvcConfig looks like this:
private static final String VIEWS_PATH = "/WEB-INF/views/";
private static final String MAIL_PATH = "mail/";
@Bean
public ServletContextTemplateResolver templateResolver() {
final ServletContextTemplateResolver resolver = new ServletContextTemplateResolver();
resolver.setPrefix(VIEWS_PATH);
resolver.setSuffix(".html");
resolver.setTemplateMode("HTML5");
resolver.setCharacterEncoding("UTF-8");
resolver.setOrder(2);
resolver.setCacheable(false);
return resolver;
}
@Bean
public ClassLoaderTemplateResolver emailTemplateResolver() {
final ClassLoaderTemplateResolver resolver = new ClassLoaderTemplateResolver();
resolver.setPrefix(MAIL_PATH);
resolver.setSuffix(".html");
resolver.setTemplateMode("HTML5");
resolver.setCharacterEncoding("UTF-8");
resolver.setOrder(1);
return resolver;
}
@Bean
public SpringTemplateEngine templateEngine() {
final SpringTemplateEngine engine = new SpringTemplateEngine();
final Set<TemplateResolver> templateResolvers = new HashSet<TemplateResolver>();
templateResolvers.add(templateResolver());
templateResolvers.add(emailTemplateResolver());
engine.setTemplateResolvers(templateResolvers);
engine.addDialect(new SpringSocialDialect());
engine.addDialect(new SpringSecurityDialect());
return engine;
}
And my EmailService
like this:
@Service
public class EmailService {
@Autowired
private JavaMailSender mailSender;
@Autowired
private TemplateEngine templateEngine;
/*
* Send HTML mail with inline image
*/
public void sendEmailToBookSeller(
final ContactBookSellerForm form,
final Locale locale) throws MessagingException {
boolean multipart = true;
boolean isHtml = true;
// Prepare the evaluation context
final Context ctx = new Context(locale);
ctx.setVariable("message", form.getMessage());
ctx.setVariable("bookTitle", form.getBookTitle());
ctx.setVariable("email", form.getToEmail());
ctx.setVariable("logo", "logo");
ctx.setVariable("logoOnlyText", "logoOnlyText");
// Prepare message
final MimeMessage mimeMessage = mailSender.createMimeMessage();
final MimeMessageHelper message = new MimeMessageHelper(mimeMessage, multipart, "UTF-8");
message.setSubject("Regarding your book on Mimswell - " + form.getBookTitle());
message.setFrom(form.getFromEmail());
message.setTo(form.getToEmail());
// Create the HTML body using Thymeleaf
final String htmlContent = templateEngine.process("email-buy-book.html", ctx);
message.setText(htmlContent, isHtml);
message.addInline("logo", new ClassPathResource("WEB-INF/views/mail/logo130130red.png"), "image/png");
message.addInline("logoOnlyText", new ClassPathResource("WEB-INF/views/mail/logo_only_text.png"), "image/png");
// Send mail
this.mailSender.send(mimeMessage);
}
}
The error occours on the following line:
final String htmlContent = templateEngine.process("email-buy-book.html", ctx);
Where it is using ServletContextResourceResolver
instead of my other resolver. I want it to use ClassLoaderTemplateResolver
since it can handle plain Context
objects instead of having to use WebContext
. However, I could try to use a WebContext
instead since it implements the IWebContext
and only use one resolver. But then I need a HttpServletRequest
, HttpServletResponse
and a ServletContext
as parameters which seems to messy.
My structure :
Any idea whats wrong in my code?
Upvotes: 2
Views: 2783
Reputation: 9155
Since you're using the ClassLoaderTemplateResolver, Spring is going to use the prefix and append it to WEB-INF/classes. So the thing to check is whether Maven (or whatever build tool you're using) copied the html file to WEB-INF/classes/mail/email-buy-book.html. If it didn't, try copying it manually and give it a go. Looking at your screenshot, I don't see the "mail" folder under "classes" so this could be the issue.
Also, only pass "email-buy-book" and leave out the extension as @grid mentioned.
final String htmlContent = templateEngine.process("email-buy-book", ctx);
I have it working with XML config and not Java config, but I don't see why that should matter for you.
Upvotes: 0
Reputation: 2071
Since you (correctly) set the ClassLoaderTemplateResolver to have priority over the ServletContextTemplateResolver, Thymeleaf tries to use the correct order but fails to resolve the view with former and then tries latter.
I believe that the problem is with the prefix and suffix parameters you set combined with the view name you pass to templateEngine.process method. Thymeleaf will construct your view name by concatenating suffix + viewname + suffix resulting to "mail/email-buy-book.html.html".
Try to pass only "email-buy-book" and see if it solves the problem.
Upvotes: 1
Reputation: 10761
I gave up this and went for the WebContext
approach instead, even though i'm stuck needing the request, response and servletcontext every time sending something. This is how I did it:
1. Get the servlet context:
@Autowired
ServletContext servletContext;
2. Get the request and response as parameters to the sendmail method:
HttpServletRequest request,
HttpServletResponse response
3. Create the WebContext instead:
final WebContext ctx = new WebContext(request, response, servletContext, locale);
It worked from now on.
Upvotes: 1