Spring 4 AOP @Aspect isn't triggering for @RestController

Nephthys76 picture Nephthys76 · Aug 24, 2015 · Viewed 8.2k times · Source

I have created an Aspect which performs a basic id comparison to ensure that a user belongs to a the same group that created the entity being requested. I have had success attaching my aspect to @Service methods, but it doesn't make sense on the service layer, and I need it to be attached to @RestController methods instead. When I attempt to do this, everything seems good, but my Aspect never triggers, and the logs are silent.

pom.xml

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-aop</artifactId>
    <version>4.1.7.RELEASE</version>
</dependency>

spring context

<context:annotation-config/>
<context:component-scan base-package="my.pkg"/>
<aop:aspectj-autoproxy/>
<aop:config proxy-target-class="true"/>

Aspect

@Aspect
@Component
public class MyAspect {
    @Pointcut("within(@org.springframework.stereotype.Controller *)")
    public void controller() {}

@Pointcut("within(@org.springframework.web.bind.annotation.RestController *)")
    public void restController() {}

    @Pointcut("args(java.security.Principal,..)")
    public void principalArgPointcut() {}

    @Around("(controller() || restController()) && principalArgPointcut()")
    public Object validate(ProceedingJoinPoint point) throws Throwable {
        doValidationBefore();
        Object result = point.proceed();
        doValidationAfter();

        return result;
    }
}

where "doValidationBefore()" and "doValidationAfter()" will throw an exception if validation fails.

And finally, my RestController

@RestController
@RequestMapping("/my-path")
public class MyController {
    @RequestMapping(value = "/{entityId}", method = RequestMethod.GET)
    public @ResponseBody
    ResponseEntity<MyEntity> getEntityDetails(Principal principal, @PathVariable("entityId") Long entityId) {
        return new ResponseEntity(HttpStatus.OK);
    }
}

Some things to note:

  • This exact aspect works when I change the execution pattern to match services and place it in my service package.
  • The Aspect and the RestController are in the same context
  • I use IDEA IDE, and when I use the "navigate to advised methods" icon on the Aspect, the method I'm testing IS listed in the list of methods.
  • None of the methods listed in "navigate to advised methods" are working

Things I have tried:

  • I added 3 libraries to my pom.xml: org.aspectj:aspectjrt:1.8.6, org.aspectj:aspectjtools:1.8.6, cglib:cglib:2.2.2. None of these made any difference.
  • I tried defining my Aspect and PointCuts directly in the context xml and removing the annotations, no difference.
  • I have tried setting my execution pattern to apply to ALL methods, and it still did not trigger.
  • I tried adding an interface for my RestController, no change.

I would love some help here, as I've been trying to solve this for quite some time now. I know it must be possible.

Answer

Nephthys76 picture Nephthys76 · Aug 24, 2015

As it turns out, my Aspect and my Controllers were NOT, in fact, in the same context.

While I believed my Controllers to be included in the context scanning of my web-context.xml, they were actually being scanned in WEB-INF/servlet-context.xml

Once I moved my Aspect configuration to WEB-INF/servlet-context.xml, my Aspect began to trigger as expected.

Thanks for all those who contemplated my problem.