REST API Design – Using Data Transfer Objects vs Exposing Complex Data Models

Architecturedesignlanguage-agnosticrest

We are working on an MVVM application. Jersey (backend) exposing a REST interface and AngularJS (frontend) being the only consumer of this interface. The application uses a complex database model (data model), which is different from the model presented to the user in the browser (view model).

Currently we have came across the following dilemma:

  1. to introduce Data Transfer Object (DTO) classes that will contain all the required attributes to invoke complex business logic operations on our model
  2. expose the existing complex data model without introducing DTO classes

Approach 1 will allow to simply the clients of the REST interface, as they will not have to understand the data model and will only have to provide the values of all the required attributes in the DTO classes. However, this approach requires an introduction of a mapping layer in the backend, from/to the data model to/from the view model.

Approach 2 results in less code in the backend, but will probably make the code in the frontend more complex as it will have to do the mapping of user input to the existing data model.

From the REST design perspective approach 2 seems to be better, but is exposing the data model in REST always the best solution?

Best Answer

expose the existing complex data model without introducing DTO classes

One major flaw of this approach is that of coupling data access layer with API. It can go very bad very quickly if those models are used elsewhere except API. I currently work on a project where both web interface and JSON API (kind of REST, but not quite) use the same Hibernate entities - it is fragile, since every change in one place affects the other. Reusability just doesn't work this way, I guess.

Sometimes you just have to have DTOs when models just don't fit into API. For example, if you have some tricky validation rules or some data you want to hide from API clients. You can go nuts with annotations, and yet it will not always work.

I also work on other project which also have both JSON API and web interface, but API uses it's own data access layer (jOOQ). It works fine, despite the fact there are two ways to access the data. It's just easier to write custom queries for API and fill the data into DTOs to begin with than to have some layer of "transformers" from data entities to DTOs. It also works much faster than any ORM and eliminates the whole class of problems related to lazy fetching and "Open Session/EntityManager in View" pattern.

So, I recommend using DTOs, and also considering using separate non-ORM data access layer for API. ORM is good for web interfaces (and probably RPC-style APIs), but seems to cause a lot of troubles with REST - it is related to the idea of CQRS.

Related Topic