Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring Data Rest controllers: behaviour and usage of @BasePathAwareController, @RepositoryRestController, @Controller and @RestController

I'm trying to understand the exact behaviour of the Spring Data Rest Controllers.

I have made a simple implementation to test 4 kinds of annotated controllers: @BasePathAwareController, @RepositoryRestController, @RestController, @Controller

The controller has a mapping for an entity "author" in the repository.

This is the controller:

@BasePathAwareController
//@RepositoryRestController
//@RestController
//@Controller
public class MyController {

    @RequestMapping(value="authors/mycontroller/test")
    public void handleRequest(){
        System.out.println("handleRequest of class MyController");
    }

    @RequestMapping(value="/authors/mycontroller/testslash")
    public void handleSlashRequest(){
        System.out.println("handleSlashRequest of class MyController");
    }

    @RequestMapping(value="api/authors/mycontroller/test")
    public void handleApiRequest(){
        System.out.println("handleApiRequest of class MyController");
    }

    @RequestMapping(value="/api/authors/mycontroller/testslash")
    public void handleSlashApiRequest(){
        System.out.println("handleSlashApiRequest of class MyController");
    }

}

I'm testing 4 methods because I have some doubts about the right mapping to be used.

For every experiment, I use a different controller with the sames mappings, simply decommenting the annotation that I need for that experiment.

I'm calling these two URLS with HTTP GET:

http://localhost:8080/myApp/api/mycontroller/test
http://localhost:8080/myApp/api/mycontroller/testslash

This is the result that I obtain using @BasePathAwareController:

http://localhost:8080/myApp/api/mycontroller/test
    White page, No errors, No print on console

http://localhost:8080/myApp/api/mycontroller/testslash
    White page, No errors, No print on console

This is the result using @RepositoryRestController:

http://localhost:8080/myApp/api/mycontroller/test
    White page, No errors, No print on console

http://localhost:8080/myApp/api/mycontroller/testslash
    White page, and this message on the console (only for the first HTTP GET on this url):
    jul 27, 2016 9:23:57 AM org.springframework.web.servlet.DispatcherServlet noHandlerFound
    WARNING: No mapping found for HTTP request with URI [/myApp/api/authors/mycontroller/testslash] in DispatcherServlet with name 'rest'

This is the result if I use @RestController:

http://localhost:8080/myApp/api/mycontroller/test
    White page, in console: "handleRequest of class MyController"

http://localhost:8080/myApp/api/mycontroller/testslash
    White page, in console: "handleSlashRequest of class MyController"

Finally, this is the result using @Controller:

http://localhost:8080/myApp/api/mycontroller/test
    HTTP STATUS 404, in console: "handleRequest of class MyController"

http://localhost:8080/myApp/api/mycontroller/testslash
    HTTP STATUS 404, in console: "handleSlashRequest of class MyController"

For both urls I have this warning:

jul 27, 2016 9:28:11 AM org.springframework.web.servlet.DispatcherServlet noHandlerFound
WARNING: No mapping found for HTTP request with URI [/myApp/api/authors/mycontroller/authors/mycontroller/test] in DispatcherServlet with name 'rest'

I don't understand what's going on.

The only annotation that seems to provide the expected result is the @RestController.

@Controller apparently seems to work, but I have an HTTP status 404 and there is a message with an inconsistent URL /myApp/api/authors/mycontroller/authors/mycontroller/test, despite there is the correct handling message on the console.

The other two annotations (@BasePathAwareController and @RepositoryRestController) don't do nothing.

In summary:

  • @BasePathAwareController: doesn't do nothing
  • @RepositoryRestController: doesn't do nothing
  • @Controller: strange behaviour
  • @RestController: works perfectly

It would be greatly appreciated any type of clarification about the behaviour and the usage of every kind of @Controller.

Thanks.

like image 354
Alessandro C Avatar asked Jul 27 '16 08:07

Alessandro C


1 Answers

I have found the way to make work all the annotated controllers, and I share it here.

@BasePathAwareController and @RepositoryRestController must have a @RequestMapping at class level:

@RepositoryRestController
//@BasePathAwareController
@RequestMapping(value="/authors/mycontroller")
public class MyController {

    @RequestMapping(value="/test")
    public void handleRequest(){
        //...
    }
}

Without the mapping at class level, both controllers are not handled.

That's the reason because in my previous tests the methods were never invoked.

The mapping at class level can starts with "/" or not, it works in both cases.

Furthermore, I have noticed that adding <mvc:default-servlet-handler/> in the configuration context, the warning "No mapping found for HTTP request with URI" is vanished.

like image 63
Alessandro C Avatar answered Oct 14 '22 18:10

Alessandro C