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?
If Controllers need to be aware of specific environment references, they can choose to implement specific awareness interfaces, just like any other bean in a Spring (web) application context can do, for example: org. springframework.
In simple words, @RestController is @Controller + @ResponseBody. So if you are using latest spring version you can directly replace @Controller with @RestController without any issue.
The @Controller annotation indicates that a particular class serves the role of a controller. There is no need to extend any controller base class or reference the Servlet API.
No, @Controller is not the same as @Service , although they both are specializations of @Component , making them both candidates for discovery by classpath scanning. The @Service annotation is used in your service layer, and @Controller is for Spring MVC controllers in your presentation layer.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With