Generate HTML email from a Template - java

I am working on a functionality where the application needs to generate user specific emails. This will be setup or configured on the user level using a email template which essentially contains a SQL query, column model, data type, subject, header, footer etc. The template serves as the dataset and layout for the email.
Now using this XML template I need to generate the HTML email. The application will read the XML, execute the SQL query and then match the resultset to the column model. Beyond this; is there any framework or API that can help generate the HTML response (nicely formatted css table) from Java objects or it has to be cooked using raw HTML tags (, etc.)?
I was also researching to see if BIRT or Jasper can provide HTML response but it doesn't seem like they are meant for that. If anyone has experience building a solution for such a use case please let me know.

Take a look at Thymeleaf. It's a HTML template engine.
It's as simple as this:
ClassLoaderTemplateResolver resolver = new ClassLoaderTemplateResolver();
resolver.setTemplateMode("HTML5");
resolver.setSuffix(".html");
TemplateEngine templateEngine = new TemplateEngine();
templateEngine.setTemplateResolver(resolver);
final Context context = new Context(Locale.CANADA);
String name = "John Doe";
context.setVariable("name", name);
// add more objects from your ResultSet
final String html = templateEngine.process("myhtml", context);
with a myhtml.html file:
<!DOCTYPE html SYSTEM "http://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-3.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org">
<head>
<title>My first template with Thymeleaf</title>
</head>
<body>
<p th:text="${name}">A Random Name</p>
</body>
</html>
Here the placeholder ${name} will replace the value A Random Name in the <p> element by the value you inserted in the context.
As for your requirement of reading and generating a table, Thymeleaf provides constructs to loop as many times as is required (ie. as long as you have data remaining). Example:
<tr th:each="prod : ${allProducts}">
will iterate through allProducts, assigning each object to the variable prod at each iteration. Take a look at the tutorials and the docs for more.
Notice, you have to write the HTML yourself.
Take a look at this answer for generating HTML report through Jasper

You can use XSLT to transform your XML to HTML. The result of your SQL query would have to be inserted as XML beforehand.

Related

Pass html data to Quarkus Template

I am using Quarkus Mailer and Quarkus Template to create an endpoint that will be responsible just for sending emails. For now it just receives the subject, body and the emails that the email should be sent to. I am using Quarkus Template so that I have a base html template for all emails. However I want to be able to pass html through the endpoint so that I am able to render different styles in the content of the template.
This is the part of the template where the body is rendered:
<tr style='mso-yfti-irow:5;height:343.95pt'>
<td width=621 valign=top style='width:466.05pt;border-top:none;border-left: solid #0E133C 2.25pt;border-bottom:none;border-right:solid #0E133C 2.25pt; padding:2.0cm 1.0cm 1.0cm 1.0cm;height:343.95pt'>
<p class=MsoNormal><span lang=PT style='mso-ansi-language:PT'>{sendEmailRequest.getBody()}<o:p></o:p></span></p>
</td>
</tr>
Basically the "sendEmailRequest.getBody()" has the html content and it is currently being rendered like this:
This is the code used to send the email:
public void sendEmail(final SendEmailRequest sendEmailRequest) {
final String html = template.data("sendEmailRequest", sendEmailRequest).render();
mailer.send((new Mail()).setSubject(sendEmailRequest.getSubject())
.setHtml(html)
.setTo(sendEmailRequest.getTos()));
}
Keep in mind that I want to keep using a base template for the email and not directly use the body received from the DTO as the whole email body. I already managed to use html from the endpoint, but that was wihtout using the template.
I posted the same question as an issue in the Quarkus repository and the solution was provided.
You can check it ou here: https://github.com/quarkusio/quarkus/issues/23893
The solution:
You need to output the unescaped value: (1) either use the raw or safe computed properties in the template ({content.raw} or {content.safe}) or (2) wrap the String value in a io.quarkus.qute.RawString (template.data("content", new RawString(content)).render()).
You can use #eval in your template to display raw html
{#eval htmlContent /}

Create a Java parser for html content similar to mailchimp one

I'd like creare a simple parser in Java that analize a string containing html and replace custom tags and if else/elseif statements, similar to Mailchimp.
Actually I simply replace my custom tags for example: *|NAME|*
with the name of the recipient, *|AGE|* whith the age of the recipient and so on.
I'd like to add conditional statements to permit expressions like:
<html>
<head>....</head>
<body>
*|IF:GENDER=M|*
Hello Mr.<b>*|NAME|*</b>
*|ELSEIF:GENDER=F|*
Hello Mrs.<i>*|NAME|*</i>
*|ELSE:|*
Dear customer
*|END:IF|*
<p>Bla bla bla</p>
....
....
</body>
</html>
In short, a very similar sintax to Mailchimp one.
The user can write his own html and add a custom syntax to customize the content based on data.
I think I'm able to create a code that works but I'm searching for the best practice to implement it. I looking for a good way to follow to implements a good code.
Would be nice if the parser can manage nested if/elseif/else statements.

Convert XML document render to hard-code as HTML

I have a requirement to publish a HTML file from an XML file where the HTML file will show hard-coded values for the specific point in time they were present on the XML file (i.e. independent of XML changes after the HTML doc is created).
Example: XML File
<dvd>
<name>Titanic</name>
<price>10</price>
</dvd>
<dvd>
<name>Avatar</name>
<price>12</price>
</dvd>
Now I need to convert these into a HTML document whereby the values are hardcoded into the HTML
Example HTML File
<html>
<body>
<h1>DVD List</h1>
<table>
<tr ...>
<th>Name</th><th>Price</th>
<td>Titanic</td><td>10</td>
<td>Avatar</td><td>12</td>
I have tried using XSLT however this only provides a render of the XML document that is updated according to XML changes. I would require a point-in-time HTML document referring to the values as they were on the XML.
Perhaps there is an easy way to do this with existing technologies, or some simple custom Java code?

Blank Rythm output when using #extends

I have an interesting problem. I'm trying to integrate the Rythm template engine into my Spring MVC application, so I wrote a simple view resolver that invokes RythmeEngine to render files. However, when I try to use #extends(...), the engine returns a blank render. I have two template files:
layout.html
<!DOCTYPE html>
<html>
<head>
<title>Rythm Sandbox</title>
</head>
<body>
<h1>Welcome!</h1>
#render()
</body>
</html>
rhythm.html
#extends(layout)
Hello World!
I am invoking RythmEngine as follows:
RythmEngine eng = RythmEngineFactory.getEngine();
File f = new File(someRootPath + name + ctx.getSuffix());
resp.setContentType("text/html");
eng.render(httpResponse.getWriter(), f, model);
And RythmEngineFactory.getEngine() returns a singleton RythmEngine with the following configuration:
Map<String, Object> props = new HashMap<String, Object>();
props.put("engine.mode", "dev");
props.put("home.template.dir", myTemplateRootDirectoryPath);
return new RythmEngine(props);
Problem
Here's the problem: without the #extends(layout) line in rhythm.html, I get a render "Hello World" as expected. However, when I try to extend layout.html, it results in a blank render (i.e., no output at all). I know it's finding the layout.html file, because if I replace #extends(layout) with something like #extends(layoutGooBlah), the error message says "Cannot find extended template by name 'layoutGooBlah'". So I know it's finding my template fine, but why would the output be blank??
Edit:
Interesting phenomenon: when I change this line:
eng.render(httpResponse.getWriter(), f, model);
To:
String s = eng.render(f, model);
httpResponse.getWriter().write(s);
It works. ??? Why won't it write to a PrintStream when using #extends??
The API engine.render(writer, ...) is buggy. See https://github.com/greenlaw110/Rythm/issues/201
BTW, I recommend you use http://github.com/greenlaw110/spring-rythm for your spring MVC application

Rendering a portion of a Play framework 2.0 template

I'm trying to call render from a controller for a tag (function) inside a template instead of the template. This way I could use it for partial renderings of a page from ajax calls. Of course I could separate the components of the form in several templates an call render on those but I think it would be cleaner the other way.
What I was trying to do is like the following:
formpage.scala.htm
#()
<html>
...
#content
...
</html>
#**********************************
* Helper generating form *
***********************************#
#content() = {
<h3 class="form-heading">#Messages("employees")</h3>
#form(routes.AppController.save()) {
#inputText...
...
}
And using ajax render the content function, without having to separate it to a
separate file. This way I could render portions of the template without fragmenting it
in multiple files.
De facto the tag is just smaller template, so you can use tags for both - using in templates and controllers, the simplest sample:
/app/views/tags/mytag.scala.html
This is my tag...
In controller can be rendered as:
public static Result createFromTag(){
return ok(views.html.tags.mytag.render());
}
In other template you just to insert:
....
And there is my tag rendered
<b>#tags.mytag()</b>
More flexibility
Of course as it's template ergo Scala function as well you can just pass some params to it or even Html body:
/app/views/tags/othertag.scala.html
#(headline: String)(body: Html)
<h3>#headline</h3>
<div class="tagsBody">
#body
</div>
In controller can be rendered as:
public static Result createFromTag(){
return ok(
views.html.tags.othertag.render(
"Head from controller",
new play.api.templates.Html("This code becomes from <i>controller</b>")
)
);
}
(of course you can import these two for shorter code in action import play.api.templates.Html; and import views.html.tags.othertag)
Finally in your template you can use the tag as:
And there is my tag rendered <br/>
#tags.othertag("Head from template"){
some content for the tag's body from <b>The Template!</b>
}
final.
You'll find tags description in documentation.

Categories