Story of the Unified UI Framework (UUF)
A learner’s guide to the UI framework of the WSO2 IoT Server 3.x
Back in the day at WSO2, I took part in a team to revamp a UI framework called Unified UI Framework (UUF). As the name implies; it is meant to be the governing UI for sharing reusable UI bits and pieces between enterprise apps.

At the time we start working on this we already had a running version of it. However, in the future, we are considering moving into fully client-side web apps with the React framework. Since still we are using UUF Hoped to write down some important stuff as the reference guide for the WSO2 IoT Server 3.x users.
Motivation for the UUF is for the shareable, composable UI units with the back-end logics
Bits from the History
Up until a certain time in history (2012), our platform was a large collation of shareable components(backend and UI). We used OSGi-based backend logic and JSP-based UIs. These UI components were wired into a single web application through a framework called Carbon UI framework. This approach allowed us to share UI logic and Backend logic through feature provisioning across multiple products such as ESB, DSS, AS…etc.
Somewhere around 2012, we started working on a new breed of products like API Manager, App Factory, and EMM. Each of these products ended up writing a single web application calling a bunch of backend APIs. This is how we ended up having web applications like ‘API-Store’, ‘API-Publisher’, and APIs like ‘Store API’ and ‘API Publisher API’. These web applications were done using Jaggery.
So the difference here is a single web application vs a web application composed through components.
While it has its own advantages like faster development time, this approach caused some problems as well.
- Product teams were using their chosen utility (JS) libraries and some even went up to the level of writing their own libraries with weird licenses (for those of you who know the history ;) )
- Each web application had its own structure making ensuring common UX among all WSO2 products an uphill task for the UX team
- Duplicate UI for the same functionality
Problems UUF is trying to solve
- Framework for creating shareable UI units
- Having a Unified Framework that minimizes the learning curve at the Support / Development which Jaggery didn’t solve
- Customization support for customers (without breaking patching)
- Consistent UX throughout all products
- Convention driven webapp development (MVC support)
UUF UI units in action: It’s showtime!
Below depicts how these re-usable UI units are composed to make the device overview page of the virtual fire alarm device in the WSO2 IoT Server.

Building blocks of the UUF
The building blocks or the concepts of the frameworks are as below;
- Pages: A page owns the URL of the unit or the application the page is part of. Each page is associated with a layout that defines the template. The page may also have a controller logic that gets executed prior to the rendering of the page.
- Layouts: A layout is a named template for how the page will look in the browser. Thus, a layout defines the boilerplate of <html>…</html> that we might repeat on each page. A layout will often define the higher levels of zones that are meant to be filled later by pages that use the given layout.
- Zones: A zone is a placeholder that is meant to be filled by pages or pages’ imported units.
- Units: A unit is the smallest piece of reusable UI capability consisting of front end and (possibly) controller logic.

1. Basic Structure of an Application
The UUF framework is written on top of Jaggery(a server-side javascript language). Thus, from the WSO2 Server’s perspective, a UUF application is yet another Jaggery application.
A UUF application will be consisting of an ‘app/’ folder where all the application-developer related files are kept. External folders such as ‘cache/’ and ‘lib/’ are being used by the UUF framework itself (‘api/’ is a special case i.e. jaggery apis).

Inside the ‘app/’ folder;
- the ‘conf/’ folder is being used for holding application configuration files(eg. app-conf.json, config.json).
- The ‘modules/’ is an optional folder where you may keep re-usable controller logics(eg. device.js, user.js).
- All the templates are stored in the ‘layouts/’ folder. Layouts are written as *.hbs (handlebar) files. If you are not familiar with Handlebars; you may think of them as plain HTML files. Whenever you need to access variables you can switch to server-side with mustaches (eg. {{foo}} ).
- The ‘pages/’ and ‘units/’ holds the pages and ui-units that are being discussed in the next section.
2. Basic Structure of a Page
A page have mandatory view(<page-name>.hbs) and a config(<page-name>.json). Optionally, there may be an optional controller(<page-name>.js) that will be executed prior to rendering the page.

2.1 Page View Template — <page-name.hbs>
A sample page view (handlebars) would look like the below;
{{#zone "topCss"}}
{{css "css/styles.css"}}
{{/zone}}{{#zone "content"}}
<div> this is a simple div </div>
<img src="{{@page.publicUri}}/images/sample.png" />
{{/zone}}{{#zone "bottomJs"}}
{{js "js/script.js"}}
<script type="text/javascript">
//your inline script goes here...
</script>
{{/zone}}
Above page view, the handlebar template would support a pre-defined set of UUF helpers and built-in handlebar helpers such as if-else, unless, each…etc. For reference, all UUF helpers being used are listed at the end of this article.
2.2 Page Configuration— <page-name.json>
A sample page configuration would be similar to the one below;
{
"version": "1.0.0",
"uri": "/device/{deviceType}",
"layout": "cdmf.layout.default"
}
Acceptable parameters:
- version: Currently has no effects. May use ‘1.0.0’
- uri: URL pattern for the page. You can have path parameters as well.
- layout: Name of the template. Should be one from the ‘/layouts’ folder.
- disabled(optional): If ‘true’, page will not be available.
- isAnonymous(optional): If ‘true’ page is accessible without login in to the application.
2.3. Page Controller — <page-name.js>
While this is optional for a page unit; the existence of a page controller will require executing onRequest() function before rendering the page view template. This can be considered as a server-side javascript. A sample page configuration would be similar to below;
function onRequest(context){
var log = new Log("page-name.js");
log.info("start of onRequest()...");
var viewModel = {};
viewModel.foo = "bar";
log.info("end of onRequest()...");
return viewModel;
}
Generally speaking, you can write any server-side java script compliance with the Js standard ECMAScript v6. All special UUF attributes available inside the onRequest() function, are listed at the end of this article.
3. Basic Structure of a Unit
A Unit is the smallest unit of reusable UI capability consisting of front end and (possibly) controller logic. A Unit assume a set of zones (defined by a layout) and pushes HTML elements into those zones. A fragment may also define zones that, dependent units can push into by using the name of the zone.
A Unit may also contain CSS, frontend JavaScript and other public web resources (e.g. css, front-end js, images).

- Unit View Template — <unit-name>.hbs: Similar to the page template. Supports pre-defined set of UUF helpers and Hbs helpers (for more details on syntaxes, please refer the UUF syntaxes section at the end of the article).
- Unit Configuration — <unit-name>.json: Similar to the page configuration, same attributes supported except layout and uri attributes.
- Unit Controller — <unit-name>.js: An optional controller is allowed. OnRequest() method will be executed by UUF before rendering the view template(for more details on syntaxes, please refer the UUF syntaxes section at the end of the article).
Render UUF Application
When rendering a UUF application; all the templates are converted into a single HTML string. For instance; there can be a page that includes a few other units as well. In that case, all units will be rendered first and included into the main page.
On existence of the Controller Js; server-side JavaScript code inside the onRequest() function will be compiled prior to the rendering of the view templates. Then the return value(i.e. a map of key-value pairs) of the function will be available in the handlebar context when rendering the view template.

Putting All things together!

Conclusion
We discussed what made us to create UUF and how you can make use of UUF to create webapps consisting of re-usable ui units. Hope you enjoyed the reading!
UUF Syntax Reference
1. View Template Hbs syntaxes
Following handlebar helpers are available for viewing the template of the page or unit.
Basic UUF helpers;
- {{#zone “_name_”}}{{/zone}}: A UUF handlebar block helper, that allows filling pre-defined spaces in the layout.
- {{css “_relative-path-to-css_”}}: A UUF handlebar helper, that allows importing css stylesheets into your page.
- {{js “_relative-path-to-js_”}}: A UUF handlebar helper, that allows importing JavaScripts into your page.
- {{unit “_name_”}}: A UUF handlebar helper, that includes a unit for a page.
Other UUF helpers;
- {{@app.context}}: This helper prints the current application context.
- {{@user}}: User object of the currently logged in user. You may access @user.username or @user.domain.
- {{@uriParams}}: A map of path parameters parsed. For instance; if your url pattern of the page is “/device/{deviceType}”; then the value being passed to deviceType will be accessible via @uriParams.deviceType.
Helpers only available in Pages:
- {{@page.publicUri}}: All the static resources inside the public folder will be available through this URI.
Helpers only available in Units:
- {{@unit.publicUri}}: All the static resources inside the public folder will be available through this URI.
- {{@unit.params}}: A map of all parameters passed through the unit include will be available. For instance; {{unit “cdmf.ui.overview” foo=“bar”}}. You can access the parameter ‘foo’ inside your overview.hbs as {{unit.params.foo}}.
2. Controller Js (server-side java script) syntaxes
Following attributes are available inside the onRequest(context) function.
Main attributes;
- {{context.app.context}}: This helper prints the current application context.
- {{context.user}}: User object of the currently logged in user. You may access context.user.username or context.user.domain.
- {{context.uriParams}}: A map of path parameters parsed. For instance; if your url pattern of the page is “/device/{deviceType}”; then the value being passed to deviceType will be accessible via context.uriParams.deviceType.
Attributes only available in Pages:
- {{context.page.publicUri}}: All the static resources inside the public folder will be available through this URI.
Attributes only available in Units:
- {{context.unit.publicUri}}: All the static resources inside the public folder will be available through this URI.
- {{context.unit.params}}: A map of all parameters passed through the unit include will be available. For instance; {{unit “cdmf.ui.overview” foo=“bar”}}. You can access the parameter ‘foo’ inside your overview.hbs as {{@unit.params.foo}}.