Sure.

First you need to be able to access the faces context from a non-faces
servlet. I posted some info on the WIKI about how to get the faces context
(and therefor all session values and access to managed beans) within a
servlet. Take a look at
http://wiki.apache.org/myfaces/AccessFacesContextFromServlet.

Our charting servlet uses simple get params to control the chart -- as this
is "visible" to the outside world we only pass params which allow us to get
the appropriate managed bean and session properties from within faces
context. So in the doGet() we call appropriate managed beans and JFreeChart
methods to creat and return the chart. This is standard servlet stuff (with
the myfaces context added). Included code below

    protected void processRequest(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
        FacesContext facesContext = getFacesContext(request, response);
          // Here we get whatever we need from the faces context.
        SessionBean sessionBean = (SessionBean)
getSessionBean(facesContext);

        if (null == sessionBean) {
            log.debug("Session bean is null.");
        } else {
            log.debug("Got session bean. Userid=" +
sessionBean.getUserId());
        }

        // Get the chart type to process from the URL
        AbstractChart chart = null;
        Integer chartType =
NumberUtils.createInteger(request.getParameter("type").trim());

        log.debug("Chart Type = '" + chartType + "'");

        // Here we do whatever needed to create the chart...
        String className = ChartType.getChartClassName(chartType);
        log.debug("Creating chart object for class '" + className + "'");

        String reportTitle = request.getParameter("til");
        log.debug("Chart Title = '" + reportTitle + "'");

        String reportSubTitle = request.getParameter("sub");
        log.debug("Chart Sub Title = '" + reportSubTitle + "'");

        // See if the chart is in the cache. The servlet is single-threaded
and reuasable which means
        /// that a new chart map is created for each instance of a chart.
Charts should be serializable
        // and not store state in any way
        if (map.containsKey(className)) {
            chart = (AbstractChart) map.get(className);
        } else {
            // Use reflection to get the chart. Note that is must have a
no-args constructor
            try {
                chart = (AbstractChart)
Class.forName(className).newInstance();
                // Push the chart to the map.
                map.put(className, chart);
            } catch (ClassNotFoundException e) {
                log.debug(e.getMessage());
                throw new IOException(e.getMessage());
            } catch (InstantiationException e) {
                log.debug(e.getMessage());
                throw new IOException(e.getMessage());
            } catch (IllegalAccessException e) {
                log.debug(e.getMessage());
                throw new IOException(e.getMessage());
            } catch (IllegalArgumentException e) {
                log.debug(e.getMessage());
                throw new IOException(e.getMessage());
            }
        }

        // Chart setup here
        if (null == chart) {
            log.error("Chart # " + chartType + " not found on server.");
            response.setContentType("text/html");

            ServletOutputStream outputStream = response.getOutputStream();
            outputStream.println("Chart not found on server.");
            outputStream.flush();
            outputStream.close();
        } else {
            // Populate the chart so it can access the params
            chart.setRequest(request);
            chart.setSessionBean(sessionBean);

            // Process the chart
            JFreeChart jfreeChart = chart.getChart();
            // get the image
            response.setContentType("image/png");
            ChartUtilities.writeChartAsPNG(response.getOutputStream(),
jfreeChart, chart.getChartWidth(), chart.getChartHeight());
        }
    }

Our JSF backing bean constructs a url based on options selected by the user.
This url is passed to the <h:graphicImage> tag. The form of the URL is
/myContextRoot/myChartServlet?param1=value1&param2=value2 etc.

In the backing bean we have

Public String getChartURL() {
        StringBuffer sb = new StringBuffer();
        sb.append("/myContextRoot/myChartServlet");
        //sb.append(.....) etc...
        return sb.toString();
}
and in the JSF we have 

<h:graphicImage styleClass="whatever..." value="#{myBackingBean.chartURL}"
/>

Our servlet implementation loads chart classes as the servlet is initialized
which speeds up the servlet once it is "warmed up". 

One more note, While this approach works well found that it is more
convienient to create a custom component to provide the JSF interface as we
use charts on a large number of our pages and it fits the MVC model better
to let the JSF fuly control the format and display of the greaphic.

I hope this helps.

        

Example

-----Original Message-----
From: Paul Spencer [mailto:[EMAIL PROTECTED] 
Sent: Thursday, June 29, 2006 7:55 AM
To: MyFaces Discussion
Subject: Re: How to displayi an images generated by a managed bean?

Julian,
Can you explain the code and configuration behind #{myBackingBean.chartURL}
and the servlet you have created?

I need to understand where the graphic is created, i.e. in the managed bean
or servlet, how the servlet gets what is needs, and any housekeeping that is
performed.


Paul Spencer

Julian Ray wrote:
> Hi Paul,
> 
> We use JFreeCharts by creating a servlet which serves up the charts 
> and then creating a URL in the backingbean which is set as the value 
> for the graphicImage
> 
> Eg <h:graphicImage styleClass="..." value="#{myBackingBean.chartURL}" 
> />
> 
> -----Original Message-----
> From: Paul Spencer [mailto:[EMAIL PROTECTED]
> Sent: Wednesday, June 28, 2006 11:14 PM
> To: MyFaces Discussion
> Subject: How to displayi an images generated by a managed bean?
> 
> I need to include a graphic image generated by JFreeCharts.  Currently 
> the generation of the image is in an action of a managed bean and is 
> displayed in a separate windows via <h:commandButton>.  How should I 
> convert this to a <h:graphicImage> so it can be displayed in an existing
page?
> 
> Paul Spencer
> 
> 


Reply via email to