Creating an Ajax-Enabled Application, a Component Approach

   
By Rick Palkovic and Mark Basler, October 2006  

Articles Index

This is the third in a short series of articles that adds Ajax functionality to a Java EE web application developed in the NetBeans IDE.

The Java EE platform includes JavaServer Faces technology. JavaServer Faces technology provides standard components that you can extend to create your own custom components, which you can then reuse in different applications. Along with the custom component, you also create a custom renderer and a custom tag to associate the component with the renderer and to reference the component from the page.

Learn About Ajax

For background information about Ajax and strategies for implementation, see Ajax Design Strategies by Ed Ort and Mark Basler.
 

When you create the JavaServer Faces custom component in this approach, you package the resources required by the component directly with the application bundle. The custom component generates the JavaScript code needed to handle Ajax interactions with the server. To fulfill the Ajax request, you use the same Java Servlet that was used in the do-it-yourself method. This approach uses the JavaServer Faces framework only as a rendering mechanism, ignoring most of the power of JavaServer Faces technology. For convenience in this article, this component-servlet approach is CompA.

A second JavaServer Faces component approach, for convenience CompB, uses a phase listener to serve the component's static resources. As an option, you can use the phase listener to intercept and fulfill the client component's Ajax requests. The phase listener can delegate responsibility to a managed bean's method or again use the legacy servlet. The client component's resources, such as the JavaScript file and CSS, are accessed through the phase listener. The phase listener approach takes advantage of more of the power of JavaServer Faces technology, and is described in the final article in this Ajax series, Creating an Ajax-Enabled Application, a Phase Listener Approach.

The CompA approach can be appropriate in the following cases:

  • When you use a legacy application that isn't currently based on JavaServer Faces technology, you can use this approach because any data that might be affected by the Ajax call is managed by a legacy mechanism. Because server-side data is not directly affected by adopting the new technology, risk to an existing production application is limited.
  • When the Ajax call doesn't affect the JavaServer Faces view state that is associated with a web page.
  • When you aren't willing to pay the performance price of saving, transferring, and restoring component view state with each Ajax call. Such cases arise when an Ajax XMLHttpRequest call is used to perform polling action, for example.
  • When the Ajax call retrieves read-only data from the server.

The CompA approach also has its shortcomings, namely:

  • The component isn't designed to manage the JavaServer Faces view state. Problems arise when the Ajax call modifies state while the state is also maintained on the client in the serialized view. The serialized view state is reconstituted when a JavaServer Faces form or action is submitted.
  • It requires that the resources be packaged with the web application, so the deployment descriptors might also need to be updated.
  • It introduces the possibility of a name conflict when using multiple components on a single page. This problem can be avoided by maintaining a well-defined namespace for your components.
  • Components created for this approach typically aren't suitable for a commercial component library.

Weighing the advantages and shortcomings of the CompA approach, it could be a sensible way to introduce JavaServer Faces and Ajax technologies into your application.

 
Contents
 
Information Flow in the CompA Approach
Getting Started
Implementing a Component Approach
Tag Library
The JavaServer Faces Config File
The CompATag Tag Class
Page Lifecycle
The compA.css Style Sheet
The compA.js File
The Dispatcher Class
Building and Deploying the Application
Summary
Next Steps
References
 
Information Flow in the CompA Approach

This section summarizes the life cycle of the book catalog page and the Ajax-created pop-up balloon. The terminology and file names in the explanations are explained in more detail later in this article. If they are unfamiliar, review this section again after you have read the entire article.

 

Rendering the Book Catalog Page


The following figure shows the life cycle of the book catalog page, beginning with the user's click on the catalog link.

Figure 1: Book Catalog Page Flow



The following steps explain the architecture illustrated in the figure:

  1. The user clicks a link for the book catalog page.
  2. On the basis of the URLs defined in the web deployment descriptor the server routes the page request to Dispatcher servlet.
  3. The Dispatcher servlet accepts the /books/bookcatalog URL, prefixes it with /faces and suffixes it with .jsp, mapping the URL to a JSP page. The Dispatcher then forwards the request through the RequestDispatcher.
  4. The JavaServer Faces framework, directed by instructions in the web.xml file, sends the JSP page identified by the URL to the FacesServlet.
  5. Through the FacesServlet, the JavaServer Faces framework identifies the CompA component by its tag and routes the page (along with the component it contains) to the CompATag tag class.
  6. The CompATag class extracts properties from the tag's attributes and populates the properties of the component. It then maps the component to a renderer type that is registered in faces-config.xml, and sends the request to the renderer for further processing.
  7. The renderer outputs the component's markup and returns control to the JavaServer Faces framework so that the next tag in the JSP page can be interpreted. After this process completes successfully, the book catalog page is ready for the user to mouse over a book link that displays a pop-up balloon.

 

Rendering the Pop-up Balloon


The following figure shows the Ajax life cycle of the pop-up balloon, produced when the user mouses over a link on the book catalog page.

Figure 2: Ajax Component Flow


  1. The user mouses over a link on the book catalog page, executing the onmouseover event handler.
  2. The onmouseover event handler calls the bpui.compA.showPopup() function in the compA.js file. This function sends a request to the CompAServlet through the XMLHttpRequest object.
  3. The CompAServlet receives the request and, using the existing BookDBA object, obtains the book title detail data and formats a response to the request.
  4. CompAServlet then returns an XML response that holds the book detail.
  5. The component-specific ajaxReturnFunction() is called when the response is returned from the CompAServlet. The ajaxReturnFunction() then extracts book detail data from the XML message, populates the pop-up balloon's table, and makes the balloon visible to the user.

Getting Started

This article assumes that you have downloaded and installed the latest NetBeans IDE and the example application that forms the basis of discussion. If you have not done so, refer to the first article in the series, Creating an Ajax-Enabled Application, a Do-It-Yourself Approach, and download the necessary tools now.

Note that the example project already contains files for all four implementation approaches in addition to the original application:

  • The base application, with no Ajax implementation
  • The do-it-yourself approach to Ajax
  • A toolkit approach to Ajax, using the Dojo toolkit
  • The CompA approach that is the topic of this article
  • The CompB phase listener approach

Implementing a Component Approach

In this, your first implementation of a JavaServer Faces component, you create a component with resources accessed directly from the web application. The component itself is bundled with the web application.

 

Opening the Bookstore Project in the NetBeans IDE


To see how the component is implemented, begin by opening the bookcatalog.jsp file in the NetBeans IDE. If the bookstore2 project is already open in the NetBeans IDE from your exercise in the last article, Creating an Ajax-Enabled Application, a Toolkit Approach, skip these steps and go directly to the next section.

To open the project:

  1. Start the NetBeans IDE.
  2. From the NetBeans toolbar, choose File > Open. The Open Project window opens.
  3. Navigate to project /examples/web/bookstore2, where project is the path to your project directory.
  4. Select the bookstore2 project folder and click Open Project Folder. The IDE opens the project folder and selects bookstore2 as the main project. The bookstore project is also opened because bookstore2 depends on many of the files in bookstore.
  5. If the IDE flags the bookstore project and alerts you that references need to be resolved:

    1. Right-click the project and choose Resolve Reference Problems from the contextual menu.
    2. In the resulting window, click Resolve and navigate to the server /glassfish/lib directory, where server is the root of your GlassFish server installation.
    3. Select the javaee.jar file and open it. Click Close to resolve the reference and close the window.
  6. If the bookstore2 project also produces an alert:

    1. Right-click the project name and choose Resolve Missing Server Problem from the contextual menu.
    2. In the resulting window, select the GlassFish server that you registered in Creating an Ajax-Enabled Application, a Do-It-Yourself Approach. Click OK to resolve the reference.

 

Replacing the bookcatalog.jsp File


Instead of editing the existing bookcatalog.jsp file, replace it with the bookcatalog_compA.jsp file already present in the project.

  1. In the NetBeans IDE, click the Projects tab to open the Projects view of your project.
  2. Expand the bookstore2 > Web Pages > books node and select the bookcatalog.jsp file.
  3. Right-click and choose Delete from the contextual menu. In the confirmation pop-up window, click Yes.
  4. Select the bookcatalog_compA.jsp file, right-click, and choose Copy from the contextual menu.
  5. Select the books node, right-click, and choose Paste from the contextual menu. A copy of the bookcatalog_compA.jsp file appears in the list.
  6. Select the copy of the bookcatalog_compA.jsp file, right-click, and choose Rename from the contextual menu. Rename the file to bookcatalog.jsp to make it part of the project build
  7. Double-click the bookcatalog.jsp file to open it in the NetBeans Editor.

 

Examining the bookcatalog.jsp File


To follow the discussion of the bookcatalog.jsp file, make sure line numbers are displayed in the NetBeans Editor. To display line numbers, right-click in the left margin of the Editor window and choose Show Line Numbers from the contextual menu.

Figure 3: Showing Numbers in Editor


On your first view of the file, note that the code is much simpler than either the do-it-yourself version from Creating an Ajax-Enabled Application, a Do-It-Yourself Approach or the toolkit version from Creating an Ajax-Enabled Application, a Toolkit Approach. The file is half the size of the do-it-yourself version.

Lines 32–39 in the file initialize the JavaServer Faces core tag library (taglib). They set the tag prefix to f and the JavaServer Faces component tag prefix to bpui for the custom taglib <bpui:compA>.

Lines 36–38, shown below, provide the necessary view tags.

<!-- BEGIN: popup -->
                  

<%@taglib uri="/jsf/core" prefix="f" %>
                  

<%@taglib prefix="bpui" uri="#" %>
                  

                   

<f:view>
                  

    <bpui:compA id="pop0" url="./PopupServlet?bookId="/>
                  

</f:view>
                  

<!-- END: popup -->

                



The <f:view> tag is used to encapsulate all the JavaServer Faces components so the FacesServlet (discussed later) operates on them in the page. Without the view tags, a JavaServer Faces context would be created but wouldn't have an object in the component tree to render.

The <bpui:compA> tag has associated attributes id and url. The id attribute is the pop-up balloon object name. The url attribute locates the services that respond to the Ajax request.

Recall that in the do-it-yourself version described in Creating an Ajax-Enabled Application, a Do-It-Yourself Approach, you hard-coded the URL in a JavaScript file. To use that implementation in another application, the URL would have to be changed in many places. Because the component approach encapsulates code for easy reuse, the URL is declared as part of the component tag's attributes in the JSP file rather than in JavaScript code.

Moreover, because the do-it-yourself approach can't distinguish multiple components, the number of pop-up balloons on a page is limited to one at a time. A properly architected component approach lets you use any number of pop-up balloons simultaneously. For example, you could have two compA components, each identified by a different id that is specified in the component's <bpui:compA> tag, each referencing a different URL. One component could use the URL of the pop-up servlet on your server, while another component could use a URL that fulfills the Ajax request in a different way.

Scroll down in the bookcatalog.jsp file and view the event handlers on lines 76–77:

onmouseover="bpui.compA.showPopup('pop0', event, '${bookId}')"
                  

onmouseout="bpui.compA.hidePopup('pop0')"
                



These lines are similar to previous versions of the onmouseover and onmouseout event handlers. In this case, though, they pass the id attribute of the pop-up object pop0 to the showPopup() and hidePopup() functions. Recall that in line 37 the value for the id attribute of the <bpui:compA> tag was defined as pop0. In addition to the pop-up id attribute, the showPopup() function is also passed the event and bookId attributes. The bookId parameter is used to obtain information about a specific book, while the event parameter denotes either an onmouseover or onmouseout event.

The showPopup() and hidePopup() functions are restricted to the bpui.compA namespace to avoid naming conflicts. To use more than one pop-up component on the page, you would provide separate id attributes for each component in a bpui:compA tag, then use the showPopup() and hidePopup() functions to identify which to hide and which to show.

In summary, in this component version of the project, the only changes necessary in the bookcatalog.jsp file are to declare the taglib, reference the component's tag, and provide a server-side component to fulfill the Ajax request. These changes provide the side benefit of allowing you to show more than one component on a page.

Tag Library

Now, examine your project's tag library descriptor ( .tld) file. Open the file in the NetBeans Editor:

  1. In the Projects window of the NetBeans IDE, expand the bookstore2 > Web Pages > WEB-INF node.
  2. Double click the ui.tld file to open it in the NetBeans Editor.

In the ui.tld file, you see that tags for CompA lie between lines 14 and 67.

Recall line 35 from bookcatalog.jsp:

                    <%@taglib prefix="bpui" uri="#"%>
                



For the application server, this line maps to the URI used for the user interface in line 8 of the ui.tld file:

                    <uri>#</uri>
                



In line 15 of the ui.tld file, you see the definition of the <name> tag:

                    <name>compA</name>

                



The name defined in line 15 is used with the taglib namespace prefix bpui in the bookcatalog.jsp file, as, for example, in line 38 from that file:

                    <bpui:compA id="pop0" url="./PopupServlet?bookId="/>
                



The bpui:compA tag maps to the tag class defined in line 16 of the ui.tld file:

                    <tag-class>com.sun.javaee.blueprints.components.ui.example.CompATag</tag-class>
                



Line 17 describes the compA tag as scriptless, which means there will be no scripting between the opening and closing tags:

                    <body-content>scriptless</body-content>
                



Take special note of the id attribute in the definition of compA (line 19). Recall how this attribute is used in the onmouseover and onmouseout event handlers in bookcatalog.jsp. When passed as a parameter to the showPopup() and hidePopup() JavaScript functions, it references a unique pop-up component. The id attribute is also used for other component-specific calls. By referencing components by id, the functions can allow more than one pop-up component to be used per page.

The style and styleClass attributes (lines 43 and 54) are defined to allow the component to override any styles that might be defined for the page elsewhere.

The JavaServer Faces Configuration File

The CompA component also has an important JavaServer Faces configuration file called faces-config.xml, which is in the same directory as ui.tld. Double-click faces-config.xml in the NetBeans Projects window to view the file in the NetBeans Editor.

CompA uses a standard JavaServer Faces output component ( javax.faces.Output) with a custom renderer that is specified in lines 12–24, shown below. The component-family and the renderer-type are mapped to the return of the CompATag methods getComponentType() and getRendererType(), respectively.

<!-- BEGIN configuration for CompA component -->
<!-- Handle requests for script file resource. Will serve script.js. -->

  <render-kit>
                  

    <renderer>
        <description>
            Renderer for CompA popup
        </description>
        <component-family>javax.faces.Output</component-family>

        <renderer-type>CompA</renderer-type>
        <renderer-class>
            com.sun.javaee.blueprints.components.ui.example.CompARenderer
        </renderer-class>
    </renderer>
</render-kit>

<!-- END configuration for CompA component -->
                



Line 20 names the renderer:

                    <renderer-type>CompA</renderer-type>
                



In line 21, the renderer is referenced to the CompARenderer class:

<renderer-class>
    com.sun.javaee.blueprints.components.ui.example.CompARenderer
</renderer-class>



The CompATag Tag Class

You now examine the CompATag class referenced by the ui.tld file to see how the pop-up component's tag data is used.

  1. In the NetBeans Projects window, expand the following node: bookstore2 > Source Packages > com.sun.javaee.blueprints.components.ui.example.
  2. Double-click the CompATag.java file to open it in the NetBeans Editor.

Figure 4: Opening CompATag.java From the Projects Window




The CompATag class extracts attribute values from the tag, populates the component, and maps to a renderer type that is registered in faces-config.xml.

The setProperties() method, beginning on line 76, extracts the attribute values for style, styleClass, and url. Line 79 of the method extracts the inputs from the tag and puts them into the component itself:

                    UIOutput outComp = (UIOutput)component;
                



Then, through the getRendererType() method (lines 45–47), the JavaServer Faces framework determines which renderer type to call:

public String getRendererType() {
                  

    return ("CompA");
                  

}
                



The tag's getComponentType() and getRendererType() methods perform the important function of mapping the JavaServer Faces object to a specific renderer. Their return values are mapped to the values entered in the faces-config.xml file to determine a specific renderer class to be used to render the component's markup.

 

The CompARenderer Class


To see how the CompARenderer class executes the rendering, you now examine the CompARenderer.java file.

  1. In the NetBeans Projects window, again view the files under the following node: bookstore2 > Source Packages > com.sun.javaee.blueprints.components.ui.example.
  2. Double-click the CompARenderer.java file to open it in the NetBeans Editor.

In the CompARenderer.java file, scroll to lines 34–35 of the CompARenderer class definition:

private static final String COMPA_SCRIPT_RESOURCE="/compA.js";
private static final String COMPA_CSS_RESOURCE="/compA.css";



These lines show that the class uses the script resources of the compA.js and compA.css files. These resources enable the display and style of the HTML markup for the pop-up balloon and help process the information that the balloon displays.

About Components,
Renderers, and Tags


See the discussion in the Java EE 5 Tutorial to learn more about how tags and renderers work with custom components.
 

Scroll to lines 82–103. Here, you see the formatting and content that was hand-coded into the page in the do-it-yourself approach. Now, this information is part of a component and is inserted into the page automatically when the component is rendered.

Scroll down and view lines 146–157. Here, you see that the component also contains references to the JavaScript file ( COMPA_SCRIPT_RESOURCE, which resolves to /compA.js) and the style sheet ( COMPA_CSS_RESOURCE, which resolves to /compA.css).

These classes illustrate the advantage of the JavaServer Faces component approach: after you create the component, you (and other developers) can reuse it easily. All of the resource information is contained in the component. By accessing the CompATag class through the FacesServlet, you eliminate additional programming.

Page Lifecycle

In summary, the CompARenderer class renders the markup code that displays the component in the page. The JavaServer Page is routed through the FacesServlet. Because the page is within the scope of the <f:view> tag, the JavaServer Faces framework recognizes that it must operate on the bpui.CompA tag.

The FacesServlet is included in the libraries that are distributed with the GlassFish application server. The FacesServlet is registered in web.xml, and is part of the Java EE framework. The JavaServer Faces framework identifies the CompA component by its bpui:compA tag and routes the request (along with the component it contains) to the tag class CompATag. There, the setProperties() method extracts properties from the tag's attributes and populates the properties of the component.

The renderer ( CompARenderer) outputs the component's markup and returns control to the the JavaServer Faces framework, so the next tag in the JSP page can be interpreted.

The compA.css Style Sheet

The CSS file for the CompA implementation needs to change only slightly from the do-it-yourself or toolkit approaches. Open the file for viewing in the NetBeans IDE:

  • In the Projects window of your project, expand the bookstore2 > Web Pages node and double-click the compA.css file. The file opens in the NetBeans Editor.

In the file, note that the class selector namespace had been changed from .bpui_alone to .bpui_compA. The namespace ensures a unique name for the styles, eliminating the possibility of inadvertent duplication. The reasoning is the same as that used in the bookcatalog.jsp file, where the name bpui.compA was used to create a separate namespace.

Extending this technique, expand the bookstore2 > Web Pages > images node and note that the images used for the corners of the pop-up balloons have also been given unique names. Best practice dictates that you always create a separate namespace when you design a component to help avoid clashes.

The compA.js File

You now examine the compA.js file. This file, in particular, illustrates the flexibility of the JavaServer Faces approach.

  • In the Files window of your project, expand the bookstore2 > web node and double-click the compA.js file. The file opens in the NetBeans Editor.

In the compA.js file, note that the bpui.compA.showPopup() function (line 9) occupies its own namespace. Otherwise, it is identical to the bpui.alone.showPopup() function in the do-it-yourself version.

The showPopupInternal() function (line 28) is markedly different, however. In line 32–35, this function retrieves the name of the pop-up object to be displayed and constructs the url attribute by concatenating the itemId value to the object's URI property:

                    popObject=bpui.compA[popupx]; … url=popObject.urlx + escape(itemId);
                



In the do-it-yourself and toolkit versions, the pop-up balloon is identified by more explicitly coding its url attribute:

                    url="../PopupServlet?bookId=" + escape(bookId);
                



As these lines reveal, in the do-it-yourself version a change in the name of the pop-up object or its URL requires a change in the JavaScript code. In contrast, the component approach requires you to make these changes only in the tag's attribute values.

In line 9, the identity of the pop-up object is passed into the showPopup() function by the arguments popupx and itemId.

When setting the timeout period for the component (line 24) you identify the component by name and item identifier ( popupx and itemId). These values identify the component that is operated upon.

bpui.compA.timeout=setTimeout(
   "bpui.compA.showPopupInternal('" + popupx + "', '" + itemId + "')", 1000);



Consider line 32 of the compA.js file, in the showPopupInternal() function:

                    popObject=bpui.compA[popupx];
                



Here you see that the function is accessing the bpui.compA[] associative array with the name of the component. The array accounts for situations in which more than one component is present in the page. For example, if the page contained two components named popup0 and popup1, the associative array would contain two objects.

The Dispatcher Class

The Dispatcher class finds known URL patterns, alters them if necessary, and forwards them for further processing.

To understand how the dispatcher does its job, first examine the web.xml file:

  1. In the NetBeans IDE Projects view of your project, expand the bookstore2 > Web Pages > WEB-INF node.
  2. Double-click the web.xml file to open it in the NetBeans Editor.
  3. Because web.xml is an XML file, the IDE tries to interpret it rather than display it. Click the XML button in the NetBeans Editor toolbar to show the file in XML view.

 

Examining the web.xml File


Note lines 35–68 of the file, where URL patterns are mapped to servlets. In these lines, all of the application's pages are mapped to the Dispatcher servlet. Lines 45–48 are typical of this mapping.

In the do-it-yourself and toolkit versions, the pop-up balloon is identified by more explicitly coding its url attribute:

<servlet-mapping>
                  

    <servlet-name>Dispatcher</servlet-name>
                  

    <url-pattern>/books/bookcatalog</url-pattern>
                  

</servlet-mapping>
                



This mapping is a remnant of the legacy coding for the project and presents a barrier to introducing JavaServer Faces technology into the project. If all URLs are routed through the Dispatcher, then JavaServer Faces processing must take place there along with other page processing. A mapping must be added to route JavaServer Faces components to the FacesServlet for processing.

Lines 25–33 set up mapping to the FacesServlet:

Consider line 32 of the compA.js file, in the showPopupInternal() function:

     <servlet>
                  

         <servlet-name>FacesServlet</servlet-name>
                  

         <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
                  

         <load-on-startup>1</load-on-startup>
                  

     </servlet>
                  

     <servlet-mapping>
                  

         <servlet-name>FacesServlet</servlet-name>
                  

         <url-pattern>/faces/*</url-pattern>
                  

     </servlet-mapping>   
                



As a result of this mapping, any URL pattern that begins with /faces/ is sent to the FacesServlet class.

Now, examine the Dispatcher to see how the /faces/ prefix is concatenated to URL patterns.

 

Examining the Dispatcher.java File


Instead of editing the existing Dispatcher.java file, replace it with the Dispatcher.java_compX file already present in the project.

  1. In the NetBeans IDE Projects view of your project, expand the bookstore2 > Source Packages > com.sun.bookstore2.dispatcher node. You see the following files in the dispatcher folder:

                            Dispatcher.java Dispatcher.java_compX Dispatcher.java_orig PopupServlet.java 
                        



    The Dispatcher.java_compX file is used for both CompA and CompB, the the next example in this series.

  2. Select the Dispatcher.java file. Right-click and choose Delete from the contextual menu. In the confirmation pop-up window, click Yes.
  3. Select the Dispatcher.java_compX file, right-click, and choose Copy from the contextual menu.
  4. Select the com.sun.bookstore2.dispatcher node, right-click, and choose Paste from the contextual menu. A copy of the Dispatcher.java_compX file appears in the list.
  5. Select the copy of the Dispatcher.java_compX file, right-click, and choose Rename from the contextual menu. Rename the file to Dispatcher.java to make it part of the project build.
  6. Double-click the Dispatcher.java file to open it in the NetBeans Editor.

In the Dispatcher.java file, note line 74, in the method doGet():

                    selectedScreen="/faces" + selectedScreen;
                



This line is the sole addition to the original Dispatcher.java file. It prefixes the /faces prefix to the /books/bookcatalog URL pattern. The /faces prefix allows the servlet mapping in the web.xml file to route the component to the FacesServlet class.

The code following line 62 shows that the prefix is concatenated only to /books/bookcatalog URL patterns. The bookcatalog page is the only one in the project that contains JavaServer Faces components.

The Dispatcher servlet doGet() method interacts with lines 45–48 of the web.xml file, noted earlier. In those lines, any URL with the pattern /books/bookcatalog is routed to the Dispatcher servlet. The Dispatcher servlet processes the URL pattern (line 74) by concatenating a /faces prefix, changing the value of the selectedScreen variable to /faces/books/bookcatalog.

In line 105 of Dispatcher.java, a JavaServer Pages .jsp suffix is appended to the URL. The URL is then forwarded to the actual JSP page for processing. In this way, the Dispatcher servlet lives up to its name: it finds known URL patterns, alters them if necessary, and forwards them.

When such a servlet appears in a legacy application, the URL patterns are typically hard-coded. To change a pattern in order to change information flow, the relevant URL pattern must be changed everywhere it appears. To add a page to the application, the new URL must be coded in several places. The advantage of a JavaServer Faces component approach is that these values are declared in the faces-config.xml file and don't need to be hard-coded elsewhere.

Building and Deploying the Application

Now, examine the generated HTML markup for the project by building and deploying it.

  1. Build and deploy the application by choosing Run > Run Main Project from the NetBeans menu bar, or clicking the Run button from the toolbar.
  2. The application opens in your client browser. In the deployed application, click the Start Shopping link to navigate to the book catalog page.
  3. In your browser, view the source HTML for the page (typically, choose View > Page Source or similar menu item).

Note that the code for this page is almost identical to that produced in the do-it-yourself version of the project. Instead of being hard-coded in JavaScript as it was in the do-it-yourself method, the pop-up rendering code is now generated by the renderer. The most obvious difference in the code is the use of the compA namespace in the pop-up portion of the file. Another difference comes at the end of the pop-up section, just before the <!-- END: popup --> comment:

<script type="text/javascript">

   bpui.compA['pop0']=
     new bpui.compA.createPopup('pop0', '/bookstore2/./PopupServlet?bookId=');
</script>



These lines initialize the pop-up balloon object. They create a new a new Popup object with the name of the object ( pop0) and the URL of the servlet to which it is being forwarded ( PopupServlet). These lines are generated by the CompARenderer servlet, in lines 116–122 of CompARenderer.java.

Later in the HTML code, the pop0 object name is referenced in the onmouseover and onmouseout event handlers for each book title. For example,

onmouseover="bpui.compA.showPopup('pop0', event, '202')"
                  

onmouseout="bpui.compA.hidePopup('pop0')"
                



It is instructive to consider the page's HTML code alongside the compA.js code that helps generate it. View the compA.js file in the IDE and consider the showPopup() function beginning on line 9. Lines 11–20 obtain the x-y coordinates of the mouse when the onmouseover event occurs. In lines 21–22, those coordinates are associated with the name of the object that pops up.

The object name and coordinates are then passed to the showPopupInternal() function (lines 28–41). That function looks up the object by name (line 32) and operates on it.

The object is actually created by the createPopup() function (beginning on line 44), more properly called a 'closure' because it contains an inner function, ajaxReturnFunction(), with variables that can be accessed outside of the createPopup() function.

Summary

Although the CompA approach requires some additional effort to code the JavaServer Faces component, it has several advantages:

  • Encapsulation of functionality in the component, which aids in troubleshooting and limits the liability of adopting new technology. In the bookstore application, for example, you can remove one line from the bookcatalog.jsp file and return to your original application, affecting only one page.
  • Ability to use multiple components on a page.
  • Reusability of the component in other pages and applications.

The CompA approach described here has a disadvantage, namely that all of the JavaScript files, images, and Java classes must be bundled with the application. You address this issue in the next article in the series.

Next Steps

In the next article iin this series you take better advantage of JavaServer Faces technology by using a phase listener approach to implement the pop-up balloons. In that approach, you can bundle all of the component's resources into a reusable .jar file.

References
 
Developer Services and Training
 
Rate and Review
Tell us what you think of the content of this page.
Excellent   Good   Fair   Poor  
Comments:
If you would like a reply to your comment, please submit your email address:
Note: We may not respond to all submitted comments.