Arun Gupta, Miles to go ...

Arun Gupta is a technology enthusiast, a passionate runner, and a community guy who works for Sun Microsystems.

http://blogs.sun.com/arungupta/date/20091002 Friday October 02, 2009

http://blogs.sun.com/arungupta/date/20090817 Monday August 17, 2009

TOTD #95: EJB 3.1 + Java Server Faces 2.0 + JPA 2.0 web application - Getting Started with Java EE 6 using NetBeans 6.8 M1 & GlassFish v3


TOTD #93 showed how to get started with Java EE 6 using NetBeans 6.8 M1 and GlassFish v3 by building a simple Servlet 3.0 + JPA 2.0 web application. TOTD #94 built upon it by using Java Server Faces 2 instead of Servlet 3.0 for displaying the results. However we are still using a POJO for all the database interactions. This works fine if we are only reading values from the database but that's not how a typical web application behaves. The web application would typically perform all CRUD operations. More typically they like to perform one or more CRUD operations within the context of a transaction. And how do you do transactions in the context of a web application ? Java EE 6 comes to your rescue.

The EJB 3.1 specification (another new specification in Java EE 6) allow POJO classes to be annotated with @EJB and bundled within WEB-INF/classes of a WAR file. And so you get all transactional capabilities in your web application very easily.

This Tip Of The Day (TOTD) shows how to enhance the application created in TOTD #94 and use EJB 3.1 instead of the JSF managed bean for performing the business logic. There are two ways to achieve this pattern as described below.

Lets call this TOTD #95.1

  1. The easiest way to back a JSF page with an EJB is to convert the managed bean into an EJB by adding @javax.ejb.Stateless annotation. So change the  "StateList" class from TOTD #94 as shown below:

    @javax.ejb.Stateless
    @ManagedBean
    public class StateList {
        @PersistenceUnit
        EntityManagerFactory emf;

        public List<States> getStates() {
            return emf.createEntityManager().createNamedQuery("States.findAll").getResultList();
        }
    }

    The change is highlighted in bold, and that's it!
Because of "Deploy-on-save" feature in NetBeans and GlassFish v3, the application is autodeployed. Otherwise right-click on the project and select Run (default shortcut "F6"). As earlier, the results can be seen at "http://localhost:8080/HelloEclipseLink/forwardToJSF.jsp" or "http://localhost:8080/HelloEclipseLink/faces/template-client.xhtml" and looks like:



The big difference this time is that the business logic is executed by an EJB in a fully transactional manner. Even though the logic in this case is a single read-only operation to the database, but you get the idea :)

Alternatively, you can use the delegate pattern in the managed bean as described below. Lets call this #95.2.
  1. Right-click on the project, select "New", "Session Bean ..." and create a stateless session bean by selecting the options as shown below:



    This creates a stateless session with the name "StateBeanBean" (bug #170392 for redundant "Bean" in the name).
  2. Simplify your managed bean by refactoring all the business logic to the EJB as shown below:

    @Stateless
    public class StateBeanBean {
        @PersistenceUnit
        EntityManagerFactory emf;
        
        public List<States> getStates() {
            return emf.createEntityManager().createNamedQuery("States.findAll").getResultList();
        }
    }

    and

    @ManagedBean
    public class StateList {
        @EJB StateBeanBean bean;

        public List<States> getStates() {
            return bean.getStates();
        }
    }

    In fact the EJB code can be further simplified to:

    @Stateless
    public class StateBeanBean {
        @PersistenceContext
        EntityManager em;
       
        public List<States> getStates() {
            return em.createNamedQuery("States.findAll").getResultList();
        }
    }

    The changes are highlighted in bold.
If the application is already running then Deploy-on-Save would have automatically deployed the entire application. Otherwise right-click on the project and select Run (default shortcut "F6"). Again, the results can be seen at "http://localhost:8080/HelloEclipseLink/forwardToJSF.jsp" or "http://localhost:8080/HelloEclipseLink/faces/template-client.xhtml" and are displayed as shown in the screenshot above.

The updated directory structure looks like:



The important point to note is that our EJB is bundled in the WAR file and no additional deployment descriptors were added or existing ones modified to achieve that. Now, that's really clean :)

The next blog in this series will show how managed beans can be replaced with WebBeans, err JCDI.

Also refer to other Java EE 6 blog entries.

Please leave suggestions on other TOTD that you'd like to see. A complete archive of all the tips is available here.

Technorati: totd glassfish v3 mysql javaee6 javaserverfaces jpa2 ejb netbeans

del.icio.us | furl | simpy | slashdot | technorati | digg |
|

http://blogs.sun.com/arungupta/date/20090814 Friday August 14, 2009

TOTD #94: A simple Java Server Faces 2.0 + JPA 2.0 application - Getting Started with Java EE 6 using NetBeans 6.8 M1 & GlassFish v3


TOTD #93 showed how to get started with Java EE 6 using NetBeans 6.8 M1 and GlassFish v3 by building a simple Servlet 3.0 + JPA 2.0 web application. JPA 2.0 + Eclipselink was used for the database connectivity and Servlet 3.0 was used for displaying the results to the user. The sample demonstrated how the two technologies can be mixed to create a simple web application. But Servlets are meant for server-side processing rather than displaying the results to end user. JavaServer Faces 2 (another new specification in Java EE 6) is designed to fulfill that purpose.

This Tip Of The Day (TOTD) shows how to enhance the application created in TOTD #93 and use JSF 2 for displaying the results.

  1. Right-click on the project, select "Properties", select "Frameworks", click on "Add ..." as shown below:



    Select "JavaServer Faces" and click on "OK". The following configuration screen is shown:



    Click on "OK" to complete the dialog. This generates a whole bunch of files (7 to be accurate) in your project. Most of these files are leftover from previous version of NetBeans and will be cleaned up. For example, "faces-config.xml" is now optional and "forwardToJSF.jsp" is redundant.
  2. Anyway, lets add a POJO class that will be our managed bean. Right-click on "server" package and select "New", "Java Class ...", give the name as "StateList". Change the class such that it looks like:

    package server;

    import java.util.List;
    import javax.faces.bean.ManagedBean;
    import javax.persistence.EntityManagerFactory;
    import javax.persistence.PersistenceUnit;
    import states.States;

    /**
     * @author arungupta
     */
    @ManagedBean
    public class StateList {
        @PersistenceUnit
        EntityManagerFactory emf;

        public List<States> getStates() {
            return emf.createEntityManager().createNamedQuery("States.findAll").getResultList();
        }
    }

    Here are the main characterisitcs of this class:
    1. This is a POJO class with @ManagedBean annotation. This annotation makes this class a managed bean that can be used in the JSF pages. As no other annotations or parameters are specified, this is a request-scoped managed bean with the name "stateList" and lazily initialized. More details about this annotation are available in the javadocs.
    2. The persistence unit created in TOTD #93 is injected using @PersistenceUnit annotation.
    3. The POJO has one getter method that queries the database and return the list of all the states.
  3. In the generated file "template-client.xhtml", change the "head" template to:

    Show States

    and "body" template to:

                    <h:dataTable var="state" value="#{stateList.states}" border="1">
                        <h:column><h:outputText value="#{state.abbrev}"/></h:column>
                        <h:column><h:outputText value="#{state.name}"/></h:column>
                    </h:dataTable>

  4. This uses the standard JSF "dataTable", "column", and "outputText" tags and uses the value expression to fetch the values from the managed bean.

If the application is already running from TOTD #93, then Deploy-on-Save would have automatically deployed the entire application. Otherwise right-click on the project and select Run (default shortcut "F6"). The results can be seen at "http://localhost:8080/HelloEclipseLink/forwardToJSF.jsp" or "http://localhost:8080/HelloEclipseLink/faces/template-client.xhtml" and looks like:



The updated directory structure looks like:



There were multiple files added by the JSF framework support in NetBeans. But as I said earlier, they will be cleaned up before the final release.

Also refer to other Java EE 6 blog entries.

Please leave suggestions on other TOTD that you'd like to see. A complete archive of all the tips is available here.

Technorati: totd glassfish v3 mysql javaee6 javaserverfaces jpa2 netbeans

del.icio.us | furl | simpy | slashdot | technorati | digg |
|

http://blogs.sun.com/arungupta/date/20090403 Friday April 03, 2009

TOTD # 77: Running Seam examples with GlassFish

Seam is a full-stack solution to assemble complex web applications using simple annotated classes, a rich set of UI components, and very little XML. It integrates Ajax and Business Process Modeling with several Java EE technologies such as Java Server Faces (JSF), Java Persistence API (JPA), and Enterprise Java Beans (EJB 3.0).

GlassFish is a Java EE compliant application server so it's natural to pick GlassFish as your deployment platform for Seam applications :)

This blog is going to show how Seam samples can be easily run on GlassFish.
  1. Download Seam 2.1.1 GA from here and unzip.
  2. Build "examples/jpa" sample as:

    ~/tools/jboss-seam-2.1.1.GA/examples/jpa >ant glassfish
    Buildfile: build.xml

    glassfish:

    initcopy:

    initpoms:
         [echo] Setting up dependencies
        [mkdir] Created dir: /Users/arungupta/tools/jboss-seam-2.1.1.GA/classes/poms
         [copy] Copying 1 file to /Users/arungupta/tools/jboss-seam-2.1.1.GA/classes/poms
    [artifact:install] [INFO] Installing /Users/arungupta/tools/jboss-seam-2.1.1.GA/classes/poms/root.pom to . . .

    . . .

    init.war:

    war:
         [copy] Copying 27 files to /Users/arungupta/tools/jboss-seam-2.1.1.GA/examples/jpa/exploded-archives-glassfish/jboss-seam-jpa.war
         [copy] Copying 7 files to /Users/arungupta/tools/jboss-seam-2.1.1.GA/examples/jpa/exploded-archives-glassfish/jboss-seam-jpa.war/WEB-INF/lib

    noejb.war:
         [copy] Copying 18 files to /Users/arungupta/tools/jboss-seam-2.1.1.GA/examples/jpa/exploded-archives-glassfish/jboss-seam-jpa.war/WEB-INF/lib
         [copy] Copying 2 files to /Users/arungupta/tools/jboss-seam-2.1.1.GA/examples/jpa/exploded-archives-glassfish/jboss-seam-jpa.war
         [copy] Copying 4 files to /Users/arungupta/tools/jboss-seam-2.1.1.GA/examples/jpa/exploded-archives-glassfish/jboss-seam-jpa.war

    distributable.war:

    noejb.archive:
          [jar] Building jar: /Users/arungupta/tools/jboss-seam-2.1.1.GA/examples/jpa/dist-glassfish/jboss-seam-jpa.war

    BUILD SUCCESSFUL
    Total time: 5 seconds
  3. Deploy the sample as:

    ~/tools/jboss-seam-2.1.1.GA/examples/jpa >~/tools/glassfish/v2.1/glassfish/bin/asadmin deploy dist-glassfish/jboss-seam-jpa.war
    Command deploy executed successfully.

    The app is now accessible at "http://localhost:8080/jboss-seam-jpa" and here are some of the captured screenshots:







    Simple and easy!
  4. Build "examples/hibernate" as:

    ~/tools/jboss-seam-2.1.1.GA/examples/hibernate >ant glassfish
    Buildfile: build.xml

    glassfish:

    initcopy:

    initpoms:
         [echo] Setting up dependencies
         [copy] Copying 1 file to /Users/arungupta/tools/jboss-seam-2.1.1.GA/classes/poms
    [artifact:install] [INFO] Installing /Users/arungupta/tools/jboss-seam-2.1.1.GA/classes/poms/root.pom to /Users/arungupta/.m2/repository/org/jboss/seam/root/2.1.1.GA/root-2.1.1.GA.pom

     . . .

    distributable.war:

    noejb.archive:
          [jar] Building jar: /Users/arungupta/tools/jboss-seam-2.1.1.GA/examples/hibernate/dist-glassfish/jboss-seam-hibernate.war

    BUILD SUCCESSFUL
    Total time: 6 seconds

  5. Deploy the sample as:

    ~/tools/jboss-seam-2.1.1.GA/examples/hibernate >~/tools/glassfish/v2.1/glassfish/bin/asadmin deploy dist-glassfish/jboss-seam-hibernate.war
    Command deploy executed successfully.

    The app is now accessible at "http://localhost:8080/jboss-seam-hibernate" and has exactly similar snapshots as shown in "jboss-seam-jpa" sample. Simple and easy, yet again!
  6. Build "examples/jee5/booking" and deploy as:

    ~/tools/jboss-seam-2.1.1.GA/examples/jee5/booking >ant
    Buildfile: build.xml

    initcopy:

    initpoms:
         [echo] Setting up dependencies
         [copy] Copying 1 file to /Users/arungupta/tools/jboss-seam-2.1.1.GA/classes/poms
    [artifact:install] [INFO] Installing /Users/arungupta/tools/jboss-seam-2.1.1.GA/classes/poms/root.pom to /Users/arungupta/.m2/repository/org/jboss/seam/root/2.1.1.GA/root-2.1.1.GA.pom
         [copy] Copying 1 file to /Users/arungupta/tools/jboss-seam-2.1.1.GA/classes/poms

    . . .

    archive:
          [jar] Building jar: /Users/arungupta/tools/jboss-seam-2.1.1.GA/examples/jee5/booking/dist/jboss-seam-jee5-booking.jar
          [jar] Building jar: /Users/arungupta/tools/jboss-seam-2.1.1.GA/examples/jee5/booking/dist/jboss-seam-jee5-booking.war
          [jar] Building jar: /Users/arungupta/tools/jboss-seam-2.1.1.GA/examples/jee5/booking/dist/jboss-seam-jee5-booking.ear

    BUILD SUCCESSFUL
    Total time: 5 seconds
    ~/tools/jboss-seam-2.1.1.GA/examples/jee5/booking >~/tools/glassfish/v2.1/glassfish/bin/asadmin deploy dist/jboss-seam-jee5-booking.ear
    Command deploy executed successfully.

    The application is now accessible at "http://localhost:8080/seam-jee5-booking". Wow, that's simple and easy as well!
So we have deployed multiple Seam samples on GlassFish v2.1 - simple and easy!

Here are some more useful pointers realted to Seam and GlassFish:
  • Chapter 39 of the Seam Community Documentation even describes how to deploy an application created using seam-gen on GlassFish.
  • Dan Allen, the author of Manning's Seam in Action, presented a webinar at TheAquarium Online.
  • Several other Seam entries @ TA.
  • Deploying a seam-gen project to GlassFish (blog entry) - Here is a quote from the blog:

    GlassFish has a very sexy administrative console, but it also has a very sexy commandline tool known as asadmin. The asadmin tool gives you virtually unbounded control over the application server, including core tasks such as starting and stopping the application server, deploying and undeploying applications, and setting up database connection pools, amidst a plethora of other controls. You'll see that my modified seam-gen tool takes advantage of a handful of these commands.

    And another one ...

    GlassFish gives you efficiency through automation, which is undoubtedly the most effective way to become efficient. ... GlassFish volunteers itself to participate in a script and is the reason why I choose it as my preferred application server.
  • GlassFish support added to seam-gen: It is certainly exciting to know that there are targets like "gf-deploy-datasource", "gf-deploy-hibernate", and "gf-prepare" available to Seam developers out-of-the-box.
  • Sample Application using JSF, Seam, and Java Persistence APIs on GlassFish - detailed step-by-step blog explaining how to run Seam applications on GlassFish
The other samples in the bundle (that I tried) rely upon non-Java EE jars in the App Server's classpath. A slight build file tweaking can bundle those jars in the application itself and will allow to run them as well.

Are you deploying your Seam applications on GlassFish ?

Happy Seaming on GlassFish!

Please leave suggestions on other TOTD (Tip Of The Day) that you'd like to see. A complete archive of all the tips is available here.

Technorati: totd seam glassfish javaee javaserverfaces ejb jpa

del.icio.us | furl | simpy | slashdot | technorati | digg |
|

http://blogs.sun.com/arungupta/date/20081211 Thursday December 11, 2008

TOTD # 59: Alternative JSF implementations on GlassFish - MyFaces and Tomahawk


GlassFish comes bundled with an industry grade implementation of Java Server Faces codenamed Mojarra. It is the most complete, up-to-date and well-tested JSF implementation and used pretty extensively. GlassFish v2 and v3 Prelude ships with JSF 1.2.x-compliant implementation that is defined as part of Java EE 5. GlassFish v3 trunk contains JSF 2.0-compliant implementation that is getting defined as part of Java EE 6. The latest version of Mojarra can be installed from the Update Center.

But GlassFish does not restrict you to Mojarra and instead it embraces other JSF implementations easily. This blog uses MyFaces, an alternate JavaServer Faces implementation from Apache, to demonstrate that. If you are interested in a brief summary of what it takes to use these alternate implementations on GlassFish then scroll to the end of this entry.

MyFaces also provides several component libraries such as Tomahawk, Trinidad, and Tobago for building web applications. This blog shows how MyFaces Tomahawk samples can be deployed on GlassFish v2 and v3. The basic integration hooks between GlassFish and other JSF implementations remain the same and are independent of the component library.

Lets get started and understand all the glory!

Download MyFaces Tomahawk samples from here. The download consists of 4 WAR files and they are unzipeed in the current directory. So create a new directory and then unzip the bundle if you want to organize it slightly better. The getting Started instructions require you to copy "simple.war" where as the actual WAR filename is "myfaces-example-simple-1.1.8.war". Anyway, we are going to deploy this sample on GlassFish v2, v3 Prelude, and v3 trunk and what needs to be done to use the MyFaces implementation bundled within the WAR.
  1. Deploy using Mojarra on GlassFish v2
    1. Deploying "myfaces-example-simple-1.1.8.war" on GlassFish v2 using "asadmin deploy myfaces-example-simple-1.1.8.war" and it shows the following message:

      [#|2008-12-05T11:00:43.710-0800|INFO|sun-appserver9.1|javax.enterprise.system.tools.deployment|_ThreadID=22;_ThreadName=Thread-43;|
      deployed with moduleid = myfaces-example-simple-1.1.8|#]

      [#|2008-12-05T11:00:44.296-0800|INFO|sun-appserver9.1|javax.enterprise.resource.webcontainer.jsf.config|_ThreadID=21;
      _ThreadName=httpWorkerThread-4848-1;/myfaces-example-simple-1.1.8;|Initializing Sun's JavaServer Faces implementation (1.2_04-b20-p03) for context '/myfaces-example-simple-1.1.8'|#]

      The bold text indicates that Mojarra 1.2 bundled with GlassFish v2 is used as the JSF runtime, the exact version is shown in the bold text. The deployed web application is accessible at "http://localhost:8080/myfaces-example-simple-1.1.8/home.jsf" and looks like:



      The following error message is shown as you click through the samples:

      [#|2008-12-03T16:27:43.935-0800|INFO|sun-appserver9.1|javax.enterprise.system.stream.out|_ThreadID=24;_ThreadName=httpSSLWorkerThread-8080-1;|
      2008-12-03 16:27:43,935 [httpSSLWorkerThread-8080-1] INFO  org.apache.myfaces.shared_tomahawk.config.MyfacesConfig - Starting up Tomahawk on the MyFaces-JSF-Implementation
      |#]

      [#|2008-12-03T16:27:43.935-0800|INFO|sun-appserver9.1|javax.enterprise.system.stream.out|_ThreadID=24;_ThreadName=httpSSLWorkerThread-8080-1;|
      2008-12-03 16:27:43,935 [httpSSLWorkerThread-8080-1] ERROR org.apache.myfaces.shared_tomahawk.config.MyfacesConfig - Both MyFaces and the RI are on your classpath. Please make sure to use only one of the two JSF-implementations.

      This error message is generated by MyFaces and may be ignored. I think the message should be a WARNING instead of an ERROR.
  2. Deploy using MyFaces on GlassFish v2
    1. Create a directory "simple" and unjar "myfaces-example-simple-1.1.8.war" in there.
    2. Add "WEB-INF/sun-web.xml" and specify the contents as:

      <?xml version="1.0" encoding="UTF-8"?>
      <!DOCTYPE sun-web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Application Server 8.1 Servlet 2.4//EN" "http://www.sun.com/software/appserver/dtds/sun-web-app_2_4-1.dtd">
      <sun-web-app>
      <class-loader delegate="false"/>
      <property name="useMyFaces" value="true"/>
      </sun-web-app>

      The key point to notice is the property name "useMyFaces". The name is slightly mis-leading because the switch essentially tells GlassFish runtime to use the bundled Java Server Faces runtime and is not restricted to MyFaces only. This is fixed in GlassFish v3 and is discussed later.
    3. Create a WAR file in "simple" directory as "jar cvf myfaces-simple-v2.war *".
    4. Deploy the generated WAR on GlassFish v2 as "asadmin deploy myfaces-simple-v2.war". It shows the following message:

      . . .

      [#|2008-12-05T11:11:25.615-0800|INFO|sun-appserver9.1|javax.enterprise.system.tools.deployment|_ThreadID=24;_ThreadName=Thread-257;|
      deployed with moduleid = myfaces-simple-v2|#]

      [#|2008-12-05T11:11:26.266-0800|INFO|sun-appserver9.1|javax.enterprise.system.stream.out|_ThreadID=21;_ThreadName=httpWorkerThread-4848-1;|
      2008-12-05 11:11:26,266 [httpWorkerThread-4848-1] INFO  org.apache.myfaces.config.FacesConfigurator - Reading standard config org/apache/myfaces/resource/standard-faces-config.xml
      |#]

      [#|2008-12-05T11:11:26.290-0800|INFO|sun-appserver9.1|javax.enterprise.system.stream.out|_ThreadID=21;_ThreadName=httpWorkerThread-4848-1;|
      2008-12-05 11:11:26,290 [httpWorkerThread-4848-1] INFO  org.apache.myfaces.config.FacesConfigurator - Reading config jar:file:/Users/arungupta/tools/glassfish/v2/ur2/glassfish/domains/domain1/applications/j2ee-modules/myfaces-simple-v2/WEB-INF/lib/tomahawk-1.1.8.jar!/
      META-INF/faces-config.xml
      |#]

      [#|2008-12-05T11:11:26.309-0800|INFO|sun-appserver9.1|javax.enterprise.system.stream.out|_ThreadID=21;_ThreadName=httpWorkerThread-4848-1;|2008-12-05 11:11:26,308 [httpWorkerThread-4848-1] INFO  org.apache.myfaces.config.FacesConfigurator - Reading config /WEB-INF/examples-config.xml
      |#]

      [#|2008-12-05T11:11:26.337-0800|INFO|sun-appserver9.1|javax.enterprise.system.stream.out|_ThreadID=21;_ThreadName=httpWorkerThread-4848-1;|2008-12-05 11:11:26,337 [httpWorkerThread-4848-1] INFO  org.apache.myfaces.config.FacesConfigurator - Reading config /WEB-INF/testSuite-config.xml
      |#]

      [#|2008-12-05T11:11:26.349-0800|INFO|sun-appserver9.1|javax.enterprise.system.stream.out|_ThreadID=21;_ThreadName=httpWorkerThread-4848-1;|2008-12-05 11:11:26,349 [httpWorkerThread-4848-1] INFO  org.apache.myfaces.config.FacesConfigurator - Starting up MyFaces-package : myfaces-api in version : 1.1.6 from path : file:/Users/arungupta/tools/glassfish/v2/ur2/glassfish/domains/domain1/applications/j2ee-modules/myfaces-simple-v2/WEB-INF/lib/myfaces-api-1.1.6.jar
      |#]

      [#|2008-12-05T11:11:26.350-0800|INFO|sun-appserver9.1|javax.enterprise.system.stream.out|_ThreadID=21;_ThreadName=httpWorkerThread-4848-1;|2008-12-05 11:11:26,350 [httpWorkerThread-4848-1] INFO  org.apache.myfaces.config.FacesConfigurator - Starting up MyFaces-package : myfaces-impl in version : 1.1.6 from path : file:/Users/arungupta/tools/glassfish/v2/ur2/glassfish/domains/domain1/applications/j2ee-modules/myfaces-simple-v2/WEB-INF/lib/myfaces-impl-1.1.6.jar
      |#]

      [#|2008-12-05T11:11:26.350-0800|INFO|sun-appserver9.1|javax.enterprise.system.stream.out|_ThreadID=21;_ThreadName=httpWorkerThread-4848-1;|2008-12-05 11:11:26,350 [httpWorkerThread-4848-1] INFO  org.apache.myfaces.config.FacesConfigurator - MyFaces-package : tomahawk-sandbox not found.
      |#]

      [#|2008-12-05T11:11:26.350-0800|INFO|sun-appserver9.1|javax.enterprise.system.stream.out|_ThreadID=21;_ThreadName=httpWorkerThread-4848-1;|2008-12-05 11:11:26,350 [httpWorkerThread-4848-1] INFO  org.apache.myfaces.config.FacesConfigurator - Starting up MyFaces-package : tomahawk in version : 1.1.8 from path : file:/Users/arungupta/tools/glassfish/v2/ur2/glassfish/domains/domain1/applications/j2ee-modules/myfaces-simple-v2/WEB-INF/lib/tomahawk-1.1.8.jar
      |#]

      . . .

      [#|2008-12-05T11:11:27.069-0800|INFO|sun-appserver9.1|javax.enterprise.system.stream.out|_ThreadID=21;_ThreadName=httpWorkerThread-4848-1;|2008-12-05 11:11:27,069 [httpWorkerThread-4848-1] INFO  org.apache.myfaces.shared_impl.config.MyfacesConfig - Starting up Tomahawk on the RI-JSF-Implementation.
      |#]

      [#|2008-12-05T11:11:27.069-0800|INFO|sun-appserver9.1|javax.enterprise.system.stream.out|_ThreadID=21;_ThreadName=httpWorkerThread-4848-1;|2008-12-05 11:11:27,069 [httpWorkerThread-4848-1] INFO  org.apache.myfaces.shared_impl.config.MyfacesConfig - Starting up Tomahawk on the MyFaces-JSF-Implementation
      |#]

      [#|2008-12-05T11:11:27.070-0800|INFO|sun-appserver9.1|javax.enterprise.system.stream.out|_ThreadID=21;_ThreadName=httpWorkerThread-4848-1;|2008-12-05 11:11:27,070 [httpWorkerThread-4848-1] ERROR org.apache.myfaces.shared_impl.config.MyfacesConfig - Both MyFaces and the RI are on your classpath. Please make sure to use only one of the two JSF-implementations.
      |#]

      [#|2008-12-05T11:11:27.070-0800|INFO|sun-appserver9.1|javax.enterprise.system.stream.out|_ThreadID=21;_ThreadName=httpWorkerThread-4848-1;|2008-12-05 11:11:27,070 [httpWorkerThread-4848-1] INFO  org.apache.myfaces.webapp.StartupServletContextListener - ServletContext '/Users/arungupta/tools/glassfish/v2/ur2/glassfish/domains/domain1/applications/j2ee-modules/myfaces-simple-v2/' initialized.
      |#]

      The first thing to note is that the message "Initializing Sun's JavaServer Faces implementation (1.2_04-b20-p03)" is not shown. That indicates Mojarra is not used as the JSF runtime. Then you can see how MyFaces 1.1.6 API and Implementation are loaded, Tomahaw 1.1.8 is loaded and finally started using MyFaces JSF implementation.

      The main page from this deployed application at "http://localhost:8080/myfaces-simple-v2" is very similar as shown below:

  3. Deploy using Mojarra on GlassFish v3 Prelude - This is very similar experience as with GlassFish v2.
    1. Deploying "myfaces-example-simple-1.1.8.war" on GlassFish v3 shows the following message:

      Dec 5, 2008 11:27:17 AM com.sun.faces.config.ConfigureListener contextInitialized
      INFO: Initializing Mojarra (1.2_10-b01-FCS) for context '/myfaces-example-simple-1.1.8'
      Dec 5, 2008 11:27:18 AM com.sun.enterprise.web.WebApplication start
      INFO: Loading application myfaces-example-simple-1.1.8 at /myfaces-example-simple-1.1.8
      Dec 5, 2008 11:27:18 AM org.glassfish.deployment.admin.DeployCommand execute
      INFO: Deployment of myfaces-example-simple-1.1.8 done is 3470 ms

      The bold text clearly indicates that Mojarra 1.2 bundled, exact version shown in the bold text, with GlassFish v3 is used as the JSF runtime. The deployed web application is accessible at "http://localhost:8080/myfaces-example-simple-1.1.8/home.jsf". Viewing the sample in browser shows:

      Dec 5, 2008 11:54:54 AM  
      INFO: 2008-12-05 11:54:54,083 [httpWorkerThread-8080-0] INFO  org.apache.myfaces.shared_tomahawk.config.MyfacesConfig - Starting up Tomahawk on the RI-JSF-Implementation.

      Dec 5, 2008 11:54:54 AM  
      INFO: 2008-12-05 11:54:54,083 [httpWorkerThread-8080-0] INFO  org.apache.myfaces.shared_tomahawk.config.MyfacesConfig - Starting up Tomahawk on the MyFaces-JSF-Implementation

      Dec 5, 2008 11:54:54 AM  
      INFO: 2008-12-05 11:54:54,083 [httpWorkerThread-8080-0] ERROR org.apache.myfaces.shared_tomahawk.config.MyfacesConfig - Both MyFaces and the RI are on your classpath. Please make sure to use only one of the two JSF-implementations.

      and may be ignored. None of the messages that indicate classloading, as shown for GlassFish v2 above, are displayed. I suspect these are standard messages displayed by MyFaces without taking into consideration that an alternate JSF runtime can be used to run these samples.
  4. Deploy using MyFaces on GlassFish v3 Prelude - There is no way to override JSF implementation with GlassFish v3 Prelude. So even though deploying "myfaces-simple-v2.war" will work fine but viewing the web page at "http://localhost:8080/myfaces-simple-v2/" will show the following exception:



    Basically, a web application cannot use MyFaces implementation on GlassFish v3 Prelude. However Mojarra provides a fully-compliant and feature-rich JSF implementation and is already baked in GlassFish v3 Prelude.
  5. Deploy using Mojarra on GlassFish v3 Trunk
    1. Pick your GlassFish v3 Build Flavor, this blog uses the trunk.
    2. Deploy the original sample as "asadmin deploy myfaces-example-simple-1.1.8.war" and the following log messages are shown:

      Dec 5, 2008 12:35:17 PM com.sun.faces.config.ConfigureListener contextInitialized
      INFO: Initializing Mojarra 2.0.0 (SNAPSHOT b05) for context '/myfaces-example-simple-1.1.8'
      Dec 5, 2008 12:35:18 PM org.apache.catalina.core.ApplicationContext log
      SEVERE: WebModule[/myfaces-example-simple-1.1.8]PWC1275: Exception sending context initialized event to listener instance of class com.sun.faces.config.ConfigureListener
      java.lang.NoClassDefFoundError: com/sun/facelets/tag/jsf/ComponentHandler
              at java.lang.ClassLoader.defineClass1(Native Method)
              at java.lang.ClassLoader.defineClass(ClassLoader.java:675)
              at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:124)
              at org.glassfish.web.loader.WebappClassLoader.findClass(WebappClassLoader.java:974)

      This happens because the application has dependencies on internal classes of Facelets 1.1.x. That makes the application non-compatible with Mojarra 2.x which comes bundled with Facelets 2.0.
    3. Lets instruct the application to disable the Facelets 2.0 baked in Mojarra by adding the following application wide context parameter in "web.xml":

      <context-param>
             <param-name>javax.faces.DISABLE_FACELET_JSF_VIEWHANDLER</param-name>
             <param-value>true</param-value>
       </context-param>

      Now the Facelets 1.1.x classes bundled with the application are used. With this change, the application gets deployed correctly and shows the following log message:

      Dec 5, 2008 2:50:21 PM com.sun.faces.config.ConfigureListener contextInitialized
      INFO: Initializing Mojarra 2.0.0 (SNAPSHOT b05) for context '/myfaces-simple-v3'
      Dec 5, 2008 2:50:21 PM com.sun.enterprise.web.WebApplication start
      INFO: Loading application myfaces-simple-v3 at /myfaces-simple-v3
      Dec 5, 2008 2:50:21 PM org.glassfish.deployment.admin.DeployCommand execute
      INFO: Deployment of myfaces-simple-v3 done is 1513 ms

      The important thing to note here is that Mojarra 2.0.0 implementation (as indicated by the bold text) is used as JSF runtime. This is the newest and the greatest runtime that implements JSF 2.0 specification and baked in GlassFish v3 trunk. The main page from this deployed application at "http://localhost:8080/myfaces-simple-v3/" looks like:

  6. Deploy using MyFaces on GlassFish v3 Trunk
    1. Download the latest GlassFish v3 Nightly.
    2. Lets deploy the WAR file previously created as "asadmin deploy myfaces-simple-v2.war". The main page of the application is accessible at "http://localhost:8080/myfaces-simple-v2".
    3. The "useMyFaces" property, as specified in "sun-web.xml", is expected to work for any bundled JSF implementation. The recommended way to deploy such a web application in GlassFish v3 is to use the property "useBundledJsf". The updated "sun-web.xml" is shown below:

      <?xml version="1.0" encoding="UTF-8"?>
      <!DOCTYPE sun-web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Application Server 8.1 Servlet 2.4//EN" "http://www.sun.com/software/appserver/dtds/sun-web-app_2_4-1.dtd">
      <sun-web-app>
      <class-loader delegate="false"/>
      <property name="useBundledJsf" value="true"/>
      </sun-web-app>
    4. Create a WAR file in "simple" directory as "jar cvf myfaces-simple-v3-usebundled.war *".
    5. Deploy the generated WAR on GlassFish v3 as "asadmin deploy myfaces-simple-v3-usebundled.war". It shows the following message:

      . . .

      Dec 5, 2008 3:19:54 PM  
      INFO: 2008-12-05 15:19:54,786 [httpWorkerThread-4848-1] INFO  org.apache.myfaces.config.FacesConfigurator - Reading config jar:file:/Users/arungupta/tools/glassfish/v3/snapshot/glassfish/domains/domain1/applications/myfaces-simple-v3-usebundled/WEB-INF/lib/tomahawk-1.1.8.jar!/
      META-INF/faces-config.xml

      Dec 5, 2008 3:19:54 PM  
      INFO: 2008-12-05 15:19:54,806 [httpWorkerThread-4848-1] INFO  org.apache.myfaces.config.FacesConfigurator - Reading config /WEB-INF/examples-config.xml

      Dec 5, 2008 3:19:54 PM  
      INFO: 2008-12-05 15:19:54,828 [httpWorkerThread-4848-1] INFO  org.apache.myfaces.config.FacesConfigurator - Reading config /WEB-INF/testSuite-config.xml

      Dec 5, 2008 3:19:54 PM  
      INFO: 2008-12-05 15:19:54,841 [httpWorkerThread-4848-1] INFO  org.apache.myfaces.config.FacesConfigurator - Starting up MyFaces-package : myfaces-api in version : 1.1.6 from path : file:/Users/arungupta/tools/glassfish/v3/snapshot/glassfish/domains/domain1/applications/myfaces-simple-v3-usebundled/WEB-INF/lib/myfaces-api-1.1.6.jar

      Dec 5, 2008 3:19:54 PM  
      INFO: 2008-12-05 15:19:54,841 [httpWorkerThread-4848-1] INFO  org.apache.myfaces.config.FacesConfigurator - Starting up MyFaces-package : myfaces-impl in version : 1.1.6 from path : file:/Users/arungupta/tools/glassfish/v3/snapshot/glassfish/domains/domain1/applications/myfaces-simple-v3-usebundled/WEB-INF/lib/myfaces-impl-1.1.6.jar

      Dec 5, 2008 3:19:54 PM  
      INFO: 2008-12-05 15:19:54,841 [httpWorkerThread-4848-1] INFO  org.apache.myfaces.config.FacesConfigurator - MyFaces-package : tomahawk-sandbox not found.

      Dec 5, 2008 3:19:54 PM  
      INFO: 2008-12-05 15:19:54,841 [httpWorkerThread-4848-1] INFO  org.apache.myfaces.config.FacesConfigurator - Starting up MyFaces-package : tomahawk in version : 1.1.8 from path : file:/Users/arungupta/tools/glassfish/v3/snapshot/glassfish/domains/domain1/applications/myfaces-simple-v3-usebundled/WEB-INF/lib/tomahawk-1.1.8.jar

      . . .

      Dec 5, 2008 3:19:55 PM  
      INFO: 2008-12-05 15:19:55,763 [httpWorkerThread-4848-1] INFO  org.apache.myfaces.shared_impl.config.MyfacesConfig - Starting up Tomahawk on the RI-JSF-Implementation.

      Dec 5, 2008 3:19:55 PM  
      INFO: 2008-12-05 15:19:55,764 [httpWorkerThread-4848-1] INFO  org.apache.myfaces.shared_impl.config.MyfacesConfig - Starting up Tomahawk on the MyFaces-JSF-Implementation

      Dec 5, 2008 3:19:55 PM  
      INFO: 2008-12-05 15:19:55,764 [httpWorkerThread-4848-1] ERROR org.apache.myfaces.shared_impl.config.MyfacesConfig - Both MyFaces and the RI are on your classpath. Please make sure to use only one of the two JSF-implementations.

      Dec 5, 2008 3:19:55 PM  
      INFO: 2008-12-05 15:19:55,764 [httpWorkerThread-4848-1] INFO  org.apache.myfaces.webapp.StartupServletContextListener - ServletContext '/Users/arungupta/tools/glassfish/v3/snapshot/glassfish/domains/domain1/applications/myfaces-simple-v3-usebundled/' initialized.

      Dec 5, 2008 3:19:55 PM com.sun.enterprise.web.WebApplication start
      INFO: Loading application myfaces-simple-v3-usebundled at /myfaces-simple-v3-usebundled
      Dec 5, 2008 3:19:55 PM org.glassfish.deployment.admin.DeployCommand execute
      INFO: Deployment of myfaces-simple-v3-usebundled done is 1994 ms

      The first thing to note is that the message "Initializing Sun's JavaServer Faces implementation (1.2_04-b20-p03)" is not shown. That indicates Mojarra is not used as the JSF runtime. Then you can see how MyFaces 1.1.6 API and Implementation are loaded, Tomahawk 1.1.8 is loaded and finally started using MyFaces JSF implementation.

      The main page from this deployed application at "http://localhost:8080/myfaces-simple-v3-usebundled" is very similar as shown below:



Here is a brief summary of how MyFaces/Tomahawk sample is deployed using Mojarra and MyFaces on GlassFish:

JSF Implementations
Mojarra MyFaces
GlassFish v2 Default "useMyFaces" property in "sun-web.xml"
GlassFish v3 Prelude Default Not supported
GlassFish v3 Trunk Disable Facelets 2.0 in "web.xml" "useMyFaces" OR "useBundledJsf" property in "sun-web.xml"
Disable Facelets 2.0 in "web.xml" (only for Facelets 1.1.x dependencies)

The steps described above for MyFaces can be used with alternate JSF implementations as well. Which JSF implementation do you use ?

Just like Tomahawk components, Trinidad and Tobago libraries should work with Mojarra as well. Have you tried them ?

Technorati: glassfish javaserverfaces mojarra apache myfaces tomahawk

del.icio.us | furl | simpy | slashdot | technorati | digg |
|

http://blogs.sun.com/arungupta/date/20081120 Thursday November 20, 2008

TOTD #54: Java Server Faces with Eclipse IDE


Ed pointed me to this excellent tutorial that explains how JavaServer Faces applications can be easily created using Eclipse IDE. The article clearly shows all the steps to create a Java Server Faces application and demonstrates the following JSF concepts:

  • How to register managed beans to a JSF application ?
  • Different templates for creating JSF pages
  • Validators
  • Resource Bundles
  • Navigation rules in faces-config.xml (very intuitive and easy-to-use)
  • Dependency injection
  • Value and Method Binding
Few code/snapshot mismatches but knowing that it's only version 0.3, it's a damn good job!

Couple of differences from the article:

First, I deployed all the samples on GlassFish v3 Prelude which has Mojarra 1.2 baked in. The screencast #28 explains how to configure GlassFish with Eclipse IDE.

Secondly, instead of using WTP, I used Eclipse 3.4 for Java EE developers which has built-in support for JSF 1.1 and 1.2 applications. So there is no need to download/configure JSP/JSTL libraries. Instead the libraries are specified during project creation as shown below:



And then let the server side provide JSF implementation by selecting radio button as shown below:



That's it, now the Mojarra baked in GlassFish v3 Prelude is used for JSF runtime.

The faces-config editor is really cool, intuitive and easy-to-use. Here is a snapshot:



Here is a snapshot of the project explorer window (package names are different from the original article):



And now finally the outputs from 4 JSF applications:












All of this using Mojarra and GlassFish v3 Prelude :)

Let us know your feedback on Mojarra at GlassFish Webtier forum, file bugs in Issue Tracker, and find the latest information about Mojarra at javaserverfaces.dev.java.net.

Technorati: totd javaserverfaces eclipse glassfish v3 mojarra

del.icio.us | furl | simpy | slashdot | technorati | digg |
|

http://blogs.sun.com/arungupta/date/20081024 Friday October 24, 2008

TOTD #51: Embedding Google Maps in Java Server Faces using GMaps4JSF


GMaps4JSF allows Google Maps to be easily integrated with any JSF application. This blog shows how to use this library with Mojarra - JSF implementation delivered from the GlassFish community.

TOTD #50 explains how to create a simple JSF 2.0 application and deploy on GlassFish v3 prelude using Mojarra 2.0 EDR2. The application allows to create a database of cities/country that you like. It uses integrated Facelets and the newly introduced JavaScript APIs to expose Ajax functionality. This blog shows how to extend that application to display a Google Map and Street View of the entered city using this library.
  1. Configure GMapsJSF library in the NetBeans project (created as described in TOTD #50)
    1. Download gmaps4jsf-core-1.1.jar.
    2. In the existing NetBeans project, right-click on the project, select Properties, Libraries, click on "Add JAR/Folder" and point to the recently download JAR.
    3. Configure Facelets support for this library. This is an important step since Facelets are the default viewing technology in JSF 2.0.
  2. In the NetBeans project, create a new Java class "server.CityCoordinates" that will use Google Geocoding APIs to retrieve latitude and longitude of the entered city. It also create a "details" entry by concatenating city and country name. Use the code listed below:

        private float latitude;
        private float longitude;
        private String details;
        @ManagedProperty(value="#{cities}")
        private Cities cities;

        private final String BASE_GEOCODER_URL = "http://maps.google.com/maps/geo?";
        private final String ENCODING = "UTF-8";
        private final String GOOGLE_MAPS_KEY = "GOOGLE_MAPS_API_KEY";
        private final String OUTPUT_FORMAT = "CSV";

        public String getLatLong() throws IOException {
            details = cities.getCityName() + ", " + cities.getCountryName();

            String GEOCODER_REQUEST =
                    BASE_GEOCODER_URL +
                    "q=" + URLEncoder.encode(details, ENCODING) +
                    "&key=" + GOOGLE_MAPS_KEY +
                    "&output=" + OUTPUT_FORMAT;
            BufferedReader reader = new BufferedReader(
                    new InputStreamReader(
                        new URL(GEOCODER_REQUEST).openStream()));
            String line = null;
            int statusCode = -1;
            while ((line = reader.readLine()) != null) {
                // 200,4,37.320052,-121.877636
                // status code,accuracy,latitude,longitude
                statusCode = Integer.parseInt(line.substring(0, 3));
                if (statusCode == 200) {
                    int secondComma = line.indexOf(",", 5);
                    int lastComma = line.lastIndexOf(",");
                    latitude = Float.valueOf(line.substring(secondComma+1, lastComma));
                    longitude = Float.valueOf(line.substring(lastComma+1));
                    System.out.println("Latitude: " + latitude);
                    System.out.println("Longitude: " + longitude);
                }
            }

            return "map";
        }

        // getters and setters

    "getLatLong()" method retrieves geocoding information using HTTP by passing the city and country name, Google Maps API key and CSV output format. The result is then processed to retrieve status code, latitude and longitude. Add the following annotation to this class:

    @ManagedBean(name="coords", scope="request")

    This ensures that "server.CityCoordinates" is injected as a managed bean in the runtime.
  3. Add a new button in "welcome.xhtml" right after "submit" button as:

    <h:commandButton action="#{coords.getLatLong}" value="map"/>
  4. Add a new page "map.xhtml" as:

    <!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:h="http://java.sun.com/jsf/html"
          xmlns:m="http://code.google.com/p/gmaps4jsf/">
        <head>
            <script src="http://maps.google.com/maps?file=api&amp;v=2&amp;key=ABQIAAAAF9QYjrVEsD9al2QCyg8e-hTwM0brOpm-All5BF6PoaKBxRWWERRHQdtsJnNsqELmKZCKghs54I-0Uw" type="text/javascript"> </script>
        </head>
        <body>
            <m:map
                latitude="#{coords.latitude}"
                longitude="#{coords.longitude}"
                width="500px"
                height="300px"
                zoom="14"
                addStretOverlay="true">
                <m:marker draggable="true">
                    <m:eventListener eventName="dragend" jsFunction="showStreet"/>
                </m:marker>
                <m:htmlInformationWindow htmlText="#{coords.details}"/>
                <m:mapControl name="GLargeMapControl" position="G_ANCHOR_BOTTOM_RIGHT"/>
                <m:mapControl name="GMapTypeControl"/>
            </m:map>
            <br/> <br/>
            <m:streetViewPanorama width="500px" height="200px"
                                  latitude="#{coords.latitude}" longitude="#{coords.longitude}"
                                  jsVariable="pano1" />

            <script type="text/javascript">
                function showStreet(latlng) {
                    pano1.setLocationAndPOV(latlng);
                }

            </script>
            <form jsfc="h:form">
                <input jsfc="h:commandButton" action="back" value="Back"/>
            </form>
        </body>
    </html>

    The code is borrowed and explained in An Introduction to GMaps4JSF. Basically the code displays a Google Map and Street View where the latitude and longitude are bound by "server.CityCoordinates" managed bean. And these attributes are populated using the geocoding information earlier. The Street View corresponds to marker in the Map which is draggable. So if the marker is dropped to a different location in the map then the Street View changes accordingly.
  5. Add new navigation rules to "faces-config.xml" as:

        <navigation-rule>
            <from-view-id>/welcome.xhtml</from-view-id>
            <navigation-case>
                <from-outcome>map</from-outcome>
                <to-view-id>/map.xhtml</to-view-id>
            </navigation-case>
        </navigation-rule>
        <navigation-rule>
            <from-view-id>/map.xhtml</from-view-id>
            <navigation-case>
                <from-outcome>back</from-outcome>
                <to-view-id>/welcome.xhtml</to-view-id>
            </navigation-case>
        </navigation-rule>
That's it, now your application is ready!

Now when a city and country name are entered on "welcome.xhtml" and "map" button is clicked then the corresponding Google Map along with the street view are shown in next page.

If "San Jose" is entered on "http://localhost:8080/Cities/faces/welcome.xhtml" then the following page is shown:



Clicking on "map" button shows the following page:



If the marker is drag/dropped to 280 and 87 junction, then the page looks like:



Some other useful pointers:
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 here using "2.0.0 EDR2" version and ask your questions on webtier@glassfish.dev.java.net.

Please leave suggestions on other TOTD (Tip Of The Day) that you'd like to see. An archive of all the tips is available here.

Technorati: totd javaserverfaces mojarra glassfish v3 netbeans gmaps4jsf googlemaps

del.icio.us | furl | simpy | slashdot | technorati | digg |
|

http://blogs.sun.com/arungupta/date/20081023 Thursday October 23, 2008

TOTD #50: Mojarra 2.0 EDR2 is now available - Try them with GlassFish v3 and NetBeans 6.5


Yaaay, 50th tip!! The previous 49 tips are available here.

Mojarra EDR2 is now available - download binary and/or source bundle!

GlassFish v2 UR2 ships with Mojarra 1.2.0_04 and v3 prelude comes with 1.2.0_10. The Mojarra binaries in both v2 and v3 can be easily replaced by the new ones as described in Release Notes. Additionally, TOTD# 47 explains how to get started with Mojarra 2.0 on GlassFish v2. This blog will guide you through the steps of installing these bits on GlassFish v3 Prelude and show how to use them with NetBeans IDE.

  1. Download latest GlassFish v3 prelude and unzip.
  2. Start Updatetool from "bin" directory. The first run of the tool downloads and installs the tool. Start the tool by typing the command again to see the screen shown below:


  3. Click on "Update", "Accept" the license and the component is then installed in GlassFish directory. Optionally, you can click on "Installed Components" and then verify that bits are installed correctly.
  4. An EDR2 compliant application can now be directly deployed in these GlassFish v3 bits. There is some work required in order to use code completion, auto-fixing of Imports  and similar features in NetBeans 6.5 RC. The steps below describe that.
    1. In "Tools", "Libraries", click on "New Library ...", enter the name "JSF2.0" as shown:

    2. Click on "OK", "Add JAR/Folder..." and pick "glassfishv3-prelude/glassfish/modules/jsf-api.jar", click on "OK".
    3. Right-click on the NetBeans project, select "Properties", "Libraries" and remove "JSTL1.1" and "JSF1.2" libraries.
    4. Click on "Add Library ...", select the newly created "JSF2.0" library, click "Add Library" and then "OK".
  5. In order to run "Cities" application on these GlassFish bits copy MySQL Connector/J jar in "glassfishv3-prelude/glassfish/lib" directory and then deploy the application.

Here are some pointers to get started:

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 here using "2.0.0 EDR2" version and ask your questions on webtier@glassfish.dev.java.net.

Please leave suggestions on other TOTD (Tip Of The Day) that you'd like to see. An archive of all the tips is available here.

Technorati: totd javaserverfaces mojarra glassfish v3 netbeans

del.icio.us | furl | simpy | slashdot | technorati | digg |
|

http://blogs.sun.com/arungupta/date/20081017 Friday October 17, 2008

TOTD #49: Converting a JSF 1.2 application to JSF 2.0 - @ManagedBean


This is a follow up to TOTD #48 which showed how to convert a JSF 1.2 application to use new features of JSF 2.0. In this blog, we'll talk about a new annotation added to the JSF 2.0 specification - @ManagedBean.

@ManagedBean is a new annotation in the JSF 2.0 specification. The javadocs (bundled with the nightly) clearly defines the purpose of this annotation:

The presence of this annotation on a class automatically registers the class with the runtime as a managed bean class. Classes must be scanned for the presence of this annotation at application startup, before any requests have been serviced.

Essentially this is an alternative to <managed-bean> fragment in "faces-config.xml". This annotation injects a class in the runtime as a managed bean and then can be used accordingly.

Using this annotation, the following "faces-config.xml" fragment from our application:

<managed-bean>
        <managed-bean-name>cities</managed-bean-name>
        <managed-bean-class>server.Cities</managed-bean-class>
        <managed-bean-scope>request</managed-bean-scope>
    </managed-bean>
    <managed-bean>
        <managed-bean-name>dbUtil</managed-bean-name>
        <managed-bean-class>server.DatabaseUtil</managed-bean-class>
        <managed-bean-scope>request</managed-bean-scope>
        <managed-property>
            <property-name>cities</property-name>
            <value>#{cities}</value>
        </managed-property>
    </managed-bean>

is simplified to

@Entity
@Table(name = "cities")
@ManagedBean(name="cities", scope="request")
@NamedQueries({@NamedQuery(...)})
public class Cities implements Serializable {

and

@ManagedBean(name="dbUtil", scope="request")
public class DatabaseUtil {

    @ManagedProperty(value="#{cities}")
    private Cities cities;

The specification defines that managed bean declaration in "faces-config.xml" overrides the annotation.

A worthy addition to this annotation is "eager" attribute. Specifying this attribute on the annotation as @ManagedProperty(..., eager="true") allows the class to be instantiated when the application is started. In JSF 1.2 land, developers write their own ServletContextListeners to perform this kind of task. And this can of course be specified in "faces-config.xml" as <managed-bean eager="true">.

Section 11.5.1 of JSF 2.0 EDR2 specification defines several similar annotations that can be used to simplify "faces-config.xml".

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 here using "2.0.0 EDR1" version and ask your questions on webtier@glassfish.dev.java.net.

Please leave suggestions on other TOTD (Tip Of The Day) that you'd like to see. An archive of all the tips is available here.

Technorati: totd javaserverfaces glassfish mojarra netbeans

del.icio.us | furl | simpy | slashdot | technorati | digg |
|

http://blogs.sun.com/arungupta/date/20081015 Wednesday October 15, 2008

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


TOTD #47 showed how to deploy a JSF 1.2 application (using Facelets and Ajax/JSF Extensions) on Mojarra 2.0-enabled GlassFish.  In this blog we'll use new features added in JSF 2.0 to simplify our application:

Let's get started!
  • Re-create the app as defined in 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":

        <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":

            <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:

    <!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>
            <h:head>
                <h1><h:outputText value="What city do you like ?" /></h1>
            </h:head>
           
            <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>
            </h:body>
            <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 here.

    Notice how the Facelet is so simplified.
  • Refactor "result.xhtml" such that the code looks like as shown below:



    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 here using "2.0.0 EDR1" version and ask your questions on webtier@glassfish.dev.java.net.

Please leave suggestions on other TOTD (Tip Of The Day) that you'd like to see. An archive of all the tips is available here.

Technorati: totd javaserverfaces glassfish mojarra netbeans

del.icio.us | furl | simpy | slashdot | technorati | digg |
|

http://blogs.sun.com/arungupta/date/20081014 Tuesday October 14, 2008

TOTD #47: Getting Started with Mojarra 2.0 nightly on GlassFish v2


Java Server Faces 2.0 specification (JSR 314, EDR2) and implementation (soon to be EDR2) are brewing. This blog shows how to get started with Mojarra - Sun's implementation of JSF.

GlassFish v2 comes bundled with Mojarra 1.2_04 which allows you to deploy a JSF 1.2 application. This blog explains how you can update GlassFish v2 to use Mojarra 2.0 nightly. And then it deploys a simple JSF 1.2-based application on this updated GlassFish instance, there by showing that your existing JSF 1.2 apps will continue to work with Mojarra 2.0-enabled GlassFish. This is an important step because it ensures no regression, unless it was a compatibility fix :)

  1. Re-create a simple JSF 1.2 application as described in TOTD #42, TOTD #45 and TOTD #46. This application allows to create a list of cities and store them in a backend database. It uses JSF Extensions to show suggestions, using Ajax, based upon the cities already entered and also uses Facelets as the view technology. Alternatively you can use any pre-existing JSF 1.2 application.
  2. Download Mojarra 2.0 latest nightly.
  3. Follow Release Notes to install the binary, the steps are summarized here for convenience (GlassFish installed in GF_HOME):
    1. Backup "GF_HOME/lib/jsf-impl.jar".
    2. Copy the new "jsf-api" and "jsf-impl" JARs from the unzipped Mojarra distribution to "GF_HOME/lib".
    3. Edit "GF_HOME/domains/<domain-name>/config/domain.xml" and add (or update the existing "classpath-prefix") 'classpath-prefix="${com.sun.aas.installRoot}/lib/jsf-api.jar" in the java-config element.
    4. Restart your server.
  4. Deploy the application on Mojarra 2.0-enabled GlassFish, that's it!
The application is accessible at "http://localhost:8080/Cities/faces/welcome.xhtml". Some of the screen captures are shown below.

If only "S" is entered in the city name, then the following output is shown:



Now with "San" ...



And another one with "De" ...



With JSF 2.0, Ajax capabilities and Facelets are now part of the specification and have already been integrated in Mojarra. A follow up blog entry will show how to use that functionality.

The downloaded Mojarra bundle has some samples (in "samples" folder) to get you started, have a look at them as well!

File JSF related bugs here using "2.0.0 EDR1" version and ask your questions on webtier@glassfish.dev.java.net.

Please leave suggestions on other TOTD (Tip Of The Day) that you'd like to see. A complete archive of all tips is available here.

Technorati: totd javaserverfaces glassfish mojarra netbeans

del.icio.us | furl | simpy | slashdot | technorati | digg |
|

http://blogs.sun.com/arungupta/date/20080922 Monday September 22, 2008

TOTD #46: Facelets with Java Server Faces 1.2


This blog updates TOTD #45 to use Facelets as view technology.

Powerful templating system, re-use and ease-of-development, designer-friendly are the key benefits of Facelets. Facelets are already an integral part of Java Server Faces 2.0. But this blog shows how to use them with JSF 1.2.

  1. Download Facelets from here (or specifically 1.1.14). Facelets Developer Documentation is a comprehensive source of information.
  2. Add "jsf-facelets.jar" from the expanded directory to Project/Libraries as shown:

  3. Change the JSF view documents to ".xhtml" by adding the a new context parameter in "web.xml" as:

    <context-param>
        <param-name>javax.faces.DEFAULT_SUFFIX</param-name>
        <param-value>.xhtml</param-value>
      </context-param>

    The updated "web.xml" looks like:

  4. Specify Facelets as the ViewHandler of JSF application by adding the following fragment to "faces-config.xml":

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

    The updated document looks like:


  5. Create three new XHTML pages by right-clicking on the project, selecting "New", "XHTML" and name them as "template", "welcome" and "result". This creates "template.xhtml", "welcome.xhtml" and "result.xhtml" in "Web Pages" folder. 
    1. Replace the generated code in "template.xtml" with the code given here. Change the <title> text "Facelets: What's your favorite City ?".
    2. Replace the generated code in "welcome.xhtml" with the code given here. Refactor "welcomeJSF.jsp" such that H1 tag and the associated text goes in <ui:define name="title"> and rest of the content goes in <ui:define name="body">. Also change the value of "template" attribute of <ui:composition> by removing "/". The updated page looks like:

    3. Replace the generated code in "result.xhtml" with the code given here. Refactor "result.jsp" such that H1 tag and the associated text goes in <ui:define name="title"> and rest of the content goes in <ui:define name="body">. Also add a namespace declaration for "http://java.sun.com/jsf/core".

      Optionally change the <h:form> associated with the command button to:

                      <form jsfc="h:form">
                          <input jsfc="h:commandButton" action="back" value="Back"/>
                      </form> 

      The updated page looks like:


  6. Add couple of more navigation rules to "faces-config.xml":

        <navigation-rule>
            <from-view-id>/welcome.xhtml</from-view-id>
            <navigation-case>
                <from-outcome>submit</from-outcome>
                <to-view-id>/result.xhtml</to-view-id>
            </navigation-case>
        </navigation-rule>
        <navigation-rule>
            <from-view-id>/result.xhtml</from-view-id>
            <navigation-case>
                <from-outcome>back</from-outcome>
                <to-view-id>/welcome.xhtml</to-view-id>
            </navigation-case>
        </navigation-rule>
And that's it, Facelets-based application is now available at "http://localhost:8080/Cities/faces/welcome.xhtml". The interaction is exactly similar to as shown in TOTD #45 and some of the sample images (borrowed from TOTD #45) are:


Now this application is using Facelets as the view technology instead of the in-built view definition framework.
Please leave suggestions on other TOTD (Tip Of The Day) that you'd like to see. A complete archive of all tips is available here.

Technorati: totd javaserverfaces facelets netbeans glassfish

del.icio.us | furl | simpy | slashdot | technorati | digg |
|

http://blogs.sun.com/arungupta/date/20080917 Wednesday September 17, 2008

TOTD #45: Ajaxifying Java Server Faces using JSF Extensions


TOTD #42 explained how to create a simple Java Server Faces application using NetBeans 6.1 and deploy on GlassFish. In the process it explained some basic JSF concepts as well. If you remember, it built an application that allows you to create a database of cities/country of your choice. In that application, any city/country combination can be entered twice and no errors are reported.

This blog entry extends TOTD #42 and show the list of cities, that have already been entered, starting with the letters entered in the text box. And instead of refreshing the entire page, it uses JSF Extensions to make an Ajax call to the endpoint and show the list of cities based upon the text entered. This behavior is similar to Autocomplete and shows the suggestions in a separate text box.

Let's get started!

  1. Download latest JSF-Extensions release.
  2. Unzip the bundle as:

    ~/tools >gunzip -c ~/Downloads/jsf-extensions-0.1.tar.gz | tar xvf -
  3. In NetBeans IDE, add the following jars to Project/Libraries

  4. Edit "welcomeJSF.jsp"
    1. Add the following to the required tag libraries

      <%@taglib prefix="jsfExt" uri="http://java.sun.com/jsf/extensions/dynafaces" %>

      The updated page looks like:

    2. Add the following tag as the first tag inside <f:view>

      <jsfExt:scripts />

      The updated page looks like:

    3. Add prependId="false" to "<h:form>" tag. The updated tag looks like:

    4. Add the following fragment as an attribute to <h:inputText> tag with "cityName" id:

      onkeyup="DynaFaces.fireAjaxTransaction(this, { execute: 'cityName', render: 'city_choices', immediate: true});"

      This is the magic fragment that issues an Ajax call to the endpoint. It ensures execute portion of the request lifecycle is executed for "cityName" and "city_choices" (defined later) is rendered.

      The updated page looks like:

    5. Add a new <h:outputText> tag after <h:commandButton> tag (to hold the suggestions output):

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

      The updated page looks like:

  5. Add the following fragment to web.xml

           <init-param>
              <param-name>javax.faces.LIFECYCLE_ID</param-name>
              <param-value>com.sun.faces.lifecycle.PARTIAL</param-value>
            </init-param>

    The updated file looks like:

  6. Edit "server.Cities" class
    1. Add a new NamedQuery in Cities class (at the mark after yellow-highlighted parentheses):




      The query is:

      @NamedQuery(name = "Cities.findSimilarName", query = "SELECT c FROM Cities c WHERE LOWER(c.cityName) LIKE :searchString"),

      This NamedQuery queries the database and return a list of city names that matches the pattern specified in "searchString" parameter.
    2. Change the toString() method implementation to return "cityName". The updated method looks like:



      This allows the city name to be printed clearly.
  7. Add a new method in "server.DatabaseUtil" as:

        public Collection<Cities> getCityChoices() {
            Collection<Cities> allCities = new ArrayList<Cities>();

            if (cities.getCityName() != null && !cities.getCityName().equals("")) {
                List list = entityManager.createNamedQuery("Cities.findSimilarName").
                        setParameter("searchString", cities.getCityName().toLowerCase() + "%").
                        getResultList();
                for (int i = 0; i < list.size(); i++) {
                    allCities.add((Cities) list.get(i));
                }
               
            }
            return allCities;
        }

    This method uses previously defined NamedQuery and adds a parameter for pattern matching.
Now, play time!

The list of created cities is:



If "S" is entered in the text box (http://localhost:8080/Cities/), then the following output is shown:



Entering "San", shows:



Entering "Sant" shows:



Entering "De" updates the page as:



And finally entering "Ber" shows the output as:



So you built a simple Ajaxified Java Server Faces application using JSF Extensions.

Here are some more references to look at:
  1. JSF Extensions Getting Started Guide
  2. Tech Tip: Adding Ajax to Java Server Faces Technology with Dynamic Faces
  3. JSF Extensions Ajax Reference
Java Server Faces 2.0 has Ajax functionality integrated into the spec and this should be more seamless. I'll try that next!

Please leave suggestions on other TOTD (Tip Of The Day) that you'd like to see. A complete archive of all tips is available here.

Technorati: totd mysql javaserverfaces netbeans glassfish ajax

del.icio.us | furl | simpy | slashdot | technorati | digg |
|

http://blogs.sun.com/arungupta/date/20080820 Wednesday August 20, 2008

TOTD #42: Hello JavaServer Faces World with NetBeans and GlassFish

This TOTD (Tip Of The Day) shows how to create a simple Java Server Faces application using NetBeans IDE 6.1. This is my first ever Java Server Faces application :) Much more comprehensive applications are already available in NetBeans and GlassFish tutorials.

The application is really simple - it allows you to create a database of cities/country that you like. You enter the city & country name on a page and click on Submit. This stores the data entered in the backend database and displays all the stored values in a new page. This application demonstrates simple JSF concepts:

  • How to create a JSF application using NetBeans IDE ?
  • How to populate a JSF widget with a Managed Bean ?
  • How to use a Persistence Unit with JSF widgets ?
  • How to setup navigation rules between multiple pages ?
  • How to print simple error validation messages ?
  • How to inject a bean into another class ?
This particular TOTD is using JSF 1.2 that is already bundled with GlassFish v2. Let's get started.
  1. In NetBeans IDE, create a new project
    1. Create a new NetBeans Web project and enter the values ("Cities") as shown:



      and click on "Next".
    2. Choose GlassFish v2 as the deployment server and click on "Next".
    3. Select "JavaServer Faces" framework as shown below:



      take defaults and click on "Finish".
  2. Create a Persistence Unit as explained in TOTD #38. The values required for this TOTD are slightly different and given below.
    1. Use the following table definition:

      create table cities(id integer AUTO_INCREMENT,
                          city_name varchar(20),
                          country_name varchar(20),
                          PRIMARY KEY(id));
    2. There is no need to populate the table.
    3. Use "jndi/cities" as Data Source name.
    4. There is no need to create a Servlet.
    5. Add the following NamedQuery:

      @NamedQuery(name = "Cities.findAll", query = "SELECT c FROM Cities c"), 

      right after the highlighted parentheses shown below:


  3. Create a new bean which will perform all the database operations
    1. Right-click on "Source Packages", select "New", "Java Class..." and specify the values as shown below:



      and click on "Finish".
    2. Create a new class instance variable for "Cities" entity class by adding a new variable and accessor methods as shown below:

          private Cities cities;
          
          public void setCities(Cities cities) {
              this.cities = cities;
          }

      and then injecting in "faces-config.xml" as shown by the fragment below:

          <managed-bean>
              <managed-bean-name>cities</managed-bean-name>
              <managed-bean-class>server.Cities</managed-bean-class>
              <managed-bean-scope>request</managed-bean-scope>
          </managed-bean>
          <managed-bean>
              <managed-bean-name>dbUtil</managed-bean-name>
              <managed-bean-class>server.DatabaseUtil</managed-bean-class>
              <managed-bean-scope>request</managed-bean-scope>
              <managed-property>
                  <property-name>cities</property-name>
                  <value>#{cities}</value>
              </managed-property>
          </managed-bean>
    3. In "server.DatabaseUtil"
      1. Inject EntityManager and UserTransaction as shown:

            @PersistenceContext(unitName="CitiesPU")
            private EntityManager entityManager;
            
            @Resource
            UserTransaction utx;
      2. Add a method that returns a Collection of all entries in the database table as shown below:

            public Collection<Cities> getAllCities() {
                Collection<Cities> allCities = new ArrayList<Cities>();

                List list = entityManager.createNamedQuery("Cities.findAll").getResultList();
                for (int i = 0; i < list.size(); i++) {
                    allCities.add((Cities)list.get(i));
                }
                return allCities;
            }
      3. Add a method that will save a new entry in the database by using values from the injected "Cities" entity class as shown below:

        public String saveCity() throws NotSupportedException, SystemException, RollbackException, HeuristicMixedException, HeuristicRollbackException {
                utx.begin();
                entityManager.persist(cities);
                utx.commit();
                
                return "submit";
            }
      4. Finally, right-click in the editor pane and select "Fix Imports":



        and click on "OK". Make sure to pick the right package name for "NotSupportedException" and "RollbackException".
  4. Add Java Server Faces widgets in the main entry page
    1. In "welcomeJSF.jsp", drag/drop "JSF Form" widget on line 22 as shown below:


    2. Select "Form Generated from Entity Class" and specify "server.Cities" entity class in the text box as shown:


    3. The generated code fragment looks like:

      <h2>Detail</h2>
       <h:form>
        <h:panelGrid columns="2">
          <h:outputText value="Id:"/>
          <h:outputText value="#{anInstanceOfserver.Cities.id}" title="Id" />
          <h:outputText value="CityName:"/>
          <h:outputText value="#{anInstanceOfserver.Cities.cityName}" title="CityName" />
          <h:outputText value="CountryName:"/>
          <h:outputText value="#{anInstanceOfserver.Cities.countryName}" title="CountryName" />
        </h:panelGrid>
       </h:form>

      It generates a 2-column table based upon fields from the entity class. We will use this form for accepting inputs by making the following changes:

      1. Remove first two "h:outputText" entries because "id" is auto generated.
      2. Change "h:outputText" that uses value expression to "h:inputText" to accept the input.
      3. Use "cities" managed bean instead of the default generated expression.
      4. Add required="true" to inputText fields. This will ensure that the form can not be submitted if text fields are empty.
      5. Add "id" attributes to inputText fields. This will be used to display the error message if fields are empty.

      The updated code fragment (with changes highlighted in bold) looks like:

      <h2>Detail</h2>
       <h:form>
        <h:panelGrid columns="2">
          <h:outputText value="CityName:"/>
          <h:inputText value="#{cities.cityName}" title="CityName" id="cityName" required="true"/>
          <h:outputText value="CountryName:"/>
          <h:inputText value="#{cities.countryName}" title="CountryName" id="countryName" required="true"/>
        </h:panelGrid>
       </h:form>

      Issue# 144217 will ensure to pick a pre-declared managed-bean or declare a new one if it does not exist already. After issue# 144499 is fixed then "id" attributes will be generated by default.
    4. Add a button to submit the results:

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

      This must be added between </h:panelGrid> and </h:form> tags.
    5. Add a placeholder for displaying error messages:

      <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"/>

      right after <h:commandButton> tag. The official docs specify the default value of "false" for both "showSummary" and "showDetail" attribute. But TLD says "false" for "showSummary" and "true" for "showDetail". Issue# 773 will fix that.
  5. Add a new page that displays result of all the entries added so far
    1. Right-click on the main project, select "New", "JSP..." and specify the name as "result".
    2. Add the following namespace declarations at top of the page:

      <%@taglib prefix="f" uri="http://java.sun.com/jsf/core"%>
      <%@taglib prefix="h" uri="http://java.sun.com/jsf/html"%>

    3. Issue #144218 will ensure these namespaces are declared by the IDE.
    4. Drag/Drop a "JSF Data Table" widget in the main HTML body and enter the values as shown:



      The generated code fragment looks like:

      <f:view>
      <h:form>
       <h1><h:outputText value="List"/></h1>
       <h:dataTable value="#{arrayOrCollectionOfserver.Cities}" var="item">
      <h:column>
       <f:facet name="header">
       <h:outputText value="Id"/>
       </f:facet>
       <h:outputText value=" #{item.id}"/>
      </h:column>
      <h:column>
       <f:facet name="header">
       <h:outputText value="CityName"/>
       </f:facet>
       <h:outputText value=" #{item.cityName}"/>
      </h:column>
      <h:column>
       <f:facet name="header">
       <h:outputText value="CountryName"/>
       </f:facet>
       <h:outputText value=" #{item.countryName}"/>
      </h:column>
      </h:dataTable>
       </h:form>
      </f:view>

      Change the <h:dataTable> tag as shown below (changes highlighted in bold):

       <h:dataTable value="#{dbUtil.allCities}" var="item">
    5. This page will be used to show the results after an entry is added to the database. Add a new button to go back to the entry page by adding the following fragment:

      <h:form>
           <h:commandButton action="back" value="back"/>
      </h:form>

      between </h:form> and </f:view> tags.
  6. Add the navigation rules to "faces-config.xml" as shown below:



    The corresponding XML fragment is:

        <navigation-rule>
            <from-view-id>/welcomeJSF.jsp</from-view-id>
            <navigation-case>
                <from-outcome>submit</from-outcome>
                <to-view-id>/result.jsp</to-view-id>
            </navigation-case>
        </navigation-rule>
        <navigation-rule>
            <from-view-id>/result.jsp</from-view-id>
            <navigation-case>
                <from-outcome>back</from-outcome>
                <to-view-id>/welcomeJSF.jsp</to-view-id>
            </navigation-case>
        </navigation-rule>

Let's run the application by right-clicking on the project and selecting "Deploy and Undeploy". The welcome page shows up and looks like as shown below:



Clicking on "Submit" without entering any values shows the default error messages as shown below:



Enter your favorite city/country and click on "Submit" to see the result page as:



Click on "Back" and enter few more cities. The updated result page looks like:



Here are some useful pointers for you:
Subsequent entries on this trail will show how Java Server Faces Technology Extensions, Facelets, Mojarra make the application richer.

Please leave suggestions on other TOTD (Tip Of The Day) that you'd like to see. A complete archive of all tips is available here.

Technorati: totd mysql javaserverfaces netbeans glassfish

del.icio.us | furl | simpy | slashdot | technorati | digg |
|

http://blogs.sun.com/arungupta/date/20080724 Thursday July 24, 2008

Job Opportunity in GlassFish Web Container Team

What's common between

You are right - GlassFish is the answer!

If you are a fresh graduate, then apply for GlassFish Scripting team. However if you have
  • Experience in Developing Web container and related web-tier technologies such as JSP, Servlets, Java Server Faces and Java Standard Tag Libraries
  • Like to define the direction of Web container in Java EE platform and GlassFish Application Server
  • Worked in the Open Source & distributed teams
  • Like to play "follow the leader" where you are the leader :)
Then GlassFish team needs you. Apply now!

Technorati: glassfish webtier jsp servlets jstl javaserverfaces job

del.icio.us | furl | simpy | slashdot | technorati | digg |
|

Valid HTML! Valid CSS!

This is a personal weblog, I do not speak for my employer.