Chapter: Internet & World Wide Web HOW TO PROGRAM - Rich Internet Application Server Technologies - Ajax-Enabled JavaServer Faces Web Applications

| Study Material, Lecturing Notes, Assignment, Reference, Wiki description explanation, brief detail |

Google Maps Map Viewer Component

When the user clicks this Button, the name in the AutoComplete Text Field is used to search the AddressBook database. We also add a Map Viewer Ajax-enabled JSF compo-nent to the page to display a map of the area for the address.

Google Maps Map Viewer Component

We now complete the AddressBook application by adding functionality to the Look Up Button. When the user clicks this Button, the name in the AutoComplete Text Field is used to search the AddressBook database. We also add a Map Viewer Ajax-enabled JSF compo-nent to the page to display a map of the area for the address. A Map Viewer uses the Google Maps API web service to find and display maps. (The details of web services are covered in Chapter 28.) In this example, using the Google Maps API is analogous to making or-dinary method calls on a Map Viewer object and its supporting bean in the page bean file. When a contact is found, we display a map of the neighborhood with a Map Marker that points to the location and indicates the contact’s name and address.


1. Obtaining a Google Maps API Key


To use the Map Viewer component, you must have an account with Google. Visit the site to register for a free account if you do not have one. Once you have logged in to your account, you must obtain a key to use the Google Maps API from The key you receive will be spe-cific to this web application and will limit the number of maps the application can display per day. When you sign up for the key, you will be asked to enter the URL for the appli-cation that will be using the Google Maps API. If you are deploying the application only on Sun Java System Application Server, enter  http://localhost:8080/ as the URL.


After you accept Google’s terms and conditions, you’ll be redirected to a page con-taining your new Google Maps API key. Save this key in a text file in a convenient location for future reference.


2. Adding a Map Viewer Component to a Page


Now that you have a key to use the Google Maps API, you are ready to complete the AddressBook application. With AddressBook.jsp open in Design mode, add a Map Viewer component named mapViewer below the nameAutoComplete. In the Properties window, set the Map Viewer’s key property to the key you obtained for accessing the Google Maps API. Set the rendered property to false so that the map will not be displayed when the user has not yet searched for an address. Set the zoomLevel property to 1 (In) so the user can see the street names on the map.


Drop a Map Marker (named mapMarker) from the BluePrints AJAX Support Beans sec-tion of the Palette anywhere on the page. This component (which is not visible in Design view) marks the contact’s location on the map. You must bind the marker to the map so that the marker will display on the map. To do so, right click the Map Viewer in the Outline tab and choose Property Bindings… to display the Property Bindings dialog. Select info from the Select bindable property column of the dialog, then select mapMarker from the Select binding target column. Click Apply, then Close.


Finally, drop a Geocoding Service Object (named geoCoder) from the BluePrints AJAX Support Beans section of the Palette anywhere on the page. This object (which is not visible in Design view) converts street addresses into latitudes and longitudes that the Map Viewer component uses to display an appropriate map.

Adding a Data Provider to the Page

To complete this application, you need a second data provider to search the AddressBook database based on the first and last name entered in the AutoComplete Text Field. We want to create a new data source rather than reuse the existing one, because the query to search for contacts is different from the query to display all the contacts. On the Runtime tab, expand the Databases node, the AddressBook database’s node and its Tables node to reveal the Addresses table. Drag the Addresses table onto the page to create the new data pro-vider. Select the new data provider in the Navigator tab and change its id to addresses-SearchDataProvider. In the Outline tab, a new node named addressesRowSet1 has been added to the SessionBean1 node. Change the id of addressesRowSet1 to addresses-SearchRowSet.


Double click the addressesSearchRowSet node to edit the SQL statement for this RowSet. Since we will use this row set to search the database for a given last and first name, we need to add search parameters to the SELECT statement the RowSet will execute. To do this, enter the text "= ?" in the Criteria column of both the first and last name rows in the SQL statement editor table. The number 1 should appear in the Order column for first name and 2 should appear for last name. Notice that the lines






have been added to the SQL statement. This indicates that the RowSet now executes a pa-rameterized SQL statement. The parameters can be set programmatically, with the first name as the first parameter and the last name as the second.


3. JSP File with a Map Viewer Component


Figure 27.14 presents the JSP file for the completed address-book application. It is nearly identical to the JSP for the previous two versions of this application. The new feature is the Map Viewer component (and its supporting components) used to display a map with the contact’s location. We discuss only the new elements of this file. [Note: This code will not run until you have specified your own Google Maps key in lines 165–166. You can paste your key into the Map Viewer component’s key property in the Properties window.]


Lines 162–168 define the mapViewer component that displays a map of the area sur-rounding the address. The component’s center attribute is bound to the page bean prop-erty mapViewer_center. This property is manipulated in the page bean file to center the map on the desired address.


76  <?xml version="1.0" encoding="UTF-8"?>


77  <!-- Fig. 27.14: AddressBook.jsp -->


78  <!-- AddressBook JSP with an add form and a Table JSF component. -->


80  <jsp:root version="1.2"


81        xmlns:bp=""


82        xmlns:f=""


83        xmlns:h=""


84        xmlns:jsp=""


85          xmlns:webuijsf="">


86          < contentType="text/html;charset=UTF-8"


87                 pageEncoding="UTF-8"/>


88          <f:view>


89          <webuijsf:page binding="#{AddressBook.page1}" id="page1">


<webuijsf:html binding="#{AddressBook.html1}" id="html1">

16        <webuijsf:head binding="#{AddressBook.head1}" id="head1">   

17        <webuijsf:link binding="#{AddressBook.link1}" id="link1"

18        url="/resources/stylesheet.css"/>        

19        </webuijsf:head>       

20        <webuijsf:body binding="#{AddressBook.body1}" id="body1"    

21        style="-rave-layout: grid">    

22        <webuijsf:form binding="#{AddressBook.form1}" id="form1"

23        virtualFormsConfig="addForm | zipTextField lnameTextField

24        fnameTextField streetTextField cityTextField stateTextField

25        | submitButton , searchForm | nameAutoComplete | 

26        lookUpButton">        

27        <webuijsf:staticText binding=           

28        "#{AddressBook.staticText1}" id="staticText1" style=

29        "font-size: 18px; left: 24px; top: 24px; position:

30        absolute" text="Add a contact to the address book:"/>

31        <webuijsf:label binding="#{AddressBook.fnameLabel}"    

32        for="fnameTextField" id="fnameLabel" style="position:

33        absolute; left: 24px; top: 72px" text="First name:"/>

34        <webuijsf:textField binding="#{AddressBook.fnameTextField}"

35        id="fnameTextField" maxLength="30" required="true"

36        style="left: 100px; top: 72px; position: absolute;

37        width: 192px"/>         

38        <webuijsf:label binding="#{AddressBook.lnameLabel}"    

39        for="lnameTextField" id="lnameLabel" style="left: 312px;

40        top: 72px; position: absolute" text="Last name:"/>

41        <webuijsf:textField binding="#{AddressBook.lnameTextField}"

42        id="lnameTextField" maxLength="30" required="true"

43        style="left: 390px; top: 72px; position: absolute;

44        width: 214px"/>         

45        <webuijsf:label binding="#{AddressBook.streetLabel}"

46        for="streetTextField" id="streetLabel" style="position:

47        absolute; left: 24px; top: 96px" text="Street:"/>

48        <webuijsf:textField binding=

49        "#{AddressBook.streetTextField}" id="streetTextField"

50        maxLength="150" required="true" style="left: 100px;

51        top: 96px; position: absolute; width: 504px"/>          

52        <webuijsf:label binding="#{AddressBook.cityLabel}"        

53        for="cityTextField" id="cityLabel" style="left: 24px;

54        top: 120px; position: absolute" text="City:"/>           

55        <webuijsf:textField binding="#{AddressBook.cityTextField}"

56        id="cityTextField" maxLength="30" required="true"

57        style="left: 100px; top: 120px; position: absolute;

58        width: 240px"/>         

59        <webuijsf:label binding="#{AddressBook.stateLabel}"      

60        for="stateTextField" id="stateLabel"

61        style="left: 360px; top: 120px; position: absolute"

62        text="State:"/>           

63        <webuijsf:textField binding="#{AddressBook.stateTextField}"

64        id="stateTextField" maxLength="2" required="true"

65        style="left: 412px; top: 120px; position: absolute;

66        width: 48px"/>           

67        <webuijsf:label binding="#{AddressBook.zipLabel}"         

68        for="zipTextField" id="zipLabel" style="left: 490px;

69        top: 120px; position: absolute" text="Zip:"/>

70        <webuijsf:textField binding="#{AddressBook.zipTextField}"

71        id="zipTextField" maxLength="5" required="true"

72        style="left: 534px; top: 120px; position: absolute;

73        width: 70px"/>

74        <webuijsf:button actionExpression=

75        "#{AddressBook.submitButton_action}" binding=

76        "#{AddressBook.submitButton}" id="submitButton"

77        primary="true" style="left: 100px; top: 168px; position:

78        absolute; width: 100px" text="Submit"/>

79        <webuijsf:button binding="#{AddressBook.clearButton}"

80        id="clearButton" reset="true" style="left: 215px; top:

81        168px; position: absolute; width: 100px" text="Clear"/>

82        <webuijsf:messageGroup binding=

83        "#{AddressBook.messageGroup1}" id="messageGroup1"

84        showGlobalOnly="true" style="left: 624px; top: 72px;

85        position: absolute"/>

86        <webuijsf:table augmentTitle="false" binding=

87        "#{AddressBook.addressesTable}" id="addressesTable"

88        paginateButton="true" paginationControls="true"

89        style="left: 24px; top: 216px; position: absolute"

90        title="Contacts" width="816">

91        <webuijsf:tableRowGroup binding=

92        "#{AddressBook.tableRowGroup1}" id="tableRowGroup1"

93        rows="5" sourceData=

94        "#{AddressBook.addressesDataProvider}"

95        sourceVar="currentRow">

96        <webuijsf:tableColumn binding=

97        "#{AddressBook.fnameColumn}"

98        headerText="First Name" id="fnameColumn"

99        sort="ADDRESSES.FIRSTNAME">

100      <webuijsf:staticText binding=

101      "#{AddressBook.staticText2}" id="staticText2"

102      text="#{currentRow.value[


104      </webuijsf:tableColumn>

105      <webuijsf:tableColumn binding=

106      "#{AddressBook.lnameColumn}"

107      headerText="Last Name" id="lnameColumn"

108      sort="ADDRESSES.LASTNAME">

109      <webuijsf:staticText binding=

110      "#{AddressBook.staticText3}" id="staticText3"

111      text="#{currentRow.value[

112      'ADDRESSES.LASTNAME']}"/>

113      </webuijsf:tableColumn>

114      <webuijsf:tableColumn binding=

115      "#{AddressBook.streetColumn}" headerText="Street"

116      id="streetColumn" sort="ADDRESSES.STREET">

117      <webuijsf:staticText binding=

118      "#{AddressBook.staticText4}" id="staticText4"

119      text="#{currentRow.value[

120      'ADDRESSES.STREET']}"/>

121      </webuijsf:tableColumn>

122                  <webuijsf:tableColumn binding=                  

123                  "#{AddressBook.cityColumn}" headerText="City"

124                  id="cityColumn" sort="ADDRESSES.CITY">                   

125                  <webuijsf:staticText binding=                       

126                  "#{AddressBook.staticText5}" id="staticText5"

127                  text="#{currentRow.value['ADDRESSES.CITY']}"/>

128                  </webuijsf:tableColumn>                  

129                  <webuijsf:tableColumn binding=                  

130                  "#{AddressBook.stateColumn}" headerText="State"

131                  id="stateColumn" sort="ADDRESSES.STATE">               

132                  <webuijsf:staticText binding=                       

133                  "#{AddressBook.staticText6}" id="staticText6"

134                  text="#{currentRow.value['ADDRESSES.STATE']}"/>

135                  </webuijsf:tableColumn>                  

136                  <webuijsf:tableColumn binding=                  

137                  "#{AddressBook.zipColumn}" headerText="Zip"

138                  id="zipColumn" sort="ADDRESSES.ZIP" width="106">

139                  <webuijsf:staticText binding=                       

140                  "#{AddressBook.staticText7}" id="staticText7"

141                  text="#{currentRow.value['ADDRESSES.ZIP']}"/>

142                  </webuijsf:tableColumn>                  

143                  </webuijsf:tableRowGroup>             

144      </webuijsf:table>                   

145      <webuijsf:staticText binding="#{AddressBook.searchHeader}"

146                  id="searchHeader" style="font-size: 18px; left: 24px;

147                  top: 420px; position: absolute"                      

148                  text="Search the address book by last name:"/>                   

149      <bp:autoComplete binding=              

150                  "#{AddressBook.nameAutoComplete}" completionMethod=

151                  "#{AddressBook.nameAutoComplete_complete}"              

152                  id="nameAutoComplete"                  

153                  style="left: 96px; top: 444px; position: absolute"/>

154      <webuijsf:label binding="#{AddressBook.label1}"             

155                  for="nameAutoComplete" id="label1" style="left: 24px;

156                  top: 447px; position: absolute" text="Last name:"/>

157      <webuijsf:button actionExpression=             

158                  "#{AddressBook.lookUpButton_action}"                

159                  binding="#{AddressBook.lookUpButton}" id="lookUpButton"

160                  style="left: 288px; top: 446px; position: absolute;

161                  width: 100px" text="Look Up"/>                  

162                  <bp:mapViewer binding="#{AddressBook.mapViewer}"               

163                  center="#{AddressBook.mapViewer_center}"                     

164                  id="mapViewer" info="#{AddressBook.mapMarker}"                    


166                  XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"                      

167                  style="height: 550px; left: 24px; top: 480px;            

168                  position: absolute; width: 814px" zoomLevel="4"/>

169      </webuijsf:form>


170      </webuijsf:body>


171      </webuijsf:html>


172      </webuijsf:page>


173      </f:view>


174      </jsp:root>


Fig. 27.14 | AddressBook JSP with a Map Viewer component.


The Look Up Button’s action attribute is now bound to method lookUpButton_action in the page bean (lines 157–158). This action handler searches the AddressBook database for the name entered in the AutoComplete Text Field and displays the contact’s name and address on a map of the contact’s location. We discuss this method in Section 27.5.4.


4. Page Bean That Displays a Map in the Map Viewer Component


Figure 27.15 presents the page bean for the completed AddressBook application. Most of this file is identical to the page beans for the first two versions of this application. We dis-cuss only the new action-handler method, lookUpButton_action.


94  // Fig. 27.15:


95  // Page bean for AddressBook.jsp.


96  package addressbook;


102   import;


103   import;


109     import com.sun.j2ee.blueprints.ui.autocomplete.AutoCompleteComponent;


110     import com.sun.j2ee.blueprints.ui.autocomplete.CompletionResult;


111     import com.sun.j2ee.blueprints.ui.geocoder.GeoCoder;


112 import com.sun.j2ee.blueprints.ui.geocoder.GeoPoint;


113 import com.sun.j2ee.blueprints.ui.mapviewer.MapComponent;


114 import com.sun.j2ee.blueprints.ui.mapviewer.MapMarker;


115 import com.sun.j2ee.blueprints.ui.mapviewer.MapPoint;


116 import com.sun.rave.web.ui.appbase.AbstractPageBean;


117 import com.sun.webui.jsf.component.Body;


118 import com.sun.webui.jsf.component.Button;


119 import com.sun.webui.jsf.component.Form;


120 import com.sun.webui.jsf.component.Head;


121 import com.sun.webui.jsf.component.Html;


122 import com.sun.webui.jsf.component.Label;


123 import com.sun.webui.jsf.component.Link;


124 import com.sun.webui.jsf.component.MessageGroup;


125 import com.sun.webui.jsf.component.Page;


126 import com.sun.webui.jsf.component.StaticText;


127 import com.sun.webui.jsf.component.Table;


128 import com.sun.webui.jsf.component.TableColumn;


129 import com.sun.webui.jsf.component.TableRowGroup;


130 import com.sun.webui.jsf.component.TextField;


131 import javax.faces.FacesException;


132 import javax.faces.context.FacesContext;


116 public class AddressBook extends AbstractPageBean

117 {


118       private int __placeholder;


123       private void _init() throws Exception

124       {


125              addressesDataProvider.setCachedRowSet(


126                    ( javax.sql.rowset.CachedRowSet ) getValue(


127                    "#{SessionBean1.addressesRowSet}" ) );


128              addressesTable.setInternalVirtualForm( true );


129              mapViewer.setRendered( false );


130              addressesSearchDataProvider.setCachedRowSet(


131                    ( javax.sql.rowset.CachedRowSet ) getValue(


132                    "#{SessionBean1.addressesSearchRowSet}" ) );


133       } // end method _init


1             // To save space, we omitted the code in lines 48-741. The complete


2             // source code is provided with this chapter's examples.


5             // action handler for the lookUpButton that searches the address book


6             // database and displays the requested address on a corresponding map.


7             public String lookUpButton_action()

8             {


9                    // split text in autocomplete field into first and last name


10                 String name = String.valueOf( nameAutoComplete.getValue() );


11                 int splitIndex = name.indexOf( "," );


12                 String lname = name.substring( 0, splitIndex );


String fname = name.substring( splitIndex + 2 );


19                  try

20                  {


21                        // set the parameters for the addressesSearchDataProvider


22                        addressesSearchDataProvider.getCachedRowSet().setObject(

23                              1, fname );


24                        addressesSearchDataProvider.getCachedRowSet().setObject(

25                              2, lname );


26                        addressesSearchDataProvider.refresh();


27                        String street = (String) addressesSearchDataProvider.getValue(


28                              "ADDRESSES.STREET" );


29                        String city = (String) addressesSearchDataProvider.getValue(


30                              "ADDRESSES.CITY" );


31                        String state = (String) addressesSearchDataProvider.getValue(


32                              "ADDRESSES.STATE" );


33                        String zip =  (String) addressesSearchDataProvider.getValue(


34                              "ADDRESSES.ZIP" );


31                        // format the address for Google Maps


32                        String googleAddress = street + ", " + city + ", " + state +

33                              " " + zip;


1                           // get the geopoints for the address


2                           GeoPoint points[] = geoCoder.geoCode( googleAddress );


12                        // if Google Maps cannot find the address

13                        if ( points == null )

14                        {


15                              error( "Map for " + googleAddress + " could not be found" );


16                              mapViewer.setRendered( false ); // hide map


17                              return null;

18                        } // end if


1                           // center the map for the given address


2                           mapViewer_center.setLatitude( points[0].getLatitude() );


3                           mapViewer_center.setLongitude( points[0].getLongitude() );


1                           // create a marker for the address and set its display text


2                           mapMarker.setLatitude( points[0].getLatitude() );


3                           mapMarker.setLongitude( points[0].getLongitude() );


4                           mapMarker.setMarkup(  fname + " " + lname + "<br/>" + street +


5                                 "<br/>" + city + ", " + state + " " + zip );


424                     mapViewer.setRendered( true ); // show map

425               } // end try


426               catch ( Exception e )

427               {


428                     error( "Error processing search. " + e.getMessage() );


429               } // end catch


431               return null;


432        } // end method lookUpButton_action


433  } // end class AddressBook


Fig. 27.15 | Page bean that gets a map to display in the Map Viewer component.

Method lookUpButton_action (lines 744–802) is invoked when the user clicks the Look Up button in the lower form on the page. Lines 747–750 retrieve the name from the AutoComplete Text Field and split it into Strings for the first and last name. Lines 755–758 obtain the addressesSearchDataProvider’s CachedRowSet, then use its method setObject to set the parameters for the query to the first and last name. The setObject method replaces a parameter in the SQL query with a specified string. Line 759 refreshes the data provider, which executes the wrapped RowSet’s query with the new parameters. The result set now contains only rows that match the first and last name from the Auto-Complete Text Field. Lines 760–767 fetch the street address, city, state and zip code for this contact from the database. Note that in this example, we assume there are not multiple entries in the address book for the same first and last name, as we fetch only the address information for the first row in the data provider. Any additional rows that match the first and last name are ignored.

Lines 770–771 format the address as a String for use with the Google Maps API. Line 774 calls the Geocoding Service Object’s geoCode method with the address as an argu-ment. This method returns an array of GeoPoint objects representing locations that match the address parameter. GeoPoint objects provide the latitude and longitude of a given loca-tion. We supply a complete address with a street, city, state and zip code as an argument to geoCode, so the returned array will contain just one GeoPoint object. Line 777 deter-mines whether the array of GeoPoint objects is null. If so, the address could not be found, and lines 779–781 display a message in the Message Group informing the user of the search error, hide the Map Viewer and return null to terminate the processing.


Lines 785–786 set the latitude and longitude of the Map Viewer’s center to those of the GeoPoint that represents the selected address. Lines 789–792 set the Map Marker’s lat-itude and longitude, and set the text to display on the marker. Line 794 displays the recen-tered map containing the Map Marker that indicates the contact’s location.


Lines 796–799 catch any exceptions generated throughout the method body and dis-play an error message in the Message Group. If the user has simply selected a name from the list of selections in the AutoComplete Text Field, there will be no errors in searching the database, as the name is guaranteed to be in the proper last name, first name format and included in the AddressBook database. We did not include any special error-handling code for cases in which the user types a name that cannot be found in the AddressBook or for improperly formatted names.

Study Material, Lecturing Notes, Assignment, Reference, Wiki description explanation, brief detail

Copyright © 2018-2020; All Rights Reserved. Developed by Therithal info, Chennai.