Question

I want to create a wrapper that traps a particular exception and retries for all methods in a large (100+ methods) interface. I have the retry code working no worries, but I can't figure out how to hook up an implementation of the interface without cut'n'paste into all the methods.

I tried to use a missing method handler but that meant that I couldn't have it implement the interface. Abstract is obviously out as I won't be able to instantiate it.

I'm hoping for a better solution than creating the class as a template on the fly but I'm willing to do that.

Was it helpful?

Solution 2

I tried to use @dmahapatro's example but I kept getting IllegalArgumentException. I eventually realised that it only happened for mixin methods (the method shows the signature of the mixin). Instead of invoke() I needed to use doMethodInvoke() to get the appropriate type coersion.

errorProneInstance.metaClass.invokeMethod = { String name, args -> 
    def result

    def method = delegate.metaClass.getMetaMethod(name, args)

    while(true) {
        try {
            result = method.doMethodInvoke(delegate, args)

            break

        } catch (AnnoyingIntermittentButRetryableException e) {
            print "ignoring exception"
        }
    }

    result
}

OTHER TIPS

Have you tried overriding invokeMethod for the interface?

YourInterface.metaClass.invokeMethod = {String name, args ->
   def result
   println "Calling method $name"
   try{
      result = metaClass.getMetaMethod(name, args).invoke(delegate, args)
   }catch(YourException | AnyOtherException | Exception e){
       println "Handling exception for method $name"
       result = //Call retry code here
   }
   println "Called method $name"

   result
}

Overriding invokeMethod works as as interceptor for all the method calls in the interface. Handle the exception for each method and return the success result.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top