Been trying to come up with a flow for a basic tiered web application, and have been reading conflicting information online. What I’m trying to figure out is if there is an advantage to still using DTO objects from your DAO to Service layer through the use of some sort of mapper.
The basic flow I foresee is as follows:
- UI Model / Form –> Controller
- Controller converts Model into Domain Object (Entity)
- Domain Object –> Service Layer
- Domain Object –> DAO
- DAO –> Domain Object(s)
- Service –> UI
- UI converts Domain into UI models
If DTO was followed DAO would pass back a DTO not the Entity. After doing some reading it seems like DTO has become slightly defunct since (at least in Java) entities have become annotated POJOs meaning their memory footprint has become very small.
Is this the case, or should DTOs be used to completely encapsulate the domain objects within the DAO layer, and, if this is the case, what would the service layer pass to the DAO?
Thanks a bunch!
According to me, passing a persistable POJO, like for instance a bean managed by JPA, is not THE good practice.
Why?
I see three main reasons:
- Potential issue with lazy collections. http://java.dzone.com/articles/avoid-lazy-jpa-collections
- Entity should contain behaviour (in contrary of an Anemic domain model)
You may not want to let your UI call some unexpected behavior. - In case of anemic domain model you may not want to expose your model structure to the UI, since every new change to model may break UI.
I prefer letting my service layer convert entities to corresponding DTO in both directions. DAO still returning entity (it’s not its job to ensure the conversion).
10
One of the reasons I think this discussion comes up repeatedly is because it seems like a serious pain-in-the-ass to take an object with all the data you need and convert it to an object that looks identical or nearly identical to the one you are handing off.
It’s true, it’s a PITA. But there are a few reasons (besides those enumerated above) for doing so.
- Domain objects can get very heavy and contain a lot of useless information for the call. This bloat slows down the UI because of all the data transmitted, marshalled/unmarshalled and parsed. When you consider a FE will have numerous links referring to your webservices and being called with AJAX or some other multi-thread approach you will quickly make your UI sluggish. All this gets to the general scalability of webservices
- Security can easily be compromised by exposing too much data. At a minimum you could expose email addresses and phone numbers of users if you don’t eliminate them from the the DTO result.
- Practical considerations: For 1 object to parade as a persisted domain object AND a DTO it would have to have more annotations than code. You will have any number of issues with managing the state of the object as it passes through layers. In general this is be much more of a PITA to manage then simply doing the tedium of copying fields from a domain object to a DTO.
But, you can manage it fairly effectively if you encapsulate the translation logic into a collection of converter classes
Have a look at lambdaJ where you can do ‘convert(domainObj,toDto)’ there is an overload of this for use with collections. Here is an example of a controller method that makes use of it. As you can see, it doesn’t look so bad.
@GET
@Path("/{id}/surveys")
public RestaurantSurveys getSurveys(@PathParam("id") Restaurant restaurant, @QueryParam("from") DateTime from, @QueryParam("to") DateTime to) {
checkDateRange(from, to);
MultiValueMap<Survey, SurveySchedule> surveysToSchedules = getSurveyScheduling(restaurant, from, to);
Collection<RestaurantSurveyDto> surveyDtos = convert(surveysToSchedules.entrySet(), SurveyToRestaurantSurveyDto.getInstance());
return new RestaurantSurveys(restaurant.getId(), from, to, surveyDtos);
}
1