Using annotations to handle exceptions?

Let's say I have a method that throws an exception. The exception exclusion code is contained in a third-party library that accesses an external service. I have several classes that do a lot of work with external services, and there are a lot of exception handling to solve potential problems. The problem I'm facing is that I can have many exceptions, but I may only need to perform one of several actions, if any, and there are a ton of try / catch blocks superimposed on them. The type of exception may not even be relevant, otherwise different methods may throw an exception of the same type, but depending on the method that he chose, different actions must be taken.

What I'm looking for is an annotation that can supersede try / catch and just dictate the behavior to be taken when there is an exception in this method. I know that Spring ApsectJ can do such things, but at present I cannot easily add any new dependencies or modify pom to customize existing ones. Thus, I hope that this can be accomplished with a special annotation. For example:

@Catcher(action=SomeEnum.SOME_ACTION) public void doSomething(ServiceObj obj) throws SomeException { ExternalService.makeThingsHappen(obj); } 

I would suggest that a separate class will handle exceptions, of course. An additional difficulty is that I will also need ServiceObj. If makeThingsHappen () fails, I may need to take additional steps. The action variable will tell the handler class what to do with obj.

Can this be done without serious tragedy, or do I hope that it may not exist?

+8
java exception exception-handling try-catch annotations
source share
2 answers

It should be a low-level process, and this does not mean that we cannot have the same with the current level, but it may need a bunch of code and a little compromise the system. However, my suggestion will be like this (I hope I understood correctly), first define an interface for those who want to handle exceptions, something like this.

 interface ExceptionHandler{ void handleException(Throwable t); } 

then provide annotation for the user (API) to mark his methods, may cause some exceptions.

 @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.ANNOTATION_TYPE) @interface Catch{ public Class<? extends ExceptionHandler> targetCatchHandler(); public Class<? extends Throwable> targetException() default Exception.class; } @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) @interface CatchGroup{ public Catch[] catchers(); } 

Next, we need an interface to start calling a method that may throw an exception, something like this.

 interface Caller{ void callMethod()throws Throwable; } 

then you need a guy who cares and manages the thread of execution and calls a possible exception handler

 class MethodCaller{ /* * @param isntance: instance which implemented the Caller interface */ public static void callMethod(Caller instance) throws Exception { Method m = instance.getClass().getMethod("callMethod"); Annotation as[] = m.getAnnotations(); Catch[] li = null; for (Annotation a : as) { if (a.annotationType().equals(CatchGroup.class)) { li = ((CatchGroup) a).catchers(); } // for(Catch cx:li){cx.targetException().getName();} } try { instance.callMethod(); } catch (Throwable e) { Class<?> ec = e.getClass(); if (li == null) { return; } for (Catch cx : li) { if (cx.targetException().equals(ec)) { ExceptionHandler h = cx.targetCatchHandler().newInstance(); h.handleException(e); break; } } } } } 

and finally, let's have an example, it works very well for me, that's cool. exception handler.

 public class Bar implements ExceptionHandler{//the class who handles the exception @Override public void handleException(Throwable t) { System.out.println("Ta Ta"); System.out.println(t.getMessage()); } } 

and the calling method.

 class Foo implements Caller{//the class who calls the method @Override @CatchGroup(catchers={ @Catch(targetCatchHandler=Bar.class,targetException=ArithmeticException.class), @Catch(targetCatchHandler=Bar.class,targetException=NullPointerException.class)}) public void callMethod()throws Throwable { int a=0,b=10; System.out.println(b/a); } public static void main(String[] args) throws Exception { Foo foo=new Foo(); MethodCaller.callMethod(foo); } } 

as you see, the user must call methods with the callmethod() method, you also omit the Caller interface and use the annotation to declare more than one method in the class that it needs a bunch of additional codez. I hope I could do a little work.

+17
source share

Thanks for the help, everyone. I looked into Spring AOP, but ultimately decided against it. I ended up using try / catch blocks, but I created a handler that is injected into each class and completes any thrown exceptions in my own exception class, and then passes this to the handler in one line. This is a bit like user 2511414's suggestion that there is a dedicated handler, but I declined the annotations. I have a large number of try / catch blocks, but at least I saved most of the processing logic. A quick summary of my solution in case other people find this is a bit confusing, but you can still understand:

 public enum DoThisEnum { DO_THIS, DO_THAT, DO_OTHER_THING; } public class MyException extends Exception { private DoThisEnum doThis; private MyObject dataObj; //Constructor, overloaded to run super(originalException) or super() //as well as taking doThis and dataObj as parameters //Getters, setters, etc } public interface IExceptionHandler { void handleException(MyException exception); } 

Then we implement IExceptionHandler with a specific class that accepts MyException, reads additional data and performs actions on it. Then every block that can cause such an exception can be caught like this:

 ... try { doSomething(Object data); } catch (SomeException e) { handler.handleException(new MyException(e, DoThisEnum.DO_THAT, data)); //Anything else to do, maybe return or return null, rethrow, etc. } 

Now most of the nitty-gritty is encapsulated in a handler, and the try / catch blocks are minimal. The handler can register the stack trace of the source exception, possibly do other things based on it, and then perform its own actions based on the enumeration. This may not be the perfect solution, but it works pretty well here.

+2
source share

All Articles