Discussions
Categories
- 385.5K All Categories
- 5.1K Data
- 2.5K Big Data Appliance
- 2.5K Data Science
- 453.4K Databases
- 223.2K General Database Discussions
- 3.8K Java and JavaScript in the Database
- 47 Multilingual Engine
- 606 MySQL Community Space
- 486 NoSQL Database
- 7.9K Oracle Database Express Edition (XE)
- 3.2K ORDS, SODA & JSON in the Database
- 585 SQLcl
- 4K SQL Developer Data Modeler
- 188K SQL & PL/SQL
- 21.5K SQL Developer
- 46 Data Integration
- 46 GoldenGate
- 298.4K Development
- 4 Application Development
- 20 Developer Projects
- 166 Programming Languages
- 295K Development Tools
- 150 DevOps
- 3.1K QA/Testing
- 646.7K Java
- 37 Java Learning Subscription
- 37.1K Database Connectivity
- 201 Java Community Process
- 108 Java 25
- 22.2K Java APIs
- 138.3K Java Development Tools
- 165.4K Java EE (Java Enterprise Edition)
- 22 Java Essentials
- 176 Java 8 Questions
- 86K Java Programming
- 82 Java Puzzle Ball
- 65.1K New To Java
- 1.7K Training / Learning / Certification
- 13.8K Java HotSpot Virtual Machine
- 94.3K Java SE
- 13.8K Java Security
- 208 Java User Groups
- 25 JavaScript - Nashorn
- Programs
- 667 LiveLabs
- 41 Workshops
- 10.3K Software
- 6.7K Berkeley DB Family
- 3.6K JHeadstart
- 6K Other Languages
- 2.3K Chinese
- 207 Deutsche Oracle Community
- 1.1K Español
- 1.9K Japanese
- 474 Portuguese
UI Component (h:selectOneMenu) showing old value not matching backing bean

jmsjr
Member Posts: 93
Mojarra 2.1.7-jbossorg-1
I'm out of my wits trying to figure out what is going on here.
I have broken down the problem that I am seeing to something smaller test case that is easily reproducable.
Two <h:selectOneRadio> ( Approved and Notified )
One <h:selectOneMenu> wrapped in a <h:panelGroup>
One <h:commandButton>
The list of contents of the <h:selectOneMenu> is dependent on the value of the "Approved" <h:selectOneRadio>, and the list is obtained from the viewBean.
Apart from the "required" attribute, the only other validation is a validator method in the bean that:
If "Approved" radio button is Yes, and "Notified" radio button is No, then a ValidatorException is thrown and is shown on the <h:messages>
Now the issue:
1) Select Approved "Yes"
2) Select Notified "No"
3) Select dropdown to PEND
4) Select Submit button
5) <h:messages> show "Notified must be true when action is PEND". All good.
6) Change Approved to "No" ... Note that there is a listener on change of Approved ... and the listener will always set the value of the dropdown to null.
Because I changed the value of the Approved radio button, the dropdown selection is then changed to the "- Select- " item, which is what I am expecting as that is what the listener method does ... and the dropdown is re-rendered.
7) Change Approved back to "Yes" ... dropdown changes back to PEND ... This is what I do not understand.
Why was it being changed back to PEND when:
A) The listener on the Approved radio button always sets the value of the dropdown to null in the backend.. and
The Approved render attribute always re-render the dropdown
???
I'm out of my wits trying to figure out what is going on here.
I have broken down the problem that I am seeing to something smaller test case that is easily reproducable.
Two <h:selectOneRadio> ( Approved and Notified )
One <h:selectOneMenu> wrapped in a <h:panelGroup>
One <h:commandButton>
The list of contents of the <h:selectOneMenu> is dependent on the value of the "Approved" <h:selectOneRadio>, and the list is obtained from the viewBean.
Apart from the "required" attribute, the only other validation is a validator method in the bean that:
If "Approved" radio button is Yes, and "Notified" radio button is No, then a ValidatorException is thrown and is shown on the <h:messages>
Now the issue:
1) Select Approved "Yes"
2) Select Notified "No"
3) Select dropdown to PEND
4) Select Submit button
5) <h:messages> show "Notified must be true when action is PEND". All good.
6) Change Approved to "No" ... Note that there is a listener on change of Approved ... and the listener will always set the value of the dropdown to null.
Because I changed the value of the Approved radio button, the dropdown selection is then changed to the "- Select- " item, which is what I am expecting as that is what the listener method does ... and the dropdown is re-rendered.
7) Change Approved back to "Yes" ... dropdown changes back to PEND ... This is what I do not understand.
Why was it being changed back to PEND when:
A) The listener on the Approved radio button always sets the value of the dropdown to null in the backend.. and

???
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core" xmlns:ui="http://java.sun.com/jsf/facelets"> <h:head></h:head> <body> <h:form> <h:outputLabel value="Approved:"/> <h:selectOneRadio id="approved" value="#{viewBean.approved}" required="true" requiredMessage="Approved is required."> <f:selectItem itemValue="true" itemLabel="Yes"/> <f:selectItem itemValue="false" itemLabel="No"/> <f:ajax event="valueChange" execute="@this" render="nextActionPanel" listener="#{viewBean.triggerApprovedChange()}"/> </h:selectOneRadio> <h:outputLabel value="Notified:"/> <h:selectOneRadio id="notified" value="#{viewBean.notified}" required="true" requiredMessage="Notified is required." validator="#{viewBean.validateNotified}"> <f:selectItem itemValue="true" itemLabel="Yes"/> <f:selectItem itemValue="false" itemLabel="No"/> <f:ajax event="valueChange" execute="@this" render="@none"/> </h:selectOneRadio> <h:panelGroup id="nextActionPanel"> <h:selectOneMenu id="nextAction" required="true" requiredMessage="Next Action is required." value="#{viewBean.nextAction}"> <f:selectItem itemValue="" itemLabel="- Select -" /> <f:selectItems value="#{viewBean.availableNextActions}" var="target" itemValue="#{target.value}" itemLabel="#{target.label}"/> <f:ajax event="valueChange" execute="@this" render="@none"/> </h:selectOneMenu> </h:panelGroup> <h:commandButton id="submit" value="Submit"/><br/> <h:messages/> </h:form> </body> </html>
package test; import java.io.Serializable; import java.util.ArrayList; import java.util.List; import javax.annotation.PostConstruct; import javax.faces.application.FacesMessage; import javax.faces.bean.ManagedBean; import javax.faces.bean.ViewScoped; import javax.faces.component.UIComponent; import javax.faces.context.FacesContext; import javax.faces.validator.ValidatorException; @ManagedBean @ViewScoped public class ViewBean implements Serializable { private static final long serialVersionUID = 1L; private Boolean approved; private Boolean notified; private String nextAction; private List<NextAction> availableNextActions; public Boolean getApproved() { return approved; } public void setApproved(Boolean selection) { this.approved = selection; } public Boolean getNotified() { return notified; } public void setNotified(Boolean selection2) { this.notified = selection2; } public String getNextAction() { return nextAction; } public void setNextAction(String nextAction) { this.nextAction = nextAction; } public void triggerApprovedChange() { changeAvailableNextActions(); setNextAction(null); } public List<NextAction> getAvailableNextActions() { return availableNextActions; } private void setAvailableNextActions(List<NextAction> availableNextActions) { this.availableNextActions = availableNextActions; } public void changeAvailableNextActions() { List<NextAction> nextActions = new ArrayList<NextAction>(); if( Boolean.TRUE.equals( getApproved() )) { nextActions.add( new NextAction("PEND", "Pend")); } nextActions.add( new NextAction("REQADVICE", "Request Advice")); nextActions.add( new NextAction("FIN", "Finish")); setAvailableNextActions(nextActions); } @PostConstruct public void init() { changeAvailableNextActions(); } public void validateNotified( FacesContext context, UIComponent toValidate, Object value) throws Exception { List<FacesMessage> messages = new ArrayList<FacesMessage>(); Boolean isNotified = (Boolean) value; if( Boolean.FALSE.equals( isNotified ) && "PEND".equals( nextAction )) { FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR, "Notified must be true when action is PEND", null); messages.add( message ); } if( messages.size() > 0 ) { throw new ValidatorException(messages); } } public class NextAction implements Serializable { private static final long serialVersionUID = 1L; private String label; private String value; public NextAction(String aValue, String aLabel) { value = aValue; label = aLabel; } public String getLabel() { return label; } public String getValue() { return value; } } }
Answers
-
ViewScoped beans have pitfalls where they start behaving as request scoped beans but I don't see any code that would cause that. Is the current behavior what you would expect if the bean were request scoped?
-
By adding <ui:debug/> ... and doing Ctrl+Shift+D after step [6] but before step [7], the viewState shows that the value of the <h:selectOneMenu> is STILL PEND.
<HtmlSelectOneMenu disabled="false" id="nextAction" immediate="false" inView="true" localValueSet="true" readonly="false" rendered="true" required="true" requiredMessage="Next Action is required." transient="false" valid="true" value="PEND">
But the question is ... why ???
1) The value for the dropdown on the bean has been changed to null ( via the method on the listener attribute of the h:selectOneRadio) ... and ...
2) The h:selectOneMenu has been re-rendered.
Edited by: jmsjr on 29-May-2013 23:51 -
r035198x wrote:Most of the viewscoped issues have been resolved actually, but this is quite an old version of JSF which will still have some of them.
ViewScoped beans have pitfalls where they start behaving as request scoped beans but I don't see any code that would cause that. Is the current behavior what you would expect if the bean were request scoped?
OP: You might want to consider trying upgrading JSF to a more recent version, if only to see if that changes anything in the behavior. If it does it is quite futile to keep trying to make your current code work and you'd perhaps need to drop the usage of viewscoped. You -should- be able to just deploy a newer JSF with your application and that should then be used in stead of the server default. -
gimbal2 wrote:I just tried it now with 2.1.11-jbossorg-3 ( that comes with JBoss 7.1.3 ) ... same problem.r035198x wrote:Most of the viewscoped issues have been resolved actually, but this is quite an old version of JSF which will still have some of them.
ViewScoped beans have pitfalls where they start behaving as request scoped beans but I don't see any code that would cause that. Is the current behavior what you would expect if the bean were request scoped?
OP: You might want to consider trying upgrading JSF to a more recent version, if only to see if that changes anything in the behavior. If it does it is quite futile to keep trying to make your current code work and you'd perhaps need to drop the usage of viewscoped. You -should- be able to just deploy a newer JSF with your application and that should then be used in stead of the server default.
Trying now with the latest 2.1.x mojarra implementation -
jmsjr wrote:Same problem with the latest Mojarra implementation 2.1.22 ( from https://javaserverfaces.java.net/nonav/2.1/download.html )gimbal2 wrote:I just tried it now with 2.1.11-jbossorg-3 ( that comes with JBoss 7.1.3 ) ... same problem.r035198x wrote:Most of the viewscoped issues have been resolved actually, but this is quite an old version of JSF which will still have some of them.
ViewScoped beans have pitfalls where they start behaving as request scoped beans but I don't see any code that would cause that. Is the current behavior what you would expect if the bean were request scoped?
OP: You might want to consider trying upgrading JSF to a more recent version, if only to see if that changes anything in the behavior. If it does it is quite futile to keep trying to make your current code work and you'd perhaps need to drop the usage of viewscoped. You -should- be able to just deploy a newer JSF with your application and that should then be used in stead of the server default.
Trying now with the latest 2.1.x mojarra implementationInitializing Mojarra 2.1.22 ( 20130508-2000 https://svn.java.net/svn/mojarra~svn/tags/[email protected])
Edited by: jmsjr on 30-May-2013 00:28 -
well, that at least gives some security that it is an issue in the usage of JSF and not a bug in the implementation.
Unfortunately these kind of problems stem from the fact that JSF is quite complex under the hood and the only real solution is to experiment and fiddle in my opinion. I tend to start to add System.out statements to the code, including in setters, to know what is executed where. I also add a phase listener to System.out when a phase starts and ends, to know what is changed in which life cycle phase. That usually gives a good enough picture to figure out where things are happening in the wrong order. -
gimbal2 wrote:Ok .. I am confused by what you just said .. as I did say that the same problem STILL exists in Mojarra 2.1.22.
well, that at least gives some security that it is an issue in the usage of JSF and not a bug in the implementation.
Unfortunately these kind of problems stem from the fact that JSF is quite complex under the hood and the only real solution is to experiment and fiddle in my opinion. I tend to start to add System.out statements to the code, including in setters, to know what is executed where. I also add a phase listener to System.out when a phase starts and ends, to know what is changed in which life cycle phase. That usually gives a good enough picture to figure out where things are happening in the wrong order.
ergo .. It is not an issue with the usage of JSF but appears to be a bug in the implementation.
The <ui:debug> shows that the value of the component is still showing the old value, not the value that I have in the backing bean ( which I was also debugging and can confirm that the getxxx() method is returning null instead of PEND ). -
It might be the same as this one:
https://java.net/jira/browse/JAVASERVERFACES-1974
... which is still open. -
jmsjr wrote:I meant a bug in the old version that JBoss ships with. But I also mean in general; as you can see JSF 2.x is already on release 22 - the chance of you finding such an easy to trigger bug has become relatively slim. So no, I must assume it is actually a problem with not understanding how JSF ticks properly. Which is understandable since after using it for 5 years it still surprises me occasionally.
Ok .. I am confused by what you just said .. as I did say that the same problem STILL exists in Mojarra 2.1.22.
ergo .. It is not an issue with the usage of JSF but appears to be a bug in the implementation.
The bug you link to is about values staying the same, not reverting back to a previous state. -
gimbal2 wrote:OK .. Maybe this will be more convincing (?). I change the xhtml so that it also displays ( via h:outputText ) .. the value of the backing bean that is the same value used for the h:selectOneMenu.jmsjr wrote:I meant a bug in the old version that JBoss ships with. But I also mean in general; as you can see JSF 2.x is already on release 22 - the chance of you finding such an easy to trigger bug has become relatively slim. So no, I must assume it is actually a problem with not understanding how JSF ticks properly. Which is understandable since after using it for 5 years it still surprises me occasionally.
Ok .. I am confused by what you just said .. as I did say that the same problem STILL exists in Mojarra 2.1.22.
ergo .. It is not an issue with the usage of JSF but appears to be a bug in the implementation.
The bug you link to is about values staying the same, not reverting back to a previous state.<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core" xmlns:ui="http://java.sun.com/jsf/facelets"> <h:head></h:head> <h:body> <h:form> <h:outputLabel value="Approved:"/> <h:selectOneRadio id="approved" value="#{viewBean.approved}" required="true" requiredMessage="Approved is required."> <f:selectItem itemValue="true" itemLabel="Yes"/> <f:selectItem itemValue="false" itemLabel="No"/> <f:ajax event="valueChange" execute="@this" render="nextActionPanel" listener="#{viewBean.triggerApprovedChange()}"/> </h:selectOneRadio> <h:outputLabel value="Notified:"/> <h:selectOneRadio id="notified" value="#{viewBean.notified}" required="true" requiredMessage="Notified is required." validator="#{viewBean.validateNotified}"> <f:selectItem itemValue="true" itemLabel="Yes"/> <f:selectItem itemValue="false" itemLabel="No"/> <f:ajax event="valueChange" execute="@this" render="@none"/> </h:selectOneRadio> <h:panelGroup id="nextActionPanel"> Backing Bean value for nextAction is '<h:outputText value="#{viewBean.nextAction}"/>'<br/> <h:selectOneMenu id="nextAction" required="true" requiredMessage="Next Action is required." value="#{viewBean.nextAction}"> <f:selectItem itemValue="" itemLabel="- Select -" /> <f:selectItems value="#{viewBean.availableNextActions}" var="target" itemValue="#{target.value}" itemLabel="#{target.label}"/> <f:ajax event="valueChange" execute="@this" render="nextActionPanel"/> </h:selectOneMenu> </h:panelGroup> <h:commandButton id="submit" value="Submit" render="@form"/><br/> <h:messages/> <ui:debug/> </h:form> </h:body> </html>
All I changed was
1) Added the following:Backing Bean value for nextAction is '<h:outputText value="#{viewBean.nextAction}"/>'<br/>
.. which is in the same panel ( <h:panelGroup id="nextActionPanel"> ) as the <h:selectOneMenu>
2) Changed the render attribute of the h:selectOneMenu so that instead of @none, it is now:<f:ajax event="valueChange" execute="@this" render="nextActionPanel"/>
3) Repeated the same steps as before ... and after step [6]:
3a) The h:outputText says:Backing Bean value for nextAction is ''
3b) But the h:selectOneMenu still has the PEND option selected.
This discussion has been closed.