Skip to main content

TOTD #48: Converting a JSF 1.2 application to JSF 2.0 - Facelets and Ajax

Posted by arungupta on October 15, 2008 at 5:40 AM PDT



href="http://blogs.sun.com/arungupta/entry/totd_47_getting_started_with">TOTD
#47 showed how to deploy a JSF 1.2 application (using
Facelets and Ajax/JSF Extensions) on href="http://javaserverfaces.dev.java.net">Mojarra
2.0-enabled GlassFish.
 In this blog we'll use new features added in JSF 2.0 to
simplify our
application:

  • Use href="http://weblogs.java.net/blog/edburns/archive/2008/08/facelets_jsf_20.html">integrated
    Facelets and href="http://blogs.sun.com/rlubke/entry/jsf_2_0_new_feature4">resource
    re-location to simplify our facelets
  • Replace JSF Extensions Ajax API with new in-built
    JavaScript APIs to expose Ajax functionality.

Let's get started!

  • Re-create the app as defined in href="http://blogs.sun.com/arungupta/entry/totd_47_getting_started_with">TOTD
    #47. This app is built using JSF 1.2 core components and
    Facelets. It uses JSF Extensions for adding Ajax capabilities. Lets
    change this app to use newer features of JSF 2.0.
  • Edit "faces-config.xml" and change the value of
    faces-config/@version from "1.2" to "2.0".
  • Remove the following fragment from "faces-config.xml":


    style="text-align: left; background-color: rgb(204, 204, 255); width: 100%;"
    cellpadding="2" cellspacing="2">
       
    <application>

           
    <view-handler>com.sun.facelets.FaceletViewHandler</view-handler>

        </application>



    This fragment is no longer required because Facelets is the default
    view technology in JSF 2.0. But it's important to remember that JSF 2.0
    Facelets is disabled by default if "WEB-INF/faces-config.xml" is
    versioned at 1.2 or older.

  • Remove the following code fragment from "web.xml":


    style="text-align: left; background-color: rgb(204, 204, 255); width: 100%;"
    cellpadding="2" cellspacing="2">
           
    <init-param>

             
    <param-name>javax.faces.LIFECYCLE_ID</param-name>

             
    <param-value>com.sun.faces.lifecycle.PARTIAL</param-value>

           
    </init-param>



    This is only required if JSF Extensions APIs are used.

  • Edit "welcome.xhtml" and replace code with:


    style="text-align: left; background-color: rgb(204, 204, 255); width: 100%;"
    cellpadding="2" cellspacing="2">
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0
    Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

    <html xmlns="http://www.w3.org/1999/xhtml"

         
    xmlns:ui="http://java.sun.com/jsf/facelets"

         
    xmlns:h="http://java.sun.com/jsf/html">

        <ui:composition>

            style="font-weight: bold;"><h:head>

               
    <h1><h:outputText value="What city do you like ?"
    /></h1>

            style="font-weight: bold;"></h:head>

           

            style="font-weight: bold;"><h:body>

               
    <h:form prependId="false">

                   
    <h:panelGrid columns="2">

                       
    <h:outputText value="CityName:"/>

                       
    <h:inputText value="#{cities.cityName}"

                                    
    title="CityName"

                                    
    id="cityName"

                                    
    required="true"

                                    
    onkeyup="javax.faces.Ajax.ajaxRequest(this,
    event, { execute: 'cityName', render: 'city_choices'});
    "/>

                       
    <h:outputText value="CountryName:"/>

                       
    <h:inputText value="#{cities.countryName}" title="CountryName"
    id="countryName" required="true"/>

                   
    </h:panelGrid>

                   


                   
    <h:commandButton action="#{dbUtil.saveCity}"
    value="submit"/>

                   
    <br/><br/>

                   
    <h:outputText id="city_choices"
    value="#{dbUtil.cityChoices}"></h:outputText>

                   


                   
    <br/><br/>

                   
    <h:message for="cityName" showSummary="true" showDetail="false"
    style="color: red"/><br/>

                   
    <h:message for="countryName" showSummary="true"
    showDetail="false" style="color: red"/>

               
    </h:form>

            style="font-weight: bold;"></h:body>

            style="font-weight: bold;"><h:outputScript
    name="ajax.js" library="javax.faces" target="header"/>


        </ui:composition>

       

    </html>



    The differences are highlighted in bold and
    explained below:

    • "template.xhtml" is no longer required because standard
      tags are used to identify "head" and "body".
    • <h:head> and <h:body> are new
      tags defined in JSF 2.0. These tags define where the nested
      resources need to be rendered.
    • <h:outputScript> is a new tag defined in
      JSF 2.0 and allows an external JavaScript file to be referenced. In
      this
      case, it is referencing "ajax.js" script and is rendered in "head". The
      script file itself is bundled in "jsf-api.jar" in
      "META-INF/resources/javax.faces" directory. It adds Ajax
      functionality to the application.
    • "javax.faces.Ajax.ajaxRequest" function is defined in the
      JavaScript file "ajax.js". This particular function invocation ensures
      that "city_choices" is
      rendered when execute
      portion of the request lifecycle is executed for "cityName" field. The
      complete documentation is available in "ajax.js". Read more
      details about what happens in the background href="http://www.jroller.com/HazemBlog/entry/ajax_integration_with_jsf_2">here.



    Notice how the Facelet is so simplified.

  • Refactor "result.xhtml" such that the code looks like as
    shown below:



    src="http://blogs.sun.com/arungupta/resource/images/mojarra2-cities-jsf2-result-xhtml.png">



    The changes are explained in the previous step, basically a clean
    Facelet using standard <h:head> and
    <h:body> tags and everything else remains as is.

And that's it, just hit "Undeploy and Deploy" in NetBeans IDE and your
application should now get deployed on Mojarra 2.0-enabled GlassFish.
To reiterate, the main things highlighted in this blog are:

  • Facelets are integrated in Mojarra 2.0.
  • New tags for resource re-location allow a simpler and
    cleaner facelet embedded in a JSF application.
  • JavaScript APIs provide a clean way to expose Ajax
    functionality in JSF app.

And all of these features are defined in the JSF 2.0 specification. So
if you are using Mojarra then be assured that you are developing a
standards compliant user interface.



Have you tried your JSF 1.2 app on Mojarra 2.0 ? Drop a comment on this
blog if you have.


File JSF related bugs href="https://javaserverfaces.dev.java.net/issues/enter_bug.cgi?issue_type=DEFECT">here
using "2.0.0 EDR1" version and ask your questions on href="mailto:webtier@glassfish.dev.java.net">webtier@glassfish.dev.java.net.



Please leave suggestions on other TOTD ( style="font-weight: bold;">Tip style="font-weight: bold;">Of style="font-weight: bold;">The style="font-weight: bold;">Day) that
you'd like to see.
An archive of all the tips is available href="http://blogs.sun.com/arungupta/tags/totd">here.




Technorati: totd
javaserverfaces
glassfish
mojarra
netbeans

Related Topics >>

Comments

Et tu, ED? Anyway, I think there is much to be said for frameworks where the developer does not have to go back and forth between various languages for programming. It makes both maintenance and development easier for everybody. Perhaps for large mythical teams where you have UI being developed in Botswana and the controller in Belige and the datamodel in Ghaziabad, it's more productive to have some people to specialize in XML and others in Java etc. but for entities with less than a zillion Rupees in capitalization it is quite cumbersome to use different languages for different parts of the applications.

I'm saying render to XML what is XML's and render to Java what is Java's. Less cryptically, I think the record shows that describing a UI in markup is a great way to build a UI quickly for a large number of kinds of applications.

Nahh... You can use annotations instead of xml if you like... ;-)

Ed Are you saying that we should use XML for Swing?

V> Like a broken record, I will put in my two cents that it is V> astounding at best that Sun, which used to be a leader in this area, V> is still pushing all this tagged based development framework V> comprising of heterogeneous technologies (XML, scripting etc.) when V> so may other environments wherein you can program almost all of a web V> application in pure Java are already available. I expect better from V> Sun. Hello Varan, and thanks for your interest. Like the ancient Roman Empire, Java's strength is its diversity. Are you asserting that programming a web application in pure Java is the "best" way to do so? You're certainly welcome to make that assertion, but I know for a fact that many users would not agree. The best thing is you can have your Wicket and eat it too! Ed

Like a broken record, I will put in my two cents that it is astounding at best that Sun, which used to be a leader in this area, is still pushing all this tagged based development framework comprising of heterogeneous technologies (XML, scripting etc.) when so may other environments wherein you can program almost all of a web application in pure Java are already available. I expect better from Sun.

That's really good, thanks for this TOTD. As for another suggestion, what about having this same TOTD but calling a ManagedBean. I would like to see how declaring ManagedBeans and navigation have been simplified in JSF 2.0 (any @ManagedBean annotation ?)