Skip to Main Content

Java EE (Java Enterprise Edition) General Discussion

Announcement

For appeals, questions and feedback about Oracle Forums, please email oracle-forums-moderators_us@oracle.com. Technical questions should be asked in the appropriate category. Thank you!

UI Component (h:selectOneMenu) showing old value not matching backing bean

jmsjrMay 30 2013 — edited Jun 2 2013
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
B) The Approved render attribute always re-render the dropdown
???
<!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;
		}
		
		
	}

}
Comments
Locked Post
New comments cannot be posted to this locked post.
Post Details
Locked on Jun 30 2013
Added on May 30 2013
28 comments
19,092 views