VRaptor + edição de formulário

Olá pessoal,

Estou com um pequeno problema no exercício 11.7 da apostila FJ28 da Caelum:

No meu controller de produtos, método altera, possuo a anotação conforme apostila:

@Put("/produtos/{produto.id}")
public void altera(Produto produto) {...}

Quando aciono por PUT, o meu objeto “produto” fica o atributo “id” com valor null. Todo o resto é passado certinho (preco, nome, descricao) menos o id.
Consequentemente não consigo salvar as alterações do meu cadastro.

No meu edita.jsp tenho o seguinte:

<form action="<c:url value="/produtos/${produto.id }" />" method="POST">

Alguém sabe por que o atributo “id” está ficando nulo?

Desde já agradeço!

Posso ver a action que chama o edita.jsp? (método edita)

Controller:

package br.com.mobilepos.controller;

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

import br.com.caelum.vraptor.Delete;
import br.com.caelum.vraptor.Get;
import br.com.caelum.vraptor.Post;
import br.com.caelum.vraptor.Put;
import br.com.caelum.vraptor.Resource;
import br.com.caelum.vraptor.Result;
import br.com.mobilepos.dao.ProdutoDao;
import br.com.mobilepos.models.*;
import br.com.caelum.vraptor.Validator;

@Resource
public class ProdutosController {
	
	private final ProdutoDao dao;
	private final Result result;
	private final Validator validator;
	
	public ProdutosController(ProdutoDao dao, Result result, Validator validator) {
		this.dao = dao;
		this.result = result;
		this.validator = validator;
	}
	
	@Get("/produtos/novo")
	public void formulario() {
		
	}
	
	@Get("/produtos/{id}")
	public Produto edita(Long id) {
		return dao.carrega(id);
	}
	
	@Delete("/produtos/{id}")
	public void remove(Long id) {
		Produto produto = dao.carrega(id);
		dao.remove(produto);
		result.redirectTo(ProdutosController.class).lista();
	}
	
	@Put("/produtos/{produto.id}")
	public void altera(Produto produto) {
		dao.atualiza(produto);
		result.redirectTo(this).lista();
	}
	
	@Post("/produtos")
	public void adiciona(Produto produto) {
		validator.validate(produto);
		validator.onErrorUsePageOf(ProdutosController.class).formulario();
		
		dao.salva(produto);
		result.redirectTo(this).lista();
	}
	
	@Get("/produtos")
	public List<Produto> lista() {
		return dao.listaTudo();
	}
}

chamo o edita via link html (GET) assim:

<a class="btn btn-mini" href="<c:url value="/produtos/${produto.id }"/>"><i class="icon-pencil"></i></a>

Parece ser alguma coisa com o id mesmo, já fiz vários testes (sem usar os verbos PUT, passando outros valores no id, etc).

Segue meu model para verificação:

package br.com.mobilepos.models;

import javax.persistence.*;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;

import org.hibernate.validator.constraints.Length;

@Entity
public class Produto {

	@Id @GeneratedValue
	private Long id;
	
	@NotNull(message="Nome não preenchido")
	@Length(max=50)
	private String nome;
	
	@NotNull(message="Descrição não preenchida")
	@Length(max=200)
	private String descricao;
	
	@Min(0)
	@Max(99999)
	private double preco;
	
	public Long getId() {
		return id;
	}

	public String getNome() {
		return nome;
	}

	public void setNome(String nome) {
		this.nome = nome;
	}

	public String getDescricao() {
		return descricao;
	}

	public void setDescricao(String descricao) {
		this.descricao = descricao;
	}

	public double getPreco() {
		return preco;
	}

	public void setPreco(double preco) {
		this.preco = preco;
	}

}

Galera,

depois de muito quebrar a cabeça percebi que meu model estava sem o método setId. Não sei por que meu Eclipse não gerou quando mandei gerar os getters and setters.

Mas tudo bem, resolvido o problema!

se vc muda o @Put pra @Post funciona?

tem algum input que mexe no id?

Não tem nenhum input que mexe no id não (é enviado pelo action do formulário apenas).
Se eu mudar pra POST funciona (desde que alterado o verbo que aciona) porque não tem nenhuma outra ação que irá “bater” com a annotation @Post + parâmetro (a do adicionar é sem parâmetro).

com o setId() funcionou mesmo com Put?

Funcionou sim, na verdade faltava o método setId(). Não acionei ele manualmente (na verdade não mudei nada do código que postei acima, apenas criei o método).
Meu atributo id está como private e não tinha setId pra ele, então imagino que ele não conseguisse atribuir o valor. Já no método que adiciona o registro ele não é passado porque é auto incremento (@GeneratedValue)