|
By Rick Palkovic and Mark Basler, September 2006
|
|
|
Articles Index
This is the first in a short series of articles that add Ajax functionality to a
Java EE
NetBeans project. Through the articles, you will see how to implement
increasingly sophisticated Ajax implementations.
Ajax is a combination of existing technologies rather than a technology in
itself. It combines, at a minimum, JavaScript, XML, HTML, and their related
technologies such as Cascading Style Sheets (CSS) and Document Object Model
(DOM).
Learn About Ajax
For background information about Ajax and
strategies for implementation, see
Ajax Design
Strategies
by Ed Ort and Mark Basler.
|
|
Ajax techniques can exchange data asynchronously between a client web
application and a web or application server, thus making the user
experience more responsive. To that end, Ajax-enabled client applications
typically use the XMLHttpRequest object to request data from
the application server.
Because Ajax relies on several underlying technologies and is not a clearly
defined technology itself, there are many ways to implement its
functionality. This series of articles uses a single example application to
describe several of the most popular and productive approaches, beginning
with the most basic. One good source of information about Ajax is the
article Ajax Design Strategies. That article provides
information about the tradeoffs among various approaches to
implementing Ajax.
To get the most out of this article, you should be familiar with the NetBeans IDE and the Java EE 5
tutorial.
The application used in these articles is derived from the Duke's Bookstore
application, included in the Java EE 5 tutorial.
The application has been extracted from the
tutorial for use in this article.
Contents
Adding a Pop-Up Balloon Feature
This article is based on the premise that, as a developer, you want to add
informational pop-up balloons to books listed in the catalog of Duke's
Bookstore. The pop-up balloons will appear when a user's mouse pointer
hovers over a catalog entry.
There are several ways to add this feature, of course. The following table
compares some alternatives and highlights the tradeoffs. (Similar
comparisons can be found elsewhere — at ajax info, for
example.)
| Technology |
Pros |
Cons |
| Conventional HTML |
- Universal browser compatibility
|
- Slow, page swap disorients users
|
| Applet |
- Can use full Java APIs
- Custom data streaming, graphic manipulation, threading,
and advanced GUIs
- Well-established scheme
|
- Code downloading time too big a penalty; too heavyweight a
solution for this feature
|
| Adobe (formerly Macromedia) Flash
|
- Excels at vector graphics
|
- Browser needs a proprietary plug-in
- Scripting language is proprietary
|
| Java
WebStart |
- Very fast response after initial load
- Disconnected operation is possible
- Incremental redeployment of downloaded application
|
- JDK 1.1 and
earlier do not work
- First-time download time could be significant
|
| DHTML
|
- Uses widely deployed technologies (JavaScript, DOM, and CSS)
|
- Does not communicate asynchronously (full page refresh
required)
|
| DHTML with
Hidden iFrame |
- Mimics asynchronous behavior as iFrame loads page in
background
|
- iFrame may soon be deprecated; W3C recommends use
of OBJECT instead
|
| Ajax |
- Uses existing technologies (JavaScript, XHTML,
DOM)
- High level of compatibility between browsers
- Toolkits and JavaServer Faces components available
- Quick response; no need to download code or full pages
- No plug-in required
- Uses existing developers' skill sets
|
- Can be complex to develop and maintain
- Browser bookmarks and history features can break
|
After comparing alternative technologies, the balance of pros and cons
tilts in favor of Ajax for your application. The arguments against using
Ajax — user's loss of context and difficulty in programming —
are not objectionable. First, because the pop-up balloons you plan don't
persist on the page, your users will be able to return to a bookmarked page
without confusion. Second, you plan to use features in the NetBeans IDE
that will simplify programming and deployment.
Implementing Pop-Up Balloons With Ajax
Your first approach to implementing the feature is to add the Ajax-based
pop-up balloons to your application directly. You write supporting
JavaScript and CSS files
and fulfill the Ajax request by writing a servlet in Java. You integrate
these files with the existing JavaServer Pages (JSP) files in
the NetBeans project. This approach is the most direct model for adding
Ajax to a legacy application. However, it might not be the easiest to
program.
To understand the architecture of this approach, consult the brief
discussion in Ajax Design Strategies.
Downloading and Installing the Tools
To follow along with remainder of this article, you will need to download
the example application and the necessary tools. If they are not installed
on your local system, download and install them now, using the installation
instructions on the download pages.
In the rest of this article, the installed location of your GlassFish
application server will be denoted by server, and the installed
location of the Duke's Bookstore project will be denoted by project.
Your installation directory trees should look like the following figure. In
this case, the value of server would be C:/glassfish,
and the value of project would be C:/bookstore.
|
Figure 1: Server and Project Installation Directories
|
Setting Build Properties
You must edit the file that defines build properties to customize it for
your environment. These build properties are used by the ant
scripts that build the project.
To edit the build.properties file:
- In a text editor, open the file
project
/examples/bp-project/build.properties
- Follow the editing instructions in the file. Specifically, edit
the following lines, specifying the path to your GlassFish installation
and the path to your project folder:
javaee.home=server
javaee.tutorial.home=project
|
for example:
javaee.home=C:/glassfish
javaee.tutorial.home=C:/bookstore
|
Editing these two lines should be sufficient for most default
installations. The following table shows how to set other values, if
necessary. If you need more help, consult these
instructions for tutorial installations.
| Property Name |
Description |
Examples |
javaee.home |
The installation directory of the GlassFish application
server |
c:/glassfish |
javaee.server.name |
Host name of the the GlassFish application server
|
localhost |
javaee.server.port |
The port number you chose while installing the
GlassFish application server |
8080 |
javaee.server.username |
The administrator username specified while
installing the GlassFish application server |
admin |
javaee.server.passwordfile |
The path to a file containing the administrator
password for the GlassFish application server. The password file
needs to be in the following format:
AS_ADMIN_PASSWORD=admin-password
Where you will replace admin-password with the admin
password for the GlassFish application server.
|
c:/bookstore/examples/
common/admin-password.txt |
javaee.adminserver.port |
The port number you chose while installing the
GlassFish application server |
4848 |
proxy.host |
The host name of your HTTP proxy server, if the GlassFish
application server is behind a firewall. Leave blank
otherwise. |
myproxy.mydomain |
proxy.port |
The port number of your HTTP proxy server, if the GlassFish
application server is behind a firewall. Leave blank
otherwise. |
8080 |
Preparing the Server and Database
Next, start the server's database and domain to prepare it for the
application deployment.
- Open a command shell. Start the GlassFish
javadb
database by typing the following command:
server/bin/asadmin start-database
|
- Start a domain by typing the following command:
server/bin/asadmin start-domain
|
Next, create database tables. This step is needed to set up the database
and jdbc resource in javadb and the GlassFish
server.
- Create database tables by typing the following commands:
cd project/examples/web/bookstore2
ant create-tables
|
Starting the NetBeans IDE and Registering the GlassFish Server
To register the GlassFish server so that it can be used with the NetBeans
IDE:
- Start the NetBeans IDE.
- From the menu bar, choose Tools > Server Manager. The Server
Manager window opens.
- In the Server Manager window, click Add Server. The Add Server
Instance window opens.
- In the Add Server Instance window, select the Sun Java System
Application Server instance. Click Next.
- Browse to specify the platform location where the GlassFish server
is installed (the value of server). The radio button Register
Local Default Domain is selected by default. The domain shown will be
the one you started from the command line:
localhost:4848(server/domains/domain1)
|
Click Next.
- Enter the administrator username and password. The default values
are Username:
admin Password: adminadmin
- Click Finish. In the Server Manager window, select the Sun Java
System Application Server. The Server Manager window looks like the
following figure.
Figure 2: Server Manager Window |
- Click Close to dismiss the Server Manager window.
Opening the Bookstore Project in the NetBeans IDE
Next, open the project in the NetBeans IDE:
- From the NetBeans toolbar, choose File > Open. The Open Project
window opens.
- Navigate to project
/examples/web/bookstore2.
Select the bookstore2 project folder and click Open Project Folder. The
IDE opens the project folder and selects bookstore2 as the main
project. Note that 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 pop-up menu.
-
In the resulting window, click Resolve and navigate to the server
/glassfish/lib
directory. 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 on
the project name and choose Resolve Missing Server Problem from the
pop-up menu.
-
In the resulting window, select the GlassFish server that you
registered previously. Click OK to resolve the reference.
Running the Bookstore Project
You can now build and deploy the bookstore2 project.
In the NetBeans Projects window, the bookstore2 project should
be shown in bold type to indicate that it is the main project. If it is
not, set it as the main project by choosing Files > Set Main Project
> bookstore2.
-
Build and deploy the bookstore2 project by choosing Run > Run
Main Project.
The status of the build is shown in the NetBeans Output window. When the build
finishes successfully, your browser opens to show the Duke's
Bookstore application.
Clicking on the Start Shopping link will take you to the catalog
page, shown below.
Figure 3: Duke's Bookstore, Catalog Page |
Exploring Duke's Bookstore
From the Duke's Bookstore catalog page, shown in the previous figure, you can
click one of the book links. Clicking a link opens a new page with detailed
information about the book, as shown in the following figure.
Figure 4: Duke's Bookstore, Detail Page |
Users would have easier access to this information if it could be
displayed in a pop-up balloon when a user rolled over the link in the
catalog page. You will now implement this feature with Ajax. In your
implementation, the entire page will not need to reload to show the
information. Only the information in the pop-up balloon loads when
the user mouses over the link. The following figure shows the
Ajax-enabled page.
Figure 5: Duke's Bookstore, with Pop-up Balloon |
Adding a Pop-Up Balloon to the Bookstore Application
Your first approach to adding the Ajax pop-up balloon to the
application
is the most basic: you will hand-code a JavaScript (.js)
file and a cascading style sheet (.css) file for the
client. To handle the client requests on the server, you hand-code
a Java
servlet (.java). You also edit the project's
bookcatalog.jsp file.
To save you time, these files have been provided for you.
They are already in the project directory, and can be found at the
following locations:
project/examples/web/bookstore2/web/popup.js
project/examples/web/bookstore2/web/popup.css
project/examples/web/bookstore2/web/books/bookstore/bookcatalog.jsp
project/examples/web/bookstore2/src/java/com/sun/bookstore2/dispatcher/PopupServlet.java
Now, examine each of these files to see how they were created.
Writing the JavaScript File
The popup.js file provides the JavaScript functions that
cause
the pop-up balloon to appear. Note that the code in this file code was
developed
following the
JavaScript Recommendations for Ajax Component Writers.
To examine the popup.js file in the IDE:
- Select the Files view of the project, expand the bookstore2 >
web node, and double-click
popup.js. The file opens in the NetBeans
JavaScript Editor.
- From the menu bar, choose View > Show Line Numbers. Refer to
the NetBeans Editor view of the file in the following discussion.
The opening lines of the file (lines 1-3) create a component
namespace object, bpui. The name is used in the Java Blueprints
Solutions Catalog, and stands for “blueprints user interface.”
Using
the namespace as a prefix is good programming practice
because it helps ensure that
functions will have unique names.
For example, if you simply defined showPopup() as a
function
instead of bpui.alone.showPopup(), then there could be a
conflict with another showPopup() function. The last such
function that is defined in a file takes precedence over all earlier
functions.
In line 7, you create a bpui.alone object to
hold the pop-up balloon.
In line 8, you create a bpui.alone.timeout
timeout variable in the object. The timeout is used as
follows.
When a user mouses over a book link in the catalog page, a timer
begins counting. If the mouse is still hovering over the link after
a timeout period of
1000 ms has elapsed, an
XMLHttpRequest request is sent to the server. If
the
server responds with the necessary pop-up balloon data before the
timeout has expired, the balloon is hidden until the end of the
timeout. If the server is slow and
does not respond until after the timeout, one of two conditions applies:
- The user keeps the mouse pointer over the link, and the
balloon pops up when the necessary data is received, or
- The user moves the pointer out of the link, and the balloon
remains hidden even after the server responds.
The timer is cleared when the user mouses out, and awaits the
next mouseover event.
Line 9 creates a bpui.alone.req object to hold the
request.
The function bpui.alone.showPopup() (beginning
on line 12) is called when the user mouses over a link. The
function sets the location for the pop-up balloon and then
sets the timer to begin counting. After the timeout period
has elapsed, the bpui.alone.showPopupInternal()
function is called.
The function bpui.alone.showPopupInternal() (beginning on
32) initiates the Ajax XMLHttpRequest request.
Because your Ajax implementation will use a servlet to respond to client
requests, your popup.js file uses the following line to
set
the URL:
url="../PopupServlet?bookId=" + escape(bookId);
|
The servlet mapping is defined in the web deployment descriptor file,
web.xml, which is stored in the following location:
project/examples/web/bookstore2/build/web/WEB-INF/web.xml
Note that another line, commented out in popup.js, can be used
to set the URL:
// url="../book_lookup.jsp?bookId=" + escape(bookId);
|
When this line is uncommented, it sets a JSP page as the dispatcher. You enable
this line later when you explore the JSP approach. For now, leave the line
as a comment.
The function then concatenates the Ajax dispatcher URL with the bookId
(line 40) and sets the pop-up balloon's Ajax callback function (line 41).
The statement at line 42 specifies that the XMLHttpRequest
object uses a GET method (as opposed to a
POST method) to communicate with the server-side component.
The url parameter indentifies the URL of the server-side
component, which was set to PopupServlet in the previous
statement. The parameter true indicates that the communication
is asynchronous.
Finally, the function sends the request (line 43).
The callback function ajaxReturnFunction() (beginning on line
46) accepts the server response. The function checks the validity of the request's
response by making sure that the ready state is complete
(readyState property equals 4) and the response is OK
(status property equals 200). For details about how to
work with Ajax XMLHttpRequest objects, click here.
The function then extracts the document root of the XML response and parses it.
The function document.getElementById() (lines 55–56) inserts
the information into the appropriate nodes of the
DOM
in the
JSP.
Note the innerHTML property, which is
used to insert an HTML fragment. Using the innerHTML property
to update the DOM avoids
the need to create each element in the object individually with
conventional DOM API
functions.
The last line of the if clause (line 58) sets the value for
the visibility style of the pop-up balloon to visible. The
initial style is set to hidden in the popup.css
file, which is explained in the following section.
The bpui.alone.hidePopup() function (beginning on line 65) is
called on mouseout to hide the pop-up balloon and clear the
timeout variable.
Writing the CSS File
In the do-it-yourself approach to Ajax described here, you must
provide a cascading style sheet (.css file) that describes the
appearance of the pop-up balloon. In this project, the
popup.css file describes the layout for the balloon, including
its fonts, colors, and dimensions. The bookcatalog.jsp file
uses these descriptions to build the pop-up balloon as it inserts content.
To view the popup.css file in the IDE, double-click the
bookstore2 > web > popup.css node in the Files window, just as you
did for the popup.js file.
The file begins by defining seven class styles that are used to set the
pop-up balloon's border widths and colors, its background color, and the
margins within which the text content of the balloon appears. The class
styles also specify the images used to produce rounded corner effects for
the pop-up balloon. In each square corner image, the outside corners are
white, and the inside corners are transparent to allow the balloon's border
color to show through.
Following these definitions is another class style definition,
div.bpui_alone_popup, that is used with the block-level
container tag <div>. This class is also used to format
the balloon's content.
To learn more about CSS,
consult one of the many online resources available, such as W3 Schools.
Editing the JavaServer Pages File
By examining the bookcatalog.jsp file, you learn
how the popup.js and
popup.css files produce a pop-up balloon.
- In the NetBeans Files window, expand the bookstore2 > web >
books node and select the
bookcatalog.jsp file.
- Right-click the file and choose Rename from the context menu.
Rename the file
bookcatalog_orig.jsp. This file is the original
version of the file, which does not produce pop-up balloons.
- Select the file
bookcatalog_popup.jsp, right-click,
and choose Rename from the context menu. Change the name to
bookcatalog.jsp.
- Double-click
bookcatalog.jsp to view the file in the
NetBeans Editor.
The original and pop-up versions of the file are nearly identical except
for the code between the comment lines at line 28 and line 57:
and
The first two lines (29–30) provide the links to the popup.js
and popup.css files:
<script type="text/javascript" src="../popup.js"></script> <link type="text/css" rel="stylesheet" href="../popup.css" />
|
As discussed earlier, the popup.css file provides the
presentation layout styles for the pop-up balloon. The code following these
links (lines 33–56) makes use of the CSS styles and HTML to draw
the balloon and insert content into it.
The remainder of the file is identical to the original
bookcatalog.jsp file, with one exception. Embedded in the
layout table for the page, in lines 100–104, are event handlers that call
JavaScript functions from popup.js when the user mouses over
or mouses out of a book title link.
<!-- added event handlers to trigger popup --> <a href="${url}" onmouseover="bpui.alone.showPopup(event, '${bookId}')" onmouseout="bpui.alone.hidePopup()"> <strong>${book.title} </strong> </a>
|
The following clause triggers the pop-up balloon:
onmouseover="bpui.alone.showPopup(event, '${bookId}')"
|
The value of ${bookId} determines
the data that is returned from the server in response to the Ajax
XMLHttpRequest.
The following clause hides the pop-up balloon:
onmouseout="bpui.alone.hidePopup()"
|
The pop-up balloon's show and hide
functions can be placed elsewhere. Here, they are placed directly following code
that provides the value for ${bookId}, which the
onmouseover() function uses to retrieve book information.
Writing a Servlet to Generate Response
With the JavaScript, CSS,
and book catalog JSP files
prepared, all you need to implement your Ajax pop-up balloons is a
servlet or server-side component to handle the XMLHttpRequest.
The most hands-on approach to implementing a dispatcher is to write a
servlet.
An example of such a servlet is provided for you at
project/examples/web/bookstore2/src/java/com/sun/bookstore2/dispatcher/PopupServlet.java
View the file in the IDE by opening the bookstore2 > src >
java> com > sun > bookstore2 > Dispatcher node and
double-clicking PopupServlet.java. The file opens in the NetBeans Java
Editor.
Note that nothing in the servlet is unique to Ajax. The servlet composes
an XML response to a client request, and is unaware of the asynchronous
nature of the request.
The client obtains information for a book by sending a request that
contains a bookID. The PopupServlet responds by pulling a Book object from
the server-side database, extracting the necessary information,
constructing an XML file, and returning the XML file to the client. In the
client, the JavaScript callback function,
bpui.alone.ajaxReturnFunction(), handles the response.
This file was created in the NetBeans IDE. Therefore, it extends the standard HTTP
servlet (line 24):
public class PopupServlet extends HttpServlet {
|
All requests and responses are forwarded to the method on line 30:
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
|
In this method, you set the return type:
response.setContentType("text/xml;charset=UTF-8");
|
You get the response writer from the response itself (line 32), which
provides a stream to write the data. Line 33 is
from the original bookstore application:
BookstoreMessages messages=new BookstoreMessages();
|
The messages object contains the data you want to display in
the pop-up balloon. The developers of the application used mnemonics to
identify parts of each message. For internationalization (i18n) reasons,
the mnemonics refer to keys in a properties file. The values of the keys
are retrieved and printed. For example, the statement
out.println(messages.getString("Critics"));
|
finds the following line, which is provided by the locale file stored in the
project/examples/web/bookstore/src/com/sun/bookstore/messages/
directory:
{ "Critics", "Here's what the critics say: " },
|
and prints the phrase "Here's what the critics say: ". Line 56
does exactly that, together with HTML formatting tags and a description
from the database that contains the critics' comments.
As part of the request from the client, the bookId of the
relevant book is passed in. Using the bookId parameter, the
servlet determines the identity of the book to look up.
Because the basic application codes a database object
(BookDBAO) in the servlet context, it is necessary to get the
database object from the servlet context in order to retrieve the book
information (lines 47 and 48). All of the bookDBAO functions
required are a result of the original bookstore application coding. The
bookDBAO.getBook(bookId) method returns a book object that
contains the necessary data.
After the servlet has obtained the data, it composes a response to the request in
the series of out.println() methods (lines 50–66). Note the
CDATA prefix in the method calls. For example,
out.println("<title><![CDATA[Book Detail]]></title>");
|
The CDATA
prefix is an XML construct that
instructs the parser to ignore any XML code in the character string. The
prefix allows the payload of the XML elements to be passed to the client
application. The complete message is contained between the output
<message> and </message> tags.
Generating Server Response with JSP
You can generate XML server response with a JSP page rather than a servlet. If you
are familiar with JSP
programming, you will probably find it much quicker to develop a JSP page than a servlet.
JSP pages show their value in speed of programming, particularly in the
NetBeans IDE. If you start your project in the NetBeans IDE, JSP pages are deployed as soon as they
are saved, eliminating redeployment and repackaging time. In addition, you
can take advantage of the tag library that is associated with JSP technology but is unavailable in a
servlet.
The JSP page that generates the
response is named book_lookup.jsp. It is stored in the
project/examples/web/bookstore2/web directory. The XML
messages that are returned by this JSP page
and PopupServlet described earlier are exactly the same.
They are just two ways of generating the same XML response.
Open the file for viewing in the NetBeans Editor by expanding the bookstore2 > web > node in the Files window and double-clicking the
book_lookup.jsp file.
The file contains two scriptlets that provide presentation logic, along with
JSP code for the presentation
itself. Separating the two activities provides modularity.
The two scriptlets in the file are demarcated by <% and
%> symbols (lines 9–28 and 40–53). JSP presentation code lies between the
scriptlets (lines 30–38).
Note that in the JSP code,
no message manipulation is required. Message manipulation
is handled by the <fmt> tag library. This code is taken
directly from the bookdetails.jsp file, in the
project/examples/web/bookstore2/web/books directory.
Users who click a book link are routed to a details page. The
information on the details page is much like that shown in the pop-up
balloon, and the code from the details page is reused for the pop-up
balloon.
In summary, if you already have the JSP
file for the details page, you do not need to write a
servlet to generate the XML response. Instead, you can use another JSP file to generate the response, using
existing code to describe the presentation, and taking advantage of the
<fmt> tag libraries to format the displayed response.
Using the book_lookup.jsp File
The popup.js file determines whether to use
PopupServlet or book_lookup.jsp to serve the
client XMLHttpRequest. To enable book_lookup.jsp:
- View bookstore2 > web > popup.js in the NetBeans Editor.
- Remove comments from line 38 so that it reads as follows:
url="../book_lookup.jsp?bookId=" + escape(bookId);
|
- Comment out line 40 by inserting initial slashes so that it reads
as follows:
// url="../PopupServlet?bookId=" + escape(bookId);
|
- Run the project by choosing Run > Run Main Project.
Your project builds, deploys, and runs with results identical to those
you saw when you used PopupServlet.java.
Summary
In this article, you learned how to hand-code an Ajax feature into a web
application that was developed in the NetBeans IDE. You installed and
configured the tools you needed to develop and deploy the application: the
NetBeans IDE and the GlassFish application server.
You learned how to code the popup.js, popup.css,
and bookcatalog.jsp files in the client to generate an
XMLHttpRequest request object. You learned how to write a servlet, deployed
on the GlassFish server, that can generate a response to the request.
You then learned how to specify a JavaServer Page on the server instead of
a servlet to generate a response.
Next Steps
In the next article in this series, you will use Dojo
toolkit libraries to implement the pop-up balloon Ajax feature.
References
Developer Services and Training
|