views:

355

answers:

2

I'm having a strange issue with annotated controllers and Spring MVC. I was trying to use Annotated controllers for the sample MVC application that Spring ships with its documentation. I used 2.5 version.

When I specify @RequestMapping at type level, I get "HTTP ERROR: 500 No adapter for handler [Controller class name]: Does your handler implement a supported interface like Controller?

If I include it in the method level, it works fine with out an issue. Adding or removing the default handle adapters to context files made no difference:

Finally, I resorted to having @RequestMapping at controller level, as well as one at the Method level, and it worked. Anyone know what could be the issue?

Here is the sample code:

This did not work:

@Controller
@RequestMapping("/*")
public class InventoryController {
    protected final Log logger = LogFactory.getLog(getClass());

    @Autowired
    private ProductManager productManager;


    public ModelAndView inventoryHandler() {
        String now = (new java.util.Date()).toString();
        logger.info("returning hello view with " + now);
        Map<String, Object> myModel = new HashMap<String, Object>();
        myModel.put("now", now);
        myModel.put("products", this.productManager.getProducts());
        return new ModelAndView("hello", "model", myModel);
    }
}

This worked:

@Controller

public class InventoryController {
    protected final Log logger = LogFactory.getLog(getClass());

    @Autowired
    private ProductManager productManager;

    @RequestMapping("/hello.htm")
    public ModelAndView inventoryHandler() {
        String now = (new java.util.Date()).toString();
        logger.info("returning hello view with " + now);
        Map<String, Object> myModel = new HashMap<String, Object>();
        myModel.put("now", now);
        myModel.put("products", this.productManager.getProducts());
        return new ModelAndView("hello", "model", myModel);
    }
}

This also worked:

@Controller
@RequestMapping("/*")
public class InventoryController {
    protected final Log logger = LogFactory.getLog(getClass());

    @Autowired
    private ProductManager productManager;

    @RequestMapping( method = RequestMethod.GET, value = "/hello.htm" )
    public ModelAndView inventoryHandler() {
        String now = (new java.util.Date()).toString();
        logger.info("returning hello view with " + now);
        Map<String, Object> myModel = new HashMap<String, Object>();
        myModel.put("now", now);
        myModel.put("products", this.productManager.getProducts());
        return new ModelAndView("hello", "model", myModel);
    }
}

Any ideas, what's happening here? I did a lot of search and no solution. I also tried with 2.5.6, and the issue was similar.

+5  A: 

You need to put @RequestMapping on the method because putting it on the class isn't enough information - Spring needs to know which method to call to handle the request.

If your class only has one method, then understandably you might think that it would pick that, but it doesn't.

Consider that one of the benefits of annotated controllers is that you can have as many @RequestMapping-annotated methods in your class as you want.

skaffman
Thank you. I was really going nuts over this. I followed the idea from this blog, wonder how it worked for the blog author:http://cchweblog.wordpress.com/2009/06/20/developing-spring-mvc-application-annotation-based-controller-and-jpa/EDIT: I understand the benefit part of having it under each method. In fact, it would be a good idea to put it even for a single method in class, who knows I may add more methods later on!
Shaw
He's got `@RequestMapping` on his methods too.
skaffman
Ah! Good catch.. I really missed that.. don't know how I overlooked..Thanks again!
Shaw
+1  A: 

This is beacuse the first configuration doesn't tell wich method of the class invoke.

rodrigoap