Skip to main content

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

Posted by arungupta on August 20, 2008 at 6:18 AM PDT



This TOTD (Tip
Of style="font-weight: bold;">The style="font-weight: bold;">Day) shows how to
create a simple href="http://java.sun.com/javaee/javaserverfaces/">Java
Server Faces application using href="http://netbeans.org">NetBeans IDE 6.1. This
is my first ever Java Server Faces application :) Much more
comprehensive applications are already available in href="http://www.netbeans.org/kb/60/web/intro.html">NetBeans
and href="http://java.sun.com/javaee/5/docs/tutorial/doc/bnaph.html">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 href="http://glassfish.org">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:



      src="http://blogs.sun.com/arungupta/resource/images/jsf-nb61-cities-create-new-project-name.png">



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



      src="http://blogs.sun.com/arungupta/resource/images/jsf-nb61-cities-create-new-project-jsf-framework.png">



      take defaults and click on "Finish".
  2. Create a Persistence Unit as explained in href="http://blogs.sun.com/arungupta/entry/totd_38_creating_a_mysql">TOTD
    #38. The values required for this TOTD are slightly different
    and given below.
    1. Use the following table definition:


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


      style="text-align: left; background-color: rgb(204, 204, 255); width: 100%;"
      cellpadding="2" cellspacing="2">
      @NamedQuery(name = "Cities.findAll", query =
      "SELECT c FROM Cities c"), 



      right after the highlighted parentheses shown below:



      src="http://blogs.sun.com/arungupta/resource/images/jsf-nb61-cities-add-named-query.png">

  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:



      src="http://blogs.sun.com/arungupta/resource/images/jsf-nb61-cities-new-dbutil.png">



      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:


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

          

          public void setCities(Cities cities) {

             
      this.cities = cities;

          }



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


      style="text-align: left; background-color: rgb(204, 204, 255); width: 100%;"
      cellpadding="2" cellspacing="2">
          <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. Inject EntityManager and UserTransaction as
      shown:


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

          private EntityManager entityManager;

          

          @Resource

          UserTransaction utx;
    4. Add a method that returns a Collection of all entries in
      the database table as shown below:


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

          }
    5. Add a method that will save a new entry in the database
      by using values from the injected "Cities" entity class as
      shown below:


      style="text-align: left; background-color: rgb(204, 204, 255); width: 100%;"
      cellpadding="2" cellspacing="2">
      public String saveCity() throws
      NotSupportedException, SystemException, RollbackException,
      HeuristicMixedException, HeuristicRollbackException {

             
      utx.begin();

             
      entityManager.persist(cities);

             
      utx.commit();

              

             
      return "submit";

          }
    6. Finally, right-click in the editor pane and select "Fix
      Imports":



      src="http://blogs.sun.com/arungupta/resource/images/jsf-nb61-cities-citiesbean-fix-import.png">



      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:



      src="http://blogs.sun.com/arungupta/resource/images/jsf-nb61-cities-form-drag.png">
    2. Select "Form Generated from Entity Class" and specify
      "server.Cities" entity class in the text box as shown:



      src="http://blogs.sun.com/arungupta/resource/images/jsf-nb61-cities-form-from-cities.png">
    3. The generated code fragment looks like:


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



      style="text-align: left; background-color: rgb(204, 204, 255); width: 100%;"
      cellpadding="2" cellspacing="2">
      <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 style="text-decoration: underline;">i href="http://www.netbeans.org/issues/show_bug.cgi?id=144499">ssue#
      144499 is fixed then "id" attributes will be generated by
      default.

    4. Add a button to submit the results:


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


      style="text-align: left; background-color: rgb(204, 204, 255); width: 100%;"
      cellpadding="2" cellspacing="2">
      <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 href="http://java.sun.com/javaee/javaserverfaces/1.2_MR1/docs/tlddocs/h/message.html">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:


      style="text-align: left; background-color: rgb(204, 204, 255); width: 100%;"
      cellpadding="2" cellspacing="2">
      <%@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:



      src="http://blogs.sun.com/arungupta/resource/images/jsf-nb61-cities-datatable-from-cities.png">



      The generated code fragment looks like:


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


      style="text-align: left; background-color: rgb(204, 204, 255); width: 100%;"
      cellpadding="2" cellspacing="2">
       <h:dataTable value="#{ style="font-weight: bold;">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:


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



    src="http://blogs.sun.com/arungupta/resource/images/jsf-nb61-cities-navigation-rules.png">



    The corresponding XML fragment is:


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



src="http://blogs.sun.com/arungupta/resource/images/jsf-nb61-cities-welcome-page.png">



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



src="http://blogs.sun.com/arungupta/resource/images/jsf-nb61-cities-validation-message.png">



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



src="http://blogs.sun.com/arungupta/resource/images/jsf-nb61-cities-result-one-city.png">



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



src="http://blogs.sun.com/arungupta/resource/images/jsf-nb61-cities-result-multiple-cities.png">



Here are some useful pointers for you:

  • href="http://java.sun.com/javaee/javaserverfaces/reference/api/">JSF
    Tag Library & API docs
  • javaserverfaces.dev.java.net
    - the community website
  • href="http://java.sun.com/javaee/5/docs/tutorial/doc/bnaph.html">Java
    EE 5 JSF Tutorial and many more on the community website
    right navbar.
  • Java
    Server Faces on SDN
  • GlassFish
    Webtier Aggregated Feed
  • Feedback
    • href="http://forums.java.net/jive/forum.jspa?forumID=138"> style="text-decoration: underline;">GlassFish
      Webtier Forum
    • GlassFish
      Webtier IRC
    • href="http://java.sun.com/javaee/javaserverfaces/#IRC">JSF
      IRC

Subsequent entries on this trail will show how href="https://jsf-extensions.dev.java.net/">Java Server
Faces Technology Extensions, href="https://facelets.dev.java.net/">Facelets, href="http://mojarra.dev.java.net">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 href="http://blogs.sun.com/arungupta/tags/totd">here.




Technorati: totd
mysql href="http://technorati.com/tag/javaserverfaces">javaserverfaces
netbeans
glassfish

Related Topics >>