Providing one stack of method calls always includes another method in Java

I have a design problem in the general utility that we use in our Java project, where I want to make sure that all the calling elements of a certain method A are wrapped in another method B. The general form of this code, as I wrote it today:

xB(new Runnable() { yA(); }); 

The launch performed by B can have arbitrary code and can call A several times, so I can not get rid of runnable in this code by adding the call A directly to B. Also, A is third-party code, so we cannot modify it. It is possible that runnable can again call B with another call to A nested, but this never happens today, so I normally ignore this case for now.

I see several options:

  • Declare A() throws BlahException and make B the only node of this exception. This is ugly because there is no exception that really needs to be thrown, but it is good because the compiler would provide a hierarchy of calls for me.
  • Write some kind of static analysis tool to provide this rule for me. I have not investigated this case yet, because it sounds like more work than anything else (but maybe there is already an existing tool that can do this?).
  • Add the statement to "start A" (indeed, this code would have to work in the custom version of Runnble, since I cannot directly change A), which we run inside call B. This can either use some additional local thread / object state -local or traverse the call stack itself, both of which are pretty ugly.

Are there any other options that I have not considered?

+5
source share
1 answer

Do you consider using AspectJ or any other AOP tool? Then you can intercept every call to method A , check method B in stacktrace. If this is not the case, you can throw an exception that excludes the execution of A , or write an error to register or do whatever you like. Something like that:

 @Aspect public class CheckInsideMethodBAspect { @Around("execution(* com.example.AClass.A(..))") public void checkNestedMethod(ProceedingJoinPoint joinPoint) { // checking for method B in the call stack boolean isInsideB = false; StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace(); for (StackTraceElement element: stackTraceElements) { if (element.getClassName().equals("ClassB") && element.getMethodName().equals("B")) { isInsideB = true; break; } } // if not inside B, throwing exception if (!isInsideB) { throw new NotInsideBException(); } // if inside B, then proceeding with method A execution joinPoint.proceed(); } } 
+2
source

All Articles