View Full Version : Design issue (POJO and DTO/VO)
manjusingh
Aug 4th, 2006, 08:35 AM
I am using struts -> Java Object (business Tier, e.g. Spring) -> Hibernate.
General practice for sendnig data to DAO is through DTO/VO for coarse grain data transfer. With hibernate we have POJO which is same as DTO. Is it good practice to use POJO for data transfer from presentation tier to Hibernate DAO, that means web tier will instantiate the POJO class, populate the POJO object and send it to DAO for persistence.
Or, shall we create separate DTO and separate POJO class ???
Arthur Loder
Aug 16th, 2006, 09:51 AM
Hi Manjusingh,
Here is a quote from Rob Harrop's and Jan Machacek's awesome Pro Spring (http://www.amazon.com/gp/product/1590594614/sr=8-1/qid=1155734967/ref=pd_bbs_1/103-9127259-7133451?ie=UTF8) (Chapter 11) about creating data transfer objects and using them to transfer data from the business tier to the data access tier (instead of just using the domain objects themselves):
"Honestly, we cannot think of a reason you would want to do this; in our eyes, it seems that this practice has sprung up out of confusion on how certain J2EE patterns should be used."
In addition, Christian Bauer and Gavin King explore the issue in Chapter 8 of their Hibernate in Action (http://www.amazon.com/gp/product/193239415X/sr=1-1/qid=1155735659/ref=pd_bbs_1/103-9127259-7133451?ie=UTF8&s=books). They note that the data transfer pattern was invented because fine-grained remote access to entity beans was too slow and entity beans were not serializable.
In the sample applications I have seen, it looks like people have avoided creating data transfer objects. You didn't really give any application-specific reasons for wanting to use data transfer objects, so I would default to using the domain objects directly and saving yourself from the code duplication and all the work to convert to and from the domain objects.
Hope this helps!
-Arthur Loder
kelly walker
Aug 24th, 2006, 11:10 AM
I have a related question. I have a distributed architecture where the presentation tier makes remote service calls. I have a coarse grained interface where the methods can return more than one type of domain object and the domain objects are from unrelated object graphs. That means I have to "wrap" these objects in an outer object which I term a DTO. Just wondered if forum members think this is good design.
Arno Werr
Aug 24th, 2006, 12:09 PM
I would argue that your case is a perfectly legitimate use of DTO - a wrapper to carry multiple data elements across a tier.
madtree
Aug 24th, 2006, 02:02 PM
I have a related question. I have a distributed architecture where the presentation tier makes remote service calls. I have a coarse grained interface where the methods can return more than one type of domain object and the domain objects are from unrelated object graphs. That means I have to "wrap" these objects in an outer object which I term a DTO. Just wondered if forum members think this is good design.
I think you use your DTOs as containers and so it is a very valid use case. The only problem is you need to code them manually so if you need a lot of them, it can be a lot of work. SDOs might offer a solution to this problem in the future (being able to pass any graph of objects and save/check changes made on them).
debasishg
Aug 26th, 2006, 12:09 PM
The use case of Kelly Walker is a good example of using DTOs. Even in the normal use case of Manju Singh, I have seen some people recommend DTOs just to enable a loose coupling between the Web layer and the domain model. Using POJOs directly in the Web tier *will* couple the domain model with the Web model - hence any change in domain model is likely to have an impact on the Web tier as well.
I would like to have the thoughts of the community on this aspect.
Cheers.
Colin Yates
Aug 26th, 2006, 05:09 PM
The use case of Kelly Walker is a good example of using DTOs. Even in the normal use case of Manju Singh, I have seen some people recommend DTOs just to enable a loose coupling between the Web layer and the domain model. Using POJOs directly in the Web tier *will* couple the domain model with the Web model - hence any change in domain model is likely to have an impact on the Web tier as well.
I would like to have the thoughts of the community on this aspect.
Cheers.
Well you do have an added abstraction in the web tier, which is the view itself.
If the domain model changed, then it is highly likely that the web tier would have to change anyway ;)
I think there *are* good reasons and situations in which that loose coupling is beneficial, but they are the exception, rather than the rule. After all, the purpose of most web apps is to interrogate the middle tier; they *are* coupled by definition.
If you need to introduce an adapter between the web tier and the middle tier, then you can always do that as and when you need it, but until then just use the POJOs in the domain model.
debasishg
Aug 27th, 2006, 12:29 AM
If you need to introduce an adapter between the web tier and the middle tier, then you can always do that as and when you need it, but until then just use the POJOs in the domain model.
Just for my clarification and understanding, if I am designing a Struts based application, within my Action class, I will use the form data to construct my domain object (POJO) and kick in the validator to get things validated before submission. Is this the model that u r recommending ?
Of course this gets rid of an entire layer of DTOs (which has no purpose in life but to transfer data across layers) and hence makes the codebase leaner :cool: .
Cheers.
Colin Yates
Aug 27th, 2006, 07:17 AM
Just for my clarification and understanding, if I am designing a Struts based application, within my Action class, I will use the form data to construct my domain object (POJO) and kick in the validator to get things validated before submission. Is this the model that u r recommending ?
Of course this gets rid of an entire layer of DTOs (which has no purpose in life but to transfer data across layers) and hence makes the codebase leaner :cool: .
Cheers.
Yes. This would be better IMO than constructing an ActionFormUser which constructed a UserVO (or UserDTO) which was passed to the middle tier which then persisted a User :)
I think you have it exactly right. ActionForm -> POJO.
Arno Werr
Aug 27th, 2006, 09:44 AM
and hence makes the codebase leaner :cool: .
If you are serious about 'lean and mean' scenario, then drop the Struts altogether with its duplication of command beans (action forms AND domain objects). Use Spring MVC instead with its 'domain objects only' approach.
debasishg
Aug 27th, 2006, 01:23 PM
If you are serious about 'lean and mean' scenario, then drop the Struts altogether with its duplication of command beans (action forms AND domain objects). Use Spring MVC instead with its 'domain objects only' approach.
I agree. I just cited Struts as an example of an MVC implementation. I really like the architecture of Spring MVC - the combination of Spring data binder and domain objects really rock:cool: . And validators are wired extremely elegantly in the whole scheme of things.
dcoales
Aug 29th, 2006, 09:34 AM
I initially tried to use my domain POJO's as the command (form backing) objects in my web layer but quickly ran into a problem. I have a class called Alarm which contains a few basic fields, e.g. name, description etc, plus some others which are references to other classes e.g. AlarmSeverity and a couple of collections. So the class might look like
class Alarm{
Long id;
String name;
String description;
AlarmSeverity alarmSeverity;
Set<Action> actions;
}
I am using OpenLaszlo for the front end - not JSP of which I know nothing - and in OpenLaszlo when the user selects a severity level from a drop down list the form field simply records the 'id' of the severity. I believe this is the same with any html select box. The select box itself is contructed by reading all the AlarmSeverity objects and constructing a list of id's and related AlarmSeverity names.
Anyway, when the user edits some basic alarm details (e.g. changes the name or severity*) and submits the form I get the Alarm id, name and description and the id of the selected severity.
When I use the POJO as the backing bean this creates a problem since it doesn't contain a field for the severityId and the 'actions' collection is set to null.
To get around this I currently use the following architecture:
In the web 'controller' layer I have a DTO called AlarmDTO which looks like:
class AlarmDTO{
Long id;
String name;
String description;
Long alarmSeverityId;
}
As you can see the AlarmSeverity property has been replaced with a Long to record the id and the collection has been removed. This DTO is populated and validated by the controller and is then passed along to the service layer for persistence. The service layer has the following jobs:
1: Use the id in the alarmDTO to retrieve the original Alarm object - assuming it still exists.
2: Copy the properties from the alarmDTO onto the Alarm POJO.
3: For each reference id (e.g. alarmSeverityId) retrieve the actual POJO to which this refers and if this is not the same as the one referred to by the original Alarm then put this new alarmSeverity object into the Alarm object.
4: Finally save the Alarm object.
A similar situation arises because the Alarm is a child of another object and all the form sends me is the id of the parent not a parent object. You can imagine the service layer routine to resolve that.
At one point I had tried to get around this by adding extra id fields to the Alarm POJO so that in addition to the AlarmSeverity property I also had an alarmSeverityId Long property. This stopped me having a separate DTO but I still had the same service layer job to do to resolve the id's passed from the form plus an extra job since the controller was setting the collection to null so I still had to reread the original Alarm and copy the collections across to the Alarm object returned from the controller. I thought doing a merge rather than save would resolve this but it didn't seem to.
From the discussions I have seen on this thread I am clearly missing something and making my life way too difficult so I would appreciate someone showing me the error of my ways and putting me on the right path.
Many thanks and sorry for the long post.
Colin Yates
Aug 29th, 2006, 11:06 AM
When selecting an "AlarmSeverity" you should register a PropertyEditor to convert from the id to the actual AlarmSeverity, thus resulting in an alarm.setSeverity(theseverity) call.
Check out propertyEditors and do a search on here.
They are very powerful.
dcoales
Aug 29th, 2006, 11:33 AM
Thanks Colin,
Like all good answers it's obvious when pointed out :-) I've already been using custom PropertyEditors in a number of places but hadn't thought of using them in this way. I can see how this solves the AlarmSeverity problem. Thanks for the pointer.
However that still leaves the collections problem and I'm still unsure what to do about it. My understanding now is as follows:
I will now use the Alarm object as my form command object. When the form data is received a new Alarm object will be created by the controller and populated from the request parameters (using a PropertyEditor as you suggest to translate id's to object references .. that sounds great).
However there will be no 'child' objects (alarm actions in this case) nor even a list of child id's in the http request object so the 'actions' collection will be empty. So at the moment I am still left with some code in the business layer to read the original object from hibernate and then repopulate the collection on the new command object before the command object is saved over the top of the original.
Is there a standard way to resolve this issue as well ?.
Many thanks.
Colin Yates
Aug 29th, 2006, 11:44 AM
You can also bind straight onto a collection using http://www.springframework.org/docs/api/org/springframework/beans/propertyeditors/CustomCollectionEditor.html.
BTW; I find things get a lot simpler if you always initialise collections, i.e. private Set alarmActions = new HashSet();
The other thing to say is that you can override formBackingObject to return the domain object fully populated from the middle tier.
dcoales
Aug 29th, 2006, 12:08 PM
Hi Colin,
All my collections are initialised to an empty collection which I guess is my problem in a way. The application flow is as follows:
1. The user calls a simple controller to retrieve alarm #1. The alarm is retrieved and an XMLBuilder walks the object graph producing some xml like:
<Alarm id='1' name='foo' description='bar' alarmPriorityId='2'>
<action id='1' name='foo'/>
<action id='2' name='bar'/>
</Alarm>
2. This xml is sent to the Laszlo client which displays it in a form. The user edits the alarm name in the Laszlo form and hits submit.
3. This calls a (different) formController to execute a save action. The parameters of the httpRequest sent only contain the Alarm details and none of the action details. The form controller doesn't know which alarm is to be updated until it receives the request and can read the id field. There is also nothing to pass to a CustomCollectionEditor at this point.
Are you saying that I can override the formBackingObject so that it waits until the request is received, plucks out the id field and then retrieves a specific Alarm from the database to use as the backing object ? This would ensure that the 'actions' collection contained action #1 and action #2 whereas without this functionality the backing object would be a new Alarm with an actions collection which contains no items.
Thanks for your help on this BTW.
Colin Yates
Aug 29th, 2006, 01:42 PM
Are you saying that I can override the formBackingObject so that it waits until the request is received, plucks out the id field and then retrieves a specific Alarm from the database to use as the backing object ? This would ensure that the 'actions' collection contained action #1 and action #2 whereas without this functionality the backing object would be a new Alarm with an actions collection which contains no items.
Exactly.
Check out the javadoc for SimpleFormController (and its super classes).
Essentially formbackingObject is called to load the persistent domain object and then the values are introspected, validation is called and if everything is peachy, onSubmit is eventually called.
I have absolutely *no* experience with Laszo so you are own your own with that ;)
Powered by vBulletin® Version 4.1.8 Copyright © 2012 vBulletin Solutions, Inc. All rights reserved.