BabbagesFaces: Fast and Efficient JSF AJAX Made Simple

Introducing BabbageFaces

Fork me on GitHubJSF is a great framework. Nonetheless it could be a whole lot simpler. That’s what BabbageFaces does for you: it’s a JSF 2.2 plugin addressing a particularly nasty issue. It allows you to reduce the complexity of JSF views, making JSF more efficient along the way. Every once in a while it even fixes an AJAX error.

Installing BabbageFaces

Installing BabbageFaces is as simple as can be. Just copy the babbageFaces-core.jar file to your web applications library folder.1 Restart the server, run your application and you’ll see – nothing. Your application works just the way it did before. Just a little faster and smoother.

That’s because BabbageFaces works at the lowest possible technical level. It allows you to simplify your programs, but it doesn’t require you to do so. BabbageFaces optimizes every JSF application out of the box, without breaking the compatibility.

Verifying your installation

If BabbageFaces has been successfully installed, you’ll see three differences:

  • There’s a message in the console windows or catalina.out (“Initializing BabbageFaces DifferentialResponseWriter”).
  • Looking at the HTML source code of your browser you’ll find that many
    and tags bear a couple of IDs you didn’t enter.
  • Many AJAX responses look different. In almost every case they are a lot shorter.

Update 08.01.2014
I just tried it with Glassfish, and simply copying the jar file didn’t work. So the better alternative may be to copy the jar file to your applications WEB-INF/lib folder, or to add the dependency to the POM file if you’re using Maven:

<dependency>
  <groupId>de.beyondjava.angularFaces</groupId>
  <artifactId>babbageFaces</artifactId>
  <version>0.1-SNAPSHOT</version>
  <scope>runtime</scope>
</dependency>

BabbageFaces isn’t available at Maven Central, so either you have to install the jar file in a local folder or you clone the AngularFaces project from GitHub and run maven install first.

In case BabbageFaces still isn’t activated you can add a line to the faces-config.xml:

<factory>
  <external-context-factory>
    de.beyondjava.jsf.ajax.context.BJExternalContextFactoryImpl
  </external-context-factory>
</factory>

So what does it optimize?

Did you ever look at JSF AJAX responses? JSF updates views by replacing the old HTML code by a new version of the HTML code. If you’re using JSF without AJAX, the entire page is replaced. If you’re using an old browser such as Internet Explorer 6 or 7 the entire page flickers. That’s a refreshingly simple and reliable approach delivering good performance on the server side. The drawback is a mediocre performance on the client side and a lot of eye strain to users who happen to work all day long with your application.

AJAX solves the problem by replacing just parts of the HTML page. That’s a huge improvement. The drawback is a whole new layer of complexity to the application.

BabbageFaces goes one step further by replacing even smaller parts of the HTML page and by removing the layer of complexity again. I’ll get back to the latter point in a minute. Let’s have a look at the client side implementation first.

If there’s an alternative to replacing a DOM node, BabbageFaces will make use of it. You don’t have to redraw a table just because a row has been deleted. BabbageFaces detects the situation and deletes just the single row.

Another example: You don’t have to replace an input field because the value of the field has changed. As it turns out, the Mojarra JSF library does just that: it replaces the entire input field (and in most cases much of its surroundings). So does PrimeFaces. Even worse, PrimeFaces has to execute some Javascript code to register the new version of the input field to the client-side PrimeFaces framework. BabbageFaces simply replaces the value of the input field.

You can watch the effect by opening your browser’s web developer tools (or FireBug) and watching the network traffic. I’ll soon publish an article on this blog explaining in depth what’s happening. As for now, just watch the size of the AJAX responses and look out for the keywords insert, delete, attribute and eval. Pure JSF is restricted to a single keyword: update.

This approach reduces network traffic by up to 90 per cent2. The time needed to render the page in the browser and to execute Javascript is also reduced a big deal. However, modern browsers have become blazing fast, so probably you won’t notice the faster client-side execution. However, a couple of years ago I did a similar optimization addressing IE7. The client rendering time of our most complex view went down from 20 seconds to a mere second. BabbageFaces does a more profound optimization, so I expect an even more impressing effect.

But as I mentioned, you need a slow network or slow hardware to notice the effect. Chances are mobile users will feel the difference. Desktop users connected to a fast office network probably won’t, unless your JSF views are extraordinarily complex. So I believe the second advantage is more important.

The benefit to programmers

BabbageFaces allows you to program more sloppily without being punished. You can get rid of a lot of IDs. As to my experience, this amounts to get rid of a lot of mistakes, not to mention a myriad of keystrokes and the time you are distracted from solving the business problem.

JSF AJAX requires programmers to provide hints which parts of the page need to be replaced. You have to decorate a lot of JSF components with unique IDs and to add these IDs to every button, menu item, tab and every other interactive component of your page.

I’ve seen programmers using a lot of IDs in order to get more efficient AJAX. If you know a particular button influences merely two input fields, you can update them instead of updating the entire form.

That’s no rocket science, so many people use IDs without thinking twice. The problem is the IDs are a technical issue. They don’t add any benefit to your business application. They distract you from solving the task you are paid for. Even worse, they are a first-class source of errors. Just imagine the business logic changes, so the button of our example above has to update the third field. It doesn’t suffice to modify your business logic, you also have to update your JSF page.

BabbageFaces allows you to always update the entire form, no matter which part of the form has been updated. It’s up to the computer to figure out what to do. You solve the business problem, leaving it to the computer to solve the technical hassles. That’s the way it ought to be. Mind you, the computer usually is better at solving technical problems than you are. Actually, JSF only allows you to optimize up to a certain point. A low-level framework like BabbageFaces can do more sophisticated optimizations. For instance, we defined the button to update two input fields each time it has been hit. Pure JSF always updates both fields, no matter whether the values have changed or not. BabbageFaces updates only one field if the other field is unchanged. Even better, it simply updates the value instead of updating the field. Even if you chose to use update="@form" or even update="@all".3

What does the name mean?

The core algorithm of BabbageFaces compares two versions of an HTML page, figuring out the differences. Thomas Andraschko baptized this module difference engine, so I decided to call the project after the inventor of the first difference engine, Charles Babbage. Actually, our difference engine is a lot less complicated than the model shown by the Wikipedia image :).

Which bugs does BabbageFaces solve?

Many AJAX clients suffer from nasty bugs caused by network delays. Sending data to the server, processing it, sending it back to the client and updating the HTML page takes some time. In most cases, it’s less than a second, but sometimes it takes more time. During this time users continue to work with the application. So it happens users start to fill fields that all of a sudden disappear. Or that are emptied after typing. In almost every case updating a form means loosing the cursor focus.

This class of error is hard to track down. Typically developers benefit from a fast developer machine and a fast network connection (i. e. local traffic that doesn’t involve the network at all), so they find it hard to reproduce the errors.

BabbageFaces reduces this class of errors by replacing smaller parts of the page. You won’t loose the inputs of a field that is not being replaced. Cursor focus won’t get lost because of the same reason. In most cases the input fields that have to be updated are fields the user has just left, so the AJAX response won’t interfere with the users actions.

Is it a free lunch?

There’s a small price tag assigned to BabbageFaces. It consumes both CPU resources and memory. In the case of the pet store demo application, this amounts to roughly 10-20% extra CPU time. I’m optimistic in many cases the reduction of network bandwidth is more important.

If CPU consumption is an issue to you, you can reduce the strain on the CPU by adding IDs to your buttons (i.e. by returning to the traditional way of programming JSF pages). By default, BabbageFaces encourages you to use the most simple solution. But of course, that doesn’t mean it forbids you to optimize manually.

In case you’re suffering from sluggish performance, please drop me a note. I’m pretty sure BabbageFaces can be tweaked a lot.

So I think the advantages outweigh the small extra cost in most cases.

Requirements

BabbageFaces requires JSF 2.2 or above. In theory it should work with every JSF 2.2 component library. However, at the time of writing I only tested it with Mojarra and with PrimeFaces.

PrimeFaces users need to use PrimeFaces 5 or above.

A framework I don’t expect to be compatible is ICEFaces. ICEFaces offers Automatic AJAX, a similar optimization, so BabbageFaces wouldn’t be useful with ICEFaces, anyways. Judging from their description (I didn’t have a look at the source codes yet) their implementation is astonishingly similar to the BabbageFaces implementation. I guess there are only so many ways to do the task.

Maturity

At the time of writing (January 4th, 2014), I just finished BabbageFaces. Every test I ran worked just fine, but still, I’d be surprised if there weren’t any errors left. For example I had to fix several bugs to run the JEE 6 pet store demo on BabbageFaces.

Update 27.05.2014
I just completed the second release candidate of BabbageFaces. I’ve tested it with my showcase examples and the PrimeFaces 5.0 showcase. BabbageFaces passed both tests without problems.

But still, please be careful if you’re using it in production. It’s very new stuff, so please test your application thoroughly. As the license says,

the program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Please feel free to open an issue on GitHub or to drop a note on this comment if you run into problems using BabbageFaces. The restrictions of the license simply state I’ll refuse to promise you to solve your issue. It doesn’t say I won’t have a look at your issue :).

Licence

I put BabbageFaces under a GPL 3 licence. Please contact me if you want to use BabbageFaces commercially.

Kudos

Essentially BabbageFaces is an idea by Thomas Andraschko. He wrote the initial prototype and gave me valuable hints when I took over. Thanks, Thomas!

Participate!

Do you want to participate with the development of BabbageFaces? I published the source code at my AngularFaces GitHub repository. So there are various ways to participate. You can report bugs by opening an issue on the AngularFaces repository. You can fork the source code and ask me to integrate your improvements by making a GitHub pull request. And of course, you can simply leave a comment on this blog.

Live demo on the showcase

There’s also a live demo on the AngularFaces showcase: http://showcase.angularfaces.com/babbageFaces/index.jsf. The first three tabs are very technical demos demonstrating the idea. The last tab shows a small real-live application.


Further reading:

AngularFaces GitHub repository (including the BabbageFaces subproject)
Automatic AJAX, an ICEFaces approach similar to BabbageFaces


  1. more precisely: put the babbageFaces into the same folder as the other JSF libraries. If you’re using a full-stack application server that’s the application server’s global class path.
  2. depending on your application, of course. You gain less if you’ve already optimized your JSF code manually.
  3. Please avoid to use @all. It’s a very inefficient way to use JSF, and I haven’t tested it with BabbageFaces yet. Chances are it doesn’t work reliably.

9 thoughts on “BabbagesFaces: Fast and Efficient JSF AJAX Made Simple

  1. Samy Omar

    Great addition for JSF world,
    I am planning to use your plugin in my coming major project specially that it will run behind a slow network connection.
    But could you tell us , when the first final version could be released ??

    Reply
    1. Stephan Rauh Post author

      That’s a big honor to me!

      I intend to finalize the version with the next two or three weeks.

      At the time being, there’s only one error I know of, so I hope to be able to provide a final version soon. As long as you avoid full-page AJAX requests (i.e. @all and ajaxfied commandButtons and commandLinks) everything should run fine with the current version.

      By the way, BabbageFaces is still pretty new, so it might be a good idea to start with small, simple JSF views instead of trying to run it immediately with a full-featured application. When I started to port the PetStore application to BabbageFaces I was surprised other people use JSF differently than I do, so I stumbled over a lot of unexpected errors.

      Reply
    1. Stephan Rauh Post author

      You’re right – since PrimeFaces 5 has been released, it’s high time I release BabbageFaces, too. At the moment I recommend to use the source code version at https://github.com/stephanrauh/AngularFaces/tree/master/AngularFaces_1.0/babbageFaces-core.

      You can download the binaries at https://github.com/stephanrauh/AngularFaces/tree/master/AngularFaces_1.0/dist. I just hesitate to call it a stable version because there are one or two issues left.

      Reply
  2. John

    This is great!

    A couple questions:
    1 – Have you considered allowing the babbageFacesStatistics to be disabled in the response? Perhaps based on the javax.faces.PROJECT_STAGE context param? This would further reduce the network load in a production environment.
    2 – How about teaming up with the PrimeFaces guys to officially recommend BabbageFaces in the next version of PrimeFaces, include in ShowCase, User Guide, etc?

    Reply
    1. Stephan Rauh Post author

      Thank you very much!

      You’re right: Of course the statistics are not meant to be included in every response. My idea is to simply generate statistics if the BabbageFaces statistics div is part of the page. If it isn’t, there’s no point in generating the statistics, so I’ll omit them. I’ve opened an issue on my GitHub repository.

      As far as I know the PrimeFaces team is aware of BabbageFaces. In fact, it’s an idea of Thomas Andraschko, one of the PrimeFaces committers. Whether I can convince them to recommend BabbageFaces is another question. In the short term I concentrate on releasing a stable version. I’m fairly optimistic the upcoming RC2 is a stable version – but then, it’s not the first time I’m optimistic. JSF responses never cease to surprise me with unexpected twists :).

      Reply
      1. John

        Hi Stephan,

        Thanks for the response. I’m happy to hear that the statistics in the response will be optional at some point, and for the continued collaboration with the PrimeFaces team.

        There is one issue I ran into today while testing RC1. If I have several components with p:ajax attached to the change event, and the async attribute is set to true, then several updates in quick succession cause BabbageFaces to choke and the rendered page becomes broken.

        After thinking about it, this make sense because of the way BabbageFaces works by determining differences. I think just adding to your documentation that ajax events must be processed synchronously should be enough for the first release. Maybe in release 1.1 or later, it could recognize the async attribute being set and produce a warning or something.

        Cheers, and best wishes on continued success with this project!

        Reply
        1. Stephan Rauh Post author

          Async sounds like a real challenge. I’m not sure BabbageFaces can support asynchronous requests properly. Maybe a warning is the best thing we can do.

          This evening I’ve finished what I’m going to call RC2. This version display the statistics only in developer mode, and only if the text

          <div id="babbageFacesStatistics"></div>
          

          is part of the JSF source code.

          You can see the showcase examples on my showcase (BabbageFaces running on Mojarra and running on Apache MyFaces). The server is a little slow (it’s the free starter version of OpenShift). On my local machine BabbageFaces is a lot faster (30%-50% additional rendering time compared to native JSF without business logic).

          Reply
  3. Peter Magsam

    hallo Stephan,

    I just tested babbageFaces with primefaces 5.2. There seem to be a bug with <pe:masterDetailLevel no reaction when I click for the next level. This error i get

    [Fatal Error] :54:262: Open quote is expected for attribute "id" associated with an element type "img".]]

    with this code

    This is the application http://www.osretail.de/osRetail I tested.

    regards form Bavaria

    Peter

    Reply

Leave a Reply

Your email address will not be published.