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.
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.
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
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.
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.
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 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.
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.
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.
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.
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.
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.
With a little knowledge, a cast iron skillet is non-stick and lasts a lifetime. |