Plugin: Keikai Spreadsheet Enterprise Component

From iDempiere en
Revision as of 12:25, 17 August 2026 by JamesChu (talk | contribs)

Description

  • This plugin makes Keikai Spreadsheet Enterprise – an Excel-compatible spreadsheet component – available inside iDempiere as an optional OSGi add-on, without modifying iDempiere core.
  • It follows the OSGi fragment + plugin pattern: the fragment attaches the Keikai runtime jars to iDempiere's ZK host bundle so ZK can discover the Keikai components, resources and exporters; the example plugin is an ordinary iDempiere form that uses them.
  • Install and uninstall it like any other iDempiere OSGi plugin. Nothing in the iDempiere repository or in the application dictionary is changed.
  • Keikai EE requires a commercial license or subscription from ZK; see Licensing. The build here uses Evaluation artifacts so the plugin can be tried at no cost.

What you get

  • A full spreadsheet inside an iDempiere form: cell editing, formulas, a toolbar, a formula bar and a context menu, loading and saving real .xlsx workbooks.
  • Export to PDF natively, through Keikai's own PDF exporter – registered by the fragment, not by your form.
  • The point of interest for implementors is that this is a genuine ZK component in a normal CustomForm, so a workbook can be driven from iDempiere data like any other UI.

Requirements

Item Version
iDempiere 13
Java runtime 17
ZK CE bundled with iDempiere 10.0.1
Keikai EE 6.3.0-Eval
  • Keikai is not a single-jar add-on. The fragment carries the base runtime plus several feature and support modules, and they must be kept in step with each other – see Components.

Components

Bundle Kind Purpose
org.idempiere.keikai.fragment OSGi fragment Attaches the Keikai runtime to the class loader of org.adempiere.ui.zk, and carries the Keikai-specific zk.xml. Required.
org.idempiere.keikai.example Plugin An example form rendering a Keikai spreadsheet, with New Book, Save Book and Export PDF wired up. Optional.

What the fragment carries

  • Twenty-eight jars, in five groups. A fragment has no dependency resolution of its own – whatever the runtime needs must be listed in Bundle-ClassPath and present under lib/, transitive dependencies included.
Group Jars Why
Keikai runtime keikai, keikai-model The spreadsheet component and its workbook model
Keikai EE features keikai-ex Required: the base jar marks some toolbar actions, Save Book among them, as EE-only
Workbook file I/O poi (io.keikai:poi – Keikai's own build of Apache POI, versioned with Keikai), poi-ooxml, poi-ooxml-lite, poi-ooxml-full, xmlbeans, curvesapi, commons-compress, commons-codec, commons-collections4, SparseBitSet Reading and writing real .xlsx files
Charts in a workbook zkcharts, jfreechart, jcommon Rendering charts that live inside a spreadsheet
PDF export keikai-pdf, openpdf The native PDF exporter, so Exporters.getExporter("pdf") resolves
ZK PE components zkex Keikai's UI is built on the ZK PE component set
Other transitive dependencies commons-io, commons-math3, filters, failureaccess, jsoup, rtree2, log4j-api, byte-buddy, byte-buddy-agent Pulled in by the jars above; the fragment must carry them because OSGi resolves nothing from Maven at runtime
  • The fragment's src/metainfo/zk/zk.xml sets two ZK library properties:
    • io.keikaiex.model.default.ExporterFactory.class = pdf=io.keikai.model.impl.pdf.PdfExporterFactory – registers the PDF exporter.
    • org.zkoss.zkmax.au.IWBS.disable = true – required for iDempiere 13, whose login flow echoes events to an initially invisible window.

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 Keikai jars are delivered as a fragment of org.adempiere.ui.zk rather than embedded in a plugin.

Installation

  • Obtain the two jars – see Building from source.
  • The order matters – a fragment only takes effect after its host bundle is re-resolved, which means a restart:
    1. Install org.idempiere.keikai.fragment through the Apache Felix Web Console (/osgi/system/console/bundles), or drop it into the runtime's plugin directory.
    2. Restart the iDempiere web application or OSGi runtime. This is not optional: besides re-resolving the host, ZK reads the fragment's zk.xml library properties during web application initialization, so hot-swapping only the example bundle will not pick up the PDF exporter registration.
    3. Install org.idempiere.keikai.example if you want the example form.
    4. On the Bundles page, confirm the fragment shows as Fragment of org.adempiere.ui.zk and the example plugin as Active – not merely Resolved.
    5. Log out and back in, so the menu tree is rebuilt with the entry the plugin adds.
  • The example plugin registers its menu entry through a 2Pack applied by its bundle activator; no manual import is required.
  • If you also run another ZK fragment – Plugin: ZK Enterprise Components or Plugin: ZK Charts Components – note that this fragment already carries its own zkex and zkcharts, and at different versions: zkcharts here is 12.2.0.0-Eval, while the ZK Charts fragment ships 12.5.0.0-Eval. Two fragments contributing the same jar to the same host, at two versions, is a resolution problem waiting to happen. Align the versions, or install only the fragment that covers what you need.

Usage

Verifying the installation

  • Open Keikai Spreadsheet Example from the menu. The sample workbook (blank.xlsx) should render with a toolbar, a formula bar and a working context menu.
Check What it proves
The spreadsheet grid renders at all The fragment resolved and ZK discovered Keikai's lang-addon.xml through the host
Cells accept typing and formulas The Keikai runtime and workbook model are live, not just the widget
Save Book downloads an .xlsx keikai-ex is present – this action is EE-only and is absent without it
Export PDF downloads a PDF keikai-pdf resolved and the fragment's zk.xml was read. If this fails while everything else works, the runtime was not restarted

Using Keikai in your own plugin

  • In ZUL, the component needs nothing declared. Once the fragment is installed, <spreadsheet> is part of the ZUL language for every page in the runtime:
<?xml version="1.0" encoding="UTF-8"?>
<zk>
  <div hflex="1" vflex="1">
    <spreadsheet id="spreadsheet" hflex="1" vflex="1" src="web/blank.xlsx"
                 showToolbar="true" showFormulabar="true" showContextMenu="true"
                 maxVisibleRows="100" maxVisibleColumns="40"/>
  </div>
</zk>
  • The workbook path is not a ZK resource path. Use src="web/blank.xlsx", not ~./blank.xlsx – Keikai resolves Spreadsheet.setSrc() through its own workbook loader, which is a different mechanism from ZK's component-creation path. The ZUL itself is still loaded the normal way, with Executions.createComponents("~./keikai-form.zul", ...).
  • Swap the context class loader around that call. ZK resolves ~./ resources through the thread context class loader; without the swap it looks in org.adempiere.ui.zk instead of your bundle and fails to find the ZUL. Restore it in finally.
  • In Java, the fragment exports nothing. org.idempiere.keikai.fragment declares no Export-Package, so Keikai classes sit on the host's class loader but are not visible to your bundle at compile or resolve time. There are two ways forward:
    1. Add an Export-Package for the Keikai packages you need to the fragment's manifest and rebuild it – the approach the ZK Charts fragment takes.
    2. Reach the classes reflectively through the component's own class loader – what the example form does, so that it needs no manifest change:
Component spreadsheet = form.getFellow("spreadsheet");
ClassLoader keikaiCl = spreadsheet.getClass().getClassLoader();

Class<?> exporters = Class.forName("io.keikai.api.Exporters", true, keikaiCl);
Object exporter = exporters.getMethod("getExporter", String.class).invoke(null, "pdf");
  • Reflection keeps the fragment untouched but gives up compile-time checking; exporting packages is cleaner if you are building a real form rather than a demo. Pick one deliberately.

Troubleshooting

Symptom Cause Fix
Bundle stays Resolved or Installed, never Active The fragment is missing, or the runtime was not restarted after installing it Install the fragment, then restart
The fragment itself stays Resolved Expected – fragments never become Active No action needed; confirm it is listed as a fragment of org.adempiere.ui.zk
Everything works except Export PDF The fragment's zk.xml was not read; ZK loads library properties at web application initialization Restart the web application, not just the bundle
Save Book is greyed out or missing keikai-ex is not in the fragment – the base jar marks this action EE-only Check Bundle-ClassPath and that lib/keikai-ex.jar exists in the built fragment
The spreadsheet renders but the workbook is empty src was written as ~./blank.xlsx Use the workbook-loader form, src="web/blank.xlsx"
Page not found: ~./keikai-form.zul The context class loader was not swapped before Executions.createComponents Swap to the plugin's class loader, restore in finally
A jar in Bundle-ClassPath has no file under lib/ The jar list drifted between pom.xml and MANIFEST.MF Re-align the two; see Building from source
NoClassDefFoundError for a third-party class after a version bump A new transitive dependency was not added to the fragment – OSGi will not fetch it from Maven at runtime Add the jar to both pom.xml and Bundle-ClassPath

Licensing

  • The plugin source is GPLv2 or later and contains no Keikai or ZK binaries. Nothing in the iDempiere repository is modified.
  • Keikai EE is a commercial product and is not covered by the plugin's open-source license. The build pulls the jars from ZK's Evaluation repository, so everything on this page can be tried at no cost; a valid license or subscription must be obtained separately before production use.
  • What uninstalling gives back. Removing the fragment leaves iDempiere core exactly as it was – there is nothing to migrate back. Be aware, though, that any form you wrote against the spreadsheet component stops working when the fragment goes, so plan that boundary deliberately.
  • To obtain a license or ask about terms, contact the ZK Framework team at [email protected] or see the Keikai product site.

Building from source

  • Requires Git, Maven, JDK 17 and a local p2 repository built from iDempiere core.
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-keikai-plugin.git
cd zkoss-idempiere-keikai-plugin
mvn clean verify -f parent-repository-pom.xml
  • The first build must have network access: the Keikai jars come from the ZK Evaluation repository, not from Maven Central.
  • Keep the jar list synchronized. Because Keikai is a multi-jar product with real transitive dependencies, adding or upgrading a module means touching:
    • org.idempiere.keikai.fragment/pom.xml – the dependency-copy artifacts, which populate lib/ during the validate phase
    • org.idempiere.keikai.fragment/META-INF/MANIFEST.MF – Bundle-ClassPath, one entry per jar
    • org.idempiere.keikai.fragment/src/metainfo/zk/zk.xml – only if the module needs a ZK library property, as keikai-pdf does
  • build.properties packages the whole lib/ directory, so it needs no per-jar edit – but that also means a jar left behind by an earlier build is packaged silently even when nothing references it. Clean lib/ when changing versions.
  • After building, verify that every jar named in Bundle-ClassPath actually exists under lib/:
cd org.idempiere.keikai.fragment
find lib -maxdepth 1 -type f -name '*.jar' -exec basename {} \; | sort
grep -o 'lib/[^ ,]*\.jar' META-INF/MANIFEST.MF build.properties

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.