Plugin: ZK Charts Components

From iDempiere en
Revision as of 09:49, 20 August 2026 by JamesChu (talk | contribs)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

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.