BEA Logo BEA WebLogic Server Release 5.0

  Corporate Info  |  News  |  Solutions  |  Products  |  Partners  |  Services  |  Events  |  Download  |  How To Buy

Designing a WebLogic EJB application

Design tips
Back to basics
Design the user interface first!
Why do you never touch the bean directly?
Components should be coarse-grained
Using inheritance and EJBeans
EJB Containers
Dynamic classloading

Using Entity Beans
Beans == rows in a database
Don't fight database optimizations
Don't distrust database optimization and caching
Avoid distributed transactions
Always write a custom primary key class for entity beans
isModified() and persistence

Using Session Beans
'Model' provided by session beans
Network transparency is a myth

Other related documents
Installing WebLogic (non-Windows)
Installing WebLogic (Windows)
Overview of WebLogic Enterprise JavaBeans
Using WebLogic Enterprise JavaBeans
Using the WebLogic EJB Deployment Wizard
Code examples
Troubleshooting EJBeans
Glossary

This is a collection of design tips and debugging points to keep in mind when building applications with EJB (Enterprise JavaBeans). A number of these tips apply to remote object models (RMI and CORBA) as much as they do to EJB.

You should also read and be familiar with:

Top

Design Tips

Back to basics

When beginning a development project that involves using Enterprise JavaBeans, it is useful to remember these basic points as you formulate your design.
  • EJB provides object services: security, transactions, persistence, remoting, etc.
  • EJBeans are transactional and secure components
  • How they are remoted -- using RMI, CORBA -- is not important
Session bean
  • Pure business "logic" bean
  • Contain no data
  • Similar to a stored procedure, but able to take advantage of the object services
Entity bean
  • Represent a row in the table: "data" bean
  • A business object with a unique business identity
  • Identity determined by the primary key
Combine entity and session beans as appropriate. An example using an order entry system:
  • Customer entity bean: the customer record
  • Order entity bean: the service order
  • Order process session bean: knows the process for completing an order:
    1. Check customer credit limit
    2. Check availability of stock
    3. Place order, record (commit) a transaction

Design the user interface first!

Don't fall into the trap of developing the object-oriented design (the bean) first, and then producing a user interface that's little more than a view of the object model.

Intuitive behavior, support for expert typists and power users, inter-screen communication, information-rich screens that aren't just pretty icons are just a few of the features that should be given attention before you start designing the beans.

If the user interface is not fast enough, go directly to the database if you have to. This may sound heretical, but the user doesn't care how it happens -- they just want to get their job done!

Why do you never touch the bean directly?

A common question and point of confusion: why do you never touch the bean directly?

Because if you didn't have the Container, then either the client (and all the different clients that might work with this bean) or the bean itself would need to know how to provide all the object services.

Instead, the ejbObject provides an interface, and through that interface you work with the bean. The container acts as an intercessor between the client and the bean.

Though this looks like it is adding an entire layer of complexity, what it means is:

  • The client application doesn't need to know anything about providing security, transactions, persistence, remoting or any of the other object services
  • Neither does the bean writer
  • All of these are provided by the Container, through the ejbObject

If these services were provided by the bean, there would be problems of duplication of code, lack of portability from one implementation to another, and the benefits of the component model would be lost.

Also, remember the difference between CORBA and EJB, and where transactions fit in:

  • CORBA is a remote access mechanism
  • EJB is a component model that provides object services
  • Transactions are governed by the underlying database for entity beans

Components should be coarse-grained

A common reasoning seems to be as follows: "Objects are good, objects that are remotely accessible are better, and remote objects with declarative transaction and security attributes are even better". Challenge this idiom as much as possible.

User-time and network-time are not free. Don't make all objects of your system available remotely. Line items in an invoice, cells of a spreadsheet... these are fine-grained objects. They shouldn't be accessed frequently over a wire.

Instead, have their containers provide a bulk-CRUD (Create, Read, Update, and Delete) API to access anything at a lower level.

Using inheritance and EJBeans

Inheritance works when building groups of related beans that share common code, but you should be aware of issues that the EJB specification does not address.

Consider ejbCreate() and ejbFind().

ejbCreate() for a bean-managed EJBean is expected to return a primary key. Any class inheriting from this bean class cannot have an ejbCreate() returning a different primary key class, even if this new class is derived from the base classes' primary key. ejbFind() has exactly the same issue.

Now, let's look at what happens if this process of implementation inheritance changes the interface: perhaps the derived bean adds a new method that is meant to be accessible remotely. The situation would be:

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 overloaded in the subclass.

See the example Enterprise JavaBean subclass Child example packages and classes.

EJB Containers

What is an EJB Container?

Though the Enterprise JavaBean 1.0 specification talks about "containers", it does not say exactly what a container is, beyond speaking of it as the place "where an enterprise Bean object lives, just as a record lives in a database, and a file or directory lives in a file system."

In the WebLogic Server, the container is the environment, the cocoon around the bean that implements EJB semantics. In other words, the container is the entire EJB service.

There are third-party products that are described as "EJB containers", but they typically provide a specialized service such as persistence; they do not provide EJB semantics (such as when to call ejbActivate, ejbLoad, ejbStore, etc.) or when to start and stop transactions.

With that context, many services that are described as requiring containers -- such as encapsulation of another system's API for their business logic -- actually require a set of EJBeans rather than a container. It's not required nor a good idea to re-write lower level services merely to provide a face to an existing public interface.

Support for multiple containers in WebLogic

Once WebLogic provides an interface to the transaction service (which will be part of our completion of JTA), anyone would be able to implement another EJB service under a different package hierarchy. Our EJB implementation is built on standard APIs (RMI, JNDI, JDBC and JTA); these APIs are our "container-to-server interface". Note that simply that supporting multiple EJB home implementations does not constitute multiple container support.

When to use a custom container

There is a place for a custom container -- such as Versant's "Enterprise Container", providing access to the Versant ODBMS. But before embarking on such an endeavor, define what the container is, what it is to do, and determine if you can't achieve the same goals by writing EJBeans instead.

Dynamic classloading

For information on EJBeans and dynamic classloading, see the Tech Support Guide Troubleshooting your WebLogic EJB application.

Using Entity Beans

Beans == rows in a database

Treat beans just as you would rows in a database. Note that a bean doesn't necessarily correspond to a single row (or any row, for that matter); this advice is merely to treat it with the same caution you'd apply for accessing rows in a database. That means:
  • Correct modeling is important: all the principles of RDAs apply

  • Most overhead is in the queries: be parsimonious with disk access and limit the complexity of joins

  • Minimize roundtrips between client and server: bean methods must return as much data as possible in one shot

  • If you need attribute accessors, have bulk get/setAttributes() methods for the same reason as above

  • Treat usage of attribute accessors (especially attribute modifiers) with suspicion: look for the real intention behind such a call. It may be better to call employee.promote() than employee.setTitle("Senior Software Engineer")

  • If all you need is data access, and you do not need the object services, EJB is not for you; you should talk directly to the database using WebLogic/JDBC

Don't fight database optimizations

Relational databases are optimized for bulk access. To avoid having to go to the database for each object, prime the EJB cache using a suitable finder to bring in a group of relevant entity beans with as few queries as possible -- ideally a single query.

Don't distrust database optimization and caching

Some of the biggest/meanest/fastest systems in deployment today have been done with the help of TP monitors such as Tuxedo running on top of relational databases. A TP monitor provides stateless services. Consequently, the application goes back to the database for every single request, without caching anything. Guess what? It works well. Don't underestimate database caching capabilities.

Avoid distributed transactions

Avoid distributing a transaction as much as possible, especially across disparate systems. This is especially true of beans wrapping legacy systems; do not try them in the same transaction. It's better to have a shared database, workflow or queued messaging setup between the two.

Always write a custom primary key class for entity beans

For container-managed persistence, the EJB 1.0 specification requires you supply an application-defined primary key class. But for bean-managed persistence, the class can be any non-primitive type (such as java.lang.String).

However, since the signature of findByPrimaryKey() requires you to supply the primary key class as the argument, if you ever change the implementation from bean-managed to container-managed persistence, you will be forced to change the home interface and consequently affect all current users of that bean.

Moral of the story: always write a custom primary key class unless you are certain that you are never going to change the type of persistence.

isModified() and persistence

WebLogic does not call isModified() for beans which manage their own persistence. Instead, it calls ejbLoad() and ejbStore() at the beginning and end of every transaction, which in turn could call isModified() (as illustrated in the extensions isModifiedBeanManaged example, a entity EJBean-managed persistence that demonstrates using isModified) if the bean doesn't want to interact with a database because it knows it is in sync with the database.

Of course, the bean must set the isModified() flag to true in any place where the state changes.

What's not obvious is that methods such as ejbRemove(), ejbActivate(), and ejbPassivate() must also set this flag to true, because the bean could be pooled and reused. Using isModified() is prone to errors.

In the case of container-managed persistence, you will need to set the flag to false in the ejbLoad() and ejbStore(), as shown in the container-managed example, if you want the container to take advantage of this optimization.

Though ejbStore() is called before the EJBean is actually written to the database, in the event an exception is raised while writing to the database, the framework will assume that the EJBean has been modified, regardless of the setting of the flag.

Using Session Beans

'Model' provided by session beans

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 client-server setup, the model typically lives on the same server as the view and talks to the server. It's preferential to have the model on the server, in the form of a session bean; a smart Java stored procedure, if you will. (This is similar to having a servlet providing support for an HTML form, save for the fact that the model session bean does not worry about the actual presentation.) There should be one model session bean instance for each GUI form instance, acting 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 bean which returns an array of values relevant to that list.

In contrast, imagine an approach where the GUI form calls a custom Finder method on the NetworkHome, and for each of the 100 EJBObject references returned, it goes back to the corresponding bean to fetch more data. You might as well go out for a cappuccino while the list gets populated.

To put this another way: never expose your entity beans directly to the client. (Though we show examples such as the beanManaged example where an entity bean is exposed to the client, this is only for the purpose of illustrating accessing entity beans only.) The model session bean should be accessing the entity beans. This keeps the transaction time short while the transaction itself is more localized and requires considerably less network bandwidth.

Network transparency is a myth

The EJB/RMI synchronous calling mechanism is convenient, but it is not network transparent; you have to deal with various flavors of java.rmi.RemoteException.

It is not cheap either, considering that it consumes a thread on the server and having it block during a transaction eats up a precious resource. Having a session bean act as a model eases the load on the system. By keeping the overall transaction short and local to the server, it reduces the possibility of other threads locked up due to contention.

 

Copyright © 2000 BEA Systems, Inc. All rights reserved.
Required browser: Netscape 4.0 or higher, or Microsoft Internet Explorer 4.0 or higher.
Last updated 09/08/1999