ManagedBean em um HtmlCommandButton - AJUDA

29 respostas
J

Gostaria de saber como eu faço para criar um HtmlCommandButton, isso em jsf, nao por algum codigo html, que no actionlistner eu posso fazer que ao clicar chame um managedbean, hoje eu tenho o codigo assim:

BotoesListner acao = new BotoesListner();
botao = new HtmlCommandButton();
botao.setValue(value);
botao.addActionListener( ** aqui Iria um managedbean **));

29 Respostas

dev.rafael

Devo recorda-lo de q é extremamente não recomendado a criação de componentes do JSF fora da view, sem falar é uma péssima prática. Mas vai lá.

botao.addActionListener(new ActionListener() {
    @Override public void processAction(ActionEvent e) {
        FacesContext fctx = FacesContext.getCurrentInstance();
        ELContext elctx = fctx.getELContext();
        ELResolver resolver = elctx.getELResolver();
        MyBean mb = (MyBean) resolver.getValue(elctx, null, "{mybean}");
        mb.doSomething();
    }
});
J

Na verdade nao sao praticas que estao sendo usadas, e sim testes, nunca fiz nada com jsf, e estou tentando desenvolver algo, logo estou aprendendo no desenvolvimento (falta de tempo)
O que na verdade estou tentando fazer é o seguinte:
Tenho alguns metodos que criam a tela dinamicamente, (direto do banco, somente informando a tabela e a tela sai pronta com objetos e tudo) e o que eu estou me batendo é em conseguir pegar os dados que serao digitados nesses objetos e gravar no banco, por exemplo:
codigo = 01
nome = maria
estado = SC

esses dados [01,maria,SC] e conseguir gravar no banco, já que no meu xhtml eu nao tenho nada, é tudo criado dinamicamente.
Saberia como seria a melhor pratica em se fazer, qual melhor metodo pra se usar? Se tiveres como me ajudar. Grato!

dev.rafael

Se vc estiver usando JSF2, então vc pode criar o seu próprio componente form p/ cria os subcomponentes dinamicamente com base nas informações retornadas da base de dados. Os components podem criar subcomponentes manualmente durante o evento PostAddToViewEvent. Sem isso vc pode encontrar alguns problemas com o ciclo de vida do JSF.

J

dev.rafael, nao querendo abusar da tua ajuda, mas respondendo tua pergunta, sim uso JSF2.0, tomcat 7.0

eu tenho um managedbean que cria a minha tela e tenho uma classe que cria os objetos conforme eu passo os parametros

vou mostrar a classe que cria os objetos…(parte dela, já que o processo é parecido)

public class CriaObjetos {
	private HtmlInputText texto;

	public UIComponent CriaTexto(Integer maxLength, Integer size,
			Boolean readOnly, Boolean required, Boolean styleObrigatorio,
			String nome) {
		Complementos comple = new Complementos();

		texto = new HtmlInputText();
		texto.setMaxlength(maxLength);
		texto.setSize(size);
		texto.setReadonly(readOnly);
		texto.setRequired(required);
		texto.setId(nome);
		
		/* caso for obrigatorio terá uma formatacao diferente */
		if (styleObrigatorio) {
			texto.setStyle(comple.getStyleObrigatorio());
		}
		//texto.setOnkeydown("if(event.keyCode==9) {event.keyCode=13}");
		/*
		 * caso mesmo sendo obrigatorio mas readonly, ficara com a segunda
		 * formatacao
		 */
		if (texto.isReadonly()) {
			texto.setStyle(comple.getSytleReadOnly());
		}
		return texto;
	}
}

e aqui vai parte do meu managedbean que cria os objetos.

public HtmlPanelGrid getCriaCampos() throws SQLException {
   private HtmlPanelGrid criaCampos;
   cxCampo = new CxCampos();
   cria = new CriaObjetos();

   ArrayList<NomeCampos> listaLinha = null;
    try {
	listaLinha = cxCampo.ListarLinhas(comple.getTabela());
    } catch (Exception e) {
	e.printStackTrace();
    }
    criaCampos = new HtmlPanelGrid();
    for (int i = 0; i < listaLinha.size() && i < listaLinha.size(); i++) {
    if (listaLinha.get(i).Registros(rec).equals("character varying")) {  
        try {
		rec = rec + 2;
		criaCampos.getChildren().add(
		    cria.CriaTexto(Integer.parseInt(splitComentario
			.get(1)), Integer
				.parseInt(splitComentario.get(1)),
		     Boolean.parseBoolean(splitComentario
			.get(2)), Boolean
			.parseBoolean(splitComentario
			.get(2)), Boolean
			.parseBoolean(splitComentario
			.get(4)), campo));
         } catch (Exception e) {
		System.out.println("Erro ao adicionar campo. "+ e.getMessage());
	}
    }
    return criaCampos;
}

Como tu pode ver, eu uso uma classe chamando a outra, simples ate entao…passos os parametros conforme eu pego do banco que sao fixos e ele consegue gerar minha tela, ate entao tudo certo para gerar, o problema é como conseguir pegar os dados digitados.

No meu xhtml eu somente faço isso…

<h:panelGrid columns="2" binding="#{criaTela.criaCampos}" />

Como que eu poderia fazer pra aplicar o PostAddToViewEvent nesse caso, ou fazer uma melhor pratica para conseguir extrair os dados digitados nos objetos?
Abraço e obrigado!

dev.rafael

Na verdade eu tenho q te agradecer pq a solução q eu vou te apresentar eu só descobri p/ conta deste post. Ai vai, no seu ManagedBean vc vai fazer o seguinte:

@Named
@RequesterScoped
public class FormBuilder implements ComponentSystemListener {

    public void processEvent(ComponentSystemEvent e) {
        // Aqui vc coloca o código q vai criar o form.
    }

}

Ai na sua view:

<h:form>
    <f:event type="javax.faces.event.PostAddToViewEvent" listener="#{formBuilder.processEvent}" />
</h:form>

De fato vc nem mesmo precisa q o seu ManagedBean FormBuilder implemente a interface ComponentSystemListener ou o método se chame processEvent, qualquer método q receba um ComponentSystemEvent pode ser usado. Embora me pareça bem coerente implementar a ComponentSystemListener.

Só mais uma coisa, usar essa solução é importante pq garante q os componentes serão criados como parte do processo de construção da árvore de componentes, realizado pelo JSF na fase RestoreView, e não no meio do processamento de um action. Outro detalhe importante é q vc nunca deve instanciar componentes do JSF usando o operador new. Ao invés disse faça:

FacesContext ctx = FacesContext.getCurrentInstance();
Application app = ctx.getApplication();
HtmlInputText input = (HtmlInputText) app.createComponent(HtmlInputText.COMPONENT_TYPE);

Dessa forma vc permite q o JSF processe quaisquer anotações presentes nos componentes criados e execute quaisquer callbacks de ciclo de vida presentes, coisa q não aconteceria se vc usasse new. Se vc estiver usando CDI e achar esse código meio extenso vc pode sempre criar um Producer p/ criar Application p/ vc e então apenas injeta-lo no seu ManagedBean.

J

Cara, vo testar isso sim, e assim que que tiver alguma novidade ou se nao for stress demais, alguma duvida eu posto aqui…
desde já obrigado!

Abraço!

J

dev.rafael, eu fiz como tu me disse...mas tive alguns problemas:
Quando carrega nao mostra mais nada em tela, mas se eu debugar passar por todas as linhas, faz perfeitinho..so nao mostra nada em tela..e tbm nao dah erro.

e a minha duvida que nao quer calar, ou eu que nao entendi como que eu vo fazer (depois que conseguir fazer funcionar e mostrar em tela, claro) para pegar os dados inseridos nos objetos?

basicamente meu codigo ficou assim:

@NamedEvent
@RequestScoped
@ManagedBean
public class CriaTeste implements ComponentListener {
	// declaraçao dos objetos
	private String campo;
	private int rec = 0;

	/* declaraçao das classes */
	private CxCampos cxCampo;
	private HtmlPanelGrid criaCampos;
	private Funcoes fun;
	private Complementos comple;
	private CriaObjetos cria;

	//HtmlPanelGrid
	public void processEvent(ComponentSystemEvent e) throws SQLException{
		cxCampo = new CxCampos();
		comple = new Complementos();
		fun = new Funcoes();
		cria = new CriaObjetos();

		ArrayList<NomeCampos> listaLinha = null;
		try {
			listaLinha = cxCampo.ListarLinhas(comple.getTabela());
		} catch (Exception e1) {
			e1.printStackTrace();
		}
		criaCampos = new HtmlPanelGrid();
		for (int i = 0; i < listaLinha.size() && i < listaLinha.size(); i++) {
			/*
			 * quebra o comentario para poder formatar os objetos e renomear os
			 * labels
			 */
			ArrayList<String> splitComentario = null;
			splitComentario = fun.QuebraComentario(listaLinha.get(i).Registros(
					rec + 4));

			if (listaLinha.get(i).Registros(rec).equals("field")) {
				rec++;
				campo = listaLinha.get(i).Registros(rec);
				try {
					rec++;
					criaCampos.getChildren().add(
							cria.CriaLabel((splitComentario.get(5) + ":")));
				} catch (Exception e1) {
					System.out.println("Erro ao adicionar campo. "
							+ e1.getMessage());
				}
			}
			System.out.println(listaLinha.get(i).Registros(rec));
			if (listaLinha.get(i).Registros(rec).equals("type")) {
				rec++;
				// Integer
				if (listaLinha.get(i).Registros(rec).equals("integer")) {
					System.out.println(splitComentario.get(0));
					if (splitComentario.get(0).equals("fk")
							| splitComentario.get(0).equals("fk2")) {
						ArrayList<String> listaFk = null;
						try {
							listaFk = fun
									.Comentarios(comple.getTabela(), campo);
						} catch (SQLException e1) {
							System.out
									.println("Erro ao carregar fks para combo. "
											+ e1.getMessage());
						}
						try {
							rec = rec + 2;
							criaCampos.getChildren().add(
									cria.CriaCombo(listaFk, Boolean
											.parseBoolean(splitComentario
													.get(4)), campo));
						} catch (Exception e1) {
							System.out.println("Erro ao adicionar campo. "
									+ e1.getMessage());
						}
					} else if (splitComentario.get(0).equals("true")) {
						try {
							rec = rec + 2;
							criaCampos
									.getChildren()
									.add(cria.CriaTexto(
											Integer.parseInt(splitComentario
													.get(1)),
											Integer.parseInt(splitComentario
													.get(1)),
											Boolean.parseBoolean(splitComentario
													.get(2)),
											Boolean.parseBoolean(splitComentario
													.get(2)),
											Boolean.parseBoolean(splitComentario
													.get(4)), campo));
						} catch (Exception e1) {
							System.out.println("Erro ao adicionar campo. "
									+ e1.getMessage());
						}
					}
					// Varchar
				} else if (listaLinha.get(i).Registros(rec)
						.equals("character varying")) {
					try {
						rec = rec + 2;
						criaCampos.getChildren().add(
								cria.CriaTexto(Integer.parseInt(splitComentario
										.get(1)), Integer
										.parseInt(splitComentario.get(1)),
										Boolean.parseBoolean(splitComentario
												.get(2)), Boolean
												.parseBoolean(splitComentario
														.get(2)), Boolean
												.parseBoolean(splitComentario
														.get(4)), campo));
					} catch (Exception e1) {
						System.out.println("Erro ao adicionar campo. "
								+ e1.getMessage());
					}
					// Date
				} else if (listaLinha.get(i).Registros(rec).equals("date")) {
					try {
						rec = rec + 2;
						criaCampos.getChildren().add(
								cria.CriaTexto(Integer.parseInt(splitComentario
										.get(1)), Integer
										.parseInt(splitComentario.get(1)),
										Boolean.parseBoolean(splitComentario
												.get(2)), Boolean
												.parseBoolean(splitComentario
														.get(2)), Boolean
												.parseBoolean(splitComentario
														.get(4)), campo));
					} catch (Exception e1) {
						System.out.println("Erro ao adicionar campo. "
								+ e1.getMessage());
					}
					// Numeric
				} else if (listaLinha.get(i).Registros(rec).equals("numeric")) {
					try {
						rec = rec + 2;
						criaCampos.getChildren().add(
								cria.CriaTexto(Integer.parseInt(splitComentario
										.get(1)), Integer
										.parseInt(splitComentario.get(1)),
										Boolean.parseBoolean(splitComentario
												.get(2)), Boolean
												.parseBoolean(splitComentario
														.get(2)), Boolean
												.parseBoolean(splitComentario
														.get(4)), campo));
					} catch (Exception e1) {
						System.out.println("Erro ao adicionar campo. "
								+ e1.getMessage());
					}
					// Boolean
				} else if (listaLinha.get(i).Registros(rec).equals("boolean")) {
					try {
						rec = rec + 2;
						criaCampos.getChildren().add(
								cria.CriaCombo(comple.TipoSimNao(), Boolean
										.parseBoolean(splitComentario.get(4)),
										campo));
					} catch (Exception e1) {
						System.out.println("Erro ao adicionar campo. "
								+ e1.getMessage());
					}
					// Time
				} else if (listaLinha.get(i).Registros(rec).equals("time")) {
					try {
						rec = rec + 2;
						criaCampos.getChildren().add(
								cria.CriaTexto(Integer.parseInt(splitComentario
										.get(1)), Integer
										.parseInt(splitComentario.get(1)),
										Boolean.parseBoolean(splitComentario
												.get(2)), Boolean
												.parseBoolean(splitComentario
														.get(2)), Boolean
												.parseBoolean(splitComentario
														.get(4)), campo));
					} catch (Exception e1) {
						System.out.println("Erro ao adicionar campo. "
								+ e1.getMessage());
					}
				}
			}
		}
		criaCampos.getChildren().add(
				cria.CriaBotao("Salvar", "leite_linhas", criaCampos));
//		return criaCampos;
	}


	@Override
	public void componentHidden(ComponentEvent e) {
		// TODO Auto-generated method stub
		
	}


	@Override
	public void componentMoved(ComponentEvent e) {
		// TODO Auto-generated method stub
		
	}


	@Override
	public void componentResized(ComponentEvent e) {
		// TODO Auto-generated method stub
		
	}


	@Override
	public void componentShown(ComponentEvent e) {
		// TODO Auto-generated method stub
		
	}

}

Esses ultimos overrides foi necessario criar por estar implementado o ComponentListener
O criCampos é aquela classe que cria os meus objetos (botao, text, labels...)

dev.rafael

Use o método setValueExpression(String, ValueExpression) p/ fazer o binding dos seus componentes. Deve funcionar:

FacesContext fctx = FacesContext.getCurrentInstance();
ELContext elctx = fctx.getELContext();
ExpressionFactory exprFactory = ExpressionFactory.newInstance();
ValueExpression expr = exprFactory.createValueExpression(elctx, "#{myMBean.property}", String.class);
J

No caso isso vai dentro da mesma procedure que eu invoco no meu xhtml? ou em uma nova?

dev.rafael

É foi mal, eu esqueci uma linha:

FacesContext fctx = FacesContext.getCurrentInstance();  
ELContext elctx = fctx.getELContext();  
ExpressionFactory exprFactory = ExpressionFactory.newInstance();  
ValueExpression expr = exprFactory.createValueExpression(elctx, "#{myMBean.property}", String.class);  

// Faltou isso...
Application app = fctx.getApplication();
HtmlInputText input = app.createComponent(HtmlInputText.COMPONENT_TYPE);
input.setValueExpression(expr);

Q vai ter o mesmo efeito de vc fazer isso:

<h:inputText value="#{myMBean.property}" />
J
public UIComponent CriaBotao(String value, String tabela, HtmlPanelGrid criaCampos) throws SQLException {
		BotoesListner acao = new BotoesListner();
		botao = new HtmlCommandButton();
		botao.setValue(value);
		
		acao.setTipoBotao(botao.getValue());
		acao.setTipoTabela(tabela);
		
		//botao.addActionListener(acao.AcaoBotao(criaCampos));
		botao.addActionListener(new ActionListener() {
		    @Override 
		    public void processAction(ActionEvent e) {
		        FacesContext fctx = FacesContext.getCurrentInstance();
		        ELContext elctx = fctx.getELContext();
		        ELResolver resolver = elctx.getELResolver();
		        KeyObjetos mb = (KeyObjetos) resolver.getValue(elctx, null, "#{keyObjeto.grava}");
		        mb.getGrava();
		    }
		});
		return botao;
	}

Cara, nesse exemplo que vc me deixou do botao, ele nao executa o meu MB, tm algo que eu esteja fazend do e errado? ai é o meu metodo d criaçao do botao.

dev.rafael

Vc não precisa de um listener. Vc pode setar o atributo action to seu Command p/ executar um action p/ vc.

HtmlCommandButton submit = (HtmlCommandButton) app.createComponent(HtmlCommandButton.COMPONENT_TYPE);
submit.setValue("Submit");
submit.setId("submit");
submit.setActionExpression(ef.createMethodExpression(elctx, "#{formBuilder.turnToMsgOut}", String.class, new Class<?>[0]));

Aqui vc pode ver o problema com o JSF. Isso funciona se, e somente se, vc settar manualmente o Id do CommandButton. Se vc não fizer isso ele simplesmente ignora a actionExpression. Vai entender :?

J

Cara esse “ef.” é de que propriedade? e o “app.” é de qua propriedade?

dev.rafael

Desculpe, devia ter postado o código completo:

Application app;
ELContext elctx;
ExpressionFactory ef;
J

Cara, eu to desanimado…de serio a parte mais dificil que era fazer a tela e grid dinamicamente eu consegui, mas nao tem cristo de funcionar o botao…ele nao faz nada
nao funciona, nao sai do chao.

meu input

FacesContext fctx = FacesContext.getCurrentInstance();  
		ELContext elctx = fctx.getELContext();  
		ExpressionFactory exprFactory = ExpressionFactory.newInstance();  
		//ValueExpression expr = exprFactory.createValueExpression(elctx, "#{keyObjetos." + nome + "}", String.class);  
		ValueExpression expr = exprFactory.createValueExpression(elctx, "#{keyObjetos.nome}", String.class);
		
		Application app = fctx.getApplication();
		HtmlInputText texto = (HtmlInputText) app.createComponent(HtmlInputText.COMPONENT_TYPE);
		texto.setId(nome);
		texto.setValueExpression(nome, expr);
		
		//texto = new HtmlInputText();
		texto.setMaxlength(maxLength);
		texto.setSize(size);
		texto.setReadonly(readOnly);
		texto.setRequired(required);

minha managedbean que contem os campos e a procedure para gravar

@ManagedBean
@SessionScoped
public class KeyObjetos {
	private Integer codigo;
	private String nome;
	
	public Integer getCodigo() {
		return codigo;
	}
	public void setCodigo(Integer codigo) {
		this.codigo = codigo;
	}
	public String getNome() {
		return nome;
	}
	public void setNome(String nome) {
		this.nome = nome;
	}
	
	
	public HtmlPanelGrid Grava(){
		/*somente pra teste*/
		HtmlPanelGrid grid = new HtmlPanelGrid();
		System.out.println(getNome());
		return grid;
	}
}

e por fim o botao que deveria chamar para gravar

FacesContext fctx = FacesContext.getCurrentInstance();  
		ELContext elctx = fctx.getELContext();  
		ExpressionFactory exprFactory = ExpressionFactory.newInstance();
		Application app = fctx.getApplication();
		HtmlCommandButton botao = (HtmlCommandButton) app.createComponent(HtmlCommandButton.COMPONENT_TYPE);
		botao.setValue(value);
		botao.setActionExpression(exprFactory.createMethodExpression(elctx, "#{keyObjeto.grava}", String.class, new Class<?>[0]));

valeu ai pela paciencia cara, abraço!

dev.rafael

Kra, no outro post eu coloquei q vc precisa setar explicitamente o id do seu HtmlCommandButton:

HtmlCommandButton botao = (HtmlCommandButton) app.createComponent(HtmlCommandButton.COMPONENT_TYPE);  
botao.setId("submit"); // É preciso fazer isso explicitamente!?
botao.setValue(value);
botao.setActionExpression(exprFactory.createMethodExpression(elctx, "#{keyObjeto.grava}", String.class, new Class<?>[0]));

Só não me pergunte pq as coisas funcionam assim.

J

Entao cara, eu coloquei agora o setId, mas sem sucesso, simplesmente nao funciona, nem erro dá, nada acontece, clica no botao como se nao tivesse nenhuma ação pra ele.

public UIComponent CriaBotao(String value) {
   FacesContext fctx = FacesContext.getCurrentInstance();  
   ELContext elctx = fctx.getELContext();  
   ExpressionFactory exprFactory = ExpressionFactory.newInstance();
   Application app = fctx.getApplication();
   HtmlCommandButton botao = (HtmlCommandButton) app.createComponent(HtmlCommandButton.COMPONENT_TYPE);
   botao.setId("submit");
   botao.setValue("Submit");
   botao.setActionExpression(exprFactory.createMethodExpression(elctx, "#{keyObjeto.grava}", String.class, new Class<?>[0]));		

   return botao;
}

O legal se eu der um print :

System.out.println(botao.getActionExpression().getExpressionString());

ele me retorna : #{keyObjeto.grava}

Será que tem alguma coisa de errado com o meu managedbean?

@ManagedBean
@SessionScoped
public class KeyObjetos {
	private Integer codigo;
	private String nome;
	
	public Integer getCodigo() {
		return codigo;
	}
	public void setCodigo(Integer codigo) {
		this.codigo = codigo;
	}
	public String getNome() {
		return nome;
	}
	public void setNome(String nome) {
		this.nome = nome;
	}
	
	
	public HtmlPanelGrid getGrava(){
		/*somente pra teste*/
		HtmlPanelGrid grid = new HtmlPanelGrid();
		System.out.println(getNome());
		return grid;
	}
}

abraço

dev.rafael

Creio q não é nada de errado com o seu código. Procurando na internet eu encontrei outras pessoas com o mesmo problema. Me parece mais um bug do CommandButton ou algum comportamento p/ o qual eu não achei documentação. De qualquer forma tente setar “rendered” explicitamente tb:

button.setId("submit");
button.setRendered(true);

Aparentemente isso funcionou p/ alguém num desses forums. P/ mim isso não foi preciso mas talvez te ajude.

J

Cara, infelizmente sem sucesso, nao executa nada, tentei trocar a ordem dos valores, id, value e rendered pra ver se isso resultava em alguma coisa tbm nao aconteceu nada, simplesmente nao faz nada

e o estranho é que se eu pegar o codigo fonte da pagina que ele cria ele me tras assim:

<td><input id="submit1" type="submit" name="submit1" value="Submit1" /></td>

sem por exemplo a opçao action do botao…

dev.rafael

Kra, não há nada de errado com o HTML gerado. Deve ser isso mesmo. Só o id é q está um pouco estranho. O id do input gerado deveria ser id_do_form:id_commandButton. Confere o form ai.

J

Olha so, acho que agora apareceu uma luz…ahaha…esse é o codigo criado pelo sistema, no caso sem usar o

<h:form>
//
</form>

<h:panelGrid columns=“2” binding="#{criaTela.criaCampos}" />

<!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"><head>
	<title>Exemplo de base</title></head>
<body><table>
<tbody>
<tr>
<td><label>
Código:</label></td>
<td><input id="codigo" type="text" name="codigo" maxlength="6" size="6" style="color:black;background:LightGrey" readonly="readonly" /></td>
</tr>
<tr>
<td><label>
Descrição:</label></td>
<td><input id="descricao" type="text" name="descricao" maxlength="50" size="50" style="color:black;background:Cornsilk" /></td>
</tr>
<tr>
<td><input id="submit1" type="submit" name="submit1" value="Submit1" /></td>
</tr>
</tbody>
</table>

</body>
</html>

agora usando o <h:form>

<h:form>
<h:panelGrid columns=“2” binding="#{criaTela.criaCampos}" />
</h:form>

<!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"><head>
	<title>Exemplo de base</title></head>
<body>
<form id="j_idt6" name="j_idt6" method="post" action="/Leite/TelaLinha.jsf" enctype="application/x-www-form-urlencoded">
<input type="hidden" name="j_idt6" value="j_idt6" />
<table>
<tbody>
<tr>
<td><label>
Código:</label></td>
<td><input id="j_idt6:codigo" type="text" name="j_idt6:codigo" maxlength="6" size="6" style="color:black;background:LightGrey" readonly="readonly" /></td>
</tr>
<tr>
<td><label>
Descrição:</label></td>
<td><input id="j_idt6:descricao" type="text" name="j_idt6:descricao" maxlength="50" size="50" style="color:black;background:Cornsilk" /></td>
</tr>
<tr>
<td><input id="j_idt6:submit1" type="submit" name="j_idt6:submit1" value="Submit1" /></td>
</tr>
</tbody>
</table>
<input type="hidden" name="javax.faces.ViewState" id="javax.faces.ViewState" value="-85512255061205404:3298559510300301891" autocomplete="off" />
</form>
</body>
</html>

Acho que era isso que tu tava falando, certo?

o detalhe agora, é que se eu clicar no botao, agora gera pelo menos um erro…(nunca feliz em ver um erro como agora…ahaha)

javax.servlet.ServletException: Index: 14, Size: 10
javax.faces.webapp.FacesServlet.service(FacesServlet.java:325)

dev.rafael

Pelo q entendi vc esqueceu da tag <h:form>. Ok, ai vai uma dica:

Vc nunca, nunca… nunca,nunca,nunca,nunca,nunca,nunca,nunca,nunca,nunca,nunca,nunca,nunca,nunca,nunca,nunca,nunca,nunca,nunca,nunca, deve se esquecer dessa tag. Senão não tem como submeter nada p/ o servidor. Componentes UICommand (h:commandButton, h:commandLink) dependem dela.

Agora posta ai o restante do seu StackTrace p/ vc se eu posso te ajudar.

J

é na verdade eu so colocava a linha que invocava o meu MB…ahaha…mas dica que com certeza que nao vou esquecer tao facil…husaihsuaihasi

cara, nao sei se é isso que tu quer mas lá vai:

20/09/2010 10:38:26 org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet Faces Servlet threw exception
java.lang.IndexOutOfBoundsException: Index: 14, Size: 10
	at java.util.ArrayList.RangeCheck(ArrayList.java:547)
	at java.util.ArrayList.get(ArrayList.java:322)
	at Fontes.NomeCampos.Registros(NomeCampos.java:53)
	at MBs.CriaTela.getCriaCampos(CriaTela.java:49)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:597)
	at javax.el.BeanELResolver.getValue(BeanELResolver.java:64)
	at javax.el.CompositeELResolver.getValue(CompositeELResolver.java:55)
	at com.sun.faces.el.FacesCompositeELResolver.getValue(FacesCompositeELResolver.java:72)
	at org.apache.el.parser.AstValue.getValue(AstValue.java:168)
	at org.apache.el.ValueExpressionImpl.getValue(ValueExpressionImpl.java:192)
	at com.sun.faces.facelets.el.TagValueExpression.getValue(TagValueExpression.java:102)
	at com.sun.faces.application.ApplicationImpl.createComponentApplyAnnotations(ApplicationImpl.java:1840)
	at com.sun.faces.application.ApplicationImpl.createComponent(ApplicationImpl.java:1070)
	at com.sun.faces.facelets.tag.jsf.ComponentTagHandlerDelegateImpl.createComponent(ComponentTagHandlerDelegateImpl.java:320)
	at com.sun.faces.facelets.tag.jsf.ComponentTagHandlerDelegateImpl.apply(ComponentTagHandlerDelegateImpl.java:145)
	at javax.faces.view.facelets.DelegatingMetaTagHandler.apply(DelegatingMetaTagHandler.java:114)
	at javax.faces.view.facelets.DelegatingMetaTagHandler.applyNextHandler(DelegatingMetaTagHandler.java:120)
	at com.sun.faces.facelets.tag.jsf.ComponentTagHandlerDelegateImpl.apply(ComponentTagHandlerDelegateImpl.java:204)
	at javax.faces.view.facelets.DelegatingMetaTagHandler.apply(DelegatingMetaTagHandler.java:114)
	at javax.faces.view.facelets.CompositeFaceletHandler.apply(CompositeFaceletHandler.java:91)
	at com.sun.faces.facelets.compiler.NamespaceHandler.apply(NamespaceHandler.java:86)
	at javax.faces.view.facelets.CompositeFaceletHandler.apply(CompositeFaceletHandler.java:91)
	at com.sun.faces.facelets.compiler.EncodingHandler.apply(EncodingHandler.java:75)
	at com.sun.faces.facelets.impl.DefaultFacelet.apply(DefaultFacelet.java:145)
	at com.sun.faces.application.view.FaceletViewHandlingStrategy.buildView(FaceletViewHandlingStrategy.java:716)
	at com.sun.faces.application.view.StateManagementStrategyImpl.restoreView(StateManagementStrategyImpl.java:203)
	at com.sun.faces.application.StateManagerImpl.restoreView(StateManagerImpl.java:177)
	at com.sun.faces.application.view.ViewHandlingStrategy.restoreView(ViewHandlingStrategy.java:131)
	at com.sun.faces.application.view.FaceletViewHandlingStrategy.restoreView(FaceletViewHandlingStrategy.java:430)
	at com.sun.faces.application.view.MultiViewHandler.restoreView(MultiViewHandler.java:143)
	at com.sun.faces.lifecycle.RestoreViewPhase.execute(RestoreViewPhase.java:199)
	at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
	at com.sun.faces.lifecycle.RestoreViewPhase.doPhase(RestoreViewPhase.java:110)
	at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118)
	at javax.faces.webapp.FacesServlet.service(FacesServlet.java:312)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:243)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:201)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:163)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:108)
	at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:556)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:402)
	at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:249)
	at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:267)
	at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:245)
	at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:260)
	at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
	at java.lang.Thread.run(Thread.java:619)
dev.rafael

Tem um bug bem aqui:

Fontes.NomeCampos.Registros(NomeCampos.java:53)  -
MBs.CriaTela.getCriaCampos(CriaTela.java:49)

E pelo q diz a sua StackTrace, parece q vc está acessando um índice 14 em uma lista de tamanho 10.

java.lang.IndexOutOfBoundsException: Index: 14, Size: 10

Confere lá!

J

Cara, acho que agora vai funcionar sim, pelo menos está executando…so pra nivel de informaçao…
por exemplo, no botao ele chama outro managedbean, mas ao clicar nele, ele chama o mesmo managedbean que criou a tela, pra depois chamar o managedbean que executa o botao

No caso, isso é algum erro de codigo meu, ou seria normal?

dev.rafael

Creio q seja normal. Componentes UICommand (h:commandButton, h:commandLink) geram requisições chamadas de postback. Ou seja, eles fazem uma requisição post p/ a mesma página. Basta vc dar uma olhada no atributo “action” do form gerado p/ vc ver q ele aponta p/ a página atual. Como na página atual vc deve ter algo assim:

<h:form>
  <f:event type="javax.faces.event.PostAddToViewEvent" listener="#{formBuilder.processEvent}" />
</h:form>

É natural q ele chame o primeiro ManagedBean pois isso é parte do processo de construção da árvore de componentes.

Ai vai mais uma dica: Evite usar o atributo binding dos componentes JSF. Vc não precisa mais dele, e ele ainda pode causar uma série de problemas principalmente pq eles reduzem a legibilidade do seu código. Qualquer atributo de um componente da view pode ser alterado através da EL não necessitando binding apenas p/ alterar atributos.

<h:panelGrid columns="#{formBuilder.columnCount}">
...
</h:panelGrid>

Se isso for insuficiente p/ vc, vc sempre pode acessar a árvore de componentes no seu processEvent:

@Named
@RequestScoped
public class FormBuilder implements ComponentSystemEventListener {
// ...
  @Override
  public void processEvent(ComponentSystemEvent e) {
    // Assim vc pega o UIComponent dentro do qual a tag event se encontra.
    HtmlPanelGrid panel = (HtmlPanelGrid) e.getComponent();
  }
// ...
}
J

Deixa eu ve se entendi, a questao de voltar a MB anterior entao é normla, ok!
e para resolver isso, eu passaria no meu xhtml essa linha:

<h:form>
  <f:event type="javax.faces.event.PostAddToViewEvent" listener="#{testeTela.processEvent}" />
</h:form>

e jogo o meu codigo todo que cria a teminha tela dentro desse codigo aqui:

@Named
@RequestScoped
public class FormBuilder implements ComponentSystemEventListener {
// ...
  @Override
  public void processEvent(ComponentSystemEvent e) {
    //aqui vai o meu codigo todo que cria a tela..??
  }
// ...
}

Isso?, pq eu criei uma classe teste e fiz as implementaçoes como tu me disse…

public class TesteTela implements ComponentSystemEventListener{
	// declaraçao dos objetos
	private String campo;
	private int rec = 0;
	private int count = 0;

	/* declaraçao das classes */
	private CxCampos cxCampo;
	private HtmlPanelGrid criaCampos;
	private Funcoes fun;
	private Complementos comple;
	private CriaObjetos cria;
	
	@Override
	public void processEvent(ComponentSystemEvent arg0)
			throws AbortProcessingException {
		cxCampo = new CxCampos();
		comple = new Complementos();
		fun = new Funcoes();
		cria = new CriaObjetos();

		ArrayList<NomeCampos> listaLinha = null;

//...... Continua o codigo (no caso fica sem result né?)
    }
}

Mas ai na hora de chamar da erro:

javax.servlet.ServletException: /TelaLinha.xhtml @14,93 listener="#{testeTela.processEvent}": Target Unreachable, identifier ‘testeTela’ resolved to null
javax.faces.webapp.FacesServlet.service(FacesServlet.java:325)

dev.rafael

A sua classe TesteTela deve estar anotada com @ManagedBean se for JSF2 ou @Named se for JSF2 + CDI. Tb é uma boa prover um escopo: @RequestScoped, @SessionScoped, @ApplicationScoped, @ViewScoped (JSF2 only), @ConversationScoped (CDI only).

J

Entao, adicionei todo as anotaçoes, e funcionou, me trouxe legal a tela, so tive que fazer diferente, ao invez de

HtmlPanelGrid panel = (HtmlPanelGrid) e.getComponent();

escrevi assim:

e.getComponent().getChildren().add(criaCampos);

Porém ao clicar no botao, ele volta, como tu mesmo disse faz o processo Postback, chama a mesma classe para executar e gera os erros de novo.
Até chega cair na classe KeyObjetos, mas quando eu crio o meu inputext e seto para que ele seja “#{keyObjetos.nome}” que é um private meu, acaba nao passando o que foi digitado no inputext, e depois acontece o erro de novo.

Criado 15 de setembro de 2010
Ultima resposta 20 de set. de 2010
Respostas 29
Participantes 2