http://java.sun.com/ http://java.sun.com/ http://java.sun.com/javaone
JavaOne - ExperiencingJava technology through education, industry, and community
2007 Conference
Home
Registration
   Conference Hotels
Schedule
   Activities
Tracks
Sessions
   General Sessions
   Business Day
   TV Day
   JavaOne Camp
Hands-on Labs
Pavilion
   Cosponsors
   Exhibitors
   Media
   How to Exhibit
Blogs
Multimedia
Java University
 
Conference Tools
Schedule Builder
Event Connect
My Registration Details
 
Conference Programs
Alumni Program
   Alumni FAQ
Eco Corner
Rock Stars
 
Related Resources
JavaOne Library
JavaOne Online
2006 Site Archive
 
Community
Forums
Sun Developer Network
 
Popular Items
Java Wear
Duke Images
 
Related Sites
java.sun.com
java.com
java.net
 
 
  Home > Guidelines, Tips, and Tricks for the Java EE 5 Platform

 Guidelines, Tips, and Tricks for the Java EE 5 Platform

   
By Rick Palkovic  

If you've been programming with some of the features recently introduced into the Java Platform, Enterprise Edition 5 (Java EE 5), such as annotations and generics, you'll be interested in session TS-4593, "Guidelines, Tips, and Tricks for Using Java EE 5 From Java BluePrints," presented Wednesday at 1:30 p.m. Speakers Inderjeet Singh, Marina Vatkina, Mahesh Kannan, and Roger Kitain presented most of the information in the form of code-example puzzles.

Kitain opened the session, presenting tips for programming in the web tier. Tips included ways to simplify web deployment descriptor entries by using wildcards in servlet names with filter-mapping descriptors. He then presented some JavaServer Faces technology code that often trips up novice developers.

Kannan followed, leading attendees through the intricacies of EJB technology coding such as dependency injection in the Java EE 5 platform. He explained how the @Resource annotation declares an environment dependency in addition to injecting that dependency into the named variable. He then described ways to use EJB 3.0 interceptors to intercept business and life-cycle methods.

Next, Vatkina described issues that can trap unwary programmers in the Java Persistence API. She explained how easy it is to write deployment descriptor entries and package applications for using Java persistence in Java EE and Java SE platform environments.

Finally, Singh provided other tips, such as how to use thread-safe variants of annotations and how to use generics with the Java Persistence API for better type safety. The following are some examples from Singh's presentation.

Java EE annotations have been designed to work with thread-safe code. For this very reason, Singh cautioned his audience to consider thread safety when using annotations in the web tier. Some annotations simply do not work because the web-tier model itself is not thread safe.

Thread Safety and Annotations: Example 1

To drive home his point, Singh presented the following code fragment, which uses the @PersistenceContext annotation:

public class MyServlet extends HttpServlet {
        @PersistenceContext (unitName="CatalogPU") 
        private EntityManager em;

   @Resource UserTransaction utx;
        //    ......
}

This use of the annotation @PersistenceContext in a servlet is not thread safe, nor would it be safe in a JavaServer Faces managed bean unless the bean is request-scoped. The use of @Resource, however, is thread safe.

Singh summarized four ways to make the code thread-safe:

  • Use a request-scoped bean in a JavaServer Faces managed bean.
  • Use class-level annotations with Java Naming and Directory Interface (JNDI) lookups.
  • Use other annotations, such as @Resource.
  • Use old-fashioned JNDI lookups.

Singh presented the following example of a thread-safe alternative. In this example, the @PersistenceContext annotation declares only the deployment descriptor entry, so it is class-scoped. Further, the servlet is thread safe because there is only one JNDI lookup per method call.

@PersistenceContext(name="EM" unitName = "CatalogPU")
public class MyServlet extends HttpServlet {
  public EntityManager getEntityManager() {
    Context ic = new InitialContext();
    return (EntityManager) ic.lookup("java:comp/env/EM");
}

Another thread-safe alternative is to use a different annotation, as in the following example. In this example, the @PersistenceUnit annotation injects EntityManagerFactory, which is a thread-safe object. The servlet is thread safe because the method creates a new entity manager for each call.

public class MyServlet extends HttpServlet {
        @PersistenceUnit (unitName="CatalogPu") 
        private EntityManagerFactory emf;
  public EntityManager getEntityManager() {
    return emf.createEntityManager();
}

Thread Safety and Annotations: Example 2

Singh presented another example of code that looks correct but that in fact can produce bugs that are difficult to characterize and fix.

public class TransactionsFilter implements Filter {
  @UserTransaction utx;
  public void doFilter(ServletRequest request,
                 ServletResponse response) throws ... {
    try {
      utx.begin();
      chain.doFilter(request, response);
      utx.commit();
    } catch (Exception e) {
      utx.rollback(e);
    }
  }
}

At first glance, this code looks typical enough. However, it is not guaranteed to work because of the way the servlet model is designed -- nothing in the model requires that the filter's doFilter() method and the servlet's service() method run in the same thread. If they run in different threads, the user transaction will fail, because transactions are not allowed to span threads. In practice, the methods usually run in the same thread, and the code works fine. But when the methods run in different threads, the resulting failure can be difficult to track down.

A movement is afoot to make unsafe annotations a compile-time error. Until then, unsafe annotations can pass unnoticed until they surface as mysterious failures at runtime.

Java EE 5 applications create domain models using the Java Persistence API. Often, these applications execute queries that return a collection of objects. The generics feature lets you specify the types of objects in collections.

Generics provide a way for you to communicate the type of the objects in a collection to the compiler. When the compiler knows the collection's element type, the compiler can check that you have used the collection consistently and can insert the correct casts on values being taken out of the collection.

When you build an application using the Java Persistence API, you can leverage generics for type safety. Using generics is generally regarded as good practice.

But using generics with Java persistence can be tricky. For example, consider the following code fragment, which uses the Java Persistence API to create a query:

public interface Query() {
  public List getResultList();
}

Java persistence does not provide a generic version of the returned collection. However, in most cases, you know the type of the objects in the resulting collection, so you can use generics to build a type-safe collection for subsequent use, as in the following example.

Query q = em.createQuery("SELECT OBJECT(i) FROM Item i");
List items = q.getResultList();
List items3 = items; 

In the example, the variable items is a genericized list of Item objects. The variable items3 is also a genericized list, but the type of the objects in the list is unknown, represented by the wildcard character ?. Certain restrictions apply to genericized lists of unknowns, but if you only want to call get() on the list and use the result, such a list can be helpful.

If you are new to generics, you might assume that generic collections are polymorphic. In that case, it would be correct to assign an object of type List to an object reference of type List. However, such assignments produce compile-time errors.

With the current version of the Java Persistence API, code that uses generics can produce spurious unchecked conversion warnings. If other developers use your code, they might not realize that they can safely ignore these warnings. You can use an annotation to suppress the warnings.

Consider this innocent getAllItems() method, which assigns query results to a generic list:

public List getAllItems(){
  EntityManager em = emf.createEntityManager();
  Query query = em.createQuery("SELECT OBJECT(i) FROM Item i");
  List items = query.getResultList();
  em.close();
  return items;
}

When this code is compiled with the -Xlint:unchecked option enabled, it generates an unchecked conversion message. The warning is generated because query.getResultList() returns a nongenericized version of List.

This warning is spurious because you know that the result of the query is always a list of Item objects. Using a typecast of (List) will not solve the problem because the compiler does not preserve the generics type information for runtime.

You can suppress the warning by preceding the code block with the annotation @SuppressWarnings("unchecked"). Needless to say, you should use the @SuppressWarnings annotation cautiously.

Rate and Review
Tell us what you think of the content of this page.
Excellent   Good   Fair   Poor  
Comments:
Your email address (no reply is possible without an address):
Sun Privacy Policy

Note: We are not able to respond to all submitted comments.