Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Same/different DTO object in create, update and get rest end points?

Consider following UserDTO class and UserController exposing endpoints to create, update and get User.

Having the id property in the UserDTO class does not make sense for create and update. If I use swagger or another auto generated API documentation then it shows that the id can be passed in create end point. But the system does not use it as ids are generated internally.

If I look at get then probably I can get rid of the id property but it is certainly required in a list user end point.

I was thinking of returning internal User domain object in get/list end points. This way I can then get rid of id property form UserDTO class.

Is there any better option I can employ for this?

public class UserDTO {
    private int id;
    private String name;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

@RestController
@RequestMapping(value = "/users", produces = MediaType.APPLICATION_JSON_VALUE)
public class UserController {
    @RequestMapping(method = RequestMethod.POST)
    @ResponseBody
    public ResponseEntity<Void> create(@RequestBody UserDTO user) {
    }

    @RequestMapping(value = "{id}", method = RequestMethod.GET)
    @ResponseBody
    public ResponseEntity<UserDTO> get(@PathVariable("id") int id) {
    }

    @RequestMapping(value = "{id}", method = RequestMethod.PUT)
    @ResponseBody
    public ResponseEntity<Void> update(@PathVariable("id") int id, @RequestBody UserDTO user) {
    }
}

This question may have been asked but I could not find. So excuse me for duplicate question.

like image 552
Bhushan Bhangale Avatar asked Jan 25 '16 11:01

Bhushan Bhangale


People also ask

Should I have different DTOs for create and update?

You do not need another DTO for create operation. You just set the default value(id=0) for creating a new object. This will help you for figuring out if the object is yet to be created in database in case you have to.

When should I use DTOs?

A DTO is helpful whenever you need to group values in ad hoc structures for passing data around. From a pure design perspective, DTOs are a solution really close to perfection. DTOs help to further decouple presentation from the service layer and the domain model.

Can DTO objects have methods?

Data Transfer Objects are public (static) classes with no methods, other than the compiler supplied default constructor, having only public fields limited to the easily serializable types: i.e. A DTO is equivalent to a struct in C.


2 Answers

Data Transfer Object (DTO) is a pattern that was created with a very well defined purpose: transfer data to remote interfaces, just like web services. This pattern fits very well in REST APIs and DTOs will give you more flexibility in the long run.

I would recommend using tailored classes for your endpoints, once REST resource representations don't need to have the same attributes as the persistence objects.

To avoid boilerplate code, you can use mapping frameworks such as MapStruct to map your REST API DTOs from/to your persistence objects.

For details on the benefits of using DTOs in REST APIs, check the following answers:

  • Why you should use DTOs in your REST API
  • Using tailored classes of request and response

To give your DTOs better names, check the following answer:

  • Giving meaningful names to your DTOs
like image 158
cassiomolin Avatar answered Sep 28 '22 17:09

cassiomolin


What's about creating two different interfaces :

interface UserDTO {

    public String getName ();

    public void setName (String name);

}

interface IdentifiableUserDTO extends UserDTO {

    public Long getId ();

    public void setId (Long id);

}


class DefaultUserDTO implements IdentifiableUserDTO {

}

and then use the Interface in your controller instead of the DTO class :

@RestController
@RequestMapping(value = "/users", produces = MediaType.APPLICATION_JSON_VALUE)
public class UserController {
    @RequestMapping(method = RequestMethod.POST)
    @ResponseBody
    public ResponseEntity<Void> create(@RequestBody IdentifiableUserDTO user) {
    }

    @RequestMapping(value = "{id}", method = RequestMethod.GET)
    @ResponseBody
    public ResponseEntity<UserDTO> get(@PathVariable("id") int id) {
    }

    @RequestMapping(value = "{id}", method = RequestMethod.PUT)
    @ResponseBody
    public ResponseEntity<Void> update(@PathVariable("id") int id, @RequestBody UserDTO user) {
    }
}
like image 36
Wael Sakhri Avatar answered Sep 28 '22 15:09

Wael Sakhri