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" action="cancel" value="#{msgs.cancel}" />
</h:form>


Reply via email to