Binding kills backing beans...what am I doing wrong? - jsf

I have the following page:
<?xml version='1.0' encoding='UTF-8' ?>
<!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:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui"
xmlns:h="http://java.sun.com/jsf/html">
<body>
<ui:composition template="./templates/fireLeftMenuTemplate.xhtml">
<ui:define name="left">
<h:form>
<p:menu model="#{gradingBean.courseMenu}"/>
</h:form>
</ui:define>
<ui:define name="content">
<h:form>
<p:accordionPanel binding="#{gradingBean.assignmentView}"/>
</h:form>
</ui:define>
</ui:composition>
</body>
The GradingBean:
#Named("gradingBean")
#ViewScoped
public class GradingBean {
#EJB
private AssignmentManager assignmentManager;
/*
* The assignmentMenu, listing all assignments for each course currently
* assisted by this grader
*/
private final DefaultMenuModel courseView = new DefaultMenuModel();
private final AccordionPanel assignmentView = new AccordionPanel();
public GradingBean() {
FireLogger.logInfo("Created GradingBean for user {0}", FireUtil.getLoggedinUserEmail());
}
#PostConstruct
private void constructBean() {
constructAssignmentView();
constructCourseMenu();
FireLogger.logInfo("Constructed bean");
}
private void constructAssignmentView() {
Tab tab = new Tab();
tab.setTitle("Hello");
assignmentView.getChildren().add(tab);
assignmentView.setRendered(true);
FireLogger.logInfo("Constructed assignmentView");
}
private void constructCourseMenu() {
/*
* For now we default to just one course at a time, since we have not
* implemented support for multiple courses as of yet.
*/
Submenu defaultCourse = new Submenu();
defaultCourse.setLabel("Objekt Orienterad Programmering IT");
/*
* add each assignment associated with this course
*/
ExpressionFactory expressionFactory =
FacesContext.getCurrentInstance()
.getApplication()
.getExpressionFactory();
for (Assignment assignment : assignmentManager.getAll()) {
MenuItem menuItem = new MenuItem();
menuItem.setValue(assignment.getTitle());
MethodExpression expression = expressionFactory.createMethodExpression(
FacesContext.getCurrentInstance().getELContext(), "#{gradingBean.printstuff('yay!')}", String.class, new Class[0]);
menuItem.setActionExpression(expression);
defaultCourse.getChildren().add(menuItem);
}
courseView.addSubmenu(defaultCourse);
FireLogger.logInfo("Constructed courseMenu");
}
public String printstuff(String stuff) {
FireLogger.logInfo("Printing! " + stuff);
return "hej";
}
public DefaultMenuModel getCourseMenu() {
return courseView;
}
public AssignmentManager getAssignmentManager() {
return assignmentManager;
}
public DefaultMenuModel getCourseView() {
return courseView;
}
public AccordionPanel getAssignmentView() {
return assignmentView;
}
public void setAssignmentManager(AssignmentManager assignmentManager) {
this.assignmentManager = assignmentManager;
}
/**
* Custom menuitem for the purpose of storing associated assignments and
* information related to them.
*/
private class AssignmentMenuItem extends MenuItem {
private static final long serialVersionUID = 1L;
private Assignment assignment;
public AssignmentMenuItem(Assignment assignment) {
super();
this.assignment = assignment;
setValue(assignment.getTitle());
}
/**
* Convenience method
*
* #param component
*/
public void addChild(UIComponent component) {
getChildren().add(component);
}
}
}
Please do not mind the code quality, it is for debugging.
The problem is this: whenever I enable the accordionPanel tag on the xhtml page, all other beans associated with this page stop working: for example, clicking any of the menuitems on the courseView menu (which DOES work perfectly in the absence of the accordion), does nothing but to reload the page. The same goes for ALL other bean action bindings (including those generated in the header).
What am I missing here? As soon as I remove the accordionPanel tag, as mentioned, it works just fine. I am guessing it has something to do with the request cycle, but I am at a loss as to just what is going wrong.
EDIT:
Logging output for pressing the menuitems (which one does not matter) 2 times:
INFO: se.gu.fire.backend.GradingBean: Created GradingBean for user a#a.com
INFO: se.gu.fire.backend.GradingBean: Constructed assignmentView
INFO: se.gu.fire.backend.GradingBean: Constructed courseMenu
INFO: se.gu.fire.backend.GradingBean: Constructed bean
INFO: se.gu.fire.backend.GradingBean: Created GradingBean for user a#a.com
INFO: se.gu.fire.backend.GradingBean: Constructed assignmentView
INFO: se.gu.fire.backend.GradingBean: Constructed courseMenu
INFO: se.gu.fire.backend.GradingBean: Constructed bean
Notice how the cycle seems to get reset, and the bean reloaded whenever this happens...this happens for all other bindings to other beans on this page as well.

The code posted so far does not indicate that (using #Named #ViewScoped makes no sense), but the symptoms are recognizeable in case of using the binding attribute on a property of a fullworthy JSF view scoped managed bean (with #ManagedBean #ViewScoped).
The binding attribute is (like as id attribute and all taghandlers) evaluated during the view build time. The view is by default (with partial state saving enabled) built on every HTTP request. When the view is built, then the view scope is ready for use. View scoped managed beans are stored in there.
However, the view scope is by default not available during view build time. This means that any EL expression referencing a view scoped bean which is evaluated during building the view will create a brand new and completely separate instance of the view scoped bean, with all properties set to default. This is then reused instead.
This chicken-egg issue can be solved by using the binding attribute exclusively on request scoped beans, or to turn off partial state saving by setting the web.xml context parameter javax.faces.PARTIAL_STATE_SAVING to false. This has been reported as JSF issue 1492 and is fixed in the upcoming JSF 2.2.
See also:
#PostConstruct method is called even if the ManagedBean has already been instantiated (e.g. on AJAX-calls)
JSTL in JSF2 Facelets... makes sense?

Related

Panel update in PrimeFaces [duplicate]

This question already has an answer here:
Ajax update/render does not work on a component which has rendered attribute
(1 answer)
Closed 6 years ago.
I'm having a issue in PrimeFaces panel update.
I have one main panel which contains two output panel. Each output panel may contains one button which is swap panel. The swap panel button is used to swap the output panel from one to another.
If I update the button action for render the panels I need to provide the main panel Id it works fine. But for a tree structure hierarchy, If I mean to give the two output panel Ids It doesn't render the panel. The Button action called only once when I put the log to confirm that.
I will attach my code samples given below:
renderingPanel.XHTML
<!DOCTYPE html>
<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:p="http://primefaces.org/ui"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:c="http://java.sun.com/jsp/jstl/core">
<h:head>
<title>
Panel Rendered
</title>
</h:head>
<h:body>
<f:event listener="#{PanelRendered.initializePageAttributes}" type="preRenderComponent"/>
<h:form id="panelFormId">
<p:panel id="mainPanelId" widgetVar="mainPanelId">
<p:outputPanel id="mainOutputPanel" rendered="#{PanelRendered.mainPanelRendered}">
<h:outputText value="hello main"/>
<p:commandButton id="mainSwap" value="Swap To Sub Panel" update="mainOutputPanel,subOutputPanel" action="#{PanelRendered.mainButtonAction}" icon="ui-icon-transferthick-e-w"/>
</p:outputPanel>
<p:outputPanel id="subOutputPanel" rendered="#{PanelRendered.subPanelRendered}">
<h:outputText value="hello sub"/>
<p:commandButton id="subSwap" value="Swap To Main" update="subOutputPanel,mainOutputPanel" action="#{PanelRendered.subButtonAction}" icon="ui-icon-transferthick-e-w"/>
</p:outputPanel>
</p:panel>
</h:form>
</h:body>
</html>
PanelRendered.Java
public class PanelRendered
{
private boolean mainPanelRendered;
private boolean subPanelRendered;
private Logger logger = Logger.getLogger(PanelRendered.class);
public PanelRendered()
{
File configFile = new File("/home/nafeel/Applications/apache-tomcat-7.0.34/webapps/treetable/conf" + File.separator + "log4j.properties");
if (configFile.exists())
{
PropertyConfigurator.configure(configFile.getAbsolutePath());
}
else
{
System.out.println("Configuration Logger File not available");
}
}
public String mainButtonAction()
{
logger.info("Enter inside main button action");
mainPanelRendered = false;
subPanelRendered = true;
return null;
}
public String subButtonAction()
{
logger.info("Enter inside sub button action");
mainPanelRendered = true;
subPanelRendered = false;
return null;
}
public void initializePageAttributes()
{
logger.info("Enter inside initializepage");
mainPanelRendered = true;
subPanelRendered = false;
}
/**
* #return the mainPanelRendered
*/
public boolean isMainPanelRendered()
{
return mainPanelRendered;
}
/**
* #param mainPanelRendered the mainPanelRendered to set
*/
public void setMainPanelRendered(boolean mainPanelRendered)
{
this.mainPanelRendered = mainPanelRendered;
}
/**
* #return the subPanelRendered
*/
public boolean isSubPanelRendered()
{
return subPanelRendered;
}
/**
* #param subPanelRendered the subPanelRendered to set
*/
public void setSubPanelRendered(boolean subPanelRendered)
{
this.subPanelRendered = subPanelRendered;
}
}
Can you follow some guideline
JAVA code
Use proper naming for bean as your class name is PanelRendered and you are using the same name in xhtml file and you havent post your #ManagedBean #ViewScoped so i assume your bean name on xhtml should be panelRendered not PanelRendered.
Use #PostConstruct to initialize variable in JSF bean. avoid to use java constructor.
XHTML code:
I just change the bean name from PanelRendered to panelRendered and i am update panel like this update="mainPanelId"
And your code is working fine at my end, if you have any error please post here.
Your question
But for a tree structure hierarchy, If I mean to give the two output panel Ids It doesn't render the panel.
if the component with rendered="false" it is not generated any HTML code on browser, so you did not find the id="subOutputPanel" tag in your outputed HTML code, and when you click on command button it call the back bean method and come to update update="mainOutputPanel,subOutputPanel" it did not find the subOutputPanel id and ajax call will fail, and you will not get correct behavior or UI. and from next time it did not call any thing, for stop call back bean method you can study what happened after prime faces get ajax fail. hope this will help you.
I'm a bit of a n00b when it comes to JSF, but I have had similar issues. I think the Booleans in your PanelRendered class should have getters named as follows:
public boolean isMainPanelRendered()
public boolean isSubPanelRendered()
The expression language used in the XHTML file stays the same. It seems to be a convention that the expression language will add "is" to the front and capitalise the letter before searching the bean for the property(function or variable).
So this:
rendered="#{PanelRendered.mainPanelRendered}"
rendered="#{PanelRendered.subPanelRendered}"
stays the same.
Edited: added } at last of rendered.
Edited: realised it would need a getter for the private member variable

JSF access private/protected property of a super class

I am very new to JSF and this is the first project I work on (got a bit too lazy with jsp) so please forgive me if the question is trivial.
So I have a Super Class Device
#Entity
#Table(name = "Devices")
public class Device
{
protected bool Authorized
public bool isAuthorized()
{ return this.Authorized;}
public void setAuthorized(bool Authorized)
{ this.Authorized = Authorized;}
}
and a sub class SensorDevice that extends the Super Class Device
public class SensorDevice extends Device
{
// has its own properties which dont matter
}
and a Managed Bean UIDeviceManager
#ManagedBean(name = "DeviceManager")
#SessionScoped
public class UIDeviceManager
{
private List<SensorDevice> Pending;
// in constructor, Pending List gets populated with the devices requiring Authorization
}
and an xhtml page which contains a Table for the Pending Devices
<p:dataTable var="device" value="#{DeviceManager.pending}">
<p:column headerText="Device Authorization">
<h:form>
<p:inputSwitch
value="#{device.isAuthorized()}"
binding="#{AuthorizationInputSwitch}"
offLabel="UnAuthorized"
onLabel="Authorized">
<p:ajax
event="change"
listener="#{device.setAuthorized(AuthorizationInputSwitch.value)}" />
</p:inputSwitch>
</h:form>
</p:column>
Now unless the syntax in the xhtml is completely messed up (I tried my best there and would appreciate guidance), the function setAuthorized for that particular device instance should be called (even with the wrong input, but will sort that later by modifying the setter function), but that doesnt happen, the Ajax doesnt get called. Instead, the inputSwitch tries to update its "value property source" and attempts to look for a property isAuthorized() in the class SensorDevice which it fails to find.
Now I am aware that this could be easily solved by making the Boolean Authorized public in the super class but as you can see it is also a JPA entity that is persisted in a database to keep track of the devices, so the only option is to keep it protected.
So how do I update parameters of a Super class from a sub-class instance in a Managed Bean from a public function rather than direct access to the parameter itself (I thought JSF looked for the setters and getters but whatever)
Btw value="#{device.isAuthorized()}"works correctly but if I try the property directly it fails ( I guess its obvious at this point )
One last thing, if the approach/architecture is wrong, please advise on what is the correct layout to achieve this functionality. I am sure there is a standard way to integrate JSF and JPA without duplicating entities and wrappers
I think you must use field name in value attribute of InputSwitch component like this:
<p:inputSwitch
value="#{device.authorized}"
binding="#{AuthorizationInputSwitch}"
offLabel="UnAuthorized"
onLabel="Authorized">
Instead of:
<p:inputSwitch
value="#{device.isAuthorized()}"
binding="#{AuthorizationInputSwitch}"
offLabel="UnAuthorized"
onLabel="Authorized">
JSF will use isAuthorized and setAuthorized method (uses Java Beans standard convention to recognize getter and setter methods)
So i think you don't need the ajax part to call setter method.
To emphasize Mojtaba's answer, this is how you access properties in JSF:
Facelets page:
<?xml version='1.0' encoding='UTF-8' ?>
<!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">
<h:head>
<title>Facelet Title</title>
</h:head>
<h:body>
<h:outputText value="#{myBean.entity.someBool}"/>
</h:body>
</html>
Managed bean:
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
#ManagedBean
#SessionScoped
public class MyBean {
private SomeEntity entity = new SomeEntity();
public SomeEntity getEntity() {
return entity;
}
}
Entity classes:
public class SomeEntity extends SomeParent {
}
public class SomeParent {
private boolean someBool = true;
public boolean isSomeBool() {
return someBool;
}
public void setSomeBool(boolean someBool) {
this.someBool = someBool;
}
}
JSF doesn't know or care that your objects are JPA entities, and standard inheritance and access rules apply.
See also
JavaBean conventions

Composite component causes unique ID error when binding to view scoped bean

We are migrating a JSF 2.1 application, from JBoss AS 7.2 to Wildfly and thus JSF 2.2. The problem We're having is the following: We have a compositecomponent that is included in a #ViewScoped bean. The component has to retain its value through multiple requests, so a Request Scoped bean is not a solution.
The exception we're getting is a multiple component id one. After the request JSF starts to render the component for the second time, and fails.
I made a simple demo for this:
MyViewBean.java
#ViewScoped
#Named
public class MyViewBean implements Serializable {
private Component component;
public Component getComponent() {
return component;
}
public void setComponent(Component component) {
this.component = component;
}
public String increment(){
component.setCounter(component.getCounter()+1);
return "";
}
}
Component.java
#FacesComponent(value = "composite")
public class Component extends UINamingContainer {
private Integer counter = 0;
public Integer getCounter() {
return counter;
}
public void setCounter(Integer counter) {
this.counter = counter;
}
}
compositeTest.xhtml
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:h="http://xmlns.jcp.org/jsf/html"
template="/WEB-INF/templates/default.xhtml"
xmlns:pelda="http://xmlns.jcp.org/jsf/composite/component">
<ui:define name="content">
<h1>Composite component Test!</h1>
<h:form>
<pelda:composite binding="#{myViewBean.component}" />
<h:commandButton action="#{myViewBean.increment()}" value="Push me!"/>
</h:form>
</ui:define>
</ui:composition>
composite.xhtml
<cc:interface componentType="composite">
</cc:interface>
<cc:implementation>
<h:outputText id="id_hello" value="Helloka" />
<h:outputText id="id_counter" value="#{cc.counter}" />
</cc:implementation>
</html>
How to achieve that the counter can be incremented (with #RequestScoped bean it resets) and won't fail with idUniqueness error? We're using Mojarra 2.2.8 (Default in wildfly), also tried with Mojarra 2.2.12 (the latest as per writing this).
Thanks in advance!
UIComponent instances are inherently request scoped. You should never reference UIComponent instances beyond the request scope. Carefully read How does the 'binding' attribute work in JSF? When and how should it be used? for an elaborate explanation on that.
You only want to save its state in the JSF state via the inherited getStateHelper() method. This acts basically as the view scope.
#FacesComponent(value = "composite")
public class Component extends UINamingContainer {
public Integer getCounter() {
return (Integer) getStateHelper().eval("counter", 0);
}
public void setCounter(Integer counter) {
getStateHelper().put("counter", counter);
}
}
Don't forget to get rid of the binding attribute in the view.
See also:
How to save state when extending UIComponentBase

When using lazy dataTable another component does not get updated / 2nd component data is one request behind

I have a PrimeFaces p:dataTable and enabled lazy loading by implementing a LazyDataModel.
The dataTable holds search results, so when doing a search request the search service only retrieves the required (paginating) data. That works fine.
When doing a ajax request with p:commandButton:
<p:commandButton id="searchCmdBtn" value="Search" action="#{searchBean.search}"
update=":resultForm:resultList :filterForm:filterMenu :resultForm:messages"
ajax="true" />
the dataTable gets updated properly, but not the filterMenu in the filterForm (differnt forms, bcz using p:layout).
The filterMenu is one request behind. Which means when I hit search button again, the filterMenu gets updated with t only gets updated after the 2nd ajax request
Bean
#ManagedBean
#ViewScoped
public class SearchBean implements Serializable {
private LazyDataModel<Entity> lazyDataModel;
private MenuModel filterMenuModel = new DefaultMenuModel();
private SearchResult searchResult = null;
public void search() {
// lazy call
getLazyDataModel();
if (searchResult != null) {
buildFilterMenu(searchResult);
}
}
private void initializeDataModel() {
lazyDataModel = new LazyDataModel<Entity>() {
private static final long serialVersionUID = 1L;
#Override
public List<Entity> load(int first, int pageSize, List<SortMeta> multiSortMeta, Map<String, String> filters) {
// handling sorting and filtering
// get search results
try {
setSearchResult(searchService.getEntities(queryText, selectedQueryOperand, getFilterOptions(), first, (first + pageSize), multiSortMeta));
} catch (Exception e) {
// handle exception
}
if (searchResult == null) {
return null;
}
List<Entity> resultEntities = searchResult.getResultEntities();
// total count
this.setRowCount((int) searchResult.getTotalSize());
return resultEntities;
}
// other override-methods
};
}
public void buildFilterMenu() {
// builds the filterMenu depending on searchResults
}
// getters and setters
public LazyDataModel<Entity> getLazyDataModel() {
if (lazyDataModel == null) {
initializeDataModel();
}
return lazyDataModel;
}
}
filters.xhtml
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui"
xmlns:fn="http://java.sun.com/jsp/jstl/functions">
<p:panelMenu id="filterMenu" model="#{searchBean.filterMenuModel}" />
</ui:composition>
After searching the PF forum I found the root cause:
The dataTable Lazy load() method is invoked during render response phase
To know about the phases, read this tutorial on JSF lifecycle from BalusC
Solutions for displaying messages (e.g: p:messages or p:growl):
Update message component with PrimeFaces RequestContext
RequestContext.getCurrentInstance().update(":growlOrMsgID");
This will not work because at that time it's too late to add additional components to update.
use dataTable attribute errorMessage
No attribute found with this name for dataTable
Put the p:messages or p:growl below the p:dataTable
Worked for me
Use PF execute method of RequestContext
The RequestContext#execute() executes a javascript after current ajax request is completed.
Worked for me
See also:
Request update of component with ajax from LazyDataModel.load?
How to handle error in Primefaces lazy load?
PF Issue: DataTable with LazyDataModel updates model during render
http://itaffinity.wordpress.com/2013/06/08/jsf-displaying-facesmessages-during-render-response-phase/

valueChangeListener method is called on selectOneMenu even though I have not changed the value

I have the following problem. When I click the button "Enviar", this calls another method that is associated to a selectOneMenu (in the attribute
valueChangeListener called "validarSelect"), and later, calls the method that this button has associated in the attribute actionListener called "validarBoton".
I wonder, why this happens. I expect the valueChangeListener to be not called since I have not changed the dropdown.
This is my page JSF:
<?xml version='1.0' encoding='windows-1252'?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<f:view xmlns:f="http://java.sun.com/jsf/core" xmlns:h="http://java.sun.com/jsf/html">
<html xmlns="http://www.w3.org/1999/xhtml">
<h:head></h:head>
<h:body>
<h:form>
<h:commandButton value="Enviar..." id="validar" actionListener="#{Domiciliacion.validarBoton}"/>
<h:selectOneMenu valueChangeListener="#{Domiciliacion.validarSelect}"
binding="#{Domiciliacion.selectCombo}">
<f:selectItems value="#{Domiciliacion.lista}"/>
<f:ajax event="valueChange" render="#this"/>
</h:selectOneMenu>
</h:form>
</h:body>
</html>
And this, is the ManagedBean:
package domiciliaciontest;
import java.util.ArrayList;
import java.util.List;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.component.html.HtmlSelectOneMenu;
import javax.faces.event.ActionEvent;
import javax.faces.event.ValueChangeEvent;
#ManagedBean(name = "Domiciliacion")
#ViewScoped
public class MB0001 {
private HtmlSelectOneMenu selectCombo;
private List<String> lista = new ArrayList<String>();
public MB0001() {
super();
System.out.println("Entro al constructor...");
lista.add("Caracas");
lista.add("Bogota");
lista.add("Santiago");
}
public void validarBoton(ActionEvent actionEvent) {
System.out.println("Entro a validarBoton...");
// Add event code here...
}
public void validarSelect(ValueChangeEvent valueChangeEvent) {
// Add event code here...
System.out.println("Entro a validarSelect...");
}
public void setSelectCombo(HtmlSelectOneMenu selectCombo) {
this.selectCombo = selectCombo;
}
public HtmlSelectOneMenu getSelectCombo() {
return selectCombo;
}
public void setLista(List<String> lista) {
this.lista = lista;
}
public List<String> getLista() {
return lista;
}
}
this is the output when I click the button "Enviar":
Entro a validarSelect...
Entro a validarBoton...
The valueChangeListener method will be invoked when the submitted value is different from the initial value, regardless of whether you have changed it yourself or not. So, if the currently submitted value (which is "Caracas" in your case) is different from the initial value (which is null in your case), then the valueChangeListener method will be invoked.
See also:
When to use valueChangeListener or f:ajax listener?
Best way to add a "nothing selected" option to a selectOneMenu in JSF
Unrelated to the concrete problem, seeing this in combination with binding attribute gives me the impression that you're trying to achieve something which you've read in an article or answer targeted on JSF 1.x. This is namely recognizeable as part of a hack to populate child dropdowns in JSF 1.x. You do not need this approach for JSF 2.x. Further, your method names with "validar" ("validate") are misleading. Don't you actually need a fullworthy Validator? But as said, that's a different problem.
See also:
Make multiple dependent / cascading selectOneMenu dropdown lists in JSF

Resources