Reputation: 2506
I'm trying to better understand exception handling and logging in a j2ee
environment to refactor some legacy code (we use log4j
for our logging mechanism). Most of our current code does something like the code below on the business tier, however, I'd like to switch over to unchecked exceptions and just ignore them unless it makes sense to handle them somewhere:
try {
doSomething();
} catch (MyException e) {
log.error("Exception:", e);
throw e;
}
After the exception is thrown in the business tier, it is then propagated up to the presentation tier, which again catches the exception and usually wraps it in a PortletException
or ServletException
and throws it again. Then, it is handled by a Spring handler which shows a 'friendly' message to the user. I'd ultimately like to only handle exceptions for which we want to show a specific error message, and just ignore everything else.
Questions:
I am confused as to how the process works...
Thanks.
EDIT: If an exception occurs in an outside library (Spring, Hibernate, etc), is it assumed that these exceptions will be printed out using whatever logging mechanism is being used? In that case, I guess that I would only need to log the exceptions that my code throws... or am I way off base here?
Upvotes: 1
Views: 2735
Reputation: 2635
You could create your own exception hierarchy to wrap them to quickly identify from where in your application architecture it is originating. Also one can go a step further to provide codes and reasons that covers majoority of the use cases.
What logging helps you is to identify the sequence of events, when potentially multiple clients are slamming the same use case or hitting a bottle neck. The logging give you a sequence to trace back because requests increasesed there was congestion in this query causing it to timeout and thus other users where seeing another exception.
While handling the application and showing it to the user is another issue.
Cheers!
Upvotes: 1
Reputation: 21194
Firstly, you can and must log the exception stack trace of all exceptions. In fact, IMO if you only log that an exception happened you might as well not log it at all. However, very often what this leads to is a relaxed view of exceptions. What you should strive for is to have 2 log files or one specific category that if exceptions are in that category they mean something critical happened and must be addressed. Even if that means logging the same exception many times. Rather too many than not at all.
Secondly, it's fine to change all exceptions to checked exceptions - the majority of exceptions are not "recoverable". What I have done that worked well is simply wrap all transactions in an exception handling wrapper which logged the exception, then I can guarantee that all exceptions are logged. Furthermore, create a bunch of exception classes that extend runtime exception - this is much better than rethrowing exceptions as runtime exceptions as very often the inner exception stack trace is not logged in full when you wrap exceptions.
And thirdly, it is important to create a mechanism to map exceptions that do filter through to the front end with the back end cause. This is challenging but it's quite important. Errors that the user sees are far easy to track down if you can map them back to an exception stack trace in the log file.
Upvotes: 0
Reputation: 652
Before proceeding any further, please take a careful look at:
The following are some of the generally accepted principles of exception handling:
- If you can't handle an exception, don't catch it.
- If you catch an exception, don't swallow it.
- Catch an exception as close as possible to its source.
- Log an exception where you catch it, unless you plan to rethrow it.
- Structure your methods according to how fine-grained your exception handling must be.
- Use as many typed exceptions as you need, particularly for application exceptions.
Point 1 is obviously in conflict with Point 3. The practical solution is a trade-off >?between how close to the source you catch an exception and how far you let it fall before you've completely lost the intent or content of the original exception.
It is usually advised that you use checked exceptions for application exceptions at the business tier. I prefer to follow the business interface pattern to decouple the business tier from the user interface and web tier. This will allow me to think of your business tier as a service layer library and callers might want to handle different situations differently when calling this layer. That is one reason you might want to include checked exceptions, since you can react differently to different exceptions. Furthermore, including checked exceptions will usually help the caller code to be better aware of what different situations might arise from invoking some functionality. It could be worth it to take a look at the business delegate pattern and how it might help you with exception handling. In short, the business delegate pattern allows you to create a very thin layer between the business layer and the web layer where you can do things like exception handling.
No matter how you go about doing this, make sure that you understand the implication of adding an application exception to your Java EE application. You may need to investigate how it interacts with your transaction management logic, specifically when it comes to transaction rollbacks. In my line of work, I had to add an @ApplicationException(rollback=false) to forbid the transaction manager from rolling back my transaction when an exception is thrown and propagated upwards.
You may be able to tell I was working with EJB, but the concepts are probably very applicable to your design as well.
So back to your questions:
Is it necessary to log exceptions in the business tier?
It is not necessary if you plan to log it later on. You better devise a logging strategy at a high level and log all caught exceptions there.
If not, do I need to log exceptions at all (especially unchecked ones)?
I think that you should log exceptions because that will help you debug any issues later on. The user is usually not savvy enough to capture any output that might be produced if the exception propagates and gets printed on his/her screen without you handling it.
What happens to uncaught exceptions that are not logged using log4j? (If they're still printed in the console, what's the purpose of log4j?)
I think it will eventually be caught by the web container and be printed out to the console. If an exception propagates upwards and reaches the web container exception handling safety nets, your exception is out of control. It is usually a sign of bad design. It is best if you keep your exceptions under control. Why wonder how a container will react to an uncaught exception? Also how beneficial will that exception be to the user? I think the information presented from uncaught exceptions are almost useless, as they are so far from the source of the error, that they become irrelevant and hard to work with when debugging.
Upvotes: 4
Reputation: 18214
You don't need to catch the business exception (as long as it's unchecked). You don't need to handle them or to log them. You can just swallow them. The problem is - what is such exception for?
Exception signals some inappropriate behaviour in the workflow of your application. If it's checked you, typically, can do something about it - try do some operation again, do some workaround, try different action, etc.
If it's unchecked, it is typically an exception you don't know how or can't handle.
It's considered a code smell if all you do is catch an exception and log it. It's not as bad as swallowing it, but still - it's not good.
Some of the containers (i.e. EJB) is required to log occurred exceptions. Moreover, in EJB 3.x if you're in a JTA managed transaction, and you won't catch an unchecked exception which is not marked as @ApplicationException(rollback=false)
than the transaction will be automatically rolled back. This might be the reason why you can see some try...catch blocks with just logging code inside.
If you want to get rid of exception handling code in your business logic, you might introduce an interceptor which will react appropriately upon particular exceptions.
HTH!
Upvotes: 0
Reputation: 10789
Is it necessary to log exceptions in the business tier?
No. But more logs = better understanding what is going on. In other way more logs = lower performance.
What happens to uncaught exceptions that are not logged using log4j?
You lost them. Logger pretty things that you can save logs in the place where you need and use filters to get only actual logs for now.
Upvotes: 0
Reputation: 115378
We definitely do not have to handle exceptions just to log them. I believe we should catch exception if we then throw other exception that contains the source exception as its cause or if we implement some logic that must be implemented in current layer when exception is thrown.
Yes, it is a little bit verbose to declare all methods as throws MyException
. This is the reason that Spring (that you use) prefer working with unchecked exceptions. BTW this is the new feature in Java 7: you can ignore exceptions without declaring that method throws it.
I believe that we still need checked exceptions for development of libraries that expose API to 3rd party applications. Application layer exceptions should be mostly runtime and be caught in one central place.
Upvotes: 0