Java, handling potentially large numbers of exceptions in one class - handler class? - java

I'm working on a Java project and I've come upon an interesting design issue. It's not exactly a problem, but it is a bit ugly with the obvious solution.
I have a class implementing Callable, although with the current implementation it could just as easily be a Runnable as I'm not interested in the outcome, at least not as far as the calling thread is concerned. The calling thread will drop a number of these into a thread pool. Each of these Callables will have a batch of data that was obtained from an external service. The Callables will perform a number of actions, many of which involve making further calls to external services. As a result, there are a good number of places where various Exceptions could be thrown.
The issue I find is that depending on where the Exception occurs, I may need to take different actions. If it happens at point A, then delete the data on the external service. If it happens at point B, move the data to a different location on the server. If it happens at point C, just log it and do nothing further, etc. Any number of Exception types could be thrown at multiple points, although I don't think I'll need to do much filtering on the type itself, but more that one occurred.
The Callable itself isn't terribly huge, so there's not a great deal of code to mess with. However, I am hesitant to kludge it up with a ton of try/catch blocks to handle every possible point/Exception that may need different handling. I realize that this may really be the only viable solution. I don't really have control over most of the Exceptions that will be thrown (maybe a handful) without catching an existing one and rethrowing my own, which seems a bit redundant. I'm wondering if there's a good pattern or method to handle this sort of thing.
I've considered an exception handling class, but I'd still need to catch each Exception somehow and pass it to the handler as the point at which the Exception was thrown is important. I could break the Callable down into more atomic classes, each with their own small block and handling, but that would be trading one kludge for another. Catching everything in the call() method outright or by grabbing the Exception from the Future in the calling thread really isn't an option as this will lose the data on where it occurred unless I want to parse the stack trace, which isn't exactly viable.
Can anyone shed some light? Maybe I'm just quibbling over the try/catch blocks and should just go ahead with it, but I feel like there must be a better way...
Hmmm, it does occur to me that annotations on methods might help here. I could break down all methods until there's only one possible exception-throwing piece of code in each. Annotate each of these with a custom annotation that dictates what is done when that method throws an exception. I'm not sure if it is possible (an exception would somehow need to be caught right there as it may happen within a loop going over each piece of data and only one piece may be problematic, or at least somehow mark that piece for processing further up the chain), but perhaps this could mitigate the need for lots of try/catch blocks and instead handle the behavior with a single annotation and a handler class to deal with the exceptions. I don't believe it's possible to dictate behavior this way with an annotation, but I'd be happy to be wrong on that.

Related

Find out all java code places where a blocking operation happens

In our Netty application. We are moving all blocking calls in our code to run in a special backgroundThreadGroup.
I'd like to be able to log in production the threadName and the lineNumber of the java code that is about to execute a blocking operation. (i.e. sync File and Network IO)
That way I can grep for the logs looking at places were we might have missed to move our blocking code to the backgroundThreadGroup.
Is there a way to instrument the JVM so that it can tell me that?
Depends on what you mean by a "blocking operation".
In a broad sense, any operation that causes a voluntary context switch is blocking. Trying to do something special about them is absolutely impractical.
For example, in Java, any method containing synchronized is potentially blocking. This includes
ConcurrentHashMap.put
SecureRandom.nextInt
System.getProperty
and many more. I don't think you really want to avoid calling all these methods that look normal at a first glance.
Even simple methods without any synchronization primitives can be blocking. E.g., ByteBuffer.get may result in a page fault and a blocking read on the OS level. Furthermore, as mentioned in comments, there are JVM level blocking operations that are not under your control.
In short, it's impractical if not impossible to find all places in the code where a blocking operation happens.
If, however, you are interested in finding particular method calls that you believe are bad (like Thread.sleep and Socket.read), you can definitely do so. There is a BlockHound project specifically for this purpose. It already has a predefined list of "bad" methods, but can be customized with your own list.
There is a library called BlockHound, that will throw an exception unless you have configured BlockHound to ignore that specific blocking call
This is how you configure BlockHound for Netty: https://github.com/violetagg/netty/blob/625f9d5781ed85bfaca6fa4e826d0d46d70fdbd8/common/src/main/java/io/netty/util/internal/Hidden.java
(You can improve the above code by replacing the last line with builder.nonBlockingThreadPredicate(
p -> p.or(thread -> thread instanceof FastThreadLocalThread)); )
see https://github.com/reactor/BlockHound
see https://blog.frankel.ch/blockhound-how-it-works/
I personally used it to find all blocking call within our Netty based service.
Good Luck

Not-an-exception exception in Java?

Does java has library exception class which means actually not an error, but good termination? I know I can make my own class or use null, but wish to know.
EDIT 1
I want to use exception object as an old fashion return code for a method, so I need something equivalent to ERROR_SUCCESS code in Win32 API.
Exceptions in Java are meant to be used for abnormal termination only. Using them to flag correct termination should be considered really bad practice.
You might use return values instead.
To directly answer your question: No. There is no standard Java exception that means "this is a normal termination".
If you wanted to, you could define a custom exception that meant this for your application.
However,
... using an exception for "normal control flow" goes against the strong recommendations of the Java designers, and a Java "Best Practice" rule that has pretty much universal acceptance. This is not to say you should NEVER do this. It is just that the cases where it is justifiable to do this are VERY RARE. (And you'd need to take special steps to avoid grossly inefficient code ... )
Anyway, the fact that it is (almost) always a terrible idea to use exceptions for normal flow control explains why a standard exception was never created. The Java designers clearly didn't want to appear to be encouraging this practice.
The closest thing to a "good termination" signal I can think of is not an exception, but a call to System.exit(int) with 0 as argument, to indicate to the operating system that the program ended successfully. From the javadocs:
Terminates the currently running Java Virtual Machine. The argument serves as a status code; by convention, a nonzero status code indicates abnormal termination. This method calls the exit method in class Runtime. This method never returns normally.
As has been pointed out, an exception is not to be used to inform of a "good termination", quite the contrary.
No. Exception means exceptional situation. You should structure your program flow so that exceptions are thrown only for exceptional situations, rather than on the normal flow.
So, if you want to return "success": return true or some enum Result.SUCCESS.
Exceptions are mean to denote that something went wrong. Different exceptions depict different items which went wrong and will thus cause the program to terminate if not handled. Something successfully finishing is not an exception.
I think what you need to do is to either return a particular value, or else, make your application fire some sort of event. In this case throwing exception is not (at least for me) recommended.
Depends what you define as "good termination" I guess - is a security exception good because it stopped someone from hacking your system? It's not really an error, but it is an abnormal situation that you need to handle.
In general exceptions are designed to be used for exceptional conditions only (which may or may not be an error in your code - it could mean that some resource is unavailable, or a security check failed etc.)
If you are using exceptions for regular control flow (i.e. they are getting thrown in normal, expected circumstances) then you are probably doing something wrong.
Maybe you mean an InterrupedException? This one is thrown, when you wish to terminate a thread gracefully.
As some other responses said, when there is no exception, nothing is raised.
Therefore, you can just your code for the "no-exception" into the try block after the rest of instructions. Something like:
try{
//code here
//code of no exception
}catch(Exception e){
//nothing or exception code
}
or you can just create your own exception by doing a class that extends Exception

Java Error handling - is it better to throw Exceptions to centralized error handlers?

I've got a decently complex little game going on in Java (solitaire, essentially like the Windows version), but I have yet to do very much error handling.
Almost all of the methods across my classes will end up either getting called by an initial constructor (eventually main()), a paintComponent() method, or a mouse event. So, my question is, is it bad practice to just use "throws Exception" on all of my lower-level methods, and only do a try/catch at my top-level methods to catch ALL the errors at once? (e.g. 3 try/catches - one for the painting, one for mouse events, one for the main method).
I realize this prevents me from easily dealing with errors on-the-spot, but I don't really plan on doing that anyways. My error handling is going to consist of writing to a log, telling the user, and killing the program. Keeping this in mind, is there anything bad with doing my error handling this way?
It depends on how you want to approach the situation.
If you just want to catch any possible exception and you don't mind about the handler code, you could simply use "throws exception", and there's nothing BAD with it either. It's like a try-catch block that covers all the function.
If you want to write specific code for specific exceptions, you should use try-catch blocks to write appropriate code for each handler.
Based on what you're saying, any caught exception would just notify the user and exit the application. Well, in this case you could just use the first approach. It's not necessarily the BEST approach, and neither is killing the application, however, if that's your strategy you could just use "throws" for each function.
Hope that helps!
If that's all you wan't to do in a case of an error, then it makes perfect sense to do it that way. This eliminates code duplication and scattering of related code. However, if you're thinking of changing how things work in the future (if there's a possibility of this happening), I would suggest to try and push the catch down as far as possible (maybe even eliminating the need for exceptions at all and just logging and exiting right away).
If you use the exception's inner fields (specifically message, which you can set in construction time), you can even eliminate the need for 3 different catch blocks and just use one (depending on your actual actions in case of an error, of course).
I wouldn't - the big reason being that it breaks encapsulation. The reason why this is important in this case is that your error handling code has one of two futures:
Becoming enormous to handle in an informative way every error the program can throw.
Be tiny but not helpful at all: "Some error occurred somewhere".
To my mind, the best structure is to catch the error, log it, alert the user, and exit as far down as possible. There's nothing that says your mouse handling code can't exit, right?
In fact, I would create an error handler class that you can call from just about anywhere, and it handles the notification and logging. Then your exception handlers can just populate it with the message to display/log, and all other code is shared. It will cost you less typing to delegate to this class than adding throws Exception at the end of every function everywhere.
If you must have a top level handler, it should just catch any unexpected runtime errors, so that you can log it and show the user that the program is really quitting for an error, and not just dump to the desktop. All other errors - even if you just want to bail out - should be caught as close to "where the exception has meaning" as possible.
I do the same thing as you are describing most of the time. What you're basically doing is working around the stupid checked exceptions that Java has. It shouldn't even be necessary to add 'throws Exception' everywhere.
If I'm working on an API that other users will use I may create specific exceptions to show what is going on in case they want to handle different exceptions in different ways.
If an error is severe enough to always exit the program, you may be better of throwing a RuntimeException instead. They are used to indicate unrecoverable errors and will avoid problems with putting "throws Exception" everywhere. You should have a handler for RuntimeExceptions anyway to provide a user-friendly error report in case they happen.
If you throw checked exceptions, they should be as specific as possible. Throwing and catching Exception can hide other exceptions that are thrown (including RuntimeExceptions) that you didn't intend and could have been handled differently. If you want to throw a general exception, you can always create your own exception class and throw that instead.
The exception handling can depend on the context so there's not one way to handle everything. If the user clicks a button to open a file and there's an error reading it, then it would be ok to throw an IOException up to the UI layer and display an error message there. On the other hand, an IOException while creating a temporary file could be handled lower down by retrying in another directory.

Catch Exception high in the call stack- when dealing with n tiers?

Say I have 3 tier app- frontend domain and data access. I have read that it is a good idea to catch exceptions high in the call stack...so if I get a data-access exception, the domain layer merely does a finally, like so
try{
}finally{
//cleans up
}
and lets the data-access exception percolate to the frontend layer. Does this not break layering by making the front-end layer deal with the innards ? I think that each layer should either handler or wrap and throw exception that it cannot handle to its calling layer...
any thoughts ?
Lots of good feedback so far, I'll give you my take.
Rule #1. ONLY catch exceptions you are going to actually handle. By handle, I mean handle in such a way that the client's request can continue. You may catch things long enough to log information (don't abuse this, usually the stack is enough information) or to convert to a different error that propagates easier (ala Runtime based). But, if you can't handle it, don't bother catching it. That's just extra code that is useless and confusing. Even when you log or convert, you end up rethrowing.
Realize that most of the time, you can NOT handle an exception. Truly. Many fail to grasp this. But the reality is, if you get an IOException reading or writing to the disk, game over. That request cannot be completed for the user. If your network is flaky and you can't talk to the database, same thing.
Rule #2. When you do get an exception that you cannot handle, the only thing you can do is try to fail in such a way that it is helpful to the user. This means, log it for later analysis (including original stack/cause), and then report something as helpful as possible to the user. Clean up whatever you must, so that the system remains in a consistent state.
Given that this communication with the end user happens at a very high level, that means you usually have to catch at that level. Most of the time, I find that there is very little value in any exception handling between it's inception point and the top level where you catch it for logging and reporting to the user. I often convert to a form of RuntimeException, but that's only done to ease propagation through the layers.
The biggest and most important thing is to realize that you usually can't handle exceptions, so any code you write for them should be as simple as possible.
I don't think layering is such a pure idea that this breaks it.
Wrapping and rethrowing doesn't add much value either.
What's wrong with having the service layer handle exceptions? That ought to be the end of the line, the last line of defense. This design lets the service log the exception - once and for all - and send a user friendly message to the UI for display.
You generally want to catch exceptions higher in the call stack, but only to the point that is makes sense. If the data level can handle and log the exception and just pass a message back to the front-end then that will keep things simple and more flexible.
Personally, if I need to have a try and a finally then I would like to also catch and do something about the situation there rather than pass it up to the caller. Just keep in mind there are always exceptions to good design rules (normally another rule like KISS).
There are three interlocking problems here.
First, constantly re-wrapping exceptions can be done but what value is it providing? You are just creating more layers around the original exception. I only wrap an exception when I can provide additional information about the exception or when the first exception causes another.
Second, the idea of an exception is to respond that a function can not be completed normally. You should catch the exception at the place where it makes the most sense to deal with the problem. If the code has "another alternative" the exception should be trapped at that point. Otherwise log it for the user or developer to work out.
Third, the try/finally block. These are useful when an exception would cause resources to hang out in a open or allocated state. I always use try/finally to clean up resources that might be left open (my favorite is the Statement/ResultSet from java.sql, a huge memory hog). A really good programmer has a lot of this in their code as a way to recover gracefully without creating huge memory leaks or resource constraints.

Where to handle fatal exceptions

I am considering a design where all fatal exceptions will be handled using a custom UncaughtExceptionHandler in a Swing application. This will include unanticipated RuntimeExceptions but also custom exceptions which are thrown when critical resources are unavailable or otherwise fail (e.g. a settings file not found, or a server communication error). The UncaughtExceptionHandler will do different things depending on the specific custom exception (and one thing for all the unanticipated), but in all cases the application will show the user an error message and exit. The alternative would be to keep the UncaughtExceptionHandler for all unanticipated exceptions, but handle all other fatal scenarios close to their origin.
Is the design I'm considering sound, or should I use the alternative? What is the typical approach used for handling fatal exceptions?
Usually, it is hard to find a good exception handling strategy. Every approach has its drawbacks. In particular, Yours is good in some sense (a centralized location for handling failures) but suffers from this flaw:
The exception handler you're describing will have special handling for each possible exception. Over time it will become a focal point of your application: every time you add new functionality you will also need to add exception-processing logic to your handler. This means that:
The handler is highly dependents on other parts, a change in impl. of some functionality is likely to trigger corresponding changes in the handler. You will need to be careful in keeping these two in sync.
The handler has poor coherency (has many reasons to change) - it contains the intersection of all features of your app.
Another problem is error recovery. After an exception is thrown (and a some notification is presented to the user), the user want to continue using the application. This means that if your code started modifying the internal data structures and then stopped due to exception, you will need to undo these modifications (or at least get the data structure back to a workable condition) before you allow additional interaction of the user. Achieving this requires a new thinking about the way your data is organized. One possible solution is to DB transactions. On the other hand, this kind of representation is more complicated than plain-old data structures so you need to weigh it against the needs of your app (is it a toy/prototype?)
I have successfully used a mix of local handling and a centralized handling in a large Swing application. The centralized handler only handled I think two or three specific types, and all uncaught exceptions. It's been a while so I don't remember all the details, but we ended up with a centralized handler that took care of two or three specific types of exceptions and all uncaught exceptions.
We used local handling where ever possible, but also defined something like ErrorMessageException that could be thrown also from background threads that did not interact with the UI. This exception had a specific handling in the central handler. We didn't think this is the most beautiful solution available, but it was simple and easy and worked well.
Any uncaught exceptions were handled as "general error" or something similar. Worked well, and of course we tried to release code that did not cause any unhandled exceptions. However, this was very helpful feature in testing.
With this approach the centralized handler was easy to maintain and did not grow unexpectedly. Also we did not see any symptoms of tight coupling, quite the opposite actually.
It would be more straight-forward to wrap the logic of the main method in an try catch block; e.g.
public static void main(String[] args) {
try {
// everything happens here
System.exit(0);
} catch (SpecificException ex) {
...
} catch (AnotherException ex) {
...
} catch (Throwable ex) {
// deal with anything else.
...
}
System.exit(1); // tell the world that we failed.
}
If you have a multithreaded application (like most Swing apps) you might want to consider sending the exceptions to a central exception-handling thread through some async queue.

Categories

Resources