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 (seems like it) or if there is a basic misunderstanding on how the annotations and interface implementation subclassing works.
For example,
@Controller
@RequestMapping("url-mapping-here")
public class Foo {
@RequestMapping(method=RequestMethod.GET)
public void showForm() {
...
}
@RequestMapping(method=RequestMethod.POST)
public String processForm() {
...
}
}
works fine. When the context starts up, the urls this handler deals with are discovered, and everything works great.
This however does not:
@Controller
@RequestMapping("url-mapping-here")
public class Foo implements Bar {
@RequestMapping(method=RequestMethod.GET)
public void showForm() {
...
}
@RequestMapping(method=RequestMethod.POST)
public String processForm() {
...
}
}
When I try to pull up the url, I get the following nasty stack trace:
javax.servlet.ServletException: No adapter for handler [com.shaneleopard.web.controller.RegistrationController@e973e3]: Does your handler implement a supported interface like Controller?
org.springframework.web.servlet.DispatcherServlet.getHandlerAdapter(DispatcherServlet.java:1091)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:874)
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:809)
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:571)
org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:501)
javax.servlet.http.HttpServlet.service(HttpServlet.java:627)
However, if I change Bar to be an abstract superclass and have Foo extend it, then it works again.
@Controller
@RequestMapping("url-mapping-here")
public class Foo extends Bar {
@RequestMapping(method=RequestMethod.GET)
public void showForm() {
...
}
@RequestMapping(method=RequestMethod.POST)
public String processForm() {
...
}
}
This seems like a bug. The @Controller annotation should be sufficient to mark this as a controller, and I should be able to implement one or more interfaces in my controller without having to do anything else. Any ideas?
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.