Oct 8, 2011

Play!Framework: Use RenderArgs and Excel module effectively

Mr. Basav Nagur has posted a blog demonstrates how easy it is to create Excel reports in Play!Framework. Being the author of Excel module, I really appreciate that. In additional I would like to help make the controller more concise in the sample code. Here is the original code of Application controller:
package controllers;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.apache.commons.lang.RandomStringUtils;
import models.Customer;
import play.Logger;
import play.modules.excel.RenderExcel;
import play.mvc.Controller;
import play.mvc.With;

@With(ExcelControllerHelper.class)
public class Application extends Controller {
    public static void index() {
        render();
    }
    public static void customerphonelist(){
        Logger.info("Generating Customer Phone List Excel report ");
        request.format = "xlsx";
        Date date = new Date();
        String user = "Bob";
        List customers = new ArrayList();
        for (int i = 0 ;i < 10; i++){
         customers.add(new Customer("Mr", RandomStringUtils.randomAlphabetic(15), RandomStringUtils.randomNumeric(10)));
        } 
        renderArgs.put("date", date);
        renderArgs.put("user", user);
        renderArgs.put("customers", customers);
        renderArgs.put(RenderExcel.RA_ASYNC, true);
        renderArgs.put(RenderExcel.RA_FILENAME, "customer_list_report.xlsx");
        render();
        Logger.info("Completed Customer Phone List Excel report ");
    }
} 

The code is correct, however we could make even better in several places:
  1. "@With(ExcelControllerHelper.class)" could be removed. The dependency on that @With has been dropped since Excel v1.2.2
  2. All renderArgs.put(...) for app variables could be removed. You simply pass the variable in the render() directly, and they will get put into renderArgs automatically. 
  3. "renderArgs.put(RenderExcel.RA_ASYNC, true);" could be eliminated if you have "excel.async=true" in your conf/application.conf file.
  4. "renderArgs.put(RenderExcel.RA_FILENAME, "customer_list_report.xlsx");" could be eliminated if your template file name is "customerphonelist.xlsx" which matches the controller name, or if the action method name renamed to "customer_list_report".
All these tiny little things tries to show the beauty of this great framework: being nice to programmer and making programming on the framework a really enjoyable experience. Now the new version of the Application.java:
package controllers;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.apache.commons.lang.RandomStringUtils;
import models.Customer;
import play.Logger;
import play.modules.excel.RenderExcel;
import play.mvc.Controller;
public class Application extends Controller {
    public static void index() {
        render();
    }
    public static void customer_list_report(){
        Logger.info("Generating Customer Phone List Excel report ");
        request.format = "xlsx";
        Date date = new Date();
        String user = "Bob";
        List customers = new ArrayList();
        for (int i = 0 ;i < 10; i++){
         customers.add(new Customer("Mr", RandomStringUtils.randomAlphabetic(15), RandomStringUtils.randomNumeric(10)));
        } 
        render(date, user, customers)
        Logger.info("Completed Customer Phone List Excel report ");
    }
} 

Isn't it more concise and easier for both programming and reading? What do you think?

One additional note about xlsx format of excel template, in order to use that, you will need Excel v1.2.3x version instead of v1.2.3 version mentioned in original post.

BTW, I would be really glad if someone tell me how to format code in the way Mr. Basav did in his post :)