Botão excluir em dataTable [RESOLVIDO]

Pessoal bom dia, minha dúvida refere-se ao pequeno programa que estou fazendo abaixo.

Como vocês podem perceber estou usando JSF para criar um formulário que cadastra as categorias com seus respectivos nomes e descrições. O problema está nesses pequenos botões que eu criei para excluir e editar. O editar eu ainda não tratei, então não tenho duvidas sobre ele por enquanto, mas o excluir quando é clicado chama um método “excluir” lá do meu bean, esse método usa o valor digitado no formulário para saber o que ele tem que excluir.

Ou seja o fato de ter um botão excluir sendo gerado em cada linha não está fazendo diferença nenhuma porque o usuário continua tendo que digitar o valor no campo do formulário para excluir o que ele quer.

Dúvida: como eu faço para que cada excluir seja capaz de excluir apenas a linha em que ele foi criado sem que o usuário digite o valor no formulário acima do dataTable.

Primeiro o código do meu bean:

package br.com.entun.control;

import java.util.ArrayList;
import java.util.List;

import javax.faces.model.SelectItem;

import br.com.entun.dao.CategoriaDao;
import br.com.entun.entidade.Categoria;

public class CategoriaBean {
	
	//ATRIBUTOS
	private Categoria categoria = new Categoria();
	
	private List<SelectItem> itensCategorias;
	
	private List<Categoria> categorias = new ArrayList<Categoria>();
	
	private CategoriaDao categoriaDao = new CategoriaDao();

	//METODOS
	public String inserir(){
		categoriaDao.inserir(categoria);
		categoria = new Categoria();
		AtualizarVariaveis();
		return "cadastrarCategoria";
	}
	
	public String excluir(){
		Categoria categ = categoriaDao.consultar(categoria.getNome());
		categoriaDao.desvincularCategorias(categ.getId());
		categoriaDao.excluir(categ);
		categoria = new Categoria();
		AtualizarVariaveis();
		return "cadastrarCategoria";
	}
	
	public CategoriaBean(){
		AtualizarVariaveis();
	}
	
	private void AtualizarVariaveis(){
		categorias = categoriaDao.consultar();
		itensCategorias = new ArrayList<SelectItem>();
		List<Categoria> categs = categorias;
		for (Categoria categ : categs){
			itensCategorias.add(new SelectItem(categ.getNome()));
		}
	}

	public List<SelectItem> getItensCategorias() {
		return itensCategorias;
	}

	public Categoria getCategoria() {
		return categoria;
	}

	public void setCategoria(Categoria categoria) {
		this.categoria = categoria;
	}

	public List<Categoria> getCategorias() {
		return categorias;
	}
	
}

Agora o código do meu JSP:

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<%@ taglib prefix="f" uri="http://java.sun.com/jsf/core"%>
<%@ taglib prefix="h" uri="http://java.sun.com/jsf/html"%>
<%@ taglib uri="http://richfaces.org/a4j" prefix="a4j"%>
<%@ taglib uri="http://richfaces.org/rich" prefix="rich"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Cadastro de Categorias</title>
</head>
<body>
	<f:view>
		<h:form>
			<rich:panel>
				<f:facet name="header">
					<h:outputText value="Cadastro de categorias" />
				</f:facet>
				<h:panelGrid columns="2">
					<h:outputText value="Nome:" />
					<h:inputText value="#{categoriaBean.categoria.nome }" />
					<h:outputText value="Descrição:" />
					<h:inputText value="#{categoriaBean.categoria.descricao }" />
					<h:commandLink value="Cadastrar" action="#{categoriaBean.inserir }" />
					<h:commandLink value="Voltar" action="cadastrarRotacao" />
				</h:panelGrid>
			</rich:panel>

			<rich:dataTable value="#{categoriaBean.categorias }" var="categoria"
				width="400">
				<f:facet name="header">
					<h:outputText value="Categorias Cadastradas" />
				</f:facet>
				<rich:column>
					<f:facet name="header">
						<h:outputText value="Id" />
					</f:facet>
					<h:outputText value="#{categoria.id }" />
				</rich:column>
				<rich:column>
					<f:facet name="header">
						<h:outputText value="Nome" />
					</f:facet>
					<h:outputText value="#{categoria.nome }" />
				</rich:column>
				<rich:column colspan="2">
					<f:facet name="header">
						<h:outputText value="Descrição" />
					</f:facet>
					<h:outputText value="#{categoria.descricao }" />
				</rich:column>
				
				<rich:column width="22">
					<h:commandLink action="#{categoriaBean.excluir}">
						<h:graphicImage width="10" height="10" value="imagens/excluir.png" />
					</h:commandLink>
					<h:commandLink action="#{categoriaBean.editar }">
						<h:graphicImage width="10" height="10" value="imagens/editar.png" />
					</h:commandLink>
				</rich:column>
			</rich:dataTable>
		</h:form>
	</f:view>
</body>
</html>

Primeiro, instancie os objetos no construtor do backingBean e não na declaração.

Depois faça o seguinte

<h:commandLink action="#{categoriaBean.excluir}">
<h:graphicImage width=“10” height=“10” value=“imagens/excluir.png” />
<f:setPropertyActionListener target="#{categoriaBean.categoria.id}" value="#{categoria.id}"/>
</h:commandLink>

<h:commandLink action="#{categoriaBean.editar}">
<h:graphicImage width=“10” height=“10” value=“imagens/editar.png” />
<f:setPropertyActionListener target="#{categoriaBean.categoria.id}" value="#{categoria.id}"/>
</h:commandLink>

Essa tag serve para você setar o objeto da linha do dataTable em um do backing Bean. Não lembro se a do jsf 1.2 é assim, mas se não for deve ser algo pareceido

marcelo.silva muito obrigado funcionou direitinho.

Fiz as alterações e resolveu, só me ajude com uma coisa aqui: porque você pediu para colocar as instâncias no construtor do backingBean e não na declaração? Boa prática? Bug eminente? E só pra tirar a dúvida eu to usando JSF 1.2 mesmo então é assim que se faz.

Você não usará esses atributos até que a classe seja instanciada, ok? Então para quê instanciar antes? Ocupar memória? :wink:

E outra, seu backingBean deve implementar a interface java.io.Serializable assim como seus modelos (Categoria, no caso), devem implementar também

Entendi sobre a ocupação da memória, mas se não for muita pertinência, a interface java.io.Serializable não serve apenas para referenciar objetos que estão em outro servidor de aplicação? Tipo no caso de uma clusterização por exemplo?

Se for pra isso mesmo eu acho que não precisaria implementar a interface já que estou fazendo uma aplicação bem simples por enquanto, então, sabe me explicar isso?

O servidor de aplicação serializa os objetos para o disco e deixa mais free memory :stuck_out_tongue: