[Resolvido] Problemas com AJAX + VRaptor + JSTL

Olá, estou fazendo o tutorial FJ28…

criei um carrinho e items para colocar no carrinho, e um botao para adicionar os produtos no carrinho. Mas o header do site não tá atualizando o número de itens no carrinho!

<div id="header">
<div id="carrinho">
<h3>Meu carrinho:</h3>
<c:if test="${empty carrinho or carrinho.totalDeItens eq 0 }">
<span>Você não possui itens no seu carrinho</span>
</c:if>
<c:if test="${carrinho.totalDeItens > 0 }">
<ul>
<li><strong>Itens:</strong> ${carrinho.totalDeItens }</li>
<li><strong>Total:</strong>
<fmt:formatNumber type="currency" value="${carrinho.total }"/></li>
</ul>
</c:if>
</div>
</div>

Quando eu dou adicionar em um item e dou debug dando System.out.println(carrinho.getTotalDeItens); ele está atualizando certinho.

Acho que o problema está na JSTL, já que eu não referenciei esse carrinho antes, apesar de ele ser um componente da Session do VRaptor. Alguém sabe se tenho que colocar algo do tipo <jsp:useBean id=“carrinho” class=“br.com.caelum.goodbuy.modelo.Carrinho”/> pra funcionar ou o VRaptor já faz essa Injeção no JSP tb?

Obrigado.

o vraptor já deveria fazer essa injeção.

o seu carrinho é um @Component @SessionScoped?

você está colocando algum carrinho manualmente no result?

Sim, é Component e SessionScoped.

O controller de carrinho recebe um carrinho por DI:

@Resource
public class CarrinhoController {
	private final Carrinho carrinho;
	private final ProdutoDao dao;
	private final Result result;
	
	public CarrinhoController(Carrinho carrinho, ProdutoDao dao, Result result) {
		this.carrinho = carrinho;
		this.dao = dao;
		this.result = result;
	}
	
	@Post @Path("/carrinho")
	public void adiciona(Item item) {
		dao.recarrega(item.getProduto());
		carrinho.adiciona(item);
		
		System.out.println(carrinho.getTotalDeItens());

		result.redirectTo(ProdutosController.class).lista();
	}
}

Eu estou colocando no JSP para falar o ${carrinho.totalDeItens} sem nenhum IF, e ele não está retornando nada. Esse System.out.print que eu coloquei de debug tá atualizando direitinho…

tenta imprimir só ${carrinho} e ve se aparece alguma coisa.

vc está com os jars do spring, do guice ou do pico no seu WEB-INF/lib?

Estou usando o PicoContainer. Quando mando um ${carrinho} também não aparece nada!

O pico não suporta ainda usar os componentes da sessão diretamente no jsp (o guice e o spring suportam)

a gente corrigiu isso, então vai funcionar na próxima versão do VRaptor.

nohhh… q doido! achei q era vacilo meu. vc sabe se tem alguma previsao de sair essa nova versão? ou é melhor eu mudar pra outro?
coloquei o pico porque era o mais simples de usar, apenas copiar um jar. mas me falaram que o guice é muito rapido. trocar o container é uma coisa trivial? nao dá pau em nada que tá pronto nao?

pode trocar sem medo, só tirar o jar do pico e colocar os jars do guice, não precisa mudar mais nada na aplicação =)

Certinho! Vou botar resolvido, troquei o Pico pelo Guice e começou a funcionar como deveria =)
Muito obrigado Lucas!

Fala ae pessoal, foi mal por reabrir o toópico, mas o meu problema está sendo exatamente o mesmo, mas com o VRaptor4, então acho que não preciso dos jars do Pico, Guice ou Spring, certo?

Segue minha classe Controller.

package br.com.caelum.goodbuy.controller;

import javax.inject.Inject;

import br.com.caelum.goodbuy.dao.ProdutoDao;
import br.com.caelum.goodbuy.modelo.Carrinho;
import br.com.caelum.goodbuy.modelo.Item;
import br.com.caelum.vraptor.Controller;
import br.com.caelum.vraptor.Get;
import br.com.caelum.vraptor.Path;
import br.com.caelum.vraptor.Post;
import br.com.caelum.vraptor.Result;

@Controller
public class CarrinhoController {

	@Inject private ProdutoDao produtoDao;
	@Inject private Result result;
	@Inject private Carrinho carrinho;

	@Post @Path("/carrinho")
	public void adiciona(Item item ) {
		try {
			System.out.println("  --");
			System.out.println("  ===> ACESSANDO CarrinhoController.adiciona()");
			item.setProduto(produtoDao.buscarPorId(item.getProduto().getId()));
			carrinho.adicionaItem(item);
			
			result.redirectTo(ProdutosController.class).lista();
		}
		catch(Exception e) {
			System.out.println("  --");
			System.out.println("  ==> ERRO :: " + e.toString());
		}
	}
	
	@Get @Path("/carrinho")
	public void visualiza() {
		// apenas para acessar a página de visualização do Carrinho de Compras
		System.out.println("  --");
		System.out.println("  ===> ACESSANDO CarrinhoController.visualiza()");
	}
}

Segue minha classe Carrinho

package br.com.caelum.goodbuy.modelo;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import javax.enterprise.context.SessionScoped;

@SessionScoped
public class Carrinho implements Serializable {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	
	private List<Item> itens = new ArrayList<Item>();
	private Double total = 0.0;
	
	public List<Item> getItens() {
		return itens;
	}
	public void setItens(List<Item> itens) {
		this.itens = itens;
	}
	
	public Double geotal() {
		return total;
	}
	public void setTotal(Double total) {
		this.total = total;
	}

	public void adicionaItem(Item item) {
		itens.add(item);
		total += item.getProduto().getPreco() * item.getQuantidade();
	}
	
	public Integer getTotalDeItens() {
		return itens.size();
	}
}

Esse é o header.jsp

<div id="header">
	<div id="carrinho">
		<h3><a href="<c:url value="/carrinho"/>">Meu carrinho:</a></h3>
		<h3><a href="<c:url value="/carrinho/index"/>">INDEX</a></h3>
		${carrinho }
	</div>
</div>

E esse é o visualiza.jsp

<h3>Itens do seu carrinho de compras</h3>
	<c:if test="${empty carrinho or carrinho.totalDeItens eq 0 }">
		<span>Você não possui itens no seu carrinho</span>
	</c:if>
	<c:if test="${carrinho.totalDeItens > 0 }">
		<table>
		  <thead>
		    <tr>
		      <th>Nome</th>
		      <th>Descrição</th>
		      <th>Preço</th>
		      <th>Qtde</th>
		      <th>Total</th>
		    </tr>
		  </thead>
		  <tbody>
		    <c:forEach items="${carrinho.itens}" var="item">
		      <tr>
		        <td>${item.produto.nome }</td>
		        <td>${item.produto.descricao }</td>
		        <td>
		          <fmt:formatNumber type="currency" 
		            value="${item.produto.preco }"/>
		        </td>
		        <td>${item.quantidade }</td>
		        <td>
		          <fmt:formatNumber type="currency" 
		            value="${item.quantidade * item.produto.preco }"/>
		        </td>
		      </tr>          
		    </c:forEach>
		  </tbody>
		  <tfoot>
		    <tr>
		      <td colspan="2"></td>
		      <th colspan="2">Total:</th>
		      <th>
		        <fmt:formatNumber type="currency" 
		          value="${carrinho.total }"/>
		      </th>
		    </tr>
		  </tfoot>
		</table>
	</c:if>

Quando instancio o Tomcat7 no modo Debug, acesso o método CarrinhoController.adiciona() vejo que o Carrinho injetado está com a lista de itens vazia e o valor total 0.0. Mas se continuo o Debug e entro no método Carrinho.adicionaItem() ae vejo o Carrinho com lista de itens preenchido e o valor total calculado certo. É como se o Controller não estivesse conseguindo “persistir” as informações dos atributos da classe injetada, mesmo sendo uma SessionScoped.

O que preciso fazer ainda?

Abraço.

Aconselho vc a abrir uma dúvida específica com isso. Não tem a ver com o tópico original.

Abre na seção de perguntas.

vc precisa colocar @Named(“carrinho”) no carrinho para ele ser acessível na JSP

Valeu Lucas,
era exatamente isso que estava faltando, anotar o Carrinho com o @Named.

Abraço e Sucesso…