users@jersey.java.net

A sample FreeMarkerProvider

From: Erdinc Yilmazel <erdinc_at_yilmazel.com>
Date: Mon, 9 Mar 2009 18:50:06 +0000

If you want to use FreeMarker along with jersey, I wrote a Provider
for that and I wanted to share it with you. You just need to annotate
any POJO with @FreeMarkerModel annotation and return an instance of
that class in your resource methods. The returned bean will be used as
the model to the FreeMarker template.

Example usage:

@FreeMarkerModel(template="index.html")
class Index {
    public String getMessage() {
        return "Hello jersey";
    }
}

@Path("/")
public class WebPages {
   @GET
   @Produces("text/html")
   public Index getIndex() {
      return new Index();
   }
}


index.html:
----------------------------------------------
<html>
<body>${message}</body>
</html>

Here is the code:
FreeMarkerProvider.java
-----------------------------------------------

import freemarker.template.Configuration;
import freemarker.template.DefaultObjectWrapper;
import freemarker.template.Template;
import freemarker.template.TemplateException;

import javax.ws.rs.Produces;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.ext.MessageBodyWriter;
import javax.ws.rs.ext.Provider;
import java.io.*;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.util.Properties;

/**
 * Author: Erdinc YILMAZEL
 * Date: Mar 9, 2009
 * Time: 12:41:20 PM
 */
@Provider
@Produces({"text/plain", "text/html"})
public class FreeMarkerProvider implements MessageBodyWriter<Object> {

   String templateBaseDir;

   Configuration cfg;

   public FreeMarkerProvider() throws IOException {
      InputStream in =
this.getClass().getClassLoader().getResourceAsStream("/templates.properties");
      if (in != null) {
         Properties properties = new Properties();
         try {
            properties.load(in);
            templateBaseDir = (String) properties.get("templateBaseDir");
         } catch (IOException e) {
            //
         }
      }

      if (templateBaseDir == null) {
         templateBaseDir = "/templates";
      }

      cfg = new Configuration();
      cfg.setDirectoryForTemplateLoading(new File(templateBaseDir));
      cfg.setObjectWrapper(new DefaultObjectWrapper());
   }

   @Override
   public boolean isWriteable(Class<?> type, Type genericType,
Annotation[] annotations, MediaType mediaType) {
      return type.isAnnotationPresent(FreeMarkerModel.class);
   }

   @Override
   public long getSize(Object o, Class<?> type, Type genericType,
Annotation[] annotations, MediaType mediaType) {
      return -1;
   }

   @Override
   public void writeTo(Object o,
                       Class<?> type,
                       Type genericType,
                       Annotation[] annotations,
                       MediaType mediaType,
                       MultivaluedMap<String, Object> httpHeaders,
                       OutputStream entityStream) throws IOException,
WebApplicationException {

      FreeMarkerModel c = type.getAnnotation(FreeMarkerModel.class);
      if (c != null) {
         httpHeaders.putSingle("Content-Type", mediaType.toString() +
"; charset=" + c.encoding());

         Template temp = cfg.getTemplate(c.template(), c.encoding());
         OutputStreamWriter outputStreamWriter = new
OutputStreamWriter(entityStream, c.encoding());
         try {
            temp.process(o, outputStreamWriter);
            outputStreamWriter.flush();
         } catch (TemplateException e) {
            e.printStackTrace();
         }
      }
   }
}

---------------------------------------

FreeMarkerModel.java

----------------------------------------
import java.lang.annotation.Target;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

/**
 * Author: Erdinc YILMAZEL
 * Date: Mar 9, 2009
 * Time: 12:39:25 PM
 */
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface FreeMarkerModel {
   String template();
   String encoding() default "UTF-8";
}