You are receiving this e-mail because you elected to receive e-mail from Sun Microsystems, Inc. To update your communications preferences, please see the link at the bottom of this message. We respect your privacy and post our privacy policy prominently on our Web site http://sun.com/privacy/

Please do not reply to the mailed version of the newsletter, this alias is not monitored. Feedback options are listed in the footer for both content and delivery issues.
  Welcome to the Enterprise Java Technologies Tech Tips.
Enterprise Java Technologies
TECHNICAL TIPS
In this Issue
 
Here you'll get tips on using enterprise Java technologies and APIs, such as those in Java 2 Platform, Enterprise Edition (J2EE) and Java Platform, Enterprise Edition 5 (Java EE 5).

This issue covers:

» Using Ajax with Java Technology
» Converting a POJO to a Persistent Entity

These tips were developed using an open source reference implementation of Java EE 5 called GlassFish. You can download GlassFish from the GlassFish Project page.

You can download the sample archive for the Ajax tip.
You can download the sample archive for the POJO objects tip.

Any use of this code and/or information below is subject to the license terms.

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.

For more Java technology content, visit these sites:

java.sun.com - The latest Java platform releases, tutorials, and newsletters.

java.net - A web forum where enthusiasts of Java technology can collaborate and build solutions together.

java.com - Hot games, cool apps -- Experience the power of Java technology.

USING Ajax WITH JAVA TECHNOLOGY
 

by Greg Murray

(Ajax) stands for Asynchronous JavaScript and XML. In essence, Ajax is an efficient way for a web application to handle user interactions with a web page -- a way that reduces the need to do a page refresh or full page reload for every user interaction. This enables rich behavior (similar to that of a desktop application or plugin-based web application) using a browser. AJAX interactions are handled asynchronously in the background. As this happens, a user can continue working with the page. AJAX Interactions are initiated by the JavaScript in the web page. When the AJAX interaction is complete, JavaScript updates the HTML source of the page. The changes are made immediately without requiring a page refresh. AJAX interactions can be used to do things such as validate form entries (while the user is entering them) using server-side logic, retrieve detailed data from the server, dynamically update data on a page, and submit partial forms from the page.

What is particularly attractive about this is that Ajax applications do not require a separate plug-in, and are platform and browser-neutral. That said, (Ajax) is not supported as well in older browsers. Care needs to be taken in writing client-side script that accounts for the differences between browsers. You might consider using a JavaScript library that abstracts the browser differences and in some cases support older browsers using alternative interaction techniques. For more details, see the AJAX FAQ for the Java Developer

So Where Does Java Technology Fit In?

Java technology and Ajax work well together. Java technology provides the server-side processing for (Ajax) interactions. It can provide this through servlets, JavaServer Pages (JSP) technology, JavaServer Faces (JSF) technology, and web services. The programming model for handling AJAX requests uses the same APIs that you would use for conventional web applications. JSF technology can be used to create reusable components that generate the client-side JavaScript and corresponding server-side AJAX processing code. Let's look at an example that uses AJAX and servlets.

Autocomplete Example

Imagine a web page in which a user can search for information about an employee. The page includes a field where the user can enter the name of the employee. In this example the entry field has an autocomplete feature. In other words, the user can type in part of the employee name, and the web application attempts to complete the name by listing all employees whose first or last name begins with the characters entered. The autocomplete feature saves the user from having to remember the complete name of the employee or from looking for the name on another page.

autocomplete example

Implementing autocomplete in a search field is something that can be performed using (Ajax). To do it, you need to provide code on the client and on the server.

On the Client

First, the user specifies the URL of a page that is loaded by the browser. For this example let's assume the page is an HTML page that is generated by a JSF component, servlet, or JSP page. The page contains a form text field that has an attribute onkeyup with the name of a JavaScript function doCompletion(). This function is called each time a key is pressed in the form text field.

    <input type="text"
          size="20"
          autocomplete="off"
          id="complete-field"
                      name="id"
          onkeyup="doCompletion();">

Let's assume that a user types in an "M" character in the form text field. In response, the doCompletion() function is called which, in turn, initializes an XMLHttpRequest object:

   function initRequest() {
       if (window.XMLHttpRequest) {
           return new XMLHttpRequest();
       } else if (window.ActiveXObject) {
           isIE = true;
           return new ActiveXObject("Microsoft.XMLHTTP");
       }
   }

   function doCompletion() {
       if (completeField.value == "") {
           clearTable();
       } else {
           var url = "autocomplete?action=complete&id=" + 
                   escape(completeField.value);
           var req = initRequest();
           req.onreadystatechange = function() {
               if (req.readyState == 4) {
                   if (req.status == 200) {
                       parseMessages(req.responseXML);
                   } else if (req.status == 204){
                       clearTable();
                   }
               }
           };
           req.open("GET", url, true);
           req.send(null);
       }
   }

The XMLHttpRequest object is not currently part of standard JavaScript (efforts are underway to standardize it), but is a de facto standard and is the heart of (Ajax). This object is responsible for interacting over HTTP with a server-side component (in this case, a servlet).

Three parameters are specified when you create an XMLHttpRequest object: a URL, the HTTP method (GET or POST), and whether or not the interaction is asynchronous. In the XMLHttpRequest example, the parameters are:

The URL autocomplete, and the text from the complete-field (an M character):
     var url = "autocomplete?action=complete&id=" + 
             escape(completeField.value);

GET, signifying the HTTP interactions uses the GET method, and true, signifying that the interaction is asynchronous:
     req.open("GET", url, true);

A callback function needs to be set when you use asynchronous calls. This callback function is called asynchronously at specific points during HTTP interaction when the readyState property on the XMLHttpRequest changes. In the example the callback function is processRequest(). It's set as the XMLHttpRequest.onreadystatechange property to a function. Notice the call to the parseMessages function when the readState is "4". The XMLHttpRequest.readyState of "4" signifies the successful completion of the HTTP interaction.

The HTTP interaction begins when XMLHttpRequest.send() is called. If the interaction is asynchronous, the browser continues to process events in the page.

On the Server

The XMLHttpRequest makes an HTTP GET request to the URL autocomplete, which is mapped to a servlet called AutoComplete. The doGet() method of the AutoComplete servlet is called. Here is what the doGet() method looks like:

   public void doGet(HttpServletRequest request, 
           HttpServletResponse response) 
        throws IOException, ServletException { 
       ... 
       String targetId = request.getParameter("id");
       if (targetId != null) targetId = targetId.trim().toLowerCase();
       Iterator it = employees.keySet().iterator();
       while (it.hasNext()) {
           EmployeeBean e = (EmployeeBean)employees.get(
                   (String)it.next());
           if ((targetId != null) &&
              (e.getFirstName().toLowerCase ().startsWith(targetId) ||
              e.getLastName().toLowerCase().startsWith(targetId))
              && !targetId.equals("")) {
              sb.append("<employee>"); 
              sb.append("<id>" + e.getId() + "</id>"); 
              sb.append("<firstName>" + e.getFirstName() + 
                      "</firstName>"); 
              sb.append("<lastName>" + e.getLastName() + 
                      "</lastName>"); 
              sb.append("</employee>"); 
              namesAdded = true; 
           } 
       } 
       if (namesAdded) { 
           response.setContentType("text/xml"); 
           response.setHeader("Cache-Control", "no-cache"); 
           response.getWriter().write("<employees>" + 
                   sb.toString() + "</employees>"); 
       } else { 
           response.setStatus(HttpServletResponse.SC_NO_CONTENT); 
       } 
    }

As you can see in this servlet, there is nothing really new you need to learn to write server-side code for Ajax processing. The response content type needs to be set to text/xml for cases where you want to exchange XML documents. With (Ajax), you can also exchange plain text or even snippets of JavaScript which may be evaluated or executed by the callback function on the client. Note too that some browsers might cache the results, and so it might be necessary to set the Cache-Control HTTP header to no-cache. In this example, the servlet generates an XML document that contains all employees with a first or last name beginning with the character M. Here is an example of an XML document that is returned to the XMLHttpRequest object that made the call:

   <employees>
      <employee>
        <id>3</id>
        <firstName>George</firstName>
        <lastName>Murphy</lastName>
      </employee>
      <employee>
        <id>2</id>
        <firstName>Greg</firstName>
        <lastName>Murphy</lastName>
      </employee>
      <employee>
        <id>11</id><firstName>Cindy</firstName>
        <lastName>Murphy</lastName>
        </employee>
      <employee>
        <id>4</id>
        <firstName>George</firstName>
        <lastName>Murray</lastName>
      </employee>
      <employee>
        <id>1</id>
        <firstName>Greg</firstName>
        <lastName>Murray</lastName>
     </employee>
   </employees>

Returning to the Client

When the XMLHttpRequest object that made the initial call receives the response, it calls the parseMessages() function (see the initialization of the XMLHttpRequest earlier in this example for more details). Here is what the parseMessages() function looks like:

   function parseMessages(responseXML) {
       clearTable();
           var employees = responseXML.getElementsByTagName(
                   "employees")[0];
       if (employees.childNodes.length > 0) {
           completeTable.setAttribute("bordercolor", "black");
           completeTable.setAttribute("border", "1");
       } else {
           clearTable();
       }
    
       for (loop = 0; loop < employees.childNodes.length; loop++) {
           var employee = employees.childNodes[loop];
           var firstName = employee.getElementsByTagName(
                   "firstName")[0];
           var lastName = employee.getElementsByTagName(
                   "lastName")[0];
           var employeeId = employee.getElementsByTagName(
                   "id")[0];
           appendEmployee(
                   firstName.childNodes[0].nodeValue,
                   lastName.childNodes[0].nodeValue, 
                   employeeId.childNodes[0].nodeValue);
       }
   }

The parseMessages() function receives as a parameter an object representation of the XML document returned by the AutoComplete servlet. The function programmatically traverses the XML document, and then uses the results to update the contents of the HTML page. This is done by injecting into a <div> element whose id is "menu-popup" the HTML source for the names in the XML document:

   <div style="position: absolute; 
      top:170px;left:140px" id="menu-popup">

As the user enters more characters, the list shortens. The user can then click on one of the names.

Hopefully by now you realize that Ajax is simply exchanging information over HTTP in the background of a page, and updating that page dynamically based on the results. For more information about (Ajax) and Java technology, see the technical article Asynchronous JavaScript Technology and XML (AJAX) With Java 2 Platform, Enterprise Edition. Also see the AJAX BluePrints page, and the AJAX FAQ for the Java Developer in Greg Murray's blog.

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.4 API (or greater). To install and run the sample:

If you haven't already done so, download GlassFish from the GlassFish Project page. GlassFish supports Servlet 2.5 and the JSP Standard Tag Library (JSTL) "out of the box". If you are using a J2EE 1.4 or Servlet 2.4 container you might need to include the JSTL JAR files in the web/WEB-INF/lib directory.

Set the following environment variables:
GLASSFISH_HOME. This should point to where you installed GlassFish (for example C:\Sun\AppServer)
ANT_HOME. This should point to where ant is installed. Ant is included in the GlassFish bundle that you downloaded. (In Windows, it's in the lib\ant subdirectory.)
JAVA_HOME. This should point to the location of JDK 5.0 on your system.

Also, add the ant location to your PATH environment variable.

Download the sample file and extract its contents. You should now see the newly extracted directory as <install_dir>\ajax-autocomplete. For example, if you extracted the contents to C:\ on a Windows machine, then your newly created directory should be at C:\ajax-autocomplete.

Go to the ajax-autocomplete directory and copy the build.properties.sample to a build.properties file.

Open the build.properties file and set the servlet.jar property to a JAR file that contains the Servlet 2.4 (or greater) API. In the case of GlassFish, the JAR file is <gf_install_dir>/glassfish/lib/javaee.jar, where <gf_install_dir> is where you installed GlassFish. Set the javaee.autodeploy directory to the directory where the web container will auto-deploy the application. On GlassFish this directory is <gf_install_dir>/glassfish/domains/domain1/autodeploy.

Start GlassFish by entering the following command:
<GF_install_dir>\bin\asadmin start-domain domain1

where <GFinstall_dir> is the directory where you installed Glassfish.

Use the Ant tool to build and deploy the application. GlassFish has a copy of Ant in the <gf_install_dir>/glassfish/bin/asant directory. You can also download Ant from the Apache Ant Project page.

To build, enter the following command.
      ant

To deploy the application, enter the following command:
      ant deploy
Open your browser to the following URL: http://localhost:8080/ajax-autocomplete/.

If you are using NetBeans 4.1 or greater, the sample is included and runnable from the tool by selecting Help -> BluePrints Solutions Catalog. From there select the Ajax -> Autocomplete example and you are done. You can run the example from within NetBeans and modify it if you choose.

When you run the example it will look as follows:
example autocomplete

Click on a name in the list to display information about the employee.
example autocomplete - Employee Info

About the Author

Greg Murray is the servlet specification lead. Greg is a former member of the Java BluePrints team, and was responsible for the web tier recommendations. He is leading the Ajax effort at Sun with the help of the BluePrints team. Greg has experience with internationalization, web services, J2SE standalone clients, and (Ajax)-based web clients.

Back to Top

CONVERTING A POJO TO A PERSISTENT ENTITY
 

by Sriramulu Lakkaraju and Abhijit Kumar

One of the goals of Java EE 5 is ease of development, and the new Java Persistence API that is defined as part of the Enterprise JavaBeans (EJB) 3.0 specification, JSR-220, is a key component designed to meet that goal. The popular Java Servlet API 2.5 also includes some minor changes that support ease of development. In this Tech Tip, you'll see an example of the Java Persistence API in use from a Java Servlet. The example shows you how to convert a POJO (Plain Old Java Object) to a persistent entity, and how to use that entity from a Java Servlet. You'll also have the opportunity to run a sample application that uses these features.

Converting a POJO to a Persistent Entity

Let's start with a POJO. (You can examine the POJO as well as the other source code for the example by downloading the sample package and extracting its contents as described in the section Running the Sample Code.) In this example, the POJO is a simple class named Customer that is implemented as a JavaBean component. The class has attributes such as customerId, firstName, lastName, company, address, phoneNumber, and emailAddress. As is the case for all JavaBean components, the Customer class has a public no-argument constructor, and has getter and setter methods to access attributes.

 package com.example.entity;

   public class Customer implements java.io.Serializable {

       private Integer customerId;
       private int version;
       private String firstName;
       private String lastName;
       private String company;
       
   ...
   
   public Integer getCustomerId() {
           return customerId;
       }
   
       protected void setCustomerId(Integer customerId) {
           this.customerId = customerId;
       }
   ...

In its current form, the class cannot be persisted -- for example, you can't save it in a relational database. To persist the class you need to convert it to an entity. The Enterprise JavaBeans 3.0 specification (JSR-220) defines an entity as a lightweight, persistent domain object. The Java Persistence API defines several annotations that help with converting a POJO to an entity.

The first steps in converting a POJO to entity are to import persistence annotations into the Customer class and then mark the class with the annotation @Entity:

   package com.example.entity;

   import javax.persistence.*;

   @Entity
   public class Customer implements java.io.Serializable {

To demonstrate it's persistence, the entity in this example will be stored in a relational database -- more specifically, an Apache Derby database (the Apache Derby database is packaged with GlassFish). Here is the SQL that is used to create the table where the entity will be stored.

   CREATE TABLE Customer (
      custId INTEGER PRIMARY KEY NOT NULL,
       firstName VARCHAR(60),
       lastName VARCHAR(60),
       company VARCHAR(255),
       address_1 VARCHAR(255),
       address_2 VARCHAR(255),
       city VARCHAR(60),
       state VARCHAR(60),
       zip VARCHAR(10),
       emailAddress VARCHAR(80),
       phoneNumber VARCHAR(80)
   ) 

The next step is to specify the table for the entity by marking the Customer class with the annotation @Table:

   package com.example.entity;

   import javax.persistence.*;

   @Entity
   @Table(name="customer")
   public class Customer {

Notice that the name of the database table (Customer) matches the unqualified class name of the entity (the fully-qualified class name is com.example.entity.Customer). If it didn't, additional annotations would be needed to map the table name. If no @Table annotation is specified for an entity class, all of the default values defined by the @Table annotation apply. The @Table annotation can be dropped if the table name matches the unqualified class name (for this reason, the @Table annotation is not specified in the Customer class in the sample supplied with this tip).

Every entity must have a primary key. For the customer database table, the primary key is customerId. Here is how the primary key is specified in the example:

   @Id(name="custId")
   
   public String getCustomerId(){
       return customerId;
   }   

The next step is to map the bean properties to the database attributes. You do this using the @Column annotation. In keeping with the ease-of-use theme in Java EE 5, there is a default mapping of bean properties to database attributes. So you only need to annotate a bean property if its name is different than its corresponding database attribute name. Here are the property names used in the Customer class:

    private Integer customerId;
    private String firstName;
    private String lastName;
    private String company;
    private String address1;
    private String address2;
    private String city;
    private String state;
    private String zip;
    private String emailAddress;
    private String phoneNumber;

In fact, there are a few differences between the bean property names and the corresponding database attribute names. For example, the class includes a property named address1 for the first line of the address. The corresponding database attribute is address_1. So using the annotation @Column, you need to annotate the accessor method for the attribute address1 and map it appropriately to the database attribute:

    @Column(name="address_1")
    public String getAddress1() {
        return address1;
    } 

Next, let's add a few query methods to the Customer class. The queries use an interface called EntityManager (javax.persistence.EntityManager). As the interface name suggests, the EntityManager interface allows you to manage entities. Here's a query that retrieves all customers from the database table.

    public static List<Customer> findAllCustomers(
      EntityManager em) {
        Query query = em.createQuery(
                "SELECT OBJECT(cust) FROM Customer cust");
        List<Customer> customers = query.getResultList();
        return customers;
    } 

The query method, findAllCustomers, uses an EntityManager and an EJB Query Language (EJB QL) string to form and execute a Query object.

Here's another query in the Customer class -- it retrieves a specific customer using the customer's ID:

    public static Customer findCustomerById(EntityManager em,
            Integer custId) {
        Query query = em.createQuery(
                "SELECT OBJECT(cust) FROM Customer cust "
                + "WHERE cust.customerId = :custId");
        query.setParameter("custId", custId);
        List<Customer> customers = query.getResultList();
        if (customers != null && customers.size() > 0) {
            return customers.get(0);
        } else {
            return null;
        }
    }

Notice how the findCustomerById method above uses the setParameter method in the Query interface to pass parameters to the query.

The Persistence Descriptor

In addition to the changes to the Customer class, you also need to create a persistence descriptor file to create a managed entity. The EJB container identifies the presence of persistent entities in a packaged application (that is, a JAR, WAR, or EAR file) using the persistence descriptor file. You can find more information about entity packaging in "Chapter 6: Entity Packaging" in the Java Persistence API specification part of JSR-220.

The persistence descriptor is in a file named persistence.xml. Here are the contents of an example persistence descriptor file:

   <?xml version="1.0" encoding="UTF-8"?>
   <persistence xmlns="http://java.sun.com/xml/ns/persistence"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
       <persistence-unit name ="myEntityManager">
           <description>Sample Customer Database</description>
       </persistence-unit>
   </persistence>

Entity packaging is based on a persistence unit, which groups together a named entity manager including its provider and configuration, the set of managed classes, and metadata that maps the classes to the database. Here is a persistence unit that is used for this example:

    <persistence-unit name ="myEntityManager">
        <description>Sample Customer Database</description>
        <jta-data-source>jdbc/__default</jta-data-source>
        <class>com.example.entity.Customer</class>
    </persistence-unit>

The persistence unit named myEntityManager will manage the entities for the example. It relies on the EJB container to provide most of the defaults. You can use the persistence.xml file to override the defaults provided by the persistence provider. For example, you can override the data source used by the entity manager by specifying a value for the element <jta-data-source>. You can also list the classes that should be treated as persistent entities by specifying a value in one or more <class> elements.

The Controller Servlet

The example in this tip includes a controller servlet. The servlet uses the annotation @PersistenceContext (javax.persistence.PersistenceContext) to inject an instance of the entity manager.

Here is a code snippet:

   import javax.persistence.EntityManager;
   import javax.persistence.PersistenceContext;
   ...

   public class ControllerServlet extends HttpServlet {

       @PersistenceContext EntityManager myEntityManager;
   ...

The name of the variable myEntityManager is important. The instance of EntityManager injected into the servlet takes its configuration from the persistence unit named myEntityManager (recall that the persistence unit in the persistence.xml file for this example is named myEntityManager).

The controller servlet uses the injected entity manager instance to access the database and jsp files as a view layer. For example, the following method in the servlet is used to display all customer records in the database:

  private void doQueryByExample(HttpServletRequest request,
      HttpServletResponse response) throws ServletException, 
      IOException {
   ...      

        List<Customer> customers =
          Customer.findAllCustomers(myEntityManager);
        if (customers.size() > 0) {
            request.setAttribute(
              ATTRIBUTE_CUSTOMER_LIST, customers);
            getRequestDispatcher("/list.jsp").forward(
              request, response);
        } else {
            getRequestDispatcher("/index.jsp").forward(
              request, response);
        }
    }

The doQueryByExample() method uses the findAllCustomers() method in the Customer class to get a list of all customers. Then doQueryByExample() sets the retrieved list as a request attribute before forwarding the request to the view list.jsp.

Running the Sample Code

A sample package accompanies this tip. It provides an example that demonstrates the techniques covered in the tip. The sample package includes the source code for the example, required descriptor files, and build scripts. To install and run the sample:

If you haven't already done so, download GlassFish from the GlassFish Project page.

Set the following environment variables:
GLASSFISH_HOME. This should point to where you installed GlassFish (for example C:\Sun\AppServer)
ANT_HOME. This should point to where ant is installed. Ant is included in the GlassFish bundle that you downloaded. (In Windows, it's in the lib\ant subdirectory.)
JAVA_HOME. This should point to the location of JDK 5.0 on your system.

Also, add the ant location to your PATH environment variable.

Download the sample package and extract its contents. You should now see the newly extracted directory as <Sample_install_dir>\web-to-entity, where <sample_install_dir> 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:\web-to-entity. The web-to-entity directory contains a subdirectory named Customer and a war file named web-to-entity.war for the sample deployment.

Start the GlassFish Application Server by entering the following command:
     <GF_install_dir>\bin\asadmin start-domain domain1

where <GFinstall_dir> is the directory where you installed Glassfish.

Start the derby database by entering the following command:
      <GF_install_dir>\bin\asadmin start-database

Create the Customer table and insert data into it. To do that, use the precompiled DerbyInitor.class from <Sample_install_dir>\web-to-entity\entity\sql>. Change to the <Sample_install_dir>\web-to-entity\entity\sql directory, and run the DerbyInitor class as follows (the command goes on one line):
      java -classpath .;<GF_install_dir>\derby\lib\derbyclient.jar
      DerbyInitor

Deploy the application. This can be done in various ways. The following instructions describe how to do it using the Sun Java System Administrator Console. Open the Administrator Console by pointing your browser to http://localhost:4848. Then login with the appropriate administrator user name and password (the default username is admin, and the default password is adminadmin). This will open a Welcome screen.

In the Welcome screen expand the Applications folder in the left navigation, and select Web Applications. This will open a Web Applications window.

In the Web Applications window, click the Deploy button. This displays the Deploy Web Module Window.

In the File to Upload field of the Deploy Web Module window browse for the web application web-to-entity.war. Then click the NEXT button. This open a second deployment window. Change the value in the Context Root field to /customer. Then click the Finish button. That completes the deployment of the application.

Run the application by pointing your browser to http://localhost:8080/customer. You should see a window that includes a GO button to start the application.

Go button example

Click the Go button. This queries the database. In response, you should see a result page that shows a list of customers.

Sample Results Page

Click on the first customer in the list, John Doe. You should see details about this customer.

Sample Details Page

To undeploy the application, select it on the Web Applications page of the Administrator Console, and click the Undeploy button.

About the Authors

Sriramulu Lakkaraju is a staff engineer in the Sun Java System Enterprise Application Server group. He has been a contributing member in Sun Java techonology for the past seven years. He has contributed in areas such as J2SE (Security & Networking) J2EE (JSP, Servlet, JSTL, EJB), and also worked on the High Availability features of the Sun Java System Application Server.

Abhijit Kumar is the architect for Sun Java System Application Server, Platform Edition. He has been a Java developer for last ten years.

Back to Top

Rate and Review
Tell us what you think of the content of this page.
Excellent   Good   Fair   Poor  
Comments:
If you would like a reply to your comment, please submit your email address:
Note: We may not respond to all submitted comments.
Comments? Send your feedback on the Tech Tips: http://developers.sun.com/contact/feedback.jsp?category=newslet

Subscribe to the following newsletters for the latest information about technologies and products in other Java platforms:
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).
You can subscribe to these and other Java technology developer newsletters or manage your current newsletter subscriptions on the Sun Developer Network Subscriptions page

IMPORTANT: Please read our Terms of Use, Privacy, and Licensing policies:
http://www.sun.com/share/text/termsofuse.html
http://www.sun.com/privacy/
http://developer.java.sun.com/berkeley_license.html

ARCHIVES: You'll find the Enterprise Java Technologies Tech Tips archives at:
http://java.sun.com/developer/EJTechTips/index.html

© 2005 Sun Microsystems, Inc. All Rights Reserved. For information on Sun's trademarks see: http://sun.com/suntrademarks
Java, J2EE, J2SE, J2ME, and all Java-based marks are trademarks or registered trademarks of Sun Microsystems, Inc. in the United States and other countries.


You are viewing a mobilized version of this site...
View original page here

Mobilized by Mowser Mowser