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

Great job Arun! I'm so glad you are helping to do these kinds of things for JSF now.

Posted by Roger Kitain on August 19, 2008 at 11:25 PM PDT #

Thanks for TOTD. I got a problem when i tried this with JavaDB. Below is the stacktrace from GlassFish log

Local Exception Stack:
Exception [TOPLINK-4002] (Oracle TopLink Essentials - 2.0.1 (Build b04-fcs (04/11/2008))): oracle.toplink.essentials.exceptions.DatabaseException
Internal Exception: java.sql.SQLSyntaxErrorException: Attempt to modify an identity column 'ID'.
Error Code: -1
Call: INSERT INTO CITIES (ID, CITY_NAME, COUNTRY_NAME) VALUES (?, ?, ?)
bind => [null, Hyderabad, India]
Query: InsertObjectQuery(server.Cities[id=null])
at oracle.toplink.essentials.exceptions.DatabaseException.sqlException(DatabaseException.java:319)
at oracle.toplink.essentials.internal.databaseaccess.DatabaseAccessor.basicExecuteCall(DatabaseAccessor.java:566)
at oracle.toplink.essentials.internal.databaseaccess.DatabaseAccessor.executeCall(DatabaseAccessor.java:452)
at oracle.toplink.essentials.internal.sessions.AbstractSession.executeCall(AbstractSession.java:690)

Posted by Madhu on August 20, 2008 at 02:35 PM PDT #

Madhu,

There might be more than one change required for running it with JavaDB. For example the table definition need to look like:

create table cities(id integer NOT NULL GENERATED ALWAYS AS IDENTITY (START WITH 1, INCREMENT BY 1),
city_name varchar(20),
country_name varchar(20),
PRIMARY KEY(id));

I got an error by executing the DDL given in the blog. Can you try with the table above ?

Posted by Arun Gupta on August 21, 2008 at 08:16 AM PDT #

Hi, I am using postgresql database and for sample work you need put :
@GeneratedValue(strategy=GenerationType.IDENTITY)
at Cities entity.

another point is that result.jsp file the correct me seen:

<h:dataTable value="#{dbUtil.allCities}" var="item"> instead <h:dataTable value="#{cities.allCities}" var="item">.

thanks

Posted by Alex on August 26, 2008 at 05:58 AM PDT #

Superb demonstration thanks.

Posted by lava kafle on August 26, 2008 at 11:50 AM PDT #

Thanks a lot Arun.

So, now I can able to code in JSF.

Posted by Kumar Gaurav on August 26, 2008 at 06:23 PM PDT #

I tried it is easy to able the code

Posted by msn adresleri on September 03, 2008 at 07:57 AM PDT #

Great work. Readers might want to check out the new enterprise tech tip for composite components in JSF 2.0

http://blogs.sun.com/enterprisetechtips/entry/true_abstraction_composite_ui_components

Ed

Posted by Ed Burns on September 09, 2008 at 02:50 AM PDT #

[Trackback] 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...

Posted by Arun Gupta's Blog on September 16, 2008 at 10:47 PM PDT #

i like to know how i can insert a String array
into a data table .
i.e.

On select a drop down in a table a new row should be created with that particular field filled with array values.

Posted by jaysonkn on October 13, 2008 at 04:29 PM PDT #

[Trackback] 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...

Posted by Arun Gupta's Blog on October 13, 2008 at 10:55 PM PDT #

Çok güzel bir yazı. Genel kültürün gelişmesi açısından çok değerli bilgiler içeriyor. Dil konusuna gelince; artık bilim dilinin İngilizce olduğunu kabullenmek lazım. Bilim değil de aslında teknoloji dili demeliyiz. Çağın gerisinde kalmamak için İngilizce’ye savaş açmak yerine onunla barışık yaşamalıyız. Dünyada en çok kullanılan dil (konuşma dili) Çincedir. Bunun sebebi de malum nüfus farkı. ikinci dil İspanyolca ve evet 3.dil Türkçedir

Posted by devbahis on October 26, 2008 at 08:31 AM PDT #

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

Posted by siyaset on October 26, 2008 at 08:32 AM PDT #

thanks

Posted by iibf on October 26, 2008 at 08:33 AM PDT #

very nice works

http://www.malatyareklam.com

Posted by malatya on October 26, 2008 at 08:35 AM PDT #

Sometimes, we live java application problems when we try to add them to our web sites. Some browsers can not read them correctly. w3 site's validator also says same errors.

If you make a new lesson about integration java scripts to web pages, i will be so happy. (classes e.g.)

Thanks for your lesson again.

Posted by sunucu on January 27, 2009 at 05:00 PM PST #

thanks for this kind of infos

Posted by kolbastı on February 04, 2009 at 01:53 AM PST #

thanks

Posted by Tabela on February 22, 2009 at 08:54 PM PST #

Java Programming... I love you!

Posted by Web Hosting on May 06, 2009 at 12:28 PM PDT #

thank you bro!...

Posted by beylikdüzü halı yıkama on July 02, 2009 at 11:20 PM PDT #

hello.. thank you for this article.

Posted by porno on July 14, 2009 at 03:25 PM PDT #

Post a Comment:
Comments are closed for this entry.
About

profile image
Arun Gupta is a technology enthusiast, a passionate runner, author, and a community guy who works for Oracle Corp.


Java EE 7 Samples

Stay Connected

Search

Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today