Monday, December 8, 2014

Building dynamic responsive multi-level menus with plain HTML and OmniFaces

Recently, I had to create a responsive multi-level menu with JSF 2.2. Requirements: the menu should
  • be created with dynamic structure from backend
  • be responsive, i.e. desktop- and mobile-friendly
  • have submenu items with navigation links
  • support touch events
  • support keyboard accessibility
PrimeFaces' menus were not a choice. They can indeed be created programmatically by model, but
  • they are not really responsive
  • submenu items only collapse / expand the submenus and can not contain navigation links
  • ...
Well, why not to pick any jQuery based plugin for responsive multi-level menus? There are a lot of plugins. See Useful List of Responsive Navigation and Menu Patterns. I choosen FlexNav.

But how to output the dynamic menu structure? ui:repeat is not a choice here because the structure (nested sub menus, etc.) is not known a priori. Fortunately, there is OmniFaces with o:tree, which allows to have full control over the markup of a tree hierarchy by declaring the JSF components or HTML elements in the markup. o:tree does not render any HTML markup by itself. Exactly what I need!

I ended up with this XHTML fragment mixing o:treeNode, o:treeNodeItem, o:treeInsertChildren and HTML elements defined by the mentioned FlexNav menu:
<h:outputScript library="js" name="jquery.flexnav.js"/>
<h:outputStylesheet library="css" name="flexnav.css"/>

<ul id="mainnavi" class="flexnav" data-breakpoint="640" role="navigation">
    <o:tree value="#{mainNavigationBean.treeModel}" var="item">
        <o:treeNode level="0">
            <o:treeNodeItem>
                <li class="item">
                    <a href="#{item.href}" title="#{item.title}">#{item.text}</a>
                    <o:treeInsertChildren/>
                </li>
            </o:treeNodeItem>
        </o:treeNode>
        <o:treeNode>
            <ul>
                <o:treeNodeItem>
                    <li>
                        <a href="#{item.href}" title="#{item.title}">#{item.text}</a>
                        <o:treeInsertChildren/>
                    </li>
                </o:treeNodeItem>
            </ul>
        </o:treeNode>
    </o:tree>
</ul>

<h:outputScript id="mainnaviScript" target="body">
    $(document).ready(function () {
        $("#mainnavi").flexNav({'calcItemWidths': true});
    });
</h:outputScript>
The OmniFaces' TreeModel with menu items is created programmatically. The Java code looks like
public TreeModel<NavigationItemDTO> getTreeModel() {
    // get menu model from a remote service
    NavigationContainerDTO rootContainer = remoteService.fetchMainNavigation(...);

    TreeModel<NavigationItemDTO> treeModel = new ListTreeModel<>();
    buildTreeModel(treeModel, rootContainer.getNavItem());

    return treeModel;
}

private void buildTreeModel(TreeModel<NavigationItemDTO> treeModel, List<NavigationItemDTO> items) {
    for (NavigationItemDTO item : items) {
        buildTreeModel(treeModel.addChild(item), item.getNavItem());
    }
}
And the end result (desktop variant):


Note that submenus are clickable and can be expanded on mouseover.

You see, JSF is flexible and sometimes you don't need full-blown components. Have fun!

Thursday, November 20, 2014

Don't repeat expressions in facelets

Have you ever seen repeated EL expressions in JSF like this one?
<h:inputText value="#{oneBean.name}" rendered="#{anotherBean.showPerson}"/>
<h:inputText value="#{oneBean.birthday}" rendered="#{anotherBean.showPerson}"/>
<h:selectOneMenu value="#{oneBean.children}" style="#{anotherBean.showPerson ? 'display:block' : 'display:none'}"/>
usw. Another example:
<ui:include src="/include/somesnippet.xhtml">
    <ui:param name="age" value="#{someBean.isMan(person) ? 63 : 60}"/>
    <ui:param name="money" value="#{someBean.isMan(person) and someBean.getCountry(person) eq 'de' ? 1000 : 900}"/>
    <ui:param name="big" value="#{someBean.getCountry(person) eq 'zh' or someBean.getCountry(person) eq 'ru' ? true : false}"/>
</ui:include>
Expressions #{anotherBean.showPerson}, #{someBean.isMan(person)}, #{someBean.getCountry(person)} are repeated multiple times. How to optimize them? Well, you can use JSTL's c:set like this code snippet
<c:set var="showPerson" value="#{anotherBean.showPerson}"/>

<h:inputText value="#{oneBean.name}" rendered="#{showPerson}"/>
<h:inputText value="#{oneBean.birthday}" rendered="#{showPerson}"/>
<h:selectOneMenu value="#{oneBean.children}" style="#{showPerson ? 'display:block' : 'display:none'}"/>

<c:set var="man" value="#{someBean.isMan(person)}"/>
<c:set var="country" value="#{someBean.getCountry(person)}"/>

<ui:include src="/include/somesnippet.xhtml">
    <ui:param name="age" value="#{man ? 63 : 60}"/>
    <ui:param name="money" value="#{man and country eq 'de' ? 1000 : 900}"/>
    <ui:param name="big" value="#{country eq 'zh' or country eq 'ru' ? true : false}"/>
</ui:include>
If you are scared about JSTL pitfalls (because you have heard that JSTL is not always JSF friendly :-)), there is an alternative and simple approach - ui:param. TagHandler ui:param uses JSF's VariableMapper to save EL expressions in a map. This map maps EL variables on a page and the EL expressions they are associated with. And here you go:
<ui:param name="showPerson" value="#{anotherBean.showPerson}"/>

<h:inputText value="#{oneBean.name}" rendered="#{showPerson}"/>
<h:inputText value="#{oneBean.birthday}" rendered="#{showPerson}"/>
<h:selectOneMenu value="#{oneBean.children}" style="#{showPerson ? 'display:block' : 'display:none'}"/>

<ui:param name="man" value="#{someBean.isMan(person)}"/>
<ui:param name="country" value="#{someBean.getCountry(person)}"/>

<ui:include src="/include/somesnippet.xhtml">
    <ui:param name="age" value="#{man ? 63 : 60}"/>
    <ui:param name="money" value="#{man and country eq 'de' ? 1000 : 900}"/>
    <ui:param name="big" value="#{country eq 'zh' or country eq 'ru' ? true : false}"/>
</ui:include>
The code is more readable, especially if you have very complex and long expressions. Note: we're speaking here about readable code and not about performance optimization because JSF TagHandlers don't evaluate EL expressions.

Friday, November 7, 2014

Dynamic aria-live for better accessibility experience

Every web developer working with the web accessibility (WAI ARIA) knows or heard about aria-live. This is an attribute, which indicates a live region - any updatable HTML element - and describes the types of updates the user agents, assistive technologies (screen readers), and user can expect from the live region. The default value of the aria-live is off. That means, updates to the region will not be presented to the user unless the assistive technology is currently focused on that region. The value polite means, assistive technologies should announce updates at the next graceful opportunity, such as at the end of speaking the current sentence or when the user pauses typing. There is also the value assertive, which forces assistive technologies to notify the user immediately. In additional, the aria-relevant attribute can specify if the updates on the live region should only be spoken when the corresponding DOM node is added or removed or both.

Most time you need to set the value once and don't care about it. E.g. markup for error messages can contain aria-live="polite".
<div class="messages" aria-live="polite">
    ... some messages ...
</div>
Every time when the content of the div container with class="messages" is updated, it will be spoken by screen readers. That's good, but sometimes you only would like to notify a sightless user when the new (after update) and old (before update) contents are not equal. Imagine a railway ticket shop where users can choose fare class, number of traveler, book places, etc. The total buy price is permanently updated. We can write
<span aria-live="polite">
    <div id="pricetotal">
        <span class="hiddenOfScreen">Total price </span>
        #{price}
    </div>
</span>
and update the div by AJAX. #{price} is a current price as EL expression calculated on the server-side (coming from the JSF world, but JavaScript templating has similar expressions). Whenever the div gets updated, screen readers speak the total price regardless if the amount was changed or not. A more clever approach sets aria-live dynamically at runtime. If the amount was changed, the aria-live on the div should have the value polite. If the old and new prices are equal, the div should have the value off. The off value prevents speaking by screen readers.

The idea is to save the last updated price in the data-price attribute of the parent element and compare the old and new prices on every AJAX update. In the code snippet below, the div with id="pricetotal" gets updated. The JavaScript block inside is being executed on every update. We read and compare old and new prices and manipulate the aria-live attribute at runtime. Whenever the aria-live is set to polite, screen readers speak "Total price" and the amount.
<span data-price="#{price}">
    <div id="pricetotal">
        <span class="hiddenOfScreen">Total price </span>
        <span class="priceoutput">#{price}</span>
        <script type="text/javascript">
            $(document).ready(function () {
                $pricetotal = $('#pricetotal');
                var oldPrice = $pricetotal.parent().data('price');
                var newPrice = $pricetotal.find('.priceoutput').text();
                if (oldPrice != newPrice) {
                    $pricetotal.attr('aria-live', 'polite');
                    $pricetotal.parent().data('price', newPrice);
                } else {
                    $pricetotal.attr('aria-live', 'off');
                }
            });
        </script>
    </div>
</span>
If prices are not equal, the new price is saved in the data-price to make it available in the next update.

Monday, November 3, 2014

PrimeFaces Extensions 3.0.0 released

Today, we released the PrimeFaces Extensions 3.0.0. It is built on top of PrimeFaces 5.1 and is fully compatible with PrimeFaces 5.1.x.

There are new components: pe:countDown, pe:knob, pe:gravatar, pe:documentViewer, pe:analogClock, pe:gChart. I have blogged about them.

The new deployet showcase will be available soon as usually here. The next release will be a maintenance release. It is time for bugfixing.

Have fun!

Sunday, October 12, 2014

WAI-ARIA support for AutoComplete widget

In this post I would like to discuss the accessibility for an AutoComplete widget. A typically AutoComplete widget provides suggestions while you type into the field. On my current work I implemented an JSF component on basis of Twitter's Typeahead - a flexible JavaScript library that provides a strong foundation for building robust typeaheads. The Typeahead widget has a solid specification in form of pseudocode that details how the UI reacts to events. The Typeahed can show a hint in the corresponsing input field, like the google's search field shows it, highlight matches, deal with custom datasets and precompiled template. Furthermore, the Bloodhound suggestion engine offers prefetching, intelligent caching, fast lookups, and backfilling with remote data.


Despite many features, one big shortcoming of the Typeahead is an insufficient WAI-ARIA support (I would say it was completely missing until now). An AutoComplete widget should be designed to be accessible out of the box to users of screen readers and other assistive tools. I have decided to add a fully WAI-ARIA support, done this taks and sent my pull request to the GitHub. Below is the new "WAI-ARIA aware" markup with an explanaition (not relevant HTML attributes are omitted).
<input class="typeahead tt-hint" aria-hidden="true">

<input class="typeahead tt-input" role="combobox"
    aria-autocomplete="list/both"
    aria-owns="someUniqueID"
    aria-activedescendant="set dynamically to someUniqueID-1, etc."
    aria-expanded="false/true">
  
<span id="someUniqueID" class="tt-dropdown-menu" role="listbox">
    <div class="tt-dataset-somename" role="presentation">
        ...
        <span class="tt-suggestions" role="presentation">
            <div id="someUniqueID-1" class="tt-suggestion" role="option">
                ... single suggestion ...
            </div>
            ...
        </span>
        ...
    </div>
</span>

<span class="tt-status" role="status" aria-live="polite" style="border:0 none; clip:rect(0, 0, 0, 0); height:1px;
      width:1px; margin:-1px; overflow:hidden; padding:0; position:absolute;">
      ... HTML string or a precompiled template ...
</span>
The first input field with the class tt-hint simulates a visual hint (s. the picture above). The hint completes the input query to the matched suggestion visually. The query can be completed to the suggestion (hint) by pressing either right arrow or tab key. The hint is not relevant for the screen readers, hence we can apply the aria-hidden="true" to that field. The hint is ignored by screen readers then. Why is it not important? Because we will force reading the matched suggestion more intelligent by the "status" area with aria-live="polite" (will be explained below).

The next input field is the main element where the user inputs query. It should have a role="combobox". This is a recommended role for an AutoComplete. See the official WAI-ARIA docu for more details. In fact, the docu also shows a rough markup structure of an AutoComplete!

The main input field should have various ARIA states and properties. aria-autocomplete="list" indicates that the input provides autocomplete suggestions in the form of a list as the user types. aria-autocomplete="both" indicates that suggestions are also provided by a hint (additional to a list). The property aria-owns indicates that there is a parent / child relationship between the input field and the list with suggestions. This property should be always set when the DOM hierarchy cannot be used to represent the relationship. Otherwise, screen readers will get a problem to find a list with suggestions. In our case, it points to the ID of the list. The most interesting property is aria-activedescendant. A sightless user navigates through the list via arrow keys. The property aria-activedescendant propagates changes in focus to assistive technology - it is adjusted to reflect the ID attribute of the current child element which has been navigated to. In the picture above, the item "Lawrence of Arabia" is selected (highlighted). aria-activedescendant is set to the ID of this item and screen readers read to blind users "Lawrence of Arabia". Note: the focus stays on the input field, so that you can still edit the input value. I suggest to read more about this property in the Google's Introduction to Web Accessibility.


The property aria-expanded indicates whether the list with suggestions is expanded (true) or collapsed (false). This property will be updated automatically when the list's state changes.

The list with suggestions itself should have a role "listbox". That means, the widget allows the user to select one or more items from a list of choices. role="option" should be applied to individual result item nodes within the list. There is an interesting article "Use "listbox" and "option" roles when constructing AutoComplete lists", which I suggest to read. Not important for the screen readers parts should be marked with role="presentation". This role says "My markup is only for non sightless users". You probably ask, what is about the role="application"? Is it important for us? Not really. I skipped it after reading "Not All ARIA Widgets Deserve role="application"".

The last element in the markup is a span with the role="status" and the property aria-live="polite". What it is good for? You can spice up your widget by letting the user know that autocomplete results are available via a text that gets automatically spoken. The text to be spoken should be added by the widget to an element that is moved outside the viewport. This is the mentioned span element with applied styles. The styles are exactly the same as the jQuery CSS class ui-helper-hidden-accessible, which hides content visually, but leaves it available to assistive technologies. The property aria-live="polite" on the span element means – updates within this element should be announced at the next graceful interval, such as when the user stops typing. Generally, The aria-live property indicates a section within the content that is live and the verbosity in which changes shall be announced. I defined the spoken text for the AutoComplete in my project as an JavaScript template compiled by Handlebars (any other templating engine such as Hogan can be used too).
Handlebars.compile(
    '{{#unless isEmpty}}{{count}} suggestions available.' +
    '{{#if withHint}}Top suggestion {{hint}} can be chosen by right arrow or tab key.' +
    '{{/if}}{{/unless}}')
When user stops to type and suggestions are shown, a screen reader reads the count of available suggestions and the top suggestion. Really nice.

Last but not least is the testing. If you do not already have a screen reader installed, install the Google Chrome extensions ChromeVox and Accessibility Developer Tools. These are good tools for the development. Please watch a short ChromeVox demo and a demo for Accessibility Developer Tools too. Alternative, you can also try a free standalone screen reader NVDA. Simple give the tools a try.

Friday, September 19, 2014

Brand new JSF components in PrimeFaces Extensions

The PrimeFaces Extensions team is glad to announce several new components for the upcoming 3.0.0 main release. Our new committer Francesco Strazzullo gave a "Turbo Boost" for the project and brought at least 6 JSF components which have been successfully intergrated! The current development state is deployet on OpenShift - please look the showcase Below is a short overview about added components with screenshots.

Analog Clock. This is a component similar to digital PrimeFaces Clock, but as an analog variant, enhanced with advanced settings.


Countdown. It simulates a countdown and fires an JSF listener after an customizable interval. You can start, stop and pause the countdown.


DocumentViewer. This is JSF wrapper of Mozilla Foundation project PDF.js - a full HTML PDF reader.


GChart. This is a JSF wrapper of Google Charts API. It's the same chart library used by Google Analytics and other Google services. Please look at Organizational Chart and Geo Chart.


A small note from me: charts can be built completely by model in Java. There is only one GChartModel which allows to add any options you want programmatically. I have used the same approach for my Chart library based on Flotcharts (thinking right now about adding it to the PF Extensions). There is only one generic model with generic setters to set options (options are serialized to JSON then). Advantage: you can export a chart on the server-side, e.g. with PhantomJS. This is a different approach to PrimeFaces' charts where each chart type has a separate model class and hard-coded fix methods for options settings.

Gravatar. This is a component for Gravatar services.


Knob. This is a nice theme-aware component to insert numeric values in a range. It has many settings for visual customization, AJAX listener and more.


Last but not least: we plan to deploy current SNAPSHOTs on the OpenShift in the future. More new components are coming soon. I intend to bring a component called pe:typeahead to the 3.0.0 too. It is based on Twitter's Typeahed. In the next post, I will explain how I have added an excellent WAI ARIA support to this great autocomplete widget. Stay tuned!

Friday, August 22, 2014

PrimeFaces Extensions 2.1.0 released

Today, we released the PrimeFaces Extensions 2.1.0. This is a maintenance release with many fixed issues and some new features for the existing components. The full issue list is on the GitHub.

As usually, you will find all infos on the homepage. The release is available in the Maven central repo.

Good news:
  • New snapshots and releases seem to be uploaded perodically to the public Sonatype's repository again, so that everybody can download them from there.
  • We will have new "sexy" components in the next main release because we could win a new commiter for us. His name is Francesco Strazzullo and he is a creator of StrazzFaces. The plan is to adopt his components for the PrimeFaces Extensions. Furthermore, I plan to bring cool components too (although I have less free time due to my current work).
  • PrimeFaces Extensions will go PRO! Thanks to Cagatay for this idea and his support. Please follow his announcement soon.

Have fun!

Sunday, July 13, 2014

How to get JSON response from JSF?

Many JavaScript widgets expect data and options in JSON format. Nowadays, it is really easy to choose a cool widget and wrap it in a composite component. But the first question is how to send an AJAX request and to recieve a response in a proper JSON format. This question is often raised by JSF users. All what you need is a XHTML facelet like this one
<f:view encoding="UTF-8" contentType="text/html"
    xmlns="http://www.w3.org/1999/xhtml"
    xmlns:h="http://xmlns.jcp.org/jsf/html"
    xmlns:f="http://xmlns.jcp.org/jsf/core">
  <h:outputText value="#{stationView.getClosestStations(param.longitude, param.latitude)}" escape="false"/>
</f:view>
Please consider the contentType="text/html" (application/json will not work here) and escape="false" in the h:outputText. The method getClosestStations() in the bean StationView produces an JSON output for a list of special Java objects. I advise to use the Gson library in order to serialize any Java object to JSON. Short example:
String[] strings = {"abc", "def", "ghi"};
Gson gson = new Gson();
gson.toJson(strings);  ==> prints ["abc", "def", "ghi"]
The XHTML file above is located under the web context. Say, under the path /rest/stations.xhtml. Ajax call in your JavaScript code should look like this one:
$.ajax({
    url: requestContextPath + '/rest/stations.xhtml',
    type: "GET",
    data: {
        "longitude": x,
        "latitude": y
    },
    dataType: "json",
    success: function (data) {
        $.each(data, function (i, station) {
            ...
        });
    },
    error: function () {
        ...
    }
});
Please refer the jQuery docu for more information regarding $.ajax. Note: if you omit dataType: "json", you have to parse the JSON string manually.
success: function (data) {
    $.each($.parseJSON(data), function (i, station) {
        ...
    });
}
The response is a pure JSON string (no HTML tags) like this one:
[{"latitude":46.947045,"longitude":7.443922,"distanz":110,"name":"Bern, Bundesplatz"},{....},...]
Need more examples for JSON response in JSF? In one of my next post I will probably explain how to implement a cool autocomplete component without writing too much code.

Monday, July 7, 2014

How to implement a custom password strength indicator in JSF

Verifying password strength using JavaScript is a common task. In this post, I will show how to add a password strength indicator to an JSF based web application. The password component in PrimeFaces already has a feedback indicator of the password strength, but it has two major shortcomings:
  • Feedback indicator is not responsive (fix width, not mobile friendly, etc.)
  • Rules for the password strength verification are hard coded in JavaScript. No customization is possible.
What we need is a good looking, easy customizable and responsive password strength indicator / meter. Fortunately, PrimeFaces has another component - progress bar which we can use for our purpose. This is not a misusage. The end result is actually impressive.

Let's start with XHTML. First, define a quite normal passwort field.
 
<p:password id="passwort" value="#{mybean.password}" label="Password" required="true" autocomplete="off"/>
 
Second, define a progress bar with displayOnly="true" and some messages for the passwort strength (weak, medium, strong).
<div style="white-space:nowrap;">
    <h:outputText value="Password strength "/>
    <h:outputText id="pwdWeak" value="weak" style="display:none" styleClass="bold weakMsg"/>
    <h:outputText id="pwdMedium" value="medium" style="display:none" styleClass="bold mediumMsg"/>
    <h:outputText id="pwdStrong" value="strong" style="display:none" styleClass="bold strongMsg"/>
</div>
<p:progressBar id="pwdStrength" value="0" styleClass="pwdStrength" displayOnly="true"/>
Let's go to the JavaScript part. We need a script block (placed somewhere after the p:progressBar) where we intend to invoke a custom JS function setupPasswordStrength().
<script type="text/javascript">
    $(document).ready(function () {
        setupPasswordStrength("passwort", "pwdStrength");
    });
</script>
The JS function has two arguments: an Id of the password field and an Id of the progress bar. In the function, we will register a callback for the namespaced keyup event. In the callback, we will check the current input value by means of reg. expressions. We would like to take the following rules (rules are up to you):
  • Password length is less than 8 characters or doesn't contain at least one digit ==> weak password
  • Password length is equal or greater than 8 characters, contains at least one digit, but doesn't have at least one lower and one upper case letter OR one special char: ==> medium password
  • Password length is equal or greater than 8 characters, contains at least one digit AND has at least one lower and one upper case letter OR one special char: ==> strong password
These are good rules I have often seen across the internet. Let's me show the JS function.
function setupPasswordStrength(pwdid, pbarid) {
    // reg. exp. for a weak password
    var weak = XRegExp("^(?=.*\\d{1,}).{8,}$");
    // reg. exp. for a strong password
    var strong = XRegExp("^(?=.*[a-z])(?=.*[A-Z]).+|(?=.*[!,%,&,@,#,$,^,*,?,_,~,\\-]).+$");

    var $this = $("#" + pwdid);
    var pbar = $("#" + pbarid).find(".ui-progressbar-value");

    // visualize on keyup
    $this.off('keyup.' + pwdid).on('keyup.' + pwdid, function(e) {
        visualizePasswordStrength($(this).val(), pbar, weak, strong);
    });

    // fix chrome issue with autofill fields
    setTimeout(function(){$this.triggerHandler('keyup.' + pwdid);}, 150);
}

function visualizePasswordStrength(pwd, pbar, weak, strong) {
    var pparent = pbar.parent().parent().parent();
    var weakMsg = pparent.find(".weakMsg");
    var mediumMsg = pparent.find(".mediumMsg");
    var strongMsg = pparent.find(".strongMsg");

    if (pwd == null || pwd.length < 1) {
        pbar.removeClass("weak medium strong");
        weakMsg.hide();
        mediumMsg.hide();
        strongMsg.hide();
        return;
    }

    if (!weak.test(pwd)) {
        // weak
        pbar.removeClass("medium strong").addClass("weak");
        mediumMsg.hide();
        strongMsg.hide();
        weakMsg.show();
        return;
    }

    if (!strong.test(pwd)) {
        // medium
        pbar.removeClass("weak strong").addClass("medium");
        weakMsg.hide();
        strongMsg.hide();
        mediumMsg.show();
        return;
    }

    // strong
    pbar.removeClass("weak medium").addClass("strong");
    weakMsg.hide();
    mediumMsg.hide();
    strongMsg.show();
}
In the function visualizePasswordStrength(), we remove and add style classes to the progress bar dependent on the password strength (when user is typing his password). They are
.weak {
    background-color: #F88E7D !important;
    border: 1px solid #F95D24 !important;
    width: 33.33% !important;
}

.medium {
    background-color: #FEE379 !important;
    border: 1px solid #EDB605 !important;
    width: 66.66% !important;
}

.strong {
    background-color: #81FF6C !important;
    border: 1px solid #05E428 !important;
    width: 101% !important;
}
The weak indicator reserves one-third of the progress bar's length. The medium and strong indicators reserve respectively two-thirds and all available space. The styling of the progress bar looks as follows:
.pwdStaerke.ui-progressbar {
    -moz-border-radius: 6px;
    -webkit-border-radius: 6px;
    border-radius: 6px;
    margin-top: 8px;
    height: 18px !important;
    border: solid 1px #c2c2c2 !important;
}

.pwdStaerke.ui-progressbar .ui-progressbar-value {
    display: block !important;
    margin-left: -2px !important;
    -moz-border-radius: 6px !important;
    -webkit-border-radius: 6px !important;
    border-radius: 6px !important;
}

Monday, May 5, 2014

PrimeFaces Extensions 2.0.0 released

A brand new release of PrimeFaces Extensions 2.0.0 is available in the Maven central repo. This release is built on top of PrimeFaces 5.0. Here are some links as usually:
The next release 2.1.0 will bring new components and new stuff. The best is yet to come.

Have fun!

Saturday, April 19, 2014

Creating dynamic JSF Components

You can often read a question how to create dynamic JSF 2 components. That means a programmatically combining already existing components to a dynamic one - just like a puzzle. There are some advices on the internet which don't work reliable in all cases. In this article for instance, the author tried to use PostAddToViewEvent, but had some troubles, and ended up then with an implementation which doesn't consider component's changes on postback. I would like to show a simple and reliable way for creating dynamic JSF 2 components.

The main question is at which time, better to say JSF phase, the components should be created? I suggest to use PreRenderComponentEvent and add all components there. In this blog post, we will create a component called DynamicButtons. DynamicButtons consists of multiple dynamic buttons. Every dynamic button is an abstraction. It is either a PrimeFaces command button or menu item. It depends on component's configuration how a dynamic button should be rendered - as command button or as menu item. In short words, DynamicButtons is a component which shows X command buttons and a menu button with items if more than X dynamic buttons are available. Here is a picture.


The component's tag is d:dynamicButtons. Every single dynamic button is condigured by the tag d:dynamicButton which has the same attributes as p:commandButton and p:menuitem. Sure, not all attributes of p:commandButton and p:menuitem are equal - some attributes in the d:dynamicButton are not availbale for items in the menu button (e.g. widgetVar). The XHTML snippet to the picture above demonstrates the usage of some attributes.
<p:growl showSummary="true" showDetail="false" autoUpdate="true"/>
<p:messages id="msgs" showSummary="true" showDetail="false"/>

<p:notificationBar position="top" effect="slide" widgetVar="bar">
    <h:outputText value="..."/>
</p:notificationBar>

<d:dynamicButtons id="dynaButtons" labelMenuButton="More Actions" iconPosMenuButton="right"
                  positionMenuButton="#{dynamicButtonsController.posMenuButton}">
    <d:dynamicButton value="Show notification" type="button" onclick="PF('bar').show()"/>
    <d:dynamicButton value="Hide notification" type="button" onclick="PF('bar').hide()"/>
    <d:dynamicButton value="Create" icon="ui-icon-plus" process="@this"
                        action="#{dynamicButtonsController.someAction('Create')}"/>
    <d:dynamicButton value="Edit" icon="ui-icon-pencil" process="@this"
                        action="#{dynamicButtonsController.someAction('Edit')}"/>
    <d:dynamicButton value="Delete" icon="ui-icon-trash" process="@this"
                        action="#{dynamicButtonsController.someAction('Delete')}"/>
    <d:dynamicButton value="Save" icon="ui-icon-disk" process="@this"
                        action="#{dynamicButtonsController.someAction('Save')}"/>
    <d:dynamicButton value="Log Work" icon="ui-icon-script" global="false" process="@this" update="msgs"
                        ignoreAutoUpdate="true" actionListener="#{dynamicButtonsController.logWork}"/>
    <d:dynamicButton value="Attach File" icon="ui-icon-document" global="false"/>
    <d:dynamicButton value="Move" icon="ui-icon-arrowthick-1-e" global="false"/>
    <d:dynamicButton value="Clone" icon="ui-icon-copy" disabled="true"/>
    <d:dynamicButton value="Comment" icon="ui-icon-comment" title="This is the comment action"/>
    <d:dynamicButton value="Homepage" icon="ui-icon-home" title="Link to the homepage" ajax="false"
                        action="/views/home?faces-redirect=true"/>
</d:dynamicButtons>
The position of the menu button is configurable by the attribute positionMenuButton. positionMenuButton defines the start index of buttons rendered in a menu button as items vertically. A valid position begins with 1. Negative or 0 value means that no menu button is rendered (all buttons are rendered horizontally). The current position can be controlled by a bean.
@Named
@ViewScoped
public class DynamicButtonsController implements Serializable {
    
    private int posMenuButton = 7;

    public void someAction(String button) {
        FacesContext ctx = FacesContext.getCurrentInstance();
        FacesMessage message = new FacesMessage("Action of the button '" + button + "' has been invoked");
        message.setSeverity(FacesMessage.SEVERITY_INFO);
        ctx.addMessage(null, message);
    }
    
    public void logWork(ActionEvent event) {
        FacesContext ctx = FacesContext.getCurrentInstance();
        FacesMessage message = new FacesMessage("Action listener for 'Log Work' has been invoked");
        message.setSeverity(FacesMessage.SEVERITY_INFO);
        ctx.addMessage(null, message);
    }

    public int getPosMenuButton() {
        return posMenuButton;
    }

    public void setPosMenuButton(int posMenuButton) {
        this.posMenuButton = posMenuButton;
    }
}
Let's create dynamic buttons. I will only show the code which is important to get the idea. First of all we need a TagHandler behind the d:dynamicButton. It's called DynamicButtonTagHandler. DynamicButtonTagHandler collects values of all attributes defined in the d:dynamicButton and buffers them in the data container object DynamicButtonHolder. The object DynamicButtonHolder is saved in the attributes map of the parent component DynamicButtons (component behind the d:dynamicButtons tag).
public class DynamicButtonTagHandler extends TagHandler {

    private final TagAttribute value;
    private final TagAttribute widgetVar;
    private final TagAttribute rendered;
    private final TagAttribute ajax;
    private final TagAttribute process;
 
    // other attributes
    ...
 
    private final TagAttribute action;
    private final TagAttribute actionListener;

    public DynamicButtonTagHandler(TagConfig config) {
        super(config);

        this.value = this.getAttribute("value");
        this.widgetVar = this.getAttribute("widgetVar");
        this.rendered = this.getAttribute("rendered");
        this.ajax = this.getAttribute("ajax");
        this.process = this.getAttribute("process");
  
        // handle other attributes
        ...
  
        this.action = this.getAttribute("action");
        this.actionListener = this.getAttribute("actionListener");
    }

    @Override
    public void apply(FaceletContext ctx, UIComponent parent) throws IOException {
        if (!ComponentHandler.isNew(parent)) {
            return;
        }

        @SuppressWarnings("unchecked")
        List<DynamicButtonHolder> holders = (List<DynamicButtonHolder>) parent.getAttributes().get(
                DynamicButtons.DYNAMIC_BUTTON_ATTR_HOLDER);
        if (holders == null) {
            holders = new ArrayList<DynamicButtonHolder>();
            parent.getAttributes().put(DynamicButtons.DYNAMIC_BUTTON_ATTR_HOLDER, holders);
        }

        DynamicButtonHolder holder = new DynamicButtonHolder();

        if (value != null) {
            if (value.isLiteral()) {
                holder.setValue(value.getValue());
            } else {
                holder.setValue(value.getValueExpression(ctx, Object.class));
            }
        }

        if (widgetVar != null) {
            if (widgetVar.isLiteral()) {
                holder.setWidgetVar(widgetVar.getValue());
            } else {
                holder.setWidgetVar(widgetVar.getValueExpression(ctx, String.class));
            }
        }

        if (rendered != null) {
            if (rendered.isLiteral()) {
                holder.setRendered(Boolean.valueOf(rendered.getValue()));
            } else {
                holder.setRendered(rendered.getValueExpression(ctx, Boolean.class));
            }
        }

        if (ajax != null) {
            if (ajax.isLiteral()) {
                holder.setAjax(Boolean.valueOf(ajax.getValue()));
            } else {
                holder.setAjax(ajax.getValueExpression(ctx, Boolean.class));
            }
        }

        if (process != null) {
            if (process.isLiteral()) {
                holder.setProcess(process.getValue());
            } else {
                holder.setProcess(process.getValueExpression(ctx, String.class));
            }
        }

        // handle other values
        ...

        if (action != null) {
            holder.setActionExpression(action.getMethodExpression(ctx, String.class, new Class[]{}));
        }

        if (actionListener != null) {
            holder.setActionListener(new MethodExpressionActionListener(actionListener.getMethodExpression(
                    ctx, Void.class, new Class[]{ActionEvent.class})));
        }

        // add data
        holders.add(holder);
    }
}
Data container class DynamicButtonHolder looks simple.
public class DynamicButtonHolder {

    private Object value;
    private Object widgetVar;
    private Object rendered;
    private Object ajax;
    private Object process;
 
    // other attributes
    ...
 
    private MethodExpression actionExpression;
    private ActionListener actionListener;

    public Object getValue() {
        return value;
    }

    public void setValue(Object value) {
        this.value = value;
    }

    public Object getWidgetVar() {
        return widgetVar;
    }

    public void setWidgetVar(Object widgetVar) {
        this.widgetVar = widgetVar;
    }

    public Object getRendered() {
        return rendered;
    }

    public void setRendered(Object rendered) {
        this.rendered = rendered;
    }

    public Object getAjax() {
        return ajax;
    }

    public void setAjax(Object ajax) {
        this.ajax = ajax;
    }

    public Object getProcess() {
        return process;
    }

    public void setProcess(Object process) {
        this.process = process;
    }

    // setter / getter for other attributes
    ...

    public MethodExpression getActionExpression() {
        return actionExpression;
    }

    public void setActionExpression(MethodExpression actionExpression) {
        this.actionExpression = actionExpression;
    }

    public ActionListener getActionListener() {
        return actionListener;
    }

    public void setActionListener(ActionListener actionListener) {
        this.actionListener = actionListener;
    }
}
The component class DynamicButtons extends HtmlPanelGroup and registers itself as a listener for PreRenderComponentEvent. Command buttons and menu items in the menu button (see positionMenuButton) are added dynamically to the panel group in the method processEvent(). It happens shortly before the rendering phase.
@FacesComponent(value = "examples.component.DynamicButtons")
@ListenerFor(systemEventClass = PreRenderComponentEvent.class)
public class DynamicButtons extends HtmlPanelGroup {

    private static final String OPTIMIZED_PACKAGE = "examples.component.";
    public static final String DYNAMIC_BUTTON_ATTR_HOLDER = "dynamicButtonAttrHolder";

    enum PropertyKeys {
        disabled,
        positionMenuButton,
        labelMenuButton,
        iconPosMenuButton
    }

    public DynamicButtons() {
        super();
    }

    public boolean isDisabled() {
        return (Boolean) getStateHelper().eval(PropertyKeys.disabled, false);
    }

    public void setDisabled(boolean disabled) {
        getStateHelper().put(PropertyKeys.disabled, disabled);
    }

    public Integer getPositionMenuButton() {
        return (Integer) getStateHelper().eval(PropertyKeys.positionMenuButton, 0);
    }

    public void setPositionMenuButton(Integer positionMenuButton) {
        getStateHelper().put(PropertyKeys.positionMenuButton, positionMenuButton);
    }

    public String getLabelMenuButton() {
        return (String) getStateHelper().eval(PropertyKeys.labelMenuButton, null);
    }

    public void setLabelMenuButton(String labelMenuButton) {
        getStateHelper().put(PropertyKeys.labelMenuButton, labelMenuButton);
    }

    public String getIconPosMenuButton() {
        return (String) getStateHelper().eval(PropertyKeys.iconPosMenuButton, "left");
    }

    public void setIconPosMenuButton(String iconPosMenuButton) {
        getStateHelper().put(PropertyKeys.iconPosMenuButton, iconPosMenuButton);
    }

    /**
     * {@inheritDoc}
     */
    public void processEvent(ComponentSystemEvent event) throws AbortProcessingException {
        super.processEvent(event);

        if (!(event instanceof PreRenderComponentEvent)) {
            return;
        }

        // add components to this panel group
        addComponents();
    }

    private void addComponents() {
        if (!isRendered()) {
            return;
        }

        @SuppressWarnings("unchecked")
        List<DynamicButtonHolder> holders = (List<DynamicButtonHolder>) getAttributes().get(
                DynamicButtons.DYNAMIC_BUTTON_ATTR_HOLDER);
        if (holders == null) {
            return;
        }

        // first remove all children
        this.getChildren().clear();

        final FacesContext fc = FacesContext.getCurrentInstance();
        MenuButton menuButton = null;
        int posMenuButton = getPositionMenuButton();

        for (int i = 0; i < holders.size(); i++) {
            DynamicButtonHolder holder = holders.get(i);

            if (posMenuButton <= 0 || i < posMenuButton - 1) {
                // create single command button
                createCommandButton(fc, holder, i);
            } else {
                if (menuButton == null) {
                    // create menu button
                    menuButton = (MenuButton)fc.getApplication().createComponent(MenuButton.COMPONENT_TYPE);
                    menuButton.setId(this.getId() + "_mbutton");
                    menuButton.setDisabled(isDisabled());
                    menuButton.setIconPos(getIconPosMenuButton());
                    menuButton.setValue(getLabelMenuButton());
                    menuButton.setStyleClass("dynaMenuButton");

                    // add as child to this component
                    this.getChildren().add(menuButton);
                }

                // create menuitem for menu button
                createMenuitem(fc, menuButton, holder, i);
            }
        }
    }

    private void createCommandButton(FacesContext fc, DynamicButtonHolder holder, int i) {
        CommandButton commandButton = (CommandButton)fc.getApplication().createComponent(
                CommandButton.COMPONENT_TYPE);
        commandButton.setId(this.getId() + "_cbutton_" + i);
        commandButton.setStyleClass("dynaCommandButton");

        // add to the children
        this.getChildren().add(commandButton);

        ELContext ec = fc.getELContext();

        Object value = getValue(ec, holder);
        if (value != null) {
            commandButton.setValue(value);
        }

        String widgetVar = getWidgetVar(ec, holder);
        if (StringUtils.isNotBlank(widgetVar)) {
            commandButton.setWidgetVar(widgetVar);
        }

        Boolean rendered = isRendered(ec, holder);
        if (rendered != null) {
            commandButton.setRendered(rendered);
        }

        Boolean ajax = isAjax(ec, holder);
        if (ajax != null) {
            commandButton.setAjax(ajax);
        }

        String process = getProcess(ec, holder);
        if (StringUtils.isNotBlank(process)) {
            commandButton.setProcess(process);
        }

        // handle other attributes
        ...

        MethodExpression me = holder.getActionExpression();
        if (me != null) {
            commandButton.setActionExpression(me);
        }

        ActionListener actionListener = holder.getActionListener();
        if (actionListener != null) {
            commandButton.addActionListener(actionListener);
        }
    }

    private void createMenuitem(FacesContext fc, MenuButton menuButton, DynamicButtonHolder holder, int i) {
        UIMenuItem menuItem = (UIMenuItem)fc.getApplication().createComponent(UIMenuItem.COMPONENT_TYPE);
        menuItem.setId(this.getId() + "_menuitem_" + i);
        menuItem.setStyleClass("dynaMenuitem");

        // add to the children
        menuButton.getChildren().add(menuItem);

        ELContext ec = fc.getELContext();

        Object value = getValue(ec, holder);
        if (value != null) {
            menuItem.setValue(value);
        }

        Boolean rendered = isRendered(ec, holder);
        if (rendered != null) {
            menuItem.setRendered(rendered);
        }

        Boolean ajax = isAjax(ec, holder);
        if (ajax != null) {
            menuItem.setAjax(ajax);
        }

        String process = getProcess(ec, holder);
        if (StringUtils.isNotBlank(process)) {
            menuItem.setProcess(process);
        }

        // handle other attributes
        ...

        MethodExpression me = holder.getActionExpression();
        if (me != null) {
            menuItem.setActionExpression(me);
        }

        ActionListener actionListener = holder.getActionListener();
        if (actionListener != null) {
            menuItem.addActionListener(actionListener);
        }
    }

    private Object getValue(ELContext ec, DynamicButtonHolder holder) {
        Object value;
        Object objValue = holder.getValue();
        if (objValue instanceof ValueExpression) {
            value = ((ValueExpression) objValue).getValue(ec);
        } else {
            value = objValue;
        }

        return value;
    }

    private String getWidgetVar(ELContext ec, DynamicButtonHolder holder) {
        String widgetVar = null;
        Object objWidgetVar = holder.getWidgetVar();
        if (objWidgetVar instanceof ValueExpression) {
            widgetVar = (String) ((ValueExpression) objWidgetVar).getValue(ec);
        } else if (objWidgetVar instanceof String) {
            widgetVar = (String) objWidgetVar;
        }

        return widgetVar;
    }

    private Boolean isRendered(ELContext ec, DynamicButtonHolder holder) {
        Boolean rendered = null;
        Object objRendered = holder.getRendered();
        if (objRendered instanceof ValueExpression) {
            rendered = (Boolean) ((ValueExpression) objRendered).getValue(ec);
        } else if (objRendered instanceof Boolean) {
            rendered = (Boolean) objRendered;
        }

        return rendered;
    }

    private Boolean isAjax(ELContext ec, DynamicButtonHolder holder) {
        Boolean ajax = null;
        Object objAjax = holder.getAjax();
        if (objAjax instanceof ValueExpression) {
            ajax = (Boolean) ((ValueExpression) objAjax).getValue(ec);
        } else if (objAjax instanceof Boolean) {
            ajax = (Boolean) objAjax;
        }

        return ajax;
    }

    private String getProcess(ELContext ec, DynamicButtonHolder holder) {
        String process = null;
        Object objProcess = holder.getProcess();
        if (objProcess instanceof ValueExpression) {
            process = (String) ((ValueExpression) objProcess).getValue(ec);
        } else if (objProcess instanceof String) {
            process = (String) objProcess;
        }

        return process;
    }

    // get other values
    ...

    public void setAttribute(PropertyKeys property, Object value) {
        getStateHelper().put(property, value);

        // some magic code which is not relevant here
        ...
    }
}
DynamicButtons and DynamicButtonTagHandler should be registered in a *.taglib.xml file.
<tag>
    <description>
        <![CDATA[Dynamic buttons.]]>
    </description>
    <tag-name>dynamicButtons</tag-name>
    <component>
        <component-type>examples.component.DynamicButtons</component-type>
        <renderer-type>javax.faces.Group</renderer-type>
    </component>
    <attribute>
        <description>
            <![CDATA[Unique identifier of the component in a NamingContainer.]]>
        </description>
        <name>id</name>
        <required>false</required>
        <type>java.lang.String</type>
    </attribute>
    ...
</tag>

<tag>
    <description>
        <![CDATA[Holder for dynamic button's attributes.]]>
    </description>
    <tag-name>dynamicButton</tag-name>
    <handler-class>examples.taghandler.DynamicButtonTagHandler</handler-class>
    <attribute>
        <description><![CDATA[Label of the component.]]></description>
        <name>value</name>
        <required>false</required>
        <type>java.lang.Object</type>
    </attribute>
    ...
</tag>

Sunday, March 30, 2014

Set up JSF environment for JUnit tests

JUnit tests often need mocked JSF / Servlet objects when you test JSF based web applications. Such objects can be FacesContext, ExternalContext, ApplicationContext, HttpRequest, HttpSession, etc. I already mentioned the MyFaces Test Framework in one of my outdated post. In this post, I would like to introduce a new simple and lightweight approach based on JUnit TestRule. The concept behind TestRule is similar to custom JUnit runners, but without restrictions (you can not use multiple runners, but you can use multiple TestRules). Let's go step by step to explain the idea. A class which implements the interface TestRule must implement the method
Statement apply(Statement base, Description description)
The first Statement parameter is a specific object which reprensents the method under the test from your test class. Such a test method can be invoked by base.evaluate(). You can place any custom code before and after the call base.evaluate(). A typically implementation follows this pattern
public Statement apply(final Statement base, Description description) {
    return new Statement() {
        @Override
        public void evaluate() throws Throwable {
            // do something before invoking the method to be tested
            ...
            try {
                base.evaluate();
            } finally {
                // do something after invoking the method to be tested
                ...
            }
        }
    };
}
In short words: the apply method allows to intercept the base call of every test method and put a custom code around. Your TestRule implementation, say MyRule, can be used in any test class with the @Rule annotation as follows:
@Rule
public TestRule myRule = new MyRule();
Note: The member variable should be public. Let's take more examples. There is a good introduction in this tutorial. The author demonstrates how to implement two TestRules: one for SpringContext to use @Autowired in test classes and one for Mockito to populate the mocks before each test. An excellent example! I allow me to repeat the usage example.
public class FooTest {

    @Rule
    public TestRule contextRule = new SpringContextRule(new String[]{"testContext.xml"}, this);

    @Rule
    public TestRule mockRule = new MockRule(this);

    @Autowired
    public String bar;

    @Mock
    public List baz;

    @Test
    public void testBar() throws Exception {
        assertEquals("bar", bar);
    }

    @Test
    public void testBaz() throws Exception {
        when(baz.size()).thenReturn(2);
        assertEquals(2, baz.size());
    }
}
This can not be achieved with two JUnit runners at once. E.g. you can not annotate a test class at the same time with @RunWith(Parameterized.class) and @RunWith(SpringJUnit4ClassRunner.class) or @RunWith(MockitoJUnitRunner.class).

But back to JSF. I want to show how to implement a TestRule for a simple and extensible JSF environment. First of all, we need a mock for FacesContext. We will implement it with Mockito - the most popular Java test framework. I have seen many different implementations, but in fact it is not difficult to implement a proper mock of FacesContext.
import javax.faces.context.FacesContext;

import org.mockito.Mockito;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;

public abstract class FacesContextMocker extends FacesContext {

    private FacesContextMocker() {
    }

    private static final Release RELEASE = new Release();

    private static class Release implements Answer<Void> {
        @Override
        public Void answer(InvocationOnMock invocation) throws Throwable {
            setCurrentInstance(null);
            return null;
        }
    }

    public static FacesContext mockFacesContext() {
        FacesContext context = Mockito.mock(FacesContext.class);
        setCurrentInstance(context);
        Mockito.doAnswer(RELEASE).when(context).release();
        return context;
    }
}
For all PrimeFaces fan we will provide a similar mock for RequestContext.
import org.primefaces.context.RequestContext;

import org.mockito.Mockito;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;

public abstract class RequestContextMocker extends RequestContext {

    private RequestContextMocker() {
    }

    private static final Release RELEASE = new Release();

    private static class Release implements Answer<Void> {
        @Override
        public Void answer(InvocationOnMock invocation) throws Throwable {
            setCurrentInstance(null);
            return null;
        }
    }

    public static RequestContext mockRequestContext() {
        RequestContext context = Mockito.mock(RequestContext.class);
        setCurrentInstance(context);
        Mockito.doAnswer(RELEASE).when(context).release();
        return context;
    }
}
Now, a minimal JSF / Servlet environment could be set up as follows
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import javax.faces.application.Application;
import javax.faces.component.UIViewRoot;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.mockito.Mockito;
import org.primefaces.context.RequestContext;

import org.junit.rules.TestRule;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;

public class JsfMock implements TestRule {

    public FacesContext mockFacesContext;
    public RequestContext mockRequestContext;
    public UIViewRoot mockViewRoot;
    public Application mockApplication;
    public ExternalContext mockExternalContext;
    public HttpSession mockHttpSession;
    public HttpServletRequest mockHttpServletRequest;
    public HttpServletResponse mockHttpServletResponse;

    @Override
    public Statement apply(final Statement base, final Description description) {
        return new Statement() {
            @Override
            public void evaluate() throws Throwable {
                init();
                try {
                    base.evaluate();
                } finally {
                    mockFacesContext.release();
                    mockRequestContext.release();
                }
            }
        };
    }

    protected void init() {
        mockFacesContext = FacesContextMocker.mockFacesContext();
        mockRequestContext = RequestContextMocker.mockRequestContext();
        mockApplication = Mockito.mock(Application.class);
        mockViewRoot = Mockito.mock(UIViewRoot.class);
        mockExternalContext = Mockito.mock(ExternalContext.class);
        mockHttpServletRequest = Mockito.mock(HttpServletRequest.class);
        mockHttpServletResponse = Mockito.mock(HttpServletResponse.class);
        mockHttpSession = Mockito.mock(HttpSession.class);

        Mockito.when(mockFacesContext.getApplication()).thenReturn(mockApplication);
        Mockito.when(mockApplication.getSupportedLocales()).thenReturn(createLocales().iterator());

        Mockito.when(mockFacesContext.getViewRoot()).thenReturn(mockViewRoot);
        Mockito.when(mockViewRoot.getLocale()).thenReturn(new Locale("en"));

        Mockito.when(mockFacesContext.getExternalContext()).thenReturn(mockExternalContext);
        Mockito.when(mockExternalContext.getRequest()).thenReturn(mockHttpServletRequest);
        Mockito.when(mockHttpServletRequest.getSession()).thenReturn(mockHttpSession);

        Map<String, String> requestMap = new HashMap<String, String>();
        Mockito.when(mockExternalContext.getRequestParameterMap()).thenReturn(requestMap);        
    }

    private List<Locale> createLocales() {
        ArrayList<Locale> locales = new ArrayList<>();
        locales.add(new Locale("en"));
        locales.add(new Locale("de"));
        ...
        return locales;
    }
}
We mocked the most used JSF / Servlet objects, linked them with each other and provided mocks via public member variables, so that they can be extended in test classes if needed. Below is an usage example which also demonstrates how to extend the mocked objects for a particular test.
public class PaymentRequestFormTest {

    private PaymentView paymentView;

    @Rule
    public JsfMock jsfMock = new JsfMock();

    @Before
    public void initialize() {
        paymentView = mock(PaymentView.class);
        ...
    }

    @Test
    public void toJson() {
        // Mock URL and context path
        StringBuffer requestURI = new StringBuffer("http://localhost:8080/webshop");
        Mockito.when(jsfMock.mockHttpServletRequest.getRequestURL()).thenReturn(requestURI);
        Mockito.when(jsfMock.mockHttpServletRequest.getContextPath()).thenReturn("/webshop");

        // Invoke toJson method
        String json = PaymentRequestForm.toJson(jsfMock.mockFacesContext, paymentView);

        // Verify
        ...
    }
}
Any feedbacks are welcome.

Wednesday, March 5, 2014

Learning Primefaces' Extensions Development

I'm glad to announce a new book Learning Primefaces' Extensions Development. The book is about various JSF components provided in the open source, community driven project PrimeFaces Extensions - an official project with additional components to the great PrimeFaces framework. PrimeFaces is a de-facto standard framework in the Java Web Development. There are already a couple of books about the PrimeFaces core: Cookbook, Started and Beginner's Guide.

What is the new book about? The book covers most important major features of the PrimeFaces Extensions. You will meet the additional JSF components, learn step-by-step how to use them in the PrimeFaces based rich JSF applications and get some ideas for writing your own components. This is a must for every JSF / PrimeFaces developer.

The book has been written by a team member of the PrimeFaces Extensions Sudheer Jonna. Thanks Sudheer for your contribution! I'm sure PrimeFaces users will be happy to hold the book in their hands.


Wednesday, January 1, 2014

PrimeFaces Extensions 1.2.1 was released with a new QRCode component

We are glad to announce the next release 1.2.1 of PrimeFaces Extensions (yes, 1.2.1 and not 1.2.0 due to some encountered issues in the newly released 1.2.0). This is a maintenance release which contains fixes for the components AjaxErrorHandler, FluidGrid, DynaForm, TimePicker, InputNumber and new features in Exporter (possibility to skip some components during export) and Waypoint (can be used now for horizontal scrolling as well).

Beside fixed issues (full list on GitHub) we added a new JSF component QRCode. QR Code is a two-dimensional barcode for multi-purpose using. Refer this article on Wikipedia if you don't know what it is.


The QR Code is generated completely on the client-side. Usage example:
<pe:qrCode renderMethod="canvas" 
           renderMode="2" 
           text="http://primefaces-extensions.github.io/"
           label="PF-Extensions"
           size="200"                 
           fillColor="7d767d"
           fontName="Ubuntu"
           fontColor="#01A9DB"
           ecLevel="H"                   
           radius="0.5"/>
Furthermore, the component library and the showcase were updated to fit JSF 2.2. The PrimeFaces team lead Çagatay Çivici has provided us his dedicated server for deployment. We would like to thank him for that! This is the same server the PrimeFaces showcase is running on. Please consider a new URL for our showcase. The old URLs are out of date (I've canceled my VPS). The showcase is running on Mojarra 2.2.x. But of course we test it on MyFaces as well.

The new release is available as usually in the Maven central repository. Have fun!

Edit: Çagatay Çivici told us that the demos including PrimeFaces showcase, labs and extensions crashed a couple of times, so that he had to undeploy the extensions' showcase. The current showcase is deployed to Amazon EC2 instance and is running on Tomcat 7 now. Thanks to our user sebargarcia.