commandButton/commandLink/ajax método de ação/ouvinte não invocado ou valor de entrada não definido/atualizado

StackOverflow https://stackoverflow.com/questions/2118656

Pergunta

Às vezes, ao usar <h:commandLink>, <h:commandButton> ou <f:ajax>, o action, actionListener ou listener método associado à tag simplesmente não está sendo invocado.Ou as propriedades do bean não são atualizadas com os dados enviados UIInput valores.

Quais são as possíveis causas e soluções para isso?

Foi útil?

Solução

Introdução

Sempre que um UICommand componente (<h:commandXxx>, <p:commandXxx>, etc) falha ao invocar o método de ação associado ou um UIInput componente (<h:inputXxx>, <p:inputXxxx>, etc) falha ao processar os valores enviados e/ou atualizar os valores do modelo, e você não está vendo nenhuma exceção e/ou avisos googláveis ​​no log do servidor, e também não quando você configura um manipulador de exceção ajax conforme Tratamento de exceções em solicitações JSF ajax, nem quando você define o parâmetro de contexto abaixo em web.xml,

<context-param>
    <param-name>javax.faces.PROJECT_STAGE</param-name>
    <param-value>Development</param-value>
</context-param>

e você também não está vendo nenhum erro e/ou aviso no Google no console JavaScript do navegador (pressione F12 no Chrome/Firefox23+/IE9+ para abrir o conjunto de ferramentas do desenvolvedor web e, em seguida, abra o Console guia) e, em seguida, analise a lista abaixo de possíveis causas.

Causas Possíveis

  1. UICommand e UIInput componentes devem ser colocados dentro de um UIForm componente, por ex. <h:form> (e, portanto, não é HTML simples <form>), caso contrário, nada poderá ser enviado ao servidor. UICommand componentes também não devem ter type="button" atributo, caso contrário, será um botão morto que só é útil para JavaScript onclick.Veja também Como enviar valores de entrada do formulário e invocar um método no bean JSF e <h:commandButton> não inicia um postback.

  2. Você não pode aninhar vários UIForm componentes entre si.Isso é ilegal em HTML.O comportamento do navegador não é especificado.Cuidado com os arquivos incluídos!Você pode usar UIForm componentes em paralelo, mas eles não se processarão durante o envio.Você também deve tomar cuidado com o antipadrão "Forma de Deus";certifique-se de não processar/validar involuntariamente todas as outras entradas (invisíveis) na mesma forma (por exemplo,ter uma caixa de diálogo oculta com as entradas necessárias no mesmo formato).Veja também Como usar <h:form> na página JSF?Formulário único?Vários formulários?Formulários aninhados?.

  3. Não UIInput deveria ter ocorrido um erro de validação/conversão de valor.Você pode usar <h:messages> para mostrar quaisquer mensagens que não são mostradas por qualquer entrada específica <h:message> componentes.Não se esqueça de incluir o id de <h:messages> no <f:ajax render>, se houver, para que também seja atualizado nas solicitações ajax.Veja também h:messages não exibe mensagens quando p:commandButton é pressionado.

  4. Se UICommand ou UIInput componentes são colocados dentro de um componente iterativo como <h:dataTable>, <ui:repeat>, etc, então você precisa garantir que exatamente o mesmo value do componente de iteração é preservado durante a fase de aplicação de valores de solicitação da solicitação de envio do formulário.O JSF irá reiterar para encontrar o link/botão clicado e os valores de entrada enviados.Colocar o bean no escopo da visualização e/ou certificar-se de carregar o modelo de dados em @PostConstruct do bean (e, portanto, não em um método getter!) deve consertar isso.Veja também Como e quando devo carregar o modelo do banco de dados para h:dataTable.

  5. Se UICommand ou UIInput componentes são incluídos por uma fonte dinâmica, como <ui:include src="#{bean.include}">, então você precisa garantir que exatamente o mesmo #{bean.include} o valor é preservado durante o tempo de construção da visualização da solicitação de envio do formulário.O JSF irá reexecutá-lo durante a construção da árvore de componentes.Colocar o bean no escopo da visualização e/ou certificar-se de carregar o modelo de dados em @PostConstruct do bean (e, portanto, não em um método getter!) deve consertar isso.Veja também Como incluir conteúdo dinâmico de atualização ajax pelo menu de navegação?(SPA JSF).

  6. O rendered atributo do componente e todos os seus pais e o test atributo de qualquer pai <c:if>/<c:when> não deveria avaliar false durante a fase de aplicação de valores de solicitação da solicitação de envio do formulário.O JSF verificará novamente como parte da proteção contra solicitações adulteradas/hackeadas.Armazenar as variáveis ​​responsáveis ​​pela condição em um @ViewScoped bean ou certificando-se de que você está pré-inicializando corretamente a condição em @PostConstruct de um @RequestScoped feijão deve consertar isso.O mesmo se aplica ao disabled atributo do componente, que não deve ser avaliado como true durante a fase de aplicação de valores de solicitação.Veja também Ação JSF CommandButton não invocada e O envio do formulário no componente renderizado condicionalmente não é processado.

  7. O onclick atributo do UICommand componente e o onsubmit atributo do UIForm componente não deve retornar false ou causar um erro de JavaScript.Deveria em caso de <h:commandLink> ou <f:ajax> também não haverá erros JS visíveis no console JS do navegador.Normalmente, pesquisar no Google a mensagem de erro exata já lhe dará a resposta.Veja também Adicionar jQuery ao PrimeFaces resulta em TypeErrors não capturados.

  8. Se você estiver usando Ajax via JSF 2.x <f:ajax> ou por ex.PrimeFaces <p:commandXxx>, certifique-se de ter um <h:head> no modelo mestre em vez do <head>.Caso contrário, o JSF não poderá incluir automaticamente os arquivos JavaScript necessários que contêm as funções Ajax.Isso resultaria em um erro de JavaScript como "mojarra não está definido" ou "PrimeFaces não está definido" no console JS do navegador.Veja também h:commandLink actionlistener não é invocado quando usado com f:ajax e ui:repeat.

  9. Se você estiver usando Ajax e os valores enviados acabarem sendo null, então certifique-se de que o UIInput e UICommand componentes de interesse são cobertos pelo <f:ajax execute> ou por ex. <p:commandXxx process>, caso contrário eles não serão executados/processados.Veja também Valores de formulário enviados não atualizados no modelo ao adicionar <f:ajax> a <h:commandButton> e Compreendendo o processo/atualização do PrimeFaces e os atributos de execução/renderização do JSF f:ajax.

  10. Se os valores enviados ainda acabarem sendo null, e você estiver usando CDI para gerenciar beans, certifique-se de importar a anotação de escopo do pacote correto, caso contrário, o CDI será padronizado como @Dependent que recria efetivamente o bean em cada avaliação da expressão EL.Veja também O bean @SessionScoped perde escopo e é recriado o tempo todo, os campos tornam-se nulos e Qual é o escopo do Bean gerenciado padrão em um aplicativo JSF 2?

  11. Se um dos pais do <h:form> com o UICommand for renderizado/atualizado anteriormente por uma solicitação ajax vinda de outro formulário na mesma página, a primeira ação sempre falhará no JSF 2.2 ou anterior.A segunda ação e as subsequentes funcionarão.Isso é causado por um bug no tratamento do estado de visualização que é relatado como Edição de especificação JSF 790 e atualmente corrigido no JSF 2.3.Para versões JSF mais antigas, você precisa especificar explicitamente o ID do <h:form> no render do <f:ajax>.Veja também h:commandButton/h:commandLink não funciona no primeiro clique, funciona apenas no segundo clique.

  12. Se o <h:form> tem enctype="multipart/form-data" definido para suportar o upload de arquivos, então você precisa ter certeza de que está usando pelo menos JSF 2.2, ou que o filtro de servlet responsável por analisar solicitações multipart/form-data está configurado corretamente, caso contrário, o FacesServlet acabará não obtendo nenhum parâmetro de solicitação e, portanto, não será capaz de aplicar os valores da solicitação.A forma de configurar esse filtro depende do componente de upload de arquivo que está sendo usado.Para tomahawk <t:inputFileUpload>, verificar esta resposta e para PrimeFaces <p:fileUpload>, verificar esta resposta.Ou, se você realmente não estiver enviando nenhum arquivo, remova o atributo completamente.

  13. Certifique-se de que o ActionEvent argumento de actionListener é um javax.faces.event.ActionEvent e portanto não java.awt.event.ActionEvent, que é o que a maioria dos IDEs sugere como primeira opção de preenchimento automático.Não ter argumentos também é errado se você usar actionListener="#{bean.method}".Se você não quiser um argumento no seu método, use actionListener="#{bean.method()}".Ou talvez você realmente queira usar action em vez de actionListener.Veja também Diferenças entre ação e actionListener.

  14. Certifique-se de que não PhaseListener ou qualquer EventListener na cadeia de solicitação-resposta mudou o ciclo de vida do JSF para pular a fase de ação de invocação, por exemplo, chamando FacesContext#renderResponse() ou FacesContext#responseComplete().

  15. Certifique-se de que não Filter ou Servlet na mesma cadeia de solicitação-resposta bloqueou a solicitação do FacesServlet de alguma forma.

  16. Se você estiver usando um PrimeFaces <p:dialog> ou um <p:overlayPanel>, então certifique-se de que eles tenham seus próprios <h:form>.Porque esses componentes são, por padrão, realocados pelo JavaScript para o final do HTML <body>.Então, se eles estivessem originalmente sentados dentro de um <form>, então eles não se sentariam mais em um <form>.Veja também A ação p:commandbutton não funciona dentro de p:dialog

  17. Bug na estrutura.Por exemplo, RichFaces tem um "erro de conversão"ao usar um rich:calendar Elemento da UI com um defaultLabel atributo (ou, em alguns casos, um rich:placeholder subelemento).Este bug evita que o método bean seja invocado quando nenhum valor é definido para a data do calendário.O rastreamento de bugs da estrutura pode ser realizado começando com um exemplo simples de trabalho e construindo a página novamente até que o bug seja descoberto.

Dicas de depuração

Caso você ainda tenha problemas, é hora de depurar.No lado do cliente, pressione F12 no navegador da web para abrir o conjunto de ferramentas do desenvolvedor da web.Clique no Console aba então veja o console JavaScript.Deve estar livre de erros de JavaScript.A captura de tela abaixo é um exemplo do Chrome que demonstra o caso de envio de um <f:ajax> botão habilitado sem ter <h:head> declarado (conforme descrito no ponto 7 acima).

js console

Clique no Rede guia para ver o monitor de tráfego HTTP.Envie o formulário e investigue se os cabeçalhos da solicitação, os dados do formulário e o corpo da resposta estão de acordo com as expectativas.A captura de tela abaixo é um exemplo do Chrome que demonstra um envio bem-sucedido de ajax de um formulário simples com um único <h:inputText> e um único <h:commandButton> com <f:ajax execute="@form" render="@form">.

network monitor

(aviso:ao postar capturas de tela de cabeçalhos de solicitação HTTP como acima de um ambiente de produção, certifique-se de embaralhar/ofuscar quaisquer cookies de sessão na captura de tela para evitar ataques de sequestro de sessão!)

No lado do servidor, certifique-se de que o servidor seja iniciado no modo de depuração.Coloque um ponto de interrupção de depuração em um método do componente JSF de interesse que você espera que seja chamado durante o processamento do envio do formulário.Por exemplo.no caso de UICommand componente, isso seria UICommand#queueEvent() e em caso de UIInput componente, isso seria UIInput#validate().Basta percorrer a execução do código e inspecionar se o fluxo e as variáveis ​​estão de acordo com as expectativas.A captura de tela abaixo é um exemplo do depurador do Eclipse.

debug server

Outras dicas

Se seu h:commandLink está dentro de um h:dataTable Há outra razão pela qual h:commandLink Pode não funcionar:

A fonte de dados subjacente que está ligada ao h:dataTable Também deve estar disponível no segundo JSF-Lifecycle que é acionado quando o link é clicado.

Portanto, se a fonte de dados subjacente for solicitada, o h:commandLink não funciona!

Embora minha resposta não seja 100% aplicável, mas a maioria dos mecanismos de pesquisa encontra isso como o primeiro golpe, decidi publicá -lo no entanto:

Se você está usando PrimeFaces (ou alguma API semelhante) p:commandButton ou p:commandLink, é provável que você tenha esquecido de adicionar explicitamente process="@this" para seus componentes de comando.

Como o guia do usuário do PrimeFaces afirma na Seção 3.18, os padrões para process e update são ambos @form, que praticamente se opõe aos padrões que você pode esperar do JSF simples f:ajax ou richfaces, que são execute="@this" e render="@none" respectivamente.

Só levei um tempo para descobrir. (... e acho que é bastante tio usar padrões diferentes do JSF!)

Eu mencionaria mais uma coisa que diz respeito ao Primefaces p:commandButton!

Quando você usa um p:commandButton para a ação que precisa ser realizada no servidor, você não pode usar type="button" porque isso é para Apertar botões que são usados ​​para executar javascript personalizado sem causar uma solicitação ajax/não-ajax ao servidor.

Para isso, você pode dispensar o type atributo (o valor padrão é "submit") ou você pode usar explicitamente type="submit".

Espero que isso ajude alguém!

Fiquei preso a esse problema e encontrei mais uma causa para esse problema. Se você não possui métodos de setter em seu feijão de apoio para as propriedades usadas no seu *.xhtml, a ação simplesmente não será invocada.

Recentemente, encontrei um problema com um UICommand não invocar em um aplicativo JSF 1.2 usando componentes de faces estendidas da IBM.

Eu tinha um botão de comando em uma linha de um datatable (a versão estendida, então <hx:datatable>) e o UiCommand não dispararia de certas linhas da tabela (as linhas que não disparariam eram as linhas maiores que o tamanho da exibição da linha padrão).

Eu tinha um componente suspenso para selecionar o número de linhas para exibir. O valor que apoia este campo estava em RequestScope. Os dados que apoiam a tabela em si estava em uma espécie de ViewScope (na realidade, temporariamente em SessionScope).

Se a exibição da linha foi aumentada através do controle que o valor também estava vinculado ao Datatable's rows Atributo, nenhuma das linhas exibidas como resultado dessa alteração pode disparar o UICommand quando clicada.

Colocar esse atributo no mesmo escopo que os dados da tabela corrigir o problema.

Eu acho que isso é mencionado no Balusc #4 acima, mas não apenas o valor da tabela precisou ser visualizada ou escopo de sessão, mas também o atributo controlando o número de linhas para exibir nessa tabela.

Eu também tive esse problema e só comecei a aprimorar a causa raiz depois de abrir o console da web do navegador. Até isso, eu não consegui receber mensagens de erro (mesmo com <p:messages>). O console da web mostrou um código de status HTTP 405 voltando do <h:commandButton type="submit" action="#{myBean.submit}">.

No meu caso, tenho uma mistura de baunilha HTTPSERVLET da OAuth Authentication via Facelets e feijões Auth0 e JSF, realizando minhas visualizações de aplicativos e lógica de negócios.

Depois de refatorar meu web.xml e remover um servidor intermediário, ele "magicamente" funcionou.

Bottom line, o problema era que o servlet médio estava usando o requestdispatcher.forward (...) para redirecionar do ambiente HTTPSERVlet para o ambiente JSF, enquanto o servlet que estava sendo chamado antes dele estava redirecionando com httpServLeSponse.sendReect (.. .. .).

Basicamente, o uso do sendRedirect () permitiu que o JSF "contêiner" assumisse o controle, enquanto o requestDispatcher.forward () obviamente não era.

O que não sei é por que o Facelet conseguiu acessar as propriedades do feijão, mas não conseguiu defini-las, e isso claramente grita por acabar com a mistura de servlets e JSF, mas espero que isso ajude alguém a evitar muitas horas de cabeça para a tabela banging.

Eu me diverti muito depurando um problema em que um <h:commandLink>ação em richfaces datatable recusou -se a disparar. A mesa costumava trabalhar em algum momento, mas parou sem motivo aparente. Não deixei pedra sobre pedra, apenas para descobrir que meu rich:datatable estava usando o errado rowKeyConverter que devolveu nulos que Richfaces usavam alegremente como teclas de linha. Isso impediu o meu <h:commandLink> ação de ser chamado.

Mais uma possibilidade: se o sintoma é que a primeira invocação funciona, mas as subsequentes não, você pode estar usando o PrimeFaces 3.x com o JSF 2.2, conforme detalhado aqui: Nenhum ViewState é enviado.

Eu corrigi meu problema em colocar o:

<h:commandButton class="btn btn-danger" value = "Remove" action="#{deleteEmployeeBean.delete}"></h:commandButton>

Dentro:

<h:form>
     <h:commandButton class="btn btn-danger" value = "Remove" action="#{deleteEmployeeBean.delete}"></h:commandButton>
</h:form>
<ui:composition>  
  <h:form id="form1">
    <p:dialog id="dialog1">
      <p:commandButton value="Save" action="#{bean.method1}" /> <!--Working-->
    </p:dialog>
  </h:form>

  <h:form id="form2">
    <p:dialog id="dialog2">
      <p:commandButton value="Save" action="#{bean.method2}" /> <!--Not Working-->
    </p:dialog>
  </h:form>
</ui:composition>

Resolver;

<ui:composition>  
  <h:form id="form1">
    <p:dialog id="dialog1">
      <p:commandButton value="Save" action="#{bean.method1}" />   <!-- Working  -->
    </p:dialog>

    <p:dialog id="dialog2">
      <p:commandButton value="Save" action="#{bean.method2}" />   <!--Working  -->
    </p:dialog>
  </h:form>
  <h:form id="form2">
    <!-- ..........  -->
  </h:form>
</ui:composition>
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top