• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

MVC Model and Domain Model

 
Greenhorn
Posts: 10
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I'm fairly new to web and java development, but fairly experienced with non-web & non-java development. Over the past few months of playing catch up on the topic of web development, it seems I have switched over in interesting times with regards to JSF, Spring, and EJB 3.0 as opposed to old style EJBs and the new interest in lighter J2EE development.

However, during my travels on the web, one thing I have seen most people skip over is the glue between the JSF backing bean, (or action bean, form bean in other frameworks), and the domain model which might be using hibernate or JPA to map to the database, and even be used in a completely different application using Swing or console based. This is mainly manifest in cases where we are editing an existing object based on an ID. We need to initially put the existing values into the page, let the user edit them, and on posting them back, put the new values into the existing object and save the object.

The backing bean can become 'polluted' with presentation level code such as action methods and binding fields for UI Components, so obviously, the backing bean object <> domain model object.

We have looked at containing the ORM object as a property of the bean, (i.e. Person object) and using #{MyBean.Person.FirstName} within the JSP page to get the value into the web page. The problem is that when the bean is rebuilt from the client page, the only values populated are those that were on the page and results in an generally unknown state of the MyBean.Person object since it could only partially be filled in.
In order to complete the person object, we need to either ensure every property is in the JSF page, or manually reload it and then have JSF overlay the new values on the freshly loaded object.

The other method, and this seems to be more straightforward, and less fraught with danger, is to have each field of data that is present on the page as a property of the bean, (i.e. #{MyBean.FirstName} ) and when first creating the bean or saving date from the bean, we manually read/write the properties from/back to the domain object. This is kind of like a facade for the data contained within the bean.

Both methods result in 2 fetches of the object from the DB. Once when you initally create the edit page, and send the values to the client. The other when the client sends the edits back, and they need to be applied to the domain object. Of course, you could put the object into the session, but it seems from my limited experience that this would be bad practice from the point of view of making an application stateless, and not requiring the users session take up gobs of objects just to perform basic edit functions.

One other (non JSF specific) method I have seen is to rebuild the Domain object from scratch using the data in the bean, and just save it. Since the ID will be used to determine whether it is an insert or an update to the object, everything will be OK in the data access layer. This may work for simple objects where ever property is on the page, but if someone adds a property then suddenly, everytime you edit an object, that property gets set to null.

I'm just wondering what people's best practices are on the topic since most examples seem to go from JSF -> Backing Bean -> JDBC -> DB when in many cases, people are looking for JSF -> Backing Bean -> Hibernate/ORM/JPA -> DB.
[ January 05, 2007: Message edited by: Andy Gibson ]
 
Ranch Hand
Posts: 148
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
How about JSF -> JPA -> DB? Yes, it's possible. Take a look at Seam. That's the "glue" you are looking for. Mind you, it takes a little investigation, but once you get it, I think it provides the answer you are looking for.

I have given an example using Seam showing this "glue" in action at http://jroller.com/page/hstang?entry=seamless_transition

Hung
 
Hung Tang
Ranch Hand
Posts: 148
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I'll add some of my thoughts. My assumption is that you are using EJB3 Entity/JPA/Hibernate for persistence.

Originally posted by Andy Gibson:
We have looked at containing the ORM object as a property of the bean, (i.e. Person object) and using #{MyBean.Person.FirstName} within the JSP page to get the value into the web page. The problem is that when the bean is rebuilt from the client page, the only values populated are those that were on the page and results in an generally unknown state of the MyBean.Person object since it could only partially be filled in.
In order to complete the person object, we need to either ensure every property is in the JSF page, or manually reload it and then have JSF overlay the new values on the freshly loaded object.



Why is MyBean.Person is in an unknown state? If you perform an edit, you first do a load, and whatever changes you make to it will get updated in the underlying data store when the changes are finally flushed. You wouldn't use JSF to overlay the new values, but instead you use Hibernate's Session or JPA's EntityManager merge() to update the new values. It's pretty straightforward for an add. In each case, you know the state of your Person object.


The other method, and this seems to be more straightforward, and less fraught with danger, is to have each field of data that is present on the page as a property of the bean, (i.e. #{MyBean.FirstName} ) and when first creating the bean or saving date from the bean, we manually read/write the properties from/back to the domain object. This is kind of like a facade for the data contained within the bean.


This is analogous to using Data Transfer Objects (DTO), which increases lines of code, and maintenance effort. It just makes a lot more sense to use entities as backing beans themselves.


Both methods result in 2 fetches of the object from the DB. Once when you initally create the edit page, and send the values to the client. The other when the client sends the edits back, and they need to be applied to the domain object.


Well if it's just add, then only 1 DB access. If it's an edit, then there's 2 DB accesses: first for initial load, second for update.


Of course, you could put the object into the session, but it seems from my limited experience that this would be bad practice from the point of view of making an application stateless, and not requiring the users session take up gobs of objects just to perform basic edit functions.


Yes, it is a bad practice to rely on session, at least for your particular use case.
 
Andy Gibson
Greenhorn
Posts: 10
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Originally posted by Hung Tang:
How about JSF -> JPA -> DB? Yes, it's possible. Take a look at Seam. That's the "glue" you are looking for. Mind you, it takes a little investigation, but once you get it, I think it provides the answer you are looking for.

I have given an example using Seam showing this "glue" in action at http://jroller.com/page/hstang?entry=seamless_transition

Hung



Hey Hung,

I am about to start taking a look at Seam. My initial concern was that it was so bound to JBoss, and we were originally considering going a spring route.

I see how you split the data and the actions into separate beans, thats something to bear in mind.

Regarding your blog post about people knocking JSF a lot, I know what you mean. As a fair newbie to the issues, it seems to me that JSF is the option that should be best choice given that it is a standard, it is widely expandable in different areas, it is component based, and it's architecture with renderkits and so on may even make it platform agnostic. While it may appear to be the right choice, there are a number of problems with it which often makes us think twice about using it which is a shame. However, when looking at something like stripes and JSF, it seems like (from my simplistic POV) that the slight amount of extra work to use JSF might be worth the fact that we are buying into a standardized technology which offers the ability to grow and expand, and not being locked into a proprietary framework.
[ January 06, 2007: Message edited by: Andy Gibson ]
 
Andy Gibson
Greenhorn
Posts: 10
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Originally posted by Hung Tang:
I'll add some of my thoughts. My assumption is that you are using EJB3 Entity/JPA/Hibernate for persistence.
...
Why is MyBean.Person is in an unknown state? If you perform an edit, you first do a load, and whatever changes you make to it will get updated in the underlying data store when the changes are finally flushed. You wouldn't use JSF to overlay the new values, but instead you use Hibernate's Session or JPA's EntityManager merge() to update the new values. It's pretty straightforward for an add. In each case, you know the state of your Person object.



Well, if you do an edit, load the person, display half of it in the JSF page and post the values back on submit, on the postback, the only values that are posted back are the ones on the form. If I am only posting back half the properties, the other half will be unknown unless I re-load the person on postback. What I'm getting at is that the whole state of the Person object is not automagically restored into the backing bean on postback. It is restored from the page which may contain only half the values. We did discover this in testing when object properties which were not put on the JSF page were being updated to null when we saved the object after editing.

This is analogous to using Data Transfer Objects (DTO), which increases lines of code, and maintenance effort. It just makes a lot more sense to use entities as backing beans themselves.



Agreed, especially since I saw you splitting out the data and action methods into two beans, one could be an entity bean. I have never seen that practice before since most articles focus on nothing more than having an action and a property in a backing bean that can be linked to a web page.

However, the problem of incomplete data still applies with an entity backing bean. I might put Person.FirstName and Person.LastName, into the JSF page, then when the page is posted back, and the bean rebuilt, those two properties will be posted back, but if I have a non-visible Person.ArchiveDate that is not on the JSF page, that will not be posted back from the page and therefore will be NULL in the backing bean. In order to properly rebuild the backing bean, I will have to reload it from the database on postback to ensure those properties will have values.

The other advantage of DTO is that it does offer uber-data hiding. For example, a 'DateOfLastOrder' could be determined from a calculation (based on the Persons list of orders) or a property of the Person object. With DTO, I just have a MyBean.DateOfLastOrder which is determined from the correct source. We can change whether it is calculated, or stored in the person in the bean without needing to change the JSP page to get it from the right source.
[ January 06, 2007: Message edited by: Andy Gibson ]
 
Hung Tang
Ranch Hand
Posts: 148
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Originally posted by Andy Gibson:
However, the problem of incomplete data still applies with an entity backing bean. I might put Person.FirstName and Person.LastName, into the JSF page, then when the page is posted back, and the bean rebuilt, those two properties will be posted back, but if I have a non-visible Person.ArchiveDate that is not on the JSF page, that will not be posted back from the page and therefore will be NULL in the backing bean. In order to properly rebuild the backing bean, I will have to reload it from the database on postback to ensure those properties will have values.


The backing bean IS the entity bean. So if you load a Person entity, despite your choice of not displaying a visible Person.ArchiveDate modification, the bean itself stills holds a value for Person.ArchiveDate due to the load, and not NULL as you claim. Am I missing something? In the example I posted, if I took out the option to edit the "website" of a user, everything will still work.


The other advantage of DTO is that it does offer uber-data hiding. For example, a 'DateOfLastOrder' could be determined from a calculation (based on the Persons list of orders) or a property of the Person object. With DTO, I just have a MyBean.DateOfLastOrder which is determined from the correct source. We can change whether it is calculated, or stored in the person in the bean without needing to change the JSP page to get it from the right source.


You could use a JSF converter to encapsulate that kind of business logic, and transfer from/to your entity. I have used DTOs in the past, and just found them rather boring, and adds so much more code to the project.
 
Hung Tang
Ranch Hand
Posts: 148
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Originally posted by Andy Gibson:
Hey Hung,

I am about to start taking a look at Seam. My initial concern was that it was so bound to JBoss, and we were originally considering going a spring route.


Andy,

I understand your concerns about JBoss. Took me quite awhile before delving into Seam. However, Seam supports Tomcat, and Glassfish out-of-the-box, and I have been using it with Tomcat for development as I have yet gone to the EJB3 route. As for Spring support, you'll be happy to hear that in the very near future, they will be adding full support for Spring integration.
 
Andy Gibson
Greenhorn
Posts: 10
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Originally posted by Hung Tang:

The backing bean IS the entity bean. So if you load a Person entity, despite your choice of not displaying a visible Person.ArchiveDate modification, the bean itself stills holds a value for Person.ArchiveDate due to the load, and not NULL as you claim. Am I missing something? In the example I posted, if I took out the option to edit the "website" of a user, everything will still work.



I'm assuming you are using a non-Seam solution with a bean which has a request scope and is therefore recreated per request.
The load takes place on the initial edit stage. When the values are posted back, the bean is recreated as an empty bean (no values), and the values are loaded from the JSF view. Unless you re-load the entity bean before the values are written back, the ArchiveDate in this case will be null since the bean that was created initially for editing is not the same one the update is applied to. Only if you re-load the entity bean before loading the values from the view will the value be set.

The solution I found that works is to reload the entity when the view is restored and the new values are placed over the reloaded values. Our DBA didn't like the idea of 2 fetches (once for initial display and edit, and one for getting the object back prior to update). It seems that there is no way around this without storing the object in a session.
However, it seems like Seam is able to hold objects over across requests (i.e. across the conversation) without making it a session object which sounds great.

DTO's do seem a lot of work, especially duplicating all fields, but it does seem to avoid a number of issues I'm encountering with regards to Domain objects, when to load them etc..

I do have a JSF book which I'm reading my way through, but that too has so far assumed that a JSF backing bean encapsulates all the data, and actions, and UIComponent bindings, and doesn't include any kind of solution for using Domain objects.
 
Andy Gibson
Greenhorn
Posts: 10
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Originally posted by Hung Tang:

Andy,

I understand your concerns about JBoss. Took me quite awhile before delving into Seam. However, Seam supports Tomcat, and Glassfish out-of-the-box, and I have been using it with Tomcat for development as I have yet gone to the EJB3 route. As for Spring support, you'll be happy to hear that in the very near future, they will be adding full support for Spring integration.



Yes, you're right, I do remember reading about that. I too have yet to delve into the EJB side. I'm still just getting to grips with Spring and JSF. I seem to recall a lot of fighting words between the JBoss/Seam/ guys and the spring guys so I'm hoping that it's not going to interfere too much with it.
We are still contemplating our platform and tool options so we are pretty much open to anything.

I think part of the problem is the annoying fact that web development is so much messier than desktop apps where I can create a person object that is going to stick around and be available to any code until I free it up. Going from that to a stateless development platform is quite a head spinner.

Thanks again for your replies,

Andy
 
Hung Tang
Ranch Hand
Posts: 148
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Originally posted by Andy Gibson:

I'm assuming you are using a non-Seam solution with a bean which has a request scope and is therefore recreated per request.


Okay, now I kind of get what's the problem. Yes, Seam does solve this problem quite elegantly using conversations. If you are using MyFaces, there's a Tomahawk component called saveState that will be of interest to you:
http://myfaces.apache.org/tomahawk/uiSaveState.html

The user object will be saved/restored for longer than a request.
 
Andy Gibson
Greenhorn
Posts: 10
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Originally posted by Hung Tang:

Okay, now I kind of get what's the problem. Yes, Seam does solve this problem quite elegantly using conversations. If you are using MyFaces, there's a Tomahawk component called saveState that will be of interest to you:
http://myfaces.apache.org/tomahawk/uiSaveState.html

The user object will be saved/restored for longer than a request.



Thanks Hung, yes, this was the problem we were/are facing. Managing domain objects across multiple stateless requests, especially given that JSF would attempt to rebuild the model (including domain objects) from the request, and we could end up with partially filled domain objects putting them in a vague state.

Regarding save state, we are kind of cautious about using something that dumps state to the client, especially if it saves collections within the bean recursively, and we could end up having to transport large amounts of state information across the network.

I'm still in favour of reading the entity bean twice, once for edit and once for update since it provides simple stateless operation without worrying about sending state to the client.

I'll be taking a look at seam this week, especially at how it manages objects across requests in a distributed environment where the same machine might not be used for the two requests.

I should also note that this problem with MVC Model and Domain Model usage is not just a JSF issue, but it is also present in other MVC frameworks (Asp.Net included). It just seems like JSF is more suited to solve the problem more elegantly, especially if it involves an expansion to JSF like Seam.

Thanks again,

Andy
[ January 07, 2007: Message edited by: Andy Gibson ]
 
If you try to please everybody, your progress is limited by the noisiest fool. And this tiny ad:
a bit of art, as a gift, the permaculture playing cards
https://gardener-gift.com
reply
    Bookmark Topic Watch Topic
  • New Topic