Thursday Oct 23, 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

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

Friday Oct 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

Tuesday Oct 14, 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

Monday Oct 13, 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

Sunday Sep 21, 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

Tuesday Sep 16, 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

Tuesday Aug 19, 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

Wednesday Jul 23, 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
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