The Source for Java Technology Collaboration
User: Password:



Ed Burns

Ed Burns's Blog

AJAXian Faces Progress Bar

Posted by edburns on May 19, 2005 at 06:30 PM | Comments (12)

I've written my first AJAXian JSF component. I took Greg Murray's very useful but utterly non-componentized Progress Bar example and generalized it into a faces component that allows you to simply put this in your page:

<d:progressBar id="progressBar" 
                           value="#{process.percentage}" 
                           interval="1000" />

And there you have a dynamically updating progress bar that doesn't cause a page refresh.

I've written the component up in the Solutions Catalog and you can get the source there as well. The main thing this building this component taught me is that writing and debugging JavaScript is no-fun so I'm glad to see that Faces can relieve the page author of such nonsense.

Technorati Tags:

Bookmark blog post: del.icio.us del.icio.us Digg Digg DZone DZone Furl Furl Reddit Reddit
Comments
Comments are listed in date ascending order (oldest first) | Post Comment

  • That is really cool! I know you mention having view state saved on the client, I'm assuming this also works with view state being stored on the server? For those that are concerned about bandwidth (who isn't??), not having to post the serialized view state would be a big saver for multiple AJAX requests.

    Posted by: jhook on May 20, 2005 at 06:13 AM

  • Because 1.1 only has the saved state param in the client saving case, the javascript needs to be fixed to not crash if the saved state param is absenst. Currently it assumes
    the saved state param is present.

    A 1.2 version of this wouldn't have to do that check because the saved state param is always present, and, indeed is specified, rather than being an implementation detail.

    Posted by: edburns on May 20, 2005 at 06:31 AM

  • I know we've talked about this in the expert group, but providing drop in functionality like this in JSF is what will make the platform really take off.

    Posted by: jhook on May 20, 2005 at 07:13 AM

  • JSF was always cool, but with these AJAXian components it's really starting to rock.

    Posted by: johnreynolds on May 20, 2005 at 07:13 AM

  • There is another AJAX JSF Component at http://www.skycode.us that does AJAX autocomplete.

    Posted by: thermonuclearprotection on May 20, 2005 at 11:00 AM

  • I downloaded bpcatalog-1.0.1_01, and it is throwing javascript error (at progress starting) with myfaces in tomcat(not working at all). But with sun java application server, it shows the progress, and throws javascript error when progress reaches 100%. What could be the problem? (I use myfaces 1.1.1)

    Posted by: hari_sujathan on January 12, 2006 at 09:48 PM

  • I haven't tested it with myfaces. Please post to their developer list.

    Ed

    Posted by: edburns on January 17, 2006 at 08:51 AM

  • It indeed doesn't work with myfaces, but the fix to make it work is simple. A quick glance at the source code reveals that the AJAX code (in progressbar.js) only submits the "com.sun.faces.VIEW" post parameter. The data comes from a hidden input parameter that stores the JSF tree clientside.

    MyFaces however doesn't use the "com.sun.faces.VIEW" name, but instead breaks it down into several parts with completely different names: "jsf_tree_64", "jsf_state_64" and "jsf_viewid". On top of that, the JSF form element in MyFaces renders an input parameter with the name of the form's ID + the "_SUBMIT" suffix. It uses this to check whether the form is actually submitted or not.

    Without these parameters present, MyFaces doesn't recognize the AJAX request as a faces request and thus does not do the processDecode stuff. You'll get a javascript error on accessing request.responseXML, since the response is the regular HTML rendering of the whole page which is not XML compliant (and even it was, it's not the message we're after).

    The fix is to simply include the parameters MyFaces wishes to have. If you change the original progressbar.js to include the following, than it should probably work in most situations (did a quick test on Tomcat 5.5.16 and MyFaces).


    // add this:
    function addEncodedElement( requestParams, elementName ) {

    var elementArray = window.document.getElementsByName(elementName);

    if ( elementArray != null && elementArray.length > 0 ) {
    var elementValue = elementArray[0].value;
    var encodedValue = encodeURI(elementValue);
    var re = new RegExp("\\+", "g");
    var encodedPlusValue = encodedValue.replace(re, "%2B");
    requestParams = requestParams + elementName + "=" + encodedPlusValue + "&";
    }

    return requestParams;
    }

    Posted by: atijms on April 14, 2006 at 04:07 PM


  • // and change the original initRequest into this:
    function initRequest(clientId) {

    var params = "";
    var formName = getCurrentFormId();

    // build the query string from the named elements in our current form
    var elementNames = new Array( "com.sun.faces.VIEW", "jsf_tree_64", "jsf_state_64", "jsf_viewid", formName + "_SUBMIT" );
    for ( i=0; i

    Posted by: atijms on April 14, 2006 at 04:08 PM

  • whoops, the last posting broke on the angel bracket. Here's the correct version:

    // and change the original initRequest into this:
    function initRequest(clientId) {

    var params = "";
    var formName = getCurrentFormId();

    // build the query string from the named elements in our current form
    var elementNames = new Array( "com.sun.faces.VIEW", "jsf_tree_64", "jsf_state_64", "jsf_viewid", formName + "_SUBMIT" );
    for ( i=0; i < elementNames.length; i++ ) {
    params = addEncodedElement( params, elementNames[i] );
    }
    params = params + formName + "=" + formName + "&" + clientId + "=ajax&" + "bpcatalog.abortPhase=4";

    var postbackURL = getPostbackURL();
    var request = getXMLHttpRequest();
    request.open("POST", postbackURL, true);
    request.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");

    var result = new Array();
    result.request = request;
    result.params = params;
    return result;
    }

    Posted by: atijms on April 14, 2006 at 04:12 PM

  • The fix for myfaces works for me but only in client side state saving mode. I tried to get it working in server side mode as well, but I didn't succeed yet. The initial request works but then the "decode" method of the renderer ist not called during polling. So instead of the xml, the whole page is returned to ajax. Any Ideas?
    (I am using myfaces 1.1.1 and tomcat 5.5)

    Posted by: nf805 on April 26, 2006 at 01:10 AM

  • Just figured out, that in works with myfaces 1.1.2 (server side state saving) with the additional parameter "jsf_sequence". (Just put it in the elementNames array)

    Seems to be a bug in 1.1.1 with restoring view.

    Posted by: nf805 on April 26, 2006 at 05:25 AM





Powered by
Movable Type 3.01D
 Feed java.net RSS Feeds