Enterprise Java Technologies Tech Tips
Tips, Techniques, and Sample Code
Welcome to the Enterprise Java Technologies Tech Tips for
November 18, 2006. 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:
* Using Java Persistence With JavaServer Faces
Technology
* Using a Model Facade
These tips were developed using the Java EE 5 SDK. You can
download the SDK from the Java EE Downloads page.
(http://java.sun.com/javaee/downloads/index.jsp)
You can view this issue of the Tech Tips on the Web.
http://java.sun.com/mailers/techtips/enterprise/2006/TechTips_Nov06.html
You can download the sample archive for the Using Java
Persistence With JavaServer Faces Technology tip at
http://java.sun.com/mailers/techtips/enterprise/2006/download/ttnov2006jsfprs.zip
You can download the sample archive for the Using a Model Facade
tip at
http://java.sun.com/mailers/techtips/enterprise/2006/download/ttnov2006facade.zip
Any use of this code and/or information below is subject to the
license terms terms at
http://developers.sun.com/dispatcher.jsp?uid=6910008
See the Subscribe/Unsubscribe note at the end of this newsletter
to subscribe to Tech Tips that focus on technologies and products
in other Java platforms.
USING JAVA PERSISTENCE WITH JAVASERVER FACES TECHNOLOGY
by Roger Kitain
JavaServer Faces technology
(http://java.sun.com/j2ee/javaserverfaces/index.jsp), often
abbreviated as JSF, is a framework that simplifies building user
interfaces (UIs) for Java Platform, Enterprise Edition (Java EE)
and Java 2 Platform, Enterprise Edition (J2EE) applications. The
March 24, 2004 Tech Tip, "Introducing JavaServer Faces
Technology"(http://java.sun.com/developer/EJTechTips/2004/tt0324.html#2)
gave a brief overview of the technology. It also showed how to
create a JSF application that includes GUI components that are
modeled by the JSF framework. A later tip showed how to create
custom components with JavaServer Faces technology
(http://java.sun.com/developer/EJTechTips/2004/tt1123.html#2).
This tip examines a sample application that uses the Java
Persistence API with the JSF framework. A package that contains
the code for the sample application
(http://java.sun.com/mailers/techtips/enterprise/2006/download/ttnov2006jsfprs.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 Java Persistence API and JSF
The Java Persistence API (or simply Java Persistence)
(http://java.sun.com/javaee/technologies/entapps/persistence.jsp)
simplifies the entity persistence model and adds additional
capabilities that were not available in Enterprise JavaBeans
(EJB) 2.1 technology. It handles all of the details of how
relational data is mapped to Java objects, and it standardizes
object-relational mapping. The Java Persistence API is included
in the EJB 3.0 specification
(http://jcp.org/en/jsr/detail?id=220).
There are some JSF features that facilitate the use of Java
Persistence in web applications. Value binding expressions bind
UI components to model tier data, so that data can be pushed to
the model when a form submit occurs. Method binding expressions
bind UI components to action methods so that a method attached
to a component can execute when that component is activated. For
example, when a button is pressed it causes a form to be
submitted. Managed beans are JSF application beans that can be
instantiated on demand. They are the model tier in a JSF
application, and instances of these beans can be stored in
a request -- either in session or application scope.
The Java Persistence API also includes an EntityManager API that
you can use to persist entities to a database. You can inject
EntityManager instances into JSF managed beans to persist data.
EntityManager instances are not thread safe, so you should not
inject them into JSF managed beans that have a scope of session
or application.
Here's an example of injecting EntityManager instances into
a JSF managed bean (assume the bean in the example, BookBean, is
an application-scoped JSF managed bean):
public class BookBean {
@PersistenceContext EntityManager em;
...
public String placeOrder() {
...
em.persist(order);
...
}
}
However that's not a particularly good approach. Here is
a better approach. It uses the EntityManagerFactory to create
EntityManager instances. It also uses a request-scoped JSF
managed bean -- this helps ensure thread safety.
public class BookBean {
@PersistenceUnit EntityManagerFactory emf;
...
public String placeOrder() {
...
EntityManager em = emf.createEntityManager();
...
em.persist(order);
...
}
}
JSF Persistence Example
If you are familiar with JSF you might also be familiar with the
JSF "guess number" application. The application asks the user to
guess a number that the application picks within a range of
numbers (1-to-10).
The application begins with the display of an HTML page that
prompts for a number between a range. After entering a number,
the user presses the "Guess" button to submit the information.
If the user submits a number that is outside the range, or
submits an invalid digit (a letter, for example), the
application displays a validation error message from JSF.
If the user submits a valid number, the "response" page appears
indicating whether the guess is correct or not.
The response page also displays an "Again" button. Pressing this
button navigates back to the initial page to allow more guesses.
A user can navigate back and forth between the pages until he
makes a correct guess. If the user presses the Again button
after making a correct guess it implicitly starts a new game.
Java Persistence is used to store in a database all the guess
attempts, and it is used to display (or play back) guess
attempts that have been stored in the database.
Let's take a look at some of the code for the guess number
application.
Here is the script that creates the database table:
create table USERGUESS
(ID INT NOT NULL,
GUESS VARCHAR(10) NOT NULL,
OUTCOME VARCHAR(10) NOT NULL,
PRIMARY KEY(ID));
Here is an entity class, UserGuess, that corresponds to the
database table:
...
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity
public class UserGuess implements java.io.Serializable {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private int id;
private String guess;
public String getGuess() {
return guess;
}
public void setGuess(String guess) {
this.guess = guess;
}
private String outcome;
public String getOutcome() {
return outcome;
}
public void setOutcome(String outcome) {
this.outcome = outcome;
}
}
The UserGuess entity consists of three properties, id, guess,
and outcome, that correspond to the database columns. The id is
the primary key that is automatically generated when a row of
data is added to the database.
A JSF managed bean, UserNumberBean.java, contains the processing
logic for the application. This bean has other methods such as
validate, but let's focus on the code that uses Java
Persistence.
This application uses a container-managed EntityManager, so it
must be controlled using the Java Transaction API (JTA). First,
let's inject the instances:
...
public class UserNumberBean {
...
// This injects the default entity manager factory
@PersistenceUnit
private EntityManagerFactory emf;
// This injects a user transaction object.
@Resource
private UserTransaction utx;
...
You can use the injected EntityManagerFactory instance anywhere
to create and use an EntityManager. You can also use the
injected UserTransaction instance to control the transactions:
...
public class UserNumberBean {
...
/**
* This method persists each attempted guess (number).
*/
private String sameGame() {
String message = null;
EntityManager em = null;
try {
em = emf.createEntityManager();
utx.begin();
em.persist(userGuess);
utx.commit();
} catch (Exception ee) {
try {
utx.rollback();
} catch (Exception re) {}
if (logger.isLoggable(Level.SEVERE)) {
logger.log(Level.SEVERE, "Database Error:",
ee.getCause());
}
message += "Database Error: "+ee.getCause();
} finally {
if (em != null) {
em.close();
}
}
return message;
}
...
/**
* This method clears the database table in preparation
* of a new game.
*/
private String newGame() {
String message = null;
EntityManager em = null;
String statement = "delete from UserGuess";
try {
em = emf.createEntityManager();
utx.begin();
em.createQuery(statement).executeUpdate();
utx.commit();
} catch (Exception ee) {
try {
utx.rollback();
} catch (Exception re) { }
if (logger.isLoggable(Level.SEVERE)) {
logger.log(Level.SEVERE, "Database Error:",
ee.getCause());
}
message = "Database Error: "+ee.getCause();
} finally {
if (em != null) {
em.close();
}
}
return message;
}
...
Posting From The Client
The initial page has a text field for entering a number and
a button labeled "Guess" for submitting the guess. Here is
a snippet of the greeting.jsp page:
...
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<%@ taglib uri="http://java.sun.com/jsf/core"
prefix="f" %>
...
...
The component displays the attempted guesses that
have been stored in the database for the current game. When the
page renders initially, or at the start of each new game, the
component does not render. This is controlled by
the boolean property hasGuesses on the bean UserNumberBean as
identified by the expression #{UserNumberBean.hasGuesses}.
A value of true indicates that guesses have been attempted.
...
public class UserNumberBean {
...
// Indicates that we have some attempted guesses.
private boolean hasGuesses = false;
...
/**
* -- Accessor methods for the hasGuesses
* property (used to control rendering of the
* DataTable of attempted guesses).
*/
public void setHasGuesses(boolean hasGuesses) {
this.hasGuesses = hasGuesses;
}
public boolean getHasGuesses() {
return hasGuesses;
}
...
The expression "#{UserNumberBean.guessList}" refers to the
Java Collection of UserGuess entity beans. When this expression
is evaluated during rendering, the UserNumberBean.getGuessList
method uses Java Persistence to load the collection from the
database:
...
public class UserNumberBean {
...
// The attempted guesses.
private Collection guessList;
...
/**
* This method loads the Collection from the
* database. The Collection is used by the
* DataTable to display attempted guesses.
*/
public Collection getGuessList() {
EntityManager em = emf.createEntityManager();
guessList = em.createQuery(
"select g from UserGuess g").getResultList();
return guessList;
}
...
The component renders the results.
Running the Sample Code
A sample package accompanies this tip that demonstrates the
techniques covered in the tip. You can deploy the sample package
on any web container that supports the Servlet 2.5 API,
JavaServer Pages (JSP) Technology 2.1, and JavaServer Faces
Technology 1.2. These instructions also assume that you are
using the Java EE 5 SDK.
To install and run the sample:
1. If you haven't already done so, download the Java EE 5 SDK
from the Java EE Downloads Page.
(http://java.sun.com/javaee/downloads/index.jsp).
2. Set the following environment variables:
o JAVAEE_HOME. This should point to where you installed the
Java EE 5 SDK.
o JAVA_HOME. This should point to the location of JDK 5.0 on
your system. JDK is included in the Java EE 5 SDK bundle
that you downloaded. (In Windows, it's in the jdk
subdirectory.)
Add $JAVA_HOME/bin and $JAVAEE_HOME/bin to your PATH
environment variable.
3. Download the sample package for the tip
(http://java.sun.com/mailers/techtips/enterprise/2006/download/ttnov2006jsfprs.zip)
and extract its contents. You should now see the newly
extracted directory as /guessNumber,
where is the directory where you
installed the sample package. For example, if you extracted
the contents to C:\ on a Windows machine, then your newly
created directory should be at C:\guessNumber. The
guessNumber directory contains the web archive, web-app.war,
for the application, and the subdirectories src and web for
viewing source. It also contains a script, db.sql, for
creating the database table.
4. Start the derby database by entering the following command:
$JAVAEE_HOME/bin/asadmin start-database
5. Start the Application Server by entering the following
command:
$JAVAEE_HOME/bin/asadmin start-domain domain1
6. Create the database table for the application:
a. Set your CLASSPATH to include:
$JAVAEE_HOME/javadb/lib/derbyclient.jar
$JAVAEE_HOME/javadb/lib/derbytools.jar
$JAVAEE_HOME/javadb/lib/derby.jar
b. Go to /guessNumber/ directory.
c. Get into ij:
java org.apache.derby.tools.ij
d. At the "ij" prompt enter the following commands:
ij>DRIVER 'org.apache.derby.jdbc.ClientDriver';
ij>CONNECT 'jdbc:derby://localhost:1527/sun-appserv-samples';
If the database does not exist yet you need to enter
the following command:
CONNECT 'jdbc:derby://localhost:1527/sun-appserv-samples;create=true';
e. At the "ij" prompt, execute:
ij> run 'db.sql';
6. Deploy the sample by copying
/guessNumber/wep-app.war to
$JAVAEE_HOME/domains/domain1/autodeploy
7. Open your browser to the URL: http://localhost:8080/web-app/
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
JavaServer Faces technology in 2001 as a member of the reference
implementation team. He has experience with Servlet and JSP
technologies. Most recently, Roger has been involved with
different rendering technologies for JavaServer Faces technology.
USING A MODEL FACADE
by Sean Brydon and Yutaka Yoshida
A number of recent Tech Tips, including the other tip in this
issue, "Using Java Persistence With JavaServer Faces
Technology," have covered various aspects of the Java
Persistence API. What's significant is that you can use the Java
Persistence API to manage persistence in the domain model of
your Java EE 5 applications and take advantage of additional
capabilities that were not available in the J2EE platform.
However there are a number of things to consider when you use
Java Persistence. For example, a Java Persistence client such as
a servlet, JSP page, or a JSF managed bean, might need to access
various types of APIs to access entities in the model. (In this
tip, the term "client" refers to web components such as JSF
managed beans, servlets, or JSP pages that call methods on Java
Persistence entity objects.) These APIs include Java Transaction
(JTA) APIs, EntityManager APIs, as well as the Java Persistence
API. Also, the client code might need to interact with several
entities, where each entity has a different API and perhaps
different requirements for transactions and entity manager
operations. The need to access these different types of APIs, as
well as the multiplicity of transactions and entity manager
operations can lead to a lot of complexity in the client code.
As your application grows, you might need to repeat the same
code for access to multiple entities. This might involve copying
similar data access logic into each servlet or managed bean that
needs to access the entities. Not only is this repetitive code
difficult to manage, but it tightly couples the code to the
entity model.
A Model Facade is a good way to simplify the code in a Java
Persistence client.
What is a Model Facade?
A Model Facade (or simply a "Facade") is a design pattern. The
Facade pattern defines a higher-level class that encapsulates
and centralizes the interactions between Java Persistence
clients and the entities and operations of the Java Persistence
API. The pattern provides a single interface for operations on
a set of entities. Using the Facade pattern can make the code in
your Java Persistence clients cleaner. A web component that uses
a Facade to access the model tier does not have to be aware of all
the details of the APIs for each entity. Neither does the web
component need to be aware of the persistence mechanisms being
used when accessing the entity managers or transaction managers.
Also, if you add a Facade between the calling clients and the
entities in the model tier, it makes your code more
loosely-coupled and easier to maintain.
A Facade isn't limited to use with Java Persistence. It's also
useful with other persistence technologies such as JDBC.
Designing and Coding a Facade
To illustrate how much cleaner it is to code with a Facade,
let's look at a "before" and "after" example. The "before"
example shows the code for a servlet that accesses entities in
a model tier. The "after" example shows the servlet code if
a Facade is used.
Here is the "before" code:
public class MyWebClient ... {
...
public void doGet(HttpServletRequest request,
HttpServletResponse response)
{
...
//processing a web request to
//add a new Item to the database
if (selectedURL.equals("additem.do")) {
String desc = request.getParameter("item_desc");
String name = request.getParameter("item_name");
...
Item item = new Item();
item.setName(name);
item.setDescription(desc);
//now access entities in model tier
EntityManager em =
emf.createEntityManager();
try{
utx.begin();
em.joinTransaction();
em.persist(item);
utx.commit();
} catch(Exception exe){
System.out.println("Error persisting item: "+exe);
try {
utx.rollback();
} catch (Exception e) {}
} finally {
em.close();
}
}
...
Here is the "after" code:
public class MyWebClient { ...
...
public void doGet(HttpServletRequest request,
HttpServletResponse response)
{
...
//processing a web request to
//add a new Item to the database
if (selectedURL.equals("additem.do")) {
String desc = request.getParameter("item_desc");
String name = request.getParameter("item_name");
...
Item item = new Item();
item.setName(name);
item.setDescription(desc);
//now access entities in model tier
MyModelFacade myfacade = new MyModelFacade();
myfacade.addItem(item);
}
One strategy to implement a Facade is to use a web component as
the facade class. This strategy is useful if you want to have
a web-only architecture and you don't want to use an EJB
container. It's also a useful strategy if you want to keep the
Facade in the web container. If your application uses a web-only
architecture and its web components access the entities, then
using a Facade can help clean up your code. Note that the focus
in this tip is on implementing a Facade for web-only
applications that are not using an EJB tier, that is, Java EE
applications that do not use the EJB container or services.
An Example Facade for a Web-Only Application
Let's take a look at the code for a Facade. You can find the
source code for the Facade as well as the code for the other
examples in this tip in the sample application package
(http://java.sun.com/mailers/techtips/enterprise/2006/download/ttnov2006facade.zip)
that accompanies the tip.
public class CatalogFacade implements ServletContextListener {
@PersistenceUnit(unitName="CatalogPu")
private EntityManagerFactory emf;
@Resource UserTransaction utx;
public CatalogFacade(){}
public void contextDestroyed(ServletContextEvent sce) {
if (emf != null && emf.isOpen()) {
emf.close();
}
}
public void contextInitialized(ServletContextEvent sce) {
ServletContext context = sce.getServletContext();
context.setAttribute("CatalogFacade", this);
}
public void addItem(Item item) throws InvalidItemException {
EntityManager em = emf.createEntityManager();
if(item.getName().length() == 0)
throw new InvalidItemException("The item" +
" name cannot be empty. Please specify a name for the item. ");
try {
utx.begin();
em.joinTransaction();
em.persist(item);
utx.commit();
} catch(Exception exe){
System.err.println(exe);
try {
utx.rollback();
} catch (Exception e){
e.initCause(exe);
throw new RuntimeException(e);
}
throw new RuntimeException(exe);
} finally {
if (em != null) {
em.close();
}
}
}
public Item getItem(int itemID){
EntityManager em = emf.createEntityManager();
Item item = em.find(Item.class,itemID);
em.close();
return item;
}
public List- getAllItems(){
EntityManager em = emf.createEntityManager();
List
- items = em.createQuery(
"SELECT OBJECT(i) FROM Item i").getResultList();
em.close();
return items;
}
}
There are a couple design choices to notice in the CatalogFacade
example:
o The Facade implements the ServletContextListener interface.
This allows it to use annotations that are useful when
accessing Java Persistence entities and related services in
the Java EE platform. If you want the Facade to use
annotations and dependency injection, the Facade must be a web
component. Plain-old Java objects (POJOs) cannot use Java EE 5
dependency injection.
o The Facade does not expose calling clients to
persistence-related exceptions. The example Facade catches
the exceptions from the Java Persistence and Java Transaction
APIs and throws a runtime exception instead.
o The Facade handles all the transactional code and the entity
manager interactions.
o The Facade does not add an extra interface (beyond that of the
Facade itself). An extra interface can make the code more
loosely-coupled from the entities and model tier, but it
requires an extra class. However you can consider adding an
extra interface in more complex cases.
o The Facade returns Java Persistence objects to be used as
POJOs by the client code. It does not return a data transfer
object or a value object that is a copy of the Java
Persistence entities. Java Persistence entities are managed by
the entity manager and can be used as model objects. Entities
can be used as POJOs. The Facade returns the Java Persistence
entities in detached mode. If you want to further
loosely-couple the code from the entities and model tier,
consider adding objects that are client-specific. Return those
instead of the entity objects.
o The Facade is thread-safe and only stores objects that can be
safely cached. It does not cache any stateful objects. The
facade only holds the EntityManagerFactory and the
UserTransaction objects, both of which are thread-safe and can
be held and cached for subsequent requests. This allows this
Facade to be cached and shared. Note that web components
should not hold EntityManager objects because doing so is not
thread safe.
Notice too that in the addItem method, JTA APIs for transaction
demarcation are needed to access the entities. Also,
EntityManager APIs are needed to store the new Item in the
database. Having this code in one place in a Facade class is
better than repeating the code in your application whenever you
need to access an entity.
Using the Facade
Now let's look at how a web component such as a servlet uses the
example Facade.
public class CatalogServlet extends HttpServlet {
private CatalogFacade cf;
private ServletContext context;
private Map nameSpace;
public void init(ServletConfig config)
throws ServletException {
context = config.getServletContext();
cf = (CatalogFacade)context.getAttribute("CatalogFacade");
initPathMapping();
}
...
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
...
try {
if (selectedURL.equals("additem.do")) {
//get values from request and set in a
//new Item to then add to database
String desc = request.getParameter("item_desc");
String name = request.getParameter("item_name");
...
Item item = new Item();
item.setName(name);
item.setDescription(desc);
...
cf.addItem(item); //now call Facade
...
}
}
The servlet uses the init method to obtain the Facade. It then
stores the Facade as a field in the servlet so that it can be
used and shared by other client requests.
private CatalogFacade cf;
By using the Facade, the servlet is shielded from the details of
the entities and from any persistence operations required to
access the entities.
Running the Sample Code
A sample package accompanies this tip that includes a Model
Facade. To install and run the sample:
1. If you haven't already done so, download the Java EE 5 SDK
from the Java EE Downloads Page
(http://java.sun.com/javaee/downloads/index.jsp). Also be
sure to have an installed version of the Java Platform
Standard Edition (Java SE) 5 SDK.
2. Download the sample package for the tip
(http://java.sun.com/mailers/techtips/enterprise/2006/download/ttnov2006facade.zip)
and extract its contents. You should now see the newly
extracted directory as /ttnov2006facade,
where is the directory where you
installed the sample package. For example, if you extracted
the contents to C:\ on a Windows machine, then your newly
created directory should be at C:\ttnov2006facade. The
TechTip-Facade directory below the ttnov2006facade directory
contains the source files and other support files for the
sample.
3. Edit the build.properties file in the TechTip-Facade
directory and set properties appropriately for your
environment. For example, set javaee.home to point to your
Java EE 5 installation directory.
4. Start the derby database by entering the following command:
$JAVAEE_HOME/bin/asadmin start-database
5. Start the Application Server by entering the following
command:
$JAVAEE_HOME/bin/asadmin start-domain domain1
6. Change to the TechTip-Facade directory and enter the command:
ant setup
This sets up the database resources.
7. Enter the command:
ant run
This builds, deploys, and launches the sample application.
The application is the Java Persistence sample application
taken from the Java BluePrints Solutions Catalog
(https://bpcatalog.dev.java.net/)
Click on the links in the displayed page to retrieve or add
items in a catalog. If you examine the source for the
application, you'll see that it uses a Model Facade as the
interface for operations on the persistent entities in the
catalog.
Summary
If you are building a Java EE 5 web application that uses the
Java Persistence API, consider refactoring your code by
introducing a Model Facade.
For additional information about Facades and the Java Persistence
API see:
o Java Petstore 2.0 Reference Application, Early Access.
(https://blueprints.dev.java.net/petstore/index.html)
o Java Persistence APIs.
(https://blueprints.dev.java.net/bpcatalog/ee5/persistence/)
o GlassFish Project - Java Persistence API implementation home page
(https://glassfish.dev.java.net/javaee5/persistence/)
o Feedback, discussions, or questions about the Java BluePrints
(https://blueprints.dev.java.net/feedback.html)
About the Authors
Sean Brydon is an engineer with Sun Microsystems where he is the
technical lead for the Java BluePrints program. He has been
involved with the Java BluePrints since its inception. He is an
author of the Addison-Wesley Java-series books, "Designing
Enterprise Applications with the Java 2 Platform, Enterprise
Edition," and "Designing Web Services with the J2EE 1.4
Platform." He is a regular speaker on enterprise application
design.
Yutaka Yoshida was a Servlet 2.4 specification lead, and is
currently working in the Java BluePrints project. He has been
involved in designing and developing the Java Adventure Builder
reference application, the Java BluePrints Solutions Catalog,
and the Java Pet Store 2.0 reference application.
DEVELOPER ASSISTANCE
Need programming advice on Java EE? Try Developer Expert
Assistance
(http://developers.sun.com/services/expertassistance/)
JAVA EE SDK CONTEST
Download the Java EE SDK. Then enter the Java EE SDK Contest
(http://java.sun.com/javaee/community/campaigns/nano-112006/welcome.jsp)
and get a chance to win an iPod Nano. The contest ends
November 30.
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
* SUBSCRIBE/UNSUBSCRIBE
Subscribe to other Java developer Tech Tips:
- Core Java Technologies Tech Tips. Get tips on using core
Java technologies and APIs, such as those in the Java 2
Platform, Standard Edition (J2SE).
- Wireless Developer Tech Tips. Get tips on using wireless
Java technologies and APIs, such as those in the Java 2
Platform, Micro Edition (J2ME).
To subscribe to these and other JDC publications:
- Go to the Sun Developer Network - Subscriptions page
(https://softwarereg.sun.com/registration/developer/en_US/subscriptions),
choose the newsletters you want to subscribe to and click
"Submit".
- To unsubscribe, go to the Subscriptions page,
(https://softwarereg.sun.com/registration/developer/en_US/subscriptions)
uncheck the appropriate checkbox, and click "Submit".
- To use our one-click unsubscribe facility, see the link at
the end of this email.
- ARCHIVES
You'll find the Enterprise Java Technologies Tech Tips archives at:
http://java.sun.com/developer/EJTechTips/index.html
- COPYRIGHT
Copyright 2006 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
November 18, 2006
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.