Presenting JSF to People with Struts Background

Last week I’ve given a JSF presentation at a local seminar. The attendants are mostly developers with Struts background and I guess they are impressed after I showed the abilites of JSF. The topics I’ve talked about are the component model, events, state management, binding mechanism, IOC and managed beans, Ajax and Apache MyFaces. Here are some pictures from the presentation.

Free Image Hosting at www.ImageShack.us Free Image Hosting at www.ImageShack.us Free Image Hosting at www.ImageShack.us Free Image Hosting at www.ImageShack.us Free Image Hosting at www.ImageShack.us
Before the presentation, I made a new build of myFaces with maven2 to get the last example web applications to demonstrate several components from both tomahawk-sandbox like tree2,tabbed pane, datatable, fisheye(my favorite), chart creator(jsf-comp) and etc. Also since FacesTrace has an educational value in addition to it’s debugging JSF flow capabilities, I’ve used it to demonstrate what is going on behind the curtains of JavaServer Faces. In general I could say people really enjoyed the framework and realized how easy to create web applications with it, hope these add more to the popularity of the framework around here.

Posted in Java. 6 Comments »

Hacking JSF State Management with AJAX

I was working on an “Export-to-Excel” feature for the datatable components we use in our project. The requirement is when the client clicks on the excel icon on a datatable, a window opens and responses the data as an excel file.

There is an excellent library created by my colleague Mert called JSFExcelCreator that takes the id of the data table and gives the excel, however after integrating this library to our custom data table renderer, we’ve realized that it only works when the state is hold at server. The reason is obvious; a phaselistener traverses the component tree in the view, finds the datatable and outputs the excel after examining it. When the state saving method is client, the newly opened window responsible for giving the excel cannot find the component tree since the view stayed as an hidden variable at the first page which fired the javascript event to open a new excel window.

The solution I’ve thought is to use AJAX and include the view state to the AJAX request, therefore JSF takes the view state, restores the view, rebuilds the component tree with no postback. This results the view to be available available in an AJAX request. Following are the javascript functions I’ve written to handle the AJAX stuff;

var http = createRequestObject();

function createRequestObject() {
    var requestObject;
    var browserName = navigator.appName;
    if(browserName == “Microsoft Internet Explorer”) {
        requestObject = new ActiveXObject(“Microsoft.XMLHTTP”);
    }
    else {
        requestObject = new XMLHttpRequest();
    }
    return requestObject;
}

function sendExcelReq(tableId) {
    var parameters = getAjaxExcelRequestParams(tableId);
    var url = document.forms[0].action;
    http.open(‘POST’, url, true);
    http.setRequestHeader(‘Content-Type’, ‘application/x-www-form-urlencoded’);
    http.onreadystatechange = function() {
        if(http.readyState == 4) {
            document.getElementById(tableId+’:excelIcon’).style.display=’inline’;
            document.getElementById(tableId+’:statusText’).style.display=’none’;
            window.open(postbackURL+’?excelResponseTableId=’ + tableId);
        } else {
            //I envy gmail’s loading text, while waiting for the excel response, make the status text visible
            document.getElementById(tableId+’:excelIcon’).style.display=’none’;
            document.getElementById(tableId+’:statusText’).style.display=’inline’;
        }
    }
    http.send(parameters);
}

function isStateClient() {
    var viewState = document.getElementsByName(‘com.sun.faces.VIEW’)[0];
    if(viewState == null)
        return false;
    else
        return true;
}

function getAjaxExcelRequestParams(tableId) {
    var params = null;
    if(isStateClient( ) ) {
        var viewStateValue = encodeURI(document.getElementsByName(‘com.sun.faces.VIEW’)[0].value);
        var regExp = new RegExp(“\\+”,”g”);
        var encodedViewState = viewStateValue.replace(regExp, “\%2B”);
        params = ‘com.sun.faces.VIEW=’ + encodedViewState + ‘&excelRequestTableId=’ + tableId;
    }
    else {
        params = ‘excelRequestTableId=’ + tableId;   
    }
    return params;
}

When the state saving is server, there is no need to include the viewstate to the Ajax request, but when it is on client, params must contain the encoded view state which will be used to restore the component tree at Restore View phase. The whole thing is this actually, including the view state to the Ajax request imitating that it is a normal JSF request and gain access to the component tree when the state saving is method client.

The phaselistener responsible for handling the request and the response of excel requests is the following(excel creation with poi code omitted);

  
    
    

    public class AjaxPhaseListener implements PhaseListener {

  public void afterPhase(PhaseEvent phaseEvent) {
    FacesContext facesContext = phaseEvent.getFacesContext();
    Map requestMap = facesContext.getExternalContext().getRequestParameterMap();
    String excelRequestTableId = (StringrequestMap.get("excelRequestTableId");
    String excelResponseTableId = (StringrequestMap.get("excelResponseTableId");
    if (excelRequestTableId != null) {
      handleExcelRequest(facesContext, excelRequestTableId);
    else if(excelResponseTableId != null) {
      handleExcelResponse(facesContext, excelResponseTableId);
    }
  }

  private void handleExcelRequest(FacesContext facesContext, String excelRequestTableId) {
    UIComponent component = findComponentInRoot(excelRequestTableId);
    if (component != null && component instanceof HtmlDataTable) {
      HttpServletResponse response = (HttpServletResponsefacesContext.getExternalContext().getResponse();
      Map session = facesContext.getExternalContext().getSessionMap();

      HSSFWorkbook generatedExcel = null;
      generatedExcel = generateExcel(facesContext,(HtmlDataTablecomponent);
      if (generatedExcel != null) {
        session.put(excelRequestTableId, generatedExcel);
      }
    }
    facesContext.responseComplete();
  }
  
  private void handleExcelResponse(FacesContext facesContext, String excelResponseTableId) {
    Map session = facesContext.getExternalContext().getSessionMap();
    HSSFWorkbook excelWorkBook = (HSSFWorkbook)session.get(excelResponseTableId);
    HttpServletResponse response = (HttpServletResponsefacesContext.getExternalContext().getResponse();
    
    response.setContentType("application/vnd.ms-excel");
    try {
      excelWorkBook.write(response.getOutputStream());
    catch (IOException e) {
      e.printStackTrace();
    }
    session.remove("excelResponseTableId");
    facesContext.responseComplete();
  }

  public void beforePhase(PhaseEvent phaseEvent) {

  }

  public PhaseId getPhaseId() {
    return PhaseId.RESTORE_VIEW;
  }
      

Long story short, using this way an one can access the viewstate even it is saved on the client and the request is of type ajax. Exporting the data to as an excel is just the outcome of this approach for demonstrating a use case. Enough of text and here are two screenshots showing the export-to-excel support in a JSF datatable. After clicking the excel icon, user is informed by a text displaying “loading”. Reminds gmail a bit:) Yes, I admit, it is inspired by gmail. After the excel is ready, the excel icon is displayed again.

Free Image Hosting at www.ImageShack.us Free Image Hosting at www.ImageShack.us 

Posted in Java. 3 Comments »

Tracing JSF Applications with FacesTrace

The simplest way to use the “runtime debugging” JSF tool FacesTrace is to place the <ft:trace /> tag at the end of a page. Then let the library do it’s job. We’ve decided to include FacesTrace in our project for both debugging and orientation purposes. We’ve some new folks and I think it would help them to get oriented faster.

The main thing in my mind was to create an infrastructure that will enable us to use facestrace without placing the <ft:trace /> component manually to each page. In order to do this, first I’ve tried to decorate the view handler and add the facestrace component to the viewroot. The component was successfully added to the tree but does not get rendered. In JSF the component tree is created during the rendering which means, JSF does not create the component tree first and then render it. This is the reason why getChildrenCount() at encodeBegin of your custom components returns 0 since JSF creates the tree during the rendering. Anyway then I’ve tried to change the form renderer and it worked like a charm. The facestrace is rendered after </h:form> meanining at the end of our pages.

 public class TraceEnabledFormRenderer extends FormRenderer {
    
     public TraceEnabledFormRenderer() {
        super();
    }

     public void encodeEnd(FacesContext context, UIComponent component) throws IOException{
         super.encodeEnd(context, component);
         ServletContext servletContext = (ServletContext)context.getExternalContext().getContext();
  
      boolean isTraceEnabled =      
Boolean.valueOf(servletContext.getInitParameter(“net.sf.facestrace.ENABLE_TRACE”)).booleanValue();

         if(isTraceEnabled) {
             Trace trace = (Trace)context.getApplication().createComponent(Trace.COMPONENT_TYPE);
             trace.encodeEnd(context);
         }
     }
}


And here is the context-param to control the faces trace.

    <context-param>
        <param-name>net.sf.facestrace.ENABLE_TRACE</param-name>
        <param-value>true</param-value>
    </context-param>

Last thing is to define the custom renderer at faces-config.

    <render-kit>
        <renderer>
            <component-family>javax.faces.Form</component-family>
            <renderer-type>javax.faces.Form</renderer-type>
            <renderer-class>conf.TraceEnabledFormRenderer</renderer-class>
        </renderer>
    </render-kit>

By the way, I’ve done some documentation, features, screenshots and more FacesTrace home page.

Posted in Java. 1 Comment »

JSF: Serving Resources From a Jar

Many rich client JSF components use external resources of their own like scrips, stylesheets, images and etc. Suppose you have created one, packed in a jar and make it  ready to distribute. The problem is that the user of your library must extract all the stuff if you’ve not added some tricks to your component to load the resources from the jar. If the resource is a script maybe it can be rendered onto the client however this will be a huge mistake. What happens if there are lots of scripts or even images, style sheets and etc. Good news is that there are various solutions you can employ for this problem.

1) Phaselistener
If you are lucky to use JSF, this is your possible answer. A restore view listener will intervene the lifecycle, if the request is for a resource, it creates a url connection and streams it onto the client. The browser usually caches the resource. After the resource is streamed phaselistener calls responseComplete to stop the JSF lifecycle. Actually phaselistener can output anything using this way excel, image etc…

2) Filter
Lucky MyFaces users are familiar with this approach. MyFaces uses an extension filter to attach the resources demanded from the components(tomahawk).

3) Servlet
Unlucky IBM JSF users are familiar with this one. It is based on the same principle with a phaselistener actually. A special request
comes to the servlet and it streams the resource onto the client.

4) Weblets
Created only for this job. This one is an open source library aiming to ease the resource loading problem. Everything seems good at first glance but weblets are “a little bit” complicated. It uses it’s own view handler and yet another metadata weblets-config.xml and more…

Comparison
Filter and Servlet is not specific to JSF but can also be used. I think Phaselistener approach is the simplest and the most convenient way if you are using JSF. I’ve used and enjoyed it when working on facestrace and JSF client side validators. The main advantage is that both filter and servlet must be declared-mapped at web.xml, on the other hand since faces-config.xml’s at classpath are merged, there is no need to declare any metadata for a phaselistener. Weblets are also another JSF alternative, I’ve never used them because I love phaselisteners more than anything in my entire life. Actually real reason is that weblets seem to be too complex for the job when compared to a simple one class phaselistener.

More information on these techniques;

Posted in Java. 4 Comments »

JSF Channel on IRC

Have unanswered questions regarding JSF? Want to talk about JSF related topics? Or maybe you just like chatting. Anyway there is a nice JSF Room at IRC freenode that you can find all of these. There are many regular guys visiting the room and irregular ones like me. Usually JSF Spec lead Ed Burns is around, I guess he is not bored of answering questions:)

I see the room as a great interactive JSF resource and generally visit to join the hot discussions on the topics including the JSF unrelated ones.  For people who are interested, it is located at “##jsf channel on irc.freenode.net“, also you can check out all the conversations logged.

Posted in Java. 1 Comment »