I have a velocity template for email notification, which looks like this:
#set( $layout = "base.vm" )
<tr>
<td style="padding: 48px 48px 0px; line-height: 20px;">
<h4 style="font-family: 'Proxima Nova', Arial, sans-serif;
font-size: 20px;
color: #21261f;
margin: 0px 0px 20px;
line-height: 24px;
font-weight: 700;">Notification</h4>
Hi $user
</td>
</tr>
I also have a reusable template which I want to use as a default layout for all templates:
<body style="font-family:'Proxima Nova',Arial,sans-serif; background-color: #f4f4f4; margin: 0; padding: 30px 0;">
<table style="margin: 0 auto; background-color: #ffffff; border-spacing: 0; min-width: 490px;">
<tbody style="font-family: 'Proxima Nova',Arial,sans-serif; font-size: 16px; color: #303744;">
$screen_content
#parse("/snippets/footer_content_separator.vm")
#parse("/snippets/footer_content.vm")
</tbody>
</table>
</body>
I'm parsing my template in code like this:
VelocityEngine velocityEngine = new VelocityEngine();
velocityEngine.setProperty(RuntimeConstants.RESOURCE_LOADERS, "classpath");
velocityEngine.setProperty("resource.loader.classpath.class", ClasspathResourceLoader.class.getName());
velocityEngine.init();
Template t = velocityEngine.getTemplate("mail-templates/my_template.vm");
VelocityContext context = new VelocityContext();
context.put("user", "testing");
StringWriter writer = new StringWriter();
t.merge(context, writer);
For some reason after merging with StringWriter, it contains only my template content, without layout template content. I've tried to add layout template path to VelocityEngine like this:
velocityEngine.setProperty("tools.view.servlet.layout.directory", "/mail-templates/");
velocityEngine.setProperty("tools.view.servlet.layout.default.template", "base.vm");
But this didn't resolve the issue. Am I adding layout template location incorrectly? Btw, this is a Spring Boot
application.
Should I switch to using macros
?
UPD: here are my dependencies from pom.xml:
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
<version>2.3</version>
</dependency>
<dependency>
<groupId>org.apache.velocity.tools</groupId>
<artifactId>velocity-tools-generic</artifactId>
<version>3.1</version>
</dependency>
The $screen_content
and $layout
feature is provided by the VelocityLayoutServlet
, in a web context (and from the velocity-tools-view
package).
In your case, you must do it manually. The layout configuration values you give to velocity will be ignored since the VelocityLayoutServlet
is not invoked.
It's much easier since you can hardcode the layout path.
VelocityEngine velocityEngine = new VelocityEngine();
velocityEngine.setProperty(RuntimeConstants.RESOURCE_LOADERS, "classpath");
velocityEngine.setProperty("resource.loader.classpath.class", ClasspathResourceLoader.class.getName());
velocityEngine.init();
Template t = velocityEngine.getTemplate("/mail-templates/base.vm");
VelocityContext context = new VelocityContext();
context.put("user", "testing");
context.put("page", "mail-templates/my_template.vm");
StringWriter writer = new StringWriter();
t.merge(context, writer);
And then, inside base.vm
:
<body style="font-family:'Proxima Nova',Arial,sans-serif; background-color: #f4f4f4; margin: 0; padding: 30px 0;">
<table style="margin: 0 auto; background-color: #ffffff; border-spacing: 0; min-width: 490px;">
<tbody style="font-family: 'Proxima Nova',Arial,sans-serif; font-size: 16px; color: #303744;">
#parse($page)
#parse("/snippets/footer_content_separator.vm")
#parse("/snippets/footer_content.vm")
</tbody>
</table>
</body>
It's a bit more complex. You would typically merge the content page in a string writer, then look inside the context which layout has been chosen by the content page, if any, then merge the layout page, putting the result of the content page merge in a $screen_content
variable.