Nov 3rd, 2005, 08:16 AM
Information for All regarding EJB and Spring JDBC
I just ran across a problem that I would like to share with you all.
This occured while using the Spring JDBC package within DAO objects used by my SLSB's.
I noticed that in WLS 8.1 That when an exception (what I considered an application exception) was being thrown that the Beans in my Bean pool were being destroyed (one at a time). I then tracked down a section in the WLS documentation that states that when a non-application exception is thrown the container will destroy the bean.
I then looked into the EJB specification and found that a non-application exception is defined as either an EJBException or any other exception extending RuntimeException. This means that the exception softening in the JDBC Spring implementation always causes my beans to be removed from the bean pool when I subclassed the Spring exceptions and declare them as application exceptions in the throws clause of the EJB method...
Changing my application exceptions to not extend any type of RuntimeException i.e. to only extend Exception (and remove the Spring Exceptions from my exception hierachy) fixed this problem...
Don't know if anybody has come across this before (or have applications they dont even realise are suffering from the same thing) but it has a significant impact on the performance of our application as the bean creation rate after some time in production becomes quite high.
The answer to this 'as stated above' is to NEVER throw an application exception from an EJB that extends RuntimeException in any way. So in our case we capture ALL Exceptions from the Spring JDBC exceptions within our DAO classes and throw application exceptions that are not derived from any RuntimeException. This does force the client to handle the exceptions with Try Catch blocks though (bit of a shame, more work on the client side, just as I was begining to enjoy removing my try catch blocks)....
Nov 3rd, 2005, 10:14 AM
Usually I catch DAO exceptions somewhere in my business layer, since usually a client cannot do anything about it anyway. So I can choose there to convert the DAO (runtime-) exception into a (non-runtime) application exception as needed.
In any case it is quite helpful to enrich exceptions with accurate information on higher levels of abstraction.
However, if you are happy to pass through low-level exceptions but wish to treat them as application exceptions you might use an AOP proxy to do the conversion for you.
Nov 3rd, 2005, 11:10 AM
Our business layer is facaded the EJB SLSB layer so it is not possible to throw RuntimeExceptions as Application exceptions back to the client.
If we just let the DOA (Spring JDBC) Exceptions propergate past the SLSB Facade layer it would cause the same problem as these are all RuntimeExceptions. So what we do is state that any DAO exception is rethrown from the EJB layer as an ApplicationDataAccessException which previously extended the Spring DataAccessException. Now we have a new ApplicationDataAccessException which does not extend the Spring DataAccessException but just plain old Exception.
We do capture any Spring exceptions that we can handle, and we handle these in the business layer but those that we cannot handle (or recover from) cannot just be ignored and allowed to propergate past the EJB container and effectively have the container destroy the bean.
Nov 4th, 2005, 12:34 AM
Yes, this is not possible, since runtime exceptions are by definition of the EJB spec system exceptions.
Originally Posted by smcardle
That's why I proposed to use a proxy (between the SLSB and your DAOs) to do the conversion automatically. Of course the application exception has to be declared to be thrown, but the conversion can be done automatically. Thus you are relieved from your try/catch blocks.
Nov 4th, 2005, 07:37 AM
I will take a look at this. However, I am not sure I will get the OK to use Spring Proxies or Spring AOP currently in our production system.
I am slowly introducing more of the Spring framework into our project (next release has more Spring code) but it is slow and the initial conversion of our DAO's to use Spring JDBC originally met with some resistance.
But thanks for a poke in the right direction and I will certainly look at intoduction of Spring AOP to replace our current implementation (used for Auditing) of AspectWerkz (which I would love to get rid of know it is defunct) with either AspectJ or Spring AOP or maybe both
P.S. The original point of the post was not realy for support or help but just a reminder to other folks that throwing RuntimeExceptions from an EJB has undesireable side effects (I for one had forgotten this as its been a long time since I read the EJB spec) even if everything looks to run OK...
Nov 4th, 2005, 08:50 AM
According to some weblogic documentation I read an EJBException will be converted to a RemoteException for remote EJB calls. According to the J2EE spec an EJBException is suppose to indicate a failed operation. So for any runtime exception you consider an application exception, you should wrap it in a EJBException. I imagine this would prevent Weblogic from destroying your bean since it considers it to be a legitimate exception rather than an unexpected run-time exception.
Since EJBException is also a RuntimeException, you don't have to modify your business interface to accomodate this problem, which for me is very important. The remoting strategy should never IMO require your business code or interface to change.