We’ve recently been involved in an EJB 3 project that uses the ‘Transfer Object’ Design Pattern. For those of you not familiar with it, this pattern came about as a result of the inefficiency of making multiple remote method calls to an EJB 2 Entity Bean.
The typical Transfer Object use case is where an EJB 2 Entity bean resides in another JVM and you want to query some information from it. Each method call to the EJB is remote (because it is in a different JVM) and to get all the information from the EJB you have to make multiple method calls. To take an example, for CustomerBean, getName(), getSurname(), getCustNum() etc. would all be remote calls. Remote calls are inherrently slow so getting the attributes of an EJB 2 Entity in this way is not very efficient.
In the Transfer Object pattern, you make one method call to the Entity Bean – getState() for example – and it returns a serializable POJO – the Transfer Object – that contains all the attributes that make up the state of the bean – name, surname etc. This makes the communication much more efficient since there is only one method call instead of one for each attribute of the bean.
However, you have to write some extra code to get the Entity to transfer its state into the Transfer Object (TO). In addition, there is the update problem – if you read some data using a TO, update it and send it back to the Entity Bean, the state of the Bean might have changed during the update so you have to write code that a) updates the state of the entity with the values in the Transfer Object and b) checks to make sure that the entity hasn’t been updated in the meantime by someone else – the ‘lost update’ problem.
In EJB 2, the use of the Transfer Object pattern was almost obligatory. In EJB 3 however, things are different. For a start, Entity Beans no longer have to reside on the EJB tier – they can be sent to any other tier and you do not have to call them remotely.
With EJB 3, if you are hosting your entire JEE applicacion (EJBs and the web presentation tier) in the same JVM, there is no need to use Transfer Objects since you are not transferring Entities between JVMs. Even if you do send Entity beans to different JVMs, it is possible to still use detached Entity Beans, though you have to ensure that the attributes of the bean have been eagerly loaded since once detached, it is no longer possible for an Entity Bean to retrieve data from the underlying database.
As my colleague Diego points out in his blog, there are some valid circumstances in which you may still want to use Transfer Objects with EJB 3. But they are few, and in the vast majority of cases, plain EJB 3 Entity Beans will work just fine.
Coming back to the work we did recently, this was a JEE application running both the EJB and Web (JSF) tiers in a single BEA WebLogic server (i.e. a single JVM). There was no requirement for remote access of the EJBs yet the code still used Transfer Objects. After some investigation, we realised that the root cause was poor Object-Relational mapping of the Entity Beans (but that’s another story). The point is, if you see an EJB 3 application using Transfer Objects or you feel your EJB 3 application needs to use Transfer Objects, be very careful. Be sure that there is a real requirement for remote access of the EJBs and that detached Entity Beans will not work. Check that you do not have an underlying issue.
Transfer Objects require lots of code, effectively add another layer to the application and require potentially buggy code to transfer state to/from an Entity Bean. Only do it if you really have to!