Table of Contents |
---|
Pentaho ChartBeans
In this article, This article provides you with an introduction to the Pentaho ChartBeans 1 project is introduced. Pentaho ChartBeans is a wrapper around existing "chart engines" (such as JFreeChart and Open Flash Chart). Wrapping these chart engines creates a single way of expressing charts.
...
To eliminate confusion in documentation, the Pentaho ChartBeans project has documented its preferred charting terminology has been provided. In addition to standardizing on terms for the purpose of the Pentaho ChartBeans project, this terminology page provides an excellent introduction to charting in general. Please review this page before proceeding.
...
The first design was based on JavaBeans and is the source from which the term "beans" derives. The proposal was for classes for each of the structural components of a chart (such as the plot, series, and title). We'll refer to this design This design will be referred to as the ChartModel
API.
ChartDocument API
The second design was based on a Document Object Model (DOM). A chart DOM is an object model that consists of elements which can have attributes and child elements. Elements have an associated namespace. Core chart elements, like title and plot would go into the Pentaho ChartBeans namespace. Other, chart engine-specific elements would go into their own namespaces. For example, Open Flash Chart-specific properties would go into a "openflashchart" namespace, while JFreeChart-specific properties would go into a "jfreechart" namespace. We'll refer to this design This design will be referred to as the ChartDocument
API.
Tale of Two APIs
...
Example from a Java Developer Perspective
Let's use In this example Pentaho ChartBeans is used to render a standalone PNG image and an HTML page with an embedded Flash chart object.
Chart Data
In this example, we create a ChartTableModel
consisting of The full source of this example is attached. It is a zipped Eclipse project called pentaho-chartbeans-demo. An included readme file instructs you how to run the example.
Chart Data
In this example, a ChartTableModel
is created consisting of 21 rows and 3 columns. In addition, we add This example also adds some row and column metadata.
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
private static ChartTableModel createChartTableModel() { // 21 rows and 3 columns Object[][] dataArray = { { 5.55, 10.11, 20.22 }, { 30.33, 40.44, 50.55 }, { 31.33, 99.44, 150.55 }, { 32.33, 1.44, 30.55 }, { 34.33, 88.44, 775.55 }, { 3510.3311, 22.44, 5420.5522 }, { 36.33, 33.44, 52.55 }, { 37.33, 76.44, 54.55 }, { 38 30.33, 7 40.44, 5950.55 }, { 39.33, 48.44, 56.55 }, { 40.33, 19.44, 57.55 }, { 50 31.33, 10499.44, 36150.55 }, { 60.33, 23.44, 74.55 }, { 20.33, 90.44, 80.55 }, { 60.33, 18.44, 27.55 }, { 10.33, 22.44, 97.55 }, { 20 32.33, 591.44, 55 30.55 }, { 90.33, 140.44, 22.55 }, { 100.33, 56.44, 76.55 }, { 4034.33, 50 88.44, 5077.55 }, { 60.66, 70.77, 80.88 } }; ChartTableModel data = new ChartTableModel(); data.setData(dataArray); // give names to the{ categories 35.33, data.setColumnName(022.44, "budget"); 54.55 }, data.setColumnName(1, "sales"); data.setColumnName(2, "forecast"); // give names to the series final String ROW_NAME_KEY = "row-name"; { 36.33, data33.setRowMetadata(0, ROW_NAME_KEY, "1");44, 52.55 }, data.setRowMetadata(1, ROW_NAME_KEY, "2"); // ----- lines omitted ----- data.setRowMetadata(20, ROW_NAME_KEY, "21"); return data;{ 37.33, } |
Chart Structure
Here we add the 21 series to the plot which in turn gets added to the chart.
Code Block | |
---|---|
java | java |
title | Dummy Chart Structure | private static ChartModel createChartModel() { 76.44, 54.55 }, List<Series> seriesList = new ArrayList<Series>(); Series series1 = new Series(); series1.setForegroundColor(0x2D00FF); { seriesList.add(series1);38.33, 7.44, Series series2 = new Series();59.55 }, series2.setForegroundColor(0x11FFE4); seriesList.add(series2); // lines omitted Series series21 = new{ Series(); 39.33, 48.44, series21.setForegroundColor(0x0596FF);56.55 }, seriesList.add(series21); CategoricalBarPlot plot = new CategoricalBarPlot(); plot.setSeries(seriesList); plot.setOrientation(Orientation.HORIZONTAL); ChartModel{ chartModel =40.33, new ChartModel(); 19.44, 57.55 }, chartModel.setTitle("Bar Chart Using Pentaho ChartBeans"); chartModel.setPlot(plot); return chartModel; }{ |
Chart Styling
For now, styling is included in the Chart Structure when using the Java API.
Generating Charts
Now let's pull all of the pieces together. First we have a main method that "boots" Pentaho ChartBeans. This reads various configuration files and otherwise readies the system for chart processing requests. Next we render one chart using the JFreeChart plugin for Pentaho ChartBeans and then we render another chart using the Open Flash Chart plugin for Pentaho ChartBeans. Note that both use the same ChartModel
and ChartTableModel
.
Code Block | |
---|---|
java | java |
title | main method | public static void main(String[] args) throws Exception {50.33, 104.44, 36.55 }, // "boot" ChartBeans { ChartBoot.getInstance().start(); 60.33, 23.44, 74.55 }, // remove any output from previous runs cleanOutput(); // render chart using JFreeChart plugin for Pentaho ChartBeans { renderUsingJFreeChartPlugin(createChartModel(), createChartTableModel(), "chartoutput/Bar.png");20.33, 90.44, 80.55 }, // render same chart using Open Flash Chart plugin for Pentaho ChartBeans renderUsingOpenFlashChartPlugin(createChartModel(), createChartTableModel(), "chartoutput/Bar.html"); { } |
See how we specify the plugin class in the first line?
Code Block | |
---|---|
java | java |
title | renderUsingJFreeChartPlugin method | private static void renderUsingJFreeChartPlugin(final ChartModel chartModel, final ChartTableModel chartTableModel, 60.33, 18.44, 27.55 }, final String chartOutputFilename) throws Exception { final IChartPlugin plugin = ChartPluginFactory.getInstance("org.pentaho.chart.plugin.jfreechart.JFreeChartPlugin"); { ChartDocumentContext cdc = ChartFactory.generateChart(chartModel, chartTableModel);10.33, 22.44, 97.55 }, IOutput output = plugin.renderChartDocument(cdc, chartTableModel); OutputUtils.persistChart(output, chartOutputFilename, IOutput.OutputTypes.FILE_TYPE_PNG, 400/*px*/, 400/*px*/); } |
The Open Flash Chart example is a little more complicated because we have to embed the chart data in an HTML document. Whereas in the JFreeChart example, the bytes for the PNG image went to the chartOutputFilename, in this example, we write the Pentaho ChartBeans output to a String which contains the JSON that will configure the Open Flash Chart object when rendered by the browser.
Note: This example uses open-flash-chart-full-embedded-font.swf, found at http://www.ofc2dz.com/, which is a patched version of Open Flash Chart 2.
Code Block | |
---|---|
java | java |
title | renderUsingOpenFlashChartPlugin method | private static void renderUsingOpenFlashChartPlugin(final ChartModel chartModel, { 20.33, 59.44, 55.55 }, { 90.33, 140.44, 22.55 }, final ChartTableModel chartTableModel, final String chartOutputFilename) throws Exception { final IChartPlugin plugin = ChartPluginFactory{ 100.33, 56.44, 76.55 }, .getInstance("org.pentaho.chart.plugin.openflashchart.OpenFlashChartPlugin"); ChartDocumentContext cdc = ChartFactory.generateChart(chartModel, chartTableModel); IOutput output{ = plugin40.renderChartDocument(cdc33, chartTableModel); 50.44, 50.55 }, ByteArrayOutputStream tmpOut = new ByteArrayOutputStream(); output.persistChart(tmpOut, IOutput.OutputTypes.DATA_TYPE_STREAM, 400, 400); final String ENCODING = "UTF-8"; ByteArrayInputStream in ={ new ByteArrayInputStream(tmpOut.toByteArray()); IOUtils.closeQuietly(tmpOut);60.66, 70.77, 80.88 } String openFlashChartJson = IOUtils.toString(in, ENCODING); IOUtils.closeQuietly(in); final String HTML_TEMPLATE = "<html>\n" + " }; <head>\n" ChartTableModel data = new +ChartTableModel(); " <title>Bar Chart Using Open Flash Chart Plugin</title>\n" data.setData(dataArray); // give names to the categories +data.setColumnName(0, "budget"); <script type=\"text/javascript\">window.getChartData = function() '{' return ''{0}''; '}'</script>\n" data.setColumnName(1, "sales"); data.setColumnName(2, "forecast"); // give names to +the "series </head>\n" + " final <body>\n" String ROW_NAME_KEY = "row-name"; + "data.setRowMetadata(0, ROW_NAME_KEY, "1"); <object id=\"ofco00b1c87708fe11dea97da1e1ba5b86bc\" height=\"100%\" align=\"middle\" width=\"100%\" \n" + " codebase=\"http://fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=8,0,0,0\" \n" + " classid=\"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\"> \n" + " <param value=\"sameDomain\" name=\"allowScriptAccess\"/><param value=\"opaque\" name=\"wmode\"/> \n" + " <param value=\"open-flash-chart.swf?get-data=getChartData\" name=\"movie\"/> \n" + " <param value=\"high\" name=\"quality\"/><embed id=\"ofce00b1c87708fe11dea97da1e1ba5b86bc\" \n" + " height=\"100%\" align=\"middle\" width=\"100%\" \n" + " pluginspage=\"http://www.macromedia.com/go/getflashplayer\" type=\"application/x-shockwave-flash\" \n" + " allowscriptaccess=\"sameDomain\" bgcolor=\"#FFFFFF\" quality=\"high\" wmode=\"opaque\" \n" + " src=\"open-flash-chart.swf?get-data=getChartData\"/></object>\n" + " </body>\n" + "</html>"; String html = MessageFormat.format(HTML_TEMPLATE, new String[] { openFlashChartJson }); FileUtils.writeStringToFile(new File(chartOutputFilename), html, "UTF-8"); } |
Example from an End User Perspective
Chart Data
Chart Structure
The ChartBeans XML document for this example is below. Its relatively brief because our data and styling is separate from the chart structure. The elements in this document define a stylesheet reference, a chart title, the series, and the chart orientation.
...
<chart xmlns="http://reporting.pentaho.org/namespaces/charting/1.0">
<!-- external style sheet -->
<stylesheet href="theme.css" />
<!-- chart title -->
<title>Bar Chart Using Pentaho ChartBeans</title>
<!-- styling on individual series using style and class attributes -->
<series style="-x-pentaho-chart-series-type: bar; -x-pentaho-chart-bar-style: bar;" class="series1" />
<series class="series2" />
<!-- lines omitted -->
<series class="series18" />
<!-- wrap colors because there are more series than colors in the theme -->
<series class="series1" />
<series class="series2" />
<series class="series3" />
<!-- styling on plot using style attribute -->
<plot style="-x-pentaho-chart-orientation: horizontal"/>
</chart>
Chart Styling
Here is the external style sheet referenced above. Here we're using class selectors. Note the W3C standard color
property as well as a custom Pentaho ChartBeans' -x-pentaho-chart-line-width
property.
...
.series1 {
color: #2D00FF;
-x-pentaho-chart-line-width: 2px;
}
.series2 {
color: #11FFE4;
-x-pentaho-chart-line-width: 2px;
}
/* lines omitted */
.series18 {
color: #B7FFE5;
-x-pentaho-chart-line-width: 2px;
}
...
data.setRowMetadata(1, ROW_NAME_KEY, "2");
// ----- lines omitted -----
data.setRowMetadata(20, ROW_NAME_KEY, "21");
return data;
}
|
Chart Structure
This example adds 21 series to the plot which in turn gets added to the chart.
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
private static ChartModel createChartModel() {
List<Series> seriesList = new ArrayList<Series>();
Series series1 = new Series();
series1.setForegroundColor(0x2D00FF);
seriesList.add(series1);
Series series2 = new Series();
series2.setForegroundColor(0x11FFE4);
seriesList.add(series2);
// lines omitted
Series series21 = new Series();
series21.setForegroundColor(0x0596FF);
seriesList.add(series21);
CategoricalBarPlot plot = new CategoricalBarPlot();
plot.setSeries(seriesList);
plot.setOrientation(Orientation.HORIZONTAL);
ChartModel chartModel = new ChartModel();
chartModel.setTitle("Bar Chart Using Pentaho ChartBeans");
chartModel.setPlot(plot);
return chartModel;
}
|
Chart Styling
For now, styling is included in the chart structure when using ChartModel
API.
Generating Charts
Now all of the pieces can be pulled together. First there is a main method that "boots" Pentaho ChartBeans. This reads various configuration files and otherwise readies the system for chart processing requests. Next, one chart is rendered using the JFreeChart plugin for Pentaho ChartBeans and then another chart is rendered using the Open Flash Chart plugin for Pentaho ChartBeans. Note that both use the same ChartModel
and ChartTableModel
.
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
public static void main(String[] args) throws Exception {
// "boot" ChartBeans
ChartBoot.getInstance().start();
// remove any output from previous runs
cleanOutput();
// render chart using JFreeChart plugin for Pentaho ChartBeans
renderUsingJFreeChartPlugin(createChartModel(), createChartTableModel(), "chartoutput/Bar.png");
// render same chart using Open Flash Chart plugin for Pentaho ChartBeans
renderUsingOpenFlashChartPlugin(createChartModel(), createChartTableModel(), "chartoutput/Bar.html");
}
|
See how one specifies the plugin class in the first line?
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
private static void renderUsingJFreeChartPlugin(final ChartModel chartModel, final ChartTableModel chartTableModel,
final String chartOutputFilename) throws Exception {
final IChartPlugin plugin = ChartPluginFactory.getInstance("org.pentaho.chart.plugin.jfreechart.JFreeChartPlugin");
ChartDocumentContext cdc = ChartFactory.generateChart(chartModel, chartTableModel);
IOutput output = plugin.renderChartDocument(cdc, chartTableModel);
OutputUtils.persistChart(output, chartOutputFilename, IOutput.OutputTypes.FILE_TYPE_PNG, 400/*px*/, 400/*px*/);
}
|
The Open Flash Chart example is a little more complicated because the chart data must be embedded in an HTML document. Whereas in the JFreeChart example, the bytes for the PNG image went to the chartOutputFilename, in this example, the Pentaho ChartBeans output is written to a String which contains the JSON that will configure the Open Flash Chart object when rendered by the browser.
Note: This example uses open-flash-chart-full-embedded-font.swf, found at http://www.ofc2dz.com/, which is a patched version of Open Flash Chart 2.
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
private static void renderUsingOpenFlashChartPlugin(final ChartModel chartModel,
final ChartTableModel chartTableModel, final String chartOutputFilename) throws Exception {
final IChartPlugin plugin = ChartPluginFactory
.getInstance("org.pentaho.chart.plugin.openflashchart.OpenFlashChartPlugin");
ChartDocumentContext cdc = ChartFactory.generateChart(chartModel, chartTableModel);
IOutput output = plugin.renderChartDocument(cdc, chartTableModel);
ByteArrayOutputStream tmpOut = new ByteArrayOutputStream();
output.persistChart(tmpOut, IOutput.OutputTypes.DATA_TYPE_STREAM, 400, 400);
final String ENCODING = "UTF-8";
ByteArrayInputStream in = new ByteArrayInputStream(tmpOut.toByteArray());
IOUtils.closeQuietly(tmpOut);
String openFlashChartJson = IOUtils.toString(in, ENCODING);
IOUtils.closeQuietly(in);
final String HTML_TEMPLATE = "<html>\n" + " <head>\n"
+ " <title>Bar Chart Using Open Flash Chart Plugin</title>\n"
+ " <script type=\"text/javascript\">window.getChartData = function() '{' return ''{0}''; '}'</script>\n"
+ " </head>\n" + " <body>\n"
+ " <object id=\"ofco00b1c87708fe11dea97da1e1ba5b86bc\" height=\"100%\" align=\"middle\" width=\"100%\" \n"
+ " codebase=\"http://fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=8,0,0,0\" \n"
+ " classid=\"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\"> \n"
+ " <param value=\"sameDomain\" name=\"allowScriptAccess\"/><param value=\"opaque\" name=\"wmode\"/> \n"
+ " <param value=\"open-flash-chart.swf?get-data=getChartData\" name=\"movie\"/> \n"
+ " <param value=\"high\" name=\"quality\"/><embed id=\"ofce00b1c87708fe11dea97da1e1ba5b86bc\" \n"
+ " height=\"100%\" align=\"middle\" width=\"100%\" \n"
+ " pluginspage=\"http://www.macromedia.com/go/getflashplayer\" type=\"application/x-shockwave-flash\" \n"
+ " allowscriptaccess=\"sameDomain\" bgcolor=\"#FFFFFF\" quality=\"high\" wmode=\"opaque\" \n"
+ " src=\"open-flash-chart.swf?get-data=getChartData\"/></object>\n" + " </body>\n" + "</html>";
String html = MessageFormat.format(HTML_TEMPLATE, new String[] { openFlashChartJson });
FileUtils.writeStringToFile(new File(chartOutputFilename), html, "UTF-8");
}
|
The full source of this example is attached. It is a zipped Eclipse project called pentaho-chartbeans-demo. An included readme file instructs you how to run the example.
Example from an End User Perspective
An end user is anyone who will be using the Pentaho BI Platform. Because the unit of work in the Pentaho BI Platform is the action sequence, an example using an xaction is shown that queries using MQL to get the data and then renders a chart using Pentaho ChartBeans.
Note: The ChartComponent mentioned below is not complete! It is a work in progress and cannot be used as is. This example is for illustration only.
Chart Data
In this example, a database is queried using an MQL query. See Generating Charts in this section.
Chart Structure
The ChartBeans XML document for this example is below. Its relatively brief because the data and styling is separate from the chart structure. The elements in this document define a stylesheet reference, a chart title, the series, and the chart orientation.
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
<chart xmlns="http://reporting.pentaho.org/namespaces/charting/1.0">
<!-- external style sheet -->
<stylesheet href="theme.css" />
<!-- chart title -->
<title>Bar Chart Using Pentaho ChartBeans</title>
<!-- styling on individual series using style and class attributes -->
<series style="-x-pentaho-chart-series-type: bar; -x-pentaho-chart-bar-style: bar;" class="series1" />
<series class="series2" />
<!-- lines omitted -->
<series class="series18" />
<!-- wrap colors because there are more series than colors in the theme -->
<series class="series1" />
<series class="series2" />
<series class="series3" />
<!-- styling on plot using style attribute -->
<plot style="-x-pentaho-chart-orientation: horizontal"/>
</chart>
|
Chart Styling
Here is the external style sheet referenced above. Here class selectors are being used. Note the W3C standard color
property as well as a custom Pentaho ChartBeans' -x-pentaho-chart-line-width
property.
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
.series1 {
color: #2D00FF;
-x-pentaho-chart-line-width: 2px;
}
.series2 {
color: #11FFE4;
-x-pentaho-chart-line-width: 2px;
}
/* lines omitted */
.series18 {
color: #B7FFE5;
-x-pentaho-chart-line-width: 2px;
}
|
Generating Charts
Note: The ChartComponent mentioned below is not complete! It is a work in progress and cannot be used as is. This example is for illustration only.
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
<?xml version="1.0" encoding="UTF-8"?>
<action-sequence>
<name>chartbeans_demo.xaction</name>
<title>chartbeans_demo.xaction</title>
<version>1</version>
<logging-level>debug</logging-level>
<documentation>
<description>Generate a chart through ChartBeans from an MQL statement.</description>
<help>Pass in an MQL statement that returns a table of three columns. The first column is the series, the second is the category and the third is the data.</help>
<result-type>rule</result-type>
</documentation>
<inputs>
<query type="string">
<sources>
<request>query</request>
</sources>
</query>
<chart-model type="string">
<sources>
<request>chart-model</request>
</sources>
</chart-model>
<chart-width type="integer">
<sources>
<request>chart-width</request>
</sources>
<default-value>-1</default-value>
</chart-width>
<chart-height type="integer">
<sources>
<request>chart-height</request>
</sources>
<default-value>-1</default-value>
</chart-height>
<series-column type="string">
<sources>
<request>series-column</request>
</sources>
<default-value/>
</series-column>
<category-column type="string">
<sources>
<request>category-column</request>
</sources>
<default-value/>
</category-column>
<value-column type="string">
<sources>
<request>value-column</request>
</sources>
<default-value/>
</value-column>
</inputs>
<outputs>
<outputstream type="content">
<destinations>
<response>content</response>
</destinations>
</outputstream>
</outputs>
<resources/>
<actions>
<action-definition>
<action-inputs>
<query />
</action-inputs>
<action-outputs>
<rule-result type="result-set" mapping="chartdata"/>
</action-outputs>
<component-name>MQLRelationalDataComponent</component-name>
<action-type>rule</action-type>
<component-definition>
<live>true</live>
<display-names>false</display-names>
</component-definition>
</action-definition>
<action-definition>
<component-name>org.pentaho.platform.engine.services.solution.PojoComponent</component-name>
<action-inputs>
<chart-model type="string"/>
<chartdata type="result-set" />
<chart-width type="integer"/>
<chart-height type="integer"/>
<series-column type="string"/>
<category-column type="string"/>
<value-column type="string"/>
</action-inputs>
<action-outputs>
<outputstream/>
</action-outputs>
<component-definition>
<class>org.pentaho.platform.plugin.action.chartbeans.ChartComponent</class>
</component-definition>
<action-name>Test the test POJO</action-name>
<logging-level>DEBUG</logging-level>
</action-definition>
</actions>
</action-sequence>
|
Results
Here is the result using the JFreeChart plugin for Pentaho ChartBeans:
Panel | ||||
---|---|---|---|---|
| ||||
|
Here is the result (in the form of a screenshot) using the Open Flash Chart plugin for Pentaho ChartBeans:
Panel | ||||
---|---|---|---|---|
| ||||
The full source of this example is attached. It is a zipped Eclipse project called pentaho-chartbeans-demo.
Who's Using Pentaho ChartBeans
org.pentaho.platform.plugin.action.chartbeans.ChartComponent
Access to Pentaho ChartBeans in the Pentaho BI Platform is provided by the Pentaho ChartBeans ChartComponent
. You can use ChartComponent
in your action sequences to generate charts. Documentation on Pentaho ChartBeans ChartComponent is currently in progress.
Summary
...
| |||
|
Status
ChartComponent (In Progress)
Access to Pentaho ChartBeans in the Pentaho BI Platform is provided by the Pentaho ChartBeans ChartComponent
. You can use ChartComponent
in your action sequences to generate charts. Documentation on Pentaho ChartBeans ChartComponent is currently in progress.
CDF Widget (Planned)
A Community Dashboard Framework (CDF) widget is planned. This will allow the dashboard to render a Pentaho ChartBeans chart.
Contributing
SVN locations appear at the bottom of this document. Building the projects follows the Pentaho Common Build. Run ant -projecthelp
for a list of the most common targets.
To discuss Pentaho ChartBeans, please post in the Pentaho Forums. Use the BI Server and Platform forum.
To create defect reports, improvement requests please use Pentaho JIRA. Use the Pentaho BI Server project and the ChartBeans component when creating JIRA cases.
Related Items
- Pentaho ChartBeans Developer Documentation 2
- JFreeChart
- Open Flash Chart
- Pentaho ChartBeans Subversion repository: svn://source.pentaho.org/svnroot/pentaho-commons/pentaho-chartbeans/trunk
- Pentaho ChartBeans ChartComponent Subversion repository: svn://source.pentaho.org/svnroot/bi-platform-v2/trunk/bi-platform-plugin-actions
1 Pentaho ChartBeans name is subject to change.
2 Be very careful when wading through the Pentaho ChartBeans developer documentation. It was created while Pentaho ChartBeans was being architected and therefore could have inaccurate information. We Pentaho developers are in the process of bringing it up to date to reflect the current code.