[RESOLVIDO]Componente não é salvo na sessão[RESOLVIDO]

Galera,
Como já falei aqui antes, sou iniciante no vraptor.
Ele é excelente para me deixar de cabelo branco.rssrs.
Vamos, lá.
Pelo que eu entendi, e so anotar a classe com @SessionScoped. Para ele ser salvo na sessão, e ser único.
Estou fazendo uma loja virtual. Utilizei a apostila FJ-28.
Mas na apostila, eles não salvam no banco o carrinho de compras.
E eu estou tentando salvar ele no banco de dados.
A principio, fiz uma outra classe chamei-a de orçamento.
Fiz o relacionamento, com itens.
Quando a pessoal clicar em Novo Orçamento, eu crio no banco de dados um orçamento.
Conforme a pessoa vai escolhendo os itens do orçamento, ela vai adicionando e já vai salvando esses itens também no banco.
So que, eu preciso enviar junto com o novo item adicionando o codigo do produto e o codigo do orçamento.
O codigo do produto, está indo certinho, já o codigo do orçamento não vai.

Olha como ficou minha classe Orcamento.java - ela está no meu modelo.

@Entity
@Component
@SessionScoped
public class Orcamento {

//váriaveis
@Id @GeneratedValue
private Long id;
private String numero;
private double total;
private double desconto;
private double frete;

/Relacionaomento com orcamentoItens
	@OneToMany(mappedBy = "orcamento",targetEntity= Itens.class,
	fetch = FetchType.LAZY, cascade = CascadeType.ALL)
	private List <Itens> itens;
//Metodos get e set

Minha classe Itens.java - Também está no meu modelo.

@Entity
public class Itens {
	@Id @GeneratedValue
	private Long id;
	private double quantidade;
			
	//Relacionamento com Produtos
		@ManyToOne
		@JoinColumn(name="produto_id")
		private Produto produto;
		//Relacionaomento com orcamento
		@ManyToOne(cascade=CascadeType.PERSIST)
		@JoinColumn(name="orcamento_id")
		private Orcamento orcamento;
		//Métodos Set e get

Tenho o controller de cada uma, que salva no banco de dados.

Na minha lista de produtos, e adicionei um botão adicionar a cada produto.
Ficou assim.

lista.jsp - esta em jsp/produtos

<!-- Adicionando o produto ao orçamento -->
<td>
<form action="<c:url value="/itens"/>" method="POST">
<input type="hidden" name="itens.produto.id"
value="${produto.id}"/>
<input class="qtde" name="itens.quantidade" value="1"/>
<input type="hidden" name="itens.orcamento.id"
//Orçamento
value="${orcamento.id}"/>
<button type="submit">Adicionar</button>
</form>
</td>

Teoricamente, era pra quando eu clicar em adicionar.
Ele salva o item, com o id do produto e do orçamento.
Como eu falei, do produto ele salva corretamente, já do orçamento ele fala que não encontrou a referência.

br.com.caelum.vraptor.InterceptionException: exception raised, check root cause for details: org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: br.com.caelum.goodbuy.modelo.Orcamento

Se eu alterar e colocar o id do orçamento no campo ‘value’ ele salva corretamente.
Já tentei colocar o orçamento no interceptor, para aparecer em todas as páginas, também não rolou.
Podem me ajudar?

Valeu Galera!

Como ele é @SessionScoped, você não precisa passar ele para a view o tempo todo, o VRaptor já faz isso para você. :wink:

Agora, ao invés de pegar o ID do orçamento na view e depois receber na action, que tal se você simplesmente recebesse o Orçamento no construtor do seu controller?

Assim você evita que alguém mude o ID do orçamento na view e você usa uma feature muito boa que é a DI.

A ideia é excelente.
Seria ótimo. Pena que eu não consegui fazer.

Olha o que eu fiz.

@Resource
public class ItensController {
	private final ItensDAO dao;
	private final Result result;
	private final Orcamento orcamento;
	public ItensController(ItensDAO dao,Result result, Orcamento orcamento) {
	this.dao = dao;
	this.result = result;
	this.orcamento = orcamento;
	}

	@Post("/itens")
	public void adiciona(Itens itens) {
	//O que eu faço aqui, para ele passar o id do meu orçamento??
	dao.salva(itens);
	result.redirectTo(this).lista();
	}

Agora, como eu faço pra passar o orcamento na linha ai encima?
Sei que não “fazem” código pra gente.
Teria que criar um metodo em Orcamento ou Item?

Eu não sei COMO você quer salvar. Mas esse orcamento será salvo aonde? Dentro de item?
Então faça algo nesse sentido:

item.setOrcamento(this.orcamento);

Brother,
Eu tenho duas classes.
Dois controllers.
O que eu preciso e quando eu for salvar um novo item, pegar o id do orçamento e salvar em orcamento_id da tabela itens.
So isso.

Tentou fazer aquilo que eu falei?

Olha como ficou.

[code]
@Resource
public class ItensController {
private final ItensDAO dao;
private final Result result;
private final Orcamento orcamento;
public ItensController(ItensDAO dao,Result result, Orcamento orcamento) {
this.dao = dao;
this.result = result;
this.orcamento = orcamento;
}

@Post("/itens")
public void adiciona(Itens itens, Orcamento orcamento) {
//O que eu faço aqui, para ele passar o id do meu orçamento??
itens.setOrcamento(this.orcamento);  
dao.salva(itens);
result.redirectTo(this).lista();
}[/code]

Minha lista de produtos.

<!-- Adicionando o produto ao orçamento -->
<td>
<form action="<c:url value="/itens"/>" method="POST">
<input type="hidden" name="itens.produto.id"
value="${produto.id}"/>
<input class="qtde" name="itens.quantidade" value="1"/>
<!-- <input type="hidden" name="itens.orcamento.id"
value="${orcamento.id}"/>
-->
<button type="submit">Adicionar</button>
</form>
</td>

Mano, descula minha burrice.rsrs.

Ta, mas e ai? O que aconteceu? Deu certo?

Deu erro? Explodiu?

O meu brother,
Explodir, explodiu.
Foda que não funcionou.
Continua com o mesmo erro.

Quais são os passos para salvar um dado na sessão?
Eu só preciso salvar o orcamento.id na sessão, e que ele seja único.
Dessa forma. Já está bom.

br.com.caelum.vraptor.InterceptionException: exception raised, check root cause for details: org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: br.com.caelum.goodbuy.modelo.Orcamento  

esse erro quer dizer que vc tentou salvar uma entidade XXX, que tem um Orcamento dentro dela e esse orçamento não está salvo…

é só salvar o orçamento antes de salvar a XXX.

Pois é meu brother.
Eu to tentando colocar o orçamento na sessão.
E com isso, passar o id dele para salvar em itens.

salve o orçamento então no começo de tudo…

ou só acumule todos os itens na memória e salve no banco só ao final do processo.

Estou salvando o orçamento primeiro.
Faço assim.
Inicio a aplicação.
Entro com usuario e senha.
Crio um novo orçamento.
E depois eu mando ele salvar o item.

Ta ai, como eu faço pra após eu criar o orçamento, colocar ele na sessão automáticamente.

Lembrando que ele está anotado com.

@Component
@SessionScoped

ele é uma entidade que está anotada com @Component?

não faça isso… se o orçamento é uma @Entity, faça:

@Component
@SessionScoped
public class OrcamentoEmProgresso {
     private Orcamento orcamento;
     // getters/setters
}

assim vc separa o que tá no banco do que está na sessão

Não, é necessário component.
O que eu preciso e salvar na sessão.
Pq ele não salva na sessão?
Tem que fazer algo mais.
TIpo, quando eu entrar na minha aplicação eu quero adicionar orçamento.
Colocar ele na seção
Escolher os meus produtos, e bimba adicionar o meu item com o id do meu orçamento.

Olha o que eu fiz.

Meu orçamento,ficu assim.

@Entity
public class Orcamento {

Minha classe OrcamentoEmProgresso.

@Component  
@SessionScoped  
public class OrcamentoEmProgresso {
	private Orcamento orcamento;
//Metodos set e get

Agora, como eu faço pra colocar ele na sessão?
Pq quando eu crio um novo usuario, eu preciso fazer login para colocar ele na sessão.
Eu vou clicar em orcamento/novo
Vou criar um novo orçamento. Vou colocar os dados necessários.
Agora, eu quero, inserir um item, passando o id_orcamento que está na sessão.
Consigo fazer isso como?

receba o OrcamentoEmProgresso no construtor que vc vai mexer com isso e mexa com o orçamento que está la dentro…
tipo:

// orcamento/novo
Orcamento orcamento = // cria e salva no banco
orcamentoEmProgresso.setOrcamento(orcamento);

// novo item
Item item = // o que veio da requisição
item.setOrcamento(orcamentoEmProgresso.getOrcamento());

se quiser pode mover algumas dessas lógicas pra dentro do OrcamentoEmProgresso.

Beleza!
Entendi. Mas não sei implementar no Controller do Vraptor.
Tem como você me ajudar?

[code]
@Get("/orcamento/novo")
@Restrito
public void formulario(Orcamento orcamento) {
//O eclipse acusa que
OrcamentoEmProgresso.setOrcamento(orcamento);

}[/code]

Precisa implementar aqui também?

@Post("/orcamento")
	@Restrito
	public void adiciona(final Orcamento orcamento) {
		dao.salva(orcamento);
		result.redirectTo(this).lista();
	}