Difference between revisions of "Plugin: ZK Charts Components"

From iDempiere en
Tag: visualeditor
 
(9 intermediate revisions by the same user not shown)
Line 1: Line 1:
 
*'''Creator:''' [[User:JamesChu|James Chu]]
 
*'''Creator:''' [[User:JamesChu|James Chu]]
 
*'''SPONSOR:''' [https://www.zkoss.org/ zkoss.org]
 
*'''SPONSOR:''' [https://www.zkoss.org/ zkoss.org]
−
*'''License:''' This plugin is licensed under the GNU [http://www.gnu.org/licenses/gpl-2.0.html GPLv2] or later. The plugin source code itself does not include ZK Charts.
+
*'''License:''' The plugin source code is licensed under the GNU [http://www.gnu.org/licenses/gpl-2.0.html GPLv2] or later. The fragment you download does embed commercially licensed ZK Evaluation binaries – see [[#Licensing|Licensing]].
−
*'''Source:''' [https://github.com/zkoss-demo/zkoss-idempiere-ee-plugin GitHub repository]
+
*'''Source:''' [https://github.com/zkoss-demo/zkoss-idempiere-addon-plugin GitHub repository]
−
*'''Dependencies:''' This plugin depends on ZK Charts, which are commercial products and are not covered by this plugin’s open-source license.  Users must obtain valid licenses for these components separately for production use.
+
*'''Supported branches:''' <code>main</code> for iDempiere 13, [https://github.com/zkoss-demo/zkoss-idempiere-addon-plugin/tree/v12 <code>v12</code>] for iDempiere 12.
 +
*'''Related:''' [[Plugin: ZK Pivottable Components]] – lives in the same repository and builds on this one.
 +
 
 
==Description==
 
==Description==
−
*This plugin enables iDempiere implementors to use '''ZK Charts components''' in iDempiere without modifying iDempiere core. It is designed as an optional add-on: you can install/uninstall it as a standard iDempiere OSGi plugin.
+
*This plugin enables iDempiere implementors to use '''ZK Charts components''' in iDempiere without modifying iDempiere core. It is designed as an optional add-on: you can install and uninstall it as a standard iDempiere OSGi plugin.
−
*ZK Charts is a commercial product (evaluation is available via ZK download center).
+
*It covers two ways of using ZK Charts:
−
==Features==
+
*#'''Globally''' – replace the chart rendering iDempiere already does, so that every existing dashboard chart, performance goal and chart field is drawn with ZK Charts, without changing a single application dictionary record.
−
*Integrate ZK Charts libraries into the iDempiere runtime as an optional add-on.
+
*#'''In a dashboard''' – a sales and inventory dashboard that redraws itself through ZK server push whenever an order or shipment is saved.
−
*Provide example window/form(s) to verify charts render correctly in iDempiere.
+
*'''Nothing is one-way.''' Uninstalling the bundle silently restores the core rendering, and any exception during rendering makes the service return <code>false</code> so that iDempiere falls through to the next renderer rather than showing an empty panel.
−
*Keep iDempiere core unchanged (plugin-based integration).
+
 
 +
[[File:Zkcharts-renderer.png|thumb|center|600px|An existing AD_Chart rendered with ZK Charts]]
 +
[[File:Zkcharts-dashboard.png|thumb|center|600px|The live sales and inventory dashboard]]
 +
 
 +
==Why ZK Charts rather than the renderer already in core==
 +
*iDempiere 13 ships billboard.js in core at no cost, and it is a perfectly capable client-side chart library. The honest comparison is narrower than "static images versus interactive charts" – that difference is against '''JFreeChart''', which is deprecated in v13.
 +
{| class="wikitable"
 +
! !! JFreeChart ''(deprecated in v13)'' !! billboard.js ''(v13 default)'' !! ZK Charts
 +
|-
 +
| Rendering || server-side PNG image || client-side SVG || client-side SVG
 +
|-
 +
| Interactive tooltips || – || yes || yes
 +
|-
 +
| Legend toggling || – || yes || yes
 +
|-
 +
| Entry animation || – || yes || yes
 +
|-
 +
| Export the chart as PNG / SVG / PDF / CSV || – || – || '''built in''', from the chart's own context menu
 +
|-
 +
| Click-to-zoom to the underlying records || yes || yes || yes
 +
|-
 +
| <code>AD_Chart</code> chart types covered || all || all || all
 +
|-
 +
| Java API available to '''your own''' plugin || the JFreeChart API || the <code>Billboard</code> component: title, type, orientation, legend, axis labels, series colors, time series || the full <code>org.zkoss.chart</code> model – plot options, per-point markers and styling, multiple axes, chart-level events, accessibility descriptions
 +
|-
 +
| Accessibility descriptions per point/series || – || – || yes
 +
|-
 +
| Support || community || community || commercial, under the ZK Charts license
 +
|-
 +
| Cost || free || free || commercial license, evaluation available
 +
|}
 +
*If all you need is a readable chart on a dashboard, billboard.js already does that. The two reasons to add this plugin are '''export straight from the chart''' and '''the much larger API surface when you build charts in your own forms''' – plus commercial support on the component itself.
 +
 
 +
==Requirements==
 +
{| class="wikitable"
 +
! Item !! Version
 +
|-
 +
| iDempiere || 13 ''(use the <code>v12</code> branch for iDempiere 12)''
 +
|-
 +
| Java runtime || 17
 +
|-
 +
| ZK CE bundled with iDempiere || 10.0.1
 +
|-
 +
| ZK Charts || 12.5.0.0-Eval
 +
|}
 +
 
 
==Installation==
 
==Installation==
−
*Download the release / install package from the GitHub repository.
+
*'''Prebuilt jars are attached to each [https://github.com/zkoss-demo/zkoss-idempiere-addon-plugin/releases GitHub release]''' – nothing has to be built to try this:
 +
{| class="wikitable"
 +
! File !! Install it when
 +
|-
 +
| <code>org.idempiere.zkcharts.fragment-13.0.0.jar</code> || Always – both plugins need it
 +
|-
 +
| <code>org.idempiere.zkcharts.renderer-13.0.0.jar</code> || You want every existing iDempiere chart drawn with ZK Charts
 +
|-
 +
| <code>org.idempiere.zkcharts.dashboard-13.0.0.jar</code> || You want the live sales dashboard
 +
|}
 +
*To build them yourself instead, see [[#Building from source|Building from source]] at the end of this page.
 +
*'''The order matters''' – a fragment only takes effect after its host bundle is re-resolved, which means a restart:
 +
*#Install <code>org.idempiere.zkcharts.fragment</code> through the Felix Web Console (<code>/osgi/system/console/bundles</code>).
 +
*#'''Restart the iDempiere runtime.'''
 +
*#Install <code>org.idempiere.zkcharts.renderer</code> and/or <code>org.idempiere.zkcharts.dashboard</code>.
 +
*#On the '''Bundles''' page, confirm the fragment shows as ''Fragment'' and the plugins as ''Active'' – not merely ''Resolved''.
 +
*#Log out and back in, so the menu tree is rebuilt with the entries the plugin adds.
 +
*The dashboard plugin adds its menu entries through a 2Pack applied by its bundle activator; no manual import is required.
  
−
*Install the generated OSGi plugin + fragment into your iDempiere runtime (same way as other plugins).  ''Note: A server restart may be required after installing fragments in some environments.''
 
 
==Usage==
 
==Usage==
−
*After installation, open the included example (if any) from the iDempiere menu and verify charts render correctly.
+
 
−
*To use charts in your own windows/forms, add dependencies on this plugin and develop with ZK Charts as usual.
+
===The client you log in as matters===
−
*Demo builds may include evaluation versions of ZK Charts for demonstration purposes only. A valid commercial license is required for production use.
+
*Every chart is scoped to the logged in client, and most of them to completed sales orders.
 +
*<code>SuperUser</code> signs in to the '''System''' client (<code>AD_Client_ID = 0</code>), which by design holds the dictionary and no business data at all – so every chart is legitimately empty and nothing is broken.
 +
*Log in as <code>GardenAdmin</code> to the '''GardenWorld''' client instead.
 +
 
 +
===Using ZK Charts in your own plugin===
 +
*This is the part most plugin developers come for. There are three pieces, and the third one is the rule that follows from the fragment design.
 +
*'''1. Compile-time dependency.''' Add the ZK Evaluation repository and the ZK Charts jar to your bundle's <code>pom.xml</code>. Tycho copies it onto the compile classpath; it is '''not''' embedded in your jar.
 +
<syntaxhighlight lang="xml">
 +
<repositories>
 +
  <repository>
 +
    <id>ZK PE/EE Evaluation</id>
 +
    <url>https://mavensync.zkoss.org/eval/</url>
 +
  </repository>
 +
</repositories>
 +
<dependencies>
 +
  <!-- Compile time only: at runtime the classes come from
 +
      org.idempiere.zkcharts.fragment through org.adempiere.ui.zk -->
 +
  <dependency>
 +
    <groupId>org.zkoss.chart</groupId>
 +
    <artifactId>zkcharts</artifactId>
 +
    <version>12.5.0.0-Eval</version>
 +
  </dependency>
 +
</dependencies>
 +
</syntaxhighlight>
 +
*'''2. Runtime wiring in <code>META-INF/MANIFEST.MF</code>.''' You do '''not''' import <code>org.zkoss.chart</code> directly. The fragment exports those packages ''through its host'', so requiring the host bundle is what makes them visible:
 +
<syntaxhighlight lang="text">
 +
Require-Bundle: org.adempiere.base;bundle-version="13.0.0",
 +
org.adempiere.ui.zk;bundle-version="13.0.0",
 +
zk;bundle-version="10.0.1",
 +
zul;bundle-version="10.0.1"
 +
</syntaxhighlight>
 +
*'''3. The rule.''' You compile against a jar on the Maven classpath but resolve at runtime through the fragment – so '''your bundle will not resolve unless <code>org.idempiere.zkcharts.fragment</code> is installed and the runtime has been restarted since'''. A bundle stuck at ''Resolved'' or ''Installed'' is almost always this.
 +
*'''A working ZUL.''' <code>&lt;charts&gt;</code> is a normal ZK component once the fragment is in place:
 +
<syntaxhighlight lang="xml">
 +
<?xml version="1.0" encoding="UTF-8"?>
 +
<zk>
 +
  <window apply="org.example.myplugin.MyChartComposer">
 +
    <charts id="chart" type="spline" title="Monthly Average Temperature"/>
 +
  </window>
 +
</zk>
 +
</syntaxhighlight>
 +
<syntaxhighlight lang="java">
 +
public class MyChartComposer extends SelectorComposer<Component> {
 +
    @Wire private Charts chart;
 +
 
 +
    @Override
 +
    public void doAfterCompose(Component comp) throws Exception {
 +
        super.doAfterCompose(comp);
 +
        chart.getYAxis().getTitle().setText("Temperature (°C)");
 +
        chart.getTooltip().setShared(true);
 +
 
 +
        Series tokyo = chart.getSeries();
 +
        tokyo.setName("Tokyo");
 +
        tokyo.getMarker().setSymbol("square");
 +
        for (double v : new double[] {5.2, 5.7, 8.7, 13.9, 18.2, 21.4, 25.0})
 +
            tokyo.addPoint(v);
 +
    }
 +
}
 +
</syntaxhighlight>
 +
*The API is the Highcharts object model exposed as Java: <code>Charts</code>, <code>Series</code>, <code>Point</code>, <code>PlotOptions</code>, axes, <code>Tooltip</code>, <code>Marker</code>, per-point <code>Accessibility</code>. See the [https://www.zkoss.org/product/zkcharts ZK Charts product page] and its [https://www.zkoss.org/zkchartsdemo/ live demo gallery] for the full component set.
 +
*The <code>org.idempiere.zkcharts.dashboard</code> bundle carries a minimal working example of exactly this. Its menu entry ships '''deactivated''' because the dashboard supersedes it; reactivate the <code>AD_Menu</code> and <code>AD_Form</code> records named "ZK Charts Example" to open it in the UI.
 +
 
 +
==Verifying==
 +
 
 +
===Verifying the renderer===
 +
*The renderer has no menu entry, so it is verified by opening things iDempiere already draws.
 +
*#'''Felix Console → Components''': <code>...renderer.ChartRendererServiceImpl</code> must be ''satisfied/active''. A bundle showing ''Active'' does not by itself mean the service registered.
 +
*#Open the '''Chart''' window and pick any chart definition. The preview should show hover tooltips, an entry animation and an export menu.
 +
*#The decisive test: ''Stop'' the renderer bundle in the Felix Console and reload the record – the chart falls back to billboard. ''Start'' it again and reload – ZK Charts is back.
 +
*#Click a bar or a slice; it must still zoom to the underlying records.
 +
*#Open a '''Performance Goal''' record to cover the goal graph and the gauge indicator.
 +
*#Any <code>Failed to render ... with ZK Charts</code> warning in the log means that path silently fell back to billboard.
 +
 
 +
===Creating test data===
 +
*The charts read <code>C_Order</code> and <code>C_OrderLine</code> only – no shipment, invoice or accounting document is required.
 +
*Create a '''Business Partner''': ''Search Key'', ''Name'', a '''Business Partner Group''' (mandatory, with no default), and tick '''Customer'''. Add a row on the '''Location''' tab, otherwise an order cannot be raised.
 +
*Create a '''Sales Order''' with the document type '''Standard Order''', add lines with products that carry a price, then press '''Complete'''.
 +
*Use ''Standard Order'' deliberately: unlike ''POS Order'' and ''On Credit Order'' it does not auto-generate an invoice on completion, which keeps the accounting setup out of the picture entirely.
 +
 
 +
==Troubleshooting==
 +
{| class="wikitable"
 +
! Symptom !! Cause !! Fix
 +
|-
 +
| Every chart empty, KPIs all zero || Signed in to the System client, which holds no business data || Log in to GardenWorld or another client with data
 +
|-
 +
| Bundle stays ''Resolved'', never ''Active'' || The fragment is missing, or the runtime was not restarted after installing it || Install the fragment, then restart
 +
|-
 +
| Charts still look unchanged after installing the renderer || The declarative service did not register || Check '''Components''', not just '''Bundles'''
 +
|-
 +
| Completing an order fails with ''No account defined for this organization / currency'' || Despite the wording this is a '''bank''' account: the payment rule is ''Cash'' and the document type auto-creates an invoice, but no <code>C_BankAccount</code> matches the order's organization and currency || Use ''Standard Order'' with payment rule ''On Credit'', or create a bank account in the '''same organization''' – the lookup matches <code>AD_Org_ID</code> exactly, so one on <code>*</code> will not do
 +
|}
 +
 
 +
==How it works==
 +
 
 +
===Rendering every iDempiere chart with ZK Charts===
 +
*<code>org.idempiere.zkcharts.renderer</code> needs no configuration and adds no menu entry. It registers an implementation of the OSGi service <code>IChartRendererService</code> with a higher service ranking than the ones in core, and iDempiere then asks it first.
 +
{| class="wikitable"
 +
! Implementation !! <code>service.ranking</code>
 +
|-
 +
| <code>org.idempiere.zkcharts.renderer</code> (this plugin) || '''100'''
 +
|-
 +
| <code>org.idempiere.zk.billboard.chart</code> (billboard.js, the v13 default) || 0
 +
|-
 +
| <code>org.adempiere.webui.apps.graph.jfreegraph</code> (JFreeChart, deprecated since v13) || -1
 +
|}
 +
*Everything that draws a chart in the web UI goes through that service, so all of the following change at once:
 +
{| class="wikitable"
 +
! Consumer !! What it draws
 +
|-
 +
| <code>DashboardController</code> || <code>PA_DashboardContent</code> chart gadgets
 +
|-
 +
| <code>WGraph</code> || <code>PA_Goal</code> performance graphs
 +
|-
 +
| <code>WPerformanceIndicator</code> || <code>PA_Goal</code> performance indicators, drawn as a gauge
 +
|-
 +
| <code>WChartEditor</code> || Chart fields inside a window
 +
|}
 +
*The data loading is deliberately identical to the core billboard renderer, so existing <code>AD_Chart</code> definitions keep producing exactly the same numbers – only the widget is swapped.
 +
 
 +
====Chart type mapping====
 +
{| class="wikitable"
 +
! <code>AD_Chart.ChartType</code> !! ZK Charts
 +
|-
 +
| Bar / 3D Bar || <code>column</code>, or <code>bar</code> when Chart Orientation is Horizontal
 +
|-
 +
| Stacked Bar / 3D Stacked Bar || the same, with <code>stacking: normal</code>
 +
|-
 +
| Line / 3D Line || <code>line</code>
 +
|-
 +
| Area || <code>area</code>
 +
|-
 +
| Stacked Area || <code>area</code> with <code>stacking: normal</code>
 +
|-
 +
| Pie / 3D Pie || <code>pie</code>
 +
|-
 +
| Ring || <code>pie</code> with <code>innerSize: 60%</code>
 +
|-
 +
| Waterfall || <code>waterfall</code>, running totals converted to per-step deltas
 +
|}
 +
*3D variants render as their 2D counterpart, which is also what the core billboard renderer does. <code>PA_Goal</code> indicators render as a <code>gauge</code> whose plot bands come from the goal's color schema.
 +
 
 +
===Live sales and inventory dashboard===
 +
*Menu: '''ZK Charts Live Sales Dashboard'''
 +
*Four KPI tiles and three charts – sales by month, top products by sales, and top products on hand. Nothing has to be refreshed by hand:
 +
*#An OSGi <code>EventHandler</code> subscribes to <code>PO_POST_CREATE</code>, <code>PO_POST_UPADTE</code> ''(sic – the typo is in iDempiere core)'' and <code>PO_POST_DELETE</code>, filtered to <code>C_Order</code>, <code>C_OrderLine</code>, <code>M_InOut</code> and <code>M_InOutLine</code>. These ''post'' topics fire '''after the transaction commits''', so the reload never reads uncommitted rows.
 +
*#The handler runs on whichever thread saved the record, so it does nothing beyond <code>Executions.schedule(...)</code>, which hands the reload to the desktop's event thread.
 +
*#ZK server push sends the new data to the browser.
 +
*Two details worth copying into your own plugin:
 +
**'''Coalescing.''' Completing one order fires a burst of events; an <code>AtomicBoolean</code> collapses them into a single reload.
 +
**'''Unregistering.''' The handler is removed in <code>onPageDetached</code>, otherwise every tab a user ever opened would keep a live subscription for the lifetime of the runtime.
 +
 
 +
==Components==
 +
{| class="wikitable"
 +
! Bundle !! Kind !! Purpose
 +
|-
 +
| <code>org.idempiere.zkcharts.fragment</code> || OSGi fragment || Attaches ZK Charts to the class loader of <code>org.adempiere.ui.zk</code>. '''Required by both plugins below.'''
 +
|-
 +
| <code>org.idempiere.zkcharts.renderer</code> || Plugin || The global chart renderer.
 +
|-
 +
| <code>org.idempiere.zkcharts.dashboard</code> || Plugin || The live sales dashboard, plus a minimal <code>&lt;charts&gt;</code> ZUL sample.
 +
|}
 +
 
 +
*The two plugins are independent – install either on its own, or both. Both need the ZK Charts fragment.
 +
*The same repository also contains [[Plugin: ZK Pivottable Components]], which is documented separately.
 +
 
 +
===Why a fragment is needed===
 +
*ZK discovers its components through <code>metainfo/zk/lang-addon.xml</code>, which is loaded with the class loader of the bundle ZK runs in – in iDempiere that is <code>org.adempiere.ui.zk</code>.
 +
*OSGi bundles have isolated class loaders, and a '''fragment''' is the only standard way to add resources to another bundle's class loader without modifying it.
 +
*That is why the ZK Charts jar is delivered as a fragment of <code>org.adempiere.ui.zk</code> rather than embedded in the plugins.
 +
 
 +
==Licensing==
 +
*'''The plugin source''' is GPLv2 or later. Nothing in the iDempiere repository is modified.
 +
*'''The fragment you download is not.''' A fragment exists to put the product jars on the host bundle's class loader, so the released fragment '''embeds them''' – <code>org.idempiere.zkcharts.fragment</code> carries ZK Charts, about 7 MB. Those are commercially licensed Evaluation binaries governed by ZK's license, not by the GPL. The other bundles in this plugin contain only this project's own code and are GPLv2 throughout.
 +
*'''ZK Charts is a commercial product''' and is not covered by the plugin's open-source license. The build pulls it from ZK's '''Evaluation''' repository, so everything on this page can be tried at no cost. The Evaluation binaries are for evaluation only – installing them is fine, redistributing them is not – and a valid license or subscription must be obtained separately before production use.
 +
*'''No lock-in.''' Uninstalling the bundle silently restores iDempiere's core chart rendering – the application dictionary was never touched, so there is nothing to migrate back. Evaluating this plugin is a reversible decision.
 +
*'''To obtain a license or ask about terms''', contact the ZK Framework team at [email protected] or see the [https://www.zkoss.org/product/zkcharts ZK Charts product page].
 +
<!-- TODO (page owner): state explicitly what the Evaluation build limits (expiry? watermark? feature gating?) and the licensing model (per developer / per production server). Readers currently have to ask by email to find out. -->
 +
<!-- TODO (page owner): add a maintenance commitment next to Creator/SPONSOR - which branches are supported, and how soon a fragment build follows an iDempiere release. -->
 +
 
 +
==Building from source==
 +
*Requires Git, Maven, JDK 17 and a local p2 repository built from iDempiere core. Full instructions, including the target platform fix-ups, are in the repository README.
 +
<syntaxhighlight lang="bash">
 +
git clone --branch release-13 https://github.com/idempiere/idempiere.git idempiere
 +
cd idempiere && mvn clean install
 +
 
 +
git clone https://github.com/zkoss-demo/zkoss-idempiere-addon-plugin.git
 +
cd zkoss-idempiere-addon-plugin
 +
(cd org.idempiere.zkcharts.fragment  && mvn clean verify)
 +
(cd org.idempiere.zkcharts.renderer  && mvn clean verify)
 +
(cd org.idempiere.zkcharts.dashboard && mvn clean verify)
 +
</syntaxhighlight>
 +
*The first build must have network access: ZK Charts is downloaded from the ZK Evaluation repository, not from Maven Central.
 +
 
 
==Feedback==
 
==Feedback==
 
*If you would like to discuss specific use cases or workflows for this plugin, we’d be happy to hear from you.  Please feel free to contact the ZK Framework team at [email protected].
 
*If you would like to discuss specific use cases or workflows for this plugin, we’d be happy to hear from you.  Please feel free to contact the ZK Framework team at [email protected].
 
*If you want to provide additional comments, please use:
 
*If you want to provide additional comments, please use:
 
**'''General support forum:''' [https://groups.google.com/forum/#!forum/idempiere iDempiere Community]
 
**'''General support forum:''' [https://groups.google.com/forum/#!forum/idempiere iDempiere Community]
−
**'''Issues for this plugin:''' [https://github.com/zkoss-demo/zkoss-idempiere-zkcharts-plugin/issues GitHub Issues]
+
**'''Issues for this plugin:''' [https://github.com/zkoss-demo/zkoss-idempiere-addon-plugin/issues GitHub Issues]
 +
 
 +
==See also==
 +
*Other ZK plugins for iDempiere:
 +
**[[Plugin: ZK Pivottable Components]]
 +
**[[Plugin: ZK Enterprise Components]]
 +
**[[Plugin: Keikai Spreadsheet Enterprise Component]]
 +
*Other charting plugins in this category:
 +
**[[Plugin: Billboard.js Chart]]
 +
**[[Plugin: Chart Maker]]
 +
*Plugin development:
 +
**[[Developing Plug-Ins - Get your Plug-In running]]
 +
**[[Make Zk WebApp OSGi]]
 +
*[https://www.zkoss.org/product/zkcharts ZK Charts] · [https://www.zkoss.org/zkchartsdemo/ ZK Charts demo gallery]
 +
 
 
[[Category:Available Plugins]]
 
[[Category:Available Plugins]]

Latest revision as of 09:49, 20 August 2026

Description

  • This plugin enables iDempiere implementors to use ZK Charts components in iDempiere without modifying iDempiere core. It is designed as an optional add-on: you can install and uninstall it as a standard iDempiere OSGi plugin.
  • It covers two ways of using ZK Charts:
    1. Globally – replace the chart rendering iDempiere already does, so that every existing dashboard chart, performance goal and chart field is drawn with ZK Charts, without changing a single application dictionary record.
    2. In a dashboard – a sales and inventory dashboard that redraws itself through ZK server push whenever an order or shipment is saved.
  • Nothing is one-way. Uninstalling the bundle silently restores the core rendering, and any exception during rendering makes the service return false so that iDempiere falls through to the next renderer rather than showing an empty panel.
An existing AD_Chart rendered with ZK Charts
The live sales and inventory dashboard

Why ZK Charts rather than the renderer already in core

  • iDempiere 13 ships billboard.js in core at no cost, and it is a perfectly capable client-side chart library. The honest comparison is narrower than "static images versus interactive charts" – that difference is against JFreeChart, which is deprecated in v13.
JFreeChart (deprecated in v13) billboard.js (v13 default) ZK Charts
Rendering server-side PNG image client-side SVG client-side SVG
Interactive tooltips – yes yes
Legend toggling – yes yes
Entry animation – yes yes
Export the chart as PNG / SVG / PDF / CSV – – built in, from the chart's own context menu
Click-to-zoom to the underlying records yes yes yes
AD_Chart chart types covered all all all
Java API available to your own plugin the JFreeChart API the Billboard component: title, type, orientation, legend, axis labels, series colors, time series the full org.zkoss.chart model – plot options, per-point markers and styling, multiple axes, chart-level events, accessibility descriptions
Accessibility descriptions per point/series – – yes
Support community community commercial, under the ZK Charts license
Cost free free commercial license, evaluation available
  • If all you need is a readable chart on a dashboard, billboard.js already does that. The two reasons to add this plugin are export straight from the chart and the much larger API surface when you build charts in your own forms – plus commercial support on the component itself.

Requirements

Item Version
iDempiere 13 (use the v12 branch for iDempiere 12)
Java runtime 17
ZK CE bundled with iDempiere 10.0.1
ZK Charts 12.5.0.0-Eval

Installation

  • Prebuilt jars are attached to each GitHub release – nothing has to be built to try this:
File Install it when
org.idempiere.zkcharts.fragment-13.0.0.jar Always – both plugins need it
org.idempiere.zkcharts.renderer-13.0.0.jar You want every existing iDempiere chart drawn with ZK Charts
org.idempiere.zkcharts.dashboard-13.0.0.jar You want the live sales dashboard
  • To build them yourself instead, see Building from source at the end of this page.
  • The order matters – a fragment only takes effect after its host bundle is re-resolved, which means a restart:
    1. Install org.idempiere.zkcharts.fragment through the Felix Web Console (/osgi/system/console/bundles).
    2. Restart the iDempiere runtime.
    3. Install org.idempiere.zkcharts.renderer and/or org.idempiere.zkcharts.dashboard.
    4. On the Bundles page, confirm the fragment shows as Fragment and the plugins as Active – not merely Resolved.
    5. Log out and back in, so the menu tree is rebuilt with the entries the plugin adds.
  • The dashboard plugin adds its menu entries through a 2Pack applied by its bundle activator; no manual import is required.

Usage

The client you log in as matters

  • Every chart is scoped to the logged in client, and most of them to completed sales orders.
  • SuperUser signs in to the System client (AD_Client_ID = 0), which by design holds the dictionary and no business data at all – so every chart is legitimately empty and nothing is broken.
  • Log in as GardenAdmin to the GardenWorld client instead.

Using ZK Charts in your own plugin

  • This is the part most plugin developers come for. There are three pieces, and the third one is the rule that follows from the fragment design.
  • 1. Compile-time dependency. Add the ZK Evaluation repository and the ZK Charts jar to your bundle's pom.xml. Tycho copies it onto the compile classpath; it is not embedded in your jar.
<repositories>
  <repository>
    <id>ZK PE/EE Evaluation</id>
    <url>https://mavensync.zkoss.org/eval/</url>
  </repository>
</repositories>
<dependencies>
  <!-- Compile time only: at runtime the classes come from
       org.idempiere.zkcharts.fragment through org.adempiere.ui.zk -->
  <dependency>
    <groupId>org.zkoss.chart</groupId>
    <artifactId>zkcharts</artifactId>
    <version>12.5.0.0-Eval</version>
  </dependency>
</dependencies>
  • 2. Runtime wiring in META-INF/MANIFEST.MF. You do not import org.zkoss.chart directly. The fragment exports those packages through its host, so requiring the host bundle is what makes them visible:
Require-Bundle: org.adempiere.base;bundle-version="13.0.0",
 org.adempiere.ui.zk;bundle-version="13.0.0",
 zk;bundle-version="10.0.1",
 zul;bundle-version="10.0.1"
  • 3. The rule. You compile against a jar on the Maven classpath but resolve at runtime through the fragment – so your bundle will not resolve unless org.idempiere.zkcharts.fragment is installed and the runtime has been restarted since. A bundle stuck at Resolved or Installed is almost always this.
  • A working ZUL. <charts> is a normal ZK component once the fragment is in place:
<?xml version="1.0" encoding="UTF-8"?>
<zk>
  <window apply="org.example.myplugin.MyChartComposer">
    <charts id="chart" type="spline" title="Monthly Average Temperature"/>
  </window>
</zk>
public class MyChartComposer extends SelectorComposer<Component> {
    @Wire private Charts chart;

    @Override
    public void doAfterCompose(Component comp) throws Exception {
        super.doAfterCompose(comp);
        chart.getYAxis().getTitle().setText("Temperature (°C)");
        chart.getTooltip().setShared(true);

        Series tokyo = chart.getSeries();
        tokyo.setName("Tokyo");
        tokyo.getMarker().setSymbol("square");
        for (double v : new double[] {5.2, 5.7, 8.7, 13.9, 18.2, 21.4, 25.0})
            tokyo.addPoint(v);
    }
}
  • The API is the Highcharts object model exposed as Java: Charts, Series, Point, PlotOptions, axes, Tooltip, Marker, per-point Accessibility. See the ZK Charts product page and its live demo gallery for the full component set.
  • The org.idempiere.zkcharts.dashboard bundle carries a minimal working example of exactly this. Its menu entry ships deactivated because the dashboard supersedes it; reactivate the AD_Menu and AD_Form records named "ZK Charts Example" to open it in the UI.

Verifying

Verifying the renderer

  • The renderer has no menu entry, so it is verified by opening things iDempiere already draws.
    1. Felix Console → Components: ...renderer.ChartRendererServiceImpl must be satisfied/active. A bundle showing Active does not by itself mean the service registered.
    2. Open the Chart window and pick any chart definition. The preview should show hover tooltips, an entry animation and an export menu.
    3. The decisive test: Stop the renderer bundle in the Felix Console and reload the record – the chart falls back to billboard. Start it again and reload – ZK Charts is back.
    4. Click a bar or a slice; it must still zoom to the underlying records.
    5. Open a Performance Goal record to cover the goal graph and the gauge indicator.
    6. Any Failed to render ... with ZK Charts warning in the log means that path silently fell back to billboard.

Creating test data

  • The charts read C_Order and C_OrderLine only – no shipment, invoice or accounting document is required.
  • Create a Business Partner: Search Key, Name, a Business Partner Group (mandatory, with no default), and tick Customer. Add a row on the Location tab, otherwise an order cannot be raised.
  • Create a Sales Order with the document type Standard Order, add lines with products that carry a price, then press Complete.
  • Use Standard Order deliberately: unlike POS Order and On Credit Order it does not auto-generate an invoice on completion, which keeps the accounting setup out of the picture entirely.

Troubleshooting

Symptom Cause Fix
Every chart empty, KPIs all zero Signed in to the System client, which holds no business data Log in to GardenWorld or another client with data
Bundle stays Resolved, never Active The fragment is missing, or the runtime was not restarted after installing it Install the fragment, then restart
Charts still look unchanged after installing the renderer The declarative service did not register Check Components, not just Bundles
Completing an order fails with No account defined for this organization / currency Despite the wording this is a bank account: the payment rule is Cash and the document type auto-creates an invoice, but no C_BankAccount matches the order's organization and currency Use Standard Order with payment rule On Credit, or create a bank account in the same organization – the lookup matches AD_Org_ID exactly, so one on * will not do

How it works

Rendering every iDempiere chart with ZK Charts

  • org.idempiere.zkcharts.renderer needs no configuration and adds no menu entry. It registers an implementation of the OSGi service IChartRendererService with a higher service ranking than the ones in core, and iDempiere then asks it first.
Implementation service.ranking
org.idempiere.zkcharts.renderer (this plugin) 100
org.idempiere.zk.billboard.chart (billboard.js, the v13 default) 0
org.adempiere.webui.apps.graph.jfreegraph (JFreeChart, deprecated since v13) -1
  • Everything that draws a chart in the web UI goes through that service, so all of the following change at once:
Consumer What it draws
DashboardController PA_DashboardContent chart gadgets
WGraph PA_Goal performance graphs
WPerformanceIndicator PA_Goal performance indicators, drawn as a gauge
WChartEditor Chart fields inside a window
  • The data loading is deliberately identical to the core billboard renderer, so existing AD_Chart definitions keep producing exactly the same numbers – only the widget is swapped.

Chart type mapping

AD_Chart.ChartType ZK Charts
Bar / 3D Bar column, or bar when Chart Orientation is Horizontal
Stacked Bar / 3D Stacked Bar the same, with stacking: normal
Line / 3D Line line
Area area
Stacked Area area with stacking: normal
Pie / 3D Pie pie
Ring pie with innerSize: 60%
Waterfall waterfall, running totals converted to per-step deltas
  • 3D variants render as their 2D counterpart, which is also what the core billboard renderer does. PA_Goal indicators render as a gauge whose plot bands come from the goal's color schema.

Live sales and inventory dashboard

  • Menu: ZK Charts Live Sales Dashboard
  • Four KPI tiles and three charts – sales by month, top products by sales, and top products on hand. Nothing has to be refreshed by hand:
    1. An OSGi EventHandler subscribes to PO_POST_CREATE, PO_POST_UPADTE (sic – the typo is in iDempiere core) and PO_POST_DELETE, filtered to C_Order, C_OrderLine, M_InOut and M_InOutLine. These post topics fire after the transaction commits, so the reload never reads uncommitted rows.
    2. The handler runs on whichever thread saved the record, so it does nothing beyond Executions.schedule(...), which hands the reload to the desktop's event thread.
    3. ZK server push sends the new data to the browser.
  • Two details worth copying into your own plugin:
    • Coalescing. Completing one order fires a burst of events; an AtomicBoolean collapses them into a single reload.
    • Unregistering. The handler is removed in onPageDetached, otherwise every tab a user ever opened would keep a live subscription for the lifetime of the runtime.

Components

Bundle Kind Purpose
org.idempiere.zkcharts.fragment OSGi fragment Attaches ZK Charts to the class loader of org.adempiere.ui.zk. Required by both plugins below.
org.idempiere.zkcharts.renderer Plugin The global chart renderer.
org.idempiere.zkcharts.dashboard Plugin The live sales dashboard, plus a minimal <charts> ZUL sample.
  • The two plugins are independent – install either on its own, or both. Both need the ZK Charts fragment.
  • The same repository also contains Plugin: ZK Pivottable Components, which is documented separately.

Why a fragment is needed

  • ZK discovers its components through metainfo/zk/lang-addon.xml, which is loaded with the class loader of the bundle ZK runs in – in iDempiere that is org.adempiere.ui.zk.
  • OSGi bundles have isolated class loaders, and a fragment is the only standard way to add resources to another bundle's class loader without modifying it.
  • That is why the ZK Charts jar is delivered as a fragment of org.adempiere.ui.zk rather than embedded in the plugins.

Licensing

  • The plugin source is GPLv2 or later. Nothing in the iDempiere repository is modified.
  • The fragment you download is not. A fragment exists to put the product jars on the host bundle's class loader, so the released fragment embeds them – org.idempiere.zkcharts.fragment carries ZK Charts, about 7 MB. Those are commercially licensed Evaluation binaries governed by ZK's license, not by the GPL. The other bundles in this plugin contain only this project's own code and are GPLv2 throughout.
  • ZK Charts is a commercial product and is not covered by the plugin's open-source license. The build pulls it from ZK's Evaluation repository, so everything on this page can be tried at no cost. The Evaluation binaries are for evaluation only – installing them is fine, redistributing them is not – and a valid license or subscription must be obtained separately before production use.
  • No lock-in. Uninstalling the bundle silently restores iDempiere's core chart rendering – the application dictionary was never touched, so there is nothing to migrate back. Evaluating this plugin is a reversible decision.
  • To obtain a license or ask about terms, contact the ZK Framework team at [email protected] or see the ZK Charts product page.

Building from source

  • Requires Git, Maven, JDK 17 and a local p2 repository built from iDempiere core. Full instructions, including the target platform fix-ups, are in the repository README.
git clone --branch release-13 https://github.com/idempiere/idempiere.git idempiere
cd idempiere && mvn clean install

git clone https://github.com/zkoss-demo/zkoss-idempiere-addon-plugin.git
cd zkoss-idempiere-addon-plugin
(cd org.idempiere.zkcharts.fragment  && mvn clean verify)
(cd org.idempiere.zkcharts.renderer  && mvn clean verify)
(cd org.idempiere.zkcharts.dashboard && mvn clean verify)
  • The first build must have network access: ZK Charts is downloaded from the ZK Evaluation repository, not from Maven Central.

Feedback

  • If you would like to discuss specific use cases or workflows for this plugin, we’d be happy to hear from you. Please feel free to contact the ZK Framework team at [email protected].
  • If you want to provide additional comments, please use:

See also

Cookies help us deliver our services. By using our services, you agree to our use of cookies.