3

I have made an annotation for aop. When I use it at any method rather than controller methods it works well. However when I use it at my controller's methods my controller stops working. It starts to give 404 not found error for mappings. I found a similar question here: Spring 3 MVC @Controller with AOP interceptors? but I don' know how to do it. My method at my controller is that:

@WebAuditable // This is my annotation that works at other methods
@Override
@RequestMapping(value = "/ad", method = RequestMethod.POST, headers = "Accept=application/json")
public
@ResponseBody
Cd create(HttpServletResponse response, @RequestBody Cd cd) {
    ...
}

My interface that my controller implements is that:

public interface BaseController<T> {

    public List<T> getAll(HttpServletResponse response);

    public T getByName(HttpServletResponse response, String id);

    public T create(HttpServletResponse response, T t);

    public T update(HttpServletResponse response, T t);

}

Any advices?

PS: @SeanPatrickFloyd says that:

Note When using controller interfaces (e.g. for AOP proxying), make sure to consistently put all your mapping annotations - such as @RequestMapping and @SessionAttributes - on the controller interface rather than on the implementation class

Community
  • 1
  • 1
kamaci
  • 72,915
  • 69
  • 228
  • 366

1 Answers1

4

The thing is: controller mapping is done at runtime, and if you use AOP proxies, the proxy objects don't have annotations at runtime, only their interfaces do. I can think of two possible strategies to work around this limitation.

Either annotate the generic interface methods, or (if you don't want to advise all controllers) create a sub-interface per implementation type, explicitly annotating their methods. I know that's a lot of rewritten code and contrary to what AOP is about, but I don't know a better way when sticking with interface based proxies.

Another way would be to switch to CGLib proxies using proxy-target-class="true". That way the proxy classes should (I'm not sure about this) retain the annotations.

Update: annotating your interface should work like this (if it works)

public interface BaseController<T> {

    @WebAuditable
    public List<T> getAll(HttpServletResponse response);

    @WebAuditable
    public T getByName(HttpServletResponse response, String id);

    @WebAuditable
    public T create(HttpServletResponse response, T t);

    @WebAuditable
    public T update(HttpServletResponse response, T t);

}

Annotating a base class won't work, because JDK proxies don't expose any information that's not backed by interfaces.

Sean Patrick Floyd
  • 292,901
  • 67
  • 465
  • 588
  • thanks for your help. How I will annotate generic methods, can you show me an example? There is a base controller interface that all my controllers implements it. (Actually there is an abstract class that implements BaseController but doesn't implement its create updatede delete methods, controllers implements them) So can I solve that problem with annotating my BaseController and how can I annotate it can show me from my question? – kamaci Nov 23 '11 at 12:36
  • I tried but didn't work annotation that interface. I couldn't find any way to do it. How about your second advice? – kamaci Nov 23 '11 at 14:39
  • @kamaci see [Proxying mechanisms](http://static.springsource.org/spring/docs/current/spring-framework-reference/html/aop.html#aop-proxying) – Sean Patrick Floyd Nov 23 '11 at 16:08