Playground for creating stateless Web applications with HTML5, CSS, JavaScript and PrimeUI on the client side and Java EE 6/7 with the JAX RS module that does the communication in JSON format on the server side.

Saturday, 23 February 2013

Introduction

In one of my previous blog items, I explained the similarity between JSF and AngularJS. But you can go even a step further. It is possible to create a single page app where you combine both frameworks and let them work together.
Not that this will be an immediate production situation, but it gave me the opportunity to explore the very nice JavaScript support of PrimeFaces.

Overview

This is how the application looks like
On the top, you have the AngularJS application. It retrieves the list of persons from a REST service that receive the data from a CDI injected service.
Clicking on the edit button, calls a Java method on a JSF Managed bean. This can be achieved by using the remoteCommand tag of PrimeFaces.
This click also triggers a partial refresh of the JSF part and shows the person information to update. The update button posts the person information to the server. Within the actionListener, we can define the JavaScript method that needs to be executed when the AJAX call is finished by using the RequestContext class of PrimeFaces.
This JavaScript method calls an AngularJS scope function that reads the person list again from the server. We receive now the updated information and thus the circle is round.

PrimeFaces for JavaScript

From browser to server.

PrimeFaces has the remoteCommand tag which enables executing backing bean methods and do partial update triggered by custom client side script. In our example it is defined as follows

The last piece of the puzzle is the update attribute which defines which JSF part must be rerendered.

So basically, the remoteCommand executes an AJAX request, like the commandButton. You can post data to the server and rerender a part of the page. But is not triggered by an element in the page but by a JavaScript call.

From server to Browser

When we have edited the person information, we click on the update button. It is an AJAX post to the server and we execute an actionListener on the JSF side. We can also update the information but we now need a way to trigger an update within the AngularJS application so that the new information is shown on the screen.

PrimeFaces has also for this kind of requirements a solution. There exists the class RequestContext where we can define the javaScript function that must be executed when the AJAX response is processed by the browser.

This is the actionListener implementation behind the update button

publicvoid updatePerson() {

personService.updatePerson(selectedPerson);

selectedPerson = null;

RequestContext requestContext = RequestContext.getCurrentInstance();

requestContext.execute("updatePersonList()");

}

Now we have already a giant step towards a solution for our problem. We are able to execute some global JavaScript function after the AJAX request/response associated with the commandButton is finished.

Calling a function within an AngularJS scope is not that difficult, you find it very quick when you google for it

function updatePersonList() {

var _scope = angular.element($('#panelTitle')).scope();

_scope.updateList();

}

panelTitle is the element, in my case the DIV, where we have defined the ng-controller directive. This is also the element where the AngularJS scope is defined. This is the function definition:

$scope.updateList = function () {

$scope.$apply( function() {

$scope.data = PersonList.query();

});

};

$scope.$apply is needed to trigger an update of the page as a result of updated data. This is needed because we update the data outside the normal processing flow of AngularJS.

Conclusion

Probably, there will never be a production app that needs the combination of JSF/PrimeFaces and AngularJS.

For me, it was the opportunity to learn the possiblities of the JavaScript features provided by PrimeFaces and the integretion of AngularJS with another trigger.

The code can be found here and it will run on a JBoss 7.1 application server.