ALVARO has posted 1 posts at DZone. View Full User Profile

Transfer Obejcts vs Business Objects - Which Approach Works Best?

11.17.2009
| 15267 views |
  • submit to reddit
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
  • 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?

Published at DZone with permission of its author, ALVARO VILAPLANA GARCIA.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Comments

Mike P(Okidoky) replied on Tue, 2009/11/17 - 2:51pm

Instead of passing changed objects to update method, only make changes using session beans inside transactions. Use the objects in a read only fashion only.

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

If you're web tier requires a large collection of records to be displayed, and you don't have (or not allowed to have) a paging mechanism in place, then you can either :
  1. Return a large collection of Transfer objects to your web tier. Each Transfer object represents a JPA entity (i.e. you convert your JPA entity to a Transfer object). In doing so, you incur a performance hit if you have thousands of these JPA entities to convert, but you prevent your JPA entities from leaking onto your web tier.
  2. You return the large collection of records onto your web tier as JPA entities. In doing so, you avoid the performance hit, but you allow your JPA entities to leak onto your web tier.

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

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.

 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)

I agree with you. Moreover if we use session beans (facade) we could use transactional persistent contextm therefore if we use business objects as JPA entities, these objects will be detached in the rendering process. Another interesting article that I would like to comment is extended persistence context vs transactional persistence context.

William Draï replied on Wed, 2009/11/18 - 5:26am

I don't agree with most of the cons of using detached objects : 1. Coupling between presentation and business tier. Why not but in most cases if you add a property in an objects, there is a high probability that you will have to display or edit it somewhere in the UI. The only thing I see is when you completely change the data model but in this case you would also have to update the model/DTO mapping. But this is a valid point if the different layers are built by completely different teams. 2. If you need a complex set of properties, the DTO will also be heavyweight. 3. It a lot easier to build reusable components in the presentation tier when the underlying data model is the same in the whole application. Having different DTOs for different use cases just makes things more complicated. 4. Using detached objects on the business tier is easy. In most cases, just validate the object received from the client and merge it in the EntityManager. By contrast, by using DTOs you have to build a mapping layer between your DTOs and your managed entities.

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

In my cases, the cons of business object is cons of tranfers object to me, when the requirement is changed often, I have to change both transfer and business objects, that's so much work to do. I understand the transfer object concept but when adding a field to screen where this owls is from database, most likely I have to change entity and DTO, but I also have to change the web tier if business tier is exposed as service, that means i may also have to change the DTO between web and business tiers. May be this is just me but I see the other teams having the same issue, any suggestion?

ALVARO VILAPLAN... replied on Wed, 2009/11/18 - 7:48am in response to: Andy Leung

First of all, I appreciate a lot your comments. I can see that there is no an agreetment about the solution to be used. Probably there is no golden rule. It will depend on the situation, use case, architecture, framework used.... at the end of the day, the software is an art. Probably we could complain about our approach each other with thousands of reasons. It is good for me to read really good points from really good architects / developers.

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

Hi Alvaro,

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.
 
SomeEntity entity = em.find(...);
ISomeEntity proxy = ProxyFactory.getProxy(entity); // this line generates proxy and fill it with data from entity

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

How is the performance? I think the framework somehow will do a deep copy of the entity into proxy object (from server side to client side) and a deep copy of the proxy object into entity (from client side to server side).

Andy Leung replied on Wed, 2009/11/18 - 11:14am

arggh..I see your point. True. Sometimes I think that it's good to use DTO even it's hand-craft because of lazy loading, security, network traffic, and DB performance. With all associations in entities, in circumstances I need to have lazy loading in the first place and then discovered that it requires certain level of eager, so ended up with performance issue or detached objects issue. If that's DTO, well all I have to do is to create Request/Response objects specifically for each business methods, and then on DB side, I can optimize the performance by using better query and populate the response objects. This will ensure DB performance and also reduce network traffic on returning entire record back to web tier where some specific use case may use only 2 fields out of 35. e.g. Many web apps are using Ajax to allow users to have quick update to...task status, let' say. With Ajax, users no longer need to click each Task details, and update the Task status while you don't update all other info; instead users can update the Task status in the List view. Now, the good things from web perspective: 1. Responsive UI 2. Better user experience 3. Reduce network traffic Now in the business logic and persistence, it's not necessary for business logic to receive the entire Task update form where it just wants to update the status ID (assuming it's a relational model), so in this case, business receives the status ID from web, so business just passes this to persistence and update ONLY the status ID in Task record using optimized update statement. Well perhaps I need to build my little framework to automate some of the processes here.

Maksym Ivanchenko replied on Wed, 2009/11/18 - 12:07pm

Alvaro,
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

Let's assume that we have the following:
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

Decoupling the business layer from the front-end is a waste of time? Really?

 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:

Reduces network traffic in distributed systems. Transfer objects are passed to the client in a single remote call.

 This is no different than JPA entities.

 Improves client performance by removing any need to assemble data models.

 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)

 Decouples business logic from the client and keeps it in the business tier.

 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. 

 Improves transaction performance by isolating the components that can be updated.

 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

Good approach in simple presentation tier design

 Actually it is very good in a complex presentation tier too.

 Business Objects Cons

Couples presentation tier and business tier

 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.

 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.

 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.

 The development in the presentation tier can be complex because we need to navigate across multiple business objects to get the properties.

 I've worked with an app that use DTOs everywhere. That was much more complex.  Use view objects where needed, not everywhere.  

The development in business tier can become very tedious because we will load a lot of properties in the domain model

 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

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.

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.  

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. 

 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

>>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)

Can you ensure that the 100% of your use cases are working with entities somehow?. 
I have cases where I return a DTO after a very complex calculations where the business logic  does not interact with entities, just calculations. 
So in my opinion to say "DTO is all the attributes of the entity(s)" is a sin, whoever say that.
I recommend you to read "Core J2EE Patterns: Best Practices and Design Strategies"

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.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.