Transfer Obejcts vs Business Objects - Which Approach Works Best?
I would like to get the community's feedback on a common technical discussion about
what is the best approach, Transfer objects or Business objects (JPA
entities) across the tiers. I don't believe there's a golden rule. It depends on the use case, the complexity of the
application in terms of architecture and frameworks used.
Transfer Object across the tiers
Pros
Cons
Business Object across the tiers
Pros
Cons
Published at DZone with permission of its author, ALVARO VILAPLANA GARCIA.Transfer Object across the tiers
Pros
- Reduces network traffic in distributed systems. Transfer objects are passed to the client in a single remote call.
- Improves client performance by removing any need to assemble data models.
- Decouples business logic from the client and keeps it in the business tier.
- Improves transaction performance by isolating the components that can be updated.
Cons
- Data in transfer objects might get obsolete. The transfer object has a copy of the data which is not automatically updated if the data changes on the server.
- The system can be complicated when using concurrent access or transaction management processes.
- Synchronization logic can complicate the system if updatable transfer objects are used.
Object creation overhead on the server side increases.
Business Object across the tiers
Pros
- Good approach in simple presentation tier design.
- Makes easier the development in business and presentation tier because there is no need to assemble data models.
Cons
- Couples presentation tier and business tier. (Note: If the business requirements don’t change often I consider that is good point to use them but otherwise it could be a nightmare for each single change to adapt the presentation tier.)
- In the case that the user interface requires a complex set of properties, passing the domain model across the tiers can become heavyweight in terms of memory.
- The development in the presentation tier can be complex because we need to navigate across multiple business objects to get the properties.
- The development in business tier can become very tedious because we will load a lot of properties in the domain model (properties from BO1 -> properties from BO2 -> properties from BO3 and so on). There are two approaches to have all the properties in presentation tier:
- In business tier: Eager relationships in JPA entities.
- In business tier: “Fetch Join” in application services.
Note: Some frameworks keep transaction opened during the render of the user interface.
When relationships in the JPA entities can be defined as LAZY, we don't have to worry about exceptions such as org.hibernate.LazyInitializationException when using Hibernate as JPA provider.
What are your thoughts? Has any one particular approach worked better for you?
(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)
Tags:





Comments
Mike P(Okidoky) replied on Tue, 2009/11/17 - 2:51pm
Exceptions are newly created records, but keep using other setters to a minimum.
Pieter van der Meer replied on Tue, 2009/11/17 - 4:03pm
Alvaro,
Ik think the cons of the business objects provide the answer on why you would never pass objects through the various layers over your application model. When usig the JPA implementation you suggest you are not only tying your presentation tier to the business tier but actually to the data access tier.
Besides the obvoius point you already point out, one of teh more desturbing things that you allow is direct manipulation of objects (data) that resides in the database from the presentation model. You got to be very sure that the presentation layer does not messes up the database.
I belive in the assumption that the seperation of concerns is key to a good design. And yes when you have a simple application that has a short live time, the straigh passthrough the layers is no problem ;-). The only question left now define simple and short lived ;-)
Aries McRae replied on Tue, 2009/11/17 - 5:29pm
Alejandro Calbazana replied on Tue, 2009/11/17 - 5:46pm
Posted a reply here... There is room for both, I think...
I do think there is a sliding scale where it is permissible to use persistence objects in the presentation tier.
Nicolas Frankel replied on Wed, 2009/11/18 - 2:48am
Excellent article considering I asked myself the question not so long ago whether it would be better not to use Transfer Object in small / independent applications.
Transfer Objects are inherited from EJB2 design patterns where you could not transfer entities from the back end to the front-end since you were tied to the EJB container. Nowadays, this behaviour is still used without any thoughts about it.
The only reason to keep this behaviour is to hide your business entitis from other applications. To hide BO from the front end if it's the same application is a waste of time IMHO (at development time and at runtime).
Some tenants of TO care to elaborate the need to use them?
For example, pieni, since you closed your JPA context when you went from the data access tier to the business tier, your BO are not tied to the DB anymore and you can do whatever you want with them: if you do not explicitly reattach them, there's not side effect on the DB.
Mladen Girazovski replied on Wed, 2009/11/18 - 5:06am
You forgot to mention the imho biggst drawback of passing Entities around:
It is only possible with dumb JavaBeans, so it encourages an "anemic domain model" where the so called Domain Objects/Entites are nothing more than data structures instead of real objects with behaviour.
You won't be able to use DDD or any other OO Design for your App, but are stuck with the old, procedural style of design that Fowler calls "Transaction Script", all the Logic ends up in your SessionBeans, which uses Daos and the Entities to perform their job.
That ain't bad in all cases, however, it is an serious limitation if you wanted to go DDD, since in DDD your Entites would have logic & references to the repositories (Daos) to perform their job.
ALVARO VILAPLAN... replied on Wed, 2009/11/18 - 9:30am
in response to:
Mike P(Okidoky)
William Draï replied on Wed, 2009/11/18 - 5:26am
Tony Siciliani replied on Wed, 2009/11/18 - 8:34am
in response to:
Nicolas Frankel
"Transfer Objects are inherited from EJB2 design patterns"
I used TOs before EJB came out, to transfer data between layers. And I suspect that I wasn't the only one.
"To hide BO from the front end if it's the same application is a waste of time IMHO"
Decoupling the business layer from the front-end is a waste of time? Really?
"Some tenants of TO care to elaborate the need to use them?"
For the most part , for reasons outlined in this article, i.e. pros of using TOs + cons of using JPA.
Andy Leung replied on Wed, 2009/11/18 - 7:32am
ALVARO VILAPLAN... replied on Wed, 2009/11/18 - 7:48am
in response to:
Andy Leung
Mladen Girazovski replied on Wed, 2009/11/18 - 8:31am
There is no need for creating complex DTOs or different DTOs per UseCase by hand, use Dozer, a Framework that will Map your Beans to whatever you want, like Maps.
Maksym Ivanchenko replied on Wed, 2009/11/18 - 10:01am
Two adding Cons for Business Object across the tiers:
1. Possible security gap. Front-end tier can be not completely trusted (e.g. freely distributed client application) and it could be security gap here when you provide outdoor classes which contain information about your database structure.
2. Possible traffic overhead. Usually Business Object contains more data than you really need in some specific calling context (especially if it has lot of embedded entities or eager relationships). In list of objects it can lead to big traffic. Or you'll be forced to use DTO in this concrete case.
From the other side I'm completely agreed with your Cons for DTO.
We've faced the same problems (lot of times :) ) in out team and wrote small framework exactly to solve this issue and find the way on razor's edge :)
The idea is to generate DTO and fill it with data dynamically when needed by using java.lang.reflect.Proxy.
In everyday usage it looks like in this example:
Your JPA entity (it exists on server only and not visible to client). It is annotated with interfaces which can proxying this entity.
@Entity @ProxyBindings ({ @ProxyBinding(interfaceClass = ISomeEntity.class) }) public class SomeEntity implements Serializable { private long id; public long getId() { return id; } public void setId(long id) { this.id = id; } }Data interface which will be used between tiers (communication protocol). It has no dependency on JPA stuffs. You can define only methods for data you want to provide to client.
@TransferProxy public interface ISomeEntity { long getId(); void setId(long id); }Usage on server.
Then you return this proxy in you EJB method. Client will work with it in transparent way (as with usual POJO) and never gets LazyInitializationException or superfluous data. Database structure is hidden completely also.
Framework also allows to make JPA entity back from coming proxy, to create instances of proxies on client, etc. Will extend if appears interesting..
What is your opinion on this "third" approach?
ALVARO VILAPLAN... replied on Wed, 2009/11/18 - 10:11am
in response to:
Maksym Ivanchenko
Andy Leung replied on Wed, 2009/11/18 - 11:14am
Maksym Ivanchenko replied on Wed, 2009/11/18 - 12:07pm
It's pretty good from performance point of view because there is no real deep cloning here. You configure what you want to get from entity by interface for proxy.
Take a look, pls:
@TransferProxy public interface ISomeEntity { long getId(); void setId(long id); List< ISomeEntityChild > getChilds(); void setChilds(List< ISomeEntityChild > childs);} @Entity @ProxyBindings ({ @ProxyBinding(interfaceClass = ISomeEntity.class) }) public class SomeEntity implements Serializable { private long id; private List<SomeEntityChild> childs = new ArrayList<SomeEntityChild>(); private List<SomeEntityAnotherChild> anotherChilds = new ArrayList<SomeEntityAnotherChild>(); public long getId() { return id; } public void setId(long id) { this.id = id; } public List<SomeEntityChild> getChilds() { return childs; } public void setChilds(List<SomeEntityChild> childs) { this.childs = childs; } public List<SomeEntityAnotherChild> getAnotherChilds() { return anotherChilds; } public void setAnotherChilds(List<SomeEntityAnotherChild> anotherChilds) { this.anotherChilds = anotherChilds; } } @TransferProxy public interface ISomeEntityChild { long getId(); void setId(long id); } @Entity @ProxyBindings ({ @ProxyBinding(interfaceClass = ISomeEntityChild.class) }) public class SomeEntityChild implements Serializable { private long id; public long getId() { return id; } public void setId(long id) { this.id = id; } } @Entity public class SomeEntityAnotherChild implements Serializable { private long id; public long getId() { return id; } public void setId(long id) { this.id = id; } }Proxying mechnaism goes into SomeEntityChild entity and makes proxy for it but ignores SomeEntityAnotherChild.
Efforts are not bigger than in simple DTO population (manually or by using Dozer, for instance) and can be considered appropriate (especially if we remember what a huge monster is modern application server).
ALVARO VILAPLAN... replied on Wed, 2009/11/18 - 12:50pm
in response to:
Maksym Ivanchenko
Business Object A: id name sureName adreess Business Object B (ManyToOne) Business Object C (ManyToOne) Business Object B: id price Business Object C id accountNumber pinNumber password 1. We have use case where you want to show in the user interface instance A.name instance A.sureName instance A.instanceB.price 2. we have use case where you want to show in the user interface instance A.name instance A.sureName instance A.instanceB.price instanceA.instanceC.accountNumber instanceA.instanceC.pinNumber instanceA.instanceC.password Question: How do you deal with this situation?Mark Unknown replied on Wed, 2009/11/18 - 7:49pm
@alvarovilaplana - It depends. But First -DTOs contain the same amount of Data as an entity. That is the DTO pattern. IF you only select certain attributes of different entities, then this is not a DTO. It is something like a (readonly) view model. Now back to the "depends". For viewing in a list, I might use a ViewModel or "Report Object" and only retrieve the attributes i care about. I could have one or more objects. I need to weigh the effort vs savings. I build these objects by doing a "select new SomeObject(a.field, b.field) from ...." For Look up objects, I typically just return those objects. The reason for doing this has much less to to with network issues and more with databases. If the object tree is pretty simple I don't waste time with View Models.
So the short of it is .. there is no right answer. You need to be or find a good architect to help you make the right decisions. And guess what - down the road you might have to make a change.
One issue I have run into is using something like GWT or Flex. These force me to use more ViewModels than i would like.
@Everyone who talks about the "tiers". The view/database/etc are not "tiers". They are layers. I have apps that have multiple layers but run on one "tier".
Mark Unknown replied on Wed, 2009/11/18 - 8:34pm
in response to:
Tony Siciliani
Yes. Sometimes, though, it is necessary. But this leads to duplicated code, non-OO code and usual just a lot of extra code. But this is not 'Decoupling". It is dealing with issues.
Robin Bygrave replied on Wed, 2009/11/18 - 8:57pm
in response to:
Mark Unknown
> But First -DTOs contain the same amount of Data as an entity
Hmmm, there might be a bit more to this in that ... entities can be "partially" populated. Some ORM's provide this via "fetch groups" ... in Ebean ORM you can specify explicitly which properties you want as part of the query language.
> I build these objects by doing a "select new SomeObject(a.field, b.field) from ...."
Yes, except it is not quite the same as a "partial object" ... where you re-use your existing model (don't need to define a new SomeObject) and your partially populated bean is still updatable and can still lazy load etc.
What this means to me ... is that it would potentially be nice to make the entity -> DTO transfer aware of the "partially populated" entity so that the transfer itself didn't invoke lazy loading un-necessarily (aka make use of the underlying "fetch groups" or "partial objects" support of the underlying ORM.
- Rob.
Mark Unknown replied on Wed, 2009/11/18 - 9:05pm
Reviewing DTO Pros:
This is no different than JPA entities.
A DTO is all the attributes of the entity(s). You best be reassembling the Domain Entity in the client layer. (see the DTO pattern as defined by Fowler)
This is not a Pro. Not having business logic in the client layer can actually be a performance issue. Some business logic should not or cannot be performed in the "client" layer.
Have no idea what this means. Anyway, DTOs should not be updated directly by any layer. They should be disassembled and reassembled. As for performance ... this, again, if in distributed system, might be performance hit.
DTO Cons - I think I pretty much agree.
Business Object Pros
Actually it is very good in a complex presentation tier too.
Business Objects Cons
So? The presentation "layer" is presenting the business objects. Add DTOs and now you have to layers coupled to an anemic object. What are you trying to "decouple"? Again, there might be reasons that you can't or don't want to use them directly. This adds overhead so only use where needed.
Then use a "View Model". This has nothing to do with "passing between tiers". It has to do with retrieving from the "store". This is less of a concern if you are using something like Coherence.
I've worked with an app that use DTOs everywhere. That was much more complex. Use view objects where needed, not everywhere.
No it doesnt. It becomes tedious if I have to create a bunch of view objects and have to re-assemble objects. My ORM does the loading. It is no work on me.
Here is the problem (again). People have confused, for years, the difference between Layers and Tiers. They also have confused DTOs with view objects.
Also, I used an example in another post - "select new SomeObject(...". There are other things to be used if you are using Hibernate, like just returning an array of objects (select a.field, b.field... ), or putting them into a list (select new list(...), or a map (select new map(...).
Mark Unknown replied on Wed, 2009/11/18 - 9:18pm
in response to:
Robin Bygrave
So Entities can actually be MORE efficient that DTO's? LOL. Anyway, I would avoid "partially loaded" entities. Use a veiw object or the other things I mentioned - if you need attributes from a complex object graph. I've worked with partially loaded DTO's. A total pain.
As I said, I use where i have to. Using partially loaded objects leads to big issues especially when working in a distributed environment. This is how most of my applications are. They also have different User and System Interfaces. If all you have is a Web interface (and you are not using GWT), I can see you being able to use your technique if the the attributes are "lazy loaded" too. If not, then not.
ALVARO VILAPLAN... replied on Thu, 2009/11/19 - 6:11am
in response to:
Mark Unknown
Robin Bygrave replied on Thu, 2009/11/19 - 3:17pm
in response to:
Mark Unknown
> Using partially loaded objects leads to big issues especially when working in a distributed environment.
I curious as to what "big issues" you had with partial objects. Yes, in a distributed environment it gets more tricky but that depends on a lot of things such as use of 'enhancement', the serialisation method and the functionality you want on the 'remote' side.
Can you list the major issues you hit?
Thanks, Rob.