we have an application that needs to send out various different types of template email. The current code is very cumbersome and not very flexible. Does any one konw of a library to help with this type of work... We are looking for some kind of templating library for email.
StringTemplate is also a very nice template engine.
Perhaps Apache Velocity could work for you?
Jack Leow said he wrote a custom HttpServletResponse so that he could re-use JSPs for generating email templates, I just did the same and would like to share my code sample / prototype for those not sure where to begin:
Usually when serving a JSP page, you'd do something like this:
res.setContentType("text/html");
RequestDispatcher jsp = req.getRequestDispatcher("/WEB-INF/templates/" + template);
res.setStatus(200);
jsp.forward(req, res);
Now instead of doing that jsp.forward to an HttpServletResponse, do a jsp.forward to your custom Servlet Response:
EmailServletResponse res2 = new EmailServletResponse();
jsp.forward(req, res2);
System.out.println(res2.toString()); <<-- email gets printed here
Your EmailServlet response will simply be a class that implements HttpServletResponse, fill in the blanks and use an underlying StringWriter to accomplish the toString conversion:
public class EmailServletResponse implements HttpServletResponse {
private int status;
private StringWriter sw = new StringWriter();
@Override
public void flushBuffer() throws IOException {
sw.flush();
}
@Override
public int getBufferSize() {
return 1024;
}
@Override
public String getCharacterEncoding() {
return "UTF-8";
}
@Override
public String getContentType() {
return "text/html";
}
@Override
public Locale getLocale() {
return Locale.getDefault();
}
@Override
public ServletOutputStream getOutputStream() throws IOException {
return new ServletOutputStream() {
@Override
public void write(int b) throws IOException {
sw.write(b);
}
};
}
@Override
public PrintWriter getWriter() throws IOException {
PrintWriter pw = new PrintWriter(sw);
return pw;
}
@Override
public boolean isCommitted() {
return false;
}
@Override
public void reset() {
}
@Override
public void resetBuffer() {
}
@Override
public void setBufferSize(int arg0) {
}
@Override
public void setCharacterEncoding(String arg0) {
}
@Override
public void setContentLength(int arg0) {
}
@Override
public void setContentType(String arg0) {
}
@Override
public void setLocale(Locale arg0) {
}
@Override
public void addCookie(Cookie arg0) {
}
@Override
public void addDateHeader(String arg0, long arg1) {
}
@Override
public void addHeader(String arg0, String arg1) {
}
@Override
public void addIntHeader(String arg0, int arg1) {
}
@Override
public boolean containsHeader(String arg0) {
return false;
}
@Override
public String encodeRedirectURL(String arg0) {
return "";
}
@Override
public String encodeRedirectUrl(String arg0) {
return "";
}
@Override
public String encodeURL(String arg0) {
return "";
}
@Override
public String encodeUrl(String arg0) {
return "";
}
@Override
public void sendError(int arg0) throws IOException {
}
@Override
public void sendError(int arg0, String arg1) throws IOException {
}
@Override
public void sendRedirect(String arg0) throws IOException {
}
@Override
public void setDateHeader(String arg0, long arg1) {
}
@Override
public void setHeader(String arg0, String arg1) {
}
@Override
public void setIntHeader(String arg0, int arg1) {
}
@Override
public void setStatus(int status) {
this.status = status;
}
@Override
public void setStatus(int status, String message) {
setStatus(status);
}
public String toString(){
return sw.getBuffer().toString();
}
}
Feel free to improve on the code where needed, this was a quick prototyping session :)
I ran into a similar problem about a year ago. In our case, our front end developers were all familiar with JSP, and I really did not want to throw another templating engine into the mix. I wanted something that relied on the servlet container's JSP processor to generate e-mail content for me.
It's fairly straightforward:
HttpServletResponse
and ServletOutputStream
that captures content written by the servlet container and turns it into a String, and relied on RequestDispatcher.include(...)
to make a "request" to the template JSP (I also wrote a custom HttpServletRequest
to isolate the original request from mutation).I prefer Freemarker, here over Velocity; imo, Freemarker much simpler in this case.
If you are using Spring, then you may be interested in, Freemarker in Spring MVC.
Here's a Java template benchmark
If you like StringTemplate, you may like Google Soy better. Better usability, better organized, better documentation, and better supported, IMO.
It is also possible to create a "mail content jsp" like
mails/orderConfirmed.jsp
mails/sendingYourOrderNotification.jsp
then simply do an http client request "/mails/*.jsp" to obtain the mail content you want.
I think it's a fair use of jsp since you want to generate HTML anyway, and requesting your own server is not bandwidth consuming.
The good thing is that you can do jsp inclusion, or even use more advanced libraries like tiles, jsf, struts, wicket. You don't need to learn a new tool for that, you can use what you already know. Jsps are a quite performant templating engine, they exists since the years 2000.
The bad point is that you can't use your typed variables to compose your jsp, you're limited to strings as request parameters (or a good huge json :-))
It is also a good way to isolate code and even to split servers later if you need performance optimization.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With