Questions and Answers - Enterprise JavaBeans Tier

   
 

 

Guidelines, Patterns, and code for end-to-end Java applications.



Questions and Answers - Enterprise JavaBeans Tier
  1.  
  2. How can I find a particular enterprise bean (component based on Enterprise JavaBeans TM technology)?
  3.  
  4. Should an enterprise bean look up the Java Database Connectivity TM (JDBC TM ) technology-based drivers directly from the ejbCreate() method?
  5.  
  6. What are some common pitfalls and practices to avoid when using enterprise beans?
  7.  
  8. How can I take advantage of my application server's connection pooling features?
  9.  
  10. How can I hold and pass references to enterprise beans?
  11.  
  12. How can nested transactions be implemented with enterprise beans?
  13.  
  14. Can I use synchronization primitives in my enterprise beans?
  15.  
  16. How do I map a single entity bean to multiple tables?
  17.  
  18. What does "stateless" mean in a stateless session bean? Can stateless session beans cache any information?
  19.  
  20. What are enterprise bean "value objects"? How do you persist value object instances?
  21.  
  22. How can I prevent concurrent calls to the same stateful session bean?
  23.  
  24. What are the issues involved in creating a singleton with enterprise beans?
  25.  
  26. What happens when an enterprise bean throws an exception? How are exceptions propagated?
  27.  
  28. What are some guidelines for using exceptions in J2EE TM ?
  29.  
  30. How should system exceptions be handled from an enterprise bean?
  31.  
  32. How do I efficiently remove a bunch of entity beans?
  33.  
  34. Does the container-managed persistence (CMP) in the EJB 2.0 specification obviate the need for the Data Access Object (DAO) pattern?
  35.  
  36. Where should the container-managed relationship (CMR) fields of an entity bean be set, in the ejbCreate() method or in the ejbPostCreate() method?
  37.  

1.   How can I find a particular enterprise bean (component based on Enterprise JavaBeans TM technology)?

 

Enterprise bean instances reside in containers for Enterprise JavaBeans (EJB TM ) technology-based components (EJB containers), within servers enabled with EJB technology (EJB servers). A client accesses an enterprise bean by calling methods on the bean's remote interface. A client "finds" a particular enterprise bean instance by getting a remote reference (that is, an object that implements the remote interface) to that bean.

A client finds an enterprise bean by acquiring a reference to the bean's home interface, and then using "create" or "find" methods to retrieve a remote reference to the bean.

The sample code below shows how Web tier objects in the Java Pet Store find an enterprise bean's home interface, and then use it to find a specific bean instance on the server by getting a remote reference to the instance. This example uses the home interface "finder" method findByPrimaryKey()) to find a particular entity bean. The following code is adapted from the Java Pet Store class EJBUtil :

                      // ... class definition ... public static InventoryHome getInventoryHome() {    try {       // Create a naming service object                                                        InitialContext initial = new InitialContext();        // Obtain an abstract reference to the EJB's home interface.                                                        Object objref = initial.lookup("java:comp/env/ejb/inventory");        // Convert the abstract reference to the home interface.                                                        InventoryHome ih =          (InventoryHome) PortableRemoteObject.narrow(objref,                                                      InventoryHome.class);       return ih;    } catch (NamingException ne) {     ...    } }                     
                  

InventoryHome InventoryEJB
  • Create a naming service object. Class InitialContext provides clients with a single point of access to naming services. An InitialContext object allows you to find enterprise beans' home interfaces by name without knowing the details of the underlying naming service (which could be any of Java Naming and Directory Interface TM (JNDI), DNS, CORBA, COS, etc.)
  • Obtain an abstract reference to the enterprise bean's home interface. Method InitialContext.lookup(), given an object's name, returns a reference to that object, using whatever directory service is configured. This abstract can be converted to (but itself is not necessarily) a reference to the enterprise bean's home interface.
  • Convert the abstract reference to the home interface. The reference returned by InitialContext.lookup() (which is always of type java.lang.Object) may or may not be the actual home interface object itself, depending upon the Container type. The EJB 1.1 specification chooses Java Remote Method Invocation (Java RMI) over IIOP as the standard programming model, and CORBA reference types can't be directly cast to home interfaces. The public static method PortableRemoteObject.narrow() takes a reference received from InitialContext.lookup(), and the java.lang.Class object of the home interface, and tries to turn the reference into an instance that implements that interface. If it succeeds, the object returned will implement the home interface; otherwise, narrow() throws an exception. Consider narrow() to be performing type-casting by a single function call.

Once you have the home interface, you can then use a finder method like findByPrimaryKey() to get the enterprise bean instance you want. The finder method findByPrimaryKey() can then be used to access a specific entity bean, as occurs in the following excerpt from OrderHandler :

                                                                     InventoryHome inventHome = EJBUtil.getInventoryHome();     ...     for (Iterator it = lineItems.iterator(); it.hasNext();) {         LineItem LI = (LineItem)it.next();                                                         Inventory inventRef = inventHome.findByPrimaryKey(LI.getItemNo());         inventRef.reduceQuantity(LI.getQty());     }                     
                  



findByPrimaryKey()LineItemInventory

2.   Should an enterprise bean look up the Java Database Connectivity TM (JDBC TM ) technology-based drivers directly from the ejbCreate() method?

No, enterprise beans should always access data sources using the JNDI interface to get a DataSource object. This allows the application server to optimize connection management. See the discussion on connection pooling below for more on this topic.

3.   What are some common pitfalls and practices to avoid when using enterprise beans?

 

  • Avoid making non-transaction services REQUIRED. Developers sometimes put TRANSACTION_REQUIRED on everything, including obviously non-transactional, asynchronous things like sending email. Don't tie up the transaction pool with spurious transaction requirements.
  • Avoid fine-grained objects. Use the Transfer Object pattern to group attributes that are always used together. This will help reduce unnecessary latency. For example, there's seldom a reason to have a remote interface method that sets and gets the apartment number of an Address. Instead, use an Address Transfer Object that represents the entire address as a single, synchronizable chunk.
  • Don't embed the SQL code within the enterprise bean code. Enterprise beans using a relational data store with bean-managed persistence (BMP) often use SQL to manipulate bean instance state. Placing the SQL directly within the enterprise bean code can make the bean dependent on a particular vendor's SQL implementation. Instead of using SQL directly in enterprise bean methods, use Data Access Object class to abstract persistence operations (see Data Access Objects).
  • Avoid unnecessary remote calls. Remote calls are expensive in network bandwidth, server load, and latency. Always be sure that every server round-trip is absolutely necessary. In particular, try to eliminate iterating server-side collections; instead, try to create a generalized business method that does whatever that iteration is trying to accomplish -- even if it's just positioning a cursor.

     

    For example, instead of doing this:
                          for (i = 0, remoteObj.first(); i < firstItem && remoteObj.valid(); i++) {         remoteObj.next();     }
                  
    try this:
                          remoteObj.seek(firstItem); 
                  
    The iteration's still there, it's just within the seek() method on the server, instead of being on the client.


4.   How can I take advantage of my application server's connection pooling features?

Most of the techniques for making most effective use of your EJB server's connection pooling feature involve properly managing the lifecycle of your enterprise beans and the connections they use. Here are some guidelines and explanations:

  • Avoid static connection fields. Enterprise bean tutorial code samples often acquire (at creation time) a reference to a connection, and save that connection in a protected static class field, for use during subsequent calls. This technique starves the connection pool, since the enterprise bean class is holding on to a connection even when no methods are being called on the bean. Therefore, always acquire a connection, use it, and return the connection to the pool before returning from the method.
  • Acquire connections through a DataSource, instead of using the JDBC interface. An enterprise bean server provider implements connection pooling behind a reference to an object that implements DataSource . Using the JDBC interface directly to acquire database connections competes with the connection pool for available connections. Below you will find sample code from the Java Pet Store that gets a (potentially pooled) connection from a DataSource. The Java Pet Store "DAO" (Data Access Object) classes use this technique.

     

                              // utility method private Connection getDBConnection() throws SQLException {           Connection connection;           try {         // Get the naming service         InitialContext ic = new InitialContext();          // Find the data source         DataSource ds = (DataSource)             ic.lookup(JNDINames.ESTORE_DATASOURCE);           // Get the connection         connection = ds.getConnection();      } catch (NamingException ne) {         throw new EJBException(ne);     } catch (SQLException se) {         throw new EJBException(se);     }      return connection; }
                          

     

  • Always acquire, use, and release a connection within a method Within any method that uses connections, always obtain a connection from a DataSource (as described above), use it, and then release it. Following this guideline ensures that connections are only held as long as they are used. The time penalty for acquiring the connection is low, because the connection already exists and is open and waiting in the pool. Pay special attention to releasing the Connection object if you use early returns (multiple returns from a method), or if exceptions are involved.

     

    Using the try/catch/finally construct is a good way to ensure that connections are always released properly. The finally clause executes unconditionally whenever the flow control exits the try block, either by completing successfully or if an exception is thrown, even for exceptions that are not caught. Here's an excerpt from the Java Pet Store class AccountDAO that demonstrates this idea:
                              private boolean userExists (String userId)     throws AccountDAOException {     ...     try {         getDBConnection();         stmt = dbConnection.createStatement();         result = stmt.executeQuery(queryStr);         ... (use the result set) ...     } catch(SQLException se) {         ...     } finally {         if (result != null) { closeResultSet(result); }         if (stmt != null) { closeStatement(stmt); }         if (dbConnection != null) { closeConnection(); }     }     return returnValue; }
                          

    Inside the try block above, the getDBConnection() method initializes the protected field dbConnection, which is used to create a statement, get a result set, and so on. The catch clause handles all SQLExceptions thrown, but no other kinds of exceptions. Nevertheless, the finally clause closes the database connection regardless of how the try block was exited.

    Note that some databases react badly if connections are closed while they have open statements or result sets, so it's good form to always close any outstanding statement and its result set before closing the corresponding connection.



5.   How can I hold and pass references to enterprise beans?

The EJB 1.1 specification does not prescribe a way for entity beans to store references to other entity beans. Application developers may choose from among several ways that entity beans can reference one another. These strategies include:

 

  • Store the remote reference in a transient, protected field of an entity bean. Entity beans can retain references to other entity beans in instance fields. The field should be protected, as all internal state should be; and it should be transient, because remote references aren't Serializable, and nontransient, nonserializable fields cause default serialization to fail. This particular method of dealing with enterprise bean references applies only to entity beans.
  • Use the referenced bean's primary key. If the referenced bean's home interface is known and fixed, the referencing bean can use get the home interface of the referenced bean, and then use findByPrimaryKey() to find the bean's remote interface.
  • Use the bean's handle. See Handle . This handle is a direct reference to the referenced bean. The referencing bean can instantiate the Handle, and call the resulting object's method getEJBObject() to retrieve the referenced bean's remote interface.

    Every remote reference (that is, every instance of a subclass of EJBObject ) has a method getHandle() that returns a serializable Handle . A handle is a serializable object, created by the application server, that specifies how to find a particular enterprise bean. The Handle object has a method called getEJBObject() which will return the referenced object if that object exists and can be found.

    Handles are typically used as robust references to server-side objects. Since they are implemented by the server vendor, their implementations are opaque; that is, there's no specified format for what should be in a Handle object. But since handles are Serializable, they can be turned into a byte string and stored or transmitted through a network, by way of Java RMI or any other protocol. Cooperating clients or server-side objects can pass handles to one another as byte strings. The receiving program can instantiate a received Handle, and then request its EJBObject.

    There is no guarantee that the bean will in fact exist when its handle is referenced. Session beans aren't guaranteed to survive container crashes, and the data representing an entity bean can be removed while serialized handles are outstanding. The Handle does guarantee either to return a reference to the remote interface for a bean, or to throw an exception if the bean couldn't be located.



6.   How can nested transactions be implemented with enterprise beans?

The EJB 2.0 specification (§ 17.1.2) states that nested transactions are not supported. Requiring nested transactions would have shut out the many database vendors who do not support them. The specification leaves open the possibility adding nested transactions in the future.

7.   Can I use synchronization primitives in my enterprise beans?

 

Synchronization primitives include the synchronized keyword, as well as methods wait(), notify() and notifyAll() of class Object . All of these are disallowed in enterprise beans, as are other methods (such as Thread.interrupt(), etc.) that would affect the server thread pool.

Since the EJB server is completely responsible for managing threads and synchronization, there is absolutely no reason to use synchronization primitives in your enterprise beans.

While Vector and other classes that contain synchronized blocks is allowed in general, we recommend using the standard Java Collection classes (which are not synchronized) instead.

Restricting synchronization and thread control guards against the possiblity of deadlock. Enterprise bean instance access is synchronized automatically by the server at specific points in an enterprise bean's lifecycle. Allowing arbitrary synchronization control in enterprise beans could cause deadlock.

For more on restrictions placed on enterprise beans, see EJB Restrictions.



8.   How do I map a single entity bean to multiple tables?

 

If you use Bean-Managed Persistence (BMP), map the bean to the the tables manually. Consider applying the Data Access Object (DAO) design pattern to accomplish this.

If you're using Container-Managed Persistence (CMP), use the vendors object/relational mapping tool to specify the mapping between your object state and the persistence schema. Be aware that the CMP solution is not portable across application server vendors under the EJB 1.1 specification. If this is a concern, consider using BMP, and migrating to CMP under the EJB 2.0 specification or later.



9.   What does "stateless" mean in a stateless session bean? Can stateless session beans cache any information?

 

Stateless for a stateless session bean means that the bean can maintain no client-specific state. Stateless session beans can (and often do) have other state which is client-independent.

Client-independent data can be cached in a stateless bean if:

  • the information being cached will never change, and
  • the application can tolerate a copy of the same cache repeated in each stateless bean instance that the container creates.


In most cases, any client-independent state that a stateless session bean may have will probably be indentical in all instances.



10.   What are enterprise bean "value objects"? How do you persist value object instances?

 

Value objects are objects that only have meaning within the context of another business object. They typically represent fairly fine-grained business concepts, like an address, credit card details and so on.

To persist an instance of a value class (which is a regular Java class, not an enterprise bean), use the class as a single property of an enterprise bean. For example, an Address class may be a value class used by class Person (so, in the example, class Person will have a method Address getAddress()). The Address may then be persisted as a whole using CMP. If BMP is used, you'll have to create persistence management code for class Address that manages moving Address data to and from the appropriate table(s).

11.   How can I prevent concurrent calls to the same stateful session bean?

The EJB 2.0 specification (§ 7.5.6) specifically disallows multiple simultaneous accesses to the same stateful session bean. If a client-invoked business method is in progress on an instance when another client-invoked call, from the same or a different client, arrives at the same instance, the container may throw RemoteException to the second client, if the client is a remote client, or EJBException if the client is a local client. This is in contrast to entity and stateless session beans, which have new instances created by the container when concurrent calls occur. In certain special circumstances (for example, to handle clustered web container architectures), the container may instead queue or serialize such concurrent requests. However, the clients can not rely on this behavior. Note that this concurrent call restriction forbids loopback calls on stateful session beans as well.

 

  • in Java Foundation Classes/Swing GUI code where multiple threads may be contending for access to the same bean;
  • in Web applications where multiple frames may be trying to access the same bean;
  • if a user double-clicks a hyperlink that makes a call against an enterprise bean; or
  • the user opens more than one browser instance and is interacting through both.

 

 

ShoppingClientControllerWebImpl synchronized

12.   What are the issues involved in creating a singleton with enterprise beans?

 

 

 

 



13.   What happens when an enterprise bean throws an exception? How are exceptions propagated?

 

The EJB 1.1 specification (Chapter 12) defines two types of exceptions:

  • application exceptions, which indicate recoverable errors at the level of the application (for example, bad user input); and
  • system exceptions, corresponding to generally unrecoverable, unexpected errors below the application level (for example, loss of database connection, Java virtual machine errors, unexpected RuntimeException), etc.


Application exceptions thrown by the enterprise bean layer are propagated to the client by the EJB container. All other enterprise bean exceptions, either RuntimeExceptions or subclasses of java.lang.Exception, are caught and handled by the container, which then throws a RemoteException to the calling client.

Enterprise beans are responsible for catching system exceptions and converting them to EJBExceptions.

See Chapter 12 of the EJB 1.1 specification for more on this topic. Pay particular attention to tables 8 and 9, which each present a matrix describing the method conditions and specified responses for various exception conditions and transaction demarcations.



14.   What are some guidelines for using exceptions in J2EE TM ?

 

Application exceptions should be exclusively subclasses of Exception . Exceptions should report only exceptional application conditions from which the client can recover, and should not report system-level problems. Application exceptions do not as a rule cause client transaction rollback or server-side bean destruction. If rollback is desired when an exception occurs, catch the exception, and call EJBContext .setRollbackOnly() to mark the transaction (irrevocably) for rollback. The container will perform the rollback on behalf of the bean. Otherwise, clients can catch application exceptions and continue to communicate with the enterprise bean, with the transaction context intact. This method only works for beans with container-managed transactions.

The EJB 1.1 specification, § 9.2.6, contains a compatibility note pointing out that the EJB 1.0 technology practice of allowing business methods to throw non-application-level java.rmi.RemoteExceptions is now deprecated. Throw and EJBException or a RuntimeException to notify the container of non-application error conditions.



15.   How should system exceptions be handled from an enterprise bean?

All system exceptions must be caught by the bean and propagated to the container as EJBException s. RuntimeExceptions are the exception to this rule, and can be allowed to propagate to the Container without first being caught.

16.   How do I efficiently remove a bunch of entity beans?

If you are using container-managed persistence, you can write a home business method that removes all the entity beans. If you are using bean-managed persistence, you can write a single JDBC call that removes the underlying table rows. However, you will need to use proper isolation level settings for the database to avoid problems such as phantom reads.

17.   Does the container-managed persistence (CMP) in the EJB 2.0 specification obviate the need for the Data Access Object (DAO) pattern?

No. There may be scenarios where the query Language capabilities of the EJB 2.0 specification may not be enough for your application. In such cases, you may need to resort to using SQL code encapsulated in a DAO. Furthermore, if you are using mostly read-only data primarily in a tabular form, it may be more natural and efficient to access it relationally through a DAO. In such situations, using entity beans may incur a performance penalty while providing little or no additional value. The catalog component of the Java Pet Store demo uses DAO for this reason.

18.   Where should the container-managed relationship (CMR) fields of an entity bean be set, in the ejbCreate() method or in the ejbPostCreate() method ?

In the ejbPostCreate() method. This is because the container creates the primary key of the CMP entity bean only after the ejbCreate() returns. Since, the primary key is needed to establish the container-managed relationships, the CMR fields must be set in the ejbPostCreate() method. See CustomerEJB in the Java Pet Store Demo, version 1.3.1 for an example.

See also:

Session state in the EJB tier
EJB Restrictions
Using JDO in the EJB tier
Left Curve
Java SDKs and Tools
Right Curve
Left Curve
Java Resources
Right Curve
JavaOne Banner Java 8 banner (182)