EJB Exception Handling
September 3, 2003 on 9:36 pm | In Java |Introduction
It is amazing that there are only so few resources [on the Internet] that show how to handle exceptions in EJB. A search on Google returns a large number of results, but almost all of these point to the same article on IBM DeveloperWorks. This shows how scarce information about this subject are. The alternative, of course, is to refer to the J2EE specifications, but the its sheer volume and jargon can be intimidating for someone wanting to learn the basics.
After foraging the Internet and reading various books, I managed to compile my own documentation that I present in this article.
Definitions
First, let us start with some basic definitions that will make it easier for the reader to understand the article.
A checked exception is one that is derived from java.lang.Exception, but is not a subclass of java.lang.RuntimeException.
An unchecked exception is one that is derived from java.lang.RuntimeException and is thrown by the Java Virtual Machine (JVM).
A system exception is one that is thrown by the system and is not recoverable. For example, an EJB container losing its connection to a database server causes a system exception. Similarly, a failed remote object method call causes a system exception.
An application exception is one that is specific to the application and is thrown due to a violation of the application business rules. therefore, an application exception must be determining for the client to know how to handle it. Such an exception is raised, for example, when the balance for a savings account becomes negative.
System Exception
System exceptions are unchecked and, by extension, are derived from java.lang.RuntimeException. Because it is nearly impossible for developers to predict their occurrences, the EJB container is the only one that is responsible for trapping system exceptions. The container automatically swallows (or wraps) an EJBException in a RemoteException that is subsequently thrown to the client. The wrapping process discards some information about the error, but the RemoteException remains sufficient since the client does not need to know about the specific erros that occurred (because they are system errors) and are unable to fix them anyway.
In addition to intercepting system exceptions, the container, depending on the implementation, may log errors.
From the above, it is now clear that if developers want system exceptions to be managed properly by the container and propagated to the client, they need to wrap them in EJBException that can be intercepted. The following code extract illustrates this point.
...
public String ejbCreate(String id, String username, String password)
throws CreateException {
try {
this.id = id;
this.username = username;
this.password = password;
insertRecord();
} catch (SQLException e) {
throw new EJBException(e); // swallow the SQLException
} catch (Exception e) {
throw new EJBException(e);
}
return id;
}
...
Note that since an EJBException is a system (and unchecked) exception, there is no need to declare it in the throws clause.
create(...) is a delegate method of the Home object created by the container. Also, the container will throw a RemoteException if the method fails due to a system error. Therefore, in the Home interface of our remote object, we declare that the create(...) method throws RemoteException, like this:
...
public UserAccount create(String id, String username, String password)
throws RemoteException;
...
The client code will then look like this:
...
try {
UserAccount userAccount =
userAccountHome.create("1001", "user", "password");
} catch (CreateException e) {
System.out.println("Object could not be created");
} catch (RemoteException e) {
System.out.println("EJB Error: " + e.getMessage() );
} catch (Exception e) {
e.printStackTrace();
}
...
In this example, the container notifies the client about a system exception by means of the RemoteException.
Application Exception
Application exceptions are checked and, therefore, need to be declared in a throws clause. They are thrown explicitly by code to indicate that a breach of the business rules has occurred. For example, trying to debit a sum of money that will make a savings account balance negative triggers a SavingsAccountDebitException. Because of their purpose, application exceptions are relied upon by the client to determine the cause of the error and send the proper notification to the end-user. Because the EJB container does not know how to process an application-specific exception, it does not intercept any. Also, application exceptions are not logged by the container.
Developers need not wrap such an exception in an EJBException. In fact, to prevent the container from hi-jacking the exception, developers SHOULD NOT write code to swallow the exception.
Below is a code extract that shows a typical application exception handling.
...
public void debit(double amount)
throws SavingsAccountDebitException {
if (this.balance == 0) {
throw new SavingsAccountDebitException(
"Cannot make a debit");
}
try {
balance -= amount;
updateRecord();
} catch (SQLException e) {
throw new EJBException(e);
} catch (Exception e) {
throw new EJBException(e);
}
}
...
Again, notice that even if an EJBException is thrown in the code, it needs not be declared in the throws clause. Also, this code does not demonstrate how transactions are rolled back, a topic which is covered further down in this article.
In the remote interface for the bean containing the above code, SavingsAccountDebitException must be declared, as in the following:
...
public void debit(double amount)
throws SavingsAccountDebitException;
...
The client code using the remote interface may then look like this:
...
try {
savingsAccount.debit(1000.00);
} catch (SavingsAccountDebitException e) {
System.out.println(e.getMessage() );
} catch (Exception e) {
e.printStackTrace();
}
...
As can be seen, the application exception has been successfully propagated to the client without being intercepted by the container. The client uses the information from the exception to notify the end-user; in this example, it simply displays the error message.
Exceptions and Transactions
The way that exceptions are handled affects the way transactions are managed
When a transaction is managed by the container, it is automatically rolled back by the latter when a system exception occurs. This is possible because the container can intercept this type of exceptions. However, when an application exception occurs, the container does not intercept it and, therefore, leaves it to the code to roll back the transaction.
The following code extract illustrates this point.
...
EntityContext ctx;
...
public void ejbRemove()
throws RemoveException {
try {
deleteRecord();
} catch (SavingsAccountDeleteException e) {
ctx.setRollbackOnly()
throw new RemoveException(e.getMessage() );
} catch (SQLException e) {
throw new EJBException(e);
} catch (Exception e) {
throw new EJBException(e);
}
}
...
Conclusion
I should point that the article mostly applies to remote EJB. When local EJB are used, RemoteException is never thrown.
As demonstrated, handling exceptions in EJB can be very different from what is done in standalone Java applications. In fact, the guidelines for dealing with each situation can be contradictory in some cases. For a comparison, please refer to my previous article, Exception Handling Best Practice.
To conclude, here are the four basic rules that, I believe, suffice to properly handle exceptions in EJB.
- If you cannot recover from a system exception, let the container handle it.
- If a business rule is violated, throw an application exception.
- Catch exceptions in the order in which you can handle them. Alternatively, catch them in descending order of likelihood of them occurring.
- Always catch a java.lang.Exception last.
Technorati Tags: Java, Exception+Handling
Related Posts:
- How to Handle Exceptions in EJB
- How to Format Dates for SQL in Java
- Exception handling or result code
- Robust Java Exception Handling
23 Comments »
RSS feed for comments on this post.
Leave a comment
Powered by blog.mu with Pool theme design by Borja Fernandez.


Nice article on EJB Exception handling
The article was seen on Erik’s weblog….
Trackback by Infloop — 4 September 2003 #
This one is very useful,i really impressed with the above information.
Comment by kiran — 12 January 2004 #
It is provides pretty good information .
Comment by Srinivas — 14 January 2004 #
really it is fantastic.
it completly clarified my doubts on EJB Exception handling
Comment by surendra babu — 28 January 2004 #
I am glad you found it useful. As I wrote, all the documentation that I found before I wrote this article was very confusing. So, I had to sit down with pen and paper to simplify all what I read.
Comment by Eddy Young — 28 January 2004 #
Concerning the practice of having EJBs throw application exceptions to indicate business rule violations, other best practice references indicate that return error codes should be used for this rather than exceptions? Is this wrong?
Comment by Rick Holland — 4 February 2004 #
Consider result code as low-tech, and exception as high tech :-)
Personally, I think that exceptions are more powerful since it does not interfere with the processing. Instead, it is up to the JVM to identify errors and notify the calling party. If you have to return result code, what happens if you want to return a result even if an error occurred and yet you need a result code?
Comment by Eddy Young — 4 February 2004 #
I was wondering if you could give the source to your examples, this is good stuff.
Comment by Cpearson — 19 February 2004 #
Too good man..
Comment by Venkat — 27 February 2004 #
I prefer to to let ejb-methods return a Result object that contains error-codes.Because then it is possible to return multiple (validation)errors. If the Result object contains errors the transaction is marked as rollback only. All Exceptions are caught in the ejb-method and thrown as EJBExceptions. I dont think that client code is interested in whether an ejb-method failed because of a IOException / EJBCreateException or whatever exception, it failed and there is not much more he can do than popping up a message “service temporily offline please notify your system administrator”. Exceptions are reserved for unexpected events.
Comment by johny — 2 March 2004 #
… and this is why I prefer to use exceptions. I don’t want to have to consider every single possibile outcome of a function call and proceed according to the result contained in the Result object.
With exceptions, I can just say, “OK, I can handle this, this and that exception, but I will just pop up an error message box for or log any other error.”
At the end of the day, it depends on the preferred way of the developer and whether he/she wishes to ride the wave the way most developers are doing [to ease code maintenance and readability]. I’m sure there are a lot of applications that are based on either method and work fine nonetheless.
Comment by Eddy Young — 2 March 2004 #
This is a nice article. Do you recommend passing back all application exceptions to the client? Currently we have a few methods like your ejbRemove() example where we catch a number of application exceptions. Currently we ‘convert’ all of them to EJBExcption, so that the transaction gets rolled back. For the one that we do pass back intact, we make sure that the transaction is rolled back, but for some reason it is view as an ‘ugly hack’. Thanks again for the article
Comment by Pete Hall — 3 March 2004 #
Given that the manual transaction rollback is described in the specifications, I do not think it is an _ugly hack_. However, I think that swallowing the application exceptions in EJBExceptions is a hack. You should always notify your client of the exact cause of an error if it knows how to handle it (display error message or retry). Either with an exception, or a result code. Masquerading an error by swallowing the exception is analogous to, I quote Bob Lee, _losing a wheel and keeping on driving_.
Comment by Eddy Young — 3 March 2004 #
I am basically doing what your article espouses - I put workflow/business logic in stateless session EJBs with container-managed transactions. The methods then throw application exceptions for business rule violations. The issue that I am having is that those applications get swallowed up by the container and the container instead throws rollback exceptions, thereby losing any information that I am passing back to my client as part of my application exception.
I am using Oracle 9iAS and Oracle claims that this is the behavior specified by the J2EE specs and followed by other leading J2EE container providers. I have read the specs and it seems to support my position.
Comment by ChrisR — 31 March 2004 #
Indeed, the container should not rollback transactions when application exceptions are thrown. Are you explicitly swallowing them in system exceptions? If yes, then this may be the cause.
If not, maybe you should try another application server. I use Orion Server and am quite satisfied with it.
Comment by Eddy Young — 31 March 2004 #
The article is very usefull.
Please queue up all the EJBException in catching order
Comment by Hemant — 4 April 2004 #
It’s good description about handling expceptions in java but it is not covered when we are come into Transaction Exceptions
Comment by Ramesh — 30 April 2004 #
Thanks for your article, it is really nice.
Comment by Jonathan — 9 May 2004 #
Funny. I was just noticing how all the Google hits were pointing to the same IBM Dev Works article.
Nice job. Thanks for taking the time.
Comment by Veronica Morales — 3 August 2005 #
Thank you very much for this article !!
Comment by Douglas — 3 March 2006 #
Douglas, you are welcome.
Comment by Eddy — 3 March 2006 #
[…] In the past, I have written about exception handling best practice and EJB exception handling. […]
Pingback by Java and friends » Robust Java Exception Handling — 20 July 2006 #
The article is very nice. It is appriciable to share his juce of effort.
Comment by Bharadwaz Hari — 8 September 2006 #