Olá amigos, boa noite.
Estou com um problema representado da seguinte forma: Possuo um <p:datatable> do primefaces, onde é exibida uma lista de usuários. Nessas colunas da tabela possuo um commandLink para exibir item, alterar item e excluir item selecionado. Ao clicar em algum desses commandLinks, é exibido um <p:dialog> que exibe um painelGrid com os dados do usuário, como nome, telefone, etc.
Porém esses campos são de preenchimento obrigatório e possuem required=true. Se eu colocar a tag immediate=true nos commandLinks, ele chama o método responsável por carregar a lista de Perfis no meu managedBean, mas o usuarioSelecionado não é setado. Caso eu retire o immediate=true do commandLink, o método que carrega a lista de perfis no managed bean não é executado, pois os campos com required impede essa questão.
Abaixo o exibirUsuarios.xhtml que demonstra a situação: Não se preocupem com template que é utilizado nesse form.
<?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"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.prime.com.tr/ui">
<ui:composition template="/resources/template.xhtml">
<ui:define name="menu">
<ui:include src="/resources/menu.xhtml" />
</ui:define>
<ui:define name="css">
<link href="${facesContext.externalContext.requestContextPath}/css/dataTable.css" rel="stylesheet" type="text/css" />
</ui:define>
<ui:define name="javascript">
<script type="text/javascript">
function retornaEvento(args) {
if(!args.validationFailed) {
dlgMsg.show();
}
}
</script>
<script type="text/javascript" src="${facesContext.externalContext.requestContextPath}/js/jquery.maskedinput-1.2.2.js"></script>
<script type="text/javascript" src="${facesContext.externalContext.requestContextPath}/js/jquery-1.4.2.js"></script>
<script type="text/javascript" src="${facesContext.externalContext.requestContextPath}/js/funcoes.js"></script>
</ui:define>
<ui:define name="corpoDialog">
<p:panel id="pnlCentro">
<f:facet name="header">
<h:outputText value="#{msg['usuario.detalhe']}" styleClass="fonteTitulo" />
</f:facet>
<h:panelGrid id="pgrUsuario" columns="2">
<h:outputLabel value="#{msg['usuario.nome']}" />
<h:inputText id="iptNome" value="#{usuarioController.usuarioSelecionado.nmUsuario}" size="70" maxlength="100"
onkeyup="this.value = somenteCaracteres(this.value)" required="true"
requiredMessage="#{msg['usuario.nome.requerido']}" />
<h:inputHidden />
<h:message for="iptNome" styleClass="fonteAlerta" showDetail="true" showSummary="false" />
<h:outputLabel value="#{msg['usuario.rua']}" />
<h:inputText id="iptRua" value="#{usuarioController.usuarioSelecionado.dsRua}" size="70" maxlength="100"
onkeyup="this.value = somenteCaracteres(this.value)"
required="true" requiredMessage="#{msg['usuario.rua.requerido']}" />
<h:inputHidden />
<h:message for="iptRua" styleClass="fonteAlerta" showDetail="true" showSummary="false" />
<h:outputLabel value="#{msg['usuario.bairro']}" />
<h:inputText id="iptBairro" value="#{usuarioController.usuarioSelecionado.dsBairro}" size="51" maxlength="50"
onkeyup="this.value = somenteCaracteres(this.value)" required="true"
requiredMessage="#{msg['usuario.bairro.requerido']}" />
<h:inputHidden />
<h:message for="iptBairro" styleClass="fonteAlerta" showDetail="true" showSummary="false" />
<h:outputLabel value="#{msg['usuario.numero']}" />
<h:inputText id="iptNumero" value="#{usuarioController.usuarioSelecionado.nuLocal}" size="11" maxlength="10"
onkeypress="return somenteNumeros(event, false)" required="true"
requiredMessage="#{msg['usuario.numero.requerido']}" />
<h:inputHidden />
<h:message for="iptNumero" styleClass="fonteAlerta" showDetail="true" showSummary="false" />
<h:outputLabel value="#{msg['usuario.cidade']}" />
<h:inputText id="iptCidade" value="#{usuarioController.usuarioSelecionado.dsCidade}" size="51" maxlength="50"
onkeyup="this.value = somenteCaracteres(this.value)" required="true"
requiredMessage="#{msg['usuario.cidade.requerido']}" />
<h:inputHidden />
<h:message for="iptCidade" styleClass="fonteAlerta" showDetail="true" showSummary="false" />
<h:outputLabel value="#{msg['usuario.estado']}" />
<h:inputText id="iptEstado" value="#{usuarioController.usuarioSelecionado.dsEstado}" size="3" maxlength="2"
onkeyup="this.value = somenteCaracteres(this.value)" required="true"
requiredMessage="#{msg['usuario.estado.requerido']}" />
<h:inputHidden />
<h:message for="iptEstado" styleClass="fonteAlerta" showDetail="true" showSummary="false" />
<h:outputLabel value="#{msg['usuario.cep']}" />
<h:inputText value="#{usuarioController.usuarioSelecionado.nuCep}" size="9" maxlength="8" />
<h:outputLabel value="#{msg['usuario.login']}" />
<h:inputText id="iptLogin" value="#{usuarioController.usuarioSelecionado.dsLogin}" size="21" maxlength="20" required="true"
requiredMessage="#{msg['usuario.login.requerido']}" />
<h:inputHidden />
<h:message for="iptLogin" styleClass="fonteAlerta" showDetail="true" showSummary="false" />
<h:outputLabel value="#{msg['usuario.senha']}" />
<p:password id="pasSenha" value="#{usuarioController.usuarioSelecionado.dsSenha}" minLength="0" size="50" maxlength="20"
weakLabel="#{msg['usuario.senha.fraca']}" goodLabel="#{msg['usuario.senha.boa']}"
strongLabel="#{msg['usuario.senha.excelente']}" promptLabel="#{msg['usuario.senha.requerido']}"
required="true" requiredMessage="#{msg['usuario.senha.requerido']}" />
<h:inputHidden />
<h:message for="pasSenha" styleClass="fonteAlerta" showDetail="true" showSummary="false" />
<h:outputLabel value="#{msg['usuario.perfil']}" />
<h:selectOneMenu value="#{usuarioController.usuarioSelecionado.perfil}">
<f:converter converterId="perfilConverter" />
<f:selectItems value="#{usuarioController.listaPerfis}" var="perfil" itemLabel="#{perfil.nmPerfil}" itemValue="#{perfil}" />
</h:selectOneMenu>
</h:panelGrid>
<f:facet name="footer">
<h:commandButton value="#{msg['botao.fechar']}" styleClass="botoes" immediate="true" onclick="dlgConteudo.close();" />
<h:outputText value=" " />
<p:commandButton id="cbtIncluir" value="#{msg['botao.incluir']}" style="display: none;" styleClass="botoes" actionListener="#{usuarioController.salvar}"
oncomplete="retornaEvento(args)" update="pgrUsuario, oplMensagem" />
<p:commandButton id="cbtAlterar" value="#{msg['botao.alterar']}" style="display: none;" styleClass="botoes" actionListener="#{usuarioController.alterar}"
oncomplete="retornaEvento(args)" update="pgrUsuario, oplMensagem" />
<p:commandButton id="cbtExcluir" value="#{msg['botao.excluir']}" style="display: none;" styleClass="botoes" actionListener="#{usuarioController.excluir}"
oncomplete="retornaEvento(args)" update="pgrUsuario, oplMensagem" />
</f:facet>
</p:panel>
</ui:define>
<ui:define name="msgDialog">
<h:panelGrid columns="1">
<h:outputLabel id="oplMensagem" value="#{usuarioController.mensagem}" styleClass="fonteAlerta" />
<h:commandButton id="cbtOk" value="#{msg['botao.ok']}" styleClass="botoes" action="#{usuarioController.preparaExibirUsuarios}" immediate="true" />
</h:panelGrid>
</ui:define>
<ui:define name="centro">
<p:panel style="position: relative; margin: auto; margin-top: 100px; width: 700px;">
<f:facet name="header">
<h:outputText value="#{msg['usuario.tabela.listaUsuarios']}" styleClass="fonteTitulo" />
</f:facet>
<p:dataTable id="tabUsuarios" value="#{usuarioController.listaUsuarios}" var="usuario" rows="10"
width="700px" emptyMessage="#{msg['tabela.nenhumRegistroEncontrado']}" paginator="true"
paginatorPosition="bottom" style="position: relative; margin: auto; text-decoration: none;"
firstPageLinkLabel="#{msg['tabela.primeiroRegistro']}" nextPageLinkLabel="#{msg['tabela.proximoRegistro']}"
previousPageLinkLabel="#{msg['tabela.anteriorRegistro']}" lastPageLinkLabel="#{msg['tabela.ultimoRegistro']}"
selectionMode="single">
<p:column>
<f:facet name="header">
<h:outputText value="ID" />
</f:facet>
<h:outputText value="#{usuario.idUsuario}" />
</p:column>
<p:column sortBy="#{usuario.nmUsuario}">
<f:facet name="header">
<h:outputText value="#{msg['usuario.tabela.nome']}" />
</f:facet>
<h:outputText value="#{usuario.nmUsuario}" />
</p:column>
<p:column>
<f:facet name="header">
<h:outputText value="#{msg['usuario.tabela.login']}" />
</f:facet>
<h:outputText value="#{usuario.dsLogin}" />
</p:column>
<p:column>
<f:facet name="header">
<h:outputText value="#{msg['usuario.tabela.perfil']}" />
</f:facet>
<h:outputText value="#{usuario.perfil.nmPerfil}" />
</p:column>
<p:column>
<p:commandLink id="cdlConsultaUsuario" actionListener="#{usuarioController.preparaUsuarioSelecionado}"
async="true" oncomplete="dlgConteudo.show();" update="pgrUsuario">
<h:graphicImage url="/img/buscar.png" title="#{msg['botao.buscar']}" />
<f:setPropertyActionListener value="#{usuario}" target="#{usuarioController.usuarioSelecionado}" />
</p:commandLink>
</p:column>
<p:column>
<h:commandLink id="cdlAlteraUsuario" action="#{usuarioController.preparaAlteracao}"
onclick="document.getElementById('cbtAlterar').style.display='inline';">
<h:graphicImage url="/img/alterar.png" title="#{msg['botao.alterar']}" />
<f:setPropertyActionListener value="#{usuario}" target="#{usuarioController.usuarioSelecionado}" />
</h:commandLink>
</p:column>
<p:column>
<h:commandLink id="cdlExcluiUsuario" action="/jsf/usuario/excluirUsuario?faces-redirect=true"
onclick="document.getElementById('cbtExcluir').style.display='inline';">
<h:graphicImage url="/img/excluir.png" title="#{msg['botao.excluir']}" />
</h:commandLink>
</p:column>
</p:dataTable>
<f:facet name="footer">
<h:commandButton value="#{msg['botao.voltar']}" styleClass="botoes" immediate="true" action="/index?faces-redirect=true">
</h:commandButton>
<h:outputText value=" " />
<p:commandButton value="#{msg['botao.incluir']}" styleClass="botoes" actionListener="#{usuarioController.preparaCriacao}" immediate="true"
update="pgrUsuario" oncomplete="dlgConteudo.show();" onclick="document.getElementById('cbtIncluir').style.display='inline';" />
</f:facet>
</p:panel>
</ui:define>
</ui:composition>
</html>
Agora o ManagedBean UsuarioController.java
package br.com.notaroberto.controller;
//~--- non-JDK imports --------------------------------------------------------
import java.util.List;
import java.util.ResourceBundle;
import javax.faces.bean.ManagedBean;
import br.com.notaroberto.dao.UsuarioDAO;
import br.com.notaroberto.model.Perfil;
import br.com.notaroberto.model.Usuario;
import br.com.notaroberto.util.Constantes;
import br.com.notaroberto.util.JsfUtil;
import javax.faces.bean.SessionScoped;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.faces.convert.FacesConverter;
import javax.faces.event.ActionEvent;
@ManagedBean(name = "usuarioController")
@SessionScoped
public class UsuarioController {
private Usuario usuario, usuarioSelecionado;
private UsuarioDAO usuarioDAO;
private List<Usuario> listaUsuarios;
private List<Perfil> listaPerfis;
private String mensagem;
private UsuarioDAO getUsuarioDAO() {
usuarioDAO = new UsuarioDAO();
return usuarioDAO;
}
public void setListaUsuarios(List<Usuario> listaUsuarios) {
this.listaUsuarios = listaUsuarios;
}
public List<Usuario> getListaUsuarios() {
return listaUsuarios;
}
public List<Perfil> getListaPerfis() {
return listaPerfis;
}
public void setListaPerfis(List<Perfil> listaPerfis) {
this.listaPerfis = listaPerfis;
}
public String getMensagem() {
return mensagem;
}
public void setMensagem(String mensagem) {
this.mensagem = mensagem;
}
public Usuario getUsuarioSelecionado() {
if (usuarioSelecionado == null) {
usuarioSelecionado = new Usuario();
}
return usuarioSelecionado;
}
public void setUsuarioSelecionado(Usuario usuarioSelecionado) {
this.usuarioSelecionado = usuarioSelecionado;
}
public String preparaExibirUsuarios() {
recriaModelo();
setListaUsuarios(getUsuarioDAO().buscaTodos());
return Constantes.URL_MENU_USUARIO;
}
public void preparaCriacao(ActionEvent actionEvent) {
carregaListaPerfis();
setUsuarioSelecionado(null);
}
public void preparaUsuarioSelecionado(ActionEvent actionEvent) {
carregaListaPerfis();
}
public String carregaListaPerfis() {
PerfilController perfilController = new PerfilController();
perfilController.preparaLista();
setListaPerfis(perfilController.getListaPerfis());
return null;
}
public void salvar(ActionEvent actionEvent) {
try {
getUsuarioDAO().salva(usuarioSelecionado);
setMensagem(ResourceBundle.getBundle("/message").getString("usuario.criadoSucesso"));
} catch (Exception e) {
setMensagem(e + " " + ResourceBundle.getBundle("/message").getString("usuario.erroIncluir"));
}
}
public String alterar() {
try {
getUsuarioDAO().altera(usuarioSelecionado);
JsfUtil.addSuccessMessage(null, ResourceBundle.getBundle("/message").getString("UsuarioUpdated"));
return "Exibe";
} catch (Exception e) {
JsfUtil.addErrorMessageExcecao(e, ResourceBundle.getBundle("/message").getString("PersistenceErrorOccured"));
return null;
}
}
public String excluir() {
try {
getUsuarioDAO().exclui(usuarioSelecionado);
JsfUtil.addSuccessMessage(null, ResourceBundle.getBundle("/message").getString("UsuarioDeleted"));
return "Exibe";
} catch (Exception e) {
JsfUtil.addErrorMessageExcecao(e, ResourceBundle.getBundle("/message").getString("PersistenceErrorOccured"));
return null;
}
}
private void recriaModelo() {
setListaUsuarios(null);
}
public String autenticaUsuario() {
String pagina = null;
try {
usuario = getUsuarioDAO().buscaLoginSenha(getUsuarioSelecionado().getDsLogin(), getUsuarioSelecionado().getDsSenha());
if (usuario == null) {
JsfUtil.addErrorMessage("form:iphMensagem", ResourceBundle.getBundle("/message").getString("usuario.naoEncontrado"));
} else {
pagina = Constantes.URL_MENU_HOME;
}
} catch (Exception e) {
JsfUtil.addErrorMessage("form:iphMensagem", ResourceBundle.getBundle("/message").getString("mensagem.conexao.erro"));
}
return pagina;
}
@FacesConverter(forClass = Usuario.class, value = "usuarioConverter")
public static class UsuarioControllerConverter implements Converter {
@Override
public Object getAsObject(FacesContext facesContext, UIComponent component, String value) {
if ((value == null) || (value.length() == 0)) {
return null;
}
UsuarioController usuarioController = (UsuarioController) facesContext.getApplication().getELResolver().getValue(facesContext.getELContext(),
null, "usuarioController");
return usuarioController.getUsuarioDAO().buscaPeloID(getID(value));
}
Integer getID(String value) {
Integer id;
id = Integer.valueOf(value);
return id;
}
String getStringID(Integer value) {
StringBuffer sb = new StringBuffer();
sb.append(value);
return sb.toString();
}
@Override
public String getAsString(FacesContext facesContext, UIComponent component, Object object) {
if (object == null) {
return null;
}
if (object instanceof Usuario) {
Usuario o = (Usuario) object;
return getStringID(o.getIdUsuario());
} else {
throw new IllegalArgumentException("objeto " + object + " possui o tipo " + object.getClass().getName()
+ "; tipo esperado: " + UsuarioController.class.getName());
}
}
}
}
Ou seja, ao clicar no commandLink eu preciso carregar a lista de perfis, preciso carregar o usuarioSelecionado através do <f:setPropertyActionListener> e exibir o dialog.
Explicitando novamente o problema, quando é colocado o immediate=true no commandLink, o mesmo ignora os required’s, carrega a lista de perfis, porém não consegue setar o usuarioSelecionado. Ao retirar o immediate=true do commandLink, o usuarioSelecionado é setado normalmente, porém neste caso o método que carrega os perfis não é acionado. Então dependendo da situação ora o dialog é exibido com os dados do usuário selecionado mas com a lista de perfis nula no h:selectOneMenu, ora o dialog é exibido e a lista é carregada normalmente, porém o usuarioSelecionado é nulo, e com isso os campos do usuario ficam nulos.
Já tentei colocar um rendered="#{usuarioController.exibePainelGrid}" no PainelGrid que possuem os dados do usuário exibido no dialog para evitar que os required’s fossem executados antes da exibição do dialog, porém isto não funciona, pois ele inicia-se como false, ou seja, não é exibido, e ao clicar no commandLink do itemSelecionado o dialog é exibido sem o painelGrid, pois mesmo setando este para ‘true’ dentro do método que carrega a lista de perfis, ou diretamente através do comando <f:setPropertyActionListener value="#{true}" target="#{usuarioController.exibePainelGrid}" /> o mesmo é executado depois do dialog ser exibido, pelo onComplete, ou seja, o painelGrid continua não sendo exibido. Mesmo dando um update nele, não funciona da mesma forma como no a4j:support com reRender=‘componente’ do antigo ajax.
OBS: O atributo exibePainelGrid no usuarioController foi retirado, mas nas tentativas de teste este foi utilizado.
Se alguém souber como solucionar o problema, será de grande ajuda.
Agradeço desde já pela atenção a todos,
Att,
Lessandro