I\'m using spring 2.5 and annotations to configure my spring-mvc web context. Unfortunately, I am unable to get the following to work. I\'m not sure if this is a bug (seem
The true reason you need to use 'proxy-target-class="true"' is in DefaultAnnotationHandlerMapping#determineUrlsForHandler()
method: though it uses ListableBeanFactory#findAnnotationOnBean
for looking up a @RequestMapping
annotation (and this takes care about any proxy issues), the additional lookup for @Controller
annotation is done using AnnotationUtils#findAnnotation
(which does not handles proxy issues)
There's no doubt that annotations and inheritance can get a little tricky, but I think that should work. Try explicitly adding the AnnotationMethodHandlerAdapter to your servlet context.
http://static.springframework.org/spring/docs/2.5.x/reference/mvc.html#mvc-ann-setup
If that doesn't work, a little more information would be helpful. Specifically, are the two annotated controller methods from the interface? Is Foo supposed to be RegistrationController?
I know it is too late but i'm writing this for anyone have this problem if you are using annotation based configuration... the solution might be like this:
@Configuration
@ComponentScan("org.foo.controller.*")
@EnableAspectJAutoProxy(proxyTargetClass=true)
public class AppConfig { ...}
Ed is right, adding
<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"/>
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"/>
works fine
If you wish to use interfaces for your Spring MVC controllers then you need to move the annotations around a bit, as mentioned in the Spring docs: http://static.springsource.org/spring/docs/3.1.x/spring-framework-reference/html/mvc.html#mvc-ann-requestmapping
Using @RequestMapping On Interface Methods A common pitfall when working with annotated controller classes happens when applying functionality that requires creating a proxy for the controller object (e.g. @Transactional methods). Usually you will introduce an interface for the controller in order to use JDK dynamic proxies. To make this work you must move the @RequestMapping annotations to the interface as well as the mapping mechanism can only "see" the interface exposed by the proxy. Alternatively, you could activate proxy-target-class="true" in the configuration for the functionality applied to the controller (in our transaction scenario in ). Doing so indicates that CGLIB-based subclass proxies should be used instead of interface-based JDK proxies. For more information on various proxying mechanisms see Section 8.6, “Proxying mechanisms”.
Unfortunately it doesn't give a concrete example of this. I have found a setup like this works:
@Controller
@RequestMapping(value = "/secure/exhibitor")
public interface ExhibitorController {
@RequestMapping(value = "/{id}")
void exhibitor(@PathVariable("id") Long id);
}
@Controller
public class ExhibitorControllerImpl implements ExhibitorController {
@Secured({"ROLE_EXHIBITOR"})
@Transactional(readOnly = true)
@Override
public void exhibitor(final Long id) {
}
}
So what you have here is an interface that declares the @Controller, @PathVariable and @RequestMapping annotations (the Spring MVC annotations) and then you can either put your @Transactional or @Secured annotations for instance on the concrete class. It is only the @Controller type annotations that you need to put on the interface because of the way Spring does its mappings.
Note that you only need to do this if you use an interface. You don't necessarily need to do it if you are happy with CGLib proxies, but if for some reason you want to use JDK dynamic proxies, this might be the way to go.
What I needed to do was replace
<tx:annotation-driven/>
with
<tx:annotation-driven proxy-target-class="true"/>
This forces aspectj to use CGLIB for doing aspects instead of dynamic proxies - CGLIB doesn't lose the annotation since it extends the class, whereas dynamic proxies just expose the implemented interface.