Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How configure a RESTful controller in Spring 3 with annotations?

I am trying to create a RESTful controller using Spring 3.0. The controller is for a management API for a portal application. The operations I want to perform are:

  • GET /api/portals to list all the portals
  • POST /api/portals to create a new portal
  • GET /api/portals/{id} to retrieve an existing portal
  • PUT /api/portals/{id} to update an existing portal
  • DELETE /api/portal/{id} to delete an existing portal

After annotating the controller as illustrated below I find the the operations to list all the portals or create a new portal do not get mapped.

So my questions are:

  • Have I annotated the class correctly?
  • Am I following the correct conventions for implementing a RESTful web service?
  • Might there be something broken in Spring?

The code extract below shows how I have annotated my class:

@Controller
@RequestMapping("/api/portals")
public final class PortalAPIController
{
    private final static Logger LOGGER = LoggerFactory.getLogger(PortalAPIController.class);

    @RequestMapping(value = "/", method = RequestMethod.GET)
    public String listPortals(final Model model)
    {
         PortalAPIController.LOGGER.debug("Portal API: listPortals()");
         .
         .
         return "portals";
    }

    @RequestMapping(value = "/", method = RequestMethod.POST)
    public String createPortal(@RequestBody final MultiValueMap<String, String> portalData, final Model model)
    {
        PortalAPIController.LOGGER.debug("Portal API: createPortal()");
        .
        .
        return "portal";
    }

    @RequestMapping(value = "/{id}", method = RequestMethod.GET)
    public String getPortal(@PathVariable("id") final String portalId, final Model model, final HttpServletResponse response)
        throws IOException
    {
        PortalAPIController.LOGGER.debug("Portal API: getPortal()");
        .
        .
        return "portal";
    }

    @RequestMapping(value = "/{id}", method = RequestMethod.PUT)
    public String updatePortal(@PathVariable("id") final String portalId,
        @RequestBody final MultiValueMap<String, String> portalData, final Model model, final HttpServletResponse response)
        throws IOException
    {
        PortalAPIController.LOGGER.debug("Portal API: updatePortal()");
        .
        .
        return "portal";
    }

    @RequestMapping(value = "/{id}", method = RequestMethod.DELETE)
    public String deletePortal(@PathVariable("id") final String portalId, final Model model, final HttpServletResponse response)
        throws IOException
    {
        PortalAPIController.LOGGER.debug("Portal API: deletePortal()");
        .
        .
        return "portal";
    }

    .
    .
}

During start-up I am seeing that Spring things it has registered the end-points:

2010-02-19 01:18:41,733 INFO [org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping] - Mapped URL path [/api/portals/] onto handler [com.btmatthews.mars.portal.web.controller.PortalAPIController@141717f]
2010-02-19 01:18:41,734 INFO [org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping] - Mapped URL path [/api/portals/{id}] onto handler [com.btmatthews.mars.portal.web.controller.PortalAPIController@141717f]
2010-02-19 01:18:41,734 INFO [org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping] - Mapped URL path [/api/portals/{id}.*] onto handler [com.btmatthews.mars.portal.web.controller.PortalAPIController@141717f]
2010-02-19 01:18:41,735 INFO [org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping] - Mapped URL path [/api/portals/{id}/] onto handler [com.btmatthews.mars.portal.web.controller.PortalAPIController@141717f]
2010-02-19 01:18:41,735 INFO [org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping] - Mapped URL path [/api/portals] onto handler [com.btmatthews.mars.portal.web.controller.PortalAPIController@141717f]
2010-02-19 01:18:41,735 INFO [org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping] - Mapped URL path [/api/portals.*] onto handler [com.btmatthews.mars.portal.web.controller.PortalAPIController@141717f]

But when I try to invoke my API using cURL

curl http://localhost:8080/com.btmatthews.minerva.portal/api/portals/

or

curl http://localhost:8080/com.btmatthews.minerva.portal/api/portals

I get the following errors:

2010-02-19 01:19:20,199 WARN [org.springframework.web.servlet.PageNotFound] - No mapping found for HTTP request with URI [/com.btmatthews.minerva.portal/api/portals] in DispatcherServlet with name 'portal'
2010-02-19 01:19:32,360 WARN [org.springframework.web.servlet.PageNotFound] - No mapping found for HTTP request with URI [/com.btmatthews.minerva.portal/api/portals/] in DispatcherServlet with name 'portal'

I get the same problem when I try to do a create:

curl -F ...... --request POST http://localhost:8080/com.btmatthtews.minerva/api/portals

But if try to operate on an existing resource (retrieve, update or delete) it works okay.

Update: The solution was provided in a comment by @axtavt. I was using <url-pattern>/api/*</url-pattern> in my web.xml servlet mapping. It needed to be changed to <url-pattern>/</url-pattern>

like image 986
Brian Matthews Avatar asked Feb 19 '10 02:02

Brian Matthews


People also ask

What is the annotations used for REST controller?

Spring RestController annotation is a convenience annotation that is itself annotated with @Controller and @ResponseBody . This annotation is applied to a class to mark it as a request handler. Spring RestController annotation is used to create RESTful web services using Spring MVC.

What is @API annotation in spring boot?

The @API annotations as per the documentation states “The annotation @Api is used to configure the whole API, and apply to all public methods of a class unless overridden by @APIMethod”. Note the words unless overridden. Often you find that you casually go ahead and mark a class with @API.

What is @RequestMapping annotation in spring boot?

One of the most important annotations in spring is the @RequestMapping Annotation which is used to map HTTP requests to handler methods of MVC and REST controllers. In Spring MVC applications, the DispatcherServlet (Front Controller) is responsible for routing incoming HTTP requests to handler methods of controllers.


1 Answers

Double check the url-pattern in your web.xml and compare it to your curl argument.

Here is an example I wrote which walks you through the whole Spring MVC process.

like image 130
earldouglas Avatar answered Oct 20 '22 04:10

earldouglas