Actions Dinâmicos (JSF)

10 respostas
T

Só pra informar, eu uso JSF hehe.
Normalmente fazemos assim…

<h:commandLink value=“Frase” action="#{bean.meuMet}" />

O problema é que o metodo do action desse commandLink sempre será “meuMet” , Eu quero que esse action seja dinamico…
Quero trocar esse “bean.meuMet”, por um metodo qualquer (ex.: “#{beanDois.metodoDois}”) em tempo de execução.

Exemplo :
Imagine que #{bean.label} seja uma propriedade do Bean , Uma String mesmo…

Ai vai estar la no bean :
private String label = “#{bean.metodoQualquer}”;
setLabel()…
getLabel()…

Então eu coloco no commandLink -> <h:commandLink value=“Frase” action="#{bean.label}" /> , agora o metodo do action seria “#{bean.metodoQualquer}” !
E então enquanto o programa roda eu altero o valor desse “label”, e o action do commaLink é alterado tambem…

A ideia é essa… Mas fazer desse jeito nao funciona o action só aceita Metodos, e nao propriedade !!
Então Como faz ?
vlwS aew…

10 Respostas

Foxlol

Na página JSF:

#{bean.chamaMetodo}

Este método chamaMetodo, chama o método desejado de acordo com o valor da variável label.
Tipo:

if (label.equals(um) {

metodoUm();

}

Ou pode usar EL Resolver para resolver as EL em tempo de execução.

T

hehe Foxlol é exatamente esses ifs que eu estou querendo evitar…
Como se usa esse EL Resolver ? Com ele da pra alterar a EL do action de um componente ?

L

Criar uma action dinâmica é uma solução realmente drástica.

Primeiro, é necessário saber quantas funções possíveis serão invocadas por botão. Se for um número pequeno, por exemplo, 3, e se for um número que não aumenta com o tempo, compensa mais você colocar os três botões na tela, cada uma invocando uma função diferente, e usar o atributo rendered para selecionar qual você quer exibir.

Existe uma outra solução que é colocar um actionListener (estes são sempre executados antes de action) que descobre o ‘estado’ da página e seta um enum no managed bean que contém a função. A action é a mesma, mas existe um if-else que seleciona o que fazer. É claro que não é o mais OO, mas você pode substituir pelo pattern State.

O mais drástico é criar um ELResolver (ou VariableResolver e PropertyResolver, se o JSF for 1.1) que busca qual método chamar.

T

Estou usando a tree do richFaces !
Os items estão no banco ! São varios tipos de Items, cada um com um metodo diferente do action !
Na Tabela dos Items vai ter uma coluna “MetodoAtion” e la vai estar “#{beanPessoa.consultar}” , “#{beanDois.excluir}” , etc…
Se eu pudesse simplismente colocar 1 commandLink e no action for um “#{item.propAction}” , ficaria bem simples…

Qual a solução para fazer algo assim ? hehe
Esse ELResolver ai pode fazer o que para me ajudar ? Ele pode alterar o action dos componente e etc ???

T

Pode sim, dê uma olhada no google, para saber como implementá-lo

EAE Foxlol !!!

L

Você pode usar esse molde aqui:

public class MyELResolver extends ELResolver {
	public Object getValue(ELContext context, Object base, 
			Object property)
	throws ELException
	{
		Object result = null;
		// base tem que ser null, estou buscando somente a propriedade "dbmethod"
		if(base == null) {
			String propertyName = (String)property;
			// ve  a propriedade é 'dbmethod', porque se não for deixa 
			// quieto, os outros ELResolvers que se virem 
			if(propertyName.equals("dbmethod")) {

				// aqui você faz o diabo pra invocar a ação desejada,
				// não conheço a regra de negócio da sua aplicação, então
				// não posso ajudar muito. Mas  preferência a reflections, hein?

				result = // coloca o retorno da invocação do método

                // se tudo deu certo, seta essa propriedade como true, senão arque com as conseqüências
				context.setPropertyResolved(true);
			}
		}
		return result;
	}
}

E coloque isso no faces-config.xml:

<application>
      <el-resolver>
           MyElResolver
     </el-resolver>
    </application>

Mas é sempre bom dar uma conferida no Google.

T

Mas cara… a tree é montada automaticamente… eu apenas informo o metodo onde estao os dados… e o componente monta a arvore sozinho…
fica mais facil eu enviar um <f:param> e depois disso acessar o metodo certo, do que tentar usar esse ELResolver !
Acho q é isso… concorda ??? oO

L

Pode ser que um ELResolver seja um overkill ou não. Eu não sei como avaliar, pq não tenho muita noção de como sua aplicação é. Mas, qualquer coisa, se vc já tem a string no formato #{bean.method}, é só invocar esse código pra buscar a representação do método:

ELContext elContext = FacesContext.getCurrentInstance().getELContext();
MethodExpression methodExpression = FacesContext.getCurrentInstance().getApplication().getExpressionFactory().createMethodExpression(elContext, minhaExpressao, classeDeRetorno, classesDeParametro);
methodExpression.invoke(elContext, parametros);

Bom não sei se é isso. Mas acho que pode ajudar.

Foxlol

Acho que ELResolver deve funcionar então.

Falaeee Sr. Orlaaando :lol:

T

Resolvi o problema fazendo o sequinte :

A Tree da jsp

<rich:tree switchType="ajax" 
		               value="#{treeBean.data}" 
		               nodeFace="#{item.type}"
		               var="item" 
		               binding="#{treeBean.uiTree}">  
				         
				         <rich:treeNode type="#{item.type}">
					       <h:commandLink styleClass="linkTreeMenu" immediate="true" value="#{item.label}" actionListener="#{treeBean.actionEvent}" action="#{treeBean.actionTree}" >
				              <f:param id="idAction" name="id" value="#{item.action}" />
				           </h:commandLink>
				         </rich:treeNode>
		    </rich:tree>

No Bean da Tree

public String actionTree(){
		
		int Fim = this.classMethod.lastIndexOf(".");
		String Bean =  this.classMethod.substring(0, Fim);
		String Metodo =  this.classMethod.substring(Fim + 1, this.classMethod.length());
		
		try {
			 FacesContext context = FacesContext.getCurrentInstance();
			 //Todos meus Beans herdam de ManagedBean
			 ManagedBean newBean = ((ManagedBean) context.getApplication().getVariableResolver().resolveVariable(context, Bean));
             
			 Method[] methods = newBean.getClass().getMethods();
			 Method method;
				
				int count = methods.length;
				for(int i=0; i<count;i++){
				    method = methods[i];
				    if(method.getName().equals(Metodo)){
				       try {
						    return (String)  method.invoke(newBean,null);
							//Entrou no Metodo certo do Bean certo e retornou a String pra redirecionar a pagina
				       } catch (Exception e) {} 
				       break;
				    }
				}
		
		} catch (Exception e) {}
		return null;
	}

	public void actionEvent(ActionEvent event) {
		UIParameter component = (UIParameter) event.getComponent().findComponent("idAction");
		this.classMethod = (String) component.getValue();
		// this.classMethod = "bean.incluir" ou "beanDois.consultar" etc..
	}

Nesse caso a Tree é o Menu do sistema, que tem todos seus itens cadastrado no banco e ela é montada a partir dai.
Funcionou beleza…
Obrigado pela atenção aew… xD

Criado 31 de outubro de 2007
Ultima resposta 1 de nov. de 2007
Respostas 10
Participantes 4