0

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.

user1017413
  • 2,023
  • 4
  • 26
  • 41
  • You can, of course, have a just a few catch clauses at each point, catching only the appropriate superclasses, and then sort things (in a common routine, perhaps) out after you catch them. Or you can even catch Throwable, sort things out, then rethrow the exceptions you don't want to handle. Could even have the whole thing table-driven somehow, so that modification is simplified. – Hot Licks Oct 11 '13 at 01:08
  • The class of exception wouldn't mean much. I don't think there are more than a handful and, in most cases, it wouldn't really matter which was thrown. The operations that throw them should be specific enough that it's not a big deal. It's more about avoiding a ton of try/catch blocks all over the place. – user1017413 Oct 11 '13 at 03:38
  • I think a design might wrap each Callable with an object that reacts to exceptions. That is, you would run the tasks through an intermediary, which uses information about the stage of the process. But that's as far as I can read into it tonight. – clwhisk Oct 11 '13 at 04:58
  • Well, the try/catch blocks need to be as specific as your response. Since we don't know anything about your app we can't be more specific. – Hot Licks Oct 11 '13 at 11:59

0 Answers0