4

What is the best approach when developing (JSON-based) REST services in terms of Data objects.

Should I split database model (back-end) from the front-end model?

Is it a good practice to always keep the DB related JPA Entities up to a specific layer and then convert them into a set of DTOs for the front-end?

For example, 3 layer architecture:

Controller

Service

Repository

Should I confine the DB entities (annotated with JPA annotations) to Repository and Service layers

And then make the Controller only operate with another set of UI 'entities' (DTOs)?

This would require some kind of mapping between the 2 either automatic or 'manual'.

This allows for 'thin' front end entities.

For example in Backend we have the JPA annotations only and we have the owner as an Account reference:

@Entity
public class Job {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    private String name;
    @ManyToOne(fetch = FetchType.LAZY)
    private Account owner;

But in the front-end layer I would have Jackson specific annotations. I don't need the whole Account object, but only its id in the UI:

class Job {
 long id;
 String name;
 long ownerId;
}

Update After experimenting with "manual" mapping, the conclusion is that it quickly becomes a mess.

In my case, I wanted the Repository layer to return Entity (JPA) and the Service layer to do the mapping and return the Dto. So for getting data from the DB, this seems pretty affordable, there is only 1 mapping involved (from Entity to Dto). But, when it comes to creating / saving entities, the problem is bigger with composite objects. For example:

Let's say I POST a UserDto (which contains UserProfileDto as a composite object) from the API client to the Controller. Now the Service layer will accept UserDto, but it will have to find the UserProfileEntity corresponding to that UserProfileDto.

Also, Repository's .save() method returns the newly persisted Entity. Now this has to be mapped to Dto and then back to Entity if I want to use it further as part of another object (otherwise I will get the object references an unsaved transient instance - save the transient instance before flushing error).

For example, if I do:

repository.save(profileEntity) this will return a newly persisted ProfileEntity, but now I need to map it to ProfileDto in order to make it part of UserDto before mapping again UserDto to UserEntity and persisting.

Note: Dto here are objects I am planning to use as a response to the client (with JSON related annotations). These live in the Service and Controller layers, whereas Entity are JPA related objects that only live in the Repository and Service layers.

ACV
  • 9,964
  • 5
  • 76
  • 81
  • 2
    I actually follow the same as u mentioned. Using same bean for db nd rest layer causes chaos in bean where each property is annotated with both layers annotation. – Hemant Patel Sep 03 '20 at 17:52
  • 2
    And initially, when we start both beans are identical, but after few iterations, we need to add a new column in db. But same is not required on rest layer Nd vice versa. This requires ignore annotations. – Hemant Patel Sep 03 '20 at 17:55
  • 2
    There are probably a lot of tutorials and opintions around there, but for a larger application i prefer to have at least three separate classes: One database entity (with JPA annotations), one entity (in terms of domain driven design or as aplain container) and finally one or multiple data transfer objects (for example JSON or XML annotations from Jackson or JAXB). Easily extendable, clear SOC, objects are not bloated with annotations and mapping frameworks do most of the work. – Glains Sep 03 '20 at 18:03
  • What good mapping framework would you suggest? Dozer last version was in 2014, MapStruct is candidate release, Orika also. Also JMapper. Is it the case that people don't use this kind of setup nowadays? Is there anything as part of Spring that would provide this functionality or should I just use custom classes for that? – ACV Sep 03 '20 at 20:03
  • There seems to be a good discussion on reddit where some also argue against any object mapping frameworks: https://www.reddit.com/r/java/comments/dt86ul/best_object_mapping_frameworks_for_java/ – ACV Sep 03 '20 at 20:07
  • I am giving it a try with manual mapping and will update shortly. But from the looks of it, there is a lot of mapping going on back and forth. – ACV Sep 03 '20 at 22:42
  • 1
    https://stackoverflow.com/a/36175349/1426227 – cassiomolin Sep 03 '20 at 23:58
  • @cassiomolin thanks, yes, those are the reasons to use DTOs. I agree, I also favour it. But when you actually start looking into it, there are many questions that need to be answered and I tried to detail here. I don't want to use auto mapping as the code you need to write there is similar in amount to the manual mapping and you don't control things. – ACV Sep 04 '20 at 09:57
  • @ACV Have you considered Lombok and MapStruct? – cassiomolin Sep 04 '20 at 09:58
  • @cassiomolin no I haven't, for now, I'll go with manual as I have a small number of entities, but I'll consider switching when the number increases. – ACV Sep 04 '20 at 10:06

0 Answers0