Enterprise Java Technologies Tech Tips
Tips, Techniques, and Sample Code
Welcome to the Enterprise Java Technologies Tech Tips for
October 26, 2007. Here you'll get tips on using enterprise
Java technologies and APIs, such as those in Java Platform,
Enterprise Edition (Java EE).
This issue covers:
* Client-Side Polling With Dynamic Faces
* Testing Interoperability Between Metro and .NET
These tips were developed using an open source reference
implementation of Java EE 5 called GlassFish, and the open
source NetBeans IDE 5.5.1. You can download GlassFish from the
GlassFish Community Downloads page
https://glassfish.dev.java.net/public/downloadsindex.html.
You can download the NetBeans IDE 5.5.1 from the NetBeans page
http://www.netbeans.org/.
You can view this issue of the Tech Tips on the Web at
http://java.sun.com/mailers/techtips/enterprise/2007/TechTips_Oct07.html
You can download the sample archive for the tip Client-Side
Polling With Dynamic Faces at:
http://java.sun.com/mailers/techtips/enterprise/2007/download/ttoct2007client-poll-dfaces.zip.
You can download the sample archive for the tip Testing
Interoperability Between Metro and .NET at:
http://java.sun.com/mailers/techtips/enterprise/2007/download/ttoct2007interop.zip.
Any use of this code and/or information below is subject to the
license terms at
http://developers.sun.com/dispatcher.jsp?uid=6910008.
You can now read the Enterprise Java Technologies Tech Tips online as a web log at:
http://blogs.sun.com/enterprisetechtips/
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CLIENT-SIDE POLLING WITH DYNAMIC FACES
by Roger Kitain
The world of dynamic web applications offers various ways for a
client and server to interact. Two approaches are particularly
well suited for situations when information on the server
changes frequently. These approaches are:
o HTTP Streaming
o Client Polling
In HTTP streaming, the client/server connection is left open for
an extended period of time so that data is streamed from the
server to the client. This approach is also known as server-side
push, reverse Ajax, or comet. As information changes on the
server, updates are pushed to the client.
With client polling, the browser periodically issues an
XMLHttpRequest call to obtain new information from the server.
For example, a client can send an XMLHttpRequest to the server
every five seconds to get new information. This approach is also
known as periodic refresh.
The Dynamic Faces framework
https://jsf-extensions.dev.java.net/ brings the power of Ajax
to traditional JavaServer Faces Technology (often abbreviated as
JSF) applications. Ajax function calls are typically made in
JavaScript, which can be unfamiliar to Java developers. With
Dynamic Faces, you can add Ajax functionality to a JSF
application with little or no JavaScript. Dynamic Faces provides
a small "out of the box" JavaScript library that you can use
with a JSF application.
This tip will show you how you can use Dynamic Faces to build
a real-time, stock query application that does client-side
polling. You'll see that you don't have to do much JavaScript
coding. A package that contains the code for the sample application
http://java.sun.com/mailers/techtips/enterprise/2007/download/tt0ct2007client-poll-dfaces.zip
accompanies the tip. The code examples in the tip are taken from
the source code of the sample (which is included in the
package).
The Stock Query Application
This tip uses a stock query application to demonstrate
client-side polling with Dynamic Faces.
First, let's take a look at the user interface (UI) for the
application.
User Interface
http://java.sun.com/mailers/techtips/enterprise/2007/images/stock-faces-ui1.jpg
The UI is pretty basic. You enter one or more space-delimited
stock symbols in the Symbol text field and click the Search
button. In response, the application displays a table of data
pertinent to the stocks represented by the symbols you entered.
You enter proxy information in the Proxy Host and Proxy
Port fields if you are behind a firewall.
The most interesting feature of the UI is the Streaming field.
The choices are On or Off. If Streaming is set to On, the client
polls the server, firing Ajax transactions every 10 seconds (or
a specified time interval).
The Remote/Local field allows you to choose either Local or
Remote. If you select Local, the application uses local data.
This is the choice to make if a network connection is not
available. If you select Remote, the application calls the Yahoo
Stock Quoting service to get the stock data.
The size of the result table dynamically changes depending on
the number of symbols that you enter.
Now let's take a look at the artifacts used in the application.
Artifacts
There are only three artifacts used in the application:
o A JavaServer Pages technology (JSP) page
o A JavaScript file
o A JSF Managed Bean
JSP Page
Here's a snippet of the JSP page for the application, home.jsp, showing the relevant parts:
...
...
...
...
...
...
Here are some things to notice in the code snippet:
o is the standard tag to include for Dynamic
Faces applications. It includes the Dynamic Faces JavaScript
library.
o The include_js('javascripts/stock-faces.js'); line is a
utility function that loads the application's JavaScript file,
stock-faces.js.
o The h:commandButton tag has an onclick JavaScript event
handler attached to it. The event handler,
DynaFaces.fireAjaxTransaction, sends an Ajax request to the
server when the button is clicked. The actionListener
specified by #{bean.getStockInfo} is then executed on the
server. What's significant here is that any view or JSF
component manipulation done on the server happens using Ajax.
o The "streaming" option is a h:selectOneMenu component that has
an onchange JavaScript event handler.
o A h:panelGrid tag with an id of stockdata" is a placeholder
the dynamic table of stock data. The attribute rendered is set
to "false", meaning that the table is not initially rendered.
However, the application code sets the attribute to true
when there is stock data to return.
JavaScript File
Here is the JavaScript file, stockfaces.js, for the application:
var pollId;
/** Delay between requests to the server when polling. */
var pollDelay = 10000;
/** Start polling the server */
function start() {
pollId = setInterval(poll, pollDelay);
}
/** Stop polling the server */
function stop() {
clearInterval(pollId);
}
function poll() {
queueEvent();
DynaFaces.fireAjaxTransaction(null, {});
}
function queueEvent() {
var actionEvent =
new DynaFaces.ActionEvent("search",
DynaFaces.PhaseId.INVOKE_APPLICATION);
DynaFaces.queueFacesEvent(actionEvent);
return false;
}
function toggleStreaming() {
var menu = document.getElementById("streaming");
var idx = menu.selectedIndex;
var streaming = menu[idx].value;
if (streaming == "Off") {
stop();
} else if (streaming == "On") {
start();
}
}
Here's what the JavaScript code in the file does:
o The polling delay, that is, the time interval between calls to
the server, is set to 10 seconds.
o The start() function initiates the server polling.
o The stop() function stops server polling.
o The poll() function queues up a server-side JSF action event.
It then fires an Ajax request to the server using the Dynamic
Faces library.
o The queueEvent() function queues up a server-side JSF action
event using the Dynamic Faces library. The action event is
processed during the standard JSF lifecycle processing as the
Ajax request flows to the server.
o The toggleStreaming() function toggles the value of the
"streaming" menu control.
JSF Managed Bean
Here's a snippet of the JSF managed bean, Bean.java, showing the
relevant parts:
/**
* This bean has methods to retrieve stock information from
* the Yahoo quote service.
*/
public class Bean {
private static final String SERVICE_URL =
"http://quote.yahoo.com/d/quotes.csv";
/**
* Action method that is used to retrieve stock
* information. This method uses two helper methods - one
* to get the stock information, and the other to
* dynamically build the "data" components for the UI.
*/
public void getStockInfo(ActionEvent ae) {
...
...
stockData = getStockData(symbols);
buildUI(stockData);
...
}
/**
* Helper method to get the stock data (remotely).
*/
private String[] getStockData(String[] symbols)
throws IOException, MalformedURLException {
String[] data = new String[symbols.length];
for (int i=0; i/client-poll-dfaces, where
is the directory where you installed the
sample application. For example, if you extracted the
contents to C:\ on a Windows machine, then your newly created
directory should be at C:\client-poll-dfaces.
3. Start GlassFish by entering the following command:
/bin/asadmin start-domain domain1
where is the directory where you installed
GlassFish.
4. Deploy the sample by copying
/client-poll-dfaces/stock-faces.war to
/domains/domain1/autodeploy
5. Open your browser to the URL: http://localhost:8080/stock-faces/.
You should see the Stock Query Application UI.
http://java.sun.com/mailers/techtips/enterprise/2007/images/stock-faces-ui1.jpg
6. Enter one or more stock symbols delimited by a space, for
example, JAVA LMT IBM. If you are behind a firewall, specify
the pertinent proxy information in the Proxy Host and Proxy
Port fields. Click the Search button. You should see a table of
stock data displayed for the symbols you entered.
http://java.sun.com/mailers/techtips/enterprise/2007/images/stock-faces-ui2.jpg
7. Try different combinations of streaming and Local/Remote
settings, and see what happens. You'll notice that if
Streaming is set to On, you don't have to press the Search
button. The stock symbols that you specified in the Symbol
text field are automatically sent using the Ajax mechanism to
the server. If you choose Local, the names and prices are
simulated, so that the data will likely be different than
the result of a Remote selection.
Summary
This tip demonstrated how you can combine JSF with Ajax to
produce dynamic applications. This application illustrated two
features of Dynamic Faces:
o fireAjaxTransaction
o Remote JSF event queuing from JavaScript
You can find out more about Dynamic Faces in the
jsf-extensions project https://jsf-extensions.dev.java.net/.
Also see Ed Burns's blog "Introducing Project Dynamic Faces"
http://weblogs.java.net/blog/edburns/archive/2006/08/introducing_pro.html.
About the Author
Roger Kitain is the JavaServer Faces technology co-specification
lead. He has been extensively involved with server-side web
technologies and products since 1997. Roger started working on
JSF in 2001 as a member of the reference implementation team.
He has experience with Java Servlet technology, JSP, and most
recently has been involved with different rendering technologies
for JSF.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
TESTING INTEROPERABILITY BETWEEN METRO AND .NET
By Harold Carr
The March 2007 Tech Tip, "Securing Web Services Using WSIT"
http://java.sun.com/mailers/techtips/enterprise/2007/TechTips_March07.html#1
introduced Web Services Interoperability Technology (WSIT)
https://wsit.dev.java.net/, an implementation of open web
services technologies that enables interoperability between
Java EE and .NET. WSIT along with Java API for XML-Based
Services (JAX-WS) comprise the stack of web services
technologies in GlassFish v2
https://glassfish.dev.java.net/. The web services stack in
GlassFish v2 is called Project Metro
https://metro.dev.java.net/ or Metro for short. Metro is built
into Sun Java System Application Server 9.1
http://www.sun.com/software/products/appsrvr/appsrvr9_1.xml.
Metro also runs in other containers such as Tomcat.
WSIT, also called Project Tango, includes features that enable
advanced web service interoperability with the .NET Windows
Communication Foundation (WCF), a set of technologies for
building and running connected systems. WSIT also addresses key
aspects of web services interoperability such as reliable
messaging, transaction handling, and security. What this means
is that any combination of Metro-based and WCF-based clients and
services can interoperate with support for reliable messaging,
transaction handling, and security.
To ensure that the stack of WCF and Metro technologies
interoperate properly and provide the proper support, Microsoft
and Sun engineers run comprehensive interoperability tests
called "plug-fests". You can find out more about the plug-fests,
including the scenarios that are tested, by viewing the Web
Services Interoperability Plug-Fest Home Page
http://www.mssoapinterop.org/ilab/. All tests pass in the
current levels of .NET and Metro: .NET 3.0 and
Metro 1.0.
In this tip, you'll build and run an interoperability test in
which a Metro-based client communicates with a WCF-based
service. A package that contains the code for the
interoperability test
http://java.sun.com/mailers/techtips/enterprise/2007/download/tt0ct2007interop.zip
accompanies the tip. The code examples in the tip are taken from
the source code of the sample (which is included in the
package).
A Reliable One-Way Interoperability Test
The interoperability test you'll build and run in this tip is
a "reliable one-way test." This type of test is described in
"Scenario #1.1. One-Way Anonymous Client" in the document "WCF
(Indigo) Introperability Lab: Reliable Messaging"
http://131.107.72.15/ilab/RM/WCFInteropPlugFest_RM.doc. This
is a typical enterprise use case where a client sends data to
a service for processing but does not wait for a response --
that's why it's called "One-Way". However, the client wants
assurances that the messages are received by the service.
The message flow in this test is as follows:
http://java.sun.com/mailers/techtips/enterprise/2007/images/put rm-flow.gif
o The client initiates the establishment of a reliable
communication channel by sending a CreateSequence protocol
message.
o The service creates a sequence identifier to uniquely identify
the reliable channel. The service returns this identifier in
a CreateSequenceResponse protocol message.
o The client sends three application messages. Each of these
messages is accompanied with header information containing the
sequence identifier for the channel and a message number
identifying the message.
o For each application message received, the service responds
with a SequenceAcknowledgement identifying what messages have
been received. The service does this without having to wait
for the business logic to complete processing.
o If the client sees that some of the messages it sent have not
been received, it retransmits those messages. (This situation
is not tested in this tip.)
o The client closes the channel when the channel is no longer
needed. This causes a LastMessage protocol messages to be sent.
o The service responds with a SequenceAcknowledgement protocol
message indicating which messages have been received.
o Again, if the client sees that some of the messages it sent
have not been received, it resends those messages. This is
followed by another LastMessage. The LastMessage-resend
sequence repeats until all messages have been received by the
service. (That is not exercised in this tip.)
o The client sends a TerminateSequence protocol message.
o The service responds with an HTTP 202 response indicating that
the request has been accepted for processing.
Metro-Based Client
Let's start by creating the Metro-based client. You can view the
source code for the client in the file ReliableOneWay.java. Here
is a snippet of the source code in that file:
package reliableoneway.client;
import org.tempuri.IPing;
import org.tempuri.PingService;
public class ReliableOneWay {
public ReliableOneWay() {}
public static void main(final String[] args)
{
try {
PingService service = new PingService();
IPing port = service.getCustomBindingIPing();
msg(null, "BEFORE FIRST MESSAGE");
msg(port, "FIRST MESSAGE");
msg(port, "SECOND MESSAGE");
msg(port, "THIRD MESSAGE");
msg(null, "TERMINATE");
((com.sun.xml.ws.Closeable)port).close();
Using a reliable messaging (RM)-based web service is no
different than using any SOAP-based web service. First you
create a proxy to the service (see the section "Running
wsimport"). Here, the service is PingService, which is
defined in the WSDL (see the section "WSDL"). Then you
obtain a port defined in that service, in this case,
CustomBindingIPing. Then you can send application messages to
that service by calling the ping method on the port. Here the
method "msg" calls port.ping(String) when port is not null. In
this example, three messages are sent.
These steps are the same steps you would take to use any
SOAP-based web service. The one additional step is calling close
on the port. This signals Metro to terminate the RM channel if
the service is using RM. In general, it's a good idea to close
ports when they are no longer needed. This enables Metro to
reclaim any resources used by that port.
WSDL
You generate the PingService proxy from the Web Service
Definition Language (WSDL) file for the service. You can find
the WSDL for the service by going to the Web Services
Interoperability Plug-Fest Home Page
http://www.mssoapinterop.org/ilab/. Click on the RM
Endpoints (WS-Addressing 1.0) link. Then click on the OneWay.svc
link. The address of the WSDL is
http://131.107.72.15/ReliableMessaging_Service_WSAddressing10_Indigo/OneWay.svc?wsdl.
The WSDL file is quite large because it is used for other test
scenarios besides scenario 1.1, that is, scenarios that involve
security. The port that this tip uses is named
CustomBinding_IPing. It references the following policy binding:
The RMASssertion in the policy binding specifies an RM policy
assertion for the service. Within the assertion, the
InactivityTimeout parameter sets then interval of time that the
service remains inactive before closing. The
AcknowledgementInterval parameter sets the interval of time that
a destination waits before sending an acknowledgment to the
message source on reliable channels. You can find out more about
RM policy assertions in the WS-ReliableMessaging Policy
specification
http://specs.xmlsoap.org/ws/2005/02/rm/WS-RMPolicy.pdf. The
main point here is that including the RMAssertion in the WSDL
and then referencing it in the CustomBinding_IPing binding that
is used in the CustomBinding_IPing port causes operations on
that port to use reliable messaging.
The Structure of the Test
In this tip, you'll use ant to create the proxy, compile the
code, and run the client test. You can also use NetBeans -- for
more details, see the WSIT Tutorial
https://wsit-docs.dev.java.net/releases/1-0-FCS/index.html.
If you haven't already done so, download and install GlassFish v2
https://glassfish.dev.java.net/public/downloadsindex.html.
Then download the sample application for the tip
http://java.sun.com/mailers/techtips/enterprise/2007/download/ttoct2007interop.zip
and extract its contents. You should now see the newly extracted
directory as /interop, where
is the directory where you installed the
sample application. For example, if you extracted the contents
to C:\ on a Windows machine, then your newly created directory
should be at C:\interop.
Although this tip demonstrates only one scenario, the directory
structure below the interop directory is set up such that
common artifacts are factored out to be used with other tests.
The directory structure is as follows:
common.xml
rm
build.xml
netbeans
ReliableOneWayService
...
src
reliableoneway
build.props
build.xml
client
ReliableOneWay.java
...
server
etc
EchoServiceRMCustomOnly.wsdl
ReliableOneWay.xsd
At the top level of the directory structure, the build.xml file
imports common.xml, where the real action takes place, and
defines one target: run-reliableoneway. The run-reliableoneway
file cleans the build directory. It then:
o Runs wsimport
o Compiles the generated code and the ReliableOneWay.java code
o Runs the test
Running wsimport
Here is the snippet of code in the build.xml file that runs
wsimport:
Notice that it uses the build.xml file in the
rm/src/reliableoneway directory. That file, in turn, uses the
build.props file in the rm/src/reliableoneway directory. Here is
the contents of build.props:
test.wsdl=
http://131.107.72.15/ReliableMessaging_Service_ ...
client.dir=client
className=reliableoneway.client.ReliableOneWay
The build.props file is a property file that defines test.wsdl
to be the location of the WSDL file of the service. It also sets
two other parameters used by common.xml so it can be used for
other tests that are not covered in this tip.
The build.xml file in the rm/src/reliableoneway directory then
uses the run-wsimport target from the common.xml file.
The wsimport task fetches the WSDL file specified in parameter
test.wsdl. It then generates the proxy code into the
rm/build/classes/org/tempuri directory, and the data schema
class into the
rm/build/classes/com/microsoft/schemas/_2003/_10/serialization
directory. This class is large because it is a superset of all
data used by all the interoperability test scenarios.
Compiling the Code and Running the Test
The final two steps in the run-reliableoneway target are:
The compile step runs the Java Programming Language compiler,
javac, on the developer-written code, ReliableOneWay.java. The
run-tests step executes the main test class as specified in the
className parameter set in build.props file. In this case,
className is set to reliableoneway.client.ReliableOneWay.
Note that sysproperty is set in the run-tests target of the
common.xml file.
This enables the client to send and receive messages.
Setting Environment Variables
Four ant parameters are set from environment variables (here
shown in bash syntax):
export PROXY_HOST=-DproxyHost=my.proxy.example.com
export PROXY_PORT=-DproxyPort=8765
export METRO_HOME=/glassfish/b58g
export TEST_HOME=~/metro-wcf-interop-tests/rm
If you are not behind a firewall then explicitly set PROXY_* to
nothing:
export PROXY_HOST=
export PROXY_PORT=
Set METRO_HOME to the top-level installation direction of
GlassFish. That setting is used to locate Metro JAR files such
as webservices-rt.jar and webservices-tools.jar in
$METRO_HOME/lib. (If you are using Tomcat or another web
container you need to update common.xml to correctly reference the
location of the Metro JAR files.)
Executing the Test
If you haven't already done so, start GlassFish by entering the
following command:
$METRO_HOME/bin/asadmin start-domain domain1
Then change to the $TEST_HOME directory and enter the following
command on the command line:
ant
Note: This test is designed to run with JDK 5. If you want to
run the test with JDK6, you need to use the Java Endorsed
Standards Override Mechanism
http://java.sun.com/javase/6/docs/technotes/guides/standards/index.html.
Test Results
The output of the test should look similar to the content in the
example-output-wcf-endpoint.txt file in the
rm/src/reliableoneway/client directory.
You can ignore all the WARNING messages at the beginning of the
test run, such as the following:
[java] WARNING: WSP0075: Policy assertion
"{http://docs.oasis-open.org/ws-rx/wsrmp/200702}RMAssertion"
was evaluated as "UNKNOWN".
These warnings are from the numerous policies for bindings in
the WSDL that are not used in this test. Similarly, you can
ignore the non-standard SOAP 1.2 binding warning messages in
the run-wsimport step.
In the output, search for BEFORE FIRST MESSAGE. This is printed
to the console just before the first invocation of port.ping.
When port.ping is called, the RM infrastructure holds the
application message back -- it first establishes a reliable
channel by sending a CreateSequence protocol message.
Content-Type: application/soap+xml;charset="utf-8";
action="http://schemas.xmlsoap.org/ws/2005/02/rm/CreateSequence"
The CreateSequenceResponse protocol message returned from the
service contains an Identifier that will be used to identify the
reliable channel.
After the reliable channel is established, the application
message is sent containing FIRST MESSAGE in the
Body element. The header contains a Sequence element that
contains the reliable channel Identifier along with
a MessageNumber, in this case the number 1.
...
1...
...FIRST MESSAGE...
Because this is a oneway message, the response to this message
contains an empty Body. The header contains
a SequenceAcknowledgement element that contains the Identifier
and an AcknowledgementRange with attributes Lower and Upper,
in this case the numbers 1 and 1 respectively.
...
urn:...
...
...
This means the lowest message number received by the service was
1 and the highest message number was 1. When there are gaps in
the acknowledgement range the client RM infrastructure resends
lost messages. It releases message copies (for garbage
collection) after those messages have been acknowledged.
Two more application messages are sent with MessageNumbers 2 and
3 respectively.
...
2...
...>SECOND MESSAGE...
...
3...
...THIRD MESSAGE...
The responses contain AcknowledgementRanges with Lower/Upper
attributes 1/2 and 1/3 respectively.
TERMINATE is printed to the console then the port.close() is
called. This causes the RM infrastructure to send a message with
an empty Body. The header of this message contains a Sequence
element with the Identifier and a MessageNumber of 4. The header
also contains an Action element specifying LastMessage to
let the service know the reliable channel is going to be closed.
...
4
... ...
http://schemas.xmlsoap.org/ws/2005/02/rm/LastMessage
...
The service responds with a SequenceAcknowledgement containing
AcknowledgementRange 1/4 indicating all messages have been
received.
...>
...
...
If messages are missing the client resends them.
After the client RM infrastructure sends LastMessage and
receives a SequenceAcknowledgement response indicating that all
messages have been received, it sends a message with an Action
header element containing TerminateSequence.
Content-Type: application/soap+xml;charset="utf-8";
action=
"http://schemas.xmlsoap.org/ws/2005/02/rm/TerminateSequence"
This lets the service know that it can release all resources
associated with the reliable channel identified by the Identifier
element. The service responds with an HTTP 202 response.
null: HTTP/1.1 202 Accepted
Summary
This tip showed you how to build and run a reliable messaging
test in which a Metro-based client communicates with a WCF-based
service, in other words, a public WCF endpoint.
Of course, you can also run the same interoperability test or
other interoperability tests using a WCF-based client or
a Metro-based service. Running the tests with different
combinations of Metro-based and WSF-based clients and servers
should enable you to verify interoperability between Metro and
.NET. It will also enable you to become a contributer to the
open source Metro project (https://metro.dev.java.net/) and test
the interoperability of the code you contribute.
About the Author
Harold Carr is the engineering lead for enterprise web
services interoperability at Sun Microsystems. Previous to this
role, Harold was responsible for RMI-IIOP load-balancing and
fail-over in the Sun Java System Application Server. He designed
the core architecture used in Sun's CORBA ORB and in the
JAX-RPC 2.0 reference implementation and the scalable socket
communications architecture used in SJSAS HTTP and IIOP
remoting. Harold helped write the OMG Portable Object Adapter
specification and was chairperson of the OMG Portable
Interceptor specification. Previous to Sun, he did distributed
computing research at Hewlett-Packard Research Laboratories and
Schlumberger Research Laboratories, was Chief Architect of
Visual Lisp technology at Autodesk, and was a logic simulation
consultant for Cirrus Logic. He holds a Ph.D., in Computer
Science from the University of Utah.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
DEVELOPER ASSISTANCE
Need programming advice on Java EE? Try Developer Expert
Assistance
http://developers.sun.com/services/expertassistance/
. . . . . . . . . . . . . . . . . . . . . . .
Please read our Terms of Use and Licensing policies:
http://www.sun.com/share/text/termsofuse.html
http://developers.sun.com/dispatcher.jsp?uid=6910008
PRIVACY STATEMENT:
Sun respects your online time and privacy
http://sun.com/privacy.
You have received this based on your e-mail preferences. If you
would prefer not to receive this information, please follow the
steps at the bottom of this message to unsubscribe.
* FEEDBACK
Comments? Send your feedback on the Enterprise Java Technologies
Tech Tips to:
Enterprise_TechTips@sun.com
- ARCHIVES
You'll find the Enterprise Java Technologies Tech Tips archives at:
http://java.sun.com/developer/EJTechTips/index.html
- COPYRIGHT
Copyright 2007 Sun Microsystems, Inc. All rights reserved.
901 San Antonio Road, Palo Alto, California 94303 USA.
This document is protected by copyright. For more information, see:
http://java.sun.com/developer/copyright.html
Enterprise Java Technologies Tech Tips
October 26, 2007
Trademark Information: http://www.sun.com/suntrademarks/
Java, J2SE, J2EE, J2ME, and all Java-based marks are trademarks
or registered trademarks of Sun Microsystems, Inc. in the
United States and other countries.