Salientprocess acquisition by IBM will make SPARK toolkit core part of IBM BPM in future release. SPARK introduces some nice new concepts, one of it is addressing that keeps SPARK containers invisible. Its public API promises to make your own coach view a container and I needed it on my code. So I tried and it did not work. Few hours of experiments with debugging SPARK code led me to workaround and defect report.
SPARK UI toolkit is built on top of IBM BPM coach framework and tries to hide some of its quirks. One of it is addressing: in coach framework navigation thru hierarchy of objects requires walking thru each level using
context.getSubview() multiple times. Such boilerplate code breaks easily on layout reogranization. SPARK addressing copes with both problems allowing path-like navigation and by distinguishing views from containers (like layouts) making the latter non-addressable.
Let see it by example. Imagine we have own widget identified by “Block” that has content box filled by vertical layout “Vertical”, and inside layout there is text field with “Text” view id.
// classic navigation var block = this.context.getSubview("Block"); var vert = block.context.getSubview("Vertical"); var text = vert.context.getSubview("Text"); // spark navigation (note layout skipped in address!) var text = bpmext.ui.getView("/Block/Text");
Now, what happen if we add extra horizontal layout between vertical and text?
// classic navigation - must be modified var block = this.context.getSubview("Block"); var vert = block.context.getSubview("Vertical"); var horiz = vert.context.getSubview("Horizontal"); var text = vert.context.getSubview("Text"); // spark navigation - simply left intact! var text = bpmext.ui.getView("/Block/Text");
What is even more attracting is that “Block” could be also invisble in addressing if its plays container role. This way with or without block we could simply address text by
getView("Text")! And SPARK UI documentation clearly says that
bpmext.ui.loadContainer() called on load handler of coach view serves this purpose.
Let start with regular coach view called “Custom Container CV” that has content box inside to place other coach views. To test behavior I made up a human service with coach holding four levels deep hierarchy mixing layouts (marked by red border) and my contaiers (blue borders). On the bottom there is text area that reports its own path plus collects path reports on all four containers.
Initially paths were reported as follows:
bpmext.ui.getCoachNGViewPath(textarea): Horizontal/Custom1/Vertical/Custom2 bpmext.ui.getViewPath(textarea): /Custom1/Custom2/Text Container: Custom2 bpmext.ui.getContainerPath(): null bpmext.ui.getViewPath(): /Custom1/Custom2 Container: Custom1 bpmext.ui.getContainerPath(): /Custom1 /* null expected, a SPARK bug? */ bpmext.ui.getViewPath(): /Custom1 Container: Vertical bpmext.ui.getContainerPath(): /Custom1/Vertical bpmext.ui.getViewPath(): null Container: Horizontal bpmext.ui.getContainerPath(): /Horizontal bpmext.ui.getViewPath(): null
What you can read from it is that we have four coach views (
getCoachNGViewPath), first horizontal layer then our custom view, then vertical layout, another custom view, and text area at the end.
Note that regular view path (
getViewPath) run on text area widget does not “see” SPARK layouts. Also note that view path for containers is null. For container path it is
a bit more irregular as only leaf (deepest) container is always available e.g. for “Vertical” container the path is
/Custom1/Vertical missing "Horizontal" at the beginning.
When "Custom container CV" is turned into SPARK container paths are reported this way:
bpmext.ui.getCoachNGViewPath(textarea): Horizontal/Custom1/Vertical/Custom2 bpmext.ui.getViewPath(textarea): /Text Container: Custom2 bpmext.ui.getContainerPath(): /Custom2 bpmext.ui.getViewPath(): null Container: Custom1 bpmext.ui.getContainerPath(): /Custom1 bpmext.ui.getViewPath(): null Container: Vertical bpmext.ui.getContainerPath(): /Vertical bpmext.ui.getViewPath(): null Container: Horizontal bpmext.ui.getContainerPath(): /Horizontal bpmext.ui.getViewPath(): null
Now it is clear that all wrappers around text area are transparent. Address path is direct, just a
/Text and all cointainers have null view paths. Interestingly container paths are dangling at root (because parent containers are still invisible even for container path?) even though "Vertical"
/Horizontal/Vertical path would be more natural then just
/Vertical. Fortunately container paths are less relevant in business logic.
Setting coach view SPARK container
SPARK 4.4.4 documentation only mentions container creation through
bpmext.ui.loadContainer(). Placed this method in coach
load lifecycle handler made coach view addressable as container (
My coach view was still wronlgy available as regular view (view
bpmext.ui.getViewPath() methods). It took me long time inspecting SPARK layouts code to understand SPARK public API shortcomings and make my coach view working as container -- I shared my concerns on product forum and SPARK support team confirmed my findings.
As of today the only way to make coach view true SPARK container is twofolds:
- set coach views property
- register coach view as container calling
bpmext.ui.loadContainer()during load phase.
I hope that SPARK team will fix its API in one of next releases, I will keep you posted.
2016-12-21 update: as of SPARK toolkit version 4.4.5 and 4.4.6 this issue still remains not fixed.