Pergunta

Há algumas coisas que estou tendo dificuldade em entender em relação ao desenvolvimento de componentes personalizados em JSF.Para os fins dessas perguntas, você pode assumir que todos os controles personalizados estão usando ligações/expressões de valor (não ligações literais), mas também estou interessado em explicações sobre eles.

  1. Onde defino o valor para a ligação de valor?Isso deveria acontecer na decodificação?Ou a decodificação deveria fazer outra coisa e depois ter o valor definido em encodeBegin?
  2. Ler da vinculação de valor - Quando leio os dados da vinculação de valor vs.lendo-o de submitvalue e colocando-o na ligação de valor?
  3. Quando os ouvintes de ação nos formulários são chamados em relação a tudo isso?Todas as páginas do ciclo de vida do JSF mencionam eventos que acontecem em várias etapas, mas não está completamente claro para mim quando apenas um simples ouvinte de um botão de comando está sendo chamado

Eu tentei algumas combinações, mas sempre acabo com erros difíceis de encontrar que acredito serem provenientes de mal-entendidos básicos do ciclo de vida do evento.

Foi útil?

Solução

Há um diagrama muito bom no Especificação JSF que mostra o ciclo de vida da solicitação - essencial para entender essas coisas.

As etapas são:

  • Restaurar visualização.A árvore UIComponent é reconstruída.
  • Aplicar valores de solicitação.Componentes editáveis ​​devem implementar EditableValueHolder.Esta fase percorre a árvore de componentes e chama o processDecodes métodos.Se o componente não for algo complexo como UIData, ele não fará muito além de chamar o seu próprio decodificar método.O decodificar método não faz muito, exceto encontrar seu renderizador e invocar seu decodificar método, passando-se como um argumento.É trabalho do renderizador obter qualquer valor enviado e configurá-lo via setSubmitValue.
  • Validações de Processo.Esta fase chama processValidators que vai ligar validar.O validar O método pega o valor enviado, converte-o com qualquer conversor, valida-o com qualquer validador e (assumindo que os dados passem nesses testes) chama definirValor.Isso armazenará o valor como uma variável local.Embora esta variável local não seja nula, ela será retornada e não o valor da ligação de valor para quaisquer chamadas para Obter valor.
  • Atualizar valores do modelo.Esta fase chama atualizações de processo.Em um componente de entrada, isso chamará atualizarModel que vai conseguir o Expressão de valor e invoque-o para definir o valor no modelo.
  • Invocar aplicativo.Ouvintes de eventos de botão e assim por diante serão invocados aqui (assim como a navegação, se não houver memória).
  • Resposta de renderização.A árvore é renderizada por meio dos renderizadores e o estado é salvo.
  • Se alguma destas fases falhar (por ex.um valor é inválido), o ciclo de vida pula para Render Response.
  • Vários eventos podem ser acionados após a maioria dessas fases, invocando ouvintes conforme apropriado (como ouvintes de mudança de valor após validações de processo).

Esta é uma versão um tanto simplificada dos eventos.Consulte a especificação para obter mais detalhes.

Eu questionaria por que você está escrevendo seu próprio UIComponent.Esta não é uma tarefa trivial e é necessário um profundo conhecimento da arquitetura JSF para acertar.Se você precisar de um controle personalizado, é melhor criar um controle concreto que estenda um UIComponent existente (como faz o HtmlInputText) com um renderizador equivalente.

Se a contaminação não for um problema, existe uma implementação JSF de código aberto na forma de Apache MyFaces.

Outras dicas

Ouvintes de ação, como para um Botão de comando, são chamados durante o Invocar aplicativo fase, que é a última fase antes da final Resposta de renderização Estágio.Isto é mostrado em O Ciclo de Vida JSF - figura 1.

É a única estrutura que já usei onde a criação de componentes é um processo profundo e intrincado como esse.Nenhuma das outras estruturas da web (no mundo .NET ou não) torna isso tão doloroso, o que é completamente inexplicável para mim.

Algumas das decisões de design por trás do JSF começam a fazer mais sentido quando você considera os objetivos.O JSF foi projetado para ser usado em ferramentas - ele expõe muitos metadados para IDEs.JSF não é um framework web - é um MVP framework que pode ser usado como um framework web.JSF é altamente extensível e configurável – você pode substituir 90% da implementação por aplicativo.

A maior parte dessas coisas apenas torna seu trabalho mais complicado se tudo o que você quiser fazer for inserir um controle HTML extra.

O componente é uma composição de vários componentes básicos InputText (e outros), btw.

Presumo que fragmentos de páginas baseados em JSP/incluídas em ferramentas não atendam aos seus requisitos.

Eu consideraria usar o seu UIComponentELTag.createComponent para criar um controle composto com uma base UIPanel e criar todos os seus filhos a partir de implementações existentes.(Presumo que você esteja usando JSPs/taglibs e fazendo algumas outras suposições.) Você provavelmente desejaria um renderizador personalizado se nenhum dos renderizadores UIPanel existentes fizesse o trabalho, mas os renderizadores são fáceis.

O melhor artigo que encontrei é Escrita de componente Jsf, quanto a 2, onde eu leio o valor para um valor vinculado no seu componente, você tem um getter que se parece com isso


public String getBar() {  
     if (null != this.bar) {  
         return this.bar ;  
     }  
     ValueBinding _vb = getValueBinding("bar");  
     return (_vb != null) ? (bar) _vb.getValue(getFacesContext()) : null;  
}
  

como isso entrou no getValueBinding?No método setProperties da sua classe de tag

  if (bar!= null) {  
         if (isValueReference(bar)) {  
             ValueBinding vb = Util.getValueBinding(bar);  
             foo.setValueBinding("bar", vb);  
         } else {  
             throw new IllegalStateException("The value for 'bar' must be a ValueBinding.");  
         }  
     }  
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top