Tosquesa do JSF!

Uma coisa que nunca gostei foi de selectOneMenu, segue embaixo um exemplo tosco, se alguem sabe como fazer diferente com mais eficiencia, posta aqui !

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<%@taglib uri="http://java.sun.com/jsf/html" prefix="h" %>

<%@taglib uri="http://richfaces.org/a4j" prefix="a4j" %>
<%@taglib uri="http://richfaces.org/rich" prefix="rich" %>


<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">

<script type="text/javascript" src="${pageContext.request.contextPath}/js/jquery.maskedinput-1.2.1.js"></script>

<link rel="stylesheet" type="text/css" href="${pageContext.request.contextPath}/css/estilos.css" />  



<title>Registrar Cliente</title>
</head>
<body>

<f:view>

<f:loadBundle basename="messages" var="msgs"  />

	<rich:tabPanel>	
	
		<rich:tab label="Cadastro de Clientes">

		<h:form id="formCliente" styleClass="global" >	
				
			<fieldset>
				<div>
					<h:messages id="MensagensGlobais" globalOnly="true" errorClass="errorMessage"
					 infoClass="successMessage" />
				</div>
				
				&lt;h2 class="h2"&gt;<font >&lt;h:outputText value="#{msgs['cliente.titulo']}" /&gt; </font>&lt;/h2&gt;
				<br />
				&lt;table&gt;
					&lt;h:inputHidden value="#{ClienteBean.cliente.id}" id="id_cliente" &gt;&lt;/h:inputHidden&gt;
									
					&lt;tr&gt;
						&lt;td class="td_titulo"&gt;&lt;h:outputLabel value="#{msgs['cliente.nome']}" for="nome" /&gt;&lt;/td&gt;
						&lt;td&gt;&lt;h:inputText id="nome" value="#{ClienteBean.cliente.nome}" required="true" maxlength="60"
							size="40" requiredMessage="Informe o seu nome" /&gt;
						&lt;/td&gt;
					&lt;/tr&gt;
				
					&lt;tr&gt;
						&lt;td class="td_titulo"&gt;&lt;h:outputLabel value="#{msgs['cliente.sobrenome']}" for="sobrenome" /&gt;&lt;/td&gt;
						&lt;td&gt;&lt;h:inputText id="sobrenome" value="#{ClienteBean.cliente.sobrenome}" required="true" maxlength="60"
							size="60" requiredMessage="Informe o seu sobrenome" /&gt;
						&lt;/td&gt;
					&lt;/tr&gt;
				
					&lt;tr&gt;
						&lt;td class="td_titulo"&gt;&lt;h:outputLabel value="#{msgs['cliente.CPF']}" for="cpf" /&gt;&lt;/td&gt;
						&lt;td&gt;
							&lt;h:inputText id="cpf" value="#{ClienteBean.cliente.cpf}" required="false" maxlength="14"
									size="14" &gt;
								&lt;rich:jQuery selector="#cpf" query="mask('999.999.999-99')" timing="onload" /&gt;						
							&lt;/h:inputText&gt;
						&lt;/td&gt;
					&lt;/tr&gt;
				
					&lt;tr&gt;
						&lt;td class="td_titulo"&gt;&lt;h:outputLabel value="#{msgs['cliente.RG']}" for="rg" /&gt;&lt;/td&gt;
						&lt;td&gt;&lt;h:inputText id="rg" value="#{ClienteBean.cliente.rg}" required="false" maxlength="13"
						 	 	size="20" &gt;
						 	 &lt;rich:jQuery selector="#rg" query="mask('999.999.999-9')" timing="onload" /&gt;			
						 	&lt;/h:inputText&gt;
						 &lt;/td&gt;
					 &lt;/tr&gt;
				
					&lt;tr&gt;
						&lt;td class="td_titulo"&gt;&lt;h:outputLabel value="#{msgs['cliente.dtnascimento']}" for="dataNascimento" /&gt;&lt;/td&gt;
						&lt;td&gt;
							&lt;rich:calendar id="dataNascimento" value="#{ClienteBean.cliente.dataNascimento}"
									required="false" datePattern="dd/MM/yyyy" &gt;
								&lt;f:convertDateTime pattern="dd/MM/yyyy"/&gt;
							&lt;/rich:calendar&gt;
							<br />&lt;h:message for="dataNascimento" styleClass="message" /&gt;
						&lt;/td&gt;
					&lt;/tr&gt;
				
					&lt;tr&gt;
						&lt;td class="td_titulo"&gt;&lt;h:outputLabel value="#{msgs['cliente.sexo']}" for="sexo" /&gt;&lt;/td&gt;
						&lt;td&gt;
							&lt;h:selectOneRadio id="sexo" value="#{ClienteBean.cliente.sexo}" required="true" 
								requiredMessage="Sexo é obrigatório" styleClass="radio"&gt;
								&lt;f:selectItems value="#{ClienteBean.opcoesSexo}" /&gt;
							&lt;/h:selectOneRadio&gt;
						&lt;/td&gt;
					&lt;/tr&gt;
					
					&lt;tr&gt;
						&lt;td class="td_titulo"&gt;&lt;h:outputLabel value="#{msgs['cliente.email']}" for="email" /&gt;&lt;/td&gt;
						&lt;td&gt;
							&lt;h:inputText id="email" value="#{ClienteBean.cliente.email}" required="false" maxlength="100"
								size="100" &gt;
							&lt;f:validator validatorId="jm.validator.email" /&gt;
							&lt;/h:inputText&gt;
							&lt;h:message for="email" styleClass="message" /&gt;
						&lt;/td&gt;
					&lt;/tr&gt;
					
					&lt;tr&gt;
						&lt;td class="td_titulo"&gt;&lt;h:outputLabel value="#{msgs['cliente.senha']}" for="senha" /&gt;&lt;/td&gt;
						&lt;td&gt;
							&lt;h:inputSecret id="senha" value="#{ClienteBean.cliente.senha}"  required="true" maxlength="6"
								size="6" requiredMessage="Senha é obrigatório"&gt;
								&lt;/h:inputSecret&gt;
								&lt;h:message for="senha" styleClass="message"&gt;&lt;/h:message&gt;
						&lt;/td&gt;
					&lt;/tr&gt;
					
					&lt;tr&gt;
						&lt;td class="td_titulo"&gt;&lt;h:outputLabel value="#{msgs['cliente.confirma_senha']}" for="senhaConfirma" /&gt;&lt;/td&gt;
						&lt;td&gt;&lt;h:inputSecret id="senhaConfirma" value="#{ClienteBean.senhaConfirma}" required="true" maxlength="6"
							size="6" requiredMessage="Confirme a senha" /&gt; 
						&lt;/td&gt;
					&lt;/tr&gt;
					
					&lt;tr&gt;
						&lt;td class="td_titulo"&gt;&lt;h:outputLabel value="#{msgs['cliente.telefone']}" for="telefone" /&gt; &lt;/td&gt;
						&lt;td&gt;
							&lt;h:inputText id="telefone" value="#{ClienteBean.cliente.telefone}" required="false"
									maxlength="14" size="14" &gt;
								&lt;rich:jQuery selector="#telefone" query="mask('(999)9999-9999')" timing="onload" /&gt;
							&lt;/h:inputText&gt;
						&lt;/td&gt;
					&lt;/tr&gt;
					
					&lt;tr&gt;
						&lt;td class="td_titulo"&gt;&lt;h:outputLabel value="#{msgs['cliente.celular']}" for="celular" /&gt; &lt;/td&gt;
						&lt;td&gt;
							&lt;h:inputText id="celular" value="#{ClienteBean.cliente.celular}" required="false"
									maxlength="14" size="14" &gt;
								&lt;rich:jQuery selector="#celular" query="mask('(999)9999-9999')" timing="onload" /&gt;
							&lt;/h:inputText&gt;
						&lt;/td&gt;
					&lt;/tr&gt;
					
				&lt;/table&gt;
				
				&lt;h2 class="h2"&gt;<font >&lt;h:outputText value="#{msgs['cliente.subtitulo']}" /&gt;</font>&lt;/h2&gt;
				<br />
					
				&lt;table&gt;
					&lt;tr&gt;
						&lt;td class="td_titulo"&gt;&lt;h:outputLabel value="#{msgs['cliente.estado']}" for="uf" /&gt;&lt;/td&gt;
						&lt;td&gt;
							&lt;h:selectOneMenu id="uf" value="#{ClienteBean.cliente.unidadeFederativa}" required="true" 
								immediate="true" requiredMessage="Informe o estado do seu endereço" rendered="true"&gt;
									&lt;f:selectItem itemLabel="-- Selecione um --" /&gt;
									&lt;f:selectItems value="#{ClienteBean.unidadesFederativas}" /&gt;
									
									&lt;a4j:support event="onchange" ajaxSingle="true" reRender="uf,municipio" 
										actionListener="#{ClienteBean.atualizaMunicipio}" /&gt;
																						
							&lt;/h:selectOneMenu&gt;				
							&lt;h:message for="uf" styleClass="uf" /&gt;
						&lt;/td&gt;
					&lt;/tr&gt;
					
					&lt;tr&gt;
						&lt;td class="td_titulo"&gt;&lt;h:outputLabel value="#{msgs['cliente.municipio']}" for="municipio" /&gt; &lt;/td&gt;
						&lt;td&gt;
							&lt;h:selectOneMenu id="municipio" value="#{ClienteBean.cliente.municipio}" required="true"
								immediate="true" requiredMessage="Informe o municipio do seu endereço" rendered="true" &gt;
								&lt;f:selectItem itemLabel="-- Selecione um --" /&gt;
								&lt;f:selectItems value="#{ClienteBean.municipios}" /&gt;					
							&lt;/h:selectOneMenu&gt;
						&lt;/td&gt;
					&lt;/tr&gt;
					
					&lt;tr&gt;
						&lt;td class="td_titulo"&gt;&lt;h:outputLabel value="#{msgs['cliente.endereco']}" for="endereco" /&gt; &lt;/td&gt;
						&lt;td&gt;
							&lt;h:inputText id="endereco" value="#{ClienteBean.cliente.endereco}" required="true"
								maxlength="60" size="60" requiredMessage="O campo endereço é obrigatório" &gt;
							&lt;/h:inputText&gt;
						&lt;/td&gt;
					&lt;/tr&gt;
					
					&lt;tr&gt;
						&lt;td class="td_titulo"&gt;&lt;h:outputLabel value="#{msgs['cliente.numero']}" for="numero" &gt;&lt;/h:outputLabel&gt; &lt;/td&gt;
						&lt;td&gt;
							&lt;h:inputText id="numero" value="#{ClienteBean.cliente.numero}" required="false" 
								maxlength="30" size="10" &gt;
							&lt;/h:inputText&gt;
						&lt;/td&gt;
					&lt;/tr&gt;
					
					&lt;tr&gt;
						&lt;td class="td_titulo" &gt;&lt;h:outputLabel value="#{msgs['cliente.complemento']}" for="complemento" &gt;&lt;/h:outputLabel&gt; &lt;/td&gt;
						&lt;td&gt;
							&lt;h:inputText id="complemento" value="#{ClienteBean.cliente.complemento}" required="false"
								maxlength="10" size="10" &gt;
							&lt;/h:inputText&gt;
						&lt;/td&gt;
					&lt;/tr&gt;
					
					&lt;tr&gt;
						&lt;td class="td_titulo"&gt;&lt;h:outputLabel value="#{msgs['cliente.bairro']}" for="bairro" /&gt; &lt;/td&gt;
						&lt;td&gt;
							&lt;h:inputText id="bairro" value="#{ClienteBean.cliente.bairro}" required="true"
								maxlength="30" size="30" requiredMessage="O campo bairro é obrigatório" &gt;&lt;/h:inputText&gt;
						&lt;/td&gt;
					&lt;/tr&gt;
					
					&lt;tr&gt;
						&lt;td class="td_titulo"&gt;&lt;h:outputLabel value="#{msgs['cliente.referencia']}" for="referencial" /&gt; &lt;/td&gt;
						&lt;td&gt;
							&lt;h:inputText id="referencial" value="#{ClienteBean.cliente.referencial}" required="false" 
								maxlength="40" size="40"&gt;
							&lt;/h:inputText&gt;
						&lt;/td&gt;
					&lt;/tr&gt;
				
				&lt;/table&gt;
							
				&lt;h:commandButton value="Registrar" action="#{ClienteBean.registrar}" /&gt;
				&lt;h:commandButton value="Limpar" type="reset" /&gt;
				&lt;h:commandButton value="Cancelar" action="mostrar" immediate="true" /&gt;
								
			&lt;/fieldset&gt;
		&lt;/h:form&gt;
							
		&lt;/rich:tab&gt;	
			
	&lt;/rich:tabPanel&gt;

&lt;/f:view&gt;


&lt;/body&gt;

&lt;/html&gt;
package jm.livrosonline.bean;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
import javax.faces.component.UIParameter;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import javax.faces.event.ValueChangeEvent;
import javax.faces.model.SelectItem;

import jm.livrosonline.dao.Alias;
import jm.livrosonline.dao.impl.DAOImpl;
import jm.livrosonline.entidade.Cliente;
import jm.livrosonline.entidade.Municipio;
import jm.livrosonline.entidade.UnidadeFederativa;
import jm.livrosonline.enumerados.Sexo;
import jm.livrosonline.util.HibernateUtil;

import org.hibernate.Session;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Restrictions;

public class ClienteBean implements Serializable {
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	
	private List&lt;SelectItem&gt; municipios;	
	private List&lt;SelectItem&gt; unidadesFederativas;	
	private Cliente cliente = new Cliente();
	private List&lt;Cliente&gt; clientes = new ArrayList&lt;Cliente&gt;();
	private String senhaConfirma;
	
	private String  editId;
	
	public ClienteBean() {
		// TODO Auto-generated constructor stub
		
	}
	
	public void atualizaMunicipio( ValueChangeEvent vce ){
			try{
				cliente.setUnidadeFederativa( (UnidadeFederativa)vce.getNewValue() );			
				loadMunicipio( (UnidadeFederativa)vce.getNewValue() );
				
			}catch( Exception e ){
				municipios.clear();
				e.printStackTrace();
				System.out.println("Erro no método atualizaMunicipio do tipo: " + e.getMessage() );
				
			}
					
	}
	
	public String novo(){	
		this.cliente = new Cliente();
		
		return "novo";
		
	}
	
	public String registrar() {
		if ( ! senhaConfirma.equals( this.cliente.getSenha() ) ) {
			FacesMessage msg = 
				new FacesMessage( "A senha de confirmação informada não confere" );
			msg.setSeverity( FacesMessage.SEVERITY_ERROR );
			FacesContext.getCurrentInstance().addMessage( null, msg );
			return "erro";
			
		}
		Session session = HibernateUtil.getSession();
		DAOImpl&lt;Cliente&gt; daoCliente = new DAOImpl&lt;Cliente&gt;(session, Cliente.class);
			
		daoCliente.merge( this.cliente );
		
		this.cliente = new Cliente();
		
		this.municipios.clear();
					
		return "mostrar";
		
	}
	
	public ArrayList&lt;SelectItem&gt; getMunicipios() {
		if ( this.municipios == null && cliente.getUnidadeFederativa() != null ){
			loadMunicipio( cliente.getUnidadeFederativa() );
			
		}else if ( this.municipios == null ) {
			return new ArrayList&lt;SelectItem&gt;();
			
		}
		
		return (ArrayList&lt;SelectItem&gt;) this.municipios;
		
	}
	
	private void loadMunicipio( UnidadeFederativa uf ){
		this.municipios = new ArrayList&lt;SelectItem&gt;();
			
		Session session = HibernateUtil.getSession();				
		DAOImpl&lt;Municipio&gt; daoMunicipio = new DAOImpl&lt;Municipio&gt;( session, Municipio.class );
		
		List&lt;Criterion&gt; criteria = new ArrayList&lt;Criterion&gt;();
		List&lt;Alias&gt; aliases = new ArrayList&lt;Alias&gt;();
		
		criteria.add( Restrictions.eq("unidadeFederativa.id", uf.getId() ) );
		List&lt;Municipio&gt; entidade =  daoMunicipio.listar( aliases, criteria, "descricao", true ); 
			
		for (Municipio municipio : entidade) {
			this.municipios.add( new SelectItem( municipio, municipio.getDescricao() ) );
			
		}		
		
	}
	
	public List&lt;SelectItem&gt; getUnidadesFederativas(){
		if ( unidadesFederativas == null ) {
			unidadesFederativas = new ArrayList&lt;SelectItem&gt;();
			
			Session session = HibernateUtil.getSession();
			DAOImpl&lt;UnidadeFederativa&gt; daoUnidadeFederativa = new DAOImpl&lt;UnidadeFederativa&gt;(session, UnidadeFederativa.class);
			
			List&lt;UnidadeFederativa&gt; entidades = daoUnidadeFederativa.list(); 
		
			for (UnidadeFederativa unidadeFederativa : entidades) {
				unidadesFederativas.add( 
						new SelectItem( unidadeFederativa , unidadeFederativa.getDescricao() ) );
			}
			
		}
		
		return unidadesFederativas;
		
	}
	
	public String escolherCliente( ){		
		Session session = HibernateUtil.getSession();
		DAOImpl&lt;Cliente&gt; daoCliente = new DAOImpl&lt;Cliente&gt;(session, Cliente.class);	
		
		
		
		return "editar";
		
											
	}
	
	
		
	public void deletarCliente( ActionEvent event ){
		UIComponent link = event.getComponent();
		UIParameter param = (UIParameter) link.findComponent("deletId");	
		Long id = ( Long ) param.getValue();
		
		Session session = HibernateUtil.getSession();
		DAOImpl&lt;Cliente&gt; daoCliente = new DAOImpl&lt;Cliente&gt;( session, Cliente.class );		
		
		daoCliente.delete( daoCliente.load( id ) );
				
	}
	
	public List&lt;SelectItem&gt; getOpcoesSexo(){
		List&lt;SelectItem&gt; itens = new ArrayList&lt;SelectItem&gt;();
		itens.add( new SelectItem( Sexo.FEMININO.toString() , "Feminino" ) );
		itens.add( new SelectItem( Sexo.MASCULINO.toString() , "Masculino" ) );
		return itens;
		
	}
	

	public Cliente getCliente() {
		return cliente;
	}

	public void setCliente(Cliente cliente) {
		this.cliente = cliente;
	}

	public String getSenhaConfirma() {
		return senhaConfirma;
	}

	public void setSenhaConfirma(String senhaConfirma) {
		this.senhaConfirma = senhaConfirma;
	}
	
	public List&lt;Cliente&gt; getClientes() throws Exception {
		Session session = HibernateUtil.getSession();
		DAOImpl&lt;Cliente&gt; daoCliente = new DAOImpl&lt;Cliente&gt;( session, Cliente.class );
		
		List&lt;Criterion&gt; criteria = new ArrayList&lt;Criterion&gt;();
		List&lt;Alias&gt; aliases = new ArrayList&lt;Alias&gt;();
		
		criteria.add( Restrictions.ilike("nome", "", MatchMode.ANYWHERE ) );
		
		this.clientes = daoCliente.listar( aliases, criteria, "nome", true );
			
		return clientes;
		
	}

	public void setClientes(List&lt;Cliente&gt; clientes) {
		this.clientes = clientes;
	}

	public String getEditId() {
		return editId;
	}

	public void setEditId(String editId) {
		this.editId = editId;
	}


	
}