Showing posts with label PrimeFaces. Show all posts
Showing posts with label PrimeFaces. Show all posts

Monday, 27 July 2015

Temporarily disable or conditional executing of PrimeFaces AJAX calls

Introduction

In JSF 2.0, the AJAX functionality is standardised in the specification and can be used in a consistent way between JSF implementations and component libraries like PrimeFaces.
With the addition of new functionality, new usage patterns become a habit. But new usages also brings more advanced scenarios with their own issues.

The situation I want to discuss today, is where you have the need for some partial screen update with AJAX but which you don't want in all situations. The conditional aspect which I referred to in the title of the text.

Problem description


Suppose you have the following screen area:


It contains the following elements from left to right
* A field to enter an existing code. When the end user leaves the field, the code is looked up.
* A second, read only field or label, where the description of the code is placed when it is an existing one.
* A button, which is only available when the first field doesn't contain an existing code and lets you add a new one.

Within the JSF page, the structure looks something like this.

<h:panelGroup id="codeArea">
    Code :
    <p:inputText value="#{codeBean.code}id="code">
        <p:ajax event="blur" listener="#{codeBean.onBlurCode}" update="codeArea"/>
    </p:inputText>
    <p:inputText value="#{codeBean.codeDescription}" disabled="true" placeholder="description"/>
    <p:commandButton icon="fa fa-plus-circle" actionListener="#{codeBean.addCode}" update="codeArea" disabled="#{empty codeBean.description}"/>
</h:panelGroup>

With the ajax tag within the input field, we can perform the partial screen update when we leave the input field. We need to update the complete group as the button needs to become disabled as we enter an existing code.

Conditional executing

This construct works perfectly when you tab out of the input field.  The blur event triggers the AJAX execution and the server side code checks if the code exists. Due to the partial screen update the button becomes disabled when the code doesn't exists or enabled when the code isn't found.

But there is a scenario which fails; when the focus is in the input field and we click on the command button.  You will found out that the click on the button is ignored.  

If we inspect what is happening in the network console of the browser; we see that there is an AJAX request to the server which corresponds to the blur event of the field.  But there is no request which corresponds to the click on the button.
This is because the blur event replaced the DOM element in the browser with another, for the end user identical component. So the click is on an element which no longer exist on the screen after the AJAX  completes.

So how can we solve this? Luckily PrimeFaces uses JQuery on the client side.  So when we could disable the onblur event execution in the case when we click on the button, we have a solution. And the good thing is that we can achieve this, quite easily.

The mousedown event is executed before the blur event. This is can bee seen by the following testing code. (thanks to mudassir)

So by adding the following code:

onmousedown="$(PrimeFaces.escapeClientId('frm:code')).off();"

We can remove all event handlers from the input field, and thus the click is executed.

Conclusion

Making the AJAX functionality can be easily achieved within PrimeFaces with the help of JQuery which is already available in the browser? In this text I showed you how you can disable the blur event in the case when you click a specific button but it will be active in other scenarios.



Monday, 8 June 2015

Focus HTML element after AJAX call with PrimeFaces


Introduction

The combination of AJAX updates to the screen and the focus of a field is more then once an issue for the developer. And this is not an issue of PrimeFaces, but comes with the fact of using AJAX.

This blog explains what you can due in the 2 most important scenarios what you normally encounter.

Problem description

Image you have on the screen 2 input fields, field A en field B.  There is an onBlur handler attached to field A which does a partial update of the screen, containing field B, with an AJAX call.

So what happens when the user is in field A en tabs out of the field? Leaving the field, results in the trigger of the onBlur handler. During the time that the AJAX calls is performed asynchronously, the browser performs the standard behaviour, and thus the focus is placed in the field B.

But then the AJAX call returns and results in updating the screen, and there are use cases where the developer decided to replace the field B. And since it is a replacement of the element in the DOM tree, the focus which was original in the field B is now lost because the field is replaced by another element.

Fixing focus issue

The first scenario describes the situation where the focus must be placed in a certain field which is updated by the AJAX call.  But it is always the same field regardless of the result of the server side code.

This can easily achieved by using the oncomplete attribute of the PrimeFaces widget who initiated the AJAX call.
This is JavaScript code which is performed when the AJAX call was successful (and thus there was no error) and the replacement of the DOM elements in the browser is completed.
So at this point the DOM tree is stable again and we can give a field the focus.

oncomplete="PrimeFaces.focus('frm:newProjectName');"

The above snippet places the focus in the newProjectName field when the AJAX is finished.

Conditionally define the focus

Another scenario is where the fields that needs to get the focus needs to be defined conditionally.  Lets examen this use case better with some screen example.



In the above case, we have a field to enter some kind of code.  And depending on the code, we sometimes needs additional information from the user.
So, there will be an AJAX handler (p:ajax) which call some java listener method to perform the server side functionality which defines if there is additional information needed. 

Initially the 'additional' field is disabled, so the focus is not placed in this field by the browser. And since the field is replaced by the AJAX call in the DOM tree, the focus would be lost anyway.

But from within the Java listener method, we can execute some JavaScript when the AJAX call is finished.  This is one of the great features of PrimeFaces.

So, by adding the following code in the Java method, we can place the focus in the additional field. And within Java it is easy when this focus must be placed there (the conditional aspect of this usecase)

RequestContext.getCurrentInstance().execute("PrimeFaces.focus('frm:additionalInfo');");

Conclusion

The focus and AJAX combination has some conflicts. In the Expert group for JSF 2.3, they are considering some additional tags to handle those situations.
Within PrimeFaces, we saw with 2 usecases that you can manage the problem with the usage of the excellent integration of JavaScript within PrimeFaces. This from within the view (JSF pages) as from within Java.

Have fun.

Monday, 13 April 2015

Native GridLayout component in PrimeFaces 5.2 (panelGrid)

Introduction

A while ago, I blogged here about the GridLayout component for JSF 2.X which allow you to have the responsive layout using DIV structure with CSS classes from Bootstrap or PrimeFaces. 


In the recent PrimeFaces 5.2, the panelGrid component is improved so that you can have the same functionality. 

Improvements

With the new version, you can specify the CSS column class yourself, which allows you to have columns of different width.


So now it is possible to write something like this 

<p:panelGrid columns="2" columnClasses="ui-grid-col-8, ui-grid-col-4" style="width: 100%" layout="grid">

    <h:outputLabel value="First Column"/>

    <h:outputLabel value="Second Column"/>
</p:panelGrid>
And have 2 columns, the first twice as wide as the second one.

The old functionality is still available, so if you don't specify any columnClasses in the above example, both columns have the same width.

So if you are using PrimeFaces, there is no need anymore for my GridLayout component, unless you want to use twitter bootstrap CSS classes.

That is all for now about the new primeFaces 5.2. Enjoy it.

Sunday, 29 March 2015

Advanced File download with PrimeFaces

Introduction


When your Web application needs to send a file to the browser, the classic approach is using a web servlet to serve the contents.
PrimeFaces has a specific tag for downloading a file, so that you don't need a servlet. And with a small trick, you can even update the screen in the same action.

FileDownload component

The example with the servlet can be skipped, I guess. Everyone created already a servlet which is able to send content to the browser.
When you are working with JSF, and PrimeFaces, there is an alternative for the servlet approach.
PrimeFaces has the FileDownload component. It is an ActionListener, so you can use it on a commandButton to perform the download.

Let's have an example.
<p:commandButton value="Download" ajax="false">
    <p:fileDownload value="#{fileBean.file}"/>
</p:commandButton>

@ManagedBean(name = "fileBean")
@RequestScoped
public class FileDownloadController {

    public StreamedContent getFile() {
        InputStream stream = this.getClass().getResourceAsStream("/yourfile.txt");        return new DefaultStreamedContent(stream, "text/plain", "downloaded_file.txt");    }
    
}

The StreamedContent, already used by the graphicImage component, contains the data which is send to the browser. You can supply the constructor with an InputStream which has the actual contents.

This can be static file or a dynamically generated one. The PrimeFaces code is then responsible for reading from the InputStream and send it to the browser. Together with the required housekeeping like setting the mime type, http status and setting the JSF response as completed.

Advanced use case

Together with file download, there are use cases where you also need to update the screen which initiated the download.
Recently we had the use case where the end user can specify some options of the file he wants to download.  The options are presented in a dialog which should be preferably closed when the download is performed. Also the screen should be indicate the file download occurred.

Here the RemoteCommand is the solution to these cases.  The RemoteCommand allows to call some JSF bean methods and JSF lifecycle methods from JavaScript.

<p:commandButton value="Download2" ajax="false" onclick="pageRefresh();">
    <p:fileDownload value="#{fileBean.file}"/>
</p:commandButton>
<p:remoteCommand update="@all" name="pageRefresh"/>

When we click on the button, the onClick activates the javaScript version of the RemoteCommand and initiates a AJAX partial page refresh of the screen. On the other hand, the click on the button also initiates the ActionListener of the FileDownload component to perform the file download.

Since we where able to initiate 2 calls, we can perform 2 actions, the download and the screen update.

Conclusion

With the help of the FileDownload component it becomes easier to program the download of a static or dynamic file in JSF. You no longer need a servlet to perform these kind of actions.
With the help of the very broad useable RemoteCommand component, we can even initiate 2 actions.  The file download and some screen updates.


Monday, 19 January 2015

GridLayout component for JSF 2.X

Introduction

It is common practice to use a CSS Grid to define the layout of your web application page.  We shouldn’t use tables for that purpose.
Also in JSF we can use this CSS Grid but it requires quit a lot of DIV elements and thus boilerplate in your page. The good thing is that we can create a custom component which reduce the amount of html we need to put in dramatically.  The component got the name gridLayout.

PrimeFaces recently introduced in his version 5.1, also CSS Grid classes.  The following example comes from the user guide.
<div class="ui-grid">
    <div class="ui-grid-row">
        <div class="ui-grid-col-4">Col1</div>
        <div class="ui-grid-col-4">Col2</div>
        <div class="ui-grid-col-4">Col2</div>
    </div>
</div>

But also other CSS Grid systems can be used with the gridLayout custom component.  The component was first used in an application that used the Bootstrap CSS grid.  And in fact, all CSS grids can be used as you specify which CSS class will be used on the row DIV and which will be used on the column DIVs.

gridLayout

The gridLayout component has 3 attributes, which are
columns: This determines the number of columns which should be created.
rowClass: Determines the CSS class which will be used on the row DIV, in above example it is ui-grid-row.
columnClasses: A comma separated list of CSS classes which will be used on the column DIVs.

The needed steps to integrate the component are described further on in this text, I already give you an example usage:

<c4j:gridLayout columns="2" rowClass="ui-grid-row" columnClasses="ui-grid-col-2, ui-grid-col-4">
    <p:outputLabel for="firstName" value="First name"/>
    <p:inputText id="firstName"/>
    <p:outputLabel for="lastName" value="Last name"/>
    <p:inputText id="lastName"/>
    <h:panelGroup/>
    <p:commandButton value="save"/>
</c4j:gridLayout>
The above example creates a layout with 2 columns. The first column, with the labels, spans 2 ‘columns’, the other column takes 4 ‘columns’ of the CSS grid.  As you can see, we don’t need to take up the complete with available.  In this example, we are just using half of the screen.
On the last row, the button is aligned with the fields due to the .

Configure the project and usage of the component.

  • Download the code from GitHub.  It is a maven project but I didn’t deploy it to Maven Central.
  • Build it locally and add it to the dependencies of your project
<dependency>
     <groupId>be.rubus.web</groupId>
     <artifactId>gridLayout</artifactId>
     <version>1.0</version>
</dependency>
  • Define the namespace on top of your xhtml page, like 
xmlns:c4j="http://www.rubus.be/component"
  • Start using it, according to the info you saw already here.

Things to know

  • It is released under the Apache V2 License.
  • It is compiled against Java 1.5
  • It is only dependent on JSF 2.0 (Java EE 6).
  • It is NOT dependent on any component library.
  • If you define less CSS classes in the columnClasses attribute, as you have defined in the columns attribute, columnClasses are reused from the beginning of the attribute value.
    So the example from the PrimeFaces user guide can be achieved by the following coding
    <c4j:gridLayout columns="3" rowClass="ui-grid-row" columnClasses="ui-grid-col-4">
  • The correct assignment of each JSF component to a certain column and row is only guaranteed if you use JSF components as children.  If you use html elements or plain text/EL expressions, the layout can be very surprising and not want you had in mind.
  • You can also put your custom CSS classes in the columnClasses attribute and even combine them.  So if you want to right align the label column, you can write something like this.
    <c4j:gridLayout columns="2" rowClass="ui-grid-row" columnClasses="ui-grid-col-2 alignRight, ui-grid-col-4">

Conclusion

The gridLayout component is a very small one but makes it easy to use the CSS Grid of your choice in your JSF Web pages.
Have fun coding.

Update

13/4/2015

With the new PrimeFaces 5.2 release, the panelGrid component is updated to have similar functionality as the GridLayout (but only for PrimeFaces CSS classes)

See http://jsfcorner.blogspot.co.at/2015/04/native-gridlayout-component-in.html.




Friday, 31 October 2014

Overriding defaults of PrimeFaces component properties

Introduction

The prime faces components can be customised with many options.  They can be specified by using the properties on the components.  For all these customisation possibilities, there are defaults active so that you don’t need to specify each option.

But what if that default value doesn’t fit for your project. What are your options?  I’ll show you how you can override the default in the case of the datable component.  but other components can be modified in the same way.

Paginator for dataTable.


The dataTable component can show the paginator bar to do navigation in a table with a lot of records.  By default, this bar is shown on top and at the bottom of the table.

But what can you do when you only want to show it at the bottom of the table?

Use the property


Of course, everywhere you place the table on a screen, you can specify the paginatorPosition property and set it to bottom.

    <p:dataTable value="#{personBean.persons}" var="person" paginator="true" rows="3" paginatorPosition="bottom"> 
        <p:column headerText="name"> #{person.name}

    </p:dataTable>

This will work of course but is more work and it can be forgotten by the developers. especially in larger scale applications.

And what happens if they decide that after all, they want to show it as it ways, on top and at the bottom? Change everything again?

CSS is everywhere

Since PrimeFaces relies heavily on CSS, a solution can be found in specifying some CSS style which hide the top paginator bar.

If you inspect the HTML in the browser, you can easily see that the top paginator has a style class with the name ui-paginator-top.

So the following CSS is able to hide the top paginator bar.

    <style type="text/css"> 
        .ui-paginator-top { 
            display: none; 
        } 
    </style>

But this solution is not ideal. The paginator is suppressed in a general way, so we don’t need to change the xhtml files individually.  But the server sends this information to the browser.  So the size of the response is too large because some parts aren’t shown anyway.

Change the defaults


There exists another way to achieve our goal.  You can alter the defaults of PrimeFaces quite easily since PrimeFaces is designed with extensibility in mind. 
The default values are coded in the class org.primefaces.component.datatable.DataTable.

There exists for example a method getPaginatorPosition() which retrieves the values specified in the xhtml file or, when not specified, returns the value “both” which is the default for this property.

So when you extend this class, you can overwrite this method and return, for instance always the value “bottom” and we now have override the default (well we basically ignore the property and always return the same value)

public class MyDataTable extends DataTable { 
    @Override 
    public String getPaginatorPosition() { 
        return "bottom"; 
    } 
}

Just overriding the method in the extended class is not enough.  You need to inform JSF that your version must be used as component class.

This can be done by specifying the following snippet in the faces-config.xml file.

    <component> 
        <component-type>org.primefaces.component.DataTable</component-type> 
        <component-class>be.rubus.web.primefaces.MyDataTable</component-class> 
    </component>

And if you now run the application, you will see that there is no top paginator bar and it isn’t even present in the generated HTML.

How can you know which value you need to use for component-type?  Look in the PrimeFaces faces-config.xml file (you can find it in the META-INF directory of the PrimeFaces jar) and look for the component class you override.  That is the value you need to use.

Conclusion


You can easily override the default values for the PrimeFaces component properties.  Just extend the PrimeFaces component class and put any value you like in the overriding method.  You just have to specify then your component class in the  faces-config.xml file.

Sunday, 6 July 2014

Mavenize your Custom PrimeFaces Theme

Introduction

PrimeFaces relies on the ThemeRoller themes for the look of the components.  There are more then 35 already available. But it is also possible to create your own custom ones.  This blog not only describes the creation of such a new theme, which is already quit good documented, but also how you can wrap it in a maven project and add some further customisations.

Create custom theme

ThemeRoller has an online visual tool to design your custom theme.  You can specify Font and colour for various types of content like header, highlights, buttons and so on.

Once you are more or less comfortable with how the examples on the site looks, you are ready to download the theme.
On the download page, it is very important to exclude all the components, you only need the skinning style. You have a convenient ‘toggle all’ checkbox to remove all the components. Also the 1.11 version of jQuery is NOT supported, so take one of the other 2 versions noted on the page.

This zip needs a few modifications before it can be used as custom theme for PrimeFaces. Luckily this is automated and can be done on this page. 

Here you can specify the custom name for your theme and after you upload the zip to the site, you are able to get a jar file which can be used directly in your application.

Mavenize 

Most of the time you want to perform some modifications on the theme. Some of the modifications I made recently are described further on.
So it can be very convenient to turn the jar file into a maven project where the maven package goal generates a valid PrimeFaces Theme.
This is very easy to accomplish.

Just create a minimal POM file, you just need the groupId, artifactId and version info, nothing else, and extract the contents of the  jar into the src/main/resources directory.


The directory structure should look like the image above. The contents of the downloaded jar file is extracted in the resources directory as indicated in the image.

From now on, you can generate the PrimeFaces theme with a simple mvm clean package command.

Customizations

In this section, I want to share you a few of the customisations I made in my recent project.

Font

One of the common questions on the PrimeFaces forum is how you can change the size of the text within PrimeFaces Components.  This can be done by specifying a value for the .ui-widget, .ui-widget .ui-widget  CSS selector.

Instead of putting it into the css file of your application, you can also put this value in the theme and use it in all your applications.

Put the same font information also in the body selector as some components of your application are not from PrimeFaces (for example the h:outputText) and should look the same.

Table record selection

If you look closely to a selected record in a data table component, you see that the upper border isn’t highlighted like the 3 other borders. (look at the showcase with a theme like Blitzer, there you can see it easily).

You can ‘fix’ this in your theme CSS, look for the ui-state-highlight selector.

.ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight {
   border: 1px double "yourColor"
   ...
}

Replace the solid with double and you wil see that all 4 borders are identical now.

Other then these 2 customisations, you can put anything you need in that theme file. Examples are
- A different colour for the cancel type of buttons
- A different colour for the default button
- Error indication on a field with a validation error
and so on.

Conclusion

Creating a custom PrimeFaces theme can be done quite easily.  Starting from the ThemeRoller visual designer, you can convert it to a maven project which allows you to customise the theme even further.


Thursday, 24 April 2014

PrimeFaces, JSF 2.2 and CDI on Google App Engine

Introduction

Recently we did a proof of concept on Google App Engine, the cloud solution of Google. The Java version, supports servlets and you can already find various resources on the internet where the procedure is described to have the technologies listed in the title working on the platform.

But some of them are already quit old or give only a partial solution.  So I decided to put our findings together in this blog post.  All the frameworks are from the Apache group or have the Apache License.

We used version 1.9.1 of the Java GAE SDK.

JSF

The most difficult technology of the list is JSF. You can find various posts where you have to create your custom version of Mojarra to be able to deploy it.  This has to do with the use of JNDI sources which is not allowed on AppEngine.

We tried the Apache MyFaces 2.2.2 version and it went remarkable smooth.  We made the following  configuration options in the appengine-web.xml file.

    <sessions-enabled>true</sessions-enabled> 
    <threadsafe>true</threadsafe> 
    <static-files> 
        <exclude path="/**.xhtml" /> 
    </static-files>


The least obvious things was that we needed to tell AppEngine that xhtml files aren’t static, so that we can define it as an url pattern for the faces servlet.  Using this url extension is a best practice so that you can’t retrieve the raw html files of JSF.

EL 2.2

At this point, we were already able to deploy a JSF application and had the hello world style application working.  But if we tested with method expressions, like

<h:commandButton value="Greet" actionListener="#{testAction.doGreeting()}" />


We received an error that the brackets weren’t expected.  So it was clear that only value expressions are recognised and not the method expressions.

We tried various EL expression factories, and it turned out that the one of JBoss worked best.  But we weren’t able to use the latest version of the framework. we received following security exception

access denied ("java.lang.RuntimePermission" "modifyThreadGroup")

Although it is a CR release, it did the job so we stayed with this maven artefact  org.jboss.el:jboss-el:1.0_02.CR6

PrimeFaces

Plain JSF applications aren’t attractive, that is why you use some component library like PrimeFaces which became the de facto standard.  Adding this to artefact to the maven dependencies, we hit another issue, but this time we identified it as a known GAE bug.

It has to do with the handling of the If-Modified-Since request header.  But we quickly found an excellent solution by Derek Berube.

Adding the 2 classes and define the filter in the web.xml file, the problem was solved.

We even tried the latest PrimeFaces 5.0 version (it was just before it went into his first CR release) and there was no other issue we could see at first glance.  So this means you can now create web application targeted to mobile devices on Google App Engine.

CDI

As I’m a strong believer of Java EE, so I tried to use CDI for the middleware instead of the Spring approach too many people take without considering the alternatives.

There is an excellent Apache implementation of CDI, called OpenWebBeans.  The following artefacts where added to the project

  • openwebbeans-impl
  • openwebbeans-spi
  • openwebbeans-web
  • openwebbeans-jsf
  • openwebbeans-el22

Regarding the configuration of OpenWebBeans, we just had to follow the procedure for a regular web server like Tomcat or Jetty.
After adding an empty beans.xml file and define the WebBeansConfigurationListener in the web.xml, the dependency injection worked like a charm.

Just as with JSF, there exists also for CDI an extension beyond the basic stuf and I choose CODI (Apache MyFaces Extensions CDI). Just adding the dependency was enough to make it work.

Other technologies

We also added the JPA option and used a maven plugin to handle the deploy to Google App Engine automatically when a mvn deploy command is issued.

I find it a pity that there is no database solution available for free on Google App Engine. It doesn’t need to be very powerful. Just a simple schema that you can use for demonstration purposes of your application.

This is in contrast with the JBoss OpenShift offering, where you can have a full Java EE stack with a database for free.  But that will be covered in another blog post.

Conclusion

Apart from one little issue (bug 8415) which can easily be bypassed, it was quit easy to assemble the required stack to have a JSF based web development environment on Google App Engine. This is in contrast with a few years back where various issues limited the possibilities.



Thursday, 30 January 2014

PrimeFaces JBoss forge plugin updated

With the announcement of the new CR release of JBoss Forge 2 (now final release), I remembered that once upon a time (already 2 years ago) I wrote a plugin for PrimeFaces for this tool.
Since then, a lot happened and that version of the plugin doesn’t support PrimeFaces 4. Although it isn’t a big problem, you can manually update the version number of the artifact to 4 in the pom.xml file, I decided to spent some time again on the plugin.
Mainly because the Forge 2 version uses a different concept and now you have the notion of addons. So a rework will be needed to keep the functionality in the new release of JBoss forge.

PrimeFaces 4

The new version of the plugin supports PrimeFaces 4 directly and you can use it to configure the Client Side Validation feature of PrimeFaces.

What are the commands that you need to specify within JBoss Forge?
forge install-plugin primefaces

This command will install the PrimeFaces plugin and is only required the one time.


new-project --named demo --topLevelPackage be.rubus.forge.demo --type war

This command will create a new maven project with packaging type war.  You can choose of course the value for the –topLevelPackage attribute. The command will also ask some questions like the location where the project must be created.


faces setup

This command will add the required maven dependencies for using JavaServer Faces development.  And it will add also some resource files like web.xml, faces-config.xml and beans.xml if you want CDI (this is a question of the command)


primefaces setup

Now the PrimeFaces dependency is added to the project. The version depends on selection you made and you are ready to go with your favourite IDE.

Additional goodies


The plugin also has some additional commands which can be handy
primefaces install-example-facelet

This adds a JSF view file (index.xhtml) which uses templating and contains a Hello World type example of using PrimeFaces.  This is handy is you are not familiar with PrimeFaces and shows you how to add the PrimeFaces namespace.  It is also an example of using the JSF 2.x template feature.


primefaces set-theme

If you execute this command, you see the list of available free themes for PrimeFaces.  It adds the required maven artifact and configures the theme in the web.xml file.


primefaces install-CSV

This is a PrimeFaces 4 specific command which configures the Client Side Validation feature in the web.xml file. See the PrimeFaces users guide how you can use this feature.

JBoss Forge 2


For the new release of the tool, the plugin will be adapted and a short guide will be posted when the addon is available. But enjoy version 1.1 of the PrimeFaces plugin from today on.

Sunday, 5 January 2014

Client Side Validation example of PrimeFaces

Introduction

With the latest version of PrimeFaces, version 4, you have the possibility to perform some validations on the client, by the browser.
This features doesn’t replace the standard JSF validation on the server side but is an addition to it.  The server side validation makes sure that any data posted to the server is valid before it is processed any further. The client side validation is there to inform user faster of data problems.
By default, all the standard validations like required fields, minimum and maximum values, string lengths and so on are available.  But you can also create the JavaScript version of your custom JSF validation.
The feature is very good explained in the PrimeFaces users guide. This posts describes the steps that I have done to make a Visa card validation on the client side.

Configuration

In order to activate the feature, you need to put the following content parameter in the web.xml file.
    <context-param>
        <param-name>primefaces.CLIENT_SIDE_VALIDATION</param-name>
        <param-value>true</param-value>
    </context-param>

Now, your application is ready to use the client side validation feature. And whenever you want to make use of it, you just have to specify the attribute validateClient on the commandButton tag for example.

The standard validations known by PrimeFaces are then performed on the fields in the form.  Any validation error is shown by the messages or growl tag which is also available in the form.

Make sure you read the PrimeFaces users guide to know all the requirements and usages.  The most import ones are


  • Put a messages or growl tag within the form. others are not yet discovered. 
  • Severity attribute of these tags is ignored.
  • Invalid fields are marked by a red border but associated label isn’t colored

These shortcomings will be removed in the next release of the framework.

Custom validation

It is also possible to have a client side validation variant of your custom validations.  Therefor I created an example, a visa card number validation.

You start by creating a standard JSF validator, so a class that implements Validator interface.  For the Client Side Validation feature of PrimeFaces, you have to implement also the org.primefaces.validate.ClientValidator interface.

It contains 2 methods, getValidatorId which defines the name of the JavaScript function that implements the validation on the client side. If the JavaScript function needs some values defined by the validator (like the minimum value for the range validation) you have to return it by the getMetadata method.

This is the java side of the solution
@FacesValidator("custom.VisaCardCheck")
public class VisaCardValidator implements Validator, ClientValidator {
    @Override
    public Map<String, Object> getMetadata() {
       return null;  // No metadata required on client side
    }

    @Override
    public String getValidatorId() {
        return "custom.VisaCardCheck";
    }

    @Override
    public void validate(FacesContext someFacesContext, UIComponent someUIComponent, Object o) throws
            ValidatorException {
        ...
    }
}


The JavaScript must be available on the page where we like to use it, the code is shown below.
PrimeFaces.validator['custom.VisaCardCheck'] = {
    reverse: function (s) {
        var o = '';
        for (var i = s.length - 1; i >= 0; i--)
            o += s[i];
        return o;
    },
    throwError: function(detail) {
        throw {
            summary: 'Validation Error',
            detail: detail
        }
    },
    validate: function (element, value) {
        var reg = /^\d+$/,
            digits = this.reverse(value).substring(1).split(""),
            sum = 0;
        if (!value.match(reg)) {
            this.throwError("Not all digits");
        }
        if (value.length < 13 || value.length > 16) {
            this.throwError("Length invalid");
        }
        if (value.charAt(0) != '4') {
            this.throwError("Wrong start digit");
        }
        for (var i = 0; i < digits.length; i++) {
            if (i%2 == 0) {
                digits[i] = digits[i] * 2;
                if (digits[i] > 9) {
                    digits[i] = digits[i] - 9
                }
            }
            sum += parseInt(digits[i]);
        }
        if (value.charAt(value.length - 1) != (sum % 10)) {
            this.throwError("Check digit validation fails");
        }
    }
};


The important thing here is that the name of the validator in the JavaScript object, custom.VisaCardCheck in my case, is the same as the value returned by the getValidatorId method of the JSF validator.

Usage of the validator at the JSF level is the same as usual.
<p:inputText id="myValue" value="#{dataBean.myValue}" required="true" validator="custom.VisaCardCheck" />

Conclusion


With the Client Side Validation framework, we can inform the user faster about issues with data, without the need to go to the server.

The best thing is that it integrates very well with JSF and it is hard to tell if the message came from the client side validation or from the server side.

The default validations are already available in their javaScript counterpart, also if you use BeanValidation. When you create a custom validation, you have to write the JavaScript yourself, of course.

Tuesday, 8 October 2013

How to debug javascript in PrimeFaces 4.0

Introduction

With each new release of PrimeFaces, the JavaScript becomes more and more important in the framework.
This is no surprise as JavaScript is needed to give the end user a rich user interface. And in the latest release there is quit a lot of new JavaScript code added for the client Side validation framework.
But if you want to debug it in the browser, you see that the code is minified. And thus stepping through it line by line is not possible.
This post describes how you can do it.

Build custom version

The source code of PrimeFaces contains the human readable code and the idea is that we build a custom jar file which contains that readable version of the JavaScript.
As the code is open source, it is available on Google code. We can do a checkout with following command.
svn checkout http://primefaces.googlecode.com/svn/primefaces/tags/4_0

Now we go to the pom.xml file and make some small changes.
The most important one is the change of the version tag.  I have changed it to 4.0-DEBUG (you can find it at the top of the pom.xml file)
    <modelVersion>4.0.0</modelVersion>
    <groupId>org.primefaces</groupId>
    <artifactId>primefaces</artifactId>
    <packaging>jar</packaging>
    <version>4.0-DEBUG</version>
    <name>primefaces</name>
    <url>http://www.primefaces.org</url>
PrimeFaces uses a maven plugin to generate the JSF components and configuration files. 
This plugin is located in the PrimeFaces maven repository which you must include into the pom file. Otherwise the build will fail.
    <pluginRepositories>
        <pluginRepository>
            <id>primeFaces_repository</id>
            <url>http://repository.primefaces.org/</url>
        </pluginRepository>
    </pluginRepositories>
When you now execute the mvn install command, you will have a customized version of PrimeFaces in your local Maven repository which contains the non minified version of JavaScript.

Using this version in your project, by specifying it in a profile so that it doesn’t go into production, you can do debugging in your favourite browser.

Conclusion

We following the above steps, you have a custom version of PrimeFaces where the JavaScript is not minified and thus can be debugged in the browser. Of course it is not suited to go to production with this version.

Sunday, 25 November 2012

Advanced PrimeFaces Graphic Image renderer for dynamic content

PrimeFaces has a component to render graphic resources and has added support for dynamic generated content.
There is a special StreamedContent class for this, so that you stream the generated resources from the JSF application to the browser.

But there are a few limitations for the component when it comes to dynamic generated content.  And they are not related to PrimeFaces but to the communication model between the browser and the application server.
Since there were lately a few questions in the PrimeFaces forum that had to do with these limitations, I decided to create an advanced renderer for the component. But there are a few warnings in using it.
For the impatient ones, you can find the project on GitHub.

How does the PrimeFaces Graphic Image renderer work?

The PrimeFaces Graphic Image renderer generates a html img tag where the src attribute points back to the application.  The URL contains a unique id and stores within the http session of the user, the EL expression linked to that unique id.
The EL expression comes from the value attribute of the p:graphicImage tag that the developer wrote in the JSF file and which points to the StreamedContent value that contains the dynamic generated content.
The browser interprets the html page and ask for the image content based on the URL found in the src attribute.

Since this URL points back to the JSF application, the PrimeFaces resource handler gets a chance to handle the request.  It recognize that the browser asks for a graphic resource with dynamic content based on the URL parts and parameters.
Based on the unique id which is available as parameter in the URL, it can take the corresponding EL and stream the content to the browser.

At this last step, the limitations can be hit in some use cases. Since the resource handler has no idea whatsoever of the page where the dynamic content is located, which bean is involved etc...  It can only rely on the EL expression the renderer has placed in the http session.  It is possible that this EL expression is only valid within a certain context.

The most striking example is the use of a composite component attribute.  Something like #{cc.attr.image} can be perfectly valid within the context of a custom composite component but it is clearly not when arbitrary executed.
The same reasoning goes for the dataTable component.  Whenever you use the alias defined in the var attribute for indicating the dynamic content, the PrimeFaces resource handler will be unable to retrieve the contents.
And the renderer can't determine the  EL expression that can give us the reference to the StreamedContent

Solution

The solution that I implemented is that we store the contents of the dynamic generated content on a location that can is always accessible, without the restriction of a context. This means we need to copy the contents to another location, the file system in our case.
The renderer copies the StreamedContent to a file in the System temp directory. For scaling reasons, this is a better alternative then storing the content directly in the http session area. We now only need to keep the file name next to the unique id instead of the EL expression.

On the other side, there is also another resource handler defined that uses the contents of the file to serve the browser request for the image resource.
The temporary files are removed when the http session is invalidated so that we don't have a problem with the disk storage size. We can't do it earlier because the browser can request the image multiple times as the user goes back in the screen flow or asks for a refresh.

Usage warnings

There is one issue with the above described solution, there is a performance drop.  It all depends on the size of the images of course but we need to write the content to disk, an additional step, and the resource handler serve it from disk which is slower then memory access.
For optimal performance, the storage on the disk is performed by using java.nio.channel.Channels.  That should guaranty to most efficient solution.

The clearing of the files is done when http session is invalidated by a HttpSessionBindingListener.  And although we can be pretty sure that the files gets removed, if the server implementation is correct, the files are kept during the user session.  When you have an application with a lot of dynamic generated content and the user works for a long time with your application, a lot of files can be created.

Intelligence of the advanced renderer

Therefore, there is some intelligence build into the Graphic Image renderer.  The scenario where the content is stored on disk is by default only used when the graphicImage tag is used within a custom composite component or a component that implements the UIData interface like dataTable.
These 2 cases are the situations where there is a lot of chance that the standard algorithm of PrimeFaces will fail. If this is not the case, the standard PrimeFaces functionality will be used (without the storage on disk).

Intelligent default functionality is fine but sometimes you need to take control yourself. This can be achieved by nesting a advancedRenderering tag within the graphicImage tag.  By specifying a boolean value for the value attribute, you can control the usage of the advanced rendering functionality.

Use cases where this can be handy.
1) You are using the graphicImage tag within a custom composite component but you as developer know that the EL you have specified can be used outside of the component (it is 'general' and not tied to a certain context) then you can disable the advanced rendering.
2) You have created the dynamic content with a bean on a request scope.  The resource handler can perfectly access the bean but in most cases the generated content is lost.  Here you can ask for the advanced rendering so that at render time, the image is stored on disk ready for streaming to the browser.

Code

The code can be found on GitHub and is released under the Apache License, Version 2.0.