With the exception of the new CMP approach, the EJB 2.0 features described so far provide opportunities for you to make improvements to your applications without monumental change. If you're using EJB 1.1 CMP and you want to move your entity beans to EJB 2.0, you have some work ahead of you. The benefits definitely exist, but the effort involved in reworking an existing application might not be an easy sell. Because of the amount of work involved, that's not the case we want to look at here. Even if you're using CMP, you can take steps to benefit from EJB 2.0. And because EJB 1.1 CMP is still a valid part of the specification (it hasn't been deprecated), it's not really a problem to stick with your current CMP implementation.
We also won't go into any more detail on message-driven beans here. The use of messaging in an application is a fundamental architectural decision that is beyond the scope of this article. However, if you have requirements for asynchronous messaging, you can avoid vendor-specific solutions that go outside the EJB specification by incorporating message-driven beans into your design. For example, an order-entry application might be required to send a confirmation email to the buyer when an order is placed. If the mail server is down when an order comes in, this shouldn't prevent the order from being accepted by the system, and it also shouldn't prevent the email from eventually being sent. A potential solution is to use a message-driven bean that pulls order information from a JMS destination only when the mail server is available. The bean could then build the required email messages and send them to the mail server. This approach separates the order-entry component of the system from the noncritical (in this case, anyway) task of sending email.
Because of the overhead associated with calls to an EJB, a common J2EE design approach is to expose only session beans to the clients of an application. With this approach, known as session bean wraps entity, the session beans are responsible for the workflow and for performing any required entity bean access as efficiently as possible. Under EJB 1.1, this need for efficiency has led to designs in which session beans interact with entity beans using coarse-grained methods that update or retrieve multiple fields of an entity with a single call.
Notice that this interface extends EJBLocalObject instead of EJBObject and that a throws clause for RemoteException isn't needed for the methods. Because this interface supports local clients, fine-grained methods such as these can be called to access individual fields without the performance penalty incurred when taking the same approach with remote clients. You can switch to a local interface only if the clients are other EJBs running in the same container, which is typically true for an entity bean. The specification allows an EJB to support both local and remote clients, but actually needing to do that isn't common.
Switching to a local interface also requires switching to a local home interface. A local home interface still supports create and finder methods, like "remote" homes do; the only differences are in the interface hierarchy and the method parameter and return types. A local home interface extends EJBLocalHome instead of EJBHome. You also have to make sure that you reference an entity using its local interface type instead of its remote interface (if it has one) in a local home. The only effect on the bean implementation class of switching to local clients is that you can get rid of the methods written for the sake of performance to operate on multiple fields.
As pointed out previously, EJB 1.1 business methods that act on more than a single object of a particular entity type are usually implemented in session beans. This is consistent with viewing session beans as controller classes that manage interactions among multiple entities, but it doesn't follow good object-oriented practices of encapsulation, loose coupling, and tight cohesion. The introduction of home methods provides an alternative to allowing entity bean business logic to spill over into session bean methods that's easy to implement.
As an example, suppose that you need a method that computes the average salary of all the employees in the human resources system. You could implement a session bean method like the one in Listing 1 to access each entity object and compute the result.
This method is a simple one, and there's nothing incorrect about implementing it in a session bean. What it does, though, is couple the session bean to the entity bean, to some extent. Computing an average is a simple calculation, but the details are found in a class other than the one to which this method really applies. If some other steps become required for computing the average (such as ignoring part-time employees), it would be simpler to maintain this logic if it were found in the employee bean class. This way, a developer making any changes to the behavior of the employee bean related to salaries wouldn't have to worry so much about what other classes might be affected.
You can refactor this session bean method into a home method simply by adding it to the employee bean's home interface and implementing it with a name that follows the required convention (see Listing 2).
Even without converting any of your application to EJB 2.0, you can prepare your code for an eventual upgrade. Deprecation within Java is a powerful tool for phasing out functionality without breaking existing code. This term likely makes you think of the compiler warnings that you get in response to javadoc tags that have been applied to classes or methods. It's also important to pay attention to the deprecation of a previously accepted practice that doesn't always correspond to a compile-time check. For EJB developers, this applies in particular to the use of RemoteException.
You're required to include RemoteException in each method declaration in a remote interface, but including it in the corresponding implementation should be avoided. Rather than passing the buck and letting this exception be thrown, you should always catch RemoteException when making a remote call from an EJB and report an EJBException instead (see Listing 4).
This is a simple change that requires very little effort. It also gets you into the habit of following EJB 2.0 rules while keeping you conscious of the fact that clients of your beans are no longer limited to being remote clients.