This Banner is For Sale !!
Get your ad here for a week in 20$ only and get upto 15k traffic Daily!!!

AspectJ + Gradle – Retry Java Method on exception




What’s AOP?

AOP – Facet Oriented Programming is a programming sample that permits the modularization of frequent cross-cutting use circumstances. This may be performed by including behaviour to present code with out the necessity to modify the code itself. This enables behaviours (retrying a technique) that aren’t a part of the enterprise logic to be added to a program with out cluttering the code core to the performance.



What’s AspectJ?

AspectJ is an aspect-oriented programming extension created at PARC for the java programming language. AspectJ is an open-source mission within the Eclipse Basis and has grow to be a extensively used normal for AOP. Extra on AspectJ – here



What’s a Be a part of Level?

A be a part of level is a degree within the management circulation of a program. Be a part of factors are effectively outlined moments within the execution of a program like a technique name, an object instantiation or variable entry.



What’s a Pointcut?

Pointcut permits the programmer to specify the purpose the place his facet code is to be executed. With level cuts we will specify be a part of factors. We give an expression to some extent lower to find out whether or not a given be a part of level matches.



What’s an Recommendation?

Advices enable a programmer to specify code that may be run at any be a part of level which matches a given pointcut. The code might be run earlier than, after, or round a matched be a part of level.

Now let’s dive right into a fundamental instance on the best way to create a customized annotation to retry a technique on a given exception utilizing AspectJ. I am right here assuming that you understand how to put in and create a Gradle mission. If not, Gradle has actually good documentation on the best way to get began. click here

Right here is my mission construction:

Project Structure

Add the next two dependencies to our Gradle mission within the construct.gradle file:
implementation 'org.aspectj:aspectjrt:1.9.8' &
implementation 'org.aspectj:aspectjweaver:1.9.8'

As I discussed earlier we will outline an recommendation to run a particular code at a be a part of level. However how does it work? We use a plugin in Gradle that does post-compile-weaving. Weaving is a course of during which the AspectJ weaver takes class recordsdata and enter and produces class recordsdata as output. The produced output class recordsdata can have a modified code that features the recommendation injected at be a part of factors that are matched by the pointcut. here

Add the AspectJ Gradle plugin id "io.freefair.aspectj.post-compile-weaving" model "6.4.1" to your construct.gradle file. For extra particulars on the plugin verify the next hyperlinks:
Gradle plugin
Post compile weaving

Let’s write our retry annotation:

@Goal(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface RetryMethod {

    public int retries() default 5;
    public int interval() default 2;
    public int backoff() default 1;

}
Enter fullscreen mode

Exit fullscreen mode

@Goal(ElementType.METHOD) tells that the annotation is for strategies.
@Retention(RetentionPolicy.RUNTIME) tells that the annotation is to be recorded within the class file by the compiler and retained by the VM at run time, so they might be learn reflectively.

I am taking the variety of retries, time interval between every retry and the backoff fee with every failure as parameters with the annotation. This manner the annotation might be configured for every methodology that we have to retry.

Now let’s outline our facet with a pointcut and the recommendation:

@Facet
public class RetryMethodAspect {

    public static last Logger log = LoggerFactory.getLogger(RetryMethodAspect.class);

    @Pointcut("@annotation(RetryMethod) && execution(* *(..))")
    public void retriableMethod() {

    }

    @Round("retriableMethod()")
    public Object retryMethodAdvice(ProceedingJoinPoint joinPoint) throws Throwable {

        log.information("Recommendation referred to as for annotation RetryMethod");
        log.information(joinPoint.toString());

        String methodName = ((MethodSignature) joinPoint.getSignature()).getName();
        int retries = ((MethodSignature) joinPoint.getSignature()).getMethod().getAnnotation(RetryMethod.class).retries();
        int interval = ((MethodSignature) joinPoint.getSignature()).getMethod().getAnnotation(RetryMethod.class).interval();
        int backoff = ((MethodSignature) joinPoint.getSignature()).getMethod().getAnnotation(RetryMethod.class).backoff();

        int delay = interval;
        int makes an attempt = 0;

        Object proceed;
        whereas(makes an attempt < retries) {
            log.information("{} try - {}",methodName,makes an attempt);
            makes an attempt++;
            strive {
                proceed = joinPoint.proceed();
                return proceed;
            }
            catch (Exception exception) {
                log.information("Exception at try - {}",attempts-1);
                if(makes an attempt >= retries) {
                    log.information("Max retry makes an attempt reached. Throwing exception.");
                    throw exception;
                }
                if(exception.getClass() == BadRequestException.class) {
                    if(exception.getMessage() != null && exception.getMessage().incorporates("Dangerous Request Obtained")) {
                        log.information("Sleeping {} seconds earlier than retry.",delay);
                        TimeUnit.SECONDS.sleep(delay);
                        delay = delay * backoff;
                    }
                }
                else {
                    throw exception;
                }
            }
        }
        throw new Exception("Failure executing methodology."); //ideally we by no means attain this line
    }

}
Enter fullscreen mode

Exit fullscreen mode

As you may see from the above code, it has a pointcut and recommendation. The pointcut has an expression that defines the be a part of level. Right here we gave it as @annotation(RetryMethod) && execution(* *(..)). This expression matches a be a part of level the place there may be an annotation @annotation(RetryMethod) and the execution(* *(..)) tells that the recommendation must be referred to as on the execution time of the tactic which is annotated with @annotation(RetryMethod).

@Round("retriableMethod()") tells that the recommendation is executed across the joint level that matched the pointcut expression.

The purpose within the code the place we name proceed = joinPoint.proceed(); is the place the place the precise methodology which is annotated is executed.

Let’s write an instance class that has a easy methodology that returns an integer with our retry annotation.

public class Instance {

    public static int rely = 0;

    @RetryMethod(
            retries = 5,
            interval = 2
    )
    public int retryMethod(String take a look at) throws BadRequestException, Exception {

        if(take a look at == "retry") {
            if(rely < 3) {
                rely++;
                throw new BadRequestException("Dangerous Request Obtained");
            }
            return 0;
        }
        else if(take a look at == "fail"){
            throw new Exception("Did not execute methodology");
        }
        return 0;
    }

}
Enter fullscreen mode

Exit fullscreen mode

Right here I wrote the retryMethod to soak up a string worth "retry" and throw an exception 3 instances for demo functions. Our goal right here is to retry the tactic when the tactic throws a BadRequestException with the message "Dangerous Request Obtained". When you’ve got already seen, we will additionally go the exception message as a parameter to the annotation and verify for the message in exception earlier than retrying our methodology.

Now let’s write a easy App.java with the primary methodology to name our retryMethod.

public class App {

    public static last Logger log = LoggerFactory.getLogger(App.class);

    public static void most important(String[] args) {
        strive {
            log.information("Calling retriable methodology");
            Instance instance = new Instance();
            int end result = instance.retryMethod("retry");
//            int end result = instance.retryMethod("fail");
//            int end result = instance.retryMethod("go");
            log.information("Printing end result - {}",end result);
        } catch (BadRequestException e) {
            e.printStackTrace();
        } catch (Exception exception) {
            exception.printStackTrace();
        }
    }

}
Enter fullscreen mode

Exit fullscreen mode

Now let’s run our most important methodology in App.java and verify whether or not our retry facet is working.

[main] INFO App - Calling retriable methodology
[main] INFO facet.RetryMethodAspect - Recommendation referred to as for annotation RetryMethod
[main] INFO facet.RetryMethodAspect - execution(int Instance.retryMethod(String))
[main] INFO facet.RetryMethodAspect - retryMethod try - 0
[main] INFO facet.RetryMethodAspect - Exception at try - 0
[main] INFO facet.RetryMethodAspect - Sleeping 2 seconds earlier than retry.
[main] INFO facet.RetryMethodAspect - retryMethod try - 1
[main] INFO facet.RetryMethodAspect - Exception at try - 1
[main] INFO facet.RetryMethodAspect - Sleeping 2 seconds earlier than retry.
[main] INFO facet.RetryMethodAspect - retryMethod try - 2
[main] INFO facet.RetryMethodAspect - Exception at try - 2
[main] INFO facet.RetryMethodAspect - Sleeping 2 seconds earlier than retry.
[main] INFO facet.RetryMethodAspect - retryMethod try - 3
[main] INFO App - Printing end result - 0

Course of completed with exit code 0
Enter fullscreen mode

Exit fullscreen mode

As you may see from the above logs our annotation labored. We’re retrying our methodology when the exception is BadRequestException and the message is "Dangerous Request Obtained". Now let’s strive a failure situation. Change the code having rely < 3 to rely < 7 and run the code. Since we talked about that retries = 5, the code ought to throw an exception after 5 makes an attempt.

[main] INFO App - Calling retriable methodology
[main] INFO facet.RetryMethodAspect - Recommendation referred to as for annotation RetryMethod
[main] INFO facet.RetryMethodAspect - execution(int Instance.retryMethod(String))
[main] INFO facet.RetryMethodAspect - retryMethod try - 0
[main] INFO facet.RetryMethodAspect - Exception at try - 0
[main] INFO facet.RetryMethodAspect - Sleeping 2 seconds earlier than retry.
[main] INFO facet.RetryMethodAspect - retryMethod try - 1
[main] INFO facet.RetryMethodAspect - Exception at try - 1
[main] INFO facet.RetryMethodAspect - Sleeping 2 seconds earlier than retry.
[main] INFO facet.RetryMethodAspect - retryMethod try - 2
[main] INFO facet.RetryMethodAspect - Exception at try - 2
[main] INFO facet.RetryMethodAspect - Sleeping 2 seconds earlier than retry.
[main] INFO facet.RetryMethodAspect - retryMethod try - 3
[main] INFO facet.RetryMethodAspect - Exception at try - 3
[main] INFO facet.RetryMethodAspect - Sleeping 2 seconds earlier than retry.
[main] INFO facet.RetryMethodAspect - retryMethod try - 4
[main] INFO facet.RetryMethodAspect - Exception at try - 4
[main] INFO facet.RetryMethodAspect - Max retry makes an attempt reached. Throwing exception.
exception.BadRequestException: Dangerous Request Obtained
    at Instance.retryMethod_aroundBody0(Instance.java:17)
    at Instance.retryMethod_aroundBody1$recommendation(Instance.java:43)
    at Instance.retryMethod(Instance.java:1)
    at App.most important(App.java:14)
Enter fullscreen mode

Exit fullscreen mode

As you may see that it threw an exception after retrying 5 instances.

Hyperlink to Code: click here

If you happen to made it this far, please present your help with reactions and do not hesitate to ask questions inside feedback, I would like to reply every one in every of them and know your ideas about this weblog. Simply FYI, That is my first weblog ever :).

The Article was Inspired from tech community site.
Contact us if this is inspired from your article and we will give you credit for it for serving the community.

This Banner is For Sale !!
Get your ad here for a week in 20$ only and get upto 10k Tech related traffic daily !!!

Leave a Reply

Your email address will not be published. Required fields are marked *

Want to Contribute to us or want to have 15k+ Audience read your Article ? Or Just want to make a strong Backlink?