There is no need for such a complicated approach what you try to achieve
is a state saving and scoping over the database.
MyFaces tomahawk has a x:saveState construct which first restores the
entire object and then sets the altered values.
No id nothing is needed once you have the data (which you obviously had
before otherwise your approach would not work.
As for the calling order, I had a similar problem recently, and I solved
it with the fact that the calling order basically is resembled by the
element order in the tree.
Which means if you have your document id on to with a hidden field the
setters and getters are called before the rest so you can use the
setters and getters of your controller bean for preinitialization.
That is very dirty however (I am not sure if this is a behavior working
over all implementations it works however on MyFaces)
The cleaner way would be to use a phase listener which gets the data
from the request and does some preinitialization or use something like
shale which sets clear interception points in the controller itself)
But as for your problem you probably can settle down to x:saveState
instead of having such a complicated construct where you try to achieve
a scoping via db surrogates and db state saving.
Werner
Adam Brod schrieb:
Hi-
I have run into a few problems moving from the struts way of thinking to
JSF. I'm hoping that the many smart people on this list have made that
jump. I'm stuck trying to design the most elegant way to implement a
piece of functionality I'll call Update Document. I would appreciate
it if anybody can help. I'm sure many people have run into a similar
design question.
Here are the relevant objects:
-Document (this is the domain object being updated)
-DocumentRepository (this is like a DAO object - it retrieves and
persists the Document)
-DocumentController (this is a POJO JSF-managed bean with /request/ scope)
-UpdateDocument.jsp (this is the JSF view that displays the Update
Document form)
Here are my constraints:
- My DocumentController (a managed bean) should not use any Faces/Http
objects. That is, no Request, no FacesContext, etc. All request
parameters should automatically map to objects
- I don't want to store anything in the session
- I want to write the least code possible (while still being manageable)
Here's what I would like to have happen (but can't figure out how to do
it):
1) On the Update Document page, the user update the document title and
clicks save
2) JSF instantiates a new documentController (request scope)
3) JSF passes the documentID to the controller
4) The documentController loads the Document from the DocumentRepository
5) JSF calls documentController.getDocument() and maps the values from
the Update Document form to the Document domain object
(e.g., h:inputText id=title
value=#{documentController.document.title}/)
What I like about my approach is that JSF just sets the values directly
on my domain object. I don't want to have to create a dummy FormBean
that JSF uses to set the parameters because then I would be forced to do
a second round of copying from the FormBean to the domain object. The
domain object is actually just an interface that only the repository can
instantiate.
My problem is that I can't ever get JSF to execute step 3 before step 5
gets called. I've tried using the updateActionListener, but that gets
invoked after the values are set. I've tried using a hidden parameter
to pass the documentID to the documentController, but that didn't seem
to work either. Below I've included a simplified DocumentController and
the Update Document form.
Does anybody have any advice??
Thanks,
Adam
public class DocumentController {
// if the documentID is set, this will load the Document from the
repository
public Document getDocument();
public void setDocumentID(long id);
// action method to save Document to the repositor
public String save();
}
This is what my UpdateDocument form looks like:
h:form id=updateDocument
h:panelGrid columns=2
h:column
h:outputLabel value=#{msgs.title} for=title /
/h:column
h:column
h:inputText id=title
value=#{documentController.document.title} required=true
f:validateLength minimum=3 maximum=25 /
/h:inputText
h:message for=title styleClass=errorMessage /
/h:column
h:column
h:outputLabel value=#{msgs.email} for=email /
/h:column
h:column
h:inputText id=email
value=#{documentController.document.email} required=true /
h:message for=email styleClass=errorMessage /
/h:column
/h:panelGrid
h:commandButton id=submit action=#{documentController.save}
value=#{msgs.enter} /
h:commandButton id=cancel