[Dúvida JSF/Facelets] Renderizando operações CRUD em uma lista [resolvido]

3 respostas
Ed.prog

Estou aprendendo JSF, e resolvi criar um blog pra testar. Mas empaquei criando um link "delete" para cada item de uma lista iterada num facelet. Tentei de algumas formas passar o atributo id do bean do artigo iterado para o id do artigo no managed bean, mas ainda não encontrei um jeito de fazer isso. Busquei algumas alternativas no google e encontrei uma nesse post de blog: http://www.laliluna.de/articles/first-java-server-faces-tutorial.html
Mas sei lá, achei meio deslocado esse jeito... não tem um jeito melhor de intercambiar atributos entre os beans?

O Facelet está dessa forma:

<?xml version="1.0" encoding="ISO-8859-1"?> 
<!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"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:rich="http://richfaces.org/rich">

	<ui:composition template="/template.xhtml">
			<ui:define name="pageTitle"> Início</ui:define>
			<ui:define name="pageHeader">				
			</ui:define>
			<ui:define name="pageContent">	
				<ui:repeat var="article" value="#{articleMb.dao.enabled}" size="5">
				
				
					<rich:panel>						
						<h:outputText styleClass="articleTitle" value="#{article.title}" />	
							
						<h:panelGroup styleClass="articleOperations" rendered="#{(request.remoteUser == article.author.email) or rich:isUserInRole('admin, moderator')}">							
							<h:form>
								<h:inputHidden value="#{articleMb.article.id}">#{article.id}</h:inputHidden>
								<h:commandLink action="#{articleMb.recycle}"><img   /> Remover</h:commandLink>
							</h:form>
							<h:outputText value=" " escape="false" />							
							<h:outputLink value="#{request.contextPath}/secure/edit.jsf"><img   /> Editar</h:outputLink>
						</h:panelGroup>									
						<div class="articleInfo">
							<h:outputFormat value="Postado {0, date, full} por #{article.author.name}.">
								<f:param value="#{article.date}"/>
							</h:outputFormat>							
						</div>						
						<rich:insert content="#{article.message}"/>
					</rich:panel>
					<br />
					
					
				</ui:repeat>						
			</ui:define>
	</ui:composition>

</html>

E o managed bean:

package br.com.todo.blog.managedbeans;

import java.util.Date;
import java.util.List;

import javax.ejb.EJB;
import javax.faces.context.FacesContext;
import javax.servlet.http.HttpServletRequest;

import br.com.todo.blog.ejb.ArticleDao;
import br.com.todo.blog.ejb.UserDao;
import br.com.todo.blog.ejb.entity.Article;
import br.com.todo.blog.ejb.entity.User;

public class ArticleMB{
	
	@EJB(name="ArticleDao", mappedName="ArticleDao/remote")
	private ArticleDao articleDao;
	private Article article;
	
	public String find(){		
		setArticle(articleDao.load(getArticle().getId()));		
		return getArticle().getId() != 0 ? "found" : "notFound";
	}
	
	public String persist(){		
		getArticle().setDate(new Date());
		getArticle().setEnabled(true);
		
		User author = new User();		
		String userId = getRemoteUser();
		if(userId == null)
			return "notPersisted";
		author = userDao.load(userId);
		getArticle().setAuthor(author);
		articleDao.save(getArticle());
		return "persisted";
	}
	public String update(){
		articleDao.update(getArticle());
		return "updated";
	}
	
	public String remove(){
		setArticle(getDao().load(getArticle().getId()));
		if(this.article == null) return "notFound";
		getDao().remove(article);				
		return "removed";
	}
	
	public String recycle(){
		setArticle(getDao().load(getArticle().getId()));
		if(this.article == null) return "notFound";
		getDao().recycle(article);				
		return "recycled";
	}
	
	public Article getArticle() {
		if(article == null)
			article = new Article();
		return article;
	}
	public void setArticle(Article article) {
		this.article = article;
	}

	public ArticleDao getDao() {
		return articleDao;
	}

	public void setDao(ArticleDao articleDao) {
		this.articleDao = articleDao;
	}

	public List<Article> listByAuthor() {		
		return articleDao.getByAuthor(getArticle().getAuthor());		
	}

	public String removeByAuthor() {
		articleDao.removeByAuthor(getArticle().getAuthor());	
		return "removedByAuthor";
	}	
	private String getRemoteUser(){
		HttpServletRequest request = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();
		return request.getRemoteUser();
	}
	
	
}

3 Respostas

dev.rafael

Na sua view:

<ui:repeat var="article" value="#{articleMb.dao.enabled}" size="5">
  ...
  <h:commandLink value="Remover" action="#{articleMb.recycle}">
    <f:setPropertyActionListener target="#{articleMb.article}" value="#{article}" />
  </h:commandLink>
  ...
</ui:repeat>

E no seu bean:

public Article getArticle() { return article; }
public void setArticle(Article article) { this.article = article; }

Infelistemente essa é a unica meneira (unica maneira certa) se fazer isso no JSF 1.2. Se vc tiver a oportunidade de usar JSF 2 vc então poderá:

<h:commandLink value="Remover" action="#{articleMb.recycle(article)}" />

E no bean:

public String recycle(Article article) {

Bem melhor! :slight_smile:

Só uma coisa, sempre q vc encontrar prefixos ou sufixos em nomes de classes é sinal de q vc precisa refatorar o seu código. De um modo geral, prefixos ou sufixos são usados pq vc ñ consegue definir com clareza o papel dessa classe no seu sistema ou pq ela ñ tem papel nenhum relevante. Infelistemente, em alguns casos nós somos obrigados a usa-los p/ conta de limitações nos nossos frameworks.
Em outras palavras, corra dos DAOs!!!

R

Olá.
vc pode usar o <f:setPropertyActionListener> para fazer o que vc precisa.

Ed.prog

@dev.rafael
Valeu mesmo! Desse jeito fica legal…
To usando 1.2 pra pegar a prática, antes de ir pro 2.0 que parece simplificar várias coisas.
Valeu pelas dicas também, vou precisar refatorar o meu pensamento junto, pois estou mal acostumado com os daos.

Criado 22 de outubro de 2010
Ultima resposta 22 de out. de 2010
Respostas 3
Participantes 3