Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring-MVC Problem using @Controller on controller implementing an interface

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?

like image 640
layne Avatar asked Sep 30 '08 17:09

layne


People also ask

Can a controller implement an interface?

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.

Can we replace @controller with @RestController?

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.

What happens when a class is annotated with the @controller annotation?

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.

Can we use @controller instead of @service?

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.


1 Answers

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.

like image 157
James Kingsbery Avatar answered Sep 29 '22 15:09

James Kingsbery