Herança em JSF para centralizar regras básicas

24 respostas
L

Bom dia a todos,

Sou Analista de Sistema e na empresa estamos iniciando um novo projeto, optamos por JSF + JPA + primefaces.
Tenho conhecimento de Java, porém sempre trabalhei com JSE. Por conhecer os problemas de evolução de sistemas tento garantir a facilidade de manutenção dos cadastros de forma homogenia.

Por isso gostaria de me informar se existe a possibilidade de implementar algo como sempre fiz no JSE.
Imaginem o seguinte, a tela de listagem ou a cadastro possuem características muito similares, eu sempre tive um ancestral visual (JFrame) que implementava as questões básicas e criava filhos que especializavam os métodos. Na realidade o filho passa simplesmente o ?Class? do objeto que será instanciado e proveria as informações para listagem e cadastro.

Muito bem, quando chequei no JSF me deparo com o problema conceitual. XHTML não é um JFrame, não é orientado á objeto. Como posso fazer que um xthml ancestral utilize de um BEAN que receba através dos seus filhos as informações necessárias para preencher as informações visuais?

A visão da ideia seria assim:

|XHTML_BASICO| usa --> |BEAN_BASICO|
^ ^
| Herda | Herda
|XHTML_PESSOA| usa --> |BEAN_PESSOA|

No final das contas como fazer um xhtml herdar e um BEAN genérico ser dinamicamente modificado por um filho?

Grato por qualquer ajuda.

24 Respostas

Hebert_Coelho

De certo modo existe. Chama Facelets.

url=http://uaihebert.com/?p=1596]JSF Mini Livro - Dicas, conceitos e boas práticas[/url]

Te aconselho muuuito estudar o JSF antes de começar a desenvolver.

L

Obrigado pela resposta, mais talvez não tenha me compreendido.

Eu já conheço JSF e sei que é possível, reutilização de código com o facelets.

A pergunta é como fazer este mecanismo com um Bean que será ofertado pelos filhos (os XHTML que usam o template).

fabiozanardi

isso mesmo,

o xhtml_basico seria o template da aplicação, e o conteudo de “pessoa” ficaria no xhtml de pessoa.

qq coisa da 1 reply ae

flw

Hebert_Coelho

A herança do bean eu faço criando uma casse abstrata e os beans vão estender esse cara.

A classe abstrata não precisa ser um MB

L

fabiozanardi é justamente isso que gostaria de melhorar.

A implementação dos componentes são as mesmas só muda o provedor dos dados (Bean).
Os botões e listagem são os mesmo para todos, mais na tela de clientes vem da tabela de cliente, já na tela de usuários vem da tabela de usuário.

A questão é não ter que refazer as regras básicas dos componentes para cada tela.

Alguma ideia?

Hebert_Coelho

lucaonoforum:
fabiozanardi é justamente isso que gostaria de melhorar.

A implementação dos componentes são as mesmas só muda o provedor dos dados (Bean).
Os botões e listagem são os mesmo para todos, mais na tela de clientes vem da tabela de cliente, já na tela de usuários vem da tabela de usuário.

A questão é não ter que refazer as regras básicas dos componentes para cada tela.

Alguma ideia?

Então o que você quer não é Herança, você quer uma tela que utilize generics.

Nunca vi isso aplicado ao JSF não que fosse funcional.

As tentativas que eu já vi, erros bizarros aconteciam.

fabiozanardi

a sua idéia é bem interessante, mas eu sempre referencio como #{bean.metodo}

não sei se da para chegar no nível que voce quer como o Hebert disse

alguém sabe se tem como ter uma tela genérica?

L

Para mim o grande problema que eu não tenho controle sobre a criação do Bean. O container cria e mantém e eu só uso.

Se eu pudesse criar o Bean ou executar algum método que configurasse as informações do Bean eu poderia implementar.

Alguém sabe se tem alguma maneira de interceptar a criação do Bean e de alguma forma criar o objeto que eu desejo no lugar do que está declarado?

AmauriSpPoa

Talvez você possa fazer suas Tag’s, ou separar em componentes com Facelets.

Da uma pesquisada nesse sentido.

Por exemplo toda tabela de crud <seu:tabelaCrud> <!--E as colunas aqui --> </seu:tabelaCrud>

onde os padrões da tabela tabelaCrud ficam em outro arquivo.

Hebert_Coelho

lucaonoforum:
Para mim o grande problema que eu não tenho controle sobre a criação do Bean. O container cria e mantém e eu só uso.

Se eu pudesse criar o Bean ou executar algum método que configurasse as informações do Bean eu poderia implementar.

Alguém sabe se tem alguma maneira de interceptar a criação do Bean e de alguma forma criar o objeto que eu desejo no lugar do que está declarado?

Até onde eu sei, não.

Existe a anotação @PostConstruct que quando colocada em um método, o JSF irá invocar esse método após sua criação.

L

AmauriSpPoa a ideia de criar as tags é muito mirabolante por que não quero criam um componente.
A ideia é simplesmente fazer a tela ser dinâmica. Neste caso vou ter de concordar como Hebert Coelho, criar tag tá com cara de algo que vai gerar erros bizarros.

Pessoal no final das contas é intervir no Bean. Em uma possível solução eu pensei o seguinte:

Passar no request um parâmetro que seria a classe que seria instanciada pelo Bean e fazer o esquema de Proxy.

Algo assim:

Localhost:8080/TelaDePessoa.jsf?class=br.com.Pessoa

O Bean iria pegar a string da classe e instanciar o objeto.

Class c = Class.forName(nomedaclasse);

Provedor obj = (Provedor) c.newInstance();

Os métodos seriam assim:

public string listarDados(){

return obj. listarDados();

}

O problema é a abertura da regra, fato de exibir a regra na url é algo muito ruim aos meios olhos.

Teria como fazer isso de outra maneira?

R

lucaonoforum:
fabiozanardi é justamente isso que gostaria de melhorar.

A implementação dos componentes são as mesmas só muda o provedor dos dados (Bean).
Os botões e listagem são os mesmo para todos, mais na tela de clientes vem da tabela de cliente, já na tela de usuários vem da tabela de usuário.

A questão é não ter que refazer as regras básicas dos componentes para cada tela.

Alguma ideia?

Eu acho que entendi o que vc quer,mas me confirme se é isso.

Por exemplo:Todas as minhas telas de cadastro tem os botões de ‘Salvar’ e ‘Cancelar’,então eu posso reaproveitar esse código em todas as telas:

generico.xhtml:

<h:panelGrid columns="2">
					<a4j:commandButton styleClass="buttonAdicionar"
									value="Salvar" action="#{bean[salvar]}">
								</a4j:commandButton>
								
								<a4j:commandButton immediate="true" styleClass="buttonAdicionar"  
								value="Cancelar" action="#{bean[listar]}"  />
					</h:panelGrid>

especifico.xhtml

<ui:decorate template="generico.xhtml">
		    	     <ui:param name="salvar" value="salvar" />
			         <ui:param name="listar" value="listar" />
			        </ui:decorate>

È isso?

lele_vader

Teria que passar o nome do bean então também do específico para chamar o managed bean certo não ?

L

Dentro do Template.xhtml
<h:outputText value="#{BeanBase.nome}"></h:outputText>

Dentro do BeanBase.java

public class BeanBase {

public string nome(){

return Classe Base;

}

}
Dentro do BeanPessoa.java

public class BeanPessoa extends BeanBase {

public string nome(){

return nome do cliente;

}

}

Dentro do Pessoa.xhtml
??? MINHA DUVIDA

A ideia é de alguma forma dentro de Pessoa.xhtml eu faça o código “#{BeanBase.nome}” retornar “nome do cliente”, sem ter que criar declarar em Pessoa.xhtml o mesmo h:outputText que tem no template.

raf4ever da maneira que você fez, até onde entendi, você passou um parametro para o evento do botão.

A ideia não é passar um parâmetro para um evento é fazer o objeto Bean ser outra classe.

Alguma ideia?

AmauriSpPoa

lucaonoforum:
AmauriSpPoa a ideia de criar as tags é muito mirabolante por que não quero criam um componente.
A ideia é simplesmente fazer a tela ser dinâmica. Neste caso vou ter de concordar como Hebert Coelho, criar tag tá com cara de algo que vai gerar erros bizarros.

Eu entendi que não é tag que você quer, mais ai dizer que tag é coisa mirabolante, acho que foi um pouco de exagero de sua parte, se seguindo esse conceito http://www.mkyong.com/jsf2/custom-tags-in-jsf-2-0/, gerar erros bizarros, não sei oque é simples.

L

Ok pode ter sido exagero mesmo, hehe, mil desculpas.

A Questão que não seria muito usual, para uma coisa como um Label e um Field um do lado do outro acho legal, mas agora imagina uma tela toda nesse esquema.

Não acho que seja a forma mais aconselhável. Porém caso não exista outra fora de fazer talvez tenha que ser assim mesmo.

Hebert_Coelho

lucaonoforum:
Ok pode ter sido exagero mesmo, hehe, mil desculpas.

A Questão que não seria muito usual, para uma coisa como um Label e um Field um do lado do outro acho legal, mas agora imagina uma tela toda nesse esquema.

Não acho que seja a forma mais aconselhável. Porém caso não exista outra fora de fazer talvez tenha que ser assim mesmo.

Pois é, o único modo que eu vejo isso possível de se realizar é pelo componentes reutilizáveis e com facelets.

Nunca vi, e quando vi, uma solução que realmente funcionasse.

AmauriSpPoa

Posso estar falando besteira, mas quando utilizava JSF 1.2 eu criava as tabelas no ManagedBean e inflava com as colunas e usava o binding com o objeto no JSP(Faz tempo), e inclusive colocava botões que chamavam funções(Métodos) para editar ou excluir.

Neste post tem como fazer objetos dinâmicos
http://www.guj.com.br/java/283453-resolvido-arraylist-e-jsf-como-fazer
Não sei se vai te ajudar, mas vamos tentando.

Talvez possa ser feito varrendo seu objeto e de acordo com os atributos, montar um formulário dinamicamente.

Hebert Coelho, o que acha, muita viagem?

Hebert_Coelho

AmauriSpPoa:
Posso estar falando besteira, mas quando utilizava JSF 1.2 eu criava as tabelas no ManagedBean e inflava com as colunas e usava o binding com o objeto no JSP(Faz tempo), e inclusive colocava botões que chamavam funções(Métodos) para editar ou excluir.

Neste post tem como fazer objetos dinâmicos
http://www.guj.com.br/java/283453-resolvido-arraylist-e-jsf-como-fazer
Não sei se vai te ajudar, mas vamos tentando.

Talvez possa ser feito varrendo seu objeto e de acordo com os atributos, montar um formulário dinamicamente.

Hebert Coelho, o que acha, muita viagem?

Na boa? Estou apenas acompanhando aqui para ver se aparece algum código. MAuhahua

É por que não vejo ganho nisso. Eu prefiro ter uma página para cada tela (com facelets) pois fica mais fácil de customizar. ^^

Pelo menos você deu uma saída. [=

L

Mais ainda não consegui pensar em algum modo de criar a classe especializada.

Setar o evento de tranquilo, mas como configurar o beam que seja usando no custiom tag?

AmauriSpPoa

Espera ai, são coisas diferentes.

Facelets, você vai usar de uma forma ou outra.
CustomTags, é uma forma de reutilizar código do xhtml.
E no ManagedBean você poderia tentar montar algo dinamicamente (do tipo varrer o objeto a ser persistido e montar o form dinamicamente).

Pensa e algo ai e quando surgir duvidas posta.

L

Eu tava falando de CustomTags mesmo.

Usando o exemplo do link e me passou ?http://www.mkyong.com/jsf2/custom-tags-in-jsf-2-0/?.

A questão é se fosse usar como o exemplo eu teria que algo assim:

Dentro do Custom Tag
<h:outputText value="#{NomeDoCampo}"></h:outputText>

Dentro do BeanBase.java

public class BeanBase {

public string nome(){

return Classe Base;

}

}
Dentro do BeanPessoa.java

public class BeanPessoa extends BeanBase {

public string nome(){

return nome do cliente;

}

}

Dentro do Pessoa.xhtml
<mkyong:button NomeDoCampo ="#{BeanPessoa.nome}"/>

E assim teria que setar todos os métodos que seriam usados. Seria isso mesmo, ou entendi errado?

AmauriSpPoa

É mais ou menos isso.

Tem um que eu fiz aqui

ManagedBean

package com.mycompany.tags;

import javax.faces.bean.ManagedBean;

@ManagedBean
public class Index {

    private String nome;
    private String telefone;

    public String getNome() {
        return nome;
    }

    public void setNome(String nome) {
        this.nome = nome;
    }

    public String getTelefone() {
        return telefone;
    }

    public void setTelefone(String telefone) {
        this.telefone = telefone;
    }
}

xhtml

&lt;?xml version='1.0' encoding='UTF-8' ?&gt;
&lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt;
&lt;html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:meu="http://amauri.com/facelets"&gt;    

    &lt;h:head&gt;
        &lt;title&gt;Facelet Title&lt;/title&gt;
    &lt;/h:head&gt;
    &lt;h:body&gt;
        &lt;h:form&gt;
            &lt;!--CustomTagLib --&gt;
            &lt;meu:fieldText  title="Nome" id="nome" value="#{index.nome}"/&gt;        
            &lt;!--Convencional--&gt;
            &lt;h:panelGrid columns="1"&gt;
                &lt;h:outputLabel value="Telefone" title="Telefone" for="telefone"/&gt;
                &lt;h:inputText id="telefone" title="Telefone" value="#{index.telefone}"/&gt; 
            &lt;/h:panelGrid&gt;        
        &lt;/h:form&gt;
    &lt;/h:body&gt;
&lt;/html&gt;

tag

&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt;
&lt;html xmlns="http://www.w3.org/1999/xhtml"   
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:ui="http://java.sun.com/jsf/facelets"&gt;
    &lt;h:body&gt;
        &lt;ui:composition&gt; 
            &lt;h:panelGrid columns="1"&gt;
                &lt;h:outputLabel value="#{title}" title="#{title}" for="#{id}"/&gt;
                &lt;h:inputText id="#{id}" title="#{title}" value="#{value}"/&gt; 
            &lt;/h:panelGrid&gt;
        &lt;/ui:composition&gt;
    &lt;/h:body&gt;
&lt;/html&gt;

É claro que tem o web.xml e um outro arquivo .taglib.xml, que eu não coloquei mas tem no link que eu passei.

L

Pessoal vocês foram de grande valia, MUITO OBRIGADO.

Porem infelizmente não cheguei aonde gostaria de chegar. Não vou fechar o Tópico na esperança de alguém já ter resolver este dilema.

Se mais alguém tiver alguma ideia, toda ajuda é bem-vinda. Alguém, :smiley: ?

Criado 5 de outubro de 2012
Ultima resposta 5 de out. de 2012
Respostas 24
Participantes 6