|
WebLogic Server EJB Design and Development
Restrictions for accessing EJB instances
Storing EJB references in home handles
Using home handles across a firewall
Preserve transaction resources
Allow the datastore to manage transactions
Use container-managed transactions over bean-managed transactions
Never demarcate transactions from a client application
Use correct modeling for entity EJBs
Entity EJBs should be coarse-grained
Entity EJBs should contain business logic
Optimize entity EJB data access
Use isModified() where appropriate
This section provides a collection of design tips and debugging points to keep in mind when building applications with Enterprise JavaBeans. A number of these tips apply to remote object models (RMI and CORBA) as much as they do to EJB.
WebLogic Server automatically creates implementations of an EJB's home and remote interfaces that are remotable. This means that all clients - whether they reside in the same server as the EJB, or on a remote computer - can access deployed EJBs in a similar fashion.
With the EJB 1.1 specification, all EJBs must specify their environment properties using JNDI. EJB clients can configure their JNDI name spaces to include the home EJBs that reside anywhere on the network - on multiple machines, application servers, or containers.
However, in designing enterprise application systems, you must still consider the effects of transmitting data across a network between EJBs and their clients. Due to network overhead, it is still more efficient to access beans from a "local" client - a servlet or another EJB - than to do so from a remote client where data must be serialized, transmitted over the network, and then unmarshalled.
One difference in accessing EJBs from local versus external clients is in obtaining an InitialContext for the bean. Remote clients obtain an InitialContext via the WebLogic Server InitialContext factory. WebLogic Server example clients generally use a getInitialContext method to perform this lookup, similar to the following excerpt:
...
Context ctx = getInitialContext("http://localhost:7001", "user1", "user1Password");
...
static Context getInitialContext(String url, String user, String password) {
Properties h = new Properties();
h.put(Context.INITIAL_CONTEXT_FACTORY,
"weblogic.jndi.WLInitialContextFactory");
h.put(Context.PROVIDER_URL, url);
h.put(Context.SECURITY_PRINCIPAL, user);
return new InitialContext(h);
}
Internal clients of an EJB, such as servlets, can simply create an InitialContext using the default contructor, as shown here:
Context ctx = new InitialContext();
Restrictions for accessing EJB instances
Entity EJBs can be accessed by multiple clients, but only in a serial fashion. If two clients attempt to access the same entity EJB instance (an instance having the same primary key), the second client blocks until the EJB is available.
An instance of a stateful session EJB can be accessed from only one client virtual machine at a time. Multiple client threads from the same virtual machine can access the same instance of a stateful session EJB, but they must do so in a serial fashion; simultaneous access to a stateful session EJB results in a RemoteException, as required by the EJB 1.1 specification.
This restriction for stateful session EJBs applies whether the EJB client is remote or internal to WebLogic Server. If multiple servlet classes access a session EJB, each servlet thread (rather than each instance of the servlet class) must have its own session EJB instance. To avoid RemoteException errors in such a scenario, each servlet should store a reference to a particular EJB instance in a local variable of the servlet's service() method.
Storing EJB references in home handles
Once a client has obtained the EJBHome object for an EJB instance, it can create a reference to the home by calling getHomeHandle(). getHomeHandle() returns a HomeHandle object, which can be used to obtain the home interface to the same EJB instance at a later time.
A client can pass the HomeHandle object as arguments to another client, and the receiving client can use handle to obtain a reference to the same EJBHome object. Clients can also serialize the HomeHandle and store it in a file for later use.
Using home handles across a firewall
By default WebLogic Server stores its IP address in the HomeHandle object for EJBs. This can cause problems with certain firewall systems. If you are unable to locate EJBHome objects using home handles passed across a firewall, set the following property in your weblogic.properties file:
weblogic.system.enableReverseDNSLookups=true
When you enable reverse DNS lookups, WebLogic Server stores the DNS name of the server, rather than the IP address, in EJB home handles.
The following sections describe design tips that you should observe when developing and deploying EJBs on your system.
Preserve transaction resources
Database transactions are typically one of the most valuable resources in an online transaction-processing system. When using EJBs with WebLogic Server, transaction resources are even more valuable due to their relationship with database connections.
WebLogic Server can use a single connection pool to service multiple, simultaneous database requests. The efficiency of the connection pool is largely determined by the number and length of database transactions that use the pool. For non-transactional database requests, WebLogic Server can allocate and deallocate a connection very quickly, so that the same connection can be used by another client. However, for transactional requests, a connection becomes "reserved" by the client for the duration of the transaction.
To optimize transaction use on your system, always follow an "inside-out" approach to transaction demarcation - transactions should begin an end at the "inside" of the system (the database) where possible, and move "outside" (toward the client application) only as necessary. The following sections describe this rule in more detail.
Allow the datastore to manage transactions
Many RDBMS systems provide high-performance locking systems for OLTP transactions. With the help of Transaction Processing (TP) monitors such as Tuxedo, RDBMS systems can also manage complex decision support queries across multiple datastores. If your underlying datastore has such capabilities, use them where possible. You should never prevent the RDBMS from automatically delimiting transactions.
Use container-managed transactions over bean-managed transactions
Your system should rarely rely on bean-managed transaction demarcation. Use WebLogic Server container-managed transaction demarcation unless you have a specific need for bean-managed transactions. Possible scenarios where you may need bean-managed transactions are:
Note: If your EJBs use multiple transactions in a single method call, it is still better to break the transactions out across multiple methods and use container-managed transactions with the revised bean.
Never demarcate transactions from a client application
In general, client applications are not guaranteed to stay active over long periods of time. If a client begins a transaction and then exits before committing, it wastes valuable transaction and connection resources in WebLogic Server. Moreover, even if the client does not exit during a transaction, the duration of the transaction may be unacceptable if it relies on user activity to commit or rollback data. Always demarcate transactions at the WebLogic Server or RDBMS level where possible.
Use correct modeling for entity EJBs
Reading and writing RDBMS data via an entity bean can consume valuable network resources. Network traffic may occur between a client and WebLogic Server, as well as between WebLogic Server and the underlying datastore. Use the following suggestions to correctly model entity EJB data and avoid unnecessary network traffic.
Entity EJBs should be coarse-grained
You should not attempt to model every object in your system as an entity EJB. In particular, small subsets of data consisting of only a few bytes should never exist as entity EJBs, as the trade-off in network resources is unacceptable.
For example, line items in an invoice or cells in a spreadsheet are too fine-grained and should not be accessed frequently over a network. In contrast, logical groupings of an invoice's entries, or a subset of cells in a spreadsheet may be modeled as an entity EJB, if additional business logic is required for the data.
Entity EJBs should contain business logic
Even coarse-grained objects may be inappropriate for modelling as an entity EJB if the data requires no additional business logic. For example, if the methods in your entity EJB work only to set or retrieve data values, it is more appropriate use JDBC calls in an RDBMS client or use a session EJB.
Entity EJBs should encapsulate additional business logic for the modeled data. For example, a banking application that uses different business rules for "Platinum" and "Gold" customers might model all customer accounts as entity EJBs; the EJB methods can then apply the appropriate business logic when setting or retrieving data fields for a particular customer type.
Optimize entity EJB data access
Entity EJBs ultimately model fields that exist in a data store. You should optimize entity EJB wherever possible to simplify and minimize database access. In particular:
Use isModified() where appropriate
Use the isModified() method in entity EJBs to eliminate unnecessary database writes for read-only operations. See Using is-modified-method-name to limit calls to ejbStore() for more information.
Using inheritance may be appropriate when building groups of related beans that share common code. However, you should be aware of several inheritance restrictions that apply to EJB implementations.
For bean-managed EJBs, the ejbCreate() method must return a primary key. Any class that inherits from the bean-managed EJB class cannot have an ejbCreate() method that returns a different primary key class. This restriction applies even if the new class is derived from the base EJB's primary key class. The restriction also applies to the bean's ejbFind() method.
Additional restrictions exist for EJBs where inheriting another EJB implementation changes the interface. For example, the following table describes a situation where a derived bean adds a new method that is meant to be accessible remotely:
Bean |
Method |
Interface |
Method |
ABean |
afoo() |
ARemote |
afoo() |
BBean (extends ABean) |
bfoo() |
BRemote |
bfoo() |
Because AHome.create() and BHome.create() return different remote interfaces, you cannot have the BHome interface inherit from the AHome interface. You can still use inheritance to have methods in the beans that are unique to a particular class, that inherit from a superclass or that are overridden in the subclass. See the example Enterprise JavaBean subclass Child example packages and classes.
In the Model-View-Controller pattern, the view is the GUI form and the model is the piece of code that supplies data to the screen. In a typical client-server system, the model lives on the same server as the view and talks to the server.
It is better to have the model reside on the server, in the form of a session bean. (This is analogous to having a servlet providing support for an HTML form, except that a model session bean does not affect the final presentation.) With this design there should be one model session bean instance for each GUI form instance, which acts as the form's representative on the server. For example, if you have a list of 100 network nodes to display in a form, you might have a method called getNetworkNodes() on the corresponding EJB which returns an array of values relevant to that list.
This approach keeps the overall transaction time short, and requires minimal network bandwidth. In contrast, consider an approach where the GUI form calls an entity EJB finder method that retrieves references to 100 separate network nodes. For each of the references, the client must go back to the datastore to retrieve additional data, which consumes considerable network bandwidth and may yield unacceptable performance.
|
Copyright © 2000 BEA Systems, Inc. All rights reserved.
|