|
EJB-Enterprise Java Beans Best Practices
|
| Access entity beans from session beans Avoid accessing EJB entity beans from client or servlet code. Instead wrap and access EJB entity beans in EJB session beans. This best practice satisfies two performance concerns: Reducing the number of remote method calls. When the client application accesses the entity bean directly, each getter method is a remote call. A wrapping session bean can access the entity bean locally, and collect the data in a structure, which it returns by value. Providing an outer transaction context for the EJB entity bean. An entity bean synchronizes its state with its underlying data store at the completion of each transaction. When the client application accesses the entity bean directly, each getter method becomes a complete transaction. A store and a load follow each method. When the session bean wraps the entity bean to provide an outer transaction context, the entity bean synchronizes its state when outer session bean reaches a transaction boundary. |
| Reuse EJB homes EJB homes are obtained from Application Server through a JNDI naming lookup. This is an expensive operation that can be minimized by caching and reusing EJB Home objects. This is similar to Best Practice Reuse DataSources for JDBC Connections. For simple applications, it might be enough to acquire the EJB home in the servlet init() method. This is consistent with Best Practice Use the HttpServlet Init Method To Perform Expensive Operations that Need Only Be Done Once. More complicated applications might require cached EJB homes in many servlets and EJBs. One possibility for these applications is to create an EJB Home Locator and Caching class.For example, using a singleton EJB home locator class that would be appropriate both for client (servlets and others) and inter-EJB access. |
| It is not appropriate to model all objects in the EJB tier as enterprise beans. Therefore, use helper objects that are subordinate to their respective enterprise beans for a number of purposes. The different types of helper objects are: data access objects and value objects. |
| Data Access Objects To encapsulate access
to data, the sample application uses data access objects. The use of separate
objects to access databases was driven by following requirements: -Keep session bean code clear and simple -Ensure easier migration to container-managed persistence for entity beans -Allow for cross-database and cross-schema portability -Provide a mechanism that supports tools from different vendors |
| Value Objects EJBs are remote objects,
they consume significant amount of system resources and network bandwidth
to execute. Therefore, before modeling a business object as an enterprise
bean, you should determine that there is a good case for doing so. For example,
if a business object merely represents a structure to hold data fields,
and the only behavior it provides are get and set methods for the fields,
then it would be wasteful of system resources to implement it as an enterprise
bean A better alternative would be to model it as a value object. A value
object is a serializable Java object that can be passed by value to the
client. A business concept should be implemented as a value object when
it is: -Fine-grained, which means it only contains methods to get the values of fields. -Dependent, which means its life cycle is completely controlled by another object. -Immutable, which means that its fields are not independently modifiable |
| Design coarse-grained EJB remote interfaces. Because every method call to an EJB by remote and home interface is a remote call, the overhead of an intercomponent call will likely be prohibitive for most fine-grained object interactions. To avoid such overheads, an EJB should represent an independent business object that has independent identity and lifecycle. A dependent object should never be modeled as an EJB. Instead, it should be implemented as a Java class and included as part of an EJB. For example, a purchase order may be implemented as an EJB, but individual line items on a purchase order may be implemented as helper classes, not as an EJB. [JavaPro] |
| Design coarse-grained EJB remote interface methods. Each client call to an EJB is a remote call and involves checks such as access control, transaction, and activation/passivation. So each call to an EJB is many times slower than a remote call and magnitude times slower than a local method call. Reducing the number of calls improves the performance. One technique in designing coarse-grained methods is to increase the amount of data passed back and forth in a method call and combine multiple methods into fewer methods. [JavaPro] |
| Reduce the number of JNDI lookups. Depending on the implementation of the naming and directory service of the application server, the JNDI lookups may take longer. Some application servers use separate processes on different machines for implementing directory information. Caching of the home handles improves the performance in such situations. A facade is an object that provides a single interface to multiple objects. A server-side facade simplifies the process and makes it so that the client doesn't have to understand each of the server-side EJBs. All of the client calls to the server are routed through the ServerFacade object. ServerFacade is a session EJB that caches the home handles to all the needed EJBs. The client could also cache the ServerFacade home handle using a singleton object on the client side. [JavaPro] |
| Use session bean wrapper for returning multiple data rows from an entity bean. Typically each entity bean in your application represents a logical row in the database. An entity bean's home interface defines one or more finder methodsone for each way to find an entity object or collection of entity objects within the home. A client invokes a finder method on the entity bean and retrieves a collection of entity objects. The client then loops through the collection of entity objects and retrieves the data. If the client is remote, this results in a remote call per row, which is too costly. Instead of this, a session EJB object (on the server side) can be used to pack all the rows returned as a result of calling a finder method on an entity home object. Listing 4 shows a session object that returns the vector/collection of data rows to the client in a single call. This approach is useful in cases where data is static on the GUIsuch as in list boxes and spreadsheets. This approach could be extended to support data modification on the client side. [JavaPro] |
| Use session beans for database batch operations. Entity beans are well suited for database operations involving one logical row at a time, but they incur a lot of performance overhead for database batch operations. For example, an entity beans finder method that returns 1,000 rows performs 1,001 select operations on the database, which reduces performance drastically. Using session beans for database batch operations improves performance because it reduces the number of calls to the database. [JavaPro] |
| Whenever possible, use container-managed persistence (CMP) rather than bean-managed persistence (BMP) In BMP, the bean provider codes database access calls using JDBC, SQLJ, and so on in bean methods. In CMP, the container provider tools generate database access calls at the enterprise bean's deployment time. The bean provider must specify, in the deployment descriptor, the list of instance fields for which container provider tools must generate access calls. CMP has the advantage that the bean class can be independent of the data source. Another advantage is that application vendors generate optimized code for CMP to improve database access performance. [JavaPro] |
| Use entity beans appropriately Entity
beans are suitable for specific scenarios. They are appropriate to use when
few rows need to be selected from the database and accessed by multiple
clients simultaneously. For example, a person's record (Person) can be cached
during his or her login session and accessed by multiple EJBs such as SecurityBean,
BankAccountBean, and so on. Therefore, Person can be modeled as an entity
bean. Entity beans are also appropriate to use when rows need to be updated
frequently by multiple transactions.
Because of performance overhead, entity beans are not suitable when many rows need to be selected, inserted, or updated from the database such as in batch processing. Consider using a session bean in such scenarios. Alternatively, you may design coarse-grained database access operations in an entity bean. [JavaPro] |
| Use the right isolation level Isolation
level refers to the degree to which multiple interleaved transactions are
prevented from interfering with each other. TRANSACTION_SERIALIZABLE is
the highest isolation level. This makes the process very slow because all
transactions (even simple reads) must wait in line to execute. Methods that
use this isolation level obtain exclusive write locks on data, which prevent
other transactions from reading, updating, or inserting data until the transaction
is complete. In isolation level TRANSACTION_REPEATABLE_READ, transactions
cannot change data that is being read by a different transaction. Write
locks are used that prevent other transactions from changing the data. Methods
that use isolation level TRANSACTION_READ_COMMITED cannot read uncommitted
data. A write lock cannot be obtained on data that is already being changed
by another transaction, so reading uncommitted data is not possible. TRANSACTION_READ_UNCOM-
MITED is the lowest transaction level. Bean methods with this isolation
level can read uncommitted changes, but they are not aware when new records
are added.
A higher transaction level is costly in terms of performance. A lower isolation level typically allows greater concurrency at the expense of more complicated logic to handle potential data inconsistencies. A useful guideline is to use the highest isolation level provided by enterprise information systems that gives acceptable performance. In the post-development phase of an enterprise application, we need to look at the issues related to performance tuning of the entire system. The remaining four tips refer to this phase of the project. [JavaPro] |
| Tune system parameters Many parameters in your application are tunable. In your operating system, for example, you can tune TCP/IP parameters, file limits, process limits, and IPC limits. In your application server, you can tune connection pool parameters, EJB pool sizes, thread count, number of JVMs, and JVM heap size. In your database server, you can tune the number of connections and processes, shared pool sizes, buffer sizes, indexes, and SQL query hints. And in your Web server, you can tune connection keep-alive parameters, thread/process count, and connection backlog. [JavaPro] |
| Use clustering to meet higher loads or consider upgrading the hardware Sometimes we reach a point where further tuning the system/code is more expensive than adding new hardware. In such cases, clustering provides an advantage. Most application servers provide the clustering feature. An EJB cluster is basically a group of EJB servers on multiple machines that work together to increase the horsepower of the system. Typically, each application server in the cluster contains the same EJBs. Servers in a cluster provide load balancing using different algorithms such as round robin, random, sticky bit, server load, and so on. [JavaPro] |
| Session bean state is not transactional. Almost every EJB application uses transactions at some point. Transactions ensure correctness and reliability and are essential to e-commerce applications. Misuse, however, can affect performance and even produce incorrect results. Its important to understand that session beans themselves cant be transactional. A common misperception is that the member variables of the session bean will be rolled back when their transaction aborts. Instead, session beans merely propagate their transaction to any resource they acquire. For instance, at the beginning of a transac-tion a session bean has a member variable with a value of zero. During the transaction, the member variable is set to two, and a row is inserted into the database. If the transaction rolls back, the mem-ber variable wont be reset to zero. However, the row will no longer be in the database. Since a database is a transactional resource, it will participate in the session beans transaction, and a rollback will abort any associated work. |
| Use container- instead of bean-managed transactions.
The EJB specification allows a session bean to choose either con-tainer-
managed or bean-managed transactions. In the former the bean writer declares
transaction attributes in the deployment descrip-tor. The EJB container
then automatically starts and commits transac-tions as requested. The bean
writer doesnt have to write any code to manage transactions. In the
latter the bean writer uses the user trans-action interface to explicitly
start and commit transactions. Container-managed transactions should always
be the bean writers first choice. In bean-managed transactions the bean writer must ensure that the transaction is committed or rolled back. While the BEA WebLogic Server includes a transaction timeout, the bean writer shouldnt rely on this feature, but release transaction resources as soon as possible. In the case of container-managed transactions this is handled auto-matically by the EJB container. |
| Remove stateful session beans when finished Instances of stateful session beans have affinity to specific clients. They will remain in the container until they are explicitly removed by the client, or removed by the container when they timeout. Meanwhile, the container might need to passivate inactive stateful session beans to disk. This requires overhead for the container and constitutes a performance hit to the application. If the passivated session bean is subsequently required by the application, the container activates it by restoring it from disk. By explicitly removing stateful session beans when finished with them, applications will decrease the need for passivation and minimize container overhead. |
| Stateful session beans are not shared by multiple users. Stateful session beans represent a stateful conversation between a single client and a bean instance. Stateful session beans cant be shared between multiple users. You shouldnt model a shared cache or any shared resource as a stateful session bean. If multiple clients need to access a single EJB instance, use an entity bean. |
| Stateless session beans are easier to scale
than stateful session beans. Since each client requires its own stateful
session bean instance, the number of bean instances and the associated resource
require-ments can grow quickly. If an application can tolerate the stateless
programming model, stateless session beans are easier to scale than stateful
session beans.
Applications should always call remove after finishing with a state-ful session bean instance. This allows the EJB container to release container resources as soon as possible. If the remove call is omitted, the EJB container will eventually passivate the bean, but this involves extra disk access. |
|
Entity beans are too heavy to use with read-only data, use JDBC instead. |
| Stateless session EJBs can be used to efficiently represent infre-quently changing shared data. |