Here are a standard set of business requirements: "make a page to view the customer details", "make a page to update the customer details" and "make a page to create a customer".
I want forms that behave as the UI for all three contexts. Consequently, I have a lot markup that looks like this.
<h:panelGroup>
<h:inputText value="#{Backer.customer.name}"
rendered="#{Backer.updateMode or Backer.createMode}" />
<h:outputText value="#{Backer.customer.name}"
rendered="#{Backer.readMode}" />
</h:panelGroup>
Backer is a request scoped managed bean. Until recently, the value of mode was *transported* via a hidden field, *restored* in the constructor of the managed bean, and *changed* in an action. For example,
1.) user opts to edit a customer
2.) user changes the name of the Customer
3.) user clicks an update button
4.) JSF infrastructure creates the managed bean
5.) managed bean (in constructor) looks at request value MODE and determines it is in update mode
6.) the new customer name is applied to the model by JSF infrastructure
7.) action fires, where customer is persisted and managed bean taken out of update mode pending a successful transaction
The idea was similar to a Constructor Injection; the container doesn't pass a dependency as a constructor paramater to a the new managed bean, the managed bean figures this out itself just by looking at the request.
I chose to stop this for a couple of reasons. I wanted to remove all manual request parsing from the application; if possible, I wanted to remove all build dependencies on the servlet api. There's no reason, I thought, that 'mode' could not be managed entirely in actions (a user clicks on 'Edit', which fires an action that puts the managed bean in 'update mode').
However it appears as though now the request values of every form are simply not applied to the model because the UIComponents they belong to have valuebindings that no longer evaluate to true.
1.) user opts to edit a Customer
2.) user changes the name of the Customer
3.) user clicks update button
4.) JSF infrastructure creates the managed bean, managed bean no longer bothers to put itself in update mode.
5.) Backer.updateMode now returns false, so request values of tags w/ @rendered="#{Backer.updateMode}" are not applied to model.
6.) action is still fired, but huge explosion occurs when application tries to persist a blank model.
I have fixed this w/ <t:saveState value="#{Backer.mode}"/> , but only because Backer.setMode() is being called before all request values are applied. I am a bit uneasy about this until I find assurance that this will happen for every request for every form. What makes the value of t:saveState so special? Is there an algorithm used to determine the order in which values are applied?
I am also curious to find out if anyone has constructive criticism of this design.
Dennis Byrne
- Can t:saveState safely be used as a setter-style depende... Dennis_Byrne
- Re: Can t:saveState safely be used as a setter-styl... Mike Kienenberger

