OK, here is a fairly interesting design question that surfaces when you begin to
design non-trivial EJBs. Unfortunately, I will have to trivialize the example to
make it easily presentable. The major assumption that you will have to make is
an EJB cannot always validate itself. Sometimes the validation of an entity bean
(a row in the database) can only be determined by another method external to the
entity bean.

Trivial Example
============
A bank allows its customers to have multiple accounts, but the balance in all
accounts combined, cannot be less than $100.

Design
======
Logically, we would create a stateless session bean Teller, that directly
manipulates Account entity beans. Our database is set to read-uncommitted, a
common and default setting of most databases. The withdrawal method in Teller
performs the following pseudocode logic:

1. Teller.withdrawal (String accountPK, BigDecimal amount) {
2.     // do the dirty work
3.     Account account = accountHome.findByPrimaryKey(accountPK);
4.     account.withdrawal(amount);
5.     // make sure account balances didn't drop below limit
6.     performLimitCheck();
7. }

Now the code in performLimitCheck() could query the database directly, or work
with a collection of EJBs. We don't really care at this point.

The Design Problem
===============
The flaw with the above logic has to do with the order that the EJB container
performs its operations. Line 4 above causes the ejbContainer to perform an
ejbLoad() on our Account bean. Next the withdrawal() method is invoked and the
bean's attributes reflect the new amount. Note: No data has been written to the
database yet! By the time line 6 performs its validation of the current state of
the database, the database hasn't changed one bit. It will always report that
all is fine.

It isn't until line 7 that the ejbContainer invokes ejbStore() and the Account
bean writes the data to the database. At this time, the database may be in an
invalid state.

The Workaround
=============
I'm not sure there is a good one. In my trivial example, some would argue that
the performLimitCheck() should take into consideration the withdrawal amount
when validating the database. I would argue that this is a trivial example.
Suppose there was business logic in the AccountBean that added interest to the
account at the same time the withdrawal amount reduced the balance? Given more
complex scenarios this "pre-validation" technique continues to have other
problems.

The only workaround that I can see is to call ejbStore() before validating the
bean, or in a worse case, invoke it at the end of the withdrawal() method. This
shouldn't cause any integrity problems that I can see, although most entity
beans would suffer performance slowdowns due to multiple ejbStore() calls.

The Solution
==========
The EJB spec authors should give us a way to tie a validation method to each
session bean method. This could be extended to entity beans, but that doesn't
help us. This validation method would be called by the EJB container after all
ejbStore() methods are called, and before the transaction is closed.

As always, I am interested in your feedback. Please comment.

jim

===========================================================================
To unsubscribe, send email to [EMAIL PROTECTED] and include in the body
of the message "signoff EJB-INTEREST".  For general help, send email to
[EMAIL PROTECTED] and include in the body of the message "help".

Reply via email to