Monday, December 05, 2011

Using a Servlet to generate chart images for BIRT

I've been working with Google's chart tools -- specifically their Image Chart tools.  My problem -- I'm using BIRT as my PDF report engine, but I have a web interface.  I want the report to look the same on the web as it does in BIRT (which has it's own excellent native charting library).  I decided the easiest way is to use an
image tag, but I have the potential for copious data, so I have to use a POST instead of a GET.

Google lists an excellent hack using a form and an Iframe as a way to submit the post and that works for me from the web.   It does not work inside of BIRT -- because as far as I know there is no way to submit a form inside of a report.  Instead I decided to use an image tag which runs through a servlet I host.

So now I can write on my web page:

<img src="../chart/chart.png">

and I can include in a dynamic text in my BIRT report

"<img src='http://mywebserver/chart/chart.png'>"  //outside quotes required for BIRT dynamic text

And now I have the same chart in both!  Voila.



import org.apache.commons.io.IOUtils;


import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import java.io.*;
import java.net.*;
import java.util.Enumeration;
import java.util.Hashtable;


public class ChartServlet extends HttpServlet {


    public void service(HttpServletRequest request, HttpServletResponse response) {
        response.setHeader("content-type", "image/png");
        try {
            // Construct data
            Hashtable dataHash = new Hashtable();
            dataHash.put("cht", "lc");
            dataHash.put("chtt", "This is my chart");
            dataHash.put("chs", "600x300");
            dataHash.put("chxt", "x");
            dataHash.put("chd", "t:40,20,50,20,100");
            StringBuilder postBuffer = new StringBuilder();
            Enumeration enumeration = dataHash.keys();
            boolean first = true;
            while (enumeration.hasMoreElements()) {
                String key = (String) enumeration.nextElement();
                String value = (String) dataHash.get(key);
                String prefix = "&";
                if (first) {
                    prefix = "";
                    first = false;
                }
                postBuffer.append(getURLPair(prefix, key, value));
            }
            String params = postBuffer.toString();
            // Send data
            URL url = new URL("http://chart.googleapis.com/chart");
              //?chid=a"+String.valueOf(Math.random()).substring(2)); to avoid caching
            URLConnection conn = url.openConnection();
            conn.setDoOutput(true);
            OutputStreamWriter wr = new OutputStreamWriter(conn.getOutputStream(),"UTF-8");
            wr.write(params);
            wr.flush();
          // Get the response and write it directly to your response
            IOUtils.copy(conn.getInputStream(), response.getOutputStream());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static String getURLPair(String prefix, String key, String value) {
        try {
            String parameterString = prefix + URLEncoder.encode(key, "UTF-8") + "=" 
            + URLEncoder.encode(value, "UTF-8");
return parameterString;
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();  
        }
        return null;
    }

}

Creative Commons License
This work is licensed under a Creative Commons Attribution 3.0 Unported License.