Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring Boot REST path mapping

I'm just thinking, what is the best practice to create PATH mapping for rest service. Let's say we have following paths:

/users POST
/users/1 PATCH, GET
/users/1/contacts GET, POST
/users/1/contacts/1 GET, PATCH

The question is - what is the best practice to create controllers. For example we have UserController where we technically could put all these mappings. Or - we should create seperate controllers (UserController, ContactsController). f.e UserController below, if we put everything under.

@RequestMapping("users")
@RestController
public class UserController {

    @RequestMapping(method = RequestMethod.POST)
    public ResponseEntity<Void> createUser() {}

    @RequestMapping(method = RequestMethod.GET)
    public User getUser() {}

    @RequestMapping(value = "{id}/contacts", method = RequestMethod.GET)
    public List<Contact> getContacts() {}

    @RequestMapping(value = "{id}/contacts", method = RequestMethod.POST)
    public ResponseEntity<Void> createContact() {}

    .....
}

And if we create separate controllers, how paths should be organized then? Probably it's a silly question, but i will be glad, if someone could share experience.

like image 622
comprex Avatar asked Oct 11 '16 19:10

comprex


People also ask

What is REST mapping in Spring boot?

The REST application follows the REST architectural approach. We use the REST application for developing and designing networked applications. It generates the HTTP request that performs CRUD operations on the data. Usually, it returns data in JSON or XML format.

What is the use of @RequestMapping annotation?

annotation. RequestMapping annotation is used to map web requests onto specific handler classes and/or handler methods. @RequestMapping can be applied to the controller class as well as methods.

What is the difference between @RequestMapping and @GetMapping?

@RequestMapping is used at the class level while @GetMapping is used to connect the methods. This is also an important Spring MVC interview question to knowing how and when to use both RequestMapping and GetMapping is crucial for Java developers.

What are the uses of @RequestMapping and @RestController annotations in Spring boot?

We can annotate classic controllers with the @Controller annotation. This is simply a specialization of the @Component class, which allows us to auto-detect implementation classes through the classpath scanning. We typically use @Controller in combination with a @RequestMapping annotation for request handling methods.


2 Answers

Lets suggest that number of entities related to User will increase in future. So it obvious that it is better to split it according to entities:

UserController -> UserService -> UserRepository,

ContactController -> ContactService -> ContactRepository,

FriendshipController -> FriendshipService -> FriendshipRepository

From my experience, User Controller

@RestController
@RequestMapping("/user")
public class UserController extends AbstractController {

...

   @RequestMapping(method = RequestMethod.POST)
   public ResponseEntity<?> createUser(@RequestHeader("X-Auth-Token") Optional<String> @RequestBody User user) {

...

   @RequestMapping(method = RequestMethod.GET)
   public ResponseEntity<?> listUsers(@RequestHeader("X-Auth-Token") Optional<String> authToken) {
...

related to user scope Friendship controller:

@RestController
@RequestMapping("/user/{id}")
public class FriendshipController extends AbstractController {

...

@RequestMapping(value = "/friendship/code", method = RequestMethod.POST)
    public ResponseEntity<?> generateCodeForUser(@PathVariable("id") long id) {

...

 @RequestMapping(value = "/friendship/code", method = RequestMethod.GET)
    public ResponseEntity<?> retrieveCodeForUser(@PathVariable("id") long id) {

...

Not sure it is axiom, but help me organize my code.

like image 179
Sergii Getman Avatar answered Nov 02 '22 23:11

Sergii Getman


I am a fan for separate controllers as they remove coupling between Users and Contacts (for example) - what if later you want to use Contacts in a separate context? (i.e. independent of the User they belong to)

If they are separated, the paths would look very similar to what you have:

Users

/users GET, POST
/users/{user-id} PATCH, GET

Contacts

/contacts GET, POST
/contacts/{contact-id} GET, PATCH

If there is a dependency between Contacts and Users (and in this case, it looks like there is one), you can have it like this:

/contacts/for-user/{user-id} GET, POST
/contacts/for-user/{user-id}/{contact-id} GET, PATCH

This allows you to add contacts to other things (not just users) and users to other contexts (regardless of their contacts)

For example, Users of a coffee maker

/coffee-maker/users GET

Or if the coffee maker fails, who do we contact for repair?

/coffee-maker/contacts GET

Probably a contact for a coffee maker repair is also a User (but they don't have to be)

One more thing, you can turn it around and say that a contact is for an appliance (i.e. a coffee maker)

  /contact/for-appliance/{appliance-id} GET

My point being that if you decouple the contacts from the users, you can assign contacts to other entities instead of forcing the relationship to be User -> Contacts - unless, of course, you don't want to decouple them because of business rules or some reason

In any case, beware that there are many ways of doing the mapping

like image 39
blurfus Avatar answered Nov 02 '22 22:11

blurfus