0

I recently added AOP with aspectJ and spring-aop to my existent spring project. The goal was to actually intercept controller calls to modify the response they send back, in order to bind some values to this response I didn't want to add manually to each and everyone of my controllers, for example the expiration date of the actual token used by the end-user (which I wasn't even able to showcase within my controller in any case). I actually managed to get it working until I started my unit tests :

In my unit tests I call directly my controller methods using Reflection feature from java, then replicate usual process (calling the filter chain, pre handler and post handlers, and the controller method itself which is first manually validated using spring validator when annotation @Valid is present on one of my parameters. All this process works fine and gets executed properly). The problem is that now that the controller method is intercepted by spring-aop, it's mentionned as coming from the proxy controller created, and all of my parameters annotations disapear. Here is a controller example :

@Override
public ResponseEntity<Object> editPassword(@Valid @RequestBody PasswordEditForm passwordEditForm, HttpServletRequest request) {
    return factorizedUserBaseController.editPassword(passwordEditForm, request, User.class);
}

the parameter PasswordEditForm has the annotation @Valid so in my test cases it was first validated before any other step, but now as I double checked it, the @Valid annotation is not present on the proxy method, and therefore the parameter doesn't get validated, any clue for how to fix this and make my parameters annotation still understandable from my test point of view?

Note : when running the spring through mvn spring-boot:run, parameters with @Valid annotation gets correctly validated and then goes to my error handler method properly.

Louis-wht
  • 535
  • 5
  • 17

1 Answers1

0

Problem Solved : from several other stackoverflow posts I understand that CGLIB (aop proxy lib used by Spring) doesn't support annotations. ( see Retain annotations on CGLIB proxies?). But my problem wasn't here, I was literally sure I was finding the method using the controller class itself (the one I coded) but what I was wrong about is that I was giving the controller instance as a parameter to some other parts of my code which in turn would use this controller class to find the method which of course wasn't working because thanks to Spring proxies, it wasn't anymore my controller itself but a proxy class extending my own controller class. Instead, I just had to replace :

    Class<?> controllerClass = controllerInstanciationContainer
            .getController()
            .getClass();

with

    Class<?> controllerClass = controllerInstanciationContainer
            .getController()
            .getClass()
            .getSuperclass();
Louis-wht
  • 535
  • 5
  • 17
  • I advise you to go all-in and use AspectJ instead of Spring AOP. Spring AOP with it's proxy-based solution is much less capable than the direct bytecode manipulating AspectJ. – Nándor Előd Fekete Sep 30 '17 at 23:27
  • I didn't knew it was even possible to use Spring with all-in AspectJ ! I thought it wasn't possible and that was why Spring developed it's spring-aop lib. Thanks for your comment, I'll take a look at this possibility because looking down the stacktraces I was quite impressed how many steps they were for this little piece of bytecode to be executed... – Louis-wht Oct 05 '17 at 09:30