|
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
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:
- The user clicks a link for the book catalog page.
- On the basis of the URLs defined in the web deployment descriptor
the server routes the page request to
Dispatcher servlet.
- 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.
- The JavaServer Faces framework, directed by instructions in
the
web.xml file, sends the JSP page identified by the URL to the
FacesServlet.
- 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.
- 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.
- 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
|
|
- The user mouses over a link on the book catalog page, executing
the
onmouseover event handler.
- 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.
- The
CompAServlet receives the request and, using the
existing BookDBA object, obtains the book title detail
data and formats a response to the request.
-
CompAServlet then returns an XML response that holds
the book detail.
- 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:
- Start the NetBeans IDE.
- From the NetBeans toolbar, choose File > Open. The Open Project
window opens.
- Navigate to project
/examples/web/bookstore2,
where project is the path to your project directory.
- 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.
- If the IDE flags the bookstore project and alerts you that
references need to be resolved:
- Right-click the project and choose Resolve Reference
Problems from the contextual menu.
- In the resulting window, click Resolve and navigate
to the server
/glassfish/lib directory, where
server is the root of your GlassFish server installation.
- Select the
javaee.jar file and open it.
Click Close to resolve the reference and close the window.
- If the bookstore2 project also produces an alert:
- Right-click the project name and choose Resolve
Missing Server Problem from the contextual menu.
- 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.
- In the NetBeans IDE, click the Projects tab to open the Projects view of your project.
- Expand the bookstore2 > Web Pages > books node and select the
bookcatalog.jsp file.
- Right-click and choose Delete from the contextual menu. In the
confirmation pop-up window, click Yes.
- Select the
bookcatalog_compA.jsp file, right-click,
and choose Copy from the contextual menu.
- 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.
- 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
- 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="http://java.sun.com/blueprints/ui" %>
<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:
- In the Projects window of the NetBeans IDE, expand the bookstore2
> Web Pages > WEB-INF node.
- 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="http://java.sun.com/blueprints/ui/compA"%>
|
For the application server, this line maps to the URI used for the user
interface in line 8 of the ui.tld file:
<uri>http://java.sun.com/blueprints/ui/CompA</uri>
|
In line 15 of the ui.tld file, you see the definition of the
<name> tag:
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.
- In the NetBeans Projects window, expand the following node:
bookstore2 > Source Packages >
com.sun.javaee.blueprints.components.ui.example.
- 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.
- In the NetBeans Projects window, again view the files under the
following node: bookstore2 > Source Packages >
com.sun.javaee.blueprints.components.ui.example.
- 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.
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:
- In the NetBeans IDE Projects view of your
project, expand the bookstore2 > Web Pages > WEB-INF node.
- Double-click the
web.xml file to open it in the
NetBeans Editor.
- 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.
- 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.
- Select the
Dispatcher.java file. Right-click and
choose Delete from the contextual menu. In the confirmation pop-up
window, click Yes.
- Select the
Dispatcher.java_compX file, right-click,
and choose Copy from the contextual menu.
- 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.
- 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.
- 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.
- Build and deploy the application by choosing Run > Run Main
Project from the NetBeans menu bar, or clicking the Run button from the
toolbar.
- The application opens in your client browser. In the deployed
application, click the Start Shopping link to navigate to the book
catalog page.
- 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
|