0

Assumption:

We have to create REST layer for managing users.

The natural thing for us is to create two methods:

  • for creating an user (or register a user)

  • for obtaining the user.

We start from the first one and firstly focus on defining user model: first name, last name, age, country, language, etc.

So far so good. The next thing is method for obtaining the user details: first name, last name, age, country, language AND additionally the whole box of other values that have been set up during user registration: id, default groups that user belongs to, maybe roles (administrator, moderator?), datetime when user had been registered and so on).

We would set this information about user within one class (user model) but what about set up constraints to these internal elements? For instance: first name or last name should be required and defined in both cases (create & get), it's ok, but user id? it's not required during 'create user' method (even it's prohibited) but get method should have this field.

It seems the simplest way is to split the user model into two classes: UserBase with all required fields (for registration) and User extends UserBase for other cases.

It's just a requirement for well implemented REST services based on resources: create new resource (user): POST ../users obtain resource (user): GET ../users/{id}

What is the best practise to handle this problem?

Andrei Ciobanu
  • 12,500
  • 24
  • 85
  • 118
Roland
  • 189
  • 3
  • 7

2 Answers2

1

I have answered a similar question here. Having dedicated model classes for your REST API will give you more flexibility in the long run and will bring some benefits. To mention a few:

  • It will prevent you from exposing fields that you shouldn't.
  • You will have full control over the attributes you are receiving when creating or updating a resource.
  • It will be handy when managing multiple versions of your API.

The boilerplate code of mapping a persistence model to a REST API model can be avoided: there are many mapping frameworks that you can use for this purpose. For instance, have a look at MapStruct, which is annotation based and works as a Maven Annotation Processor.

Also consider Lombok to generate getters, setters, equals(), hashcode() and toString() methods for you.

cassiomolin
  • 124,154
  • 35
  • 280
  • 359
0

For complex applications I tend to create a User class that contains everything a User needs, and then add a new layer of classes related to User that only contain the necessary data for that type of operations.

I call this new layer of classes DTO.

Then I have a third party library that acts like a model mapper between the User and the DTO objects. I had good experiences using ModelMapper.

For example if I have an Order class as the main class in the model layer, and another class OrderDTO that only expose the information I need for a particular operation, the mapping works like this:

// Assume getters and setters on each class
class Order {
  Customer customer;
  Address billingAddress;
}

class Customer {
  Name name;
}

class Name {
  String firstName;
  String lastName;
}

class Address {
  String street;
  String city;
}

And OrderDTO:

// Assume getters and setters
class OrderDTO {
  String customerFirstName;
  String customerLastName;
  String billingStreet;
  String billingCity;
}

To play with the two I only need to:

ModelMapper modelMapper = new ModelMapper();
OrderDTO orderDTO = modelMapper.map(order, OrderDTO.class);

Not everybody likes the DTO approach, but I think it's the most flexible way of doing things especially if the application becomes complex.

Now, concerning the validations. I tend to annotate the User class with annotations from javax.validation.constraints, and the verify the BindingResult for any errors.

Andrei Ciobanu
  • 12,500
  • 24
  • 85
  • 118