Suggestions for Java email templating? [closed]
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:
- I had to have a JSP page in my application (you can put it in /WEB-INF if you don't want it externally accessible).
- I wrote a custom
HttpServletResponse
andServletOutputStream
that captures content written by the servlet container and turns it into a String, and relied onRequestDispatcher.include(...)
to make a "request" to the template JSP (I also wrote a customHttpServletRequest
to isolate the original request from mutation). - Because this is a bit of a hack, and not the way the servlet API was intended to be used, I encapsulated all this in a utility class, so that all the client code has to do is pass in the path to the JSP template, and get back the processed content.
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.