<< August 2009 | Home | October 2009 >>

ICEfaces revisited

Since my previous blog-post (Dynamic DataTables in ICEfaces), I have encountered several more situations where calling setId() seems to be required: for example, PanelCollapsible content was not rendered, and the Highlight effect was never fired, unless their generation was accompanied with a setId() call. The strange thing is that in these cases the problem only occurred on some platforms, not on others. Same application source, same ICEfaces version, same GlassFish version, but slightly different Java revisions and completely different operating systems. I gave up trying to find the underlying reason for this, and added the following code instead:

    private int ensureIds(UIComponent x, int i) {
        if (x.getId() == null) {
            i++;
            x.setId("g" + Integer.toString(i));
        }
	for (Iterator j = x.getFacetsAndChildren(); j.hasNext(); ) {
i = ensureIds(j.next(), i);
}
return i;
}

Then immediately after all components have been generated, ensureIds(binding,0) is called, where binding is the root UIComponent of the generated tree.

Some more non-obvious quirks:

  • The ICEfaces Ajax push-server does not work reliably with the GlassFish https listener. It has problems even with ordinary http behind a https-frontend reverse proxy (I am currently using Apache httpd with mod_proxy for this). This is a shame, because no one uses unencrypted transport these days for non-public data of any kind. Apparently ICEsoft provides a non-free Enterprise Push Server that is designed to handle https, and it also handles clustering and failover. Clustering and failover is clearly enterprise stuff, but surely something as basic as https should be among the fundamental feature set. I consider the push-server to be dangerously close to crippleware... Fortunately it is possible to get along without the push-server, as long as you are content to live with some limitations.

  • Some ICEfaces components (e.g. RowSelector) need method expressions with named beans. This is awkward for two reasons: the first is that a named JSF bean, which is a declared container-managed entity, must be referenced in the expression. But a simple listener object (or "lambda closure" in other languages) would have been enough. The second reason is that ICEfaces uses a deprecated API for this method expression, producing a warning at every compilation.

  • The presence of a started but uncommitted UserTransaction seems to inhibit ICEfaces from performing a rendering after a OnDemandRenderer.requestRender(). Actually, I am not 100% sure about this one, but switching the order of my requestRender() and commit() calls got asynchronous rendering working for me.

I just had get this off my chest. All in all, I still like ICEfaces very much, and I wouldn't trade it for any alternative Ajax toolkit.