Avoid exposing JPA entities in REST API, Instead generate client beans using OpenAPI Generator and map them to entities using MapStruct.
There’s always been discussion about whether we should expose JPA entities in RESTful APIs, or define Data Transfer Objects(DTOs) and map entity classes to the DTOs. We will discuss pros and cons of exposing JPA entities as REST API resources.
We will see how to generate REST API DTOs from Open API Specification using openapi-generator tools and also how to greatly simplify mapping between JPA entities and DTOs using MapStruct code generator.
Why it is tempting to expose entities as REST API resources
- Most times entities look the same as RESTful DTO, exposing JPA entities directly reduces code, Controllers, services, and repositories all deal with the same classes.
- Reduce code and maintenance overhead of two classes, like when adding an attribute one and forget to add in another.
Why its not good idea to expose JPA entities as REST API resources
- Separation of concerns, resource representation concerns of REST shoul be separate from the transactional concerns of JPA. Which means API and persistence layer should evolve independently of each other.
- There could be mismatches between internal representation and the API resource. Like a resource having information that is populated and saved by more than one entities.
- API shouldn’t expose any implementation details of your application, like entities may contain identifiers, paths on disk and some other internal data.
- Entity could be a large data object and API users don’t want to download the object just to read the other fields of the entity.
- When we use entities as API resources, we will end up having lots of annotations on the same class which can reduce readability. Like we might end up having JPA annotations (@Entity, @Id, @GeneratedValue, @Column, @ManyToMany, @MappedBy, etc), XML annotations (@XmlRootElement, @XmlType, @XmlElement, etc), JSON annotations (@JsonInclude, @JsonIgnore, @JsonProperty, etc), and validation annotations (@NotNull, @Null, etc) all on the same class.
- Supporting multiple versions of our RESTful API is much easier if we are exposing DTOs.