Well, the easiest and straight forward solution would be tu use plain java try catchs, not that flexible, but often useful enough as error handling strategies does not change that often. Those exceptions you can not catch are declared on the method to may be thrown, and may be handled by your Object B If you wanna be more flexible. Create an interface for your service A with all the possible exceptions declared.
Implement that interface with logic but without any error handling. Then you could create ErrorStrategy objects that implement the interface as well and delegate incoming calls to another implementation of that interface, BUT and this is the interesting part append some error handling strategy for one or more particular exceptions. Here is an example to make it more understandable public interface A { void someMethod() throws IOException, MalformedURLException; } class AImpl implements A { @Override public void someMethod() throws IOException, MalformedURLException { // here goes your business logic } } class ErrorHandlerOne implements A { @Override public void someMethod() throws IOException { try { delegate.someMethod(); } catch (MalformedURLException e) { // handle the exception } } } If you wanna be even more flexible, I would recommend to use AOP mechanisms instead of the simple delegation chain, that way you can easily plug-in and exchange your error handling strategies.
If you use Spring and your Service A is a Spring-Bean you could easily use Springs build in AOP support. In that case the after throwing advice is what you looking for After throwing advice: Advice to be executed if a method exits by throwing an exception import org.aspectj.lang.annotation. Aspect; import org.aspectj.lang.annotation.
AfterThrowing; @Aspect public class AfterThrowingExample { @AfterThrowing( pointcut="com.xyz.myapp.A.someOperation()" throwing="ex") public void doRecoveryActions(IOException ex) { // ... } }.
Well, the easiest and straight forward solution would be tu use plain java try catchs, not that flexible, but often useful enough as error handling strategies does not change that often. Those exceptions you can not catch are declared on the method to may be thrown, and may be handled by your Object B. If you wanna be more flexible.
Create an interface for your service A with all the possible exceptions declared. Implement that interface with logic but without any error handling. Then you could create ErrorStrategy objects that implement the interface as well and delegate incoming calls to another implementation of that interface, BUT and this is the interesting part append some error handling strategy for one or more particular exceptions.
Here is an example to make it more understandable. Public interface A { void someMethod() throws IOException, MalformedURLException; } class AImpl implements A { @Override public void someMethod() throws IOException, MalformedURLException { // here goes your business logic } } class ErrorHandlerOne implements A { @Override public void someMethod() throws IOException { try { delegate.someMethod(); } catch (MalformedURLException e) { // handle the exception } } } If you wanna be even more flexible, I would recommend to use AOP mechanisms instead of the simple delegation chain, that way you can easily plug-in and exchange your error handling strategies. If you use Spring and your Service A is a Spring-Bean you could easily use Springs build in AOP support.In that case the after throwing advice is what you looking for.
After throwing advice: Advice to be executed if a method exits by throwing an exception. Import org.aspectj.lang.annotation. Aspect; import org.aspectj.lang.annotation.
AfterThrowing; @Aspect public class AfterThrowingExample { @AfterThrowing( pointcut="com.xyz.myapp.A.someOperation()" throwing="ex") public void doRecoveryActions(IOException ex) { // ... } }.
Thank you nils. In fact being able to plug in and exchange the strategies is my core point. Background the the taks of the service depends on external resources and as such can throw a quite a variety of different exceptions.
Since I don't assume that I know all of these at design time and will come up with new exceptions later, I would like to be able to inject the error handling via my IoC Container (Spring in this case) – er4z0r Feb 10 '10 at 11:36 When you say that you don't know all the exceptions, that means we are talking about RuntimeExceptions, right. That way you don't need to define them on the interfaces anyway. If you are using Spring everything becomes even more easy :-) If your service A is a Spring Bean, I would totally suggest to use Springs AOP mechanisms to plug-in error handlers.
Full flexible, easy to configure and prbly. In line with your application/framework. – Nils Schmidt Feb 10 '10 at 13:02 That sounds well.
I'll have a look at it. – er4z0r Feb 10 '10 at 14:55.
Try Observer pattern. In general, your ServiceA should have methods like addFirstTypeExceptionsListener (ServiceListener l) addSecondTypeExceptionsListener (ServiceListener l) or addExceptionListener (ServiceListener l, ExceptionTypeEnum type). Your ServiceB then should implement ServiceListener interface which will probably have method like handleException (Exception e); If we abstract away from your question then it's a bad practice to use exceptions for flow control.
– er4z0r Feb 10 '10 at 10:57 Yes. Look also at Nils Schmidt approach based on decorator pattern.My approach gives your lower coupling but it's a matter of taste what to use in your situation. – Roman Feb 10 '10 at 11:05.
Keep it simple and use plain exceptions. They are already meant to implement different error handling strategies: you can catch different exception and act accordingly. You can implement your own error handling scheme as long as exceptions remain, well, exceptional.
Otherwise if it's really control flow, you should think about it differently. Here is one in pseudo-code: CannotDownloadException. When the download is realy not possible.
Fatal error. RetryDownlaodException. When the download is momentary not possible.
Can implement retry logic. The names are not so good, but it illustrates the principle. Class ServiceB { private serviceA serviceA; public download( URL url ) throws CannotDownloadException { try { serviceA.
Download( url ); } catch( RetryDownloadException ex ) { // you could have here something more elaborated that would // perform a retry strategy based on a configuration (e.g. The number of retry, // or the interval between retry) try { sleep( 10 sec ); serviceA. Download( url ); } catch( RetryDownloadException ex ) { throw new CannotDownloadException(); } } } } class ServiceA { public download( URL url ) throws DownloadException { try { if(! url.isValid() ) throws new CannotDownloadException(); serviceA. Download( url ); } catch( ConnectionException ex ) { throw new RetryDownloadException(); } } }.
O.K. Forgot to mention another constraint: The tasks performed by ServiceA are asynchronous by nature. That means simply doing a serviceA. Download(URL url) and catching the exceptions won't work since that would mean that the call to needs to be a blocking call, which I can not afford.
– er4z0r Feb 10 '10 at 11:44 Hmm...That can still be adapted for asynchronous scenario. Instead of a blocking call you have two callbacks onSuccess, and onError. In onError you can select and implement a retry logic.
The point is that you can use Exception to define the class or errors that you can handle -- that's their initial purpose. The exact error handling logic for each class can be selected dynamically. – ewernli Feb 10 '10 at 11:49 Yeah that is more like it.
Currntly I have a Callback interface with exactlly those methods where each of the methods is passed the task that failed/succeeded and the onError also an Exception which caused the failure. This Interface is implemented by ServiceA as well as ServiceB so ServiceA can delegate every exception it cannot handle alone. My problem is now how to implement the internal lookup of Exception ExceptionHandlerStrategy.
– er4z0r Feb 10 '10 at 11:54 Why don't you simply map one strategy to each exception type? – ewernli Feb 10 '10 at 11:57 That was the plan. Using a HashMap.
I just wanted to hear if there is a well known solution for this. – er4z0r Feb 10 '10 at 12:01.
I cant really gove you an answer,but what I can give you is a way to a solution, that is you have to find the anglde that you relate to or peaks your interest. A good paper is one that people get drawn into because it reaches them ln some way.As for me WW11 to me, I think of the holocaust and the effect it had on the survivors, their families and those who stood by and did nothing until it was too late.