I have a design problem in a common utility that we use in our Java project where I want to ensure that all callers of a particular method A are wrapped by another method B. The general form of this code as I've written it today is:
x.B(new Runnable() {
y.A();
});
The runnable that is being executed by B can have arbitrary code, and may call A multiple times, so I can't get rid of the runnable in this code by adding the call to A directly into B. Also, A is third-party code, so we can't modify it. It's possible that the runnable could call B again with another nested call to A, but today that never happens so I am ok ignoring that case for now.
I see a few options:
A() throws BlahException
and make it so that B is the only catcher of that exception. This is ugly because there isn't any exception that should truly be thrown, but it's nice because the compiler would ensure the call hierarchy for me.Are there other options I haven't considered?
Have you considered using AspectJ, or some other aspect-oriented programming (AOP) tools? Then you could intercept every call of method A
, check for method B
in the stacktrace. If it's not there, you could throw exception preventing execution of A
, or write an error to log, or do whatever you like. Something like this:
@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();
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With