tag:blogger.com,1999:blog-43585942586567264382024-03-19T08:27:28.593+01:00The Dashbuilder ProjectTurn your data into interactive dashboards!
Unknownnoreply@blogger.comBlogger25125tag:blogger.com,1999:blog-4358594258656726438.post-69574040564361549172021-05-26T15:51:00.004+02:002021-05-26T16:05:32.824+02:00DashBuilder project is active and innovating at a fast pace!<p><span style="font-family: Arial; font-size: 11pt; white-space: pre-wrap;">Hi everyone! </span></p><span id="docs-internal-guid-8c058a9b-7fff-df6e-f614-39e17fac654b"><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="font-family: Arial; font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">First of all, sorry for the lack of news on this blog. But I come here to bring you some exciting news!</span></p><br /><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="font-family: Arial; font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">DashBuilder project is active and innovating at a fast pace! But how can I keep you with the new features?</span></p><br /><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="font-family: Arial; font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">First, we have a new blog home </span><a href="https://blog.kie.org/" style="text-decoration-line: none;"><span style="color: #1155cc; font-family: Arial; font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; text-decoration-line: underline; text-decoration-skip-ink: none; vertical-align: baseline; white-space: pre-wrap;">blog.kie.org</span></a><span style="font-family: Arial; font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">. From now on, this blog is decommissioned, and we will publish all the DashBuilder news and blog posts on the KIE blog.</span></p><br /><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span id="docs-internal-guid-64bac55a-7fff-680f-69c8-031d72188583"></span></p><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;">You can also check out this</span><a href="https://blog.kie.org/2021/04/dashbuilder-an-apache-licensed-business-reporting-and-monitoring-tool.html" style="text-decoration: none;"><span style="-webkit-text-decoration-skip: none; background-color: transparent; color: #1155cc; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration-skip-ink: none; text-decoration: underline; vertical-align: baseline; white-space: pre;"> blog post</span></a><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> to see a summary of the most exciting DashBuilder new features; follow the </span><a href="https://blog.kie.org/2021/05/dashbuilder-getting-started-guide.html" style="text-decoration: none;"><span style="-webkit-text-decoration-skip: none; background-color: transparent; color: #1155cc; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration-skip-ink: none; text-decoration: underline; vertical-align: baseline; white-space: pre;">Getting Started Guide</span></a><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> or check our </span><a href="https://github.com/kiegroup/appformer/tree/master/dashbuilder" style="text-decoration: none;"><span style="-webkit-text-decoration-skip: none; background-color: transparent; color: #1155cc; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration-skip-ink: none; text-decoration: underline; vertical-align: baseline; white-space: pre;">codebase</span></a><span style="background-color: transparent; color: black; font-family: Arial; font-size: 11pt; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre;"> directly.</span></p><br /><p dir="ltr" style="line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;"><span style="font-family: Arial; font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;">See you there</span></p><div><span style="font-family: Arial; font-size: 11pt; font-variant-east-asian: normal; font-variant-numeric: normal; vertical-align: baseline; white-space: pre-wrap;"><br /></span></div></span>Eder Ignatowiczhttp://www.blogger.com/profile/04762106931598040277noreply@blogger.com0tag:blogger.com,1999:blog-4358594258656726438.post-65892670924670856762016-10-19T10:09:00.002+02:002016-10-19T10:09:37.707+02:00UF Dashbuilder - Custom metric displayersA common feature users usually ask for is the ability to customize the look&feel of their metric displayers. In order to cope with those kind of scenarios, UF Dashbuilder provides an editor which allows for the edition and customization of the metric HTML code. The perspective editor's <i>Displayer Component</i> is in charge of providing such functionality. In order to start the edition process just drag & drop a <i>Displayer Component</i> from the component sidebar on the right:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEif1F4Y6zsK-zYIN6kKIdcYUWEuka7TqaSDYMNvEE9yqF5cfKA4nCBAQgL2Uf5UlUSfM7SnWqoelI5E9EdQjxJVWMT-DDC3U87xz69r1_dOonCm1uFgPfe5wQIX-vvaCWeI0RqXJnrve_A/s1600/metric4.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEif1F4Y6zsK-zYIN6kKIdcYUWEuka7TqaSDYMNvEE9yqF5cfKA4nCBAQgL2Uf5UlUSfM7SnWqoelI5E9EdQjxJVWMT-DDC3U87xz69r1_dOonCm1uFgPfe5wQIX-vvaCWeI0RqXJnrve_A/s1600/metric4.png" /></a></div>
<br />
<br />
<br />
Once opened, select the <i>Metric</i> type from the types on the left. The system provides four predefined templates. On the center of the screen, a preview of the metric is shown along with the <i>HTML</i> and <i>Javascript</i> options, both give access to the metric's source code.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhK1-sNiEztJFhAcEoUphQ8Z4qqSKiwRzw9wO80K5QqaK7GwXRfaZjhP4_4QP97QrElxAinpPYn9UT_kSpjYy-GKBqZLVv-XrXag9P7ecFE2MMKPBmbMtUuI1j3ivzxvGL9NxfTBrjEOw8/s1600/metric1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhK1-sNiEztJFhAcEoUphQ8Z4qqSKiwRzw9wO80K5QqaK7GwXRfaZjhP4_4QP97QrElxAinpPYn9UT_kSpjYy-GKBqZLVv-XrXag9P7ecFE2MMKPBmbMtUuI1j3ivzxvGL9NxfTBrjEOw8/s1600/metric1.png" /></a></div>
<br />
<br />
<br />
From the HTML tab, it is possible to provide a custom template using the HTML language. Some metric related variables can be injected in the template as well just by clicking on the upper right icon and selecting from the list of available variables. Also both <a href="http://getbootstrap.com/" target="_blank"><i>Bootstrap 3</i> </a>and <a href="https://www.patternfly.org/" target="_blank">PatternFly</a> are supported for CSS styling.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgPgrcdZ_r9HCy0lTeORiUeAHu3sMXAH-a33H5hiZRM9tb0BJXCC2wot5N7_4LhjBEmsqHg-BjdknTOnzxq4e7t0YDdyAJXRT5p6yZ7bCAwe7SMMGplgHh9URaBL7rUjmWUoqEu-aJuaag/s1600/metric2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgPgrcdZ_r9HCy0lTeORiUeAHu3sMXAH-a33H5hiZRM9tb0BJXCC2wot5N7_4LhjBEmsqHg-BjdknTOnzxq4e7t0YDdyAJXRT5p6yZ7bCAwe7SMMGplgHh9URaBL7rUjmWUoqEu-aJuaag/s1600/metric2.png" /></a></div>
<br />
<br />
<br />
From the <i>Javascript</i> tab users can provide a JS snippet which is executed every time the metric is displayed. Likewise the HTML tab, it is possible to reference some context variables as well as DOM elements from the HTML template. Altogether it allows for the implementation of nice features like for example: changing the color of the metric if its value exceeds a given threshold, apply a custom format to the value, etc.<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhIO1oTO5c8J1TLRT6dOhRxd_cGswugrCIfoBXMKvaoEsL_oubjXZl1ocYGmGf5FA_jS_6aX2VhnBRbGAExsh5_0hzOgWPt7B77FrUjKWNR1T2QECWBQQn3Swmy-6HuxQznDaU_cw7U5us/s1600/metric3.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhIO1oTO5c8J1TLRT6dOhRxd_cGswugrCIfoBXMKvaoEsL_oubjXZl1ocYGmGf5FA_jS_6aX2VhnBRbGAExsh5_0hzOgWPt7B77FrUjKWNR1T2QECWBQQn3Swmy-6HuxQznDaU_cw7U5us/s1600/metric3.png" /></a></div>
<br />
<br />
The next <a href="https://youtu.be/Mto0qvjkNoI" target="_blank">video</a> (do not forget to select HD) shows how to create and customize a new metric using the features described above. Enjoy!<br />
<br />
<br />Unknownnoreply@blogger.com7tag:blogger.com,1999:blog-4358594258656726438.post-53369292046954166902016-08-24T13:35:00.008+02:002016-08-24T13:44:18.257+02:00UF Dashbuilder - Security Management The implementation of the security management features in UF Dashbuilder is done (see the related <a href="https://issues.jboss.org/projects/DASHBUILDE/issues/DASHBUILDE-100" target="_blank">ticket</a> in JIRA). This is a major step towards the full migration of the old Dashbuilder tooling to GWT/Uberfire. The <a href="https://youtu.be/S4HCTuAmqGA" target="_blank">following video</a> is a preview of the new security management screen in the UF Dashbuilder webapp (don't forget to select full HD for a better display).<br />
<br />
<br />
This article describes how administrator users can manage the application's users, groups and permissions using an intuitive and friendly user interface in order to configure who can access the different resources and features available. The security management capabilities presented exceed by far the ones provided by the old Dashbuilder.<br />
<div>
<br /></div>
<h2>
Basic concepts</h2>
In order to understand the new security management module, a few core concepts need to be introduced first.<br />
<br />
<h4>
Roles vs Groups</h4>
<div>
<br /></div>
Users can be assigned with more than one role and/or group. It is always mandatory to assign at least one role to the user, otherwise he/she won’t be able to login. Roles are defined at application server level and they are part of the webapp’s web.xml descriptor. On the other hand, groups are a more flexible concept, since they can be defined at runtime.<br />
<br />
<h4>
Permissions</h4>
<div>
<br /></div>
A permission is basically something the user can do within the application. Usually, an action related to a specific resource. For instance:<br />
<br />
<ul>
<li>View a perspective</li>
<li>Save a project</li>
<li>View a repository</li>
<li>Delete a dashboard</li>
</ul>
<br />
A permission can be granted or denied and it can be global or resource specific. For instance:<br />
<br />
<ul>
<li>Global: “Create new perspectives”</li>
<li>Specific: “View the home perspective”</li>
</ul>
<br />
As you can see, a permission is a "resource + action" pair. In the concrete case of a perspective we have: <i>read, update, delete and create</i> as the available actions. That means that there are four possible permissions that could be granted for perspectives.<br />
<br />
Permissions do not necessarily need to be tied to a resource. Sometimes it is also necessary to protect access to specific features, like for instance "<i>generate a sales report</i>". That means, permissions can be used not only to protect access to resources but also to custom features within the application.<br />
<br />
<h4>
Authorization policy</h4>
<br />
The set of permissions assigned to every role and/or group is called the authorization (or security) policy. Every application contains a single security policy which is used every time the system checks a permission.<br />
<br />
The authorization policy file is stored in a file called <i>WEB-INF/classes/security-policy.properties</i> under the application's WAR structure.<br />
<br />
<br />
NOTE: If no policy is defined then the authorization management features are disabled and the application behaves as if all the resources & features were granted by default.<br />
<br />
Here is an example of a security policy file:<br />
<br />
<i># Role "admin"<br />role.admin.permission.perspective.read=true<br />role.admin.permission.perspective.read.Dashboard=false<br /><br /># Role "user"<br />role.user.permission.perspective.read=false<br />role.user.permission.perspective.read.Home=true<br />role.user.permission.perspective.read.Dashboard=true</i><br />
Every entry defines a single permission which is assigned to a role/group. On application start up, the policy file is loaded and stored into memory.<br />
<br />
<h4>
Security provider</h4>
<div>
<br /></div>
A security environment is usually provided by the use of a <i>realm</i>. Realms are used to restrict access to the different application's resources. So realms contains the information about the users, groups, roles, permissions and any other related information.<br />
<br />
In most typical scenarios the application's security is delegated to the container's security mechanism, which consumes a given realm at same time. It's important to consider that there exist several realm implementations, for example Wildfly provides a realm based on the <i>application-users.properties/application-roles.properties</i> files, Tomcat provides a realm based on the <i>tomcat-users.xml</i> file, etc.<br />
<div>
<br />
So there is no single security realm to rely on, it can be different in each installation.<br />
<br />
Due to the potential different security environments that have to be supported, the security module provides a well defined API with some default built-in security providers.</div>
<div>
<br />
A <b>security provider</b> is the formal name given to a concrete user and group management service implementation for a given realm.<br />
<br />
The user & group management features available will depend on the security provider configured.<br />
If the built-in providers do not fit with the application's security realm, it is easy to build and register your own provider.<br />
<br />
<br />
<h2>
Installation and setup</h2>
<br />
At the time of this writing, the application provides two pre-installed security providers:<br />
<br />
<ul>
<li><b>Wildfly 10 / EAP 7 </b>- Both distributions use the <a href="https://github.com/uberfire/uberfire/tree/master/uberfire-extensions/uberfire-security/uberfire-security-management/uberfire-security-management-wildfly" target="_blank">Wildfly security provider</a> configured for the use of the default realm files <i>application-users.properties</i> and <i>application-roles.properties</i></li>
</ul>
<ul>
<li><b>Tomcat</b> - It uses the <a href="https://github.com/uberfire/uberfire/tree/master/uberfire-extensions/uberfire-security/uberfire-security-management/uberfire-security-management-tomcat" target="_blank">Tomcat security provider</a> configured for the use of the default realm file <i>tomcat-users.xml</i></li>
</ul>
<br />
Please, read each <a href="https://github.com/uberfire/uberfire/tree/master/uberfire-extensions/uberfire-security/uberfire-security-management" target="_blank">provider's documentation</a> in order to apply the concrete settings for the target deployment environment.<br />
<br />
On the other hand, when either using a custom security provider or using one of the availables, consider the following installation options:<br />
<br />
<ul>
<li>Enable the security management feature on an existing WAR distribution</li>
<li>Setup and installation in an existing or new project</li>
</ul>
<br />
NOTE: If no security provider is installed, there will be no available user interface for managing the security realm.</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div>
<br />
Once a security provider is installed and setup, the user and group management features are automatically enabled in the security management UI (see the "Usage" section below).<br />
<br />
<h4>
Enabling user & group management</h4>
<br />
Given an existing WAR distribution, follow these steps in order to install and enable the user & group management features:<br />
<br />
<ul>
<li>Ensure the following libraries are present on <i>WEB-INF/lib</i>:</li>
<ul>
<li><i>WEB-INF/lib/uberfire-security-management-api-?.jar</i></li>
<li><i>WEB-INF/lib/uberfire-security-management-backend-?.jar</i></li>
</ul>
</ul>
<ul>
<li>Copy the the security provider library to <i>WEB-INF/lib</i>:</li>
<ul>
<li>e.g: <i>WEB-INF/lib/uberfire-security-management-wildfly-?.jar</i></li>
<li>If the provider requires additional libraries, copy them as well </li>
</ul>
</ul>
<ul>
<li>Replace the whole content of the <i>WEB-INF/classes/security-management.properties</i> file, or if not present, create it. The settings present on this file depend on the concrete implementation used. </li>
</ul>
<ul>
<li>If deploying on Wildfly or EAP, check if the <i>WEB-INF/jboss-deployment-structure.xml</i> requires any update.</li>
</ul>
<div>
Please, read each <a href="https://github.com/uberfire/uberfire/tree/master/uberfire-extensions/uberfire-security/uberfire-security-management" target="_blank">provider's documentation</a> for more information.</div>
<h4>
</h4>
<h4>
Disabling user & group management</h4>
<br />
The user & groups management features can be disabled, and thus no services or user interface will be available, by means of either:<br />
<br />
<ul>
<li>Uninstalling the security provider from the application. When no concrete security provider is installed, the user and group management features will be disabled and no services or user interface will be displayed to the user. </li>
</ul>
<ul>
<li>Removing or commenting the security management configuration file. Removing or commenting all the lines in the configuration file located at <i>WEB-INF/classes/security-management.properties</i> is another way to disable the user and group management features.</li>
</ul>
<h2>
Usage</h2>
<br />
The Security Management perspective is available under the <i>Administration</i> section in the top menu bar.</div>
<div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg3GQrZwGWFAXF368hieNEHRp1llFH_lK0pGcY6Lvq2Wexjj8ZmifG9y3Piuccn2SsN9MHzXUhgrKy9sFty4VTnVEREERxmXNrr2JoANhCM4WW0D2O9j_ye8oJSFoQsPm6Cz6lihCStNGQ/s1600/1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg3GQrZwGWFAXF368hieNEHRp1llFH_lK0pGcY6Lvq2Wexjj8ZmifG9y3Piuccn2SsN9MHzXUhgrKy9sFty4VTnVEREERxmXNrr2JoANhCM4WW0D2O9j_ye8oJSFoQsPm6Cz6lihCStNGQ/s1600/1.png" /></a></div>
<h2>
</h2>
<br />
The next screenshot shows how this new perspective looks:<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjB_RwBxHNVNY1n9XCVMfAP1o7E66TLNqcLW9dfrOcqxF2b7oCBD_xnwjEj-SQJpmecQLd31s0Y-AR18MGHdGpR7wHUKHjdMYrZQGXO8j2syu0Wospz3afdEGqPeYiQxDxjzHO2GU6m594/s1600/2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjB_RwBxHNVNY1n9XCVMfAP1o7E66TLNqcLW9dfrOcqxF2b7oCBD_xnwjEj-SQJpmecQLd31s0Y-AR18MGHdGpR7wHUKHjdMYrZQGXO8j2syu0Wospz3afdEGqPeYiQxDxjzHO2GU6m594/s1600/2.png" /></a></div>
<div>
<br /></div>
<div>
This perspective supports:</div>
<ul>
<li>List all the roles, groups and users available</li>
<li>Create & delete users and groups</li>
<li>Edit users, assign roles or groups, and change user properties</li>
<li>Edit both roles & groups security settings, which include:</li>
<ul>
<li>The home perspective a user will be directed to after login</li>
<li>The permissions granted or denied to the different workbench resources and features available</li>
</ul>
</ul>
<br />
All of the above together provides a complete users and groups management subsystem as well as a permission configuration UI for protecting access to specific resources or features.<br />
<br />
The next sections provide a deep insight into all these features.<br />
<br />
NOTE: The user and group management related features can be entirely disabled. See the previous section<br />
"<i>Disabling user & group management</i>". If that's the case then both the <i>Groups</i> and <i>Users</i> tabs will remain hidden from the user.</div>
<div>
<br /></div>
<div>
<h3>
User management</h3>
<br />
By selecting the <i>Users</i> tab in the left sidebar, the application shows all the users present by default on the application's security realm:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhyEmzdXIrqJ1Wt_e-Ivvx-0YgqyqWp4q_62uJ4B32okz3z6ymrnRNWaBGmDoAQu_E61XOFw7vSEmg9rnJoMpn6TWwSB4BL9DrmZY9L0wrXL9UMzeVWv4pKqrMmO6NLZ4QHMQHa2qF41Ms/s1600/3.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhyEmzdXIrqJ1Wt_e-Ivvx-0YgqyqWp4q_62uJ4B32okz3z6ymrnRNWaBGmDoAQu_E61XOFw7vSEmg9rnJoMpn6TWwSB4BL9DrmZY9L0wrXL9UMzeVWv4pKqrMmO6NLZ4QHMQHa2qF41Ms/s1600/3.png" /></a></div>
<h3>
</h3>
<ul>
<li><b>Searching for users</b></li>
</ul>
<br />
In addition to listing all the users, search is also allowed. When specifying the search pattern in the search box the users listed will be reduced to only those that matches the search pattern.<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjCTBTzUPrcwfaNAijEshj-5kJKIvGnMpJuLIcENYmyOo-0ssG1DNOzUdpBdc_hErbmhlyaT8LLT7oJpBp4A9sTGbLJBZ-s-Fr2M18ZHS8szA_geRjuZhZh6u1GUuCfDIWNd0-Z_nI9CWQ/s1600/SecurityManagementUsersSearch.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjCTBTzUPrcwfaNAijEshj-5kJKIvGnMpJuLIcENYmyOo-0ssG1DNOzUdpBdc_hErbmhlyaT8LLT7oJpBp4A9sTGbLJBZ-s-Fr2M18ZHS8szA_geRjuZhZh6u1GUuCfDIWNd0-Z_nI9CWQ/s1600/SecurityManagementUsersSearch.png" /></a></div>
<div class="" style="clear: both; text-align: left;">
Search patterns depend on the concrete security provider being used by the application.</div>
<div class="" style="clear: both; text-align: left;">
Please, read each <a href="https://github.com/uberfire/uberfire/tree/master/uberfire-extensions/uberfire-security/uberfire-security-management" target="_blank">provider's documentation</a> for more information.</div>
<div class="" style="clear: both; text-align: left;">
<br /></div>
<ul>
<li><b>Creating new users</b></li>
</ul>
<br />
By clicking on the "<i>New user +</i>" anchor, a form is displayed on the right.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgpX4X-3zeoaRxfuJpw7-K8Rfa8uG4O1IpGdn1ZZYYpFZwIj1N31XAvSmKlpGhokAPJ9GOtx6SIa5AYoGIfSvxnKvDUm_hiIcbzMi0i77efn87Y94OsHTvPz8S1Q0f95xVRRinqx23yzgk/s1600/SecurityManagementNewUserForm.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgpX4X-3zeoaRxfuJpw7-K8Rfa8uG4O1IpGdn1ZZYYpFZwIj1N31XAvSmKlpGhokAPJ9GOtx6SIa5AYoGIfSvxnKvDUm_hiIcbzMi0i77efn87Y94OsHTvPz8S1Q0f95xVRRinqx23yzgk/s1600/SecurityManagementNewUserForm.png" /></a></div>
<div class="" style="clear: both; text-align: left;">
This is a wizard like interface where the application asks for the new user name, a password as well as what roles/groups to assign.</div>
<div class="" style="clear: both; text-align: left;">
<br /></div>
<ul>
<li><b>Editing a user</b></li>
</ul>
<div class="" style="clear: both;">
<br />
After clicking on a user in the left sidebar, the user editor is opened on the screen's right.<br />
<br />
For instance, the details screen for the <i>admin</i> user when using the Wildfly security provider looks like the following screenshot:</div>
<div class="separator" style="clear: both;">
<br /></div>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhiHgJSoACkK0xpcG2pMA3hkRwPzehRxBZaguypjFQf4IVzoxRWCnbNuWXnDOlJcnTqNTwSSFjSWlGgx6hwor4_WSXcI204RU6WNGhtws-vABJcnVrroliA3Iuwy1Lh6S5rsv_KbEOvj2g/s1600/SecurityManagementViewUser.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhiHgJSoACkK0xpcG2pMA3hkRwPzehRxBZaguypjFQf4IVzoxRWCnbNuWXnDOlJcnTqNTwSSFjSWlGgx6hwor4_WSXcI204RU6WNGhtws-vABJcnVrroliA3Iuwy1Lh6S5rsv_KbEOvj2g/s1600/SecurityManagementViewUser.png" /></a><br />
<br />
Same screen but when using the Keycloak security provider looks as:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh5fYxOFeEg8DXkvcB-6fYblYHN6cU22JsyWYIqHlzfFuHK4hrzzu-AsX7LL99cUplqcoeFbJvrLqheg3L8ScJLPam5ZqvZYpv7ytiUxrQIRvRORp4vg8q1o_fYFSdVeX9z3Y0cLD8_5PE/s1600/SecurityManagementViewUserKC.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh5fYxOFeEg8DXkvcB-6fYblYHN6cU22JsyWYIqHlzfFuHK4hrzzu-AsX7LL99cUplqcoeFbJvrLqheg3L8ScJLPam5ZqvZYpv7ytiUxrQIRvRORp4vg8q1o_fYFSdVeX9z3Y0cLD8_5PE/s1600/SecurityManagementViewUserKC.png" /></a></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
Note that when using the Keycloak provider, a new user attributes section is displayed, but it's not present when using the Wildfly provider. This is due to the fact that the information and actions available always depend on each provider's capabilities as explained in the "<i>Security provider capabilities"</i> section below.<br />
<br />
Next is the type of information handled in the user's details screen:</div>
<div>
<ul>
<li>The user name</li>
<li>The user's attributes</li>
<li>The assigned groups</li>
<li>The assigned roles</li>
<li>The permissions granted or denied</li>
</ul>
<br />
In order to <b>update or delete an existing user</b>, click on the <i>Edit</i> button present near to the username in the user editor screen:</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEguhERR9Gu78c8tcV5jqptdeA47cfSlraCS7ZTt1VleZ3UJYzzcE1E48OprB0PGTJdDP7w7xiVqS16FZcQboJQDCpvvCOH08qTEMuPvgGpfq1-1r7nxEw-9bRXy1jbjguEWN1ylVcJRrX8/s1600/SecurityManagementEditUser.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEguhERR9Gu78c8tcV5jqptdeA47cfSlraCS7ZTt1VleZ3UJYzzcE1E48OprB0PGTJdDP7w7xiVqS16FZcQboJQDCpvvCOH08qTEMuPvgGpfq1-1r7nxEw-9bRXy1jbjguEWN1ylVcJRrX8/s1600/SecurityManagementEditUser.png" /></a></div>
<div>
<br /></div>
Once the editor is in edit mode, different operations can be done (provided the security provider supports </div>
<div>
them):<br />
<br />
For instance, to modify the set of roles and groups assigned to the user or to change the user's password as well.<br />
<br />
<ul>
<li><b>Permissions summary</b></li>
</ul>
<br />
The <i>Permissions</i> tab shows a summary of all the permissions assigned to this particular user. This is a very helpful view as it allows administrator users to verify if a target user has the right permission levels according to the security settings of its roles and groups.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjKVh0SnlszAPdp9cqFfz3edOi-C6mBHQ5Tp5Rkn1T-Rv7PDTs2S7RG-ensJWri_8zZxzLUSEDXbR1XkVq_lLJoDpv8NwM88X-T9FKalT4cTLl5atJvytjUIdVuLjGFZkViTgodXD6hOQU/s1600/SecurityManagementUserPermissions.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjKVh0SnlszAPdp9cqFfz3edOi-C6mBHQ5Tp5Rkn1T-Rv7PDTs2S7RG-ensJWri_8zZxzLUSEDXbR1XkVq_lLJoDpv8NwM88X-T9FKalT4cTLl5atJvytjUIdVuLjGFZkViTgodXD6hOQU/s1600/SecurityManagementUserPermissions.png" /></a></div>
<div>
Further details about how to assign permissions to roles and groups are in the "<i>Security Settings Editor"</i> section below.</div>
<div>
<br /></div>
<ul>
<li><b>Updating the user's attributes</b></li>
</ul>
<br />
User attributes can added or deleted using the actions available in the attributes table:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZQoJ2L_07N0kE55HJE0b1yMFCaJGGCHlC5NHfD-KZrOl6oaQ2a9GJQXXz_623CetrYENeSWE17QlV9M8QbMGbRKEoZyL0z0xCBZB13E_ese9mkFjwRxwGfNNUx4QVwtMC1B5-73BM8oQ/s1600/SecurityManagementUserAttributes.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZQoJ2L_07N0kE55HJE0b1yMFCaJGGCHlC5NHfD-KZrOl6oaQ2a9GJQXXz_623CetrYENeSWE17QlV9M8QbMGbRKEoZyL0z0xCBZB13E_ese9mkFjwRxwGfNNUx4QVwtMC1B5-73BM8oQ/s1600/SecurityManagementUserAttributes.png" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<ul>
<li><b>Updating assigned groups</b></li>
</ul>
<br />
From the <i>Groups</i> tab, a group selection popup is presented when clicking on the "<i>Add to groups"</i> button:<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiArWDxuN7aezAF1fIUH0IQNPS2_PEEunbxisJMGMfZe5TbaSYD7YH9mwc5K73opiicd1174d4atc1HVWGWd0hiTF76A-4FwiVheb0WgCykBtz9y5vF8h5HsXUumZDY3-dJofoAE-TzLlI/s1600/SecurityManagementGroupsSelection.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiArWDxuN7aezAF1fIUH0IQNPS2_PEEunbxisJMGMfZe5TbaSYD7YH9mwc5K73opiicd1174d4atc1HVWGWd0hiTF76A-4FwiVheb0WgCykBtz9y5vF8h5HsXUumZDY3-dJofoAE-TzLlI/s1600/SecurityManagementGroupsSelection.png" /></a></div>
<div>
<b><br /></b></div>
<div>
<b><br /></b></div>
<div>
This popup screen allows the user to search and select or deselect the groups assigned to the user.</div>
<div>
<br /></div>
<ul>
<li><b>Updating assigned roles</b></li>
</ul>
<br />
From the <i>Roles</i> tab, a role selection popup is presented when clicking on "<i>Add to roles</i>" button:<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhG4ZKhovZ1_0rVw52ZCWr1WifftpO2XpEtr57tnPu2jjEZju_q9WDH_Cc-rt4jFULOWs3joLTV_8ow0ZrJN2NBnnzja-qdV4a2HUFCb42zP9BtNfx8yo7xMu9M5hlUKhdkfMgmXdcRSdI/s1600/SecurityManagementRolesSelection.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhG4ZKhovZ1_0rVw52ZCWr1WifftpO2XpEtr57tnPu2jjEZju_q9WDH_Cc-rt4jFULOWs3joLTV_8ow0ZrJN2NBnnzja-qdV4a2HUFCb42zP9BtNfx8yo7xMu9M5hlUKhdkfMgmXdcRSdI/s1600/SecurityManagementRolesSelection.png" /></a></div>
<div>
<b><br /></b></div>
<div>
This popup screen allows the user to search and select or deselect the roles assigned to the user.</div>
<div>
<br /></div>
<ul>
<li><b>Changing the user's password</b></li>
</ul>
<br />
A change password popup screen is presented when clicking on the "<i>Change password"</i> button:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg_ZzMIwW_JSyLBdy16gRL5h3Om0-i-5Q7C4ComDnzkZl4tN11uxCUGYAYEsg6WntZXq4hTXO9XOaLjtifU30qMEr-VVuPQOiX5SEou1U_48F-p97eVgWrqN4RJZ7tAdY4XKiI2CDwl_ig/s1600/SecurityManagementChangePassword.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg_ZzMIwW_JSyLBdy16gRL5h3Om0-i-5Q7C4ComDnzkZl4tN11uxCUGYAYEsg6WntZXq4hTXO9XOaLjtifU30qMEr-VVuPQOiX5SEou1U_48F-p97eVgWrqN4RJZ7tAdY4XKiI2CDwl_ig/s1600/SecurityManagementChangePassword.png" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<ul>
<li><b>Deleting users</b></li>
</ul>
<br />
The user currently being edited can be deleted from the realm by clicking on the "<i>Delete</i>" button.<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg6Vz7PZOikmumFlQOLJfHLkDl1JUwk_FK72LQL-Atd61_q-jmES6jnMYXANY9z56ja8wRTWc_Cykan0RwQfkkYtZSUgrwewhGU_ca-Hr8E5tKjcWFTKrCNftNztJXdwjYNPy6lBjyBuCw/s1600/SecurityManagementDeleteUser.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg6Vz7PZOikmumFlQOLJfHLkDl1JUwk_FK72LQL-Atd61_q-jmES6jnMYXANY9z56ja8wRTWc_Cykan0RwQfkkYtZSUgrwewhGU_ca-Hr8E5tKjcWFTKrCNftNztJXdwjYNPy6lBjyBuCw/s1600/SecurityManagementDeleteUser.png" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<h4>
Security provider capabilities</h4>
<br />
Each security realm can provide support for different operations. For example, consider the use of a Wildfly's realm based on properties files. The contents for the <i>applications-users.properties</i> is like:<br />
<br />
<i>admin=207b6e0cc556d7084b5e2db7d822555c<br />katy=fd37b5d0b82ce027bfad677a54fbccee<br />john=afda4373c6021f3f5841cd6c0a027244<br />guest=b5d048a237bfd2874b6928e1f37ee15e</i><br />
<br />
Notice that it's based on key-value pairs where the key is the user name, and the value is the hashed value for the user's password. So a user is just represented by a key and its user name, it does not have a name nor an address or any other meta information.<br />
<br />
On the other hand, consider the use of a realm provided by a Keycloak server. The user information is composed by more meta-data, such as the surname, address, etc, as in the following image:</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEimyNjENcy7P0JDqdYYkI0WQu9NDj72Pi13wGDEMtUg7YYiBBqkdMPZp-UnFhp5YyBoMKa6ejWmF7k2el2DutgAANsVaBnBS3jIyZzRk8FDiF6ma-hnPQ1Ug5FPMHjlr9z-dk8qS27XfD0/s1600/SecurityManagementViewUserKC.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEimyNjENcy7P0JDqdYYkI0WQu9NDj72Pi13wGDEMtUg7YYiBBqkdMPZp-UnFhp5YyBoMKa6ejWmF7k2el2DutgAANsVaBnBS3jIyZzRk8FDiF6ma-hnPQ1Ug5FPMHjlr9z-dk8qS27XfD0/s1600/SecurityManagementViewUserKC.png" /></a></div>
<div>
<br /></div>
<div>
So the different services and client side components from the User and Group Management API are based on <b>capabilities </b>which are used to expose or restrict the available functionality provided by the different services and client side components. Examples of capabilities are:<br />
<br />
<ul>
<li>Create a user</li>
<li>Update a user</li>
<li>Delete a user</li>
<li>Update user's attributes</li>
<li>Create a group</li>
<li>Update a group</li>
<li>Assign groups to a user</li>
<li>Assign roles to a user</li>
</ul>
<br />
Each security provider must specify a set of capabilities supported. From the previous examples, it is noted that the Wildfly security provider does not support the attributes management capability - the user is only composed by the user name. On the other hand the Keycloak provider does support this capability.<br />
<br />
The different views and user interface components rely on the capabilities supported by each provider, so if a capability is not supported by the provider in use, the UI does not provide the views for the management of that capability. As an example, consider that a concrete provider does not support deleting users - the delete user button on the user interface will be not available.<br />
<br />
Please take a look at the concrete service provider documentation to check all the supported capabilities for each one, the default ones can be found <a href="https://github.com/uberfire/uberfire/tree/master/uberfire-extensions/uberfire-security/uberfire-security-management" target="_blank">here</a>.<br />
<br />
<h2>
Group management</h2>
<br />
By selecting the <i>Groups</i> tab in the left sidebar, the application shows all the groups present by default on the application's security realm:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjpHsiOL0jHArxdYwKTcmP6tOzGoMBDTu4N2O8zZVWVu67_ajRytjnL8T6MR56YA3E9yNARstFKqj-XMU_KIfhwX5g4m5p8g8d4EOj1u67eoEXYW795uF-2pyyt7WPM1MeCjxzd0FWQn4Y/s1600/SecurityManagementGroupsExplorer.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjpHsiOL0jHArxdYwKTcmP6tOzGoMBDTu4N2O8zZVWVu67_ajRytjnL8T6MR56YA3E9yNARstFKqj-XMU_KIfhwX5g4m5p8g8d4EOj1u67eoEXYW795uF-2pyyt7WPM1MeCjxzd0FWQn4Y/s1600/SecurityManagementGroupsExplorer.png" /></a></div>
<ul>
<li><b>Searching for groups</b></li>
</ul>
<br />
In addition to listing all the groups, search is also allowed. When specifying the search pattern in the search box the groups listed will be reduced to only those that matches the search pattern.</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiircgkWj0k6JYHFfMunAFmwBo-eBZbI6RMmAb5K1vNHlKmouXUtCJk878kEaZTmYu3LAwlxSFxINJbl2ZslR8yEbUE7ht2UXEcZqRPEsmFyIwXQhUH0HProjo7CAH52k2ujT6iX6a-Msg/s1600/SecurityManagementGroupsSearch.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiircgkWj0k6JYHFfMunAFmwBo-eBZbI6RMmAb5K1vNHlKmouXUtCJk878kEaZTmYu3LAwlxSFxINJbl2ZslR8yEbUE7ht2UXEcZqRPEsmFyIwXQhUH0HProjo7CAH52k2ujT6iX6a-Msg/s1600/SecurityManagementGroupsSearch.png" /></a></div>
<div>
<br /></div>
<div>
Search patterns depend on the concrete security provider being used by the application.</div>
<br />
<div>
Please, read each <a href="https://github.com/uberfire/uberfire/tree/master/uberfire-extensions/uberfire-security/uberfire-security-management" target="_blank">provider's documentation</a> for more information.<br />
<br />
<ul>
<li><b>Creating new groups</b></li>
</ul>
<br />
By clicking on the "<i>New group +</i>" anchor, a new screen will be presented on the center panel to perform a new group creation.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh_RjBq9y4b8WCN6Aj9aqKmCf0quFpte_FsvtDMRbqmhwfDrmhBfVLfyk2YprID0qL7Y2h45a5o96eBXOFNa-W_wA8A89r9AdtrJV83YC0ttvTVofiJ9wdQ0_43ydztlW2bXonCQ9BkIXM/s1600/SecurityManagementNewGroup.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh_RjBq9y4b8WCN6Aj9aqKmCf0quFpte_FsvtDMRbqmhwfDrmhBfVLfyk2YprID0qL7Y2h45a5o96eBXOFNa-W_wA8A89r9AdtrJV83YC0ttvTVofiJ9wdQ0_43ydztlW2bXonCQ9BkIXM/s1600/SecurityManagementNewGroup.png" /></a></div>
<div>
After typing a name and clicking <i>Save</i>, the next step is to assign users to it:</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhhxO-AC2pf7WR30IJU87KBNDy02SLF34qtXFi491ud7tMmbTq5uxXaDqCLvULfZ5d-rbCRez_i_rMb72Tjmj_tGFo_9Mb9z4SQ73L0XTkbptfeh0DH-_2_iF4B371VrKg3_jGCc9FTAxE/s1600/SecurityManagementNewGroupUserSelection.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhhxO-AC2pf7WR30IJU87KBNDy02SLF34qtXFi491ud7tMmbTq5uxXaDqCLvULfZ5d-rbCRez_i_rMb72Tjmj_tGFo_9Mb9z4SQ73L0XTkbptfeh0DH-_2_iF4B371VrKg3_jGCc9FTAxE/s1600/SecurityManagementNewGroupUserSelection.png" /></a></div>
<div>
<br />
Clicking on the "<i>Add selected users</i>" button finishes the group creation.</div>
<ul>
<li><b>Modifying a group</b></li>
</ul>
After clicking on a group in the left sidebar, the security settings editor for the selected group instance is opened on the screen's right. Further details at the "<i>Security Settings Editor"</i> section below.<br />
<br />
<ul>
<li><b>Deleting groups</b></li>
</ul>
To delete an existing group just click on the <i>Delete</i> button.</div>
<div>
<br /></div>
<div>
<h2>
Role management</h2>
<br />
By selecting the <i>Roles</i> tab in the left sidebar, the application shows all the application roles:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj2zvMoEX_FNia7wrtvXOfbHQW_czZDfRRbbdRERaftyKQ5TTEG0BaHwdZZaVU0_TVgaD6ZWxBd66x_T34iV3s4IM1_VZia9hp2d86OSEAIGXNtYyVe_ds68XKsUvGG5tFaLKDZrVtwPrs/s1600/SecurityManagementRolesExplorer.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj2zvMoEX_FNia7wrtvXOfbHQW_czZDfRRbbdRERaftyKQ5TTEG0BaHwdZZaVU0_TVgaD6ZWxBd66x_T34iV3s4IM1_VZia9hp2d86OSEAIGXNtYyVe_ds68XKsUvGG5tFaLKDZrVtwPrs/s640/SecurityManagementRolesExplorer.png" width="426" /></a></div>
<div>
<br /></div>
Unlike users and groups, roles can not be created nor deleted as they come from the application's web.xml descriptor. After clicking on a role in the left sidebar, the role editor is opened on the right, which is exactly the same security settings editor used for groups. Further details at the "<i>Security Settings Editor"</i> section.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhYwhJqSuH444QNNVfx1R2dnU3Y3zDpOQEL37huMZ06hY6gq2v-95sgbzN1O-lDdkJZePCg7sq7Wq8VX7FZsIlccuOYea02wZfiU3gOXWNv8PhTIIefzXbRGl9rFgEC-TGgktnO-KYoAPc/s1600/SecurityManagementEditRole.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhYwhJqSuH444QNNVfx1R2dnU3Y3zDpOQEL37huMZ06hY6gq2v-95sgbzN1O-lDdkJZePCg7sq7Wq8VX7FZsIlccuOYea02wZfiU3gOXWNv8PhTIIefzXbRGl9rFgEC-TGgktnO-KYoAPc/s1600/SecurityManagementEditRole.png" /></a></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
That means both role and group based permissions can be defined. The main difference between roles and group are:</div>
<ul>
<li>Roles are an application defined resource. They are defined as <security-role> entries in the application's web.xml descriptor.</li>
</ul>
<ul>
<li>Groups are dynamic and can be defined at runtime. The installed security provider determines where groups instances are stored.</li>
</ul>
<br />
They can be used together without any trouble. Groups are recommended though as they are a more flexible than roles.</div>
<div>
<br /></div>
<div>
<ul>
<li><b>Searching for roles</b></li>
</ul>
<br />
In addition to listing all the roles, search is also allowed. When specifying the search pattern in the search box the roles listed will be reduced to only those that matches the search pattern.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh68afxSvvnMRUeNirCgPCaYnN8Qdiz55mONXvKb9MjU6L16VG2N9qcmuXNMpJhLauSd1C9Up0aXvIi8EJigx3DKruUTkrmO0BljynTqsm2Hxo7Dk5WHA77R8g1dD0emJsoLMIIzt8nOvs/s1600/SecurityManagementRolesSearch.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh68afxSvvnMRUeNirCgPCaYnN8Qdiz55mONXvKb9MjU6L16VG2N9qcmuXNMpJhLauSd1C9Up0aXvIi8EJigx3DKruUTkrmO0BljynTqsm2Hxo7Dk5WHA77R8g1dD0emJsoLMIIzt8nOvs/s1600/SecurityManagementRolesSearch.png" /></a></div>
<br />
Search patterns depend on the concrete security provider being used by the application.</div>
<div>
<br /></div>
<div>
Please, read each <a href="https://github.com/uberfire/uberfire/tree/master/uberfire-extensions/uberfire-security/uberfire-security-management" target="_blank">provider's documentation</a> for more information.<br />
<br />
<br />
<h2>
Security Settings Editor</h2>
<br />
This editor is used to set several security settings for both roles and groups.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgFT8YKyxJww1Qu3vvkwRMYNA01BdMpdGYHzcGXU7oDdsnDpd92MBnVanY062SS_FwVbaUL8Pb4MxqYugtlgUFJZribhYeFRL5W2JP9xZKPlo-mfe4gmpKXz6rNoEG1Vrfn5T9kaisvp2Y/s1600/SecurityManagementSecuritySettsEditor.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgFT8YKyxJww1Qu3vvkwRMYNA01BdMpdGYHzcGXU7oDdsnDpd92MBnVanY062SS_FwVbaUL8Pb4MxqYugtlgUFJZribhYeFRL5W2JP9xZKPlo-mfe4gmpKXz6rNoEG1Vrfn5T9kaisvp2Y/s1600/SecurityManagementSecuritySettsEditor.png" /></a></div>
<h4>
</h4>
<h4>
Home perspective</h4>
<br />
This is the perspective where the user is directed after login. This makes it possible to have different home pages for different users, since users can be assigned to<br />
different roles or groups.<br />
<br />
<h4>
Priority</h4>
<br />
It is used to determine what settings (home perspective, permissions, ...) have precedence for those users with more that one role or group assigned.<br />
<br />
Without this setting, it won't be possible to determine what role/group should take precedence. For instance, an administrative role has higher priority than a non-administrative one. For users with both administrative and non-administrative roles granted, administrative privileges will always win, provided the administrative role's priority is greater than the other.<br />
<br />
<h4>
Permissions</h4>
<br />
Currently, only perspective permissions are supported in the UI. If access to a perspective is denied then it will not be shown in any of application menus. Update, Delete and Create permissions change the behaviour of the perspective management plugin editor.</div>
<div>
<br /></div>
<div>
For perspectives, it is possible to define global permissions and add single instance exceptions afterwards. For instance, <i>Read</i> access can be granted to all the perspectives and deny access just to an individual perspective. This is called the <b>grant all deny a few</b> strategy.</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjfZ-2jZVLl_Y35t2cenHYsqLBEsahBvtP9PpF-tyzvD7Cf_ERIg5jFUQJjF6a2b0NegNOGJKxK4K_z70MR0Gm597sd31MsoaYdgDHcVsKoae7cLIo9obNizxnt307YLOiLMH7FXrAwWxI/s1600/SecurityManagementPerspectiveDenied.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjfZ-2jZVLl_Y35t2cenHYsqLBEsahBvtP9PpF-tyzvD7Cf_ERIg5jFUQJjF6a2b0NegNOGJKxK4K_z70MR0Gm597sd31MsoaYdgDHcVsKoae7cLIo9obNizxnt307YLOiLMH7FXrAwWxI/s1600/SecurityManagementPerspectiveDenied.png" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
The opposite, <b>deny all grant a few</b> strategy is also supported:</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgv84tCkmEn4RwKdAZGBsSpfRumOUX0yIVVjdoItc0csqOtiiCOTdZ07JTYxkg9Alm5qipXRkCtmZuPfI0PeE-rarEwgfP8fWxn9zHc2DgpaLjcPWAVmmTABrv6yfxTuG9AGwh8U4y1hnE/s1600/SecurityManagementPerspectiveGranted.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgv84tCkmEn4RwKdAZGBsSpfRumOUX0yIVVjdoItc0csqOtiiCOTdZ07JTYxkg9Alm5qipXRkCtmZuPfI0PeE-rarEwgfP8fWxn9zHc2DgpaLjcPWAVmmTABrv6yfxTuG9AGwh8U4y1hnE/s1600/SecurityManagementPerspectiveGranted.png" /></a></div>
<div>
<br /></div>
<div>
NOTE: In the example above, the <i>Update</i> and <i>Delete</i> permissions are disabled as it does not makes sense to define such permissions if the user is not even able to read perspectives.<br />
<br />
<br />
<h2>
Security Policy Storage</h2>
<br />
The security policy is stored under the workbench’s VFS. Most concrete, in a GIT repo called “security”.<br />
The ACL table is stored in a file called “security-policy.properties” under the “authz” directory. Next is an example of the entries this file contains:<br />
<br />
<i>role.admin.home=HomePerspective<br />role.admin.priority=0<br />role.admin.permission.perspective.read=true<br />role.admin.permission.perspective.create=true<br />role.admin.permission.perspective.delete=true<br />role.admin.permission.perspective.update=true</i><br />
<br />
Every time the ACL is modified from the security settings UI the changes are stored into the GIT repo.<br />
<br />
Initially, when the application is deployed for the first time there is no security policy stored in GIT. However, the application might need to set-up a default policy with the different access profiles for each of the application roles.<br />
<br />
In order to support default policies the system allows for declaring a security policy as part of the webapp’s content. This can be done just by placing a security-policy.properties file under the webapp’s resource classpath (the <i>WEB-INF/classes</i> directory inside the WAR archive is a valid one). On app start-up the following steps are executed:<br />
<br />
<ul>
<li>Check if an active policy is already stored in GIT</li>
<li>If not, then check if a policy has been defined under the webapp’s classpath</li>
<li>If found, such policy is stored under GIT</li>
</ul>
<br />
The above is an auto-deploy mechanism which is used in the workbench to set-up its default security policy.<br />
<br />
One slight variation of the deployment process is the ability to split the “security-policy.properties” file into small pieces so that it is possible, for example, to define one file per role. The split files must start by the “security-module-” prefix, for instance: “security-module-admin.properties”. The deployment mechanism will read and deploy both the "security-policy.properties" and all the optional “security-module-?.properties” found on the classpath.<br />
<br />
Notice, despite using the split approach, the “security-policy.properties” must always be present as it is used as a marker file by the security subsystem in order to locate the other policy files. This split mechanism allows for a better organization of the whole security policy.</div>
<div>
<br />
<h2>
Authorization API</h2>
<br />
Uberfire provides a complete API around permissions. The <i>AuthorizationManager</i> is the main interface for checking if permissions are granted to users.<br />
<div>
<pre style="border-radius: 3px; border: 0px; box-sizing: border-box; margin-bottom: 16px; overflow: auto; padding: 16px; word-wrap: normal;"><pre style="background-color: #f7f7f7; border-image-outset: initial; border-image-repeat: initial; border-image-slice: initial; border-image-source: initial; border-image-width: initial; border-radius: 3px; border: 0px; box-sizing: border-box; color: #333333; font-family: consolas, 'liberation mono', menlo, courier, monospace; font-size: 13.6px; line-height: 1.45; margin-bottom: 16px; overflow: auto; padding: 16px; white-space: pre-wrap; word-wrap: normal;"><code style="background: transparent; border-radius: 3px; border: 0px; box-sizing: border-box; display: inline; font-family: consolas, 'liberation mono', menlo, courier, monospace; font-size: 13.6px; line-height: inherit; margin: 0px; padding: 0px; white-space: pre; word-wrap: normal;">@Inject
AuthorizationManager authzManager;
Perspective perpsective1;
User user;
...
boolean result = authzManager.authorize(perspective1, user);</code></pre>
</pre>
</div>
Using the fluent API can also be expressed as:<br />
<div>
<br /></div>
<div>
<pre style="background-color: #f7f7f7; border-radius: 3px; border: 0px; box-sizing: border-box; color: #333333; font-family: consolas, 'liberation mono', menlo, courier, monospace; font-size: 13.6px; line-height: 1.45; margin-bottom: 16px; overflow: auto; padding: 16px; white-space: pre-wrap; word-wrap: normal;"><code style="background: transparent; border-radius: 3px; border: 0px; box-sizing: border-box; display: inline; font-family: consolas, 'liberation mono', menlo, courier, monospace; font-size: 13.6px; line-height: inherit; margin: 0px; padding: 0px; white-space: pre; word-wrap: normal;">authorizationManager.check(perspective1, user)
.granted(() -> ...)
.denied(() -> ...); </code></pre>
<br />
The security check calls always use the permissions defined in the security policy.<br />
<br />
For those interested in those APIs, an entire chapter can be found in the <a href="http://www.uberfireframework.org/docs/security/security.html">Uberfire's documentation</a>.<br />
<br />
<h2>
Summary</h2>
<br />
The features described above bring even more flexibility to Dashbuilder. Users and groups can be created right from the UI, new assets like perspectives can be authored (the new Perspective editor is about to be released :-) ) and, finally, permissions on perspectives can be granted or denied.<br />
<br />
In the future, along with the improvement of the authoring capabilities, more permission types will be added. The ultimate goal is to deliver a zero/low code, very flexible and customizable tooling which allows to develop, build and deploy business dashboards in the cloud.<br />
<br />
<div>
UF Dasbuilder is close to its 1.0 release. Only a few major features like the filter controls or the perspective builder are still in progress. The next article will introduce the perspective builder which is the main component used for dashboard design. Stay tuned!</div>
<div>
<br /></div>
</div>
<div>
<div style="box-sizing: border-box; color: #333333; font-family: 'open sans', 'clear sans', 'helvetica neue', helvetica, arial, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;">
<span style="color: black; font-family: "times new roman"; font-size: small; line-height: normal;"><br /></span></div>
<div style="box-sizing: border-box; color: #333333; font-family: 'open sans', 'clear sans', 'helvetica neue', helvetica, arial, sans-serif; font-size: 16px; line-height: 25.6px; margin-bottom: 16px;">
</div>
</div>
</div>
Unknownnoreply@blogger.com24tag:blogger.com,1999:blog-4358594258656726438.post-7103714410576575162016-07-01T00:48:00.003+02:002016-07-01T00:48:53.740+02:00UF Dashbuilder - Upgraded support for Elastic Search 2.x<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi5Pqrq807ofZQVxevsRtBkhe2nmUN0-5PAmDXyXXH0lUDaORU1nEa2nXZAw2ruUakHXlM39cZODN9XawAS0RbrXuMHsoNZFZgP7G6GSOP7EQDpHhL_EuKTV2l1bEMlve_uOKmnO5FsjKU5/s1600/el_icon_32.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi5Pqrq807ofZQVxevsRtBkhe2nmUN0-5PAmDXyXXH0lUDaORU1nEa2nXZAw2ruUakHXlM39cZODN9XawAS0RbrXuMHsoNZFZgP7G6GSOP7EQDpHhL_EuKTV2l1bEMlve_uOKmnO5FsjKU5/s1600/el_icon_32.png" /></a>The Dashbuilder's <i><b>Elastic Search Data Provider</b></i> support has been upgraded to the latest Elastic version, so you can now create your dashboards consuming both <a href="https://www.elastic.co/" target="_blank">Elastic Search</a> 1.x or 2.x.<br />
<br />
<br />
Now it is extremely easy to create your own data sets, data visualizations and dashboards from data located in any Elastic Search node. Just give it a try!<br />
<br />
Please, take a look at the <a href="https://github.com/dashbuilder/dashbuilder/tree/master/dashbuilder-backend/dashbuilder-dataset-elasticsearch" target="_blank">Elastic Search Data provider documentation</a> and also consider following this <a href="https://github.com/dashbuilder/dashbuilder/tree/master/dashbuilder-backend/dashbuilder-dataset-elasticsearch/example" target="_blank">quick start guide</a> which provides some examples and it will teach you how to create a simple showcase environment in just minutes.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi6RakGMDF7IV7znTv9_k0C8rStPG3yBz2NgfFb58ClbS4P07HkuXC9SWxlNFsY6jJJS_heMvMkLb3QW8KqAcshU8N8rEEonOkGbRSAFnVgwzuoFFON0ww5OlNwl_DmtlNlKMDeIVPxVMOZ/s1600/uf-dash-els-data-provider.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="256" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi6RakGMDF7IV7znTv9_k0C8rStPG3yBz2NgfFb58ClbS4P07HkuXC9SWxlNFsY6jJJS_heMvMkLb3QW8KqAcshU8N8rEEonOkGbRSAFnVgwzuoFFON0ww5OlNwl_DmtlNlKMDeIVPxVMOZ/s640/uf-dash-els-data-provider.png" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Elastic Search data set authoring</td></tr>
</tbody></table>
<br />
Getting into more technical details, this upgrade implies a complete internal refactoring of the connector and the endpoint consumer. This is due to the upgrade to <i>Java 8</i> in current Dashbuilder version in master, which allows to get rid of the Jest client used to connect to the Elastic Search node and use the native <a href="https://www.elastic.co/guide/en/elasticsearch/client/java-api/current/client.html" target="_blank">Elastic's Java client</a> instead. A lot of marshalling/parsing code has been removed and all the remote service communication is now delegated to the Elastic's client itself, which makes Dashbuilder's code cleaner and easy to manipulate and extend according your needs.<br />
<br />
<br />
<br />
<br />Unknownnoreply@blogger.com2tag:blogger.com,1999:blog-4358594258656726438.post-2657723747912627272015-10-20T19:07:00.001+02:002015-10-29T17:18:17.106+01:00UF Dashbuilder - Real-time dashboard with ElasticSearch & Logstash<br />
This article is about a new Dashbuilder's feature for consuming and visualizing data stored in an <i>ElasticSearch </i>server. <i>ElasticSearch</i> (aka <i>ELS</i>) is a noSQL storage, indexing & search service that <span style="background-color: white; color: #252525; font-family: sans-serif; font-size: 14px; line-height: 22.3999996185303px;">provides</span> a distributed, multitenant-capable full-text search engine with a RESTful web interface and schema-free JSON documents. If you want to learn more about it, please visit the <a href="https://www.elastic.co/products/elasticsearch" target="_blank">ElasticSearch home page</a>.<br />
<br />
Dashbuilder is a web based tooling that eases the process of building dashboards . As you might know, Dashbuilder provides a simple API that allows to integrate with any external storage system: the <i>Data Provider API</i>. Since latest <i>0.3.0.Final</i> release, Dashbuilder adds another data provider for the <i>Elastic Search </i>integration, along with the already existing CSV, SQL and Bean providers. This new one provider allows the users to consume unstructured data from an ElasticSearch server instance at real-time. So you can abstract the data stored in your ELS into a data set structure, and then use all the <i>Data Set API</i> features and power to create your visualizations, as can be done with any of the other data providers available.<br />
<br />
The following sections will give you a quick overview of the ElasticSearch integration features. At the end of the article you will also find a tutorial that shows how easy is to integrate Dashbuilder with an ELS server, or as in this example, with the <a href="https://www.elastic.co/webinars/introduction-elk-stack" target="_blank">ELK stack</a>, providing an step-by-step tutorial for the creation of a real-time system metrics dashboard. (You can skip the first part of this article if you are only interested following the the tutorial).<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEifpZkYKEdAbv-4ZomcIAFbmULeh1D7y1PBgILXmS6r46eO-z8FWDkhkGeb3EhjE03iLzNeelp7otbcghtW0FbM5kgoL3KCRPdGAILTKI7StM3LVm4vrWfsAPHC6z3_uprmu4KKNO1i_plW/s1600/dashbresulting-dashboard.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="392" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEifpZkYKEdAbv-4ZomcIAFbmULeh1D7y1PBgILXmS6r46eO-z8FWDkhkGeb3EhjE03iLzNeelp7otbcghtW0FbM5kgoL3KCRPdGAILTKI7StM3LVm4vrWfsAPHC6z3_uprmu4KKNO1i_plW/s640/dashbresulting-dashboard.png" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><i>The tutorial's resulting dashboard</i></td></tr>
</tbody></table>
<br />
<span style="color: red;"><br /></span>
<br />
<h3>
The ElasticSearch data provider</h3>
<div>
<br /></div>
<h4>
Overview</h4>
<div>
</div>
The main goal for the <b><i>Elastic Search data provider</i></b> is to consume unstructured data from an ELS index and generate a resulting structured data set, which can be used along the application to create your visualizations and dashboards.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEje0NZEuIbSlSKaJWbtr_Z7CdztW7BCmm7LCx7OiSPVSuWKISvArlz-lnbewsi33qKZz3o3qfZktpObmsSH1HaMVWTc-V5rjHSfl4WS6JTNGhf0YXXzRzi46IJMCHgjTnjAfJ91Gc8eyxRq/s1600/ELS+provider+overview.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="449" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEje0NZEuIbSlSKaJWbtr_Z7CdztW7BCmm7LCx7OiSPVSuWKISvArlz-lnbewsi33qKZz3o3qfZktpObmsSH1HaMVWTc-V5rjHSfl4WS6JTNGhf0YXXzRzi46IJMCHgjTnjAfJ91Gc8eyxRq/s640/ELS+provider+overview.png" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><i>Elastic Search Data Provider overview</i></td></tr>
</tbody></table>
As you can see, Dashbuilder communicates with the server instance using the <a href="https://www.elastic.co/guide/en/elasticsearch/reference/1.7/index.html" target="_blank">RESTFul API</a> provided by ElasticSearch. It allows an easy integration as the protocol used for the communication is the HTTP/JSON one, which has lots of already well known advantages, such as providing data in an easy and human readable structure, skipping the needs for firewall configurations, etc etc.<br />
<br />
<h4>
Key concepts</h4>
<div>
</div>
In order to consume data from an index stored in a ELS server, the data provider needs a set of mandatory attributes that describe where and how to find and consume it. These attributes are defined by the user and stored in a structure called <i><b>Elasticsearch Data Set Definition</b>. </i>The minimal attributes to set in order to consume data from an ELS instance are:<br />
<br />
<table cellspacing="10">
<tbody>
<tr><th>Attribute</th><th>Example</th><th>Description</th></tr>
<tr><td>Server URL</td><td><i>http://localhost:9200</i></td><td>The server URL for your ELS RESTFul API services</td></tr>
<tr><td>Cluster name</td><td><i>elasticsearch</i></td><td>The name of the cluster in the server instance</td></tr>
<tr><td>Index</td><td><i>expensereports</i></td><td>The name of the index to consume</td></tr>
<tr><td>Type/s</td><td><i>expense</i></td><td>The document type/s to consume for the given index</td></tr>
</tbody>
</table>
<br />
Once a data set definition is created, Dashbuilder is able to process data lookup calls against the ELS instance and generate a resulting data set, so finally the users can create their visualizations and dashboards using the remote data.<br />
<br />
Another important key point about turning ELS unstructured data into structured data sets are the <b><i>data set columns</i></b>. ElasticSearch provides its own core data types that are implicitly bind to data set columns by the ELS data provider.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiBec2qBwYVi8n1hygtN0Xt2ivNRcY4uPi47rsnQzWNMFBmr3gUZMrhyphenhyphenzZuiwYcpe_qyjRovfyC_GtTAFRwbazABupjYpCeRGbGkX7FVxLTnxITZjuj912YaqyYNJeeGB6E-gEk8wHmv8E5/s1600/ELS+columns+binding.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="262" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiBec2qBwYVi8n1hygtN0Xt2ivNRcY4uPi47rsnQzWNMFBmr3gUZMrhyphenhyphenzZuiwYcpe_qyjRovfyC_GtTAFRwbazABupjYpCeRGbGkX7FVxLTnxITZjuj912YaqyYNJeeGB6E-gEk8wHmv8E5/s640/ELS+columns+binding.png" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><i>Data columns binding from an index mappings</i></td></tr>
</tbody></table>
<br />
The data columns binding is done automatically by the application when creating a new ELS data set definition. It binds the <i>field name</i>, <i>data type</i>, <i>format</i> and <i>patterns</i> from an ELS index mappings into data set columns with a given name, data type, format and pattern as well.<br />
<br />
A detailed documentation about how column binding works and other cool features can be found at the <a href="https://github.com/dashbuilder/dashbuilder/blob/master/dashbuilder-backend/dashbuilder-dataset-elasticsearch/README.md" target="_blank">ElasticSearch data provider documentation</a>.<br />
<br />
<h2>
Real-time system metrics dashboard</h2>
<div>
</div>
This section is intended to be an a step-by-step tutorial that will show you how to define and consume data from an ELS server instance and use it to create your visualizations and dashboards from scratch.<br />
<br />
As you will see in this tutorial, it's really easy to create data set definitions, visualizations and dashboards in Dashbuilder. This demo is intended for non-technical users, as there is no need for coding or having high level technical skills. In a few mouse clicks you will be consuming your ELS data and creating dashboards! :)<br />
<br />
Let's see the scenario used for this tutorial and then we will deep into each workflow step for achieving a real-time system metrics dashboard.<br />
<br />
<h3>
Scenario</h3>
<div>
</div>
The main goal for the system metrics dashboard is to be able to consume and visualize different metrics that come from different computers at real-time.<br />
<br />
For this tutorial we have used a well known system metrics reporting and storage environment provided by the <a href="http://collectd.org/" target="_blank"><i>collectd</i> daemon</a> and the <a href="https://www.elastic.co/webinars/introduction-elk-stack" target="_blank">ELK stack</a>. We decided to use this scenario as it's really easy to setup and you can find lots of documents and articles on the net about it. The main difference with the other tutorials based on the ELK stack is the use of <a href="http://dashbuilder.org/" target="_blank">Dashbuilder</a> as the monitoring web application instead of <i><a href="https://www.elastic.co/products/kibana" target="_blank">Kibana</a></i>.<br />
<br />
The following diagram describes the environment used in this tutorial:<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi9oVqS5tSmnWzPXlvsf9YWsgrBCLGcDDuwPKup9lpDe22LT4c-dtokBKx4WCr5_rU_yKTE6Bpdl8VDlrnPi6dJm1alEN7QNmm4XS5V7QLkwuBcnrcLArXmaaezMt76fHRnSZ6IVJMCgCNZ/s1600/Real-time+dashboard+scenario.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="344" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi9oVqS5tSmnWzPXlvsf9YWsgrBCLGcDDuwPKup9lpDe22LT4c-dtokBKx4WCr5_rU_yKTE6Bpdl8VDlrnPi6dJm1alEN7QNmm4XS5V7QLkwuBcnrcLArXmaaezMt76fHRnSZ6IVJMCgCNZ/s640/Real-time+dashboard+scenario.png" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><i>System metrics scenario</i></td></tr>
</tbody></table>
As you can see, the scenario consists of:<br />
<br />
<ul>
<li>Two computers to be monitored - Computer A & Computer B</li>
<li>The main server that provides:</li>
<ul>
<li>An instance of <i>Logstash</i> server</li>
<li>An instance of an <i>ElasticSearch</i> server</li>
<li>The Dashbuilder application</li>
</ul>
<li>A single client that consumes the dashboard/s</li>
</ul>
The overall workflow for this scenario follows these steps:<br />
<br />
<ol>
<li><u>Collection and transmission of the system metrics</u><br />Both computer A and computer B have the <i>collectd </i>service running, which captures some of the system metrics and send these ones over the local network using TCP and UDP packets</li>
<li><u>Process and storage of the system metrics</u><br />The <i>collectd </i>resulting packets from both computers are processed by the <i>Logstash</i> server and sent to <i>ElasticSearch</i>, responsible for storing all the metrics data in a given index</li>
<li><u>Consume and visualize the system metrics</u><br />Once the client that consumes the dashboard needs to retrieve some metric data, Dashbuilder application performs all the data look-up operations against the ELS storage server, producing the resulting data sets that feed your dashboards and visualizations.</li>
</ol>
<blockquote class="tr_bq">
<span style="font-size: x-small;">NOTE: In this tutorial, the Logstash server has been configured to store the logs into an index named <i>logstash-logs</i> in the ELS instance, and is not the default one used by <i>Logstash </i>in a clean installation.</span></blockquote>
Once having this or a similar scenario, we are able to consume the computer metrics from the <i>ElasticSearch</i> server and benefit from all Dashbuilder's features.<br />
<br />
Keep in mind that Dashbuilder only worries about the ELS server data, it does not care how metrics are collected, processed or transmitted. This means you can store the metrics in any storage supported by Dashbuilder.<br />
<br />
<h3>
Metrics data</h3>
<div>
</div>
<div>
Using <i>collectd </i>for generating the metrics provides a huge flexibility and power as it's really easy to install, configure and it supports lots of plugin and metrics. Consider that these metrics are captured by the <i>Logstash</i> server, which process and finally stores each one into the ELS server. So here is the list of fields in the generated logstash's index for each metric that will be consumed by the tutorial:</div>
<div>
<br /></div>
<table cellspacing="10">
<tbody>
<tr><th>Field name</th><th>Description</th></tr>
<tr><td><i>@timestamp</i></td><td>The timestamp for the metric</td></tr>
<tr><td><i>host.raw</i></td><td>The hostname that produces the metric (the ".raw" indicates that we are using a multi-field for the <i>host</i> field in the index, for the logstash generated index, it contains the <i>not_analyzed</i> value of the hostname)</td></tr>
<tr><td><i>plugin</i></td><td>The metric plugin (cpu, memory, df, processes, interface)</td></tr>
<tr><td><i>plugin_instance</i></td><td>The instance for the metric for a given plugin</td></tr>
<tr><td><i>type_instance</i></td><td>The type for a given metric (cpu used, cpu free, etc)</td></tr>
<tr><td><i>value</i></td><td>Contains the concrete value for the given metric and type</td></tr>
<tr><td><i>rx</i></td><td>Contains the network packets received in the given interval</td></tr>
<tr><td><i>tx</i></td><td>Contains the network packets sent in the given interval</td></tr>
</tbody>
</table>
<div>
<br /></div>
<div>
Here you can find more information about the <a href="https://collectd.org/wiki/index.php/Table_of_Plugins" target="_blank">collectd plugins and metrics</a> and the <a href="https://www.elastic.co/blog/logstash-collectd-input-plugin" target="_blank">collectd input plugin for <i>Logstash</i></a>.</div>
<div>
<br />
Let's deep into the step-by-step creation of the system metrics dashboard!<br />
</div>
<div>
<h3>
Step by step tutorial</h3>
</div>
<div>
</div>
Once described the environment and the metrics to be consumed, let's start the tutorial for creating a real-time system metrics dashboard using Dashbuilder.<br />
<br />
The result of this tutorial is given by a simple three step workflow:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhoINnl9npqer9P3jdp4n308spy1OEI3_0U-HfFOS2lAefqmuxrDofa3ooutHOPCvRj4DsoN9iCcXlXlmEf2NV6H2E2vk5FTd2JIrNNRR3_FgJ6KmFqFVVWvXaZpeHazNJVwkDuawxQe1dH/s1600/ELS+workflow.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhoINnl9npqer9P3jdp4n308spy1OEI3_0U-HfFOS2lAefqmuxrDofa3ooutHOPCvRj4DsoN9iCcXlXlmEf2NV6H2E2vk5FTd2JIrNNRR3_FgJ6KmFqFVVWvXaZpeHazNJVwkDuawxQe1dH/s1600/ELS+workflow.png" /></a></div>
<blockquote class="tr_bq">
Considerations:<br />
<ul>
<li>Dashbuilder web application running at http://localhost:8080/dashbuilder</li>
</ul>
<ul>
<li>ElasticSearch server RESTFul API available and running at http://localhost:9200</li>
</ul>
<ul>
<li>Consider the <i>logstash</i> for the ELS cluster name. </li>
</ul>
</blockquote>
<blockquote class="tr_bq">
<ul>
<li>Consider <i>logstash-logs </i>as the index generated by logstash in the ELS server which contains all system metrics data</li>
</ul>
</blockquote>
<div>
<h4>
Step 1 - Create the data set definition</h4>
</div>
<div>
</div>
Let's create the definition for our metrics data set.<br />
<br />
This tutorial describes just the minimal configuration required for generating a data set with all metrics stored in the ELS server's index. It does not deep into the use of data set filters, column types modifications or advanced attributes and features. Just try and play yourself with it! ;)<br />
<br />
At Dashbuilder web application's home click on <i>Authoring -> Data Set Authoring</i> item on top menu:<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjBGvWjEU-s1hry4XVv3eaD3jtSAHz5T_o7CJNg3QIQRTuX5KXeZ87AxYb316BG8kx8S2t5F3BFhaOvS8YhA_HIkSn8se6Teovf5-UfHWvVh3vWepUvrz8Rrx4EZboZ6QrNP3lLYnH8MvWa/s1600/dashb-home.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="248" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjBGvWjEU-s1hry4XVv3eaD3jtSAHz5T_o7CJNg3QIQRTuX5KXeZ87AxYb316BG8kx8S2t5F3BFhaOvS8YhA_HIkSn8se6Teovf5-UfHWvVh3vWepUvrz8Rrx4EZboZ6QrNP3lLYnH8MvWa/s640/dashb-home.png" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><i>Data set authoring menu item</i> </td></tr>
</tbody></table>
Once at the data set authoring perspective, click on <i>New data set </i>button provided in the data set explorer view:<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjybJ5D_qYH06NMOZ2SKjG4IBkiqLDk_SKw6fpHk8teyIIZvBeHsGkM9F57QWJc4-uIKNnVckCn1IX0Hz_kgcmbxShjaL8gcv6rPRcDp4_eJg1OfcE9oV2rDEWOX6lbq6kXzKDrRzS0FyHb/s1600/dashb-new-dataset.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="215" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjybJ5D_qYH06NMOZ2SKjG4IBkiqLDk_SKw6fpHk8teyIIZvBeHsGkM9F57QWJc4-uIKNnVckCn1IX0Hz_kgcmbxShjaL8gcv6rPRcDp4_eJg1OfcE9oV2rDEWOX6lbq6kXzKDrRzS0FyHb/s400/dashb-new-dataset.png" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><i>New data set button</i></td></tr>
</tbody></table>
On the center area of the data set authoring perspective appears a data set creation wizard. First step is to select the data provider type, for this tutorial select the <i>ElasticSearch</i> one and click on <i>Next</i>:<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjHwUuML4MME_MJzzRat8rm7itagzU_B_NrtcS5jiWq7icFbl2HHCNFhYmZv-86SUTXwRljyEc4AdV7vEvA9Rqe5rFwgBmAs6a90FCRENMhJuBMuQgssiBUNW-nBJ2sONv2dxe643PmQ1tB/s1600/dashb-provider-selection.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="211" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjHwUuML4MME_MJzzRat8rm7itagzU_B_NrtcS5jiWq7icFbl2HHCNFhYmZv-86SUTXwRljyEc4AdV7vEvA9Rqe5rFwgBmAs6a90FCRENMhJuBMuQgssiBUNW-nBJ2sONv2dxe643PmQ1tB/s640/dashb-provider-selection.png" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><i>Data provider type selection screen</i></td></tr>
</tbody></table>
Next screen is the <i>ElasticSearch data provider</i> configuration, use the configuration values from your scenario and click on <i>Test </i>button:<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiphX9979Mo7eOTrsmpw1SjRXv81rLTYdw_VKdu4heYRzTgPL5ZPXHpm7Y_I_aoWD-cxHgcwi88-REY97sQJMNHiAjxKwu3IkH-XeJvKBbZQMnpSnmYzplW0P9cukgVWsIsQiMyfBRA6Mys/s1600/dashb-data-config.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="276" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiphX9979Mo7eOTrsmpw1SjRXv81rLTYdw_VKdu4heYRzTgPL5ZPXHpm7Y_I_aoWD-cxHgcwi88-REY97sQJMNHiAjxKwu3IkH-XeJvKBbZQMnpSnmYzplW0P9cukgVWsIsQiMyfBRA6Mys/s640/dashb-data-config.png" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><i>Data provider configuration screen</i></td></tr>
</tbody></table>
At this point, the application is able to communicate with the ELS server and retrieve the mappings for the index and some preview values:<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjmw7k-9bDcUQLg3RmMxJTD2UjA82sS_JJ4dbTXLDyulTkYyfS11Ivc7pxyj57cNVQGkJPkV-vsQHoTHiwiLwMIwMoPxdzsPcsV0VgZX5JPPEATspILY_tihVJIAo8Rp87zlfF9tTDlqZgB/s1600/dashb-preview-table.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="258" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjmw7k-9bDcUQLg3RmMxJTD2UjA82sS_JJ4dbTXLDyulTkYyfS11Ivc7pxyj57cNVQGkJPkV-vsQHoTHiwiLwMIwMoPxdzsPcsV0VgZX5JPPEATspILY_tihVJIAo8Rp87zlfF9tTDlqZgB/s640/dashb-preview-table.png" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><i>Data provider configuration and data set preview screen</i></td></tr>
</tbody></table>
At this screen you can add or remove the data set columns, modify their column types, specify an initial data set filter, and configure more advanced features at the <i>Advanced</i> tab.<br />
<br />
As commented, this tutorial describes a minimal configuration for creating the data set definition, although is not the best implementation for real production usages.<br />
<br />
Tips:<br />
<blockquote class="tr_bq">
<ul>
<li>Just select the columns for your needs</li>
</ul>
<ul>
<li>Modify column types for your needs</li>
</ul>
<ul>
<li>Add initial filters when consuming the data set from several indicators</li>
</ul>
<ul>
<li>Consider data set refreshing</li>
</ul>
<ul>
<li>Do not create just one data set definition for your metrics indicators, create different ones for different metrics and hosts. </li>
</ul>
</blockquote>
<blockquote class="tr_bq">
<ul>
<li>More information can be found at the previous <a href="http://dashbuilder.blogspot.com.es/2015/06/uf-dashbuilder-data-set-authoring.html" target="_blank">Data set authoring article</a>.</li>
</ul>
</blockquote>
<br />
<br />
As for this tutorial, just click on <i>Save</i> button to store your data set definition and make it available for creating the dashboard's visualizations.<br />
<br />
After save, you should see the new "<i>All system metrics"</i> data set definition in the explorer's list:<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgSxEVkxiYsSQj7P33QeXL8e8g1MFII0izR3i8vLcEPS3nTIGhXHNZJbX8FvCITRLzUqVMnb38ryF4EzlPJZQmYDkfvwTCIUm0JDOrhuqQeCPeO1u6cn3ViSMKfd1msg1nMKMnBwObqw0W9/s1600/dashb-explorer-datasets.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgSxEVkxiYsSQj7P33QeXL8e8g1MFII0izR3i8vLcEPS3nTIGhXHNZJbX8FvCITRLzUqVMnb38ryF4EzlPJZQmYDkfvwTCIUm0JDOrhuqQeCPeO1u6cn3ViSMKfd1msg1nMKMnBwObqw0W9/s320/dashb-explorer-datasets.png" width="301" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><i>Data set explorer view</i></td></tr>
</tbody></table>
Now you can create new visualizations and dashboards using the <i>All system metrics</i> data set, let's go for it!<br />
<br />
<h4>
Step 2 - Create a dashboard</h4>
<div>
</div>
<div>
To create or navigate through the existing dashboards, use the <i>Dashboards</i> top menu item.<br />
<br />
Click on<i> Dashboards -> New dashboard</i>:</div>
<div>
<br /></div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhu_YJwtadjJPsYC8iGN8UhybSAZHtKGoxOHrM2zig8nL5cq0rChAUgXwPsecaoHn7v6_EFeeJyrAuqs0Zb2hs-B7BTaBswMZMNEIRzg8aFkOauejsmrDqKueHA_0bR1kzjxIMJOnzYZKOl/s1600/dashb-create-dashboard.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="151" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhu_YJwtadjJPsYC8iGN8UhybSAZHtKGoxOHrM2zig8nL5cq0rChAUgXwPsecaoHn7v6_EFeeJyrAuqs0Zb2hs-B7BTaBswMZMNEIRzg8aFkOauejsmrDqKueHA_0bR1kzjxIMJOnzYZKOl/s400/dashb-create-dashboard.png" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><i>Dashboards menu</i></td></tr>
</tbody></table>
And set a dashboard name on the popup screen:<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiIUB_g4H7YeJ2eGJP3KgbpUC7yZ17wK9MIRtKVSIihBNAyEvevUp2cqIC_MP44L_HQEHdHQcQGb0dZuuCQZ0N7kb0UNmqe_Za8fG8K3ACWHrVux6bqrxW4rBKY7XUweDBFQp25l8G9UCX9/s1600/dashb-perspective-popup.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="209" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiIUB_g4H7YeJ2eGJP3KgbpUC7yZ17wK9MIRtKVSIihBNAyEvevUp2cqIC_MP44L_HQEHdHQcQGb0dZuuCQZ0N7kb0UNmqe_Za8fG8K3ACWHrVux6bqrxW4rBKY7XUweDBFQp25l8G9UCX9/s640/dashb-perspective-popup.png" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><i>New dashboard popup</i></td></tr>
</tbody></table>
Once a name is typed, press <i>Ok</i> and an empty dashboard appears.<br />
<br />
At this point you can create as many displayers as you need, but before starting to create the displayers, you first should think about what you want and what you need.<br />
<br />
For this tutorial consider the resulting dashboard's displayers and layout used as the following picture describes:<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgvMsrElP_ElceItI5vFqfZNPF34n7bcYi_A8qpfEDv5qb6ooBXwGQmtE29xerKos74t8pW3BweLndtqzRtowgyPHsmZzx26MR81gjusA8-1rjgyMDIl6qNH47-UMN0juutItk31bCXUTm8/s1600/ELS+system+metrics+dash.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgvMsrElP_ElceItI5vFqfZNPF34n7bcYi_A8qpfEDv5qb6ooBXwGQmtE29xerKos74t8pW3BweLndtqzRtowgyPHsmZzx26MR81gjusA8-1rjgyMDIl6qNH47-UMN0juutItk31bCXUTm8/s640/ELS+system+metrics+dash.png" width="620" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><i>Displayers and layout for the dashboard</i></td></tr>
</tbody></table>
As you can see:<br />
<br />
<ul>
<li>The dashboard will have <b>5 displayers</b><br /> </li>
<li>On left side it will have 3 metric displayers to show current memory, cpu and disk usage<br /> </li>
<li>On right side it will have an area chart (memory used in last minute) and a pie chart displayer (to show the current servers that are up and running)<br /> </li>
<li>All displayers will have the <b>refresh feature enabled</b>, using a one second interval, in order to display the real-time metrics<br /> </li>
<li>All displayers will show the <b>average value</b> for each metric, as several hosts can be present at same time<br /> </li>
<li>As you will see in the video, the metrics in real environments usually come with some delay produced by network latency, processing times, etc. So all displayers have a<i> <b>time frame</b></i><b> filter</b> to avoid this latency on the charts - for this environment we chose a time frame as:<br /><br /> <i>now -7second till now -3second</i><br /><br />Considering a maximum delay of 3 seconds for the metrics, and showing last 4 seconds of data for each one.</li>
</ul>
<br />
Next section describes how to use this popup for creating several displayers and have them created in your dashboard, so keep reading! ;)<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<h4>
Step 3 - Create the visualizations</h4>
<div>
</div>
This section explains how to create the displayers for this concrete dashboard, but it does not deep into details about the displayer editor popup and its usage, as this component has been already explained in this <a href="http://dashbuilder.blogspot.com.es/2015/03/uf-dashbuilder-displayer-editor-api_3.html" target="_blank">previous article</a>.<br />
<br />
In order to create a new displayer just click on the <i>New displayer </i>button on right side of the top menu:<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjbMpSfn3H_Z-QUI5nRzInFaB0HyPEgvPppezdtoggO9osLnm_e1lLIOQ0eD419qb0nN9OVkxDIyOyz7ikDLP_OlDkGjGGQV5FmVCgEaK_kHepW6Bqn_-ZrjgAXwhowsjYfhlRFZw4PdjhX/s1600/dashb-new-displayer-button.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjbMpSfn3H_Z-QUI5nRzInFaB0HyPEgvPppezdtoggO9osLnm_e1lLIOQ0eD419qb0nN9OVkxDIyOyz7ikDLP_OlDkGjGGQV5FmVCgEaK_kHepW6Bqn_-ZrjgAXwhowsjYfhlRFZw4PdjhX/s1600/dashb-new-displayer-button.png" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><i style="font-size: 12.8000001907349px;">New displayer button</i></td></tr>
</tbody></table>
The displayer editor popup appears as:<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh5_4L6p5yrttkvT0xK5gAepgTx5naIeCorbSymvgMw33nS5JgxoQXefLgvlY83Oy9tcTQrDXd1__XyM_c1I0nyJjeFyR_u__TrzhiVWv1zNj7lolF9o5bCyBKoOJX7vls_NJAXYYtN2iDT/s1600/dashb-displayer-editor.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="196" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh5_4L6p5yrttkvT0xK5gAepgTx5naIeCorbSymvgMw33nS5JgxoQXefLgvlY83Oy9tcTQrDXd1__XyM_c1I0nyJjeFyR_u__TrzhiVWv1zNj7lolF9o5bCyBKoOJX7vls_NJAXYYtN2iDT/s400/dashb-displayer-editor.png" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><i style="font-size: 12.8000001907349px;">Displayer editor popup</i></td></tr>
</tbody></table>
<br />
This screen has three tabs, in order to configure the displayer type, the source data and other display related properties.<br />
<br />
<b>Displayer 1 - Memory usage metric displayer</b><br />
<br />
Let's create our first displayer - a memory usage metric displayer using the following configuration:<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgkRBsBumbhAo6OWVR19TFtPpfBR84set7RUaGLw9nQ4iDafaZz-FLKUZ1N8tVeUfUw2npb6G0fubD9g313GvOrkLnnsqy-DyKX1IAkpv2L7mVVRj5dQBK5jtM0tdWRqzW98OSRBwtR3K8l/s1600/memory_metric.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgkRBsBumbhAo6OWVR19TFtPpfBR84set7RUaGLw9nQ4iDafaZz-FLKUZ1N8tVeUfUw2npb6G0fubD9g313GvOrkLnnsqy-DyKX1IAkpv2L7mVVRj5dQBK5jtM0tdWRqzW98OSRBwtR3K8l/s1600/memory_metric.png" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><i>Memory usage metric displayer configuration</i></td></tr>
</tbody></table>
<br />
<br />
<ul>
<li>On tab <i>type</i>, select type <i>Metric<br /> </i></li>
<li>On tab <i>data</i>, specify the just new created "All system metrics" data set and add the filters (see the above diagram). The filter configuration should look like this: </li>
</ul>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgK0lAvW86zFnA793MG2Ch0D-XE92V4NbiADj1RrIT6m7_WdAuVGmOZLgKaRTbNLBRFwNP5oVNnAiiDUh7zTkkJwqQdIpt8OBRN9J873lw3Rj0UTcw7nh3SpkJgs-ZdU4Oasi2clh-Hfhob/s1600/filters2.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgK0lAvW86zFnA793MG2Ch0D-XE92V4NbiADj1RrIT6m7_WdAuVGmOZLgKaRTbNLBRFwNP5oVNnAiiDUh7zTkkJwqQdIpt8OBRN9J873lw3Rj0UTcw7nh3SpkJgs-ZdU4Oasi2clh-Hfhob/s400/filters2.png" width="253" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><i>Filter configuration</i></td></tr>
</tbody></table>
<br />
<ul>
<li>On same tab <i>data</i>, set the metric to display using an average function as:</li>
</ul>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEib9lATB0I9aX7StXa2TX2jyV5175D0vA1vIN9l1F8BgpfezowL5B4KBg_KQQ3KSyjuyGNrvrtJrCtrJbyTqwyn-XQ38foMAjbkEf-iF9XnpYRg0B7TZYBsp3fQdY1JuCS5EdWQfP8ZnaeM/s1600/columns.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEib9lATB0I9aX7StXa2TX2jyV5175D0vA1vIN9l1F8BgpfezowL5B4KBg_KQQ3KSyjuyGNrvrtJrCtrJbyTqwyn-XQ38foMAjbkEf-iF9XnpYRg0B7TZYBsp3fQdY1JuCS5EdWQfP8ZnaeM/s1600/columns.png" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><i>Data set column to display using the avg function</i></td></tr>
</tbody></table>
<br />
<div>
<ul>
<li>Move to <i>display </i>tab and set a title for the chart:</li>
</ul>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjL0PUBYDp-k-LGdMSp9vKIpOyIWRptgGAdotN0W7dTWyo2BiRBT-ObJq_TS84Coa90KPQWMzmCaKERh2IpGJ368ZiK14nIouOdQBM5pKBznM3lAsGNO_KUAzfR1XYO6pjQrRRNKRQA-sXG/s1600/title2.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjL0PUBYDp-k-LGdMSp9vKIpOyIWRptgGAdotN0W7dTWyo2BiRBT-ObJq_TS84Coa90KPQWMzmCaKERh2IpGJ368ZiK14nIouOdQBM5pKBznM3lAsGNO_KUAzfR1XYO6pjQrRRNKRQA-sXG/s1600/title2.png" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><i style="font-size: 12.8000001907349px;">Displayer title</i></td></tr>
</tbody></table>
<div>
<br /></div>
</div>
<br />
<br />
<ul>
<li>In order to display the value in Gb, go to the Columns section and use the following values for the column attributes:</li>
</ul>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhf2On4Bjhrw0x9N3il30kuiIOCIwoTGbksKJrinbYy5hLaFOJiitl7neZ8g7j-DvcLrSg3uUy97ScKdLPLJaqfhoHxenxT3c5LCYdTH-I8qh771vD_v7HP9FThmNYWPrCtKe6CfzdqABUg/s1600/pattern.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhf2On4Bjhrw0x9N3il30kuiIOCIwoTGbksKJrinbYy5hLaFOJiitl7neZ8g7j-DvcLrSg3uUy97ScKdLPLJaqfhoHxenxT3c5LCYdTH-I8qh771vD_v7HP9FThmNYWPrCtKe6CfzdqABUg/s1600/pattern.png" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><i>Column configuration</i></td></tr>
</tbody></table>
<br />
<blockquote class="tr_bq">
<span style="font-size: x-small;">NOTE: For the expression attribute use <i>value / 10<sup>9</sup></i> , and </span><span style="font-size: x-small;">for the pattern attribute </span><span style="font-size: x-small;">use </span><i style="font-size: small;">#.##</i><span style="font-size: x-small;"> in order to show the input values in Gbytes</span></blockquote>
<ul>
<li>On same<i> display</i> tab, open the refresh section and enable it using a 1second interval:</li>
</ul>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhhfiqwo3qtKdk8nLejWDwFcd2r-FPW0r9AXUN1Bdo7tvAza2-NAq9T8a3O8o20n2nvBPNCL-UAthpXasb8Ef-u_xuo0yVxEpCAwZFPB1qL3_B4aSVpJWgBwA3frYnl_chilu3JCvbY2rt0/s1600/refresh.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhhfiqwo3qtKdk8nLejWDwFcd2r-FPW0r9AXUN1Bdo7tvAza2-NAq9T8a3O8o20n2nvBPNCL-UAthpXasb8Ef-u_xuo0yVxEpCAwZFPB1qL3_B4aSVpJWgBwA3frYnl_chilu3JCvbY2rt0/s400/refresh.png" width="268" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><i>Refresh data every second</i></td></tr>
</tbody></table>
<br />
<div>
<br /></div>
<br />
Once the configuration is finished just click the <i>Ok</i> button and the new displayer will be dropped into the dashboard layout:<br />
<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEipZPCKcYS6fKMqYaq2dwDRY9KwYcsHn6_jvzDyET-yQSXSYZwl_VqpkPNKYn-YAfzx_KFICHB5eOhhMZdx8tg2gPAQvKeYB0QGaJ7WcX0rycxn-qWW1znVGWN7ihWgNCydDk4YZvYW7YIH/s1600/mem_metric.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEipZPCKcYS6fKMqYaq2dwDRY9KwYcsHn6_jvzDyET-yQSXSYZwl_VqpkPNKYn-YAfzx_KFICHB5eOhhMZdx8tg2gPAQvKeYB0QGaJ7WcX0rycxn-qWW1znVGWN7ihWgNCydDk4YZvYW7YIH/s1600/mem_metric.png" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><i>Memory used metric displayer</i></td></tr>
</tbody></table>
<br />
As you can see, you can create as many displayers as needed and drag&drop them into different dashboard areas. Just click the mouse-left button on the displayer panels's header and drag&drop it into the desired layout's region, when the compass control appears:<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEioC1h_tVC7-uTBnOpF0pYwEm5UrmHQGE1Tuof2dJk4pKnXLZ0-ztdok3qYs6BqTI39-x7nd-MA8DvHfk6ONBL7LX1QnHCF2kpax5LMnGOkCUVCyVFIHUviEY7GcSVtI-CDNwxQ1IZG9d0l/s1600/compass.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="382" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEioC1h_tVC7-uTBnOpF0pYwEm5UrmHQGE1Tuof2dJk4pKnXLZ0-ztdok3qYs6BqTI39-x7nd-MA8DvHfk6ONBL7LX1QnHCF2kpax5LMnGOkCUVCyVFIHUviEY7GcSVtI-CDNwxQ1IZG9d0l/s640/compass.png" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><i>Move your displayers inside the dashboard</i></td></tr>
</tbody></table>
<br />
For the next dashboard's displayers, the creation workflow is similar, but just applying the different values on filters and columns. Here is the quick summary of their configuration:<br />
<br />
<b>Displayer 2 - CPU usage metric displayer</b><br />
<br />
1.- Apply filters and columns values as:<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi9a7i_8_gDLmltqj7BpFenH0LLbMG4FXdoofSwTOvZR0yK3_mJYekwGISPS61LJg3K7NHIdP4aomFPwlNqvzzKKmP_1smEEwCTAWbrqqKvelS6YrF7FhB_XAqDOvPNavOVS0rxOf2T-FjV/s1600/cpu_metric.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi9a7i_8_gDLmltqj7BpFenH0LLbMG4FXdoofSwTOvZR0yK3_mJYekwGISPS61LJg3K7NHIdP4aomFPwlNqvzzKKmP_1smEEwCTAWbrqqKvelS6YrF7FhB_XAqDOvPNavOVS0rxOf2T-FjV/s1600/cpu_metric.png" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><i style="font-size: 12.8000001907349px;">CPU usage metric displayer configuration</i></td></tr>
</tbody></table>
2.- Set a title for the chart and enable the refresh feature using an interval of 1second<br />
<br />
3.- There is no need to change column patterns as the values already are in percentage format<br />
<div>
</div>
<br />
<b>Displayer 3 - Free disk space metric displayer</b><br />
<br />
1.- Apply filters and columns values as:<br />
<div>
<br /></div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgNE4HhPDNaIBaKXv_8urT_fq2mjXYXUA64_C9K1BE4EgVxE1MuTP2gbj7tNadxKNpgvDiK1L8d-TjI2OJ9NvqYqmtAUhnjzbTcp195by-JuzPg0A2PCrjWUSUcb_o7ZVNi93GXBirea4xg/s1600/disk_metric.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgNE4HhPDNaIBaKXv_8urT_fq2mjXYXUA64_C9K1BE4EgVxE1MuTP2gbj7tNadxKNpgvDiK1L8d-TjI2OJ9NvqYqmtAUhnjzbTcp195by-JuzPg0A2PCrjWUSUcb_o7ZVNi93GXBirea4xg/s1600/disk_metric.png" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><i style="font-size: 12.8000001907349px;">Free disk space metric displayer configuration</i></td></tr>
</tbody></table>
<div>
2.- Set a title for the chart and enable the refresh feature using an interval of 1second<br />
<br />
3.- Apply same column configuration (expression & pattern) as the displayer 1.</div>
<br />
<b>Displayer 4 - </b><b>Memory usage displayer using an area chart</b><br />
<br />
1.- Apply filters and columns values as:<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhEFcx0x1j-83P_ShIk9EpJxghwjeW5OtM26Kw6eyLW8-g-ZRq0nvIOWO5jibjRTiXDMGR-KKpoWt85ous9F3kNNXkRsvyKPBqYCeJ8BMYKlbd2Q9coM817pAlYto2FJ2KZcvy-1o2qBnAb/s1600/memory_area.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhEFcx0x1j-83P_ShIk9EpJxghwjeW5OtM26Kw6eyLW8-g-ZRq0nvIOWO5jibjRTiXDMGR-KKpoWt85ous9F3kNNXkRsvyKPBqYCeJ8BMYKlbd2Q9coM817pAlYto2FJ2KZcvy-1o2qBnAb/s1600/memory_area.png" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><i style="font-size: 12.8000001907349px;">Memory usage area chart configuration</i></td></tr>
</tbody></table>
2.- Set a title for the chart and enable the refresh feature using an interval of 1second<br />
<br />
3.- Apply same column configuration (expression & pattern) as the displayer 1.<br />
<br />
<b>Displayer 5 - </b><b>Servers pie chart</b><br />
<br />
1.- Apply filters and columns values as:<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhbJuwwLBtj2Ketxq5QxL4DsOcU44XYERcvvcbKNhq55xrowG7vPREV50aAexB6UBRTKhdFSF1mQdOmRsygzNmcBQvpwMKbHSLmWtonVer5saqNhd-h0OXrDejl7KWSoXkKvXI6lVHLxOav/s1600/servers_pie.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhbJuwwLBtj2Ketxq5QxL4DsOcU44XYERcvvcbKNhq55xrowG7vPREV50aAexB6UBRTKhdFSF1mQdOmRsygzNmcBQvpwMKbHSLmWtonVer5saqNhd-h0OXrDejl7KWSoXkKvXI6lVHLxOav/s1600/servers_pie.png" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><i style="font-size: 12.8000001907349px;">Server pie chart configuration</i></td></tr>
</tbody></table>
2.- Set a title for the chart and enable the refresh feature using an interval of 1second<br />
<br />
<h2>
Video</h2>
<div>
</div>
<div>
In order to show the system metrics dashboard in action, here there is quick video that shows how to create some displayers, apply the configurations and move them inside the dashboard areas for generating the final layout.<br />
<br />
The environment used for this tutorial was:<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEju7uLtAqir4w6VzfUJWTcUyqc3ZlYeA00lpheWRNIMGQdN6hh8GuHSOCsdP_tiKDPryYOWMW0GpZwBc8eo69a7nlq32sCZ2CPwriTvlF6mUPiy_Y6048NhQHrV4frK_I9U04gGmaaB2cXE/s1600/Video+environment.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="347" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEju7uLtAqir4w6VzfUJWTcUyqc3ZlYeA00lpheWRNIMGQdN6hh8GuHSOCsdP_tiKDPryYOWMW0GpZwBc8eo69a7nlq32sCZ2CPwriTvlF6mUPiy_Y6048NhQHrV4frK_I9U04gGmaaB2cXE/s640/Video+environment.png" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><i style="font-size: 12.8000001907349px;">Environemnt used for the tutorial</i></td></tr>
</tbody></table>
<br />
Also consider that the metrics data is coming from two different servers (under our control), so we can start, stop and stress them producing the real-time data being monitored by the dashboard.<br />
<br />
To avoid long videos it starts with the data set definition, the dashboard and some displayers already created and configured.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<iframe width="320" height="266" class="YOUTUBE-iframe-video" data-thumbnail-src="https://i.ytimg.com/vi/TH-iaVMV1NE/0.jpg" src="https://www.youtube.com/embed/TH-iaVMV1NE?feature=player_embedded" frameborder="0" allowfullscreen></iframe></div>
<br />
<br /></div>
<br />
<br />
<br />
<br />
<br />Unknownnoreply@blogger.com18tag:blogger.com,1999:blog-4358594258656726438.post-43756825584092094882015-06-03T18:23:00.002+02:002015-06-04T00:18:47.091+02:00UF Dashbuilder - Data set authoring<div class="separator" style="clear: both; text-align: center;">
</div>
<h2>
</h2>
<div>
This article introduces the new Dashbuilder's Data Set authoring user interface which allows the user to list, create, update and remove data sets from a web browser. Please note that it's an end-user oriented guide, so do not expect to deep into technical details.</div>
<div>
<br />
A Data set is one of the main components in Dashbuilder's architecture; all of the different visualizations use Data sets to get the data they need. So if you are not used to the Data set API & architecture, it's high recommended reading this <a href="http://dashbuilder.blogspot.com.es/2015/02/uf-dashbuilder-and-new-data-set.html">previous article</a>. <br />
<br /></div>
<div>
</div>
<div>
Consider<b> </b>the <b>Data set authoring</b> as the name given to the web interface that provides a set of screens to manage your Data sets in a user friendly way. In the following <a href="https://www.youtube.com/watch?v=g09AbDjcfx4" target="_blank">video</a> you can get a quick preview of how the new interface looks like (do not forget to select HD) and how easy is to register a new data set.</div>
<div>
<br /></div>
<div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi0ajSS5C_vP1ZS6ac3VxYI6F-z78ojPP8WkGnrJ4MXzvbYPWSMYdxQ1Agr8mpR9Jdkp02I2ddC496aMapoYdVAfHKRBCdWsxObl2EyHOEj_Ju9hl4rABafYeFgKRPDPXR0ZbViYtAuBMq1/s1600/authoring-perspective.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="193" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi0ajSS5C_vP1ZS6ac3VxYI6F-z78ojPP8WkGnrJ4MXzvbYPWSMYdxQ1Agr8mpR9Jdkp02I2ddC496aMapoYdVAfHKRBCdWsxObl2EyHOEj_Ju9hl4rABafYeFgKRPDPXR0ZbViYtAuBMq1/s640/authoring-perspective.png" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Data Set authoring perspective</td></tr>
</tbody></table>
<br /></div>
<div>
<u>Note</u>: given that point, the use of this authoring perspective gives the user a new and much more easy way for managing Data sets than the default <i>deployment scanner</i> (See section <i>Data set deployment</i> in <a href="http://dashbuilder.blogspot.com.es/2015/02/uf-dashbuilder-and-new-data-set.html" target="_blank">this article</a>).</div>
<br />
<h2>
Refreshing some concepts ...</h2>
<div>
To be able to create and edit data sets it's important to get used to the Data set API and some other concepts. This is a quick review (all details in this <a href="http://dashbuilder.blogspot.com.es/2015/02/uf-dashbuilder-and-new-data-set.html" target="_blank">previous article</a>).<br />
<br />
(If you are already familiar with the Data set API & concepts you can skip this section)</div>
<h3>
</h3>
<h3>
</h3>
<h3>
Data set & Data set definition</h3>
<div>
<br />
The most obvious should be assuming that data set authoring is about the management of data sets, so the underlying model should be a d<i>ata set</i>. Is it...? Almost true.. but strictly speaking it does not allow the management of <i>Data set</i> instances, it allows the management of<i> <b>Data set definitions</b></i>.</div>
<div>
<br /></div>
<div>
Remember that a <i><b>Data set definition</b></i> is just the representation of a <i>Data set</i> attributes and columns. It provides the information for being able to look up information from remote systems , collect and perform data operations, resulting in Data sets. If looking deeper in the architecture, the definition is a persistent entity that uses the JSON exchange format. Thus you can consider the Data set authoring as a web interface editor for JSON Data set definitions.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhEw0lE1Gaxtz7qaa_cKavOxaBus04YZbkHPdmlYquczKVuhNAcZ-O6xrXOXrQxm3pUHb-GUu8CWTXop99jmNFJZsuFK8vIUfmMy63DDZnbyFExIN6Awb9uJnuV0KwJfCIlJVLFbC2F-dso/s1600/datasetdef.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhEw0lE1Gaxtz7qaa_cKavOxaBus04YZbkHPdmlYquczKVuhNAcZ-O6xrXOXrQxm3pUHb-GUu8CWTXop99jmNFJZsuFK8vIUfmMy63DDZnbyFExIN6Awb9uJnuV0KwJfCIlJVLFbC2F-dso/s1600/datasetdef.png" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
<i>Data set definition</i> class members:</div>
</div>
<div>
<ul>
<li>A <b>name</b> and <b>unique identifier</b> (UUID)</li>
<li>A <b>type. </b>It defines the storage type that provides the remote data to be consumed. <br />Currently the editor supports <i>Bean</i>, <i>SQL</i>, <i>CSV</i> and <i>ElasticSearch</i> types. These types allow for looking up data from a Java class, a DBMS, a CSV file or an ElasticSearch storage system respectively.</li>
<li>Specific <b>attributes. </b>For example, if using an external DBMS the JDBC url and connection credentials are mandatory user input attributes.</li>
<li><b>Data columns. </b>Define which columns will be present in the Data Set when a look-up is performed. See next section <i>Data columns</i>.</li>
<li>Initial <b>data filter. </b>Minimize the look-up result size by providing a filter. </li>
<li><b>Cache</b> and <b>refresh</b> settings. Some other attributes related to client & backend cache sizes and the data refresh policy.</li>
</ul>
<ul>
</ul>
</div>
<div>
<h3>
</h3>
<h3>
</h3>
<h3>
Data columns</h3>
<div>
<i>Data columns</i> are the name used for the columns of the resulting data set when a look up is performed.</div>
<div>
<br /></div>
<div>
A data column have a <b>unique identifier</b> for the column in the data set and a <b>data type</b>. Dashbuilder supports 4 column types:</div>
<div>
<ul>
<li><b>Number</b> - The row values for the column are considered numbers, so you can use the column for further column functions use (sum, min, max, average, etc).</li>
<li><b>Date</b> - The row values for the column are considered dates, so you can use the column for further column date related functions (timeframe, intervals, etc)</li>
<li><b>Text</b> - The row values for the column are considered plain text. The column cannot be used in any numeric functions neither cannot be grouped (this column will be never indexed in the internal registry).</li>
<li><b>Label</b> - The row values for the column are considered text literals. The column can be grouped as the values are considered concrete. </li>
</ul>
</div>
No matter which remote system you want to look up, the resulting data set will return a set of columns of one of the four default types above. So there exists, by default, a mapping between remote system column types and the Dashbuilder's types. The user is able to modify the type for some columns, depending on the data provider and the column type of the remote system.<br />
<br />
The data set authoring perspective allows the data columns manipulation as you will see in the next sections.<br />
<h3>
</h3>
<h3>
</h3>
<h3>
<br /></h3>
<h3>
Initial data filter</h3>
</div>
<div>
It's important to remember that a Data set definition can define a filter. It's named <i>initial data filter</i> as it is present in the definition of the data set itself, so all further data displayers and other components that use this definition will be using the subset of data that satisfies the filter conditions.<br />
<br />
The goal of the initial filter is to allow for removing from the data those rows that the user does not consider necessary. The filter works on any data provider type.<br />
<blockquote class="tr_bq">
Note: For SQL data provider type, you can use both initial filter or just add custom criteria in the SQL sentence. The first is more appropriated for non technical users since they might not have do the required SQL language skills.</blockquote>
</div>
<div>
So it's important to note that you can specify a data filter at two levels:</div>
<div>
<ul>
<li>In a Data set definition</li>
<li>In a Data displayer definition</li>
</ul>
</div>
<div>
Having in mind that a Data displayer consumes data from a Data set, there are some implications when deciding at which level specify the data filter. For instance, you may have a data set getting the expense reports only from the London office, and then having several displayers feeding from such data set. Another option is to define a data set with no initial filter and then let the individual displayers to specify a filter. It's up to the user to decide on the best approach. Depending on the case might be better to define the filter at a data set level for reusing across all the displayers. The decission may also have impact on the performance, since a filtered cached data set will have far better performance than a lot of individual non-cached data set lookup requests per displayer (cache settings are described at the end of the article). </div>
<div>
<br /></div>
<div>
<h2>
The authoring perspective</h2>
</div>
<div>
Once familiarized with the API and some other basic concepts, let's see in detail the authoring perspective, its components and the main use cases of the tooling.<br />
<br />
The<b> Data set authoring</b> is the name given to the web interface that provides a set of screens to manage your Data sets in a user friendly way.<br />
<br /></div>
<div>
You can navigate to the perspective at <i>Main menu -> Authoring -> Data Set authoring</i>:<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgbGk3GKXSLdsf7EXE5z73p5cgqluAC1W9HCn1mxm0I5NOFWBDxnILVGJ8rd__Liqsfbh6K_FSP3LQpQVdFC64WRMSFDaoLFL6rrxNqSHxx88r31M-e2Rx75DFG7AjG3rtCfLH1lP4lTs-E/s1600/authoring-menu-item.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="67" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgbGk3GKXSLdsf7EXE5z73p5cgqluAC1W9HCn1mxm0I5NOFWBDxnILVGJ8rd__Liqsfbh6K_FSP3LQpQVdFC64WRMSFDaoLFL6rrxNqSHxx88r31M-e2Rx75DFG7AjG3rtCfLH1lP4lTs-E/s400/authoring-menu-item.png" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Data Set authoring menu item</td></tr>
</tbody></table>
The following screenshot shows the perspective screen:<br />
<i><br /></i>
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgsLsaXdyLfSVHV_ExVErGBiqLAmd3c45qFg6_mXoC2azpGCj9I3L-8T3MB565_ep0tM9Y0AipUx747AWxIrg2QX36anLcZWPP0rWp4psAGIHdubnWfZQGe6apaDcC3v5wflpEYMjJdtZtR/s1600/authoring-perspective-sections.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="193" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgsLsaXdyLfSVHV_ExVErGBiqLAmd3c45qFg6_mXoC2azpGCj9I3L-8T3MB565_ep0tM9Y0AipUx747AWxIrg2QX36anLcZWPP0rWp4psAGIHdubnWfZQGe6apaDcC3v5wflpEYMjJdtZtR/s640/authoring-perspective-sections.png" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Data Set authoring perspective</td></tr>
</tbody></table>
This view defines two panels/sections: the <i>Data set explorer</i> and the <i>Data set editor</i><br />
<ul>
<li><b>Data set explorer</b><br />It allows the user to explore and remove current system data sets. See next section <i>Data set explorer</i>.</li>
</ul>
<ul>
<li><b>Data set editor</b><br />It allows to create, read or update a data Set. See next section <i>Data set editor</i>. </li>
</ul>
<br />
Note: For more information about <a href="http://www.uberfireframework.org/" target="_blank">UberFire</a> perspectives and how to use them, please take a look at the <a href="http://www.uberfireframework.org/tutorial.html" target="_blank">official documentation</a>.<br />
<br />
<h3>
</h3>
<h2>
Data set explorer</h2>
</div>
<div>
The Data Set explorer is a client side component with the main goal listing all public data sets present in the system and let the user perform authoring actions.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEguAMxVElN0pNo3BrvRggMTh0j5jS2yaaH__7TkKnwOusdEfqjRg1nK32MkKFAFr0mEWSqtEsLCIKjQ9rzy21gmi0c3L8MmpuklCZwfwAdJjj96_-ZrSoPl-yubcFjKmwJJZWm0bUGCms7l/s1600/explorer.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEguAMxVElN0pNo3BrvRggMTh0j5jS2yaaH__7TkKnwOusdEfqjRg1nK32MkKFAFr0mEWSqtEsLCIKjQ9rzy21gmi0c3L8MmpuklCZwfwAdJjj96_-ZrSoPl-yubcFjKmwJJZWm0bUGCms7l/s400/explorer.png" width="297" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Data set explorer</td></tr>
</tbody></table>
It provides:<br />
<ul>
<li><span style="color: red;">(1)</span> A button for creating a new Data set.</li>
<li><span style="color: red;">(2)</span> The list of current available public Data sets.</li>
<li><span style="color: red;">(3)</span> An icon that represents the Data set's provider type (Bean, SQL, CSV, etc)</li>
<li><span style="color: red;">(4)</span> Details of current cache and refresh policy status.</li>
<li><span style="color: red;">(5)</span> Details of current size on backend (unit as rows) and current size on client side (unit in bytes).</li>
<li><span style="color: red;">(6)</span> The button for creating, reading or update a Data set. Its behavior is to open the Data set editor for interacting with the instance. </li>
<li><span style="color: red;">(7)</span> The button for removing a Data set.</li>
</ul>
<br />
<ul>
</ul>
</div>
<h3>
</h3>
<h2>
Data set editor</h2>
<div>
The <b>Data set editor</b> is a client side component that allows the user to create, read or update a data set.</div>
<div>
<br /></div>
<div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEibt5Og5OaXJAiY0lGHdUQChnST-fScHIWoS6kc_ZD3VXCfJGTQv-W8EU8hXve2EzUbNVvpnbxEoxf7gn08JV-K5NCkYbXEyEmNDkkE-ESebZsnPg_qNESvIsFSSawyT7xk2LdyKBQcOaun/s1600/dset-editor-home.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="192" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEibt5Og5OaXJAiY0lGHdUQChnST-fScHIWoS6kc_ZD3VXCfJGTQv-W8EU8hXve2EzUbNVvpnbxEoxf7gn08JV-K5NCkYbXEyEmNDkkE-ESebZsnPg_qNESvIsFSSawyT7xk2LdyKBQcOaun/s640/dset-editor-home.png" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Data Set editor home screen</td></tr>
</tbody></table>
The user interacts with the editor by:<br />
<ul>
<li>Clicking on <i>Edit</i> button in Data Set explorer</li>
<li>Clicking on <i>New Data Set</i> button in Data Set explorer</li>
<li>Clicking on <i>New data set</i> link in Data Set editor's home screen</li>
</ul>
</div>
<h3>
</h3>
<h3>
<br /></h3>
<h3>
Basic creation & edition workflow</h3>
The interaction with the editor for both create and edit goals is given by a given workflow with three steps:<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEifUOEG-UecqNvN9p1W5E_1yGlobHnsqnlbrdUNE8Wc3luw9zh4zOAWnN5h6c48po5-RlJmuJy7Q-v-cIVUielnDejtIsavPHHzmpX1gE4jbApv57jHlJGvJ1VYd1RCyyp3CXGlEzuHS0xl/s1600/workflow.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="116" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEifUOEG-UecqNvN9p1W5E_1yGlobHnsqnlbrdUNE8Wc3luw9zh4zOAWnN5h6c48po5-RlJmuJy7Q-v-cIVUielnDejtIsavPHHzmpX1gE4jbApv57jHlJGvJ1VYd1RCyyp3CXGlEzuHS0xl/s640/workflow.png" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Data Set creation & edition workflow</td></tr>
</tbody></table>
<div class="separator" style="clear: both; text-align: center;">
</div>
<ol>
<li>Data provider type selection<br /><br />Specify the kind of remote storage system (BEAN, SQL, CSV, ElasticSearch)<br /> </li>
<li>Data configuration - Basic and provider type's specific attributes edition<br /><br />Specify the attributes for being able to perform the look up to the remote system. These attributes vary depending on the Data provider type selected on previous step.<br /> </li>
<li>Advanced configuration - Table preview & Edition of data set's columns, initial filter, caché and refresh settings<br /><br />Configure the structure, data and other settings for the resulting data set.</li>
</ol>
<br />
<h3>
<u>Workflow step 1 - Type selection</u></h3>
Allows the user 's specify the type of data provider for the data set to create.<br />
<br />
The screen lists all the current available data provider types and helper popovers with descriptions. Each data provider is represented with a descriptive image:<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi10oCHSteR9_zNN4C1AoEMOA5J_fl49GVyaSvKhzgpeFoSeKagW-v3pSJQ8kB-StBoLf2pAaaLandO_bOsJnpQZbiG-3nVQWis1t4KU9Ud2dcySd-kJnO5CeNGmDeH0TdqyEEbd1v5-PF_/s1600/provider_type_selection_screen.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="169" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi10oCHSteR9_zNN4C1AoEMOA5J_fl49GVyaSvKhzgpeFoSeKagW-v3pSJQ8kB-StBoLf2pAaaLandO_bOsJnpQZbiG-3nVQWis1t4KU9Ud2dcySd-kJnO5CeNGmDeH0TdqyEEbd1v5-PF_/s640/provider_type_selection_screen.png" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Data provider type selection screen</td></tr>
</tbody></table>
This screen is only present when creating a Data set. It's not allowed to modify the Data set's provider type for an already existing data set.<br />
<br />
Four data provider types are currently supported:<br />
<ul>
<li>Bean (Java class)</li>
<li>SQL</li>
<li>CSV</li>
<li>Elastic Search</li>
</ul>
Once a type is selected, click on <i>Next</i> button to continue with next creation workflow step.<br />
<br />
<h3>
<u>Workflow step</u><u> 2 - Provider specific attributes</u></h3>
Once specified a kind of storage to look up in previous step, the next one is the configuration of the specific attributes to use it.<br />
<br />
The following picture shows the configuration screen for an <i>SQL</i> data provider type:<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg5JJN0NBJeFG5wofSrR4q265gbtvHLDenCv771_Hbceds_gMWBVv4HQwea9z9EcsTmBFCtvo9VIAMHXoPzZ3Ssv74MBpObkqg61j5jZl83ZNgFLpa_mqeecAQBgys6_mKKFigJh2wM6t5w/s1600/new_sql_screen.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="382" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg5JJN0NBJeFG5wofSrR4q265gbtvHLDenCv771_Hbceds_gMWBVv4HQwea9z9EcsTmBFCtvo9VIAMHXoPzZ3Ssv74MBpObkqg61j5jZl83ZNgFLpa_mqeecAQBgys6_mKKFigJh2wM6t5w/s640/new_sql_screen.png" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">New SQL Data set creation screen</td></tr>
</tbody></table>
Once data set name and connection attribute inputs are filled, for this <i>SQL</i> specific case, click on <i>Test </i>button to perform a initial connection to the source SQL storage. This process will fetch a small set of data and continue to next workflow step.<br />
<br />
Similar use for other data provider types:<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj4eZIb-fu4DUWRpYiouldETzNzatlsJctMqkmZN3GFbvLuUwn1twb3P6mHto9irA9GpNsHmU92c4oR5DNifF2MIfIJsNqMPMStMtx8g7PmbxNEKVx9vxn5qhu2iy43NBEm_uD-tefjeydz/s1600/bean_specific_screen.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="140" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj4eZIb-fu4DUWRpYiouldETzNzatlsJctMqkmZN3GFbvLuUwn1twb3P6mHto9irA9GpNsHmU92c4oR5DNifF2MIfIJsNqMPMStMtx8g7PmbxNEKVx9vxn5qhu2iy43NBEm_uD-tefjeydz/s400/bean_specific_screen.png" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">BEAN Data set type</td></tr>
</tbody></table>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiOPctJkgmEPW4S-XcBuBX1AIrXk5fzM0-8F2_g6dt8fI8Sqfr9cuaq3zMmCckeoCcAeaK8M50zYfmfwIf-6KVvHa8NYnM8G02xl4pZFzFo2WQL1iXNUVEdQNQjCsyLsAZuQ8aF2pomfbmh/s1600/csv_specific_screen.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="171" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiOPctJkgmEPW4S-XcBuBX1AIrXk5fzM0-8F2_g6dt8fI8Sqfr9cuaq3zMmCckeoCcAeaK8M50zYfmfwIf-6KVvHa8NYnM8G02xl4pZFzFo2WQL1iXNUVEdQNQjCsyLsAZuQ8aF2pomfbmh/s320/csv_specific_screen.png" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">CSV Data set<span style="font-size: 12.8000001907349px;"> type</span></td></tr>
</tbody></table>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhFOYcsytemY7wEC3VbLQeJW-YL_Qa-4sPz69InxDfNOtqWOCYXnAaEidpD94RDm4qz-xZfAv17nBdQ1UlDxRlm_gy4Ev-FNlP6roPJEWR9cgqzj08-b9nHmvx8XKM9H7uQPltZiUkR8SKa/s1600/el_specific_screen.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="119" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhFOYcsytemY7wEC3VbLQeJW-YL_Qa-4sPz69InxDfNOtqWOCYXnAaEidpD94RDm4qz-xZfAv17nBdQ1UlDxRlm_gy4Ev-FNlP6roPJEWR9cgqzj08-b9nHmvx8XKM9H7uQPltZiUkR8SKa/s320/el_specific_screen.png" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Elastic Search Data set<span style="font-size: 12.8000001907349px;"> type</span></td></tr>
</tbody></table>
Notes:<br />
<ul>
<li>The <i>UUID</i> attribute is a read only field, for further use in remote API or specific operations, as it's generated by the system, but you cannot edit it.</li>
<li>You can go back to the <i>configuration </i>tab at any time while creating or editing a data set, but if you modify any value on this tab inputs, you have to click on <i>Test </i>button to apply your new changes and perform a new look up. Doing that, <u>you will lose any columns or filter configuration</u>, as the look up result can have different data and/or structure. </li>
</ul>
<br />
<h3>
<u>Workflow step</u><u> 3 - Data set preview and advanced settings</u></h3>
At this point, the system is able to perform a look up to the remote system and return a data set. In this workflow's step you can check your result data and customize the structure and the rows for your own interest.<br />
<br />
This step is presented by using the screens of the <i>Preview</i> and <i>Advanced</i> tabs:<br />
<br />
<b>Preview tab</b><br />
<b><br /></b>
As you can see there are three main sections in this screen:<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgJnwwL7whoyufWCwxbGdFVzdjp3ItRW_bqeXZ5dnc7dkjEGTJC77pHkPaodo951M6eXuc_PjUpyR0Y0c0QBDqG-m-LwXEWbVgE2VL8s0VM-CZOZim1ny9KEiudYlPjPNCyGQes1DpSwTAb/s1600/preview_tab.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="294" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgJnwwL7whoyufWCwxbGdFVzdjp3ItRW_bqeXZ5dnc7dkjEGTJC77pHkPaodo951M6eXuc_PjUpyR0Y0c0QBDqG-m-LwXEWbVgE2VL8s0VM-CZOZim1ny9KEiudYlPjPNCyGQes1DpSwTAb/s640/preview_tab.png" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Preview tab</td></tr>
</tbody></table>
This tab contains three sections:<br />
<br />
<i><u>Data set preview</u></i><br />
<br />
A data table is located in the central area of the editor screen. This table displays the data that comes back from the remote system look up process.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh9g4DtFtHObGT8hK8Ak3TvyMKHT1eyeaUOkZDtlORdJ-12pHa3oUW7Z4J_MzY6c_YeuK4uOHIeKdFpqKTD8lsvrNCWKWX_QSGxgcvaN8fp0gWTnjYZ8V4wpaFvl4Crll8tTJy0u60CqbmZ/s1600/table_preview.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="230" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh9g4DtFtHObGT8hK8Ak3TvyMKHT1eyeaUOkZDtlORdJ-12pHa3oUW7Z4J_MzY6c_YeuK4uOHIeKdFpqKTD8lsvrNCWKWX_QSGxgcvaN8fp0gWTnjYZ8V4wpaFvl4Crll8tTJy0u60CqbmZ/s400/table_preview.png" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Data set preview</td></tr>
</tbody></table>
<br />
<br />
You can apply some operations on this table such as filtering and sorting.<br />
<br />
<i><u>Data set columns</u></i><br />
<br />
You can manage your data set columns in the <i>Columns tab </i>area:<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEixtRuwSbPiX3bYmnMdpyo54WkPgJtx7dmjJutx89-X3zqd7Yrzh5JM7hDLLUOXZbNK0d18ofNFsNNLqqabWlbjqkQ97cI2-DoVH7dDPtLnTyS91e6UYWs5VatgNje7vOBaODP5xL3f47Cp/s1600/columns_tab.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="236" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEixtRuwSbPiX3bYmnMdpyo54WkPgJtx7dmjJutx89-X3zqd7Yrzh5JM7hDLLUOXZbNK0d18ofNFsNNLqqabWlbjqkQ97cI2-DoVH7dDPtLnTyS91e6UYWs5VatgNje7vOBaODP5xL3f47Cp/s320/columns_tab.png" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Data set columns</td></tr>
</tbody></table>
<br />
Use the checkbox <span style="color: red;">(1)</span> to add or remove columns of the data set. Select only those columns you want to be visible and accessible to dashboard displayers.<br />
<br />
Use the drop down image selector <span style="color: red;">(2)</span> to change the column type. This have some implications on further column operations, as already explained on previous sections.<br />
<br />
Note: <i>BEAN</i> Data provider type does not support changing column types as it's up to the developer to decide which are the concrete types for each column.<br />
<div>
<br />
<i><u>Data set filter</u></i><br />
<br />
In the <i>Filter tab </i>area you can specify the Data set definition initial filter:<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZsQeCoAQ_E4JPoBnDZEk_LYvMw4_qovHo__1sTkHkcQ1X7BNnsm68RdvBDKomkDejb7gtkCjNEy54r8ZqzVOnORBKfPcXfFAR6Ui0QDm52mPx7bOgJvHPg3pukiSGuZ0P0MRNi1xMyPtt/s1600/filter_tab.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="156" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZsQeCoAQ_E4JPoBnDZEk_LYvMw4_qovHo__1sTkHkcQ1X7BNnsm68RdvBDKomkDejb7gtkCjNEy54r8ZqzVOnORBKfPcXfFAR6Ui0QDm52mPx7bOgJvHPg3pukiSGuZ0P0MRNi1xMyPtt/s320/filter_tab.png" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Data set filter</td></tr>
</tbody></table>
<br />
While adding or removing filter conditions and operations, the preview table on central area will be updated with the new subset of data.<br />
<br />
Note: The use of the filter interface is already detailed in this <a href="http://dashbuilder.blogspot.com.es/2015/02/uf-dashbuilder-and-new-data-set.html" target="_blank">previous article</a>.<br />
<br />
<ul>
</ul>
<b>Advanced tab</b><br />
<b><br /></b>
Last settings to configure for a Data set definition are present in the <i>Advanced </i>tab:<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiWMM2_fMgHuR0XzoIOnMEjYF2P6z3X9oyd5Q1dO3n-yiWCfpfGQziNv95uEKE_x6bifLJe-SK0CB_3XEe65TQKyrcMiwidUF6-2_HB-hHJVzjPyMdE0HXQ6EYoROCgb9Di9avsvt8bnY-G/s1600/tab_advanced.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="276" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiWMM2_fMgHuR0XzoIOnMEjYF2P6z3X9oyd5Q1dO3n-yiWCfpfGQziNv95uEKE_x6bifLJe-SK0CB_3XEe65TQKyrcMiwidUF6-2_HB-hHJVzjPyMdE0HXQ6EYoROCgb9Di9avsvt8bnY-G/s640/tab_advanced.png" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Advanced settings tab</td></tr>
</tbody></table>
In this screen you can specify caching and refresh settings. These settings are very important for making the most of the system capabilities thus improving the performance and having better application responsive levels.<br />
<br />
At <span style="color: red;">(1)</span> you can enable or disable the <i>client cache</i> for the Data set and specify the maximum size (Bytes).<br />
<br />
At <span style="color: red;">(2)</span> you can enable or disable the <i>backend cache</i> for the Data set and specify the maximum cache size (expressed in data set's rows).<br />
<br />
At <span style="color: red;">(3)</span> you can enable or disable automatic refresh for the Data set and the refresh period.<br />
<br />
At <span style="color: red;">(4)</span> you can enable or disable the <i>refresh on stale data </i>setting.<br />
<br />
Let's dig into more details about the use of these settings on the following paragraphs (it's recommended the previous reading of <a href="http://dashbuilder.blogspot.com.es/2015/02/uf-dashbuilder-and-new-data-set.html" target="_blank">this article</a> as it introduces the basics concepts behind Caching&Refresh).<br />
<br />
<h4>
Caching</h4>
Dashbuilder is built with caching mechanisms for holding data sets and performing data operations using <i>in-memory</i> strategies. The use of these features have lots of advantages, as reducing network traffic, remote system payload, processing times etc. In the other hand, the user is responsible for the right use of caching and their sizes to avoid hitting performance issues. <br />
<br />
Two levels of caching are provided:<br />
<br />
<ul>
<li>The client cache</li>
<li>The backend cache</li>
</ul>
The following diagram shows how caching is involved in any data set look up, group, filter and or sort operations:<br />
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj0HLWutI1AQwERjbyINQqKN0ccQKq8E8bQNNfvqTFhnbZKd8_3elUcZmc5FyJfuLQQmIwoDc5akpwoCpDyN7wauXIcUv2eHgy_hFBvOYZWlDT6iBvuhKqppDjgy4A_tHBfUYdr7jA3nipi/s1600/caches.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="340" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj0HLWutI1AQwERjbyINQqKN0ccQKq8E8bQNNfvqTFhnbZKd8_3elUcZmc5FyJfuLQQmIwoDc5akpwoCpDyN7wauXIcUv2eHgy_hFBvOYZWlDT6iBvuhKqppDjgy4A_tHBfUYdr7jA3nipi/s640/caches.png" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Cachés</td></tr>
</tbody></table>
Any data look up operation produces a resulting data set, so the use of the caching determines where that lookup operation is executed and where the resulting data set is located.<br />
<br />
<i><u>Client cache</u></i><br />
<i><br /></i>If ON then the data set coming from a look up operation is pushed into the web browser so that all the data displayers or other components that feed from this data set <b>do not need to perform requests to the backend, </b>everything is resolved at a client side:<br />
<br />
<ul>
<li>The data set is stored in the web browser's memory</li>
<li>The related displayers feed from the data set stored in the browser</li>
<li>Grouping, aggrtegations (sum, max, min, etc), filters and sort operations are processed within the web browser, by means of a <i>Javascript</i> data set operation engine.</li>
</ul>
<br />
If you know beforehand that your data set will remain small, you can enable the <i>client cache</i>. It will reduce the number of backend requests, not only the requests to Dashbuilder's backend, but also the requests to your backend storage system. On the other hand, if you consider that your data set will be quite big, disable the client cache so as to not hitting with browser issues such as slow performance or intermittent hangs.<br />
<br />
<i><u>Backend cache</u></i><br />
<br />
It's goal is to provide a caching mechanism for data sets on backend side.<br />
<br />
This feature allows to <b>reduce the number of requests to the external storage system</b>, by holding the data set in memory and performing group, filter and sort operations using the <i>in-memory</i> engine.<br />
<br />
It's useful for data sets that do not change quite often and their size can be considered acceptable to be held and processed in memory. It can be helpful if the remote system network connection bandwidth has high latency. On the other hand, if your data set is going to be updated frequently, it's better to disable the backend cache and perform the requests to the external system on each look up request, so the external system is responsible for executing group, filter and sort operations using the latest data.<br />
<br />
<i>Note</i>: <i>BEAN</i> and <i>CSV data provider </i>types relies on the backend cache by default, as in both cases the data set must be always loaded into memory in order to resolve any data lookup operation using the in-memory engine. This is the reason why the backend settings are not visible in the Advanced settings tab.<br />
<span style="font-size: x-small;"><br /></span>
<br />
<h4>
Refresh policy</h4>
Dasbuilder provides the <i>data set refresh </i>feature. Its goal is to perform <b>invalidation of any cached data</b> when certain conditions are meet.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgy7jti6o5q2IpK54vdjoFSsLIpNP714LoH8EStceMEn1NJ8xllTeEAYdZIG8_YDmVCCeGvSOQCGnrUzromnIV7Yy1xJuXlW0MJmCrc4SlHgs3Wb4tyur-YHlr9hRB-XQNYn3bjsWVC5hqw/s1600/refresh_policy.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="83" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgy7jti6o5q2IpK54vdjoFSsLIpNP714LoH8EStceMEn1NJ8xllTeEAYdZIG8_YDmVCCeGvSOQCGnrUzromnIV7Yy1xJuXlW0MJmCrc4SlHgs3Wb4tyur-YHlr9hRB-XQNYn3bjsWVC5hqw/s400/refresh_policy.png" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="font-size: 12.8000001907349px;">Refresh policy settings</td></tr>
</tbody></table>
<blockquote class="tr_bq">
<span style="font-size: x-small;">At <span style="color: red;">(1)</span> you can enable or disable the <i>data refresh</i> feature.<br />At <span style="color: red;">(2)</span> you can specify the <i>refresh interval</i>.<br />At <span style="color: red;">(3)</span> you can enable or disable refresh only when data is out of dated. </span></blockquote>
The data set refresh policy is tightly related with data set caching, detailed in previous section. This invalidation mechanism determines the cache life-cycle.<br />
<br />
Depending on the nature of the source data there exist three main refresh use cases:<br />
<ul>
<li>Source data changes predictable<br /><br />Imagine a database being updated every night. In that case, the suggested configuration is use a <i>refresh</i> <i>interval = 1Day <span style="color: red;">(2)</span> </i>and disable<i> refreshing on stale data </i><i><span style="color: red;">(3)</span></i>, so the system will always invalidate the cached data set every day. this is the right configuration when we know in advance that the data is going to change (predictable changes). </li>
</ul>
<ul>
<li>Source data changes unpredictable<br /><br />On the other hand, if we do not know whether the database is updated every day, the suggested configuration is to use a <i>refresh</i> <i>interval = 1Day <span style="color: red;">(2)</span> </i>and enable<i> refreshing on stale data </i><i><span style="color: red;">(3)</span></i>, so the system, before invalidating any data, will check if it has been updated. If so, the system will invalidate the current stale data set and will populate the cache with fresh data.</li>
</ul>
<ul>
<li>Real time scenarios<br /><br />On real time scenarios caching makes no sense as data is going to be updated constantly. In this kind of scenarios the data sent to the client has to be constantly updated, so rather than managing the refresh settings for the data set in the Data set Editor (remember this settings affect the caching, and caching is not enabled) you have to define when to update your dashboard displayers by modifying the refresh settings from the Displayer Editor configuration screen. For more information on Displayer Editor and real-time dashboards, please refer to <a href="http://dashbuilder.blogspot.com.es/2015/03/uf-dashbuilder-displayer-editor-api_3.html" target="_blank">Dashbuilder Displayer Editor & API</a> and <a href="http://dashbuilder.blogspot.com.es/2015/03/uf-dashbuilder-real-time-dashboards.html" target="_blank">Real time dashboards </a>articles.</li>
</ul>
</div>
Unknownnoreply@blogger.com4tag:blogger.com,1999:blog-4358594258656726438.post-30334713834586506802015-03-31T19:09:00.001+02:002015-04-05T22:56:31.624+02:00UF Dashbuilder - Export displayer data to CSV and Excel<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div style="text-align: center;">
<iframe allowfullscreen="" class="YOUTUBE-iframe-video" data-thumbnail-src="https://i.ytimg.com/vi/XaXPal30KyI/0.jpg" frameborder="0" height="266" src="http://www.youtube.com/embed/XaXPal30KyI?feature=player_embedded" width="320"></iframe></div>
<div class="separator" style="clear: both; text-align: center;">
Displayer data export demo (select HD)</div>
<br />
<br />
In short video demo above we demonstrate an interesting new feature that we've just added to dashbuilder, nl. the ability to export a displayer's data set, either to comma-separated-value format, or to excel format. While this is perhaps not a visually very impacting feature, it's without a doubt a very useful one.<br />
<br />
The first important thing worth mentioning is the fact that this export can be applied to <u>any type</u> of displayer. In the end a displayer is in fact nothing more than a visual representation of some sort of underlying tabular data, so this is actually quite straightforward.<br />
<br />
In the demo we can see a couple of displayers based on some example sales opportunities data. To the left we have a bar chart displayer representing some opportunities by their current pipeline status, and to the right a table displayer with more detailed information about the these sales opportunities. How to create and configure dashbuilder displayers was covered in a previous entry: <a href="http://dashbuilder.blogspot.com/2015/03/uf-dashbuilder-displayer-editor-api_3.html" target="_blank">UF Dashbuilder Displayer Editor & API</a>.<br />
<br />
In the first part of the demo you can see how the data export feature can be activated. To do that we have to go to the displayer's actions dropdown and select edit. In the displayer's edit popup window we then move to the display tab where its appearance properties are configured and here, if we open up the 'general' section, we can see 2 new checkboxes have been added for data export, either to csv and/or to excel format. Initially, these checkboxes are set to off, which means that the creator of a displayer has to explicitely enable data export for a specific displayer.<br />
<br />
In the demo, a different type of export is chosen for each displayer, and when we return to normal view mode and revisit the actions dropdown, we can see how the new export action has now become now available to us. It's really as simple as that.<br />
<br />
The next part of the demo shows how, and this is an important detail, the exported data concerns the currently visualized displayer window, i.e. if the displayer is subject to filtering, as is clearly seen in the demo, the <u>exported data will be filtered accordingly</u>.<br />
<br />
That's all, we hope you find this feature useful, please don't hesitate to get back to us with any feedback!<br />
<br />Unknownnoreply@blogger.com8tag:blogger.com,1999:blog-4358594258656726438.post-9103652745098491142015-03-27T12:36:00.001+01:002015-03-27T13:34:25.955+01:00UF Dashbuilder - Real time dashboards Dashboard solutions face different scenarios when it comes to data retrieval. While some dashboards do not require frequent updates as the data doesn't change very often or even rarely, other dashboards may require constant updates, because its data changes at a very fast pace. Therefore, we can classify our dashboards into two main groups:<br />
<div>
<br /></div>
<ul>
<li><b>Analitics</b>: usually focused on the analysis of information about the past (historical/statistics), or about information that is known in advance (forecasts). The main trait of these dashboards is that data does not change very often and the time frame is usually long. Some examples: A company's sales evolution and forecast, sport statistics in general, etc.</li>
</ul>
<div>
<br /></div>
<ul>
<li><b>Real time</b>: their main trait is that data changes at a very fast pace. Therefore, this requires to update the indicators & reflect the changes in the UI frequently. Usually, the data is bound to a very short time frame, such as the last 10 seconds. Real time dashboards are typically used to monitor critical resources or systems, for example: Health display sensors, IT resources, air traffic control, etc. </li>
</ul>
<br />
Here is a comparison table which summarizes the main features of both:<br />
<br />
<table border="1" style="width: 100%px;">
<tbody>
<tr>
<td> </td><td> Analytics </td><td> Real-time </td>
</tr>
<tr>
<td> Data changes very often </td><td> No</td><td> Yes </td>
</tr>
<tr>
<td> Time frame </td><td> Any</td><td> Short </td>
</tr>
<tr>
<td> Amount of information </td><td> Any</td><td> Little </td>
</tr>
<tr>
<td> Dashboard updates</td><td> Rarely</td><td> Frequent </td>
</tr>
</tbody></table>
<br />
<br />
Dashbuilder is a general purpose dashboard solution. One of its design goals is to support both approaches. The following <a href="https://www.youtube.com/watch?v=LEtSUeEy0Xc" target="_blank">video</a> shows an example of a real time dashboard built using the Dashbuilder GWT Client API (do not forget to select HD). The dashboard contains some metrics about an emulated cluster (the values shown are not real).<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj8Fiz6hnSc1u8JlzmHiOyf3DFhZvZJEY_z-4owZsa386x6iPa8ukX_ZQcn2HjHOZSFoKYR2oITWZ7eQUofmWssDn2eCAolTuokMpk60xNtpf_H6BYUm5MKBDtWZ07Q3gvvfkiptjYIK6Y/s1600/real-time-example.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj8Fiz6hnSc1u8JlzmHiOyf3DFhZvZJEY_z-4owZsa386x6iPa8ukX_ZQcn2HjHOZSFoKYR2oITWZ7eQUofmWssDn2eCAolTuokMpk60xNtpf_H6BYUm5MKBDtWZ07Q3gvvfkiptjYIK6Y/s1600/real-time-example.png" height="394" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Real time dashboard example</td></tr>
</tbody></table>
<br />
The dashboard is part of the Dashbuilder examples gallery and it's basically a GWT UI binder widget (source code <a href="https://github.com/dashbuilder/dashbuilder/blob/master/dashbuilder-webapp/src/main/java/org/dashbuilder/client/metrics/ClusterMetricsDashboard.java" target="_blank">here</a>).<br />
<br />
Not only we allow for creating programmatic dashboards but also for custom ones created by end users. The next <a href="https://www.youtube.com/watch?v=FdSvV0ivG8w" target="_blank">video</a> (select HD) is a demo of how to create a real-time dashboard from scratch using the tooling. Here again, we're using the emulated cluster metrics data set, so the values shown are not real.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEibqwTuO7714OiKKzodXX5RAivNhkCAqLZmY55Mxs0CDXeqjxm2p_hdxBoJY9HbvqfhWgBshaXhyphenhyphenbgtrj5jbk44ygfDe6KSdC0BdkNeoYloibcvclVJJJklUPpkAvUGVyMvGBhSdjXrifs/s1600/real-time-creation.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEibqwTuO7714OiKKzodXX5RAivNhkCAqLZmY55Mxs0CDXeqjxm2p_hdxBoJY9HbvqfhWgBshaXhyphenhyphenbgtrj5jbk44ygfDe6KSdC0BdkNeoYloibcvclVJJJklUPpkAvUGVyMvGBhSdjXrifs/s1600/real-time-creation.png" height="394" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Creating a real-time dashboard</td></tr>
</tbody></table>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
As you can see, Dashbuilder covers a wide range of scenarios. As we introduced in this <a href="http://dashbuilder.blogspot.com.es/2015/02/uf-dashbuilder-and-new-data-set.html" target="_blank">blog entry</a>, data can be extracted from different systems. Once you have the data you can easily create your own visualizations. Both the analytics and real-time approaches are supported out of the box. <br />
<br />
Unknownnoreply@blogger.com4tag:blogger.com,1999:blog-4358594258656726438.post-88414488606390708232015-03-20T13:42:00.000+01:002015-04-05T23:00:42.813+02:00UF Dashbuilder - Metric visualizations A metric is a very useful type of visualization for displaying a single value for a given data property. For example:<br />
<br />
<ul>
<li>The number of running processes in a server, memory used, CPU load, I/O throughput, etc...</li>
<li>The number of tweets received last week</li>
<li>The total travel expenses in a company</li>
</ul>
<div>
The next screenshot shows a sample dashboard using the new metric visualization recently added to Dashbuilder. </div>
<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiWm_E69KBTRhVCu7JOyDIKBhvOksI1kfV8AcGg2evwSOVw7VGlNtO7FfKwXUPCg6wzMaInDXzQZ0FeONn_qCkU0uW0ZZgsTyx75ZfPBYDAkNvhFypypaX2MeINPoP6DbUFog_3u4i0glM/s1600/sales_dashboard.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img alt="Sales dashboard example" border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiWm_E69KBTRhVCu7JOyDIKBhvOksI1kfV8AcGg2evwSOVw7VGlNtO7FfKwXUPCg6wzMaInDXzQZ0FeONn_qCkU0uW0ZZgsTyx75ZfPBYDAkNvhFypypaX2MeINPoP6DbUFog_3u4i0glM/s1600/sales_dashboard.png" height="436" title="Sales dashboard example" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Sales dashboard example</td></tr>
</tbody></table>
<div class="separator" style="clear: both; text-align: center;">
<span style="text-align: left;"><br /></span></div>
The entire dashboard is consuming the same data set, although every displayer has been configured with the proper settings. Next, we are going to see how those metrics indicators can be created using the tooling.<br />
<br />
<b><span style="font-size: large;"> Metric displayer</span></b><br />
<br />
As you can see below, a new "Metric" visualization type has been added to the Displayer Editor.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjIWlLAc6-kq1_F16-iG-XeaHHLBbwz8tpDmvw98L0FyVYI1j1B5JjtEQZ8QRnVD_i9VhAaRzpVpBNcdIyIw_bv56dnbHGmk9i3pq-4Dta9u90TLD2Te3TRlWYWYLj4X3FSEqgU6GTADEM/s1600/metric_editor.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img alt="Displayer editor - Metric visualization type " border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjIWlLAc6-kq1_F16-iG-XeaHHLBbwz8tpDmvw98L0FyVYI1j1B5JjtEQZ8QRnVD_i9VhAaRzpVpBNcdIyIw_bv56dnbHGmk9i3pq-4Dta9u90TLD2Te3TRlWYWYLj4X3FSEqgU6GTADEM/s1600/metric_editor.png" height="488" title="Displayer editor - Metric visualization type " width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Displayer editor - Metric visualization type </td></tr>
</tbody></table>
<br />
<br />
Once the "Metric" option has been selected, next step is to configure the data retrieval (see below, the "Data" tab). From this tab we need to:<br />
<br />
<ol>
<li>Select the source data set. In this case we have chosen the "Sales opportunities" example, which is a Java Bean generated data set containing the sales of a virtual company from the last 2 years until 3 years in the future.</li>
<li>Select the metric to display. In this case we have selected the total sum of the opportunities closed within the current company's fiscal year. To do so, from the "Filters" section, we have added a filter on the property "closingDate". </li>
</ol>
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgRAfIJnXoJIhT3ldR2MNviQs3FCn5I1VgtgaapRU6pwE2XWnag9GByWB_1fUbouR-_fcs8hKZB3EbbR8oJB5uei15VVafubm9etIaTbdij5XjuHgpgHfwy8MI1Q7Qb0CAWejhqjJtwJq0/s1600/metric_editor_2.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img alt="Metric displayer configuration" border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgRAfIJnXoJIhT3ldR2MNviQs3FCn5I1VgtgaapRU6pwE2XWnag9GByWB_1fUbouR-_fcs8hKZB3EbbR8oJB5uei15VVafubm9etIaTbdij5XjuHgpgHfwy8MI1Q7Qb0CAWejhqjJtwJq0/s1600/metric_editor_2.png" height="382" title="Metric displayer configuration" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Metric displayer configuration</td></tr>
</tbody></table>
<br />
After configuring the data retrieval, the last step is to adjust the "Display" settings. First of all, the metric needs a title. Secondly, the metric format can also be adjusted. There are 2 settings involved:<br />
<br />
<b>Expression</b><br />
<br />
It's a mathematical operation applied to the value retrieved from the data set. In our case, we are using "value/1000" as we want to display thousand dollars. Thousands are easier to understand by end users as sales amounts are usually big figures.<br />
<br />
<div>
We can combine the most common mathematical operators: <br />
</div>
<div>
* => Multiply<br />
<div>
/ => Divide</div>
<div>
+ => Add</div>
<div>
- => Subtract</div>
<div>
<br /></div>
<div>
For example: </div>
<div>
<ul>
<li>"value*1.21" => Amount plus 21% tax"</li>
</ul>
Actually, we can use any valid JavaScript expression. For instance, "Math.sqrt(value)", square root, is also valid.</div>
<div>
<br /></div>
<div>
<b>Pattern</b></div>
<div>
<br /></div>
<div>
It's used to format the value obtained after applying the above expression. In our case we want to use the "$" currency symbol together with the "K" suffix as we want to indicate the value displayed is formatted in thousand dollars. f.i: "$ 10,345.23 K". Pattern expressions are based on the default <a href="http://www.gwtproject.org/javadoc/latest/com/google/gwt/i18n/client/NumberFormat.html" target="_blank">Java notation</a> format for numbers. Some examples:</div>
<div>
<br /></div>
<div>
<ul>
<li>"#,###" => "10,300" no decimal part</li>
<li>"$#,###.##" => "$10,300.45" decimal part, currency symbol</li>
<li>"000000.000" => "010300.453" leading and trailing zeros, no commas</li>
</ul>
</div>
<div>
<div>
<br /></div>
<div>
<br />
That's all for today. As you can see, in Dashbuilder, has never been so easy to create & configure metrics visualizations on top of your data. Thanks for reading and stay tuned!</div>
<br />
<br /></div>
</div>
Unknownnoreply@blogger.com1tag:blogger.com,1999:blog-4358594258656726438.post-42035576713711337032015-03-10T13:07:00.001+01:002015-03-10T17:32:20.291+01:00UF Dashbuilder - Activity monitoring in jBPM Last week, the jBPM team announced the 6.2.0.Final release (announcement <a href="http://blog.athico.com/2015/03/jbpm-620final-released.html" target="_blank">here</a>). In this release (like in previous ones) you can author processes, rules, data models, forms and all the assets of a BPM project. You can also create or clone existing projects from remote GIT repositories and group such repositories into different organizational units. Everything can be done from the jBPM authoring console (aka KIE Workbench), a unified UI built using the Uberfire framework & GWT.<br />
<br />
In this latest release, they have also added a new perspective to monitor the activity of the source GIT repositories and organizational units managed by the tooling (see screenshot below). The perspective itself it's just a dashboard displaying several indicators about the commit activity. From the dashboard controls it is possible to:<br />
<br />
<ul>
<li>Show the overall activity on our repositories</li>
<li>Select a single organizational unit or repository</li>
<li>List the top contributors</li>
<li>Show only the activity for an specific time frame</li>
</ul>
<br />
In this <a href="https://www.youtube.com/watch?v=IX4XfggAR7s" target="_blank">video</a> you can see the dashboard in action (do not forget to select HD).<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjHlzpBsxPNMa_cuLshaDtBv5Wjh0ycxpHLdBn9uSaeRtKgu6Hq15CrES_ZwozJXqONP30CJw5GmBdRMz-u8gAYH9TMlNxyCSoxJ4PowJUgW-zHb-3SqKU5Jq7ZS_0LhSImUcCB-yYF5Kk/s1600/contributors.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjHlzpBsxPNMa_cuLshaDtBv5Wjh0ycxpHLdBn9uSaeRtKgu6Hq15CrES_ZwozJXqONP30CJw5GmBdRMz-u8gAYH9TMlNxyCSoxJ4PowJUgW-zHb-3SqKU5Jq7ZS_0LhSImUcCB-yYF5Kk/s1600/contributors.png" height="441" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Contributors Perspective</td></tr>
</tbody></table>
<br />
Organizational units can be managed from the menu <i>Authoring>Administration>Organizational Units</i>. Every time an organizational unit is added or removed the dashboard is updated.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjdScK-yAk8oo03PnjItYxr3-26ulbWDWoUwbEig9e1_1Yl8UQNSR3UNHiB5CyjsG0dwto0Qp3SmbFL2u0bg9XsfWJPm9VMuyWHKJAhDkeTZoR37vrVYSv3s1eG490AaJJ_IbFbHoWe-mc/s1600/orgunits.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjdScK-yAk8oo03PnjItYxr3-26ulbWDWoUwbEig9e1_1Yl8UQNSR3UNHiB5CyjsG0dwto0Qp3SmbFL2u0bg9XsfWJPm9VMuyWHKJAhDkeTZoR37vrVYSv3s1eG490AaJJ_IbFbHoWe-mc/s1600/orgunits.png" height="200" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Administration - Organizational Units </td></tr>
</tbody></table>
<br />
Likewise, from the <i>Authoring>Administration>Repositories </i>view we can create, clone or delete repositories. The dashboard will always feed from the list of repositories available.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj6uHtzyLkeIEjmnbgg5Ap8SOAPljVEdQvID1cLosl8C8cZlkIzUrGMEYsrcY02pwc5_g72tneV8YZgB1IiDUsH8nVh2rP1kHEDd8NXPcd3q4sAk72UTD7MB0QR9TenleEyvxaUJoFHjiU/s1600/repos.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj6uHtzyLkeIEjmnbgg5Ap8SOAPljVEdQvID1cLosl8C8cZlkIzUrGMEYsrcY02pwc5_g72tneV8YZgB1IiDUsH8nVh2rP1kHEDd8NXPcd3q4sAk72UTD7MB0QR9TenleEyvxaUJoFHjiU/s1600/repos.png" height="214" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Administration - Repositories</td></tr>
</tbody></table>
<br />
<br />
<br />
As shown, activity monitoring in jBPM can be applied not only to the processes business domain but also to the authoring lifecycle in order the get a detailed view of the ongoing development activities.<br />
<br />
<b><span style="font-size: large;">
How it's made</span></b><br />
<br />
<br />
The following diagram shows the overall design of the dashboard architecture. Components in grey are platform components, blue ones are specific to the contributors dashboard.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgxoAQBgaDYQg1jrO-Ip7b_sYStkMvaGcZqDVoWjXEaUgVtazpusturOmRW6Y90KXMvQeXy3ol9-t7JHQuNGWSff2NSdn6rp_EdCkhvN_pFJ_bjgScPiVIMxXo5PHe3Xa6BjGlJLKr7ZOo/s1600/Contributors+perspective+architecture.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgxoAQBgaDYQg1jrO-Ip7b_sYStkMvaGcZqDVoWjXEaUgVtazpusturOmRW6Y90KXMvQeXy3ol9-t7JHQuNGWSff2NSdn6rp_EdCkhvN_pFJ_bjgScPiVIMxXo5PHe3Xa6BjGlJLKr7ZOo/s1600/Contributors+perspective+architecture.png" height="356" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Contributors dashboard architecture</td></tr>
</tbody></table>
<br />
These are the steps the backend components take to build the contributors data set:<br />
<br />
<ul>
<li>The <i>ContributorsManager</i> asks the platform services for the set of available org. units & repos. </li>
<li>Once it has such information, it builds a data set containing the commit activity.</li>
<li>The contributors dataset is registered into the Dashbuilder's <i>DataSetManager</i>.</li>
</ul>
<div>
<br /></div>
<div>
All the steps above are executed on application start up time. Once running, the <i>ContributorsManager</i> also receives notifications form the platform services about any changes on the org. units & repositories registered, so that the contributors data set is synced up accordingly. </div>
<br />
<br />
<br />
From the UI perspective, the jBPM's contributors dashboard is an example of a hard-coded dashboard built using the Dashbuilder Displayer API, which was introduced in <a href="http://dashbuilder.blogspot.com.es/2015/03/uf-dashbuilder-displayer-editor-api_3.html" target="_blank">this</a> previous blog entry. The <i>ContributorsDashboard</i> component is just a GWT composite widget containing several <i>Displayer</i> instances feeding from the contributors data set.<br />
<div>
<br /></div>
(The source code of the contributors perspective can be found <a href="https://github.com/droolsjbpm/kie-wb-common/tree/master/kie-wb-common-screens/kie-wb-common-contributors" target="_blank">here</a>)<br />
<br />
<br />
<br />
<br />
This has been a good example of how to leverage the Dashbuilder technology to build activity monitoring dashboards. In the future, we plan for applying the technology in other areas within jBPM, like, for instance, an improved version of the jBPM process dashboard. We will keep you posted!<br />
<br />Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-4358594258656726438.post-6808230300615621962015-03-05T19:53:00.000+01:002015-03-05T19:53:55.126+01:00Dashbuilder 6.2.0 releasedThe 6.2.0 Final release is available for <a href="http://dashbuilder.org/downloads_binaries.html" target="_blank">download </a>in the dashbuilder.org website.<br />
<br />
<br />
<ul>
<li>Improved import/export support for unattended dashboard deployment. This allows for automating the movement of dashboards between different environments (dev/test/prod). Further details in the following 6.2.0 book's <a href="http://docs.jboss.org/dashbuilder/release/6.2.0.Final/html_single/#chap-dashbuilder-import-export" target="_blank">chapter</a>. </li>
</ul>
<ul>
<li>Added support for Weblogic 12c and Sybase DB (ASE 15.7) </li>
</ul>
<div>
<br /></div>
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-4358594258656726438.post-46589419087725957642015-03-03T18:45:00.004+01:002015-03-04T10:07:55.394+01:00UF Dashbuilder - Rendering Subsystem<span style="font-size: small;"> More and more data is being collected nowadays, but collecting lots of data does not make any sense until these data can be extracted, analyzed and interpreted to make it understandable for business people. Data visualization is one of the key points of this process: data visualization is the presentation of data in a pictorial or graphical format. There exist several ways of displaying and representing these data such as tables or charts.</span><br />
<span style="font-size: small;"><br /></span>Data visualization software is wide extended in the market, there exist lots of libraries that provides the ability to create data tables and all kind of charts. Some of them are proprietary, some open source, some provides specific graphs and others are designed to be used in specific scenarios.<br />
<br />
In Dashbuilder, we think the best approach is to be able to adapt to any of those libraries easily. It allows the developer to use all the power of the Dashbuilder's data set API and display the data as user expects, using different data visualization components from different libraries that can be adapted to every situation.<br />
<br />
These visualization components that integrate the visualization libraries with Dashbuilder Data Set API are called <i><b>Displayers</b></i>. Dashbuilder provides by default some displayer components, such as the Google bar, pie and table displayers, or the Lienzo bar chart displayer, among others.<br />
<br />
Another concept that comes into play is the <i><b>Renderer Library</b></i>: a Dashbuilder component that allows the framework to use any third party data visualization library. It allows the communication between data set API and the way how data is visualized. The goal of a renderer is to provide a Displayer for each of the visualizations supported.<br />
<br />
As you can see, data visualization is the last stage in business data analysis; as it's what the end user will see and use to take business decisions. So it's very important to talk about how Dashbuilder renders the data and how it adapts to any situation by integrating and handling third party data visualization libraries.<br />
<br />
This article explains the internals of the Dashbuilder rendering subsystem, its architecture and the design of the different components and interfaces involved.<br />
<h3>
</h3>
<h3>
</h3>
<h3>
<span style="font-size: large;"><br /></span></h3>
<h3>
<span style="font-size: large;">The rendering subsystem</span></h3>
<div>
</div>
The rendering subsystem in Dashbuilder is the responsible for generating the different kinds of visualization components, such as bar charts, pie charts, area charts, bubble charts, tables, maps and so on.<br />
<br />
These are some examples of visualization components provided by default:<br />
<div class="separator" style="clear: both;">
<br /></div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiN3s-1LJdclIffACqmAC7MS6nAVHV0pHUC0hj55WorM_uxkYFV7k7xOI2vHlC77oeqT4JluLf7weDXVziaOqcPHI3e85_FmkdgwdFbz2fnhv9-RGV1pZeXQCZYmBQnbAOkQBtZCzRGa57D/s1600/gwt_bar_pie.jpeg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiN3s-1LJdclIffACqmAC7MS6nAVHV0pHUC0hj55WorM_uxkYFV7k7xOI2vHlC77oeqT4JluLf7weDXVziaOqcPHI3e85_FmkdgwdFbz2fnhv9-RGV1pZeXQCZYmBQnbAOkQBtZCzRGa57D/s1600/gwt_bar_pie.jpeg" height="236" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="font-size: 12.8000001907349px;">GWT Bar and Pie Charts</td></tr>
</tbody></table>
<div class="separator" style="clear: both;">
<br /></div>
<div>
<br />
The main advantage of the rendering subsystem is that it's not tied to any visualization library, as it provides a pluggable mechanism in order to use your favorite one.</div>
<div>
<br /></div>
<h4>
Data visualization libraries are pluggable. What does that mean?</h4>
<div>
<br />
Dashbuilder is a data visualization framework that provides the ability to query, collect and organize your business data, but its goal is not focused in developing and providing data visualization components on the client side; it just provides the grouped, filtered an sorted data to use in those visualization components, that can be provided by any third party data visualization library.</div>
<div>
<br /></div>
<div>
Summarizing, the rendering subsystem provides a <i>pluggable</i> mechanism that connects the data set API with a data visualization component, and it allows to use any third party library to visualize it. </div>
<div>
<br /></div>
<div>
This external data visualization mechanism is represented by the <i style="font-weight: bold;">RendererLibrary </i>interface<i> </i>and managed by the<i> RendererLibLocator </i>as you can see in the following diagram:<i> </i></div>
<div>
<br /></div>
<div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhMEFtbC4-QPSpliUPlEq-f6UtlDvygkYGp-s-Lyebtfp7Uk44mGQ5auu8UtDHb9QCNvlgWOxs8BIQeluGqY0R9snoaRzo8jIgUnSMTrMOqvo8u-H-FI2zB_coLE5zMMKr5yeXdVpi2LuM/s1600/UF+Dashbuilder+Renderer+subsystem.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhMEFtbC4-QPSpliUPlEq-f6UtlDvygkYGp-s-Lyebtfp7Uk44mGQ5auu8UtDHb9QCNvlgWOxs8BIQeluGqY0R9snoaRzo8jIgUnSMTrMOqvo8u-H-FI2zB_coLE5zMMKr5yeXdVpi2LuM/s1600/UF+Dashbuilder+Renderer+subsystem.png" height="564" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="font-size: 12.8000001907349px;"><span style="font-size: small;">Renderer subsystem main interfaces</span></td></tr>
</tbody></table>
<br /></div>
<div>
As an example, consider the following two charts. Both display the same chart type and same data but using different data visualization libraries: <i><a href="https://code.google.com/p/gwt-charts/">GWT</a> </i>and <a href="https://github.com/ahome-it/lienzo-charts/" style="font-style: italic;">Lienzo</a>:</div>
<div>
<br /></div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhrUQ68Td83RicaRQLP8Vk-BBdJo-FtMk-iEVyy59VhY0MjaGWXsLtNTPqCgyFTLL5DZPC_F1BUq4LFVmPVRMlp0-Npk9hUMkt6Cv6r2mt1aUm305g8R-JjqM-zXHfsKugWK1n5yCsUrYRH/s1600/gwt_vs_lienzo.jpeg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhrUQ68Td83RicaRQLP8Vk-BBdJo-FtMk-iEVyy59VhY0MjaGWXsLtNTPqCgyFTLL5DZPC_F1BUq4LFVmPVRMlp0-Npk9hUMkt6Cv6r2mt1aUm305g8R-JjqM-zXHfsKugWK1n5yCsUrYRH/s1600/gwt_vs_lienzo.jpeg" height="193" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="font-size: 12.8000001907349px;">Bar Chart - Lienzo vs <span style="font-size: 12.8000001907349px;">GWT</span></td></tr>
</tbody></table>
<br />
<br />
<h3>
<span style="font-size: large;">Renderer Library</span></h3>
<div>
A <i>RendererLibrary</i> is a component that displays the data using an specific visualization library. Its main goal<i> </i>is to provide a data <i style="font-weight: bold;">Displayer </i>component for each visualization component the visualization library provides.<br />
<br />
For example, consider the GWT charting library. As it provides a bar chart, the <i>Dashbulder's Google Renderer library</i> will provide the <i>GoogleBarChartDisplayer</i>. As it provides a pie chart, the Dashbulder's Google Renderer library will provide the <i>PieBarChartDisplayer</i>. And make it extensible for all kind of GWT charts.<br />
<br />
The following UML diagram shows an example of a RendererLibrary implementation for Google GWT charting.<br />
<br />
In this example, the renderer implementation class is <i>GoogleRenderer </i>(implements <i>Renderer </i>interface) and it provides a <i>GoogleDisplayer </i>based class (implements <i>Displayer </i>interface). Note that GoogleDisplayer class extends some other abstract Google base classes, but it's up to the developer the architecture for it. <u>Dashbuilder just requires to implmenent the <i>Displayer </i>interface for drawing the component</u>.</div>
<div>
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjnhLxn-j77gj6aXagMZa940UYa2dZbMVdsXFJ4G1zQzS215GnBLxj6hv4UtEWfpNJYHeWEmosTEdvoHWy9Rb8NeYv_v7o0eljXDlk4nUFoFhAGxxYX3vMG-Utwnmn2-qMWwf3nGD3xEOo/s1600/UF+Dashbuilder+Google+Renderer.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjnhLxn-j77gj6aXagMZa940UYa2dZbMVdsXFJ4G1zQzS215GnBLxj6hv4UtEWfpNJYHeWEmosTEdvoHWy9Rb8NeYv_v7o0eljXDlk4nUFoFhAGxxYX3vMG-Utwnmn2-qMWwf3nGD3xEOo/s1600/UF+Dashbuilder+Google+Renderer.png" height="640" width="624" /></a></td></tr>
<tr><td class="tr-caption" style="font-size: 12.8000001907349px;"><span style="font-size: small;">Google Renderer & Displayer classes diagram</span></td></tr>
</tbody></table>
<br />
<h3>
<div>
<span style="font-size: small;"><span style="font-weight: normal;">As you can see in the diagram above, each </span><i style="font-weight: normal;">RendererLibrary</i><span style="font-weight: normal;"> has a unique identifier. But as most important, a </span><i style="font-weight: normal;">RendererLibrary</i><span style="font-weight: normal;"> component </span>must provide<span style="font-weight: normal;"> two methods: </span><i>draw</i><span style="font-weight: normal;"> and </span><i>redraw</i><i style="font-weight: normal;">, </i><span style="font-weight: normal;">which are used by the framework as: </span><i style="font-weight: normal;">draw</i><span style="font-weight: normal;"> method to init & render the visualization for the first time, and </span><i style="font-weight: normal;">redraw</i><span style="font-weight: normal;"> to get and display the latest data changes.</span></span></div>
<div style="font-weight: normal;">
<span style="font-size: small;"><br /></span></div>
<div style="font-weight: normal;">
<span style="font-size: small;">It's important to note that each third party data visualization library can provide custom functionality and custom settings for a visualization component that are not present in the same component from another library.</span><br />
<span style="font-size: small;"><br /></span><span style="font-size: small;">For those interested in developing a new renderer, please just take a look at the current implementations of the <a href="https://github.com/dashbuilder/dashbuilder/blob/master/dashbuilder-client/dashbuilder-renderers/dashbuilder-renderer-google/src/main/java/org/dashbuilder/renderer/google/client/GoogleRenderer.java">GoogleRenderer</a> and <a href="https://github.com/dashbuilder/dashbuilder/blob/master/dashbuilder-client/dashbuilder-renderers/dashbuilder-renderer-lienzo/src/main/java/org/dashbuilder/renderer/lienzo/client/LienzoRenderer.java">LienzoRenderer</a> in GitHub.</span><br />
<span style="font-size: small;"><br /></span></div>
</h3>
<h4>
<span style="font-size: large;">Available rendering libraries</span></h4>
</div>
<div>
Dashbuilder supports by default:<br />
<ul>
<li><b>GWT</b> - Data visualization library that provides several chart types that are build using the popular <a href="http://www.gwtproject.org/">GWT framework</a>. Provided by Google.<br /><br />The project is located at <a href="https://code.google.com/p/gwt-charts/">Google Code</a> and you can find the gallery <a href="https://developers.google.com/chart/interactive/docs/gallery">here</a>.</li>
</ul>
<ul>
<li><b>Lienzo </b> - Data visualization library that it's still a prototype under development and not ready to be used in production environments. It provides, at this stage, two chart types: bar & pie. It's tight integrated with Dashbuilder and will provide extended functionality. Keep updated on it!<br /><br />Note that it's Open Source and distributed by <a href="http://www.ahome-it.com/">Ahomé Innovation Technologies</a>.<br /><br />The project is located at <a href="https://github.com/ahome-it/lienzo-charts/">GitHub</a> and you can find the gallery <a href="http://www.lienzo-core.com/lienzo-ks/#WELCOME">here</a>.<br /> </li>
</ul>
</div>
<div>
These are the visualization components supported by each <i>Rendering Library</i>:<br />
<br />
<table align="center" border="1"><tbody>
<tr><th>Renderer Library</th><th>Bar Chart</th><th>Pie Chart</th><th>Area Chart</th><th>Line Chart</th><th>Bubble Chart</th><th>Meter Chart</th><th>Table</th><th>Map</th></tr>
<tr><td align="center">GWT</td><td align="center">X</td><td align="center">X</td><td align="center">X</td><td align="center">X</td><td align="center">X</td><td align="center">X</td><td align="center">X</td><td align="center">X</td></tr>
<tr><td align="center">Lienzo </td><td align="center">X</td><td align="center">X</td><td align="center">-</td><td align="center">-</td><td align="center">-</td><td align="center">-</td><td align="center">-</td><td align="center">-</td></tr>
</tbody></table>
<br />
<u>IMPORTANT</u><b>:</b> In future releases we will integrate new renderer libraries in order to support other visualization frameworks such as <a href="http://d3js.org/"><b>D3</b></a>. Stay tuned!<br />
<br /></div>
<div>
<br /></div>
<div>
<h3>
<span style="font-size: large;">The rendering process</span></h3>
</div>
<div>
Once your are familiarized with the basic components in Dashbuilder, let's explain how the rendering process works. <b>Rendering</b> is the process of generating a component or an image from a given model by a computer program. In Dashbuilder, the rendering process allows for getting & draw a <i>Displayer</i> instance from a given <i>DisplayerSettings</i> configuration.<br />
<br />
In the <a href="http://dashbuilder.blogspot.com.es/2015/03/uf-dashbuilder-displayer-editor-api_3.html">previous</a> article,<span style="color: red;"> </span>we talked about <i>Displayers</i> and how to create them. Now we are going to give some insights about the internals, and how Dashbuilder uses the renderer libraries to create & draw a Displayer.<br />
<br />
The rendering process implies:<br />
<ul>
<li><b>To perform a data set look up</b></li>
</ul>
Given a data set (looked up from an external system) the users want to display the data in a certain way, by performing operations on it, such as grouping, filtering or sorting. This is the initial step to achieve data visualization: collect and organize your business data in a concrete way that will allow the business decision maker to analyze and interpret it. (In this previous <a href="http://dashbuilder.blogspot.com.es/2015/02/uf-dashbuilder-and-new-data-set.html" target="_blank">article</a> you can get all the details about the data set lookup process).<br />
<ul>
<li><b>To provide the settings for the data visualization component that will display the information</b></li>
</ul>
At this point, the data is already collected and organized, next step is to decide which data visualization library to use and configure it for your purposes.<br />
<ul>
<li><b>To obtain a Displayer component from Renderer class</b></li>
</ul>
Once data set is collected, organized and the user have decided & configured the data visualization library to use, next step is to obtain the <i>Displayer </i>component that matches all these requirements. This displayer is provided by the renderer class.<br />
<ul>
<li><b>To draw the data visualization component (draw the Displayer instance)</b></li>
</ul>
Having the Displayer component instance it's time to show the data visualization component to the end user. To achieve that goal the Displayer component provides two methods: <i>draw</i> and <i>redraw</i>.<br />
<br />
<h3>
</h3>
<h3>
<span style="font-size: small;">Rendering process in action</span></h3>
Next lines gets you into a deep detail in Dashbuilder architecture and how component interact to achieve the rendering process.</div>
<div>
<br />
Consider your are creating a view (<i>MyView</i>) with a bar chart component using Dashbuilder. Your view source code would be similar to:<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhI6ZSyk0qf8wdr3s2CMnyX0denu7QWYCohLvHwK5V7neC3aJ6nhLteuqKDsxsHTlkYPh69GHfDtfOMH4jfmV3u5vJwEjwLhH4-QC4ddt9a6sPABVyy83c1kArMStroJcc06Wf-qN6M0YFH/s1600/MyViewExample.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhI6ZSyk0qf8wdr3s2CMnyX0denu7QWYCohLvHwK5V7neC3aJ6nhLteuqKDsxsHTlkYPh69GHfDtfOMH4jfmV3u5vJwEjwLhH4-QC4ddt9a6sPABVyy83c1kArMStroJcc06Wf-qN6M0YFH/s1600/MyViewExample.png" height="640" width="620" /></a></td></tr>
<tr><td class="tr-caption" style="font-size: 12.8000001907349px;"><span style="font-size: small;">Example of view that uses a Bar Chart Displayer</span></td></tr>
</tbody></table>
<br />
The following diagram shows the sequence of calls between all the components involved during this bar chart displayer creation:<br />
<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhn08e-Nx2G90EUcHW1evgti4K45FQ41FO6tEktRGdlAADv79u6OMeQzZs5GVKzkrngIBy2fpJqt58qkFwTYbPQdR4JRKd_xTGhBX-_0KobDOS3Eu2fRLMn4rsH8jXOZ6-i9tFWl1ZQ-PWk/s1600/renderer-displayer-creation-seq.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhn08e-Nx2G90EUcHW1evgti4K45FQ41FO6tEktRGdlAADv79u6OMeQzZs5GVKzkrngIBy2fpJqt58qkFwTYbPQdR4JRKd_xTGhBX-_0KobDOS3Eu2fRLMn4rsH8jXOZ6-i9tFWl1ZQ-PWk/s1600/renderer-displayer-creation-seq.jpg" height="523" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="font-size: 12.8000001907349px;"><span style="font-size: small;">Displayer lookup sequence diagram</span></td></tr>
</tbody></table>
<ol>
<li> Build the settings for your <i>Displayer</i> component that will be used to show the bar chart.<br /> </li>
<ol>
<li>Build the <span style="color: #741b47;">displayerSettings</span> instance from the factory methods that provide <i>DisplayerSettingsFactory<br /> </i></li>
<li><i><span style="font-style: normal;">The settings instance contains the data set look up, the renderer library to use, the data visualization component to render and its settings<br /> </span></i></li>
</ol>
<li>Build a <i>DisplayerHelper</i> instance and use it to show the component (see <span style="color: blue;">init</span> method)<br /> </li>
<ol>
<li>Obtain the <i>Displayer</i> component instance for your settings.<br /> </li>
<ol>
<li>Use the helper class <i>DisplayerHelper</i> to perform a displayer look up by using the method <i>lookupDisplayer</i>. As you can see, to look up a displayer you have to provide the settings as method argument.<br /> </li>
<li><i>DisplayerHelper </i>delegates the look up of the displayer to the <i>DisplayerLocator</i> class and uses the returned instance to apply other configurations.<br /> </li>
<li>The <i>DisplayerLocator</i> uses the <i>RendererLibLocator</i> component to locate the data visualization component specified by the settings instance. It's done by calling the method <i>lookupRenderer</i>. The result is a <i>RendererLibrary </i>instance, that is the responsible to provide a <i>Displayer</i> component that will display the data by using the settings provided.<br /> </li>
</ol>
<li>Use <i>Displayer</i> component API methods to draw the data visualization component.<br /> </li>
<ol>
<li>Once we have a <i>Displayer</i> component instance that matches our settings, it's time to draw the data visualization component, in this case, the bar chart.<br /> </li>
<li>The <i>DisplayerHelper </i>class provides a method for showing the data visualization component: <i>draw</i>. This method takes the Displayer instance as argument and perform all the operation to draw the chart.<br /> </li>
<li>Note that <i>DisplayerHelper </i>delegates the draw logic to the <i>RendererLib </i>instance, as it's each renderer library the responsible to draw the data in a certain way and using a certain library.</li>
</ol>
</ol>
</ol>
</div>
<h3>
<span style="font-size: large;">Conclusion</span></h3>
<br />
<div>
</div>
<br />
<div style="-webkit-text-stroke-width: 0px; color: black; font-family: 'Times New Roman'; font-size: medium; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px;">
<div style="margin: 0px;">
Data visualization is one of the most important aspects in any data analysis software, it provides an understandable way to analyze your business data.</div>
<div style="margin: 0px;">
<br /></div>
<div style="margin: 0px;">
In Dashbuilder we don't want to force end users to see and analyze all kind of data in the same way, we don't want to be tied or focused to an specific data visualization component, as depending on the nature of the data, a different visualization technique or library could be required.</div>
<div style="margin: 0px;">
<br /></div>
<div style="margin: 0px;">
For those reasons we think the best approach is to provide a rendering subsystem that can be integrated with any third party data visualization library, as it provides an extensible and scalable way to analyze and display your business data!</div>
</div>
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-4358594258656726438.post-52903109046662339742015-03-03T18:07:00.000+01:002015-03-03T18:07:55.627+01:00UF Dashbuilder Displayer Editor & API<div>
<span style="font-family: Verdana, sans-serif;"> In the <a href="http://dashbuilder.blogspot.com.es/2015/02/uf-dashbuilder-and-new-data-set.html" target="_blank">previous</a> article, we introduced the data set API and how to perform data set look ups. Next step is to visualize this data set in a graphical way. So translating that into Dashbuilder language: to create a Displayer. A Displayer is a component responsible for rendering a data visualization component such as a bar chart, pie chart, tables, etc. This article explains how you can create a displayer to visualize your data. </span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span><span style="font-family: Verdana, sans-serif;">There exist two methods:</span><br />
<span style="font-family: Verdana, sans-serif;"><br />
</span><br />
<ul>
<li><span style="font-family: Verdana, sans-serif;">The <b><i>Data Displayer UI Editor</i></b><br /><br />This is a UI component used to configure all the data set look up, displayer settings and other stuff. Can be used to create, update or remove data displayers at runtime.</span></li>
</ul>
<ul>
<li><span style="font-family: Verdana, sans-serif;">The <b>Dashbuilder's Displayer API</b><br /><br />Instead of creating the displayer at runtime using the UI, you can create displayers at compile time using the Dashbuilder's API. </span></li>
</ul>
<h3>
<span style="font-family: Verdana, sans-serif;"><br /></span></h3>
<h3>
<span style="font-family: Verdana, sans-serif;">Creating a displayer from the UI</span></h3>
<span style="font-family: Verdana, sans-serif;">You can create, update or remove displayers </span><span style="font-family: Verdana, sans-serif;">at runtime </span><span style="font-family: Verdana, sans-serif;">using the Displayer Editor</span><span style="font-family: Verdana, sans-serif;">. This is the initial screen of this component:</span><br />
<span style="font-family: Verdana, sans-serif;"><br />
</span><br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZatxYkGcVMOI5Hr_X38lxY6DK1eGfIogDYTSeh1X52oClEi6Fz_nf8RvGtuqj6biVNflTrf87SF7Gh7L4IfS-PPLXE_g9F3wbYI7xklMXFjO6ek9eQOvKXwJqHBdr9FLcc0arhPqRUHLM/s1600/datadisplayereditor_types.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><span style="font-family: Verdana, sans-serif;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZatxYkGcVMOI5Hr_X38lxY6DK1eGfIogDYTSeh1X52oClEi6Fz_nf8RvGtuqj6biVNflTrf87SF7Gh7L4IfS-PPLXE_g9F3wbYI7xklMXFjO6ek9eQOvKXwJqHBdr9FLcc0arhPqRUHLM/s1600/datadisplayereditor_types.png" height="392" width="640" /></span></a></td></tr>
<tr><td class="tr-caption" style="font-size: 13px;"><span style="font-family: Verdana, sans-serif; font-size: 12.8000001907349px;">Data Displayer Editor component</span></td></tr>
</tbody></table>
<span style="font-family: Verdana, sans-serif;"><br /></span><span style="font-family: Verdana, sans-serif;">As you can see, there exist three main tabs:</span><br />
<ul>
<li><span style="font-family: Verdana, sans-serif;"><b>Types tab</b> - Allows to select the displayer type, such as bar chart, pie chart, table, etc.<br /> </span></li>
<li><span style="font-family: Verdana, sans-serif;"><b>Data tab</b> - Allows to configure the data set look up for that displayer in order to fetch the data that will be displayed.<br /> </span></li>
<li><span style="font-family: Verdana, sans-serif;"><b>Display tab</b> - Allows to select a renderer and configure the settings for the displayer type selected. the set of settings available varies depending on the displayer type and renderer selected.</span></li>
</ul>
<span style="font-family: Verdana, sans-serif;">So the steps to create or update a displayer are:</span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span>
<br />
<ul><span style="font-family: Verdana, sans-serif;">
<li>Choose the desired <b>visualization type</b> from the <i>type </i>tab. In this example. a <i>Line Chart</i> is selected.</li>
</span></ul>
<span style="font-family: Verdana, sans-serif;"><br /></span>
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiYoEFQvQOyQoSPGdxezueeFWuvjDCaqm46iAhSpuXs3n1lh0lbmpRF9j2MxSTbQya-g3cm3r22PyjDEMdRRnPoTr4hxjpKkK07DR5UKTEsrg8y5xaDr_CFdCFaMtTD-DBpQMMj1U7IwqfC/s1600/datadisplayereditor_type_line.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><span style="font-family: Verdana, sans-serif;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiYoEFQvQOyQoSPGdxezueeFWuvjDCaqm46iAhSpuXs3n1lh0lbmpRF9j2MxSTbQya-g3cm3r22PyjDEMdRRnPoTr4hxjpKkK07DR5UKTEsrg8y5xaDr_CFdCFaMtTD-DBpQMMj1U7IwqfC/s1600/datadisplayereditor_type_line.png" height="387" width="640" /></span></a></td></tr>
<tr><td class="tr-caption" style="font-size: 13px;"><span style="font-family: Verdana, sans-serif;">Data Displayer Editor - Type tab</span><br />
<span style="font-family: Verdana, sans-serif;"><br /></span></td></tr>
</tbody></table>
<span style="font-family: Verdana, sans-serif;"><br /></span>
<br />
<ul><span style="font-family: Verdana, sans-serif;">
<li>Click on the <i>Data</i> tab and configure the <b>data lookup</b> settings.</li>
</span></ul>
<span style="font-family: Verdana, sans-serif;"><br /></span>
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi68ezFtNOB_1uYtxQnoS-qfGjiKkupy3prMawT9BJJKe9tWgw4_A9Aazec8KwvrpFMQjImPcG3j4U8AsPO_4_7Jf4-KQOLHsK4qO9by0G2IfZiGohO2zz4XzJAUg4W0nKgADCHbU9G7l0O/s1600/datadisplayereditor_data.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><span style="font-family: Verdana, sans-serif;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi68ezFtNOB_1uYtxQnoS-qfGjiKkupy3prMawT9BJJKe9tWgw4_A9Aazec8KwvrpFMQjImPcG3j4U8AsPO_4_7Jf4-KQOLHsK4qO9by0G2IfZiGohO2zz4XzJAUg4W0nKgADCHbU9G7l0O/s1600/datadisplayereditor_data.png" height="411" width="640" /></span></a></td></tr>
<tr><td class="tr-caption" style="font-size: 13px;"><span style="font-family: Verdana, sans-serif; font-size: 12.8000001907349px;">Data Displayer Editor - Data tab</span></td></tr>
</tbody></table>
<ol><ul>
<li><span style="font-family: Verdana, sans-serif;">First step is to select a Data Set instance. In that case we are using the <i>expenseReports</i> data set.<br /> </span></li>
<li><span style="font-family: Verdana, sans-serif;">You can filter the data set rows by adding filters in the <i>Filters </i>section.<br /> </span></li>
<li><span style="font-family: Verdana, sans-serif;">Select the categories property for the Line chart, in this case, the <i>office </i>data property.<br /> </span></li>
<li><span style="font-family: Verdana, sans-serif;">Add the series for the Line chart: the property and the function to apply. In this example, we are using the <i>sum</i> function to calculate the amount per office.</span></li>
</ul>
</ol>
<ul><span style="font-family: Verdana, sans-serif;">
<li>Click on <i>Display</i> tab to configure the <b>display settings</b>.</li>
</span></ul>
<span style="font-family: Verdana, sans-serif;"><br /></span>
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEig95vPfZE6LbuBhBC4flHt_OyUp11DX9h91pMoFQY0_JIXTxOmoOrwYfGBEwwgs_dmWCW2mOso9rs8Fyvs_W6E-6n9lNHoFFcpwcewT3IvhDh8ScfP8zgjqiili3eIz1iqAKQZxky8_uF8/s1600/datadisplayereditor_display.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><span style="font-family: Verdana, sans-serif;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEig95vPfZE6LbuBhBC4flHt_OyUp11DX9h91pMoFQY0_JIXTxOmoOrwYfGBEwwgs_dmWCW2mOso9rs8Fyvs_W6E-6n9lNHoFFcpwcewT3IvhDh8ScfP8zgjqiili3eIz1iqAKQZxky8_uF8/s1600/datadisplayereditor_display.png" height="385" width="640" /></span></a></td></tr>
<tr><td class="tr-caption" style="font-size: 12.8000001907349px;"><span style="font-family: Verdana, sans-serif; font-size: 12.8000001907349px;">Data Displayer Editor - Display tab</span></td></tr>
</tbody></table>
<span style="font-family: Verdana, sans-serif;"><br />In this tab you have all the displayer settings available for the displayer type selected. Here you can configure the chart position, chart size, chart title, axis titles, margins, legend, tooltips and much more.<br /><br />Another interesting setting is the <i>renderer selector</i>. It allows to change the <i>RendererLibrary </i>for type of chart. For example, we can switch from GWT to Lienzo charts by just changing the selector value:</span><br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><span style="font-family: Verdana, sans-serif;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgH3_jfLHTJpJNhQHsbrIaLDlzoYJCMUegApvDAdp-XWAAQfMfUJEFngVOFzn6SRKU9dy_5dpjeEFP8uLAqnJNpY6hnxg0j4WZnxdRg2mqVJa_pYLqqN3D7Iyd-1QcpeWKF6H_gAg-FvjyW/s1600/datadisplayereditor_renderer_selection.png" style="margin-left: auto; margin-right: auto;" /></span></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><span style="font-family: Verdana, sans-serif;">Renderer selector</span></td></tr>
</tbody></table>
<span style="font-family: Verdana, sans-serif;">Note that this selector only appears when there exist more than one renderer for the selected displayer type.</span></div>
<div>
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<div>
<ul>
<li><span style="font-family: Verdana, sans-serif;">Once the type, the data lookup and display settings are configured, just click the <i>OK</i> button to <b>see the results</b>. The chart is rendered according the set of settings defined:</span></li>
</ul>
<span style="font-family: Verdana, sans-serif;"><br />
</span><br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEguwBEttMXXGXrDTLrFqBrP0N-qIh3vvLerpwc2KOepWwZs9Bh5XOfvggntaJTY_Yp-gmKkU9QrvbVKTGrIyhaH0rT77aXJlZgHM_D_IMifT5CCYm4JRkqOFS-9FuyLQLJWDtQH3PMIJSU2/s1600/displayer.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><span style="font-family: Verdana, sans-serif;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEguwBEttMXXGXrDTLrFqBrP0N-qIh3vvLerpwc2KOepWwZs9Bh5XOfvggntaJTY_Yp-gmKkU9QrvbVKTGrIyhaH0rT77aXJlZgHM_D_IMifT5CCYm4JRkqOFS-9FuyLQLJWDtQH3PMIJSU2/s1600/displayer.png" height="385" width="640" /></span></a></td></tr>
<tr><td class="tr-caption" style="font-size: 12.8000001907349px;"><span style="font-family: Verdana, sans-serif;">Displayer built using Data Displayer Editor in the UI</span></td></tr>
</tbody></table>
<ol></ol>
<h3>
<span style="font-family: Verdana, sans-serif;"><br /></span></h3>
<h3>
<span style="font-family: Verdana, sans-serif;">Creating a chart using the Displayer API</span></h3>
<span style="font-family: Verdana, sans-serif;">You can also use the Dashbuilder's API to create a <i>Displayer</i> instance. Basically, the first step is to create a <i>DisplayerSettings </i>instance and use this instance to lookup a <i>Displayer </i>instance that will show the data visualization component. Next screenshot is an example of a <i>DisplayerSettings</i> used to build a Line chart with a data set that contains the sales evolution per year:</span></div>
<span style="font-family: Verdana, sans-serif;"><br /></span>
<br />
<div>
</div>
<span style="font-family: Verdana, sans-serif;"><br /></span>
<br />
<div style="-webkit-text-stroke-width: 0px; color: black; font-family: 'Times New Roman'; font-size: medium; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px;">
<div style="margin: 0px;">
<span style="font-family: Verdana, sans-serif;"><br /></span></div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJTwFO0Ud8yKVN8E_RXNvHExp6elZNScEF6vm5xayOzLYSh9KI_hSeSlRS8DFVDxuFUsMCthJ13nFtIbOte4Hii0AyxMwb8LB2d20jbc6gRwR43x-oCVY_7umZEoPRFhmLOaGfYOR8aWmy/s1600/displayersettings_api.png" height="370" style="margin-left: auto; margin-right: auto;" width="400" /></td></tr>
<tr><td class="tr-caption" style="text-align: center;">DisplayerSettings creating using Dashbuilder's API</td></tr>
</tbody></table>
<br />
From the code above:<br />
<br />
<ol>
<li>Use of <i>DisplayerSettingsFactory</i> to create a <i>DisplayerSettings</i> instance for a displayer type, in this example, a <i>line chart</i>.<br /> </li>
<li>Configure the <i>Displayer</i> configuration parameters such as title, columns, filters and so on. Several API methods are available in the <i>DisplayerSettings</i> interface: title, columns, filters, renderer, sort operations, grouping, etc.<br /> </li>
<li>Configure a <i>DataSetLookup</i>.<br /> </li>
<ol>
<li>You can create a new data set inline as in the example by using the <i>DataSetFactory</i> component.<br /> </li>
<li>You can use an existing data set by specifying its <i>UUID</i> (the data set must have been previously deployed or created using the UI).<br /> </li>
</ol>
<li>Last step is to call the <i>buildSettings</i> method from <i>DisplayerSettingsFactory</i>. It provides the <i>DisplayerSettings</i> instance for your settings. </li>
</ol>
If you want to <b>use a concrete <i>RendererLibrary</i></b> for rendering the displayer, you can use the <i>renderer</i> method from <i>DisplayerSettings</i> as:<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEimKpjf3oa8sOR3omv9cvNldJLISLKzpr4leTwv-puFRADuY9S9ctYCz0CDW7j2wFr5uxpTPv9SWQQN5UiFo_q8wIQceounQ3HxDhLWooAzCYi4QtXvbKQGfTJS7sS9awswGXAdRG-kPiBB/s1600/displayersettings_api_renderer.png" style="margin-left: auto; margin-right: auto;"><img border="0" height="396" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEimKpjf3oa8sOR3omv9cvNldJLISLKzpr4leTwv-puFRADuY9S9ctYCz0CDW7j2wFr5uxpTPv9SWQQN5UiFo_q8wIQceounQ3HxDhLWooAzCYi4QtXvbKQGfTJS7sS9awswGXAdRG-kPiBB/s1600/displayersettings_api_renderer.png" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Using a concrete renderer via API</td></tr>
</tbody></table>
<br />
Once you have the<i> DisplayerSettings</i> instance built you can use the<i> DisplayerHelper</i> class to visualize your displayer in your view page. As easy as follows:<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhIBV_aB2zRDqnDcJVq_p2IBJVl7P4iBCNEyPcXLYR7CwYoWZzNkbsVO_HiAV0-DsZWM9YW5D9GPz7VnYxzofi1dZTdFSyPFCvkTdDdQKuh0kLIj07AZQ-L8jJNiZa8RaGNgJ6HOerbOXWw/s1600/displayerhelper_example.png" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhIBV_aB2zRDqnDcJVq_p2IBJVl7P4iBCNEyPcXLYR7CwYoWZzNkbsVO_HiAV0-DsZWM9YW5D9GPz7VnYxzofi1dZTdFSyPFCvkTdDdQKuh0kLIj07AZQ-L8jJNiZa8RaGNgJ6HOerbOXWw/s1600/displayerhelper_example.png" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Creating your view</td></tr>
</tbody></table>
As you can see, the constructor for the <i>DisplayerView</i> helper class requires the <i>DisplayerSettings</i> instance previously built and it can be added in any GWT panel, as it's considered a composite GWT widget.<br />
<br />
Once <i>DisplayerHelper</i> widget instance is created and added into your view panels, you can use the <i>draw</i> method to display it. </div>
<div style="-webkit-text-stroke-width: 0px; color: black; font-family: 'Times New Roman'; font-size: medium; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px;">
<br /></div>
<div style="-webkit-text-stroke-width: 0px; color: black; font-family: 'Times New Roman'; font-size: medium; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px;">
Finally your view look like:<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhajaZccSu_me0VrYeJ9HGJ7drsJ90tONTgvixcbMnv7oeSKf1GyiCmVQPPsnLGrJ8fQ0X35D9rBG4xiSe-BA82_NzlVgE40WW29DlgNt1BZ9klMMrWRYYjch_Tfq6YNFR7Vu5iUwzTUfAd/s1600/salesevolution_kpi.png" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhajaZccSu_me0VrYeJ9HGJ7drsJ90tONTgvixcbMnv7oeSKf1GyiCmVQPPsnLGrJ8fQ0X35D9rBG4xiSe-BA82_NzlVgE40WW29DlgNt1BZ9klMMrWRYYjch_Tfq6YNFR7Vu5iUwzTUfAd/s1600/salesevolution_kpi.png" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Displayer created using Dashbuilder's API</td></tr>
</tbody></table>
and.... that's all! :-). For those interested in the API details, please take a look at the Dashbuilder gallery which contains more examples of how to build displayer instances using the API - <a href="https://github.com/dashbuilder/dashbuilder/blob/master/dashbuilder-webapp/src/main/java/org/dashbuilder/client/gallery/GalleryTree.java">Gallery examples</a>.</div>
<!-- Blogger automated replacement: "https://images-blogger-opensocial.googleusercontent.com/gadgets/proxy?url=http%3A%2F%2F1.bp.blogspot.com%2F-uXdytRUadNA%2FVPOJ8Ntcx2I%2FAAAAAAAAGnU%2FW-npjQuEFGQ%2Fs1600%2Fdisplayerhelper_example.png&container=blogger&gadget=a&rewriteMime=image%2F*" with "https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhIBV_aB2zRDqnDcJVq_p2IBJVl7P4iBCNEyPcXLYR7CwYoWZzNkbsVO_HiAV0-DsZWM9YW5D9GPz7VnYxzofi1dZTdFSyPFCvkTdDdQKuh0kLIj07AZQ-L8jJNiZa8RaGNgJ6HOerbOXWw/s1600/displayerhelper_example.png" --><!-- Blogger automated replacement: "https://images-blogger-opensocial.googleusercontent.com/gadgets/proxy?url=http%3A%2F%2F1.bp.blogspot.com%2F-TcFVduEgX5w%2FVPOIbzXG6AI%2FAAAAAAAAGnE%2FPZ8fqcrzhz4%2Fs1600%2Fdisplayersettings_api_renderer.png&container=blogger&gadget=a&rewriteMime=image%2F*" with "https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEimKpjf3oa8sOR3omv9cvNldJLISLKzpr4leTwv-puFRADuY9S9ctYCz0CDW7j2wFr5uxpTPv9SWQQN5UiFo_q8wIQceounQ3HxDhLWooAzCYi4QtXvbKQGfTJS7sS9awswGXAdRG-kPiBB/s1600/displayersettings_api_renderer.png" --><!-- Blogger automated replacement: "https://images-blogger-opensocial.googleusercontent.com/gadgets/proxy?url=http%3A%2F%2F1.bp.blogspot.com%2F-TxiWaRf8PPA%2FVPOMGzoCUII%2FAAAAAAAAGng%2F2MjzEeUpnAs%2Fs1600%2Fsalesevolution_kpi.png&container=blogger&gadget=a&rewriteMime=image%2F*" with "https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhajaZccSu_me0VrYeJ9HGJ7drsJ90tONTgvixcbMnv7oeSKf1GyiCmVQPPsnLGrJ8fQ0X35D9rBG4xiSe-BA82_NzlVgE40WW29DlgNt1BZ9klMMrWRYYjch_Tfq6YNFR7Vu5iUwzTUfAd/s1600/salesevolution_kpi.png" -->Unknownnoreply@blogger.com2tag:blogger.com,1999:blog-4358594258656726438.post-60292785119859379412015-02-13T10:39:00.001+01:002015-04-07T17:16:22.949+02:00UF Dashbuilder and the new data set architecture Uberfire and the GWT echosystem brings not only a lot of exciting cool features but also an extremely powerful development environment. UF Dashbuilder stands for the Uberfire-zed version of Dashbuilder. Since last year, we've been working on rewriting the whole Dashbuilder application on top of Uberfire and GWT. During this migration stage we have rewritten, almost entirely, the backend layer and some of the UI components. There is still a lot of work to do, as we know, but we want to start sharing what we have achieved so far. In previous articles we showed how to use the technology to build dashboards using the Displayer API. Today we're going to explore the Data Set architecture, how to define and deploy data sets in Dashbuilder and make the dashboards feed from them.<br />
<br />
So what is a data set? Well, basically, it is a set of columns populated with some rows. Another valid definition is: a matrix of data composed by timestamps, texts and numbers values. A data set can be stored into different systems: a database, an excel file, in the memory of an app. or into a lot of other different systems. The good news is that in Dashbuilder there exist an standard way to define a data set, regardless where the data set is stored.<br />
<br />
<h3>
<b>Data set definitions</b></h3>
<br />
Every time we want to provide access to a given external data, a data set definition has to be deployed. That definition contains information about:<br />
<ul>
<li>where the data set is stored, </li>
<li>how can be accessed, read and/or parsed, and</li>
<li>what columns contains and of which type.</li>
</ul>
<div>
<br /></div>
<div>
Let's take for instance the following data set definition:</div>
<div>
<br /></div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEheTHPmyLqcuhmhXWZ-YD6rY5xJAKFKjL1PqRFndxKgIbZRzXsYpIynmZRzNipNBoHKxNLCOslXtJiaMKUKy6xqfN4rJmcWPhJDWX_PcHLLgKOEoFyHbf5HQcIwVYhOzVC4DcLMs6xao58/s1600/csvdatasetdef.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img alt="CSV data set definition example" border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEheTHPmyLqcuhmhXWZ-YD6rY5xJAKFKjL1PqRFndxKgIbZRzXsYpIynmZRzNipNBoHKxNLCOslXtJiaMKUKy6xqfN4rJmcWPhJDWX_PcHLLgKOEoFyHbf5HQcIwVYhOzVC4DcLMs6xao58/s1600/csvdatasetdef.png" title="CSV data set definition example" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">CSV data set definition example</td></tr>
</tbody></table>
<div>
<br /></div>
<div>
The definition is a JSON document containing the following properties:</div>
<div>
<ul>
<li><b><i>uuid</i></b>: A unique universal identifier. </li>
</ul>
<ul>
<li><b><i>provider</i></b>: The method used to get access to the data set. Depending on the selected method a set of extra properties need to be provided, For instance, the <i>filePath</i> is needed in CSV along with <i>separatorChar</i>, <i>quoteChar</i> and <i>escapeChar</i>, in order to parse & read the CSV file. </li>
</ul>
<div>
At the time of this writing we support the following providers:</div>
<ul><ul>
<li><b><i>CSV</i></b>, for accessing data stored in comma-separated-value files.</li>
<li><b><i>SQL</i></b>, for getting data from relational databases through SQL queries.</li>
<li><b><i>BEAN</i></b>, a Java bean interface for generating data sets directly from Java. </li>
<li><b><i>ELASTICSEARCH</i></b>, for querying documents stored into Elastic Search indexes.</li>
</ul>
</ul>
<ul>
<li><b><i>isPublic</i></b>: if set to true means that it can be accessed from the UI editors by anyone with the right permissions. </li>
</ul>
<ul>
<li><b><i>columns</i></b>: this section is used to define which are the data columns we want to be part of the data set, including their type and format. Columns not defined here will be considered as non-existing even if they are part of the data stored. There exist 4 types available:</li>
</ul>
<ul><ul>
<li><i>date</i>: for date-time values.</li>
<li><i>number</i>: for numeric values.</li>
<li><i>label:</i> for text context that can be categorized.</li>
<li><i>text:</i> for non-categorizable text content (more info at the <i>Data set lookups</i> section).</li>
</ul>
</ul>
<ul>
<li><b><i>pushEnabled</i></b></li>
<li><b><i>pushMaxSize</i></b></li>
<li><b><i>refreshTime</i></b></li>
<li><b><i>refreshAlways</i></b>: this 4 properties are related to the caching & refresh mechanisms. Will talk about that later on in the <i>Caching & Refresh</i> section.</li>
</ul>
<div>
All the properties listed above are common to all the providers, regardless of its type. Let's take a look at some other data set definition examples:</div>
<div>
<br /></div>
<div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhTzLdLaYNT_Oifk4A6gKlIEnrPZg5VQN6NK9qW0d60HLTqsCFKOGoNHqnwarlWaYm7Mw6UX7GS4LDtUZerwwOaYQEut8ag1oTZUaKE4o2XGu_oyGy_hSvSqiM1Fh9N1geuKbyPVfWFVHo/s1600/sqldatasetdef.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhTzLdLaYNT_Oifk4A6gKlIEnrPZg5VQN6NK9qW0d60HLTqsCFKOGoNHqnwarlWaYm7Mw6UX7GS4LDtUZerwwOaYQEut8ag1oTZUaKE4o2XGu_oyGy_hSvSqiM1Fh9N1geuKbyPVfWFVHo/s1600/sqldatasetdef.png" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">SQL data set definition </td></tr>
</tbody></table>
For SQL data sets you need to specify an existing app. server <i>dataSource</i>, the <i>dbSchema</i> (optional) and the <i>dbSQL</i> used to get the data. As you can see the <i>allColumnsEnabled</i> is specific and tells the provider that we want to consider all the columns in the SQL as part of the data set. As for the column types they will be inferred from the database metadata. If we want to override an existing column definition we can still define a <i>columns</i> section as in the CSV example.</div>
<div>
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEipUR1-9jBy-Q6W-MLR3SS3SarDRSNSKyufvtN09SXUQYLnpGqFo9xJNdEB1AXyvliloceR3UkK4eabofTFWgyZ5Bp2cfwl8XMlDLJI_AtZu45ERgM7aBq5wMpJrt3z_hGMEfAvHea6Kfo/s1600/beandatasetdef.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEipUR1-9jBy-Q6W-MLR3SS3SarDRSNSKyufvtN09SXUQYLnpGqFo9xJNdEB1AXyvliloceR3UkK4eabofTFWgyZ5Bp2cfwl8XMlDLJI_AtZu45ERgM7aBq5wMpJrt3z_hGMEfAvHea6Kfo/s1600/beandatasetdef.png" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Java Bean generated data set definition</td></tr>
</tbody></table>
</div>
</div>
<br />
The Java Bean provider is an extension mechanism that allows to delegate into a Java class the data set generation. In this case we only have to specify a fully qualified class name plus an optional set of parameters that will be passed to the Java Bean.<br />
<div>
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh0JsyFPuE9hKX6RKkEo7R8RyLsc8iC4LfEInFGzC8Oq7-cR7by1w7KpDD_kFCHzaSfE0y1KUkCZg25wZL92dM-yJWc6_NMAhHnqVtexjGn9fslHtWt9SEPcGAvM3bfhIzJoUc8ikw1zXg/s1600/elsdatasetdef.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh0JsyFPuE9hKX6RKkEo7R8RyLsc8iC4LfEInFGzC8Oq7-cR7by1w7KpDD_kFCHzaSfE0y1KUkCZg25wZL92dM-yJWc6_NMAhHnqVtexjGn9fslHtWt9SEPcGAvM3bfhIzJoUc8ikw1zXg/s1600/elsdatasetdef.png" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Elastic Search data set definition</td></tr>
</tbody></table>
The Elastic Search provider is a very good example of integration with a nonSQL storage. The columns <i>serverURL</i>, <i>clusterName</i>, <i>index</i> and <i>type</i> are specific and tells the provider what concrete Elastic Search index and document type this data set defines.<br />
<h4>
</h4>
<h4>
</h4>
<h4>
</h4>
<h3>
</h3>
<h3>
<br /></h3>
<h3>
Data set deployment</h3>
<br />
As we've seen so far, Dashbuilder supports several data set types, and it offers a common mechanism for defining such data sets. Once a data set is defined it needs to be deployed, otherwise it won't be accessible to the Dashbuilder modules.<br />
<br />
Dashbuilder is delivered as a web application archive (WAR file). Inside this WAR file there exists a directory called <i>dashbuilder.war/WEB-INF/datasets</i> containing all the data set definitions. Deploying a new data set it's as easy as creating a <i>.dset </i>file containing our JSON definition and copying that file to the deployment directory. Once detected, the data set definition will be loaded and registered automatically in the Dashbuilder data set registry. Changes made to the deployed files will be also detected. When this happens, the entire data set definition is reloaded and any cached data is removed (see the <i>Refresh & cache </i>section below).<br />
<div>
<br /></div>
<div>
The following video, shows a live demo of how to deploy a data set at runtime and how the dashboards can get access to it automatically.<br />
<span style="text-align: center;"><br /></span>
<br />
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen="" class="YOUTUBE-iframe-video" data-thumbnail-src="https://i.ytimg.com/vi/ZcJWobZqp00/0.jpg" frameborder="0" height="266" src="http://www.youtube.com/embed/ZcJWobZqp00?feature=player_embedded" width="320"></iframe></div>
<span style="text-align: center;"><br /></span><span style="text-align: center;"><span style="text-align: start;"> The process described is more intended for technical people. In the next few weeks though, we will be working on a new feature for allowing the end users to edit & deploy its data sets from the UI, the Data Set Editor. We also plan for storing the data sets definitions into GIT repositories through the Uberfire's VFS service as well, to make it easier to share and move data sets between installations.</span></span>
<br />
<span style="text-align: center;"><span style="text-align: start;"><br /></span></span>
<br />
<h3>
<span style="text-align: center;">Data set lookups </span></h3>
</div>
<br />
So far so good. The next question is: how the charts in a dashboard get the data they need? Well, once a data set is deployed is ready for receiving <i>lookup requests</i>. For instance:<br />
<br />
<ul>
<li>Get the total amount of expenses by department</li>
<li>Get the outstanding sales till the end of this year, grouped by office</li>
<li>Get the orders received in the last 5 minutes</li>
<li>Get the travel expenses by employee, only from the sales department </li>
<li>Get the sales pipeline expected for the next few years </li>
</ul>
<div>
<br />
As you can see, a <i>data set lookup request</i> is basically a query over an existing data set, but with some constraints. To be more specific, a <i>lookup request</i> is a sequence of data manipulation operations which produce a resulting data set. The set of operations supported are:</div>
<div>
<ul>
<li><b>filter</b>: to get a subset of the whole data set by means of specifying constraints on one or multiple data set columns.</li>
</ul>
<ul>
<li><b>group</b>: to categorize the whole data sets into groups. LABEL and DATE are the only supported column types. </li>
</ul>
<ul>
<li><b>sort</b>: to sort the resulting data set by one or multiple columns.</li>
</ul>
<ul>
<li><b>trim</b>: To limit the maximum number of rows the resulting data set must have.</li>
</ul>
</div>
<br />
A lookup request takes an input data set and produces a resulting data set. As illustrated in the following diagram:<br />
<div>
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-l-Ykcn3Cv8VwGMearT9R62zgerbQNyypExkBB1t_Hozp8gqBSexhi0Q8q-9NnyhAw6ITKd03g3NxsRbqL6jmA9whv4mMkhjXIKW0GYY_gZGlK1V9XKpk0Hpz7XI9mVIiszEZq4_bUGg/s1600/DataSet+lookup+request.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-l-Ykcn3Cv8VwGMearT9R62zgerbQNyypExkBB1t_Hozp8gqBSexhi0Q8q-9NnyhAw6ITKd03g3NxsRbqL6jmA9whv4mMkhjXIKW0GYY_gZGlK1V9XKpk0Hpz7XI9mVIiszEZq4_bUGg/s1600/DataSet+lookup+request.png" height="569" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Data set lookup request</td></tr>
</tbody></table>
<br />
<div>
So the way to express some of the examples above as a lookup request is as follows: </div>
<div>
<ul>
<li>Get the total amount of expenses by department</li>
</ul>
<div>
<i> .dataset("expenses")</i></div>
<div>
<i> .group("department")</i></div>
<div>
<i> .column("department")</i></div>
<div>
<i> .column("amount", "sum")</i></div>
<ul>
<li>Get the outstanding sales till the end of this year, grouped by office</li>
</ul>
<div>
<div>
<i> .dataset("expenses")</i></div>
<div>
<i> .filter("date", timeFrame("now till end[year]"))</i></div>
<div>
<i> .group("office")</i></div>
<div>
<i> .column("office")</i></div>
<div>
<i> .column("expectedAmount", "sum")</i></div>
</div>
<ul>
<li>Get the travel expenses by employee, only from the sales department </li>
</ul>
<div>
<div>
<div>
<i> .dataset("expenses")</i></div>
<div>
<i> .filter("department", equalsTo("sales"))</i></div>
<div>
<i> .group("employee")</i></div>
<div>
<i> .column("</i><i>employee</i><i>")</i></div>
<div>
<i> .column("amount", "sum")</i></div>
</div>
<ul></ul>
</div>
</div>
<div>
</div>
<br />
How this lookup requests relates to the displayers/charts in the UI? The answer is that every displayer, no matter whether is a chart, a table or a selector, performs a lookup request in order to retrieve the data required. Obviously, the set of operations in the lookup request varies depending on the chart type. For instance, a pie chart feeds from a two column data set where the first column is usually the result of a group operation, whereas a table displayer can feed both from grouped and non-grouped data sets and they also permits a variable number of columns in the resulting data set.<br />
<br />
For those interested in the internals or just want to see how the Dataset API looks like, I recommend taking a look at the different <a href="https://github.com/dashbuilder/dashbuilder/tree/master/dashbuilder-backend/dashbuilder-dataset-core/src/test/java/org/dashbuilder/dataset" target="_blank">test cases </a>existing on GitHub.<br />
<br />
Using the <i>Displayer Editor</i> users can configure all the data retrieval settings, as shown in the next screenshot.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div>
<table cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh4wQXoa7NqxTG8nsshB5I5EdQNARn9mAKp3SMoVeqjk2AeiOHxxGF6vD2MlaxYTLpaa6K2sDOH8W57sFdBrkA1o1hIPTQ5zxgp7LZQZBTxPaSxR4IfRxVefHiOhmMGFhlSTmL4oGdpW9M/s1600/editDisplayer.png" imageanchor="1" style="clear: right; margin-bottom: 1em; margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh4wQXoa7NqxTG8nsshB5I5EdQNARn9mAKp3SMoVeqjk2AeiOHxxGF6vD2MlaxYTLpaa6K2sDOH8W57sFdBrkA1o1hIPTQ5zxgp7LZQZBTxPaSxR4IfRxVefHiOhmMGFhlSTmL4oGdpW9M/s1600/editDisplayer.png" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Displayer Editor UI</td></tr>
</tbody></table>
<br />
<br />
From this editor, users can define the lookup's filter, group, and sort operations as well as configuring the resulting data set columns. The editor is adaptable, than means that the available settings varies depending on the displayer type selected. Actually, what the application is doing behind the scenes is building and executing a single lookup request over the selected data set.<br />
<br /></div>
<h3>
Data providers</h3>
<div>
<br />
<br /></div>
So far, we have learned how to define, deploy and perform data lookup requests on a given data set. Now we're going to go a little deeper in order to describe how the Dashbuilder core deals with the processing of data set lookup requests.<br />
<br />
As we described before, every data set definition is linked to a provider: CSV, SQL, BEAN or ELASTICSEARCH. Each data set lookup request is delegated to the proper data provider implementation which is responsible for resolving the request. In case of an SQL dataset, the lookup request is transformed into an SQL query which contains all the lookup's filter, group and sort operations. Thanks to the existing provider interface, Dashbuilder does not have to take care about the lookup request resolution. We can start with a CSV data set definition and move our data to a relational database later on and all our implementations on top of such data set won't break, this includes the dashboards we build and any other client implementations we might have.<br />
<br />
The next diagram shows the internal pieces of the Dashbuilder's Data Set Subsystem. Every lookup request received is processed following these steps:<br />
<br />
<ol>
<li>Get the data set definition the lookup request is referring to.</li>
<li>Get the provider implementation the data set is linked to.</li>
<li>Delegate into the provider the processing of the lookup request. </li>
</ol>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
</div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiCFwhXghyXniEmoLkmBWQSIoYC-L1yipu4_0S6HVKsZ3NAtSiXGJ6YaTvYk2YhBsVnG_ZAQDoQDmnpKRgp2ZHSC_f0emjYTqI9vzYhnQqiOSBUaTV0pnNpfbJEPMPnvp45QfYhS3PfzpI/s1600/DataSetRegistry+arch.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiCFwhXghyXniEmoLkmBWQSIoYC-L1yipu4_0S6HVKsZ3NAtSiXGJ6YaTvYk2YhBsVnG_ZAQDoQDmnpKRgp2ZHSC_f0emjYTqI9vzYhnQqiOSBUaTV0pnNpfbJEPMPnvp45QfYhS3PfzpI/s1600/DataSetRegistry+arch.png" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Data Set Subsystem Architecture</td></tr>
</tbody></table>
<h4>
<span style="font-weight: normal;"> </span></h4>
<h4>
<span style="font-weight: normal;"> In the diagram, we can see the <i>DataSetDeployer</i> component which looks for data set deployments & updates. There also exists an especial type of provider called <i>StaticProvider </i>which holds and resolves lookup requests in memory. Unlike the SQL or ELS providers which execute queries against the external data storage, the CSV and BEAN providers are not query processing engines. So what they actually do is to read/generate and register the whole data set into the static (in-memory) provider. This is specially helpful for small data set use cases. For big data scenarios you should definitely consider using an SQL or ELS provider. </span></h4>
<h4>
<span style="font-weight: normal;"> When the first lookup request over a CSV data set is requested, the <i>CSVProvider</i> loads, registers and </span><span style="font-weight: normal;">delegates</span><span style="font-weight: normal;"> into the </span><i style="font-weight: normal;">StaticProvider</i><span style="font-weight: normal;"> the lookup request processing. So the CSV and BEAN providers are just data set loaders since the real processing is carried out by the static provider. The static provider relies on a data set operation engine implementation capable of resolving a sequence of filter, group and sort operations over a data set (further details in the next section).</span></h4>
<div>
<span style="font-weight: normal;"><br /></span></div>
<h3>
Caching & Refresh</h3>
<br />
In the beginning of this article we stated that a data set definition may contain four extra properties:<br />
<br />
<ul>
<li><i>pushEnabled (<i>false by </i>default )</i></li>
<li><i>pushMaxSize </i><i>(<i>1024Kb by </i>default )</i></li>
<li><i>refreshTime (-1=disabled by default)</i></li>
<li><i>refreshAlways </i><i>(<i>false by </i>default )</i></li>
</ul>
<div>
<br />
All of them are related with the caching & refresh mechanisms. Let's take a look at the following diagram which depicts the Dashbuilder's client/server architecture. </div>
<div>
<br /></div>
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh30IbXEft2G48ZUumdsS8ClaDZ_FHwf4Dt7cOpMRGYHZ7kYR5uzyfbNLLKaVKk_zYg646wnUmpqBycKL1JtIyer91P4uN90U957U7JuhqSprJx0S2RMUM4B-x3GS4_i9V-bIqZwWlxmlY/s1600/DataSet+push.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh30IbXEft2G48ZUumdsS8ClaDZ_FHwf4Dt7cOpMRGYHZ7kYR5uzyfbNLLKaVKk_zYg646wnUmpqBycKL1JtIyer91P4uN90U957U7JuhqSprJx0S2RMUM4B-x3GS4_i9V-bIqZwWlxmlY/s1600/DataSet+push.png" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Client/Server Architecture </td></tr>
</tbody></table>
<br />
<div>
Imagine we have an end user interacting with a dashboard. Let's see what happens when a chart issues a data set lookup request:</div>
<div>
<i><br /></i></div>
<div>
1. The <i>DataSetClientServices</i> class receives the request and </div>
<div>
2. <i>...</i> asks the server for the data set metadata which contains the data set definition, size, ... </div>
<div>
<br /></div>
<div>
If "<i>pushEnabled=true" a</i>n<i>d "pushMaxSize<dataSetSize" </i>then,</div>
<div>
<br /></div>
<div>
3. The whole data set is pushed to the browser. </div>
<div>
4. The data set is registered into the <i>ClientDataSetManager</i>.</div>
<div>
5. Finally, the initial (and the subsequent) data set lookup request is processed on the client.</div>
<div>
<br /></div>
<div>
If "<i>pushEnabled=false" </i>or<i> "</i><i>pushMaxSize </i>is not<i> < dataSetSize" </i>then the lookup requests is always processed in the backend. </div>
<br />
The push mechanism allows for uploading an entire data set to the user's browser. It applies to any kind of data set, no matter what is the provider type. It's a kind of browser caching mechanism. The main motivations behind this mechanism are the following:<br />
<br />
<ul>
<li>Improve the performance. Once a data set is loaded all the data set group, filter sort operations performed issued from the UI are resolved without any further calls to the backend.</li>
</ul>
<ul>
<li>Support a pure lightweight client approach. The whole Dashbuilder UI components could be used without the need of the backend layer. Data sets can be registered through calls to the <i>ClientDataSetManager</i> and all the lookup requests will be resolved at a client side. Obviously, this approach is not suitable for large data sets.</li>
</ul>
<br />
<br />
The <i>DataSetManager</i> interface is the main entry point for any data set access operation, including the lookup requests. As shown in the diagram, there exists two implementations of the <i>DataSetManager</i> interface, one in GWT and a server implementation in pure Java. Both depend on the<i> DataSetOpEngine,</i> which is a GWT shared implementation that can run on both client & server, this makes possible the ability to process lookup requests in the client side.<br />
<br />
<br />
So far, so good. However, what if a data set is pushed and the source data is updated? or, for instance, what if a CSV file changes or if a new document is added to an Elastic Search index? Here is when the two remain settings <i>refreshTime</i> & <i>refreshAlways </i> comes into action. <br />
<br />
<br />
Imagine a database which is updated every night. If we want to get the most updated data then we must set "<i>refreshTime=1day"</i> and<i> "refreshAlways=true"</i>. On the contrary, if our data changes every now and then then we must set "<i>refreshAlways=false"</i> which means that the system will ask the database (once a day) whether the data set is outdated before invalidating the current data set.<br />
<br />
For SQL/ELS data sets , it makes no sense to set the refresh settings if push is disabled, since all the lookup requests will always be executed against the external storage. Otherwise, for CSV/BEAN it always makes sense, since the contents of the data sets are always loaded and cached in the backend.<br />
<br />
For every data set with refresh enabled, an invalidation task is registered into the Scheduler component, as shown in the diagram above. When the refresh interval is reached, the task is executed, a <i>DataSetStaleEvent </i>is fired and any data set cached data (both on the client & backend) is removed.<br />
<br />
From the UI perspective we can control in detail when we want a chart to get refreshed. The refresh settings are located in the <i>Displayer Editor > Display tab > Refresh</i> category. One option is to refresh every time a <i>DataSetStaleEvent </i>is received. Another option is to force to refresh every N seconds. This last option is more suitable for real-time use cases.<br />
<br />
To sum up, if we know our data is going to change and if we want our dashboards to be notified on every update we must enable the refresh settings. Optionally, if we want to improve our dashboard performance then we can go for enabling the data push feature, but only if our data set is small enough.<br />
<br />
In next articles we will talk about real-time dashboards, how to build them and how to integrate Dashbuilder with a non SQL storage like Elastic Search. Stay tuned!<br />
<br />
<br /></div>
Unknownnoreply@blogger.com1tag:blogger.com,1999:blog-4358594258656726438.post-1924814518038861122015-01-23T10:57:00.000+01:002015-01-23T10:57:00.215+01:00Dashbuilder Overview<span style="background-color: #fdfdfd; color: #333333; font-family: monospace; font-size: 13.600000381469727px;">For those of you who would like to learn more about Dashbuilder, Jan Hrcek QE Engineer at RedHat, published an <a href="http://css.dzone.com/articles/business-activity-monitoring" target="_blank">article</a> on DZone. </span><span style="background-color: #fdfdfd; color: #333333; font-family: monospace; font-size: 13.600000381469727px;">The article gives a conceptual overview of the application and presents its main features. </span><br />
<span style="background-color: #fdfdfd; color: #333333; font-family: monospace; font-size: 13.600000381469727px;"><br /></span>
<span style="background-color: #fdfdfd; color: #333333; font-family: monospace; font-size: 13.600000381469727px;">Thanks Jan for this contribution! </span>Unknownnoreply@blogger.com1tag:blogger.com,1999:blog-4358594258656726438.post-60071163669644922652014-12-19T11:10:00.005+01:002014-12-19T16:42:31.081+01:00Using filtered SQL queries for building big data dashboards<br />
<div align="JUSTIFY" style="line-height: d%; margin-bottom: 0in;">
<span style="font-family: inherit;"><span style="font-size: x-small;"> </span>Dashbuilder
is a tool I like to describe as a “micro” BI. It lets the user
create dashboards and showcase their data using pie, bar or line
charts as well as display data in a tabular form. Data could be
loaded from plain text like CSV files or query from a database
connection. When data is small enough, Dashbuilder can handle pretty
well the whole set in memory as far as it doesn't exceed the 2MB size
limit. However, most of the time, our data sets are bigger and we
can't upload all the data for Dashbuilder to handle it by its own. Is
in these cases where database backed queries can help us to implement
nice drill down reports and charts without preloading all the data.
</span></div>
<div align="JUSTIFY" style="line-height: d%; margin-bottom: 0in;">
<span style="font-family: inherit;"><br /></span></div>
<div align="JUSTIFY" style="line-height: d%; margin-bottom: 0in;">
<span style="font-family: inherit;"> Let's take as an example a very simple <i>stock exchange dashboard</i> which is fed from two database tables:</span></div>
<div align="JUSTIFY" style="line-height: d%; margin-bottom: 0in;">
<span style="font-family: inherit;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEivcujm8npnGGD0uk2w4UmRLTDPdERS2iAGP1RlNGf4NA_v8RkZ7CJNjjVGQCOKRVZj-4-yBUzQswlUb0NoDUoOfT4F5XvftE5DtzIGnUb1vYqKpVv5lDh5mrpMFJyglmznY1_QStlhJR4/s1600/stocktrade_dbtables.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><span style="font-family: inherit;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEivcujm8npnGGD0uk2w4UmRLTDPdERS2iAGP1RlNGf4NA_v8RkZ7CJNjjVGQCOKRVZj-4-yBUzQswlUb0NoDUoOfT4F5XvftE5DtzIGnUb1vYqKpVv5lDh5mrpMFJyglmznY1_QStlhJR4/s1600/stocktrade_dbtables.png" height="141" width="320" /></span></a></div>
<div align="JUSTIFY" style="line-height: d%; margin-bottom: 0in;">
<span style="font-family: inherit;"><br /></span></div>
<div align="JUSTIFY" style="line-height: d%; margin-bottom: 0in;">
<span style="font-family: inherit;"> The dashboard displays some indicators about several companies from several countries selling their shares at a given price on every day closing date. The dashboard displays 4 KPIs (Key Performance Indicators) as you can see in the following screenshot: </span></div>
<div align="JUSTIFY" style="line-height: d%; margin-bottom: 0in;">
<span style="font-family: inherit;"><br /></span></div>
<div align="JUSTIFY" style="line-height: d%; margin-bottom: 0in;">
<div class="separator" style="clear: both; text-align: center;">
</div>
<span style="font-family: inherit;"><br /></span></div>
<div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgVNs5uJ_dcKXUpFSJjAoCqbfDfO3D-_qNKKM-_HyHP5smavM35YFrdyui7wd-_31Mv-5Y4gXRTcXfohlW6dJx7bppTE44FbUOulGbUxgfT2Tr_0joHlCHOrb5CBUaQqA4JS8MklN4O9_k/s1600/StockTradeDashboard.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><span style="font-family: inherit;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgVNs5uJ_dcKXUpFSJjAoCqbfDfO3D-_qNKKM-_HyHP5smavM35YFrdyui7wd-_31Mv-5Y4gXRTcXfohlW6dJx7bppTE44FbUOulGbUxgfT2Tr_0joHlCHOrb5CBUaQqA4JS8MklN4O9_k/s1600/StockTradeDashboard.png" height="229" width="320" /></span></a></div>
<span style="font-family: inherit;"><br /></span></div>
<div align="JUSTIFY" style="line-height: d%; margin-bottom: 0in;">
<span style="font-family: inherit;"> All the indicators are displaying data coming from the two database tables defined above.</span><br />
<span style="font-family: inherit;"><br />
</span><br />
<ul>
<li><span style="font-family: inherit;">Bar chart - Average price per company</span></li>
<li><span style="font-family: inherit;">Area chart - Sales price evolution</span></li>
<li><span style="font-family: inherit;">Pie chart - Companies per country</span></li>
<li><span style="font-family: inherit;">Table report - Stock prices at closing date </span></li>
</ul>
<div>
<span style="font-family: inherit;"><br /></span>
<span style="font-family: inherit;"> At the end of this article [1] you'll find detailed instructions about how to download and install this example dashboard. What we're going to start discussing next is the two strategies we can use for building a dashboard. This is an important aspect to consider, specially if we're facing big data scenarios.</span></div>
</div>
<h2 style="line-height: d%; margin-bottom: 0in;">
<span style="font-family: inherit; font-size: small;"><b><br /></b></span></h2>
<h2 style="line-height: d%; margin-bottom: 0in;">
<span style="font-family: inherit; font-size: small;"><b>The <i>in-memo</i></b><b><i>ry</i> strategy</b></span></h2>
<div align="JUSTIFY" style="line-height: d%; margin-bottom: 0in;">
<span style="font-family: inherit;"><br /></span>
<span style="font-family: inherit;"> This strategy consists in creating a data provider which load all the data set rows by executing a single SQL query over the two tables. </span></div>
<div align="JUSTIFY" style="line-height: d%; margin-bottom: 0in;">
<span style="font-family: inherit;"><br /></span></div>
<div align="JUSTIFY" style="line-height: d%; margin-bottom: 0in;">
<span style="font-family: inherit;"> </span><span style="font-family: Courier New, Courier, monospace;"> SELECT C.NAME, C.COUNTRY, S.PRICE_PER_SHARE, S.CLOSING_DATE</span></div>
<div align="JUSTIFY" style="line-height: d%; margin-bottom: 0in;">
</div>
<div align="JUSTIFY" style="line-height: d%; margin-bottom: 0in;">
<span style="font-family: Courier New, Courier, monospace;"> FROM COMPANY C JOIN STOCK S ON (C.ID=S.ID_COMPANY)</span></div>
<div align="JUSTIFY" style="line-height: d%; margin-bottom: 0in;">
<span style="font-family: inherit;"><br /></span></div>
<div align="JUSTIFY" style="line-height: d%; margin-bottom: 0in;">
<span style="font-family: inherit;"> Every single indicator on the dashboard will consume the same data set. When filters are executed from the UI no further SQLs are executed since all the calculations are done over the data set in memory. The following video shows a browser window and a bash console showing that only a single SQL is executed when the dashboard is initialized.</span><br />
<span style="font-family: inherit;"><br /></span></div>
<div align="JUSTIFY" style="line-height: d%; margin-bottom: 0in;">
<span style="font-family: inherit;"><br /></span></div>
<div align="JUSTIFY" style="line-height: d%; margin-bottom: 0in;">
<div class="separator" style="clear: both; text-align: center;">
<span style="font-family: inherit;"><br /></span></div>
<div style="text-align: center;">
<span style="font-family: inherit;"><iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.youtube.com/embed/vFEZS70U53o?feature=player_embedded' frameborder='0'></iframe></span></div>
<div style="text-align: center;">
<span style="font-family: inherit;"><br /></span></div>
</div>
<div align="JUSTIFY" style="line-height: d%; margin-bottom: 0in;">
<span style="font-family: inherit;"><br /></span></div>
<div align="JUSTIFY" style="line-height: d%; margin-bottom: 0in;">
<span style="font-family: inherit;"> Pros:</span></div>
<div align="JUSTIFY" style="line-height: d%; margin-bottom: 0in;">
</div>
<ul>
<li><span style="font-family: inherit;">Data retrieval logic keeps very simple</span></li>
<li><span style="font-family: inherit;">Only a single data provider is needed</span></li>
<li><span style="font-family: inherit;">Faster configuration of KPIs since all the data set properties are available at design time</span></li>
<li><span style="font-family: inherit;">Multiple indicators from a single data provider</span></li>
</ul>
<div>
<span style="font-family: inherit;"> Cons:</span></div>
<div>
<ul>
<li><span style="font-family: inherit;">Can't be applied on medium/large data sets due to poor performance</span></li>
</ul>
</div>
<h2 style="line-height: d%; margin-bottom: 0in;">
<span style="font-family: inherit; font-size: small;"><br /></span></h2>
<h2 style="line-height: d%; margin-bottom: 0in;">
<span style="font-family: inherit; font-size: small;">The <i>native</i> strategy</span></h2>
<div>
<span style="font-family: inherit;"><br /></span></div>
<div>
<span style="font-family: inherit;"> The native approach consists in having a data provider for every indicator in the dashboard. instead of loading an handling all the data set in memory. Every KPI is told what data has to display. The next video shows a full SQL based version of the sales stock dashboard. As you can see, every time the user filters on the dashboard, some SQL queries are executed. No data is hold in memory, the dashboard is always asking the DB for the data.</span></div>
<div>
<span style="font-family: inherit;"><br /></span></div>
<div>
<div class="separator" style="clear: both; text-align: center;">
<span style="font-family: inherit;"><iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.youtube.com/embed/CeCTjbJn-lw?feature=player_embedded' frameborder='0'></iframe></span></div>
<span style="font-family: inherit;"><br /></span></div>
<div>
<span style="font-family: inherit;"><br /></span></div>
<div>
<span style="font-family: inherit;"><span style="text-align: justify;"> As you can see, on every filter request the SQLs are parsed, injected with the filter values and re-executed. The SQL data providers are the following</span><span style="text-align: justify;">:</span></span></div>
<div>
<span style="font-family: inherit;"><br /></span></div>
<div>
<span style="font-family: inherit;"><span style="text-align: justify;"> </span><span style="text-align: justify;"> </span><u>Bar chart - Average price per company</u></span></div>
<div>
<span style="font-family: inherit;"><br /></span></div>
<div>
<div>
<span style="font-family: inherit;"> </span><span style="font-family: Courier New, Courier, monospace;">SELECT C.NAME, AVG(S.PRICE_PER_SHARE)</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> FROM COMPANY C JOIN STOCK S ON (C.ID=S.ID_COMPANY)</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> WHERE <i>{sql_condition, optional, c.country, country}</i></span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> AND <i>{sql_condition, optional, c.name, name}</i></span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> GROUP BY C.NAME</span></div>
<div>
<span style="font-family: inherit;"><br /></span></div>
</div>
<div>
<span style="font-family: inherit;"><span style="text-align: justify;"> </span><span style="text-align: justify;"> </span><u>Area chart - Sales price evolution</u></span></div>
<div>
<span style="font-family: inherit;"><br /></span></div>
<div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> SELECT S.CLOSING_DATE, AVG(S.PRICE_PER_SHARE)</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> FROM COMPANY C JOIN STOCK S ON (C.ID=S.ID_COMPANY)</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> WHERE <i>{sql_condition, optional, c.country, country}</i></span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> AND <i>{sql_condition, optional, c.name, name}</i></span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> GROUP BY CLOSING_DATE</span></div>
</div>
<div>
<span style="font-family: inherit;"><br /></span></div>
<div>
<span style="font-family: inherit;"><span style="text-align: justify;"> </span><span style="text-align: justify;"> </span><u>Pie chart - Companies per country</u></span></div>
<div>
<span style="font-family: inherit;"><br /></span></div>
<div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> SELECT COUNTRY, COUNT(ID)</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> FROM COMPANY</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> WHERE <i>{sql_condition, optional, country, country}</i></span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> AND <i>{sql_condition, optional, name, name}</i></span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> GROUP BY COUNTRY</span></div>
</div>
<div>
<span style="font-family: inherit;"><br /></span></div>
<div>
<span style="font-family: inherit;"><span style="text-align: justify;"> </span><span style="text-align: justify;"> </span><u>Table report</u></span></div>
<div>
<span style="font-family: inherit;"><br /></span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"> SELECT C.NAME, C.COUNTRY, S.PRICE_PER_SHARE, S.CLOSING_DATE<br /> FROM COMPANY C JOIN STOCK S ON (C.ID=S.ID_COMPANY)<br /> WHERE <i>{sql_condition, optional, c.country, country}</i><br /> AND <i>{sql_condition, optional, c.name, name}</i></span></div>
<div align="JUSTIFY" style="line-height: d%; margin-bottom: 0in;">
<span style="font-family: inherit;"><br /></span></div>
<div align="JUSTIFY" style="line-height: d%; margin-bottom: 0in;">
<span style="font-family: inherit;"><br /></span></div>
<div align="JUSTIFY" style="line-height: d%; margin-bottom: 0in;">
<span style="font-family: inherit;"> As you can see every KPI is delegating the filter & group by operations to the database. The filter magic happens thanks to the <b>{sql_condition}</b> statements. Every time a filter occurs in the UI the dashbuilder core gets all the SQL data providers referenced by the KPIs and it parses/injects into those SQLs the current filter selections made by the user. The signature of the<i> sql_condition </i>clause is the following:</span></div>
<div align="JUSTIFY" style="line-height: d%; margin-bottom: 0in;">
<span style="font-family: inherit;"><br /></span></div>
<div align="JUSTIFY" style="line-height: d%; margin-bottom: 0in;">
<span style="font-family: inherit;"><i> {sql_condition, [optional | required], [db column], [filter property]} </i>where:</span><br />
<span style="font-family: inherit;"><br /></span></div>
<ul>
<li><span style="font-family: inherit;"><b>optional</b>: if no filter exists for the given property then the condition is ignored. </span></li>
<li><span style="font-family: inherit;"><b>required</b>: if no filter is present then the SQL returns no data.</span></li>
<li><span style="font-family: inherit;"><b>db column</b>: the db column where the current filter is applied.</span></li>
<li><span style="font-family: inherit;"><b>filter property</b>: the UI property which selected values are taken. </span></li>
</ul>
<div style="text-align: justify;">
<span style="font-family: inherit;"><br /></span>
<span style="font-family: inherit;"> Pros:</span></div>
<div style="text-align: justify;">
</div>
<ul>
<li><span style="font-family: inherit;">Support for high volumes of data. The database tables need to be properly indexed though.</span></li>
</ul>
<div>
<span style="font-family: inherit;"> Cons:</span></div>
<div>
<ul>
<li><span style="font-family: inherit;">The set up of the data providers is a little bit more tricky as it requires to create SQL queries with the required filter, group by and sort operations for every KPI.</span></li>
</ul>
</div>
<span style="font-family: inherit;"><br />
When designing a dashboard never forget of thinking thoroughly about the origin, type and the volume of the data we want to display in order to go for the right strategy.</span><br />
<span style="font-family: inherit;"><br />
-----------------------------------------------------------------------------------------------------------</span><br />
<div align="JUSTIFY" style="line-height: d%; margin-bottom: 0in;">
<span style="font-family: inherit;"> </span></div>
<div align="JUSTIFY" style="line-height: d%; margin-bottom: 0in;">
<span style="font-family: inherit;">[1] These are the steps to download an deploy the Stock Trade sample dashboard: </span><br />
<ol>
<li><span style="font-family: inherit;"><a href="https://hudson.jboss.org/hudson/view/Drools%20jBPM/job/dashboard-builder/442/" target="_blank">Download</a> & deploy the Dashbuilder webapp on your favorite app server - <a href="https://github.com/droolsjbpm/dashboard-builder/tree/master/builder" target="_blank">Installation instructions</a>. </span></li>
</ol>
<span style="font-family: inherit;"> (You can also build from </span><a href="https://github.com/droolsjbpm/dashboard-builder" style="font-family: inherit;" target="_blank">sources</a><span style="font-family: inherit;">)</span><br />
<ol>
<li><span style="font-family: inherit;">Extract the contents of the following <a href="https://drive.google.com/open?id=0B9iPuH73LCG9R1BjNVpfdE53Q2M&authuser=0" target="_blank">zip</a> file into <i>dashbuilder.war/WEB-INF/deployments</i> folder</span></li>
<li><span style="font-family: inherit;">Create the stock trade database tables. Use or adapt the H2 script file <i>stocktrade-h2.sql</i> provided.</span></li>
<li><span style="font-family: inherit;">Start the app. The dashboard should be automatically deployed.</span></li>
</ol>
</div>
Unknownnoreply@blogger.com5tag:blogger.com,1999:blog-4358594258656726438.post-31735702363685580192014-08-06T13:38:00.000+02:002014-08-06T17:10:13.261+02:00Dashbuilder 6.1.0 released It's been 7 months after the latest release of Dashbuilder. During this time we've spent most of the time testing the application on other platforms such as WebSphere or WildFly as well as adding several bug fixes. As a result, the current 6.1 is much more stable and offers wider compatibility with other platforms. <br />
<br />
New features added:<br />
<ul>
<li>Support for the WildFly 8.x and WebSphere 8.x application servers</li>
<li>Ability to embed KPIs into third-party applications (as we advanced a few months ago in this <a href="http://dashbuilder.blogspot.com.es/2014/03/embed-kpi-chart-into-your-web-app.html" target="_blank">blog entry</a>)</li>
</ul>
<div>
The links to the release artifacts can be found on the project website <a href="http://dashbuilder.org/" target="_blank">http://dashbuilder.org</a> </div>
<div>
<br /></div>
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-4358594258656726438.post-30585983665332645202014-07-23T12:57:00.000+02:002014-07-23T13:14:11.519+02:00New tabular reports component<div>
<div>
As we mentioned in a previous post (<a href="http://dashbuilder.blogspot.com.es/2014/06/rich-interactive-dashboards-in-uberfire.html" target="_blank">Rich interactive dashboards in uberfire</a>), the data viewer layer is not tied to just one type of visualization technology, but instead supports pluggable renderers. This means that, if so desired, each of the components of a specific dashboard can be configured with it's own specific rendering technology, independently of the renderer its fellows components might use.<br />
On the other hand it's also possible to have only the tables report components, for example, to use a specific table rendering technology, while all the others use the default renderer (which, for now, is the Google Charts Visualization library). This is what we'll illustrate in this blog entry.</div>
<div>
<br /></div>
<div>
Recently we've added a new table visualization component, which in a foreseeable near future will become the default rendering technology for table reports, replacing the previously mentioned Google library for this type of displayers.</div>
<div>
<br /></div>
<div>
So, how do we tell the framework that it should visualize a table using this new renderer? Let's go back to an example from the previous post to illustrate this:</div>
<div>
<br /></div>
<div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjGt7VwowgsiKn1XkQ_6YHyZVPlWHBGG7Th_3f8EVHCpYmyFeVm1tvjIML1rdZ9Swdx89jXmK-ernU1ddP_QoERbeV7zNb35VzNcAAkgOb6h0BtoagiTFPTkhgauQ432kdKE9DeH-URkIk/s1600/salespipeline.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjGt7VwowgsiKn1XkQ_6YHyZVPlWHBGG7Th_3f8EVHCpYmyFeVm1tvjIML1rdZ9Swdx89jXmK-ernU1ddP_QoERbeV7zNb35VzNcAAkgOb6h0BtoagiTFPTkhgauQ432kdKE9DeH-URkIk/s1600/salespipeline.png" height="483" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="font-size: 13px;">The sales pipeline dashboard.</td></tr>
</tbody></table>
<br />
As you can see the 'Sales pipeline' dashboard that is shown in the above image consists of a line chart, a few pie charts, a bar chart, and finally, a table report. The latter is being visualized using the (still) default Google visualization library. Let's check out how the table report of this dashboard is setup:<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg3L4z27v67rTEZIj6OysZZa9txXIMLs0GsDuVp6F2WVg3yjdPWnsBaik5EG991Jphpcm8hLWCWXziv_h8oytacZXY6cY0bD-ez31z1kHYfckmZ_bQAgQIGE0zauTJkobBs7GMvoWz7I6I/s1600/blog_tablesetup1.jpeg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg3L4z27v67rTEZIj6OysZZa9txXIMLs0GsDuVp6F2WVg3yjdPWnsBaik5EG991Jphpcm8hLWCWXziv_h8oytacZXY6cY0bD-ez31z1kHYfckmZ_bQAgQIGE0zauTJkobBs7GMvoWz7I6I/s1600/blog_tablesetup1.jpeg" height="312" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="font-size: 13px;">The table report setup</td></tr>
</tbody></table>
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
As you can see, this is fairly straightforward; through a sequence of API calls we tell the framework to configure a table renderer component, with its title, the default ordering column and sense, the page size, the columns it should display, and the data set it should work with.<br />
<br />
This setup displays the table as it can be seen in the first image, with the default google visualization library. Let's now change this to our new table component. For this to happen we need to adapt the above configuration as follows:<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiReAkBhuYfQXrPqaSRNRlW9HxCb3Q8m9n5AoTJbmzH2WvcAj7urk0VUHJuNLu5ZXhzuHoZlxVQUqi_7jQpCa4RP9SJNOiwA_r9yQLZqRPNBAbgDZie9eXL0wA7guVyhZqZEGOMhMl9EiA/s1600/blog_tablesetup2_renderer.jpeg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiReAkBhuYfQXrPqaSRNRlW9HxCb3Q8m9n5AoTJbmzH2WvcAj7urk0VUHJuNLu5ZXhzuHoZlxVQUqi_7jQpCa4RP9SJNOiwA_r9yQLZqRPNBAbgDZie9eXL0wA7guVyhZqZEGOMhMl9EiA/s1600/blog_tablesetup2_renderer.jpeg" height="325" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="font-size: 13px;">Set a specific renderer</td></tr>
</tbody></table>
<br />
So, it's as simple as adding a call to 'renderer( <rendererID> )', to the component's setup to get the job done and that's that! The result is shown in the image below: </div>
</div>
<div>
<br /></div>
<div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhpXKxBo47mijtY5VUXISQllv6bxzr3cPyD28ph0xhaoa_H0t2TA-GV70DxEqO0F_38Bc6NWyj6vwbRMesM3SbCUwljr0eZA74OUiWZGn9muASq9aSPHZb8yBgI6jcGkvyYiWRnm1mYpvQ/s1600/blog_dbchangedtable.jpeg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhpXKxBo47mijtY5VUXISQllv6bxzr3cPyD28ph0xhaoa_H0t2TA-GV70DxEqO0F_38Bc6NWyj6vwbRMesM3SbCUwljr0eZA74OUiWZGn9muASq9aSPHZb8yBgI6jcGkvyYiWRnm1mYpvQ/s1600/blog_dbchangedtable.jpeg" height="516" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="font-size: 13px;">New table component renderer.</td></tr>
</tbody></table>
As you can see, the table report is now visualized with our new table component. It offers several improvements over the google table renderer:<br />
<br />
<ul>
<li>it's based on a standard widget-set, so no dependency on third party (possibly closed-source) libraries,</li>
<li>the possibility to hide columns through a column selector pop up,</li>
<li>the ability to manually adjust the column widths,</li>
<li>the ability for the table to emit filtering events that occur within it (e.g. someone selects a specific country or product), so that other components can adapt their content accordingly (see also the entry on filtering: <a href="http://dashbuilder.blogspot.com/2014/07/an-introduction-to-displayer-filtering.html" target="_blank">An introduction to displayer filtering</a> )</li>
</ul>
<br />
Below we've included a small screen cast to illustrate some of these features:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.youtube.com/embed/9KQh6Sr3qzE?feature=player_embedded' frameborder='0'></iframe></div>
</div>
Unknownnoreply@blogger.com2tag:blogger.com,1999:blog-4358594258656726438.post-59950346892341916652014-07-22T19:11:00.000+02:002014-07-22T19:11:04.974+02:00An introduction to displayer filtering<div>
One of the most interesting features of interactive dashboards is the fact that they consist of data visualization components that can be made responsive to events that happen within some other data displayer component, which is usually being shown in the same dashboard. Equally important is that data visualization components can be told to notify to others that some kind of 'event' has happened within it, e.g. a data filter event in a pie chart, or some value that was selected inside a table report cell.</div>
<div>
<br /></div>
<div>
So how is this achieved in dashbuilder?</div>
<div>
<br /></div>
<div>
Check out the following example of what could be a sales dashboard:<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjyGXgh5L7AEtKPwEgNyz0rf7MyX1WINvhYf0AHWD5noQhv8AORJpgwFoy-izNVOjMBI-aSd4e4hBXwdnSQ0i7RifkTuxN7NaNkhwaEjXoJ4BuvAk-yuTTocwW8QzM5AZlHI2VdLF78pWU/s1600/dashboard.jpeg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjyGXgh5L7AEtKPwEgNyz0rf7MyX1WINvhYf0AHWD5noQhv8AORJpgwFoy-izNVOjMBI-aSd4e4hBXwdnSQ0i7RifkTuxN7NaNkhwaEjXoJ4BuvAk-yuTTocwW8QzM5AZlHI2VdLF78pWU/s1600/dashboard.jpeg" height="332" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">An example sales dashboard</td></tr>
</tbody></table>
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
We have a meter chart, a bubble chart, a line chart and a couple of bar charts in there, representing some possible sales indicators. Now imagine that a sales manager wants to check the correlation between all of these for a specific country (bubble chart), or for a specific product or employee (bar charts). If these charts were simply static visualizations, he/she wouldn't be able to do that, rendering the dashboard practically useless for detailed data interpretation.<br />
<br />
So, the importance of being able to configure the charts, whatever their type, and where necessary (it might not always be desirable nor useful), so that they can respond to external and / or 'self' events (i.e. filtering actions), and also be able to notify other charts of those is beyond doubt.<br />
<br />
As you might already know, all data visualization components in dashbuilder can be configured through a very straightforward and easy-to-use API. Take the bubble chart in the above dashboard, for instance, which is setup as follows:<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjBaEKNtP1APX4L_SbyiRDw3tuUyFvmi3Lvbn1xiy3BX1Ilkx4XA47nVpE0uKIKfJ7KWlmpBGDeYHYH5_v8ciqeJnu-WFBcoWjn3y8vaYfrPCHqMm-BNh4VqVR7AatpePEO67TSCCN3LGo/s1600/bubblechart-config_rect.jpeg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjBaEKNtP1APX4L_SbyiRDw3tuUyFvmi3Lvbn1xiy3BX1Ilkx4XA47nVpE0uKIKfJ7KWlmpBGDeYHYH5_v8ciqeJnu-WFBcoWjn3y8vaYfrPCHqMm-BNh4VqVR7AatpePEO67TSCCN3LGo/s1600/bubblechart-config_rect.jpeg" height="248" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">The bubble chart setup</td></tr>
</tbody></table>
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
Pay attention to the call to the '<i>filterOn( ... )</i>' method, surrounded by the red rectangle, this is where all the filtering 'magic' happens. Let's dig a little deeper into what this method offers.<br />
As you can see it accepts three boolean parameters:<br />
<br />
<ul>
<li>The first one will configure the data displayer so that it will respond to the filtering events it generates itself, i.e. the event generated by the displayer will affect its own content. Say for a second we were to have this parameter to 'true' in the 'By product' bar chart configuration. If we were then to click on 'Product 11' for example, the result would be the following:</li>
</ul>
<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi_grwaCWmc7GXldkSuQ8cNoYkVbjyV7ubVd2MWdjyWMM5otYxQ9gX_IMiK8ck_Pxlr9AVY_8Y6w1WUkHTilraZdJN3X2XgahTuB_EZAUC4tDKIZSXaUAnr_xY_9yICnXBi2uiUQKnbX5g/s1600/dashboard_filteredbybarproduct.jpeg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi_grwaCWmc7GXldkSuQ8cNoYkVbjyV7ubVd2MWdjyWMM5otYxQ9gX_IMiK8ck_Pxlr9AVY_8Y6w1WUkHTilraZdJN3X2XgahTuB_EZAUC4tDKIZSXaUAnr_xY_9yICnXBi2uiUQKnbX5g/s1600/dashboard_filteredbybarproduct.jpeg" height="342" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">An 'auto'-filtering bar chart</td></tr>
</tbody></table>
<div class="separator" style="clear: both; text-align: center;">
</div>
We observe that only the two bars corresponding to 'Product 11' have remained present in the 'By product' graph. It's up to the dashboard designer to determine if this effect is what is convenient for the type of dashboard and for the type of graph in its specific context. In this case we might wonder if, functionally speaking, it makes sense to have a bar chart auto-filter itself, but please note that the auto-filtering option also plays an important role in the ability to apply 'drill-down' to data displayers. However, this will be the topic of a future post.<br />
<br />
Also note that when we clicked on the 'Product 11' bar, all the other graphs, with the exception of the meter chart, automatically adjusted their content to the newly set filter. This is because of the<br />
<ul>
<li>Second filterOn parameter, which will configure the data displayer so that it will notify the filtering event that has occurred within it to others. Others? That is, every other displayer that has registered itself to listen to the events within a certain context (basically, although not strictly, a dashboard). This is achieved by coordinating displayers through a '<i>DisplayerCoordinator</i>' component, as illustrated below:<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEir4ptYU58u4CLcg1rQYdpjVRj8foRdpgAn6FxW2aZiE-YC80HtFAhyphenhyphenLH4Kvrp4ReukvdkwzgLVmpbOHmClpPFPszT08fr0kvK0gqg_dprHue2UxPcfkO9982YOR7p3ZvFx0XbJok1M-T4/s1600/displayercoordinator.jpeg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEir4ptYU58u4CLcg1rQYdpjVRj8foRdpgAn6FxW2aZiE-YC80HtFAhyphenhyphenLH4Kvrp4ReukvdkwzgLVmpbOHmClpPFPszT08fr0kvK0gqg_dprHue2UxPcfkO9982YOR7p3ZvFx0XbJok1M-T4/s1600/displayercoordinator.jpeg" height="87" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Coordinate displayers amongst themselves</td></tr>
</tbody></table>
Every component that registers with this coordinator will be notified of the events that occur within the other components in the same coordinator instance, but <i>only</i> if its</li>
</ul>
<ul>
<li>Third <i>filterOn()</i> parameter, which tells a displayer to respond or not to the events that are notified throughout a specific dashboard, is set to true. For the sake of this example, this parameter was set to 'false' for the meter chart and, as you can see from the screenshot where the bar chart auto filter was demonstrated, the meter chart has not changed its content.</li>
</ul>
That's it for our brief introduction to displayer filtering, in a future post we will broaden this subject and also introduce the ability to 'drill down' in the data represented by a displayer. Stay tuned!</div>
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-4358594258656726438.post-4676121199946630992014-06-25T15:16:00.003+02:002015-03-13T11:43:46.148+01:00Rich Interactive Dashboards in Uberfire Uberfire is one of the latest & coolest projects within JBoss middleware. The <a href="https://github.com/uberfire/uberfire" target="_blank">Uberfire project</a> was kicked off about two years ago. Despite it's still on the release 0.5 I think is mature enough to start bringing some of the Dashbuilder features to it. Uberfire leverages the GWT & Errai technologies and provides a rich framework to develop desktop-like rich internet applications.<br />
<br />
The next video (don't forget to select HD) shows a live showcase with some interactive sample dashboards built using the Dashbuilder client API. All the dashboards are fed from a dynamically generated client data set. So there is no interaction with the backend. All the operations (group, filter, sort) are performed on the client side. The Dashbuilder architecture allows for handling data sets on both client & server though. For demo purposes we have gone for the client approach as it is easier to implement.<br />
<br />
In next blog entries we will walk through the architecture internals as well as the APIs. Today, I'm just going to give an overview of how these sample dashboards have been built.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.youtube.com/embed/clbFaQqtWvQ?feature=player_embedded' frameborder='0'></iframe><br />
<br />
The four dashboards (see screenshots below) are fed from a dynamically generated data set (the sales opportunities data set - <a href="https://github.com/dashbuilder/dashbuilder/blob/master/dashbuilder-webapp/src/main/java/org/dashbuilder/backend/SalesDataSetGenerator.java" target="_blank">SalesDataSetGenerator.java</a>), which is a Bean type data set generator that registers a data set at Showcase initialization time. The dashboards themselves are just GWT UI Binder widgets composed by a bunch of data viewer instances spread on the same page layout. <br />
<br />
<table cellpadding="5">
<tbody>
<tr>
<td align="center"><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiHHVvnfXjHmcDM98Uk4yTwX6omeX1I0t6my9-rycYnwWd7_sf5q-0UKD4CbrBGQIfEWCNj2T7XxD3vd5s-J4i9nOZ2aedmNKtsXITPJjyhFZZRDeoTfv3wYyo3XCNOVbK1zo8_8JsUkjg/s1600/salesgoal.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiHHVvnfXjHmcDM98Uk4yTwX6omeX1I0t6my9-rycYnwWd7_sf5q-0UKD4CbrBGQIfEWCNj2T7XxD3vd5s-J4i9nOZ2aedmNKtsXITPJjyhFZZRDeoTfv3wYyo3XCNOVbK1zo8_8JsUkjg/s1600/salesgoal.png" height="240" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Sales goals</td></tr>
</tbody></table>
</td>
<td align="center"><table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: left; margin-right: 1em; text-align: left;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjGt7VwowgsiKn1XkQ_6YHyZVPlWHBGG7Th_3f8EVHCpYmyFeVm1tvjIML1rdZ9Swdx89jXmK-ernU1ddP_QoERbeV7zNb35VzNcAAkgOb6h0BtoagiTFPTkhgauQ432kdKE9DeH-URkIk/s1600/salespipeline.png" imageanchor="1" style="clear: left; margin-bottom: 1em; margin-left: auto; margin-right: auto;"><img alt="Sales goal dashboard" border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjGt7VwowgsiKn1XkQ_6YHyZVPlWHBGG7Th_3f8EVHCpYmyFeVm1tvjIML1rdZ9Swdx89jXmK-ernU1ddP_QoERbeV7zNb35VzNcAAkgOb6h0BtoagiTFPTkhgauQ432kdKE9DeH-URkIk/s1600/salespipeline.png" height="240" title="Sales goal dashboard" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Sales pipeline</td></tr>
</tbody></table>
</td>
</tr>
<tr>
<td align="center"><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi5p30frpHgsT3AAQ9ez7IbBR_um5fFWSygxfLmaVSDZPyaNn48ctagG7EjZBlN3QvADcBH5L68ANFff1BeZJ5T3bTRtG7LC4JeNoQBhS7gU1nMVclHBqoF8Utl_xS7JHm_yeWh0zIfxA8/s1600/salesbycountry.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi5p30frpHgsT3AAQ9ez7IbBR_um5fFWSygxfLmaVSDZPyaNn48ctagG7EjZBlN3QvADcBH5L68ANFff1BeZJ5T3bTRtG7LC4JeNoQBhS7gU1nMVclHBqoF8Utl_xS7JHm_yeWh0zIfxA8/s1600/salesbycountry.png" height="240" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Sales distribution by country</td></tr>
</tbody></table>
</td>
<td align="center"><table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: left; margin-right: 1em; text-align: left;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjfFk0d3xI99d4Bw35m-cTxz6BWB8EXyw7v5an5FNnVuGxRnAiuV2JvTz0zkmi_r1TIQZsu8qwA5Scr7UZJqGczBICiRah1ABOqtD3T5TbT9ZWPfkEgpBxCq_pFn6FfWdkGXcn5vKWu0Ik/s1600/salesreports.png" imageanchor="1" style="clear: left; margin-bottom: 1em; margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjfFk0d3xI99d4Bw35m-cTxz6BWB8EXyw7v5an5FNnVuGxRnAiuV2JvTz0zkmi_r1TIQZsu8qwA5Scr7UZJqGczBICiRah1ABOqtD3T5TbT9ZWPfkEgpBxCq_pFn6FfWdkGXcn5vKWu0Ik/s1600/salesreports.png" height="240" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Sales table reports</td></tr>
</tbody></table>
</td>
</tr>
</tbody></table>
<br />
Let's take for instance the first dashboard. The UI Binder template (<a href="https://github.com/dashbuilder/dashbuilder/blob/master/dashbuilder-webapp/src/main/java/org/dashbuilder/client/sales/widgets/SalesGoals.ui.xml" target="_blank">SalesGoals.ui.xml</a>) is used to lay out all the charts properly. Each chart is assigned a unique identifier used within the dashboard (<a href="https://github.com/dashbuilder/dashbuilder/blob/master/dashbuilder-webapp/src/main/java/org/dashbuilder/client/sales/widgets/SalesGoals.java" target="_blank">SalesGoals.java</a>). <br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi9iiMFMB15WptwVT7bxW4DcJbaAUgUTegravanJ3Izzy98QAjrXApsddaiqKcW1555TEoFjyBBtFzDmzviEWRtK2cBq_NoFscVLR5rxbYpbUmlIK174U3zonerTCG97fs1dwgCtTa6ItE/s1600/dashboard_ui_xml.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi9iiMFMB15WptwVT7bxW4DcJbaAUgUTegravanJ3Izzy98QAjrXApsddaiqKcW1555TEoFjyBBtFzDmzviEWRtK2cBq_NoFscVLR5rxbYpbUmlIK174U3zonerTCG97fs1dwgCtTa6ItE/s1600/dashboard_ui_xml.png" height="210" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Dashboard UI binder template</td></tr>
</tbody></table>
<br />
The chart definition is composed by two parts, both defined using a very simple but powerful API.<br />
<ul>
<li>A <b>data set reference </b>the chart is going to display. Here we can specify a plain data set or a data set lookup which is just a sequence of operations (filter, sort, group) performed over an existing data set.</li>
</ul>
<ul>
<li>A <b>display configuration</b> or how we want to visualize the data. There are several types of visualizations - pie, bar, line, area, meter, map bubble charts, tables, hierarchical trees, etc... The display settings will depend on the type of visualization chosen.</li>
</ul>
<div class="separator" style="clear: both; text-align: center;">
</div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh7JgVijBYX6LMIGmIiMLW-23U6WdybQ3_uZXEWZTnh3r621vbXoqxQSciN558lDbQvFtYkSLlaxW-Rr9L91VGZmg40JVwGNYdwsoqnRunSEbP_hFCCfHAEGkmV7O-KzYHN2s3bymJXERg/s1600/bubble.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh7JgVijBYX6LMIGmIiMLW-23U6WdybQ3_uZXEWZTnh3r621vbXoqxQSciN558lDbQvFtYkSLlaxW-Rr9L91VGZmg40JVwGNYdwsoqnRunSEbP_hFCCfHAEGkmV7O-KzYHN2s3bymJXERg/s1600/bubble.png" height="193" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Data Displayer API sample</td></tr>
</tbody></table>
<br />
As I said, we'll dive into the API internals in next blog entries. For now, just taking a look at the examples is the quickest way to figure out how this API works.<br />
<div>
<br /></div>
One last note worth to mention is that, right now, the default rendering technology used is the <i>Google Charts Visualization</i> library. We went for Google because it was the quickest road to follow in order to get an early prototype. Nevertheless, the data viewer layer is not tied to any specific rendering technology as it supports the concept of pluggable renderers. So, in the future, it'll be possible to have several renderers available and have every chart decide which particular one to use.<br />
<br />
The <a href="https://github.com/dashbuilder" target="_blank">project</a> is hosted on Github. Despite it's in a very early stage of development we're pushing hard to bring many new features in the next few months:<br />
<ul>
<li>Data visualization editors</li>
<li>Drag&drop dashboard composer</li>
<li>Renderer based on the D3 library</li>
<li>Support for real-time dashboards</li>
<li>RESTful API for remote dashboard interaction</li>
</ul>
<br />
That's all. I encourage you to clone the project, build, run it and play with the examples.<br />
<br />
Enjoy it!<br />
<br />
<br />Unknownnoreply@blogger.com2tag:blogger.com,1999:blog-4358594258656726438.post-54655159055378521942014-03-11T12:01:00.003+01:002014-06-27T11:35:21.068+02:00Embed a KPI chart into your web app<div style="color: #333333; font-family: Arial, sans-serif; font-size: 14px; line-height: 20px; padding: 0px;">
<span style="background-color: white;"> Recently, a new cool feature has been added to the Dashbuilder echosystem: the ability to embed dashboard charts into your own web app via a lightweight easy to use JavaScript API.</span></div>
<div style="color: #333333; font-family: Arial, sans-serif; font-size: 14px; line-height: 20px; padding: 0px;">
<span style="background-color: white;"><br /></span></div>
<div style="color: #333333; font-family: Arial, sans-serif; font-size: 14px; line-height: 20px; padding: 0px;">
<span style="background-color: white;"> As you may know, Dashbuilder allows for the creation of custom feature complete dashboards. Now, once a dashboard is built, it's possible to pick up any KPI and paste it into your web application. </span></div>
<div style="color: #333333; font-family: Arial, sans-serif; font-size: 14px; line-height: 20px; padding: 0px;">
<span style="background-color: white;"><br /></span></div>
<div>
<span style="background-color: white; color: #333333; font-family: Arial, sans-serif; font-size: 14px; line-height: 20px;"> To see how this mechanism works, two out-of-the-box examples have been added to the tooling. To test them just type the following URL on a fresh Dashbuilder installation:</span></div>
<div>
<ul class="alternate" style="color: #333333; font-family: Arial, sans-serif; font-size: 14px; line-height: 20px; margin: 10px 0px 0px;" type="square">
<li><span style="background-color: white;">Multiple charts example: <a href="http://%3Chost%3E:<port>/dashbuilder/js-api/demo1.html" rel="nofollow">http://<host>:<port>/dashbuilder/js-api/demo1.html</a></span></li>
</ul>
<div>
<span style="color: #333333; font-family: Arial, sans-serif;"><span style="background-color: white; font-size: 14px; line-height: 20px;"><br /></span></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgyDR5JZz_T5v1X9UMgluhUezyFfZSqBbXoxQaGNGCmPGTp0faAw9-ufBeJ2xkwLVylUwFgtNMwjJn5pF9ALAA0VrqshjroRQsos-uavcFD1c-A1LTG9akY8Tfx6tvjPMpDCooGd4lLl3Y/s1600/embedkpis1.png" imageanchor="1" style="background-color: white; margin-left: 1em; margin-right: 1em;"><img alt="KPI embed sample" border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgyDR5JZz_T5v1X9UMgluhUezyFfZSqBbXoxQaGNGCmPGTp0faAw9-ufBeJ2xkwLVylUwFgtNMwjJn5pF9ALAA0VrqshjroRQsos-uavcFD1c-A1LTG9akY8Tfx6tvjPMpDCooGd4lLl3Y/s1600/embedkpis1.png" height="472" title="KPI embed sample" width="640" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<span style="background-color: white;"><br /></span></div>
<ul class="alternate" style="color: #333333; font-family: Arial, sans-serif; font-size: 14px; line-height: 20px; margin: 10px 0px 0px;" type="square">
<li><span style="background-color: white;">Tabular report example: <a href="http://%3Chost%3E:<port>/dashbuilder/js-api/demo2.html" rel="nofollow">http://<host>:<port>/dashbuilder/js-api/demo2.html</a></span></li>
</ul>
<div>
<span style="color: #333333; font-family: Arial, sans-serif;"><span style="background-color: white; font-size: 14px; line-height: 20px;"><br /></span></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjEPKmLCaoDY922IPo8E697kw27-9MrYkPHx7qa9uLOX6FokcnInkgv7AG2VJ_D6GC5oSj7rWmGC_pvdwWuM1S-nCUCnWFiC8kTq-S3uLQOmgqsvv-9sH2V-rbsCgBEcWkhpxYvNeZSS-g/s1600/embedkpis2.png" imageanchor="1" style="background-color: white; margin-left: 1em; margin-right: 1em;"><img alt="Report embed sample" border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjEPKmLCaoDY922IPo8E697kw27-9MrYkPHx7qa9uLOX6FokcnInkgv7AG2VJ_D6GC5oSj7rWmGC_pvdwWuM1S-nCUCnWFiC8kTq-S3uLQOmgqsvv-9sH2V-rbsCgBEcWkhpxYvNeZSS-g/s1600/embedkpis2.png" height="456" title="Report embed sample" width="640" /></a></div>
<div style="color: #333333; font-family: Arial, sans-serif; font-size: 14px; line-height: 20px; margin-top: 10px; padding: 0px;">
<span style="background-color: white;"> If you want to figure out how to use this JS lib just take a look at the HTML files provided. Both are displaying charts belonging to the pre-installed dashboards that come along with the tooling. </span></div>
<div style="margin-top: 10px; padding: 0px;">
<span style="color: #333333; font-family: Arial, sans-serif;"><span style="font-size: 14px; line-height: 20px;"> Notice, this brand new feature is only available in the latest sources in GitHub (soon in the forthcoming 6.1.0 Final release). So if you wanna play with it you'll need to build the release from sources, as described </span><span style="background-color: white; font-size: 14px; line-height: 20px;"><a href="https://github.com/droolsjbpm/dashboard-builder#quickstart" target="_blank">here</a>. </span></span><br />
<span style="color: #333333; font-family: Arial, sans-serif;"><span style="background-color: white; font-size: 14px; line-height: 20px;"><br /></span></span>
<span style="color: #333333; font-family: Arial, sans-serif;"><span style="background-color: white; font-size: 14px; line-height: 20px;"> In the near future, an additional RESTful API will be provided so that third-party applications can not only embed KPI mashups but also to make calls to the Dashbuilder data engine. REST support will empower Dashbuilder integration capabilities with remote apps, making possible for developers to retrieve/push data from dashboards. Some real world uses cases could be the following:</span></span></div>
<div style="margin-top: 10px; padding: 0px;">
</div>
<ul>
<li><span style="background-color: white; color: #333333; font-family: Arial, sans-serif; font-size: 14px; line-height: 20px;">Alert management based on KPI threasholds.</span></li>
<li><span style="background-color: white; color: #333333; font-family: Arial, sans-serif; font-size: 14px; line-height: 20px;">UI development reading the data coming from a given KPI.</span></li>
<li><span style="background-color: white;"><span style="color: #333333; font-family: Arial, sans-serif;"><span style="font-size: 14px; line-height: 20px;">Push data from an external app: ERP, CRM or the like, to feed a dashboard</span></span><span style="color: #333333; font-family: Arial, sans-serif; font-size: 14px; line-height: 20px;">.</span></span></li>
</ul>
<div style="margin-top: 10px; padding: 0px;">
</div>
<div>
<span style="color: #333333; font-family: Arial, sans-serif;"><span style="background-color: white; font-size: 14px; line-height: 20px;">This and many others interesting features will be delivered throughout the next months. </span></span></div>
<div>
<span style="background-color: white; color: #333333; font-family: Arial, sans-serif; font-size: 14px; line-height: 20px;"><br /></span></div>
<div>
<span style="background-color: white; color: #333333; font-family: Arial, sans-serif; font-size: 14px; line-height: 20px;">Stay tuned! </span></div>
</div>
<div>
<br /></div>
Unknownnoreply@blogger.com2tag:blogger.com,1999:blog-4358594258656726438.post-49587144160157962322014-02-24T12:56:00.000+01:002014-03-11T17:56:20.172+01:00The Dashbuilder demo gets Docker-ized <span style="font-family: Arial, Helvetica, sans-serif;"><span style="background-color: white; color: #333333; line-height: 20px;"> During the last week I've been playing a little with Docker. </span><a href="https://www.docker.io/" style="background-color: white; line-height: 20px;" target="_blank">Docker</a><span style="background-color: white; color: #333333; line-height: 20px;"> is an open-source virtualization technology that automates the deployment of any application as a lightweight, portable, self-sufficient container that will run virtually anywhere. For those interested in getting all the details I recommend watching this excellent </span><a href="http://www.youtube.com/watch?v=3N3n9FzebAA" style="background-color: white; line-height: 20px;" target="_blank">presentation</a><span style="background-color: white; color: #333333; line-height: 20px;"> given by the Docker's founder Solomon Hykes.</span></span><br />
<div style="background-color: white; margin-bottom: 10px;">
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span>
<span style="font-family: Arial, Helvetica, sans-serif;"> In a nutshell, what Docker provides is a platform for:</span><br />
<ul>
<li><span style="font-family: Arial, Helvetica, sans-serif;">Creating custom images. an image could be an application, a custom Linux distro, a service or whatever packaged Linux software you can imagine. An image it's basically composed by a base Linux distro plus some software installed and configured on top of it. </span></li>
</ul>
<ul>
<li><span style="font-family: Arial, Helvetica, sans-serif;">Sharing a custom image with others via the Docker's central repository - <a href="https://index.docker.io/" target="_blank">https://index.docker.io</a>. You can push your own images, search for images and pull images created by others.</span></li>
</ul>
<ul>
<li><span style="font-family: Arial, Helvetica, sans-serif;">A daemon service (accessible via a REST API) plus a command utility package for creating containers and managing its life cycle: list the available containers, start/stop a container instance, etc.</span></li>
</ul>
<span style="font-family: Arial, Helvetica, sans-serif;"> What I've done in Dashbuilder is to create a Docker image containing the latest <a href="https://github.com/dgutierr/dashbuilder-demo" target="_blank">demo</a> of the <a href="https://github.com/droolsjbpm/dashboard-builder" target="_blank">project</a> and push that image to the Docker shared repository. </span><br />
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span>
<br />
<h2>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: large;">Installation</span></h2>
<span style="color: #333333; line-height: 20px;"><span style="font-family: Arial, Helvetica, sans-serif;"> Before going further, you need to install the Docker package on your Linux host. At the time of this writing Docker is only available for Linux based machines. Windows and Mac OSX support is still under development. Please read the <a href="http://docs.docker.io/en/latest/installation" target="_blank">Docker package installation</a>.</span></span><br />
<span style="color: #333333; line-height: 20px;"><span style="font-family: Arial, Helvetica, sans-serif;"><br /></span></span>
<span style="color: #333333; line-height: 20px;"><span style="font-family: Arial, Helvetica, sans-serif;">Once you have Docker installed you can carry on with the demo </span></span><span style="color: #333333; font-family: Arial, Helvetica, sans-serif; line-height: 20px;">installation as follows:</span></div>
<ol style="background-color: white; color: #333333; line-height: 20px; margin: 0px 0px 10px 25px; padding: 0px;">
<li><div style="margin-bottom: 10px;">
<span style="font-family: Arial, Helvetica, sans-serif;">Pull the image from the central repo:</span></div>
<pre style="background-color: whitesmoke; border: 1px solid rgba(0, 0, 0, 0.14902); margin-bottom: 10px; padding: 9.5px; white-space: pre-wrap; word-break: break-all; word-wrap: break-word;"><code class="bash" style="background-color: #f0f0f0; border: 0px; color: black; display: block; padding: 0.5em;"><span style="font-family: Arial, Helvetica, sans-serif;"><span class="built_in" style="font-weight: bold;">sudo</span> docker pull dgutierr/dashbdemo
</span></code></pre>
</li>
<li><div style="margin-bottom: 10px;">
<span style="font-family: Arial, Helvetica, sans-serif;">Run the image:</span></div>
<pre style="background-color: whitesmoke; border: 1px solid rgba(0, 0, 0, 0.14902); margin-bottom: 10px; padding: 9.5px; white-space: pre-wrap; word-break: break-all; word-wrap: break-word;"><code class="dockerfile" style="background-color: #f0f0f0; border: 0px; color: black; display: block; padding: 0.5em;"><span style="font-family: Arial, Helvetica, sans-serif;">sudo docker <span class="keyword" style="font-weight: bold;">run</span> -p <span class="number" style="color: #008800;">8080</span>:<span class="number" style="color: #008800;">8080</span> dgutierr/dashbdemo
</span></code></pre>
</li>
<li><div style="margin-bottom: 10px;">
<span style="font-family: Arial, Helvetica, sans-serif;">Open the app:</span></div>
<pre style="background-color: whitesmoke; border: 1px solid rgba(0, 0, 0, 0.14902); margin-bottom: 10px; padding: 9.5px; white-space: pre-wrap; word-break: break-all; word-wrap: break-word;"><code class="undefined" style="background-color: #f0f0f0; border: 0px; color: black; display: block; padding: 0.5em;"><span style="font-family: Arial, Helvetica, sans-serif;">http://localhost:8080/dashbuilder
Users: root/root, demo/demo
</span></code></pre>
</li>
</ol>
<div style="background-color: white; color: #333333; line-height: 20px; margin-bottom: 10px;">
<span style="font-family: Arial, Helvetica, sans-serif;"> If you actually don't know how to interact with the app, please take a look at the <a href="http://docs.jboss.org/dashbuilder/release/6.0.1.Final/html_single/" target="_blank">Quick Start Guide</a>.</span><br />
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span>
<span style="font-family: Arial, Helvetica, sans-serif;"> Enjoy! </span><br />
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span>
<br />
<h2>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: large;">Image internals</span></h2>
<span style="font-family: Arial, Helvetica, sans-serif;"> Our Docker image is based on the <a href="https://index.docker.io/u/mattdm/fedora/" target="_blank">mattdm/fedora</a> image, which is basically a Fedora 20 distro, plus the following software installed:</span></div>
<ul style="background-color: white; color: #333333; line-height: 20px; margin: 0px 0px 10px 25px; padding: 0px;">
<li><span style="font-family: Arial, Helvetica, sans-serif;">Open JDK 1.7.0,</span></li>
<li><span style="font-family: Arial, Helvetica, sans-serif;">Git client, and </span></li>
<li><span style="font-family: Arial, Helvetica, sans-serif;">A git clone of the Dashbuilder <a data-original-title="" href="https://github.com/dgutierr/dashbuilder-demo" style="color: #213b8f; text-decoration: none;" title="">demo</a> repository.</span></li>
</ul>
Unknownnoreply@blogger.com6tag:blogger.com,1999:blog-4358594258656726438.post-6710723933987100022014-01-29T12:49:00.001+01:002014-01-29T12:51:56.933+01:00First steps to create your dashboards<h3 class="post-title entry-title" itemprop="name" style="background-color: white; font-family: Arial, Tahoma, Helvetica, FreeSans, sans-serif; font-size: 22px; font-weight: normal; margin: 0.75em 0px 0px; position: relative;">
<span style="font-family: Verdana, Geneva, sans-serif; font-size: 13px; line-height: 1.4;">One of the most typical situations with <a href="http://www.dashbuilder.org/" target="_blank">Dashbuilder</a> is that you already have some existing data you want to create dashboards from.</span></h3>
<div>
<span style="font-family: Verdana, Geneva, sans-serif; font-size: 13px; line-height: 1.4;"><br /></span></div>
<div class="post-body entry-content" id="post-body-5773041049655025015" itemprop="description articleBody" style="background-color: white; font-family: Verdana, Geneva, sans-serif; font-size: 13px; line-height: 1.4; position: relative; width: 790px;">
You can add new dashboards by configuration with Dashbuilder's composition tool, by f<span style="line-height: 1.4;">ollowing these steps:</span></div>
<div class="post-body entry-content" id="post-body-5773041049655025015" itemprop="description articleBody" style="background-color: white; font-family: Verdana, Geneva, sans-serif; font-size: 13px; line-height: 1.4; position: relative; width: 790px;">
<b><br /></b></div>
<div class="post-body entry-content" id="post-body-5773041049655025015" itemprop="description articleBody" style="background-color: white; font-family: Verdana, Geneva, sans-serif; font-size: 13px; line-height: 1.4; position: relative; width: 790px;">
<b>Step 01</b> - You must first carefully think what data needs to be displayed to users and which is the desired format. It’s both important to have the right data and to display it in simple and concise way. Dashboards must be simple to use and to understand, focusing on displaying only relevant information.</div>
<div class="post-body entry-content" id="post-body-5773041049655025015" itemprop="description articleBody" style="background-color: white; font-family: Verdana, Geneva, sans-serif; font-size: 13px; line-height: 1.4; position: relative; width: 790px;">
<br />
At this stage, you must also take into account performance and volume concerns.<br />
<b><br /></b></div>
<div class="post-body entry-content" id="post-body-5773041049655025015" itemprop="description articleBody" style="background-color: white; font-family: Verdana, Geneva, sans-serif; font-size: 13px; line-height: 1.4; position: relative; width: 790px;">
<b>Step 02</b> - Make sure the data is available through an standard protocol and a known format, suitable to be queried. Typically, a database or an structured file would be enough. If this is not available in this format, you can always create a new connector or publish it through any custom integration.<br />
<b><br /></b></div>
<div class="post-body entry-content" id="post-body-5773041049655025015" itemprop="description articleBody" style="background-color: white; font-family: Verdana, Geneva, sans-serif; font-size: 13px; line-height: 1.4; position: relative; width: 790px;">
<b>Step 03</b> - Setup connectivity parameters. By using the tool with the right privileges, you can define connectors parameters (i.e. JDBC connections) and data providers configuration (i.e. SQL queries)<br />
<b><br /></b></div>
<div class="post-body entry-content" id="post-body-5773041049655025015" itemprop="description articleBody" style="background-color: white; font-family: Verdana, Geneva, sans-serif; font-size: 13px; line-height: 1.4; position: relative; width: 790px;">
<b>Step 04</b> - Configure one or several workspaces with as many pages as needed. Set up navigation across them, for example, by using the provided menus. It’s important to realize every page or workspace will have its own access URL, that can be linked from any other application.<br />
<b><br /></b></div>
<div class="post-body entry-content" id="post-body-5773041049655025015" itemprop="description articleBody" style="background-color: white; font-family: Verdana, Geneva, sans-serif; font-size: 13px; line-height: 1.4; position: relative; width: 790px;">
<b>Step 05</b> - Add indicators (charts) and reports to pages, and configure them. By using the KPI indicator editor, you set them to display the right information at the right place.<br />
<b><br /></b></div>
<div class="post-body entry-content" id="post-body-5773041049655025015" itemprop="description articleBody" style="background-color: white; font-family: Verdana, Geneva, sans-serif; font-size: 13px; line-height: 1.4; position: relative; width: 790px;">
<b>Step 06</b> - Configure filter and drill down capabilities. This component controls how navigation is performed when users click on the charts, by filtering the data by the right property value.<br />
<b><br /></b></div>
<div class="post-body entry-content" id="post-body-5773041049655025015" itemprop="description articleBody" style="background-color: white; font-family: Verdana, Geneva, sans-serif; font-size: 13px; line-height: 1.4; position: relative; width: 790px;">
<b>Step 07</b> - Set the right permissions for each level of information. You can define which elements of the dashboards should be visible or even editable for a different range of users or roles.<br />
<b><br /></b></div>
<div class="post-body entry-content" id="post-body-5773041049655025015" itemprop="description articleBody" style="background-color: white; font-family: Verdana, Geneva, sans-serif; font-size: 13px; line-height: 1.4; position: relative; width: 790px;">
<b>Step 08</b> - Customize look'n' feel. Sometimes, a custom look and feel is required. There are different tools to modify the standard look, by providing CSS and graphical resources, as well as custom HTML content.<br />
<b><br /></b></div>
<div class="post-body entry-content" id="post-body-5773041049655025015" itemprop="description articleBody" style="background-color: white; font-family: Verdana, Geneva, sans-serif; font-size: 13px; line-height: 1.4; position: relative; width: 790px;">
<b>Step 09</b> - Test your dashboards for each role.<br />
<b><br /></b></div>
<div class="post-body entry-content" id="post-body-5773041049655025015" itemprop="description articleBody" style="background-color: white; font-family: Verdana, Geneva, sans-serif; font-size: 13px; line-height: 1.4; position: relative; width: 790px;">
<b>Step 10</b> - Gather user feedback and improve your dashboards based on it.<br />
<br />
You can find more information about how to implement each of these steps at the project's documentation page <a href="http://dashbuilder.org/documentation.html" style="background-color: transparent;">http://dashbuilder.org/documentation.html</a></div>
<div class="post-body entry-content" id="post-body-5773041049655025015" itemprop="description articleBody" style="background-color: white; font-family: Verdana, Geneva, sans-serif; font-size: 13px; line-height: 1.4; position: relative; width: 790px;">
<br /></div>
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-4358594258656726438.post-8511528013516053812014-01-28T16:59:00.001+01:002014-01-28T17:05:05.855+01:00Process monitoring with jBPM integration<p>Dashbuilder is packaged and automatically ready to use with jBPM 6 workbench (<a href="https://www.jboss.org/jbpm">https://www.jboss.org/jbpm</a>). By doing so, you will get several process and task related dashboards, that are connected to jBPM history log.</p> <p>They will provide, for example, an overview of the running and completed processes and tasks. Different sort of reports and indicators will become available for BPM monitoring, including time related (i.e. average task durations) or instance related (i.e amount of active processes).</p> <p>You can find the instructions to install this flavour of Dashbuilder at <a href="http://docs.jboss.org/jbpm/v6.0/userguide/jBPMGettingStarted.html">http://docs.jboss.org/jbpm/v6.0/userguide/jBPMGettingStarted.html</a></p> <p>Read more about this integration at <a href="http://docs.jboss.org/jbpm/v6.0/userguide/chap-bam.html">http://docs.jboss.org/jbpm/v6.0/userguide/chap-bam.html</a></p>
<img height="355" id="docs-internal-guid-36083893-d992-2308-ad07-fe4acfc6c47d" src="https://lh4.googleusercontent.com/amEyCusIjZuKScVX2BqNNL1RA-Sb9vZ7wAo0RNkSqVtwceDTN1RNGPhR9Qi0ZFEi6Mo4CJLb_WrcB5nrhxGO4PIiLe8M8tTn05LreQc_SMdik8ZEJw9BEWXq_g" style="border: 0px;" width="640" />Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-4358594258656726438.post-2146523693585362962014-01-28T16:25:00.002+01:002014-01-28T16:25:44.793+01:00Dashbuilder 6.0.1 releasedA new version of Dashbuilder has been release along with the Drools & jBPM platform.<br />
This version contains only some bug fixes.
You can download it from <a href="http://www.dashbuilder.org/downloads_binaries.html" target="_blank">here</a> <link download="" to=""></link>, and as always, you are more than welcome to provide feedback about it.<br />
We will continue working on the new generation of Dashbuilder, that will greatly improve its integration and reporting capabilities.Unknownnoreply@blogger.com0