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¶m2=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
>
>