Document Information

Preface

1.  Introduction

2.  Understanding Java Platform, Enterprise Edition

3.  Creating Your First Java EE Application

4.  Creating Your Second Web Application

Creating the firstcup Project

Create the Web Application Project

Creating the Java Persistence API Entity

Create the FirstcupUser Entity Class

Add Properties to the FirstcupUser Entity

Add Constructors to the FirstcupUser Entity

Add a Named Query to the FirstcupUser Entity

Creating the Enterprise Bean

Create the DukesBirthdayBean Enterprise Bean Class

Add a Logger Instance to DukesBirthdayBean.java

Add a Business Method to DukesBirthdayBean that Gets the Average Age Difference of firstcup Users

Add a Business Method for Calculating the Age Difference Between Duke and the User

Building, Packaging, Deploying, and Running the firstcup Web Application

Build, Package, and Deploy the firstcup Web Application

Run the firstcup Application

5.  Next Steps

 

Creating the Web Client

To create the web client, you need to perform the following tasks:

  • Create a resource bundle to hold localized messages used by the Facelets pages.

  • Configure the resource bundle in the configuration file.

  • Create the DukesBDay managed bean class.

  • Create the Facelets pages.

Creating a Resource Bundle

In this section, you'll create the resource bundle that contains the static text and error messages used by the Facelets pages. The firstcup client supports both English and Spanish locales. Therefore you need to create two properties files, each of which will contain the messages for one of the locales.

Create a Resource Bundle

  1. Right-click the firstcup project in the Projects tab.
  2. From the popup menu, choose New, then choose Other.
  3. In the Categories pane, select Other.
  4. In the File Types pane, select Properties File, then click Next.
  5. In the File Name field, type WebMessages.
  6. In the Folder field, type src/java/firstcup/web as the location of the file.
  7. Click Finish.
  8. After NetBeans IDE creates the properties file, type the following messages or copy them from here to the file:
    Welcome=Hi. My name is Duke. Let us find out who is older -- you or I. 
    DukeIs=Duke is
    YearsOldToday=years old today.
    Instructions=Type your birthday and click submit.
    YourBD=Your birthday
    Pattern=MM/dd/yyyy
    YouAre=You are 
    Year=year
    Years=years
    Older=older than Duke!
    Younger=younger than Duke!
    SameAge= the same age as Duke!
    Submit=Submit
    Back=Back
    AverageAge=The average age difference of all First Cup users is

    These messages will be referenced from the XHTML pages.

  9. From the File menu, choose Save.
  10. To add the Spanish translations of the messages, copy the properties file WebMessages_es.properties from tut-install/firstcup/example/firstcup/src/java/com/sun/firstcup/web to tut-install/firstcup/myexample/firstcup/src/java/firstcup/web.

    You can create multiple properties files, each with a set of messages for a different locale. By storing localized static text and messages in resource bundles, you don't need to create a separate set of XHTML pages for each locale.

Configuring the Resource Bundle in the Configuration File

To make the resource bundle available to the application, you need to configure it in the configuration file, by performing the following task.

Create a Configuration File

The faces-config.xml deployment descriptor contains configuration settings for the JavaServer Faces application. JSF applications don't require a deployment descriptor unless they use features that can only be configured in faces-config.xml. In firstcup, the deployment descriptor has settings defining the resource bundle that provides localized strings in English and Spanish.

  1. Select the firstcup project in the Projects tab.
  2. From the File menu, choose New File.
  3. In the Categories pane, select JavaServer Faces.
  4. In the File Types pane, select JSF Faces Configuration.
  5. Click Next, then click Finish.

Configure the Resource Bundle

The firstcup application is localized for the English and Spanish languages. JavaServer Faces applications can automatically select the proper language based on the locale of the user's web browser. Specify the default and supported locales in the faces-config.xml file.

  1. With the newly created faces-config.xml file open, click XML.
  2. Place the cursor between the opening and closing faces-config tags.
  3. Add the following <application> tag to configure the resource bundle:
    <application>
        <resource-bundle>
            <base-name>firstcup.web.WebMessages</base-name>
            <var>bundle</var>
        </resource-bundle>
        <locale-config>
            <default-locale>en</default-locale>
            <supported-locale>es</supported-locale>
        </locale-config>
    </application>

    The base-name element of the resource-bundle element identifies the fully qualified class name of the resource bundle. The var element identifies the name by which the XHTML pages will reference the resource bundle. The locale-config element identifies the locales supported by the resource bundle.

  4. Right-click in the editor window and select Format.
  5. From the File menu, choose Save.

Creating the DukesBDay Managed Bean Class

The DukesBDay JavaBeans component is a backing bean. A backing bean is a JavaServer Faces managed bean that acts as a temporary data storage for the values of the components included on a particular JavaServer Faces page. A managed bean is a JavaBeans component that a JavaServer Faces application instantiates and stores in scope. The section following this one describes more about managed beans and how to configure them.

This section describes how to create the DukesBDay class. To create the class you need to do the following:

  • Create the managed bean class.

  • Add a property that stores Duke's current age from the JAX-RS web service.

  • Add a property that stores the user's current birth date.

  • Add a property that stores the age difference from the DukesBirthdayBean enterprise bean.

  • Add a property that stores the absolute value of the age difference.

  • Add a property that stores the average age difference of all users.

  • Add a method that calls DukesBirthdaybean.getAgeDifference, sets the absolute age difference, and forwards the user to the display page.

Create the Managed Bean Class

Create a JavaServer Faces managed bean class that will subsequently be modified.

  1. Right-click the firstcup.web package in the Projects tab.
  2. From the popup menu, choose New, then choose Other.
  3. In the Categories pane, select JavaServer Faces.
  4. In the File Types pane, select JSF Managed Bean, then click Next.
  5. In the Class Name field, type DukesBDay.
  6. In the Package field, select firstcup.web.
  7. Select session from the Scope menu.
  8. Click Finish.

    You should now see the DukesBDay.java file inside the firstcup.web package in the Projects tab. The DukesBDay.java file should also be open in the editor pane.

  9. In the editor pane, find the @Named annotation and modify the value attribute, with the value DukesBDay. The resulting code should look like this:
    @Named(value = "DukesBDay")

Add an Enterprise Bean Reference

Add a javax.ejb.EJB annotation to inject a reference to the DukesBirthdayBean enterprise bean. This session bean will be called from the methods in DukesBDay.

  1. Right-click in the editor window inside the class and select Insert Code, then select Call Enterprise Bean.
  2. In the Call Enterprise Bean dialog, expand the firstcup application, select DukesBirthdayBean, and click OK.

    The following field will be added:

    @EJB
    private DukesBirthdayBean dukesBirthdayBean;

Add Properties to the Bean

During this task, you will add the following properties to the DukesBDay bean:

  • age for getting Duke's age from the web service

  • yourBD to hold the user's birth date

  • ageDiff to get the age difference from the enterprise bean

  • absAgeDiff to hold the absolute value of the age difference

  • averageAgeDifference to hold the average age difference of all users

The getter method for the age property uses the java.net and java.io classes to create an HTTP connection to the Duke's Age web service and stores the result.

The yourBD property is annotated @NotNull to indicate that this property must be set. The @NotNull annotation is one of the Bean Validation constraints.

  1. In the DukesBDay class, copy and paste the following field definitions:
        protected int age;
        @NotNull protected Date yourBD;
        protected int ageDiff;
        protected int absAgeDiff;
        protected Double averageAgeDifference;
        private static final Logger logger = Logger.getLogger("firstcup.web.DukesBDay");
  2. Add a default constructor that sets the initial values of the fields by copying and pasting the following code:
        public DukesBDay() {
            age = -1;
            yourBD = null;
            ageDiff = -1;
            absAgeDiff = -1;
            averageAgeDifference = -1.0;
        }
  3. Add the following getter and setter methods for the new fields by copying and pasting the following code:
        public int getAge() {
            // Use the java.net.* APIs to access the Duke's Age RESTful web service
            HttpURLConnection connection = null;
            BufferedReader rd = null;
            StringBuilder sb = null;
            String line = null;
            URL serverAddress = null;
    
            try {
                serverAddress = new URL(
                        "http://localhost:8080/DukesAgeService/resources/dukesAge");
                connection = (HttpURLConnection) serverAddress.openConnection();
                connection.setRequestMethod("GET");
                connection.setDoOutput(true);
                connection.setReadTimeout(10000);
    
                // Make the connection to Duke's Age
                connection.connect();
    
                // Read in the response
                rd = new BufferedReader(
                        new InputStreamReader(connection.getInputStream()));
                sb = new StringBuilder();
                while ((line = rd.readLine()) != null) {
                    sb.append(line);
                }
    
                // Convert the response to an int
                age = Integer.parseInt(sb.toString());
            } catch (MalformedURLException e) {
                logger.warning("A MalformedURLException occurred.");
                e.printStackTrace();
            } catch (ProtocolException e) {
                logger.warning("A ProtocolException occurred.");
                e.printStackTrace();
            } catch (IOException e) {
                logger.warning("An IOException occurred");
                e.printStackTrace();
            }
    
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    
        public Date getYourBD() {
            return yourBD;
        }
    
        public void setYourBD(Date yourBD) {
            this.yourBD = yourBD;
        }
    
        public int getAgeDiff() {
            return ageDiff;
        }
    
        public void setAgeDiff(int ageDiff) {
            this.ageDiff = ageDiff;
        }
    
        public int getAbsAgeDiff() {
            return absAgeDiff;
        }
    
        public void setAbsAgeDiff(int absAgeDiff) {
            this.absAgeDiff = absAgeDiff;
        }
    
        public Double getAverageAgeDifference() {
            return averageAgeDifference;
        }
    
        public void setAverageAgeDifference(Double averageAgeDifference) {
            this.averageAgeDifference = averageAgeDifference;
        }
  4. Right-click in the editor window and select Format.
  5. Right-click in the editor window and select Fix Imports, and click OK.

Get the Age Difference from the DukesBirthdayBean Enterprise Bean

During this task, you will create a processBirthday method to get the difference in age between the user's age and Duke's age from the EJB, set the absAgeDiff variable to the absolute value of the age difference, and set a result string that will forward the user to the display page.

  1. Add a processBirthday method by copying and pasting the following code just before the end of the class:
        public String processBirthday() {
            this.setAgeDiff(dukesBirthdayBean.getAgeDifference(yourBD));
            logger.info("age diff from dukesbday " + ageDiff);
            this.setAbsAgeDiff(Math.abs(this.getAgeDiff()));
            logger.info("absAgeDiff " + absAgeDiff);
            this.setAverageAgeDifference(dukesBirthdayBean.getAverageAgeDifference());
            logger.info("averageAgeDifference " + averageAgeDifference);
            return "/response.xhtml";
        }

    This method calls the getAgeDifference method of DukesBirthdayBean to get the age difference and store it in the ageDiff property, sets the absolute age difference stored in the absAgeDiff property, and sets the average age difference stored in the averageAgeDifference property. It returns the relative URL of the response page to which the user will be forwarded.

  2. Right-click in the editor window and select Format.
  3. From the File menu, choose Save.

Creating the Facelets Client

The Facelets client consists of a resource library, a composite component, and two XHTML files.

Resource Libraries in firstcup

A JavaServer Faces resource library is a collection of user-created components collected in a standard location in a web application. Resource libraries are identified according to a resource identifier, a string that represents a particular resource within a web application. Resources can be packaged either at the root of the web application or on the web application's classpath.

A resource packaged in the web application root must be in a subdirectory of a resources directory at the web application root.

resources/resource-identifier

A resource packaged in the web application classpath must be in a subdirectory of the META-INF/resources directory within a web application.

META-INF/resources/resource-identifier

Resource identifiers are unique strings that conform to the following format:

[locale-prefix/][library-name/][library-version/]resource-name[/resource-version]

Elements of the resource identifier in brackets ([]) are optional. A resource name, identifying a particular resource (a file or a graphic, for example), is required. In firstcup, a resource library with the name components is packaged in the web application root, and this library contains one resource, a file called inputDate.xhtml. The resource identifier for this resource is therefore components/inputDate.xhtml, and it is located in the web application root at resources/components/inputDate.xhtml.

The inputDate Composite Component

A composite component is a set of user-defined JavaServerFaces and Facelets components located in a resource. In firstcup, the inputDate.xhtml resource, located in the components resource library, is a composite component that contains tags for reading in a date the user enters in a form. Composite components consist of an interface definition and an implementation.

The interface definition is specified with the <cc:interface> tag to define which attributes are exposed to pages that use the composite component. Attributes are identified with the <cc:attribute> tag.

The inputDate.xhtml interface definition is as follows. It defines a single attribute, date, that must be specified in pages that use the inputDate composite component.

<cc:interface>
    <cc:attribute name="date" />
</cc:interface>

The implementation of the composite component is specified with the <cc:implementation> tag. The tags within the <cc:implementation> are the actual component tags that will be added to pages that use the composite component. They can be any HTML Render Kit, JavaServer Faces, or Facelets tags. The #{cc.attrs.attribute-name} expression is used to get the value of the specified attribute from the page or component that is using the composite component.

The implementation of the inputDate composite component is as follows. An HTML input text component will store the entered text into the date attribute, accessed by the #{cc.attrs.date} expression. A JavaServer Faces convertDateTime component will convert the entered text to a date with the form of MM/dd/yyyy (04/13/2009, for example).

<cc:implementation>
    <h:inputText value="#{cc.attrs.date}">
        <f:convertDateTime pattern="MM/dd/yyyy" />
    </h:inputText>
</cc:implementation>

Create the inputDate Composite Component

Create the inputDate composite component as a resource in the components resource library.

  1. Select the firstcup project in the Projects tab.
  2. From the File menu, choose New File.
  3. In the Categories pane, select JavaServer Faces.
  4. In the File Types pane, select JSF Composite Component, then click Next.
  5. In the File Name field, type inputDate.
  6. In the Folder field, type resources/components, then click Finish.
  7. Add the composite component interface definition between the opening and closing <cc:interface> tags in inputDate.xhtml:
        <cc:interface>
            <cc:attribute name="date" />
        </cc:interface>
  8. Add the composite component implementation between the opening and closing cc:implementation tags:
        <cc:implementation>
            <h:inputText value="#{cc.attrs.date}">
                <f:convertDateTime pattern="MM/dd/yyyy" />
            </h:inputText>
        </cc:implementation>
  9. On each of the other two lines where error glyphs appear, press Alt-Enter and select the library declaration that appears.
  10. Right-click in the editor window and select Format.
  11. From the File menu, choose Save.

The Facelets Web Interface

The firstcup web application interface has two XHTML files. The greeting.xhtml file displays Duke's current age and the form where the user can enter a birthday. The response.xhtml file displays the age difference between the user and Duke.

The greeting.xhtml file contains several pieces of the firstcup application detailed previously. It uses the localized strings contained in WebMessages.properties and WebMessages_es.properties. It uses the DukesBDay managed bean to call both the DukesAgeResource JAX-RS web service and the DukesBirthdayBean enterprise bean. It uses the inputDate composite component to create the input for the user to enter a birthday.

Here's the content of the greeting.xhtml file.

<?xml version="1.0" encoding="UTF-8"?>
<!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" xml:lang="en" lang="en"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:fc="http://java.sun.com/jsf/composite/components">
    <h:head>
        <title>Firstcup Greeting Page</title>
    </h:head>
    <h:body>
        <h:form>
            <h2>
                <h:outputText value="#{bundle.Welcome}"/>
            </h2>
            <h:outputText value="#{bundle.DukeIs} "/>
            <h:outputText value="#{DukesBDay.age} #{bundle.YearsOldToday}"/>
            <p/>
            <h:outputText value="#{bundle.Instructions}"/>
            <p/>
            <h:outputText value="#{bundle.YourBD} "/>
            <fc:inputDate id="userBirthday" date="#{DukesBDay.yourBD}" />
            <h:outputText value=" #{bundle.Pattern}"/>
            <p/>
            <h:commandButton value="#{bundle.Submit}"
                             action="#{DukesBDay.processBirthday}"/>
            <p/>
            <h:message for="userBirthday" style="color:red"/>
        </h:form>

    </h:body>
</html>

The greeting.xhtml file uses the HTML Render Kit and the components resource library tag libraries. The components tag library has a prefix of fc, and is used to specify the inputDate composite component in the form below. The <fc:inputDate id="userBirthday" date="#{DukesBDay.yourBD}" /> tag has the required date attribute, and it stores the value in the yourBD property in the DukesBDay managed bean by using the EL expression #{DukesBDay.yourBD}.

The localized strings are referred to by using the EL expressions #{bundle.property-name}. For example, the <h:outputText value="#{bundle.Welcome}"/> tag will display the following string in English locales:

Hi. I'm Duke. Let's find out who's older -- you or I.

The <h:commandButton> tag creates a Submit button and specifies that a successful submission should render the response.xhtml file by setting the action attribute to #{DukesBDay.processBirthday}. The processBirthday method returns the value "/response.xhtml". The action attribute is used to define navigation rules for forms in Facelets pages.

If the form submission is unsuccessful, a warning message is displayed. This is done with the <h:message for="userBirthday" style="color:red"/> tag, which is connected to the inputDate composite component with the id userBirthday. That is, if there's an error with the input of the inputDate component, a warning message is displayed.

The response.xhtml file displays the age difference between the user and Duke and the average age difference of all users so far. Different strings are displayed based on whether the user is the same age, younger, or older than Duke. The text can be displayed or not based on the conditions specified by the rendered attribute of the <h:outputText> tag. The conditions used in the rendered attribute are EL language alternatives to the Java programming language conditional operators to allow XML parsing of the XHTML file.

Table 4-1 Conditional Operator EL Language Alternatives

Logical Condition

Java Programming Language Conditional Operator

EL Language Alternative

AND

&&

&&

EQUALS

==

==

LESS THAN

<

lt

GREATER THAN

>

gt

Here's the content of the response.xhtml file.

<?xml version='1.0' encoding='UTF-8' ?>
<!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">
    <h:head>
        <title>Response Page</title>
    </h:head>
    <h:body>
        <h:form>
            <h:outputText value="#{bundle.YouAre} "/>
            <h:outputText value="#{bundle.SameAge}"
                          rendered="#{DukesBDay.ageDiff == 0}"/>
            <h:outputText value="#{DukesBDay.absAgeDiff}"
                          rendered="#{DukesBDay.ageDiff lt 0}"/>
            <h:outputText value=" #{bundle.Year} "
                          rendered="#{DukesBDay.ageDiff == -1}"/>
            <h:outputText value=" #{bundle.Years} "
                          rendered="#{DukesBDay.ageDiff lt -1}"/>
            <h:outputText value="#{bundle.Younger}"
                          rendered="#{DukesBDay.ageDiff lt 0}"/>
            <h:outputText value="#{DukesBDay.absAgeDiff}"
                          rendered="#{DukesBDay.ageDiff gt 0}"/>
            <h:outputText value=" #{bundle.Year} "
                          rendered="#{DukesBDay.ageDiff == 1}"/>
            <h:outputText value=" #{bundle.Years} "
                          rendered="#{DukesBDay.ageDiff gt 1}"/>
            <h:outputText value="#{bundle.Older}"
                          rendered="#{DukesBDay.ageDiff gt 0}"/>
            <p/>
            <h:outputText 
                value="#{bundle.AverageAge} #{DukesBDay.averageAgeDifference}."/>
            <p/>
            <h:commandButton id="back" value="#{bundle.Back}" action="greeting"/>
        </h:form>
    </h:body>
</html>

For example, the #{bundle.SameAge} string is displayed if the user and Duke have the same birthday as specified by the condition #{DukesBDay.ageDiff == 0} in the rendered attribute. That is, display the following string if the ageDiff property of DukesBDay equals 0:

You are the same age as Duke!

The form also contains a <h:commandButton> tag that creates a back button that will direct the user back to the greeting.xhtml page, as specified in the action attribute.

Create the XHTML Files

Create the Facelets XHTML files in NetBeans IDE.

  1. Select Web Pages under the firstcup project in the Projects tab.
  2. From the File menu, choose New File.
  3. In the Categories pane, select JavaServer Faces.
  4. In the File Types pane, select JSF Page, then click Next.
  5. In the File Name field, type greeting, then click Finish.
  6. Repeat the previous steps to create a new Facelets file named response.

Set the Welcome File in the web.xml Deployment Descriptor

Configure the application to use greeting.xhtml as the welcome file by modifying web.xml.

  1. In the firstcup project, expand the Configuration Files node, then double-click web.xml.
  2. Click Pages.
  3. Click Browse under Welcome Files, expand Web Pages, select greeting.xhtml, and click Select File.
  4. Edit the Welcome Files text field so that the field looks like this:
    faces/greeting.xhtml
  5. From the File menu, choose Save.

Modify the XHTML Files

Modify greeting.xhtml to include the components tag library. Modify the titles of both files.

  1. In the firstcup project, double-click greeting.xhtml under Web Pages.
  2. Replace the current <html> tag with the following, which includes the components tag library:
    <html xmlns="http://www.w3.org/1999/xhtml"
          xmlns:h="http://java.sun.com/jsf/html"
          xmlns:fc="http://java.sun.com/jsf/composite/components">

    The components resource library is referred to by the fc prefix. The HTML Render Kit tag library is also used in greeting.xhtml.

  3. Modify the title directly after the <html> tag.
    <h:head>
        <title>First Cup Greeting Page</title>
    </h:head>
  4. From the File menu, choose Save.
  5. Double-click response.xhtml and modify the title as follows:
    <h:head>
        <title>Response Page</title>
    </h:head>
  6. From the File menu, choose Save.

Add the Form to greeting.xhtml

Add the form that provides the user interface for displaying Duke's age and specifying the user's birthday.

  1. In the firstcup project, in greeting.xhtml, replace the text between the <h:body> and </h:body> tags with the following:
    <h:form>
        <h2>
            <h:outputText value="#{bundle.Welcome}"/>
        </h2>
        <h:outputText value="#{bundle.DukeIs} "/>
        <h:outputText value="#{DukesBDay.age} #{bundle.YearsOldToday}"/>
        <p/>
        <h:outputText value="#{bundle.Instructions}"/>
        <p/>
        <h:outputText value="#{bundle.YourBD} "/>
        <fc:inputDate id="userBirthday" date="#{DukesBDay.yourBD}" />
        <h:outputText value=" #{bundle.Pattern}"/>
        <p/>
        <h:commandButton value="#{bundle.Submit}" 
                         action="#{DukesBDay.processBirthday}"/>
        <p/>
        <h:message for="userBirthday" style="color:red"/>
    </h:form>
  2. Right-click in the editor window and select Format.
  3. From the File menu, choose Save.

Add the Form to response.html

Add a form that displays the age difference between Duke and the user, displays the average age difference of all users, and allows the user to navigate back to greeting.xhtml.

  1. In the firstcup project, in response.xhtml, replace the text between the <h:body> and </h:body> tags with the following:
    <h:form>
        <h:outputText value="#{bundle.YouAre} "/>
        <h:outputText value="#{bundle.SameAge}"
                      rendered="#{DukesBDay.ageDiff == 0}"/>
        <h:outputText value="#{DukesBDay.absAgeDiff}"
                      rendered="#{DukesBDay.ageDiff lt 0}"/>
        <h:outputText value=" #{bundle.Year} "
                      rendered="#{DukesBDay.ageDiff == -1}"/>
        <h:outputText value=" #{bundle.Years} "
                      rendered="#{DukesBDay.ageDiff lt -1}"/>
        <h:outputText value="#{bundle.Younger}"
                      rendered="#{DukesBDay.ageDiff lt 0}"/>
        <h:outputText value="#{DukesBDay.absAgeDiff}"
                      rendered="#{DukesBDay.ageDiff gt 0}"/>
        <h:outputText value=" #{bundle.Year} "
                      rendered="#{DukesBDay.ageDiff == 1}"/>
        <h:outputText value=" #{bundle.Years} "
                      rendered="#{DukesBDay.ageDiff gt 1}"/>
        <h:outputText value="#{bundle.Older}" 
                      rendered="#{DukesBDay.ageDiff gt 0}"/>
        <p/>
        <h:outputText 
            value="#{bundle.AverageAge} #{DukesBDay.averageAgeDifference}." />
        <p/>
        <h:commandButton id="back" value="#{bundle.Back}" action="greeting"/>
    </h:form>
  2. Right-click in the editor window and select Format.
  3. From the File menu, choose Save.