Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 960
J. Scarbrough Avatar asked Jan 18 '09 23:01

J. Scarbrough


8 Answers

StringTemplate is also a very nice template engine.

like image 193
Dave Ray Avatar answered Oct 03 '22 23:10

Dave Ray


Perhaps Apache Velocity could work for you?

like image 33
javamonkey79 Avatar answered Oct 03 '22 22:10

javamonkey79


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 :)

like image 42
Jan Vladimir Mostert Avatar answered Oct 04 '22 00:10

Jan Vladimir Mostert


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:

  1. 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).
  2. I wrote a custom 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).
  3. 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.
like image 29
Jack Leow Avatar answered Oct 03 '22 23:10

Jack Leow


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.

like image 34
Adeel Ansari Avatar answered Oct 03 '22 22:10

Adeel Ansari


Here's a Java template benchmark

enter image description here

like image 40
Name is carl Avatar answered Oct 03 '22 23:10

Name is carl


If you like StringTemplate, you may like Google Soy better. Better usability, better organized, better documentation, and better supported, IMO.

like image 32
Rich Apodaca Avatar answered Oct 04 '22 00:10

Rich Apodaca


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.

like image 21
Zied Hamdi Avatar answered Oct 03 '22 23:10

Zied Hamdi