Hi everyone,
Here is a thought about exception handling within an EJB container. Let me first start
with a little example to demonstrate the nature of a potential problem with the
conventional exception handling practices.
Suppose we have an EJB called MortgageDAOBean which implements Stateless interface.
public class MortgageDAOBean
| {
| public BigDecimal getCurrentRate()
| {
| // get current rate from the database.
| }
| }
We also have an EJB called MortgageCalculatorBean which implements Stateless interface.
public class MortgageCalculatorBean
| {
| private MortgageDAOBean mortgageDAOBean;
|
| public BigDecimal getMortgageAmount()
| {
| BigDecimal currentRate = mortgageDAOBean.getCurrentRate();
|
| // do some further calculations here.
| }
| }
And finally we have an EJB called MortgatePublisherBean which implements Stateless
interface and sends the results of mortgage calculations to some JMS destination.
public class MortgatePublisherBean
| {
| private MortgageCalculatorBean mortgageCalculatorBean;
|
| public void publishMortgageAmount()
| {
| BigDecimal mortgageAmount = mortgageCalculatorBean.getMortgageAmount();
|
| // do some publishing logic here.
| }
| }
For the sake of simplicity we can assume that methods of MortgageDAOBean and
MortgageCalculatorBean throw only EJBException, which is a system exception that makes the
container to roll back the transaction, log the exception and discard the instance of the
EJB.
Note that our MortgatePublisherBean does not do any exception handling because at this
stage we are not interested in any particular type of exception, as long as EJBException
is thrown that suffices us.
However, we may have a situation when we need to do some exception handling depending on
whether the exception was thrown by MortgageDAOBean or MortgageCalculatorBean.
Furthermore, this requirement only exists in the context of MortgatePublisherBean and
should not be applied to any other potential users of MortgageDAOBean or
MortgageCalculatorBean. This task cannot be achieved with our current implementation of
EJB?s, because both of the EJB?s throw the same type of exception, which is EJBException.
What we would need is some type of exceptions which are associated with a particular type
of activity. In our case we could have, for example, DataAccessException associated with
MortgageDAOBean and CalculationException associated with MortgageCalculatorBean. These
exceptions must not force users to catch them (remember that it?s only
MortgatePublisherBean that needs to handle these exceptions), must be delivered as they
are (without being wrapped within EJBException) and must result in transaction rollback.
This can be achieved by sub classing our exceptions from RuntimeException and defining
them as application exceptions which cause transaction rollback.
So now our MortgatePublisherBean would look like this:
public class MortgatePublisherBean
| {
| private MortgageCalculatorBean mortgageCalculatorBean;
|
| public void publishMortgageAmount()
| {
| try
| {
| BigDecimal mortgageAmount =
mortgageCalculatorBean.getMortgageAmount();
| }
| catch(DataAccessException exception)
| {
| // do some exception handling here.
| }
| catch(CalculationException exception)
| {
| // do some exception handling here.
| }
| }
| }
This works fine and solves the problem with exact exception handling. However this
approach has a major drawback. The problem comes from the fact that application exceptions
do not signal the container to discard EJB instances in which such exceptions occur.
To demonstrate the consequences of this problem, imagine that our MortgatePublisherBean
would implement Stateful instead of Stateless interface. This would mean that a new
instance of MortgatePublisherBean will have to be created and associated with its own
client for the length of its lifecycle. Whenever CalculationException occurs within an
instance of MortgatePublisherBean the instance will not be automatically destroyed by the
container and will exist until it is explicitly destroyed by its client or expires
according to its timeout settings. This can potentially lead to multiple instances of
MortgatePublisherBean with incorrect internal state remaining in memory of the container.
It may seem like a useful thing to be able to define application exceptions as those that
will cause destruction of EJB?s within which they occurred and as those that will not
cause destruction of EJB?s.
For example, both DataAccessException and CalculationException exceptions may be defined
as application exceptions that cause EJB instance destruction. This is because both of
these exceptions are unrecoverable and there is no point to keep instances of EJB?s within
which the exceptions occurred (in other words there is not much we can do to those
instances because their state may be corrupt). On the other hand checked application
exceptions such as IllegalArgumentException may be defined as application exceptions that
do not cause EJB instance destruction. This is because we may want to do some recovery
procedures and call the instance of the EJB again, in which case it must still exist
within the container.
Introducing this level of customisation for application exceptions will allow to use more
specific types of exceptions than just EJBException, but also preserve the interaction
between EJB?s and a container that is currently ensured by EJBException.
This is rather a suggestion and I may well miss something, anyway it would be great to
hear what other people think of this idea.
View the original post :
http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4059452#...
Reply to the post :
http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&a...