Custom AOP spring boot annotation with ribbon client blocking api call with return “1”

Tags: , , , ,



I have really poor experience with ribbon/eureka so forgive me if this is a stupid question:

I have two different microservice both connected to a discovery server, the first one calls the second using a custom annotation that sends a request using rest template. Custom annotation name is PreHasAuthority

Controller :

    @PreHasAuthority(value="[0].getProject()+'.requirements.update'")
    @PostMapping(CREATE_UPDATE_REQUIREMENT)
    public ResponseEntity<?> createUpdateRequirement(@Valid @RequestBody RequirementDTO requirementDTO
, HttpServletRequest request, HttpServletResponse response) {
        
        return requirementService.createUpdateRequirement(requirementDTO, request, response);
    }

Annotation interface :

import java.lang.annotation.*;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface PreHasAuthority {

    String value();
    
}

Annotation implementation:

import java.lang.reflect.Method;

import javax.servlet.http.HttpServletRequest;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.stereotype.Component;

import netcomgroup.eu.service.AuthenticationService;

@Aspect
@Component
public class PreHasAuthorityServiceAspect {

    @Autowired
    private AuthenticationService authenticationService;
    
    @Around(value = "@annotation(PreHasAuthority)")
    public void around(ProceedingJoinPoint joinPoint) throws Throwable {
        
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        PreHasAuthority preHasAuthority = method.getAnnotation(PreHasAuthority.class);
        
        Object[] args = joinPoint.getArgs();
        String permission = preHasAuthority.value();
        ExpressionParser elParser = new SpelExpressionParser();
        Expression expression = elParser.parseExpression(permission);
        String per = (String) expression.getValue(args);
        
        String token =null;
        for(Object o : args) {
            if(o instanceof HttpServletRequest) {
                HttpServletRequest request = (HttpServletRequest)o;
                token=request.getHeader("X-Auth");
                break;
            }
        }
        
        if(token==null) {
            throw new IllegalArgumentException("Token not found");
        }
        
        boolean hasPerm = authenticationService.checkPermission(per,token);
        
        if(!hasPerm) 
            throw new Exception("Not Authorized");
    }
}

My Ribbon configuration

import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RoundRobinRule;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;

public class RibbonConfiguration {

    @Autowired
    IClientConfig config;

    @Bean
    public IRule ribbonRule(IClientConfig config) {
        return new RoundRobinRule();
    }
}

Eureka config in application properties

#Eureka config
eureka.client.serviceUrl.defaultZone= http://${registry.host:localhost}:${registry.port:8761}/eureka/
eureka.client.healthcheck.enabled= true
eureka.instance.leaseRenewalIntervalInSeconds= 10
eureka.instance.leaseExpirationDurationInSeconds= 10

by calling the api from postman request is sendend correctly to the second microservice and i’m certain the return is “true”.

After that the request stops before entering the createUpdateRequirement method and returns ‘1’ as postman body response. No error of sort is provided.

My guess is that the problem resides within the custom annotation, cause when i remove the annotation the api call works perfectly, but i cannot understand the problem as it seems all setted up correctly to me.

Answer

Your @Around advice never calls joinPoint.proceed(). Hence, the intercepted target method will never be executed.

The second problem is that your advice method returns void, i.e. it will never match any method returning another type such as the ResponseEntity<?> createUpdateRequirement(..) method.

Besides, around is a reserved keyword in native AspectJ syntax. Even though it might work in annotation-driven syntax, you ought to rename your advice method to something else like aroundAdvice or interceptPreHasAuthority – whatever.

Please do read an AspectJ or Spring AOP tutorial, especially the Spring manual’s AOP chapter. 😉



Source: stackoverflow