Fork me on GitHub

Application bundle/library provides a level of abstraction on top of HTML, Bootstrap, JsTree, Font Awesome, and KnockoutJS bundles. This page outlines core concepts and shows usage examples. See Java API for additional details.


Application interface is an abstraction of a web application consisting of the following parts:

  • Header
  • Navigation bar
  • Navigation panel
  • Content panel
  • Footer

There are two implementations of this interface:

Bootstrap application

The below code snippet shows how to build a bootstrap container application with Ajax jsTree navigation panel. If desired, an application can be customized by overriding configureXXX() methods.

Application app = new BootstrapContainerApplication(Theme.Litera, false);

Tag treeContainer = app.getHTMLPage().getFactory().div();
HTMLFactory htmlFactory = HTMLFactory.INSTANCE;
	.navigationBar("Navigation bar")
	.contentPanel(/* htmlFactory.overlay("Content overlay"), */ "Content")

JsTreeFactory jsTreeFactory = JsTreeFactory.INSTANCE;


app.getHTMLPage().body(jsTreeFactory.bind(treeContainer, jsTreeFactory.buildAjaxJsTree(" == '#' ? 'jstree.json' : 'jstree-' + + '.json'", "'context-menu-' + + '.json'")));		

writeFile("app/bootstrap/index.html", app.toString());

// JsTree
JsTreeNode rootNode = jsTreeFactory.jsTreeNode();
rootNode.icon("far fa-user");
JSONArray jsTreeRootNodes = new JSONArray();
writeFile("app/bootstrap/jstree.json", jsTreeRootNodes.toString());		

JSONArray jsTreeChildNodes = new JSONArray();

JsTreeNode childNode = jsTreeFactory.jsTreeNode();
childNode.icon("far fa-user");
writeFile("app/bootstrap/jstree-"+rootNode.getId()+".json", jsTreeChildNodes.toString());

// JsTree context menu - the same menu for both nodes.
JsTreeContextMenuItem item = jsTreeFactory.jsTreeContextMenuItem();
item.label("Do it!");
item.icon("far fa-user");
item.action("window.location.href=''; console.log('hey');");

JSONObject menu = new JSONObject();
menu.put("do-it", item.toJSON());
writeFile("app/bootstrap/context-menu-"+rootNode.getId()+".json", menu.toString());
writeFile("app/bootstrap/context-menu-"+childNode.getId()+".json", menu.toString());

The application:

Single-page routing application

BootstrapContainerRouterApplication class allows to easily build Single-page applications based on Backbone router which uses jQuery load() to load content from the server.

The out of the box implementation ‘router/{target id}/{conent path}’ route by loading content from the path to the element with target id.

For example:

    • https://myapp/mypage.html#router/content/some/info will load https://myapp/some/info into an HTML element with id ‘content’.
    • https://myapp/mypage.html#router/footer//other/stuff will load https://other/stuff into an HTML element with id ‘footer’.

The router dims the target element and displays “Loading…” progress bar. If load fails it displays an error message.

The routing logic can be customized by sub-classing BootstrapContainerRouterApplication and overriding its getContentRouterCode.

An example of such customization can be found in EcoreDocumentationApplication - it loads and interpolates a customized content-router.js classloader resource. This resource always loads content to an HTML element with id content and prepends content path with doc. It also navigates to an initial route.

Bank model documentation is an example of an SPA (Single-page application) generated by leveraging EcoreDocumentationApplication.


Label is something that can be displayed in a variety of ways. It has the following attributes:

  • Icon - image URL (if there is slash) or css class, e.g. fas fa-user.
  • Text
  • Color and Outline - used when a label is displayed as a badge or a button.
  • Id - used by sub-interfaces, e.g. actions.
  • Tooltip
  • Description - more detailed description than a tooltip. It can be displayed in a modal
  • Notification - can be displayed as a badge next the text.

Label is a base interface for Action and a number of other interfaces.


Action is the unit of system/user interaction.

Actions define a vocabulary of human/system interaction. In such a vocabulary actions are “verbs”. E.g. “View transactions” or “Submit payment”. If actions are verbs, then property sources are nouns. They are explained below.

Often a struggle in creating a new application is the fact that the users have a vague idea how it may look like. With application-language metaphor we can say that “if they can articulate it, we can automate it” - take their descriptions and turn verbs into actions and nouns into entities or value objects.

For example: “Jim uploads a feed from mainframe and then Bob validates it for inconsistencies”. From this we may tell that:

  • There is a user/actor/role Jim with “upload mainframe feed” action.
  • There is a user/actor/role Bob with “verify mainframe feed” action.
  • There is a “mainframe feed” entity which gets uploaded and validated.

Thinking in terms of actions allows to stay focused on functionality and not get distracted by lower-level concerns such as button colors, borders, etc. Such concerns are important once the core application functionality is solidified.
One of my friends once told me a long time ago that “it is much easier to make a functional application fast than a fast application functional”. Thinking in actions helps to deliver functionality faster and take care of non-functional requirements later.

While the framework allows to refine appearance of UI elements on a case-by-case basis having a consistent UI increases clarity of human-system interactions.

Where there’s a vocabulary there’s a dictionary. Building an application in terms of actions and property sources allows to create and publish such a user-system dictionary as part of the build process.

In Java terms an action may be thought of as a method in a callback interface (Web UI) passed to a user. The user interacts with the system by “invoking callback methods” - activating actions so they get executed by the system by invoking their generate() method.

Action activator

ActionActivators are used to trigger action execution on the server side. There are three types of action activators:

  • NavigationActionActivator - when user clicks on the action UI element it triggers navigation to the specified URL.
  • ScriptActionActivator - when user clicks on the action UI element it triggers execution of the specified script.
  • BindingActionActivator - the activator is responsible for configure the UI element to activate action execution. For example, such a binder may add KnockoutJS click binding.

In the above text is it assumed that UI elements are activated by a mouse click. However, they may be activated differently, e.g. for a form action activation shall happen on form submit. In this case the navigation url would go to the action attribute of the form and the script code would go to the onSubmit handler.

Contained actions

Actions have getChildren() method returning a collection of contained (sub) actions. There are also several default getXXXChildrens() methods filtering and grouping child actions.

An action may play different roles. Action role defines where it appears in the UI. There are several built-in roles


Navigation actions correspond to contained objects and are typically rendered in the navigation panel. For example a bank customer has/owns accounts. Actions to view such accounts would be displayed in the navigation panel. In entity-relationship terms navigation actions correspond to containment references and in Java terms they correspond to fields. You may also think of them as “view (noun)” actions. E.g. “view account”.


Context actions get their name from the fact that they are displayed as a JsTree context menu items. They are also output as buttons in the content panel. Context actions correspond to methods/operations/verbs. E.g. “open account” context action of a “view customer” action.


Section actions play the same role as navigation actions, but they are displayed in the content panel of the contained action. For example, “view transactions” section action of “view statement” action would display a list of transactions below statement details. Section actions may be executed/generated along with the containing action. In this case they don’t need an activator. Section actions with NavigationActionActivators may be executed by loading section content using AJAX.


PropertySource or PropertyDescriptor actions in this role are displayed in view mode.


PropertySource or PropertyDescriptor actions in this role are displayed in edit mode.

Action categories

Action extends Categorized. It allows to group actions into categories. Anonymous categories have id but no text or icon.

Categories are presented in the UI in following ways:

  • Navbar - uncategorized actions are at the top level, categorized are grouped into dropdowns. Headers and separators are not supported in category drop-downs. Anonymous categories are not supported.
  • Dropdown - headers for named categories and separators for anonymous.
  • Action groups - different action groups for categories. Named categories are represented as action groups in cards with the category icon and text in the header.
  • jsTree
    • Nodes - a node for named categories, anonymous categories are not supported - treated as uncategorized.
    • TODO: Context menu - dividers for anonymous categories, and sub-menus for named categories.
  • Buttons - button groups, all categories are treated as anonymous.
  • TODO: Sections - named categories add an extra level. Anonymous categories are displayed as a horizontal lines (HR) in header sections and as separate action groups, not supported in navs.

View generator

ViewGenerator provides access to lower-level API’s factories and methods to build UI elements from application abstractions such as actions.

View part

ViewPart generates Web UI leveraging ViewGenerator passed to its generate() method.

The library provides several view part implementations used by the action application builder (see below). View parts in the viewparts package may be customized via subclassing.

Application builder

ApplicationBuilder builds an application passed to its build() method.


ViewPartApplicationBuilder is an abstract implementation of ApplicationBuilder. It creates a ViewGenerator, view parts for the header, navigation bar, navigation panel, content panel, and footer, and then delegates application building to the view parts.


AbstractActionApplicationBuilder is a subclass of ViewPartApplicationBuilder which builds application from an action hierarchy. It uses 3 actions to build the application:

  • Active action - action which has been executed and results of its execution are presented to the user in the content panel. This action or its parent in the path are selected in the navigation bar or the navigation panel.
  • Principal action - this action’s link is displayed as the navigation bar brand. Context actions are displayed in the navigation bar, and child actions are displayed in the navigation panel. The action takes its name from the fact that it would typically represent the security principal. The principal action is computed as the second element in the active action path if the path has two or more elements, or as the active action if the path has 1 element. Null otherwise. This behavior may be customize by overriding getPrincipalAction() method.
  • Root action - this action’s link is displayed in the header and its context actions are displayed in the footer. It is computed as the first element in the active action path, or as the active action if the path is empty. This behavior can be customized by overriding getRootAction() method.

AbstractActionApplicationBuilder delegates building to the following view parts:

The header view part is so simple that it is implemented as a lambda.


ActionApplicationBuilder is a concrete subclass of AbstractActionApplicationBuilder which take active, principal, and root actions in constructors.

In the examples below “view account” is an active action, “John Doe” is the principal action and the “Bank of Nasdanika” is the root action.

Action group navigation panel

The code snippet below shows how an application builder is constructed for the default action group navigation panel.

ApplicationBuilder appBuilder = new ActionApplicationBuilder(appAction, principalAction, principalAction.getChildren(), selected, Collections.emptyMap()) {
	protected Object generateHeader(ViewGenerator viewGenerator) {
		return ((Tag) super.generateHeader(viewGenerator)).addClass("text-dark").style().text().decoration().none();

Full code is available in the testActionApplication class.

jsTree navigation panel

ActionApplicationBuilder jsTreeAppBuilder = new ActionApplicationBuilder(appAction, principalAction, principalAction.getChildren(), selected, Collections.emptyMap()) {
	protected Object generateHeader(ViewGenerator viewGenerator) {
		return ((Tag) super.generateHeader(viewGenerator)).addClass("text-dark").style().text().decoration().none();
	protected ViewPart getNavigationPanelViewPart() {
			return new JsTreeNavigationPanelViewPart(navigationPanelActions, activeAction);

Data sources and properties

DataSource is something which can provide access to some data, knows how to retrieve a version/revision of the data object, and also knows how to update that data using a map of property deltas. There are two flavors of DataSource - SingleValueDataSource and MultiValueDataSource.

Property is something which knows how to deal with properties/attributes of objects returned by data sources. E.g. if a data source returns a Person object then FirstName property know how retrieve and set the person’s first name.

Property sources and descriptors

PropertySource extends DataSource, Label, and ActionProvider. I.e. it is a data source which can be displayed in the UI and have associated actions.

As in the case of the DataSource, there are two flavors of PropertySource:

Property source has getPropertyDescriptors() method returning a list of PropertyDescriptors. Property descriptor extends Label, Property, and Categorized.

Wile properties are concerned with value retrieval and update, property descriptors are concerned with displaying and editing property values.

Use in Maven projects

Add repository and dependency as shown below:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="" xmlns:xsi=""