Friday, May 22, 2009

Using GWT and Ajax4jsf together

Recently I had to face a situation it's hard to speak about :) In a Seam+RichFaces based application we needed to develop a special component, which needs a large amount of client side JavaScript code. I decided to use GWT to develop this functionality. It's very simple to embed a GWT application supporting a JSF component to a page, especially if you have only one instance of the component on the page - you just include the compiled JS.

Everything seemed working fine until I tested it in Internet Explorer 6. In IE6, the GWT RPC calls just didn't succeed, the IE6 JavaScript error report said 'unhandled exception', in a meaningless line of JS code, of course. I found that it works fine if I don't have an a4j:form on my page. After a number of tries I found that the loading of the core JavaScript library of Ajax4Jsf already causes the problem, and then, looking through the code, I found a suspicious statement:

 XMLHttpRequest = function() {
   _SARISSA_XMLHTTP_PROGID = Sarissa.pickRecentProgID( [
     "Msxml2.XMLHTTP.6.0", "MSXML2.XMLHTTP.3.0",
     "MSXML2.XMLHTTP", "Microsoft.XMLHTTP" ]);
  return new ActiveXObject(_SARISSA_XMLHTTP_PROGID);

And this turned out to be the problem indeed. Normally, the XMLHttpRequest variable is simply null. I didn't dare look through the GWT RPC implementation to investigate the problem further :) But at this point, we can already work the thing around.

So I introduced a 'beforeRequest' and 'afterRequest' JSNI methods in my GWT code to ensure that '$wnd.XMLHttpRequest' is null during the RPC call. This way, GWT RPC calls work fine, and the normal a4j functionality is still available in the page.

Tuesday, May 12, 2009

Showing not shown Faces Messages

Most of us using JSF 1.2 RI are familiar with the warning message in our logs:

[lifecycle] WARNING: FacesMessage(s) have been enqueued, but may not have been displayed.

JavaServer Faces has a mechanism to assign messages to specific components. In the common case, if an input field has a validation error, the error message is queued to that field, and a h:message put next to the input field can show the message on the page:

<h:inputtext id="firstName"/>
<h:message for="firstName"/>

The JSF Reference Implementation has a solution to help us find out if we forgot to put a h:message tag for some components. Unfortunately, it only shows a warning message in the log, and we have no programmatic way to process those messages. Well, almost no way.

If you dare take a look in com.sun.faces.lifecycle.RenderResponsePhase, you can see that if there are any messages queued, a special variable of the Set is added to the request map. All client ids of controls with faces messages are added to this set. When h:message tags render, they access the messages queued for their associated client ids using the getMessages(String clientId) method in com.sun.faces.context.FacesContextImpl. This method removes the client id from the set, thus signalling that the messages for that client id are displayed. When finished rendering, messages for the client ids remaining in the Set are those that are not displayed. The class RenderResponsePhase simply logs these messages and then disposes the Set.

In one of my applications, I wanted to present these messages at the top of my forms. This can come really useful especially in development phase. As seen from the above, I have the necessary information ready at the very end of each render phase. I created a Seam component with a method to handle it:

public class MessageHandler {

public String handleUnAssignedMessages() {
    // copy-paste from com.sun.faces.lifecycle.RenderResponsePhase
        Set clientIds = TypedCollections.dynamicallyCastSet(
                (Set) FacesContext.getCurrentInstance().getExternalContext().getRequestMap()
                .remove(RIConstants.CLIENT_ID_MESSAGES_NOT_DISPLAYED), String.class);
        if (clientIds != null)
            for (String clientId : clientIds) {
                Iterator messages = 
                while (messages.hasNext()) {
                    FacesMessage message =;
                    if (message.getSeverity() == FacesMessage.SEVERITY_ERROR ||
                            message.getSeverity() == FacesMessage.SEVERITY_FATAL) {
                        String text = message.getSummary() + " " + message.getDetail();
                                new FacesMessage(FacesMessage.SEVERITY_ERROR, text, text));
    return "";

This method simply collects all nondisplayed error messages and enqueues them without assigning them to a specific client id. Note that you'll have to include the jsf-impl.jar in your classpath for this code to compile. Having these messages enqueued, you can present them by a h:messages tag, or you can do anything programmatically with them.

Note that as you only have this information at the end of the render phase, you have to put the invocation of this method at the end of your page. If you want also to present them on the page with a h:messages tag, you have to put it after the invocation of the method above. You can then move the html output to the desired place in your document (above your forms, probably) with a simple javascript code:

#{messageHandler.handleUnAssignedMessages()} <h:messages layout="table" styleclass="msg_gl" infoclass="info-message" warnclass="warning-message" errorclass="error-message" globalonly="#{true}" showsummary="#{false}" showdetail="#{true}"> </h:messages>

So that's it.