AngularFaces: AngularJS Puts JSF on Steroids

Where Java Server Faces shines – and where it does not

Fork me on GitHubJSF 2.0 is a nice framework to create web applications. It offers a decent level of abstraction. Most of the time you don’t have to deal with basic technologies like HTML and Javascript. It fun to use it. You can create an attractive-looking application in no time.

But things become ugly once you start to write an AJAX client. It looks deceptively innocent at first sight. What’s so difficult about adding simple attributes like update="@form" or – if you happen not to use Primefaces – a nested tag like <f:ajax>? Beware: You’ll end up wading knee-deep in Javascript code, DOM trees and HTML. You’ll add an id to virtually every component of your dialogues, and you have to know a lot about when events are fired. Firebug soon becomes your best friend1.

The one thing I like about JSF is it simple, declarative approach. But once you start to write an AJAX client, simplicity soon gets lost. The more Javascript code you add, the more you move away from the declarative approach to a more imperative approach.

Javascript to the rescue?

During the last couple of months I’ve begun to prefer pure Javascript over AJAX. Not that I really liked the language. But I came to believe sometimes simple Javascript code is easier to maintain than all-too-clever JSF-AJAX code. Not to mention the network latency and costly server CPUs.

Later I learned about AngularJS. I was immediately struck by the similarity of the concepts. JSF facelets allow you to define an web application’s HTML in a declarative way. So does AngularJS.

Let’s combine ‘em

So what about combining the two frameworks? Angular allows you to do most of the stuff you need AJAX for. The idea is to define a single-page app with JSF. The application communicates with the server by traditional JSF means: submit buttons. You may also use AJAX to make things smoother. But you can rid of most of your AJAX code, leaving it to AngularJS.

By doing so we get an AngularJS application without the need to create REST services. We can utilize the power and ease of JSF’s server side data binding, while still being able to unleash the power of client side Javascript.

That’s the idea behind the AngularFaces project: to create a JSF library allowing you to write an application without the need to use ids. AngularFaces is going to use the power of the client without sacrificing the simplicity of non-AJAX JSF.

Who the AngularFaces project’s for

The project focuses on simplifying JSF. If you’re already an AngularJS programmer familiar with writing and using REST services, the project will probably be of little value to you. AngularFaces is going to offer a new way to communicate with the server, and it’s going to provide an easy entry to the Angular world to JEE programmers.

Two feasible approaches

Using Angular to make the JSF experience more pleasant is fine, but it’s only one of two possible approaches. It’s the approach I’m going to concentrate on in the first place. However, this is a somewhat limited approach. The idea of AngularJS is to manipulate the DOM tree freely. AngularFaces will not try to move the manipulated DOM tree to the server. In other words, if you use AngularJS extensively, you may experience some nasty surprises after the next JSF request. JSF stores a represantation of the DOM tree on the server, and after a while this representation may differ from the real DOM tree. In other words, it may be wrong.

You can easily avoid this trap by using JSF requests exclusively to show another JSF page. That’s not exactly what’s meant by a single page application. It’s rather a collection of small single page applications working together.

On the long run, you might want to follow a more client-centric approach. Most likely, you’ll start writing pure AngularJS applications using REST approaches. In this case, AngularFaces helped you to migrate from JSF to AngularJS.

There’s an alternative: by seperating AngularJS code and JSF forms you can use JSF as an alternative communication means with the server. Most likely AngularFaces is going to explore this way later. The disadvantage of REST services is their lack of state. Sometimes you need state, and JSF’s powerful server communication comes in handy.

Current state of development

I soon found out it’s possible to combine AngularJS and JSF, even if it’s not without difficulties. You need JSF 2.2′s pass-through-attributes. However, the resulting code is verbose, even ugly. So I decided to hide the technical complexities in a JSF component library, based on the Primefaces library. At the time of writing, the component library allows you to write mix Angular and JSF code, brings some of the more importants JSR 303 annotations to the client and simplifies the XHTML files even further by generating label and error messages without having to define them.

A simple demo application

I’d like to conclude with a little example. It allows you to enter two numbers and add them. Angular adds them as you type, and so does JSF after hitting the submit button.


(You can have a look at the live demo at the AngularFaces showcase).

The controller bean defines several constraints. Those constraints are evaluated on the client side as you type:

The AngularFaces components read the JSR 303 annotations and generate the Javascript and HTML code to check the constraints.

Just for the sake of demonstration I added some minor differences to the JSF error messages. After hitting the add button, JSF renders this page like so:

Of course, the final AngularFaces library is not intended to show any differences, no matter whether the page is displayed by JSF or AngularJS. Among other things, the Javascript code ought to be reponsible for coloring the label as you type. The image above shows an early prototype.

To generate the calculator page, you need this XHTML code:

<f:view <!-- boiler plate code ommitted --> >
  <h:head>
    <script src="calculatorController.js"></script>
  </h:head>
  <a:body ng-app="calculatorApp" ng-controller="calculatorController">
    <h:form ng:name="myform" id="myform">
      <h:panelGrid columns="2">
        <a:inputText label="First number" value="#{calculatorBean.number1}"/>
        <a:inputText label="Second number" value="#{calculatorBean.number2}" />
        <a:commandButton type="submit" value="add" action="#{calculatorBean.add}"/> 
        <h:outputText value="Angular Preview: 
                 {{toString(number1)}} + {{toString(number2)}} = {{add()}}" />
        <a:inputText label="JSF Result" value="#{calculatorBean.result}" />
      </h:panelGrid>
    </h:form>
    <h:messages />
  </a:body>
</f:view>

As you can see, this is a lot less code than you have to write using other JSF libraries.

The XHTML page automatically tries to load the controller, which is expected to have the same name as the ng-controller attribute (“calculatorController.js” in our case):

function calculatorController($scope) {
  $scope.add = function() {
    if ($scope.number1 && $scope.number2) {
      $scope.result = parseInt($scope.number1) + parseInt($scope.number2);
    } else
      $scope.result = "(undefined)";
    return $scope.result;
  };
  $scope.toString = function(number) {
    if (number)
       return number;
    else
       return "(empty)";
    }
}

That’s it for today. During the next couple of weeks I’m going to publish descriptions of various AngularFaces components. You can find the source code on GitHub at https://github.com/stephanrauh/AngularFaces. You can participate with the project by forking AngularFaces and sending me a pull request.

Update 28.03.2014: AngularFaces 2.0

AngularFaces has been a success story. However, I found it difficult to continue with the current approach: Deriving from PrimeFaces components and adding value to them. Most PrimeFaces components haven’t been written with extensibility in mind. Plus I was surprised by the amount of interest BabbageFaces attracted. Obviously many of you are interested in a framework that reduces both the number of requests and the volume of network traffic of a JSF application.

The next version of AngularFaces is going to address both targets. At the same time, it’s going to open for Dart and AngularDart programmers (as a second option besides Javascript and AngularJS). Currently I’m developing a client-side widget library written in Dart. It’s inspired by Rudy de Busscher’s AngularPrime project. The idea is to create a very compact GUI DSL that can be run by modern browsers. Current the project’s code name is AngularPrime/Dart, and as the name suggests, it allows Dart programmers to exploit the full power of AngularDart.

This is going to allow AngularFaces 2.0 to send very compact JSF responses (basically the GUI DSL). The Angular API allows you to reduce the number of requests to a minimum.

By the way I don’t consider AngularFaces as a full-blown JSF widget library. It’s sort of a plugin to other JSF component libraries, PrimeFaces in particular. AngularFaces will offer 10 or 20 of the most common components. I’ll leave it to PrimeFaces to provide the remaining (typically more sophisticated) components.

Feedback

I’d like to hear from you. Do you like or object the idea?


Further reading:

AngularFaces’ source code
live demo of AngularFaces on OpenShift
GitHub repository of the AngularFaces client side widget library


  1. Experienced JSF programmers may consider my description a little exaggerated. That’s because you already know what to do – and what to do not. Watch a JSF newby to get my point.

8 thoughts on “AngularFaces: AngularJS Puts JSF on Steroids

  1. Pingback: AngularFaces: AngularJS Puts JSF on Steroids | ...

  2. Bernard

    You are crazy! I thought I’m too attached to JSF but now I see there are couple of steps ahead of me before loosing sanity completely.
    Best of luck with AngularFaces.

    IMHO one must choose but prove me wrong.

    Reply
    1. Stephan Rauh

      I take it as a compliment :).

      But sure you’re right. You’ll never be able to unleash the full power of AngularJS if you’re slowed down by JSF. The other way round – well, I’m not sure yet. That’s why I started AngularFaces. I do believe Angular’s able to smooth out some edges of JSF. My first experiments went surprisingly well. I’ve even been able to Angularize a PrimeFaces data table with in-cell-editing.

      By the way, doing something virtually impossible is a lot of fun!

      Reply
  3. Pingback: AngularJS Highlights: Week Ending 11 August 2013 | SyntaxSpectrum

  4. Yamada

    I disagree with the statement that when using ajax with JSF one will be handling a lot with javascript, DOM trees and HTML manipulation. About the ids it is true. If you dont want to refresh everything (using @all) one must take care of ids to specify exactly what you want to render/update after an ajax event/request.

    The only reason to use AngularJS in combination with JEE server side solution would be to completely decouple the UI team skills from the server side dev team. For example, if you want to hire a third party company to produce your web front end. And if you go to this approach it should be better to use JAX-RS on the server side.

    Reply
    1. Stephan Rauh Post author

      Oops, did I really mention DOM manipulation? If so, you’re right – it’s not a good idea to manipulate the DOM tree in a JSF program. Thank you for pointing this out! But it helps a lot to know a lot about HTML, CSS and Javascript. In theory, you can do without Javascript. In reality I saw my team using more and more Javascript.

      Basically my idea is to use AngularJS to smooth out some rough edges of JSF. This is particularly interesting if you’ve already got a JSF application. As for green field applications, I agree with you. When you’re free to choose the architecture, you’ll probably prefer pure AngularJS plus WebServices or REST.

      Reply
  5. Cliff Lo

    Hi Stephen,

    Here I would like to suggest if it is possible to add library of Dart import to your <a> tag? I would say it would be very helpful because this allows us to use AngularDart which would have compile time debugging instead of AngularJS.

    Regards,

    Cliff

    Reply

Leave a Reply

Your email address will not be published.


*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>