Ultimo problema para finalizar meu primeiro Sistema

197 respostas
vaadinjavamysqlspringprogramação
R

Boa tarde a todos, há alguns meses comecei a desenvolver meu primeiro sistema web, sem nenhum conhecimento, com um frame pouco utilizado no Brasil, o Vaadin. Graças a ajuda de vários colegas aqui do fórum, hoje estou quase finalizando este projeto, aprendi muito com cada colega, e agradeço a cada um que ajudou.

Para finalizar este sistema, tenho um ultimo problema.

Esta é minha janela de Vendas:

na parte superior desta janela tenho os dados do cliente, então seleciono o nome do cliente para preencher os dados, ao selecionar o nome do cliente, os demais dados são preenchidos automaticamente:

restando apenas o campo forma de pagamento, que o usuario pode escolher antes de selecionar os produtos a serem vendidos…ou após, para efeitos de teste vamos selecionar agora no começo(o erro se da das duas maneiras)

Forma de pagamento Selecionada:

Agora adiciono os produtos, para isso clico em “+Item” :

os campos referentes aos produtos são adicionados…vou add 3 produtos

clico em salvar e a venda é salva na lista/grid

Até aqui ok, tudo certo…agora vamos ao problema

se eu fechar o navegador, ou der F5 acontece isso quando eu tento alterar ou visualizar(duplo clique) a venda:

erro/problema: Os produtos vendidos, são limpos / apagados

Não sei o que fiz de errado, creio que seja algo simples, mas como estou começando com programação, tudo pra mim é bem complicado. Alguém poderia me dar uma ajuda ou ideia para consertar estes problemas?

Seguem códigos:

Classe FormasDePagamento:

package br.com.fjsistemas.backend;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@AllArgsConstructor
@NoArgsConstructor
@Data
@Entity
public class FormasDePagamento {
	
	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	private Long id;
	
	private String forma; 
	private String condicao;
	
}

Classe Venda:

package br.com.fjsistemas.backend;

import java.time.LocalDate;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@AllArgsConstructor
@NoArgsConstructor
@Data
@Entity
public class Venda {

	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	private Long id;

	private LocalDate dataVenda = LocalDate.now();

	@ManyToOne
	private Cliente cliente;
	
	@ManyToOne
	private FormasDePagamento formasDepagamento;
	
	private String valorTotalVenda;
}

Classe VendaView(UI)

package br.com.fjsistemas.compraVenda;

import java.text.NumberFormat;
import java.text.ParseException;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

import javax.annotation.PostConstruct;

import org.springframework.beans.factory.annotation.Autowired;
import org.vaadin.textfieldformatter.CustomStringBlockFormatter;

import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.button.ButtonVariant;
import com.vaadin.flow.component.combobox.ComboBox;
import com.vaadin.flow.component.datepicker.DatePicker;
import com.vaadin.flow.component.dialog.Dialog;
import com.vaadin.flow.component.grid.Grid;
import com.vaadin.flow.component.grid.GridVariant;
import com.vaadin.flow.component.html.Div;
import com.vaadin.flow.component.html.Label;
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.component.textfield.NumberField;
import com.vaadin.flow.component.textfield.TextField;
import com.vaadin.flow.data.binder.Binder;
import com.vaadin.flow.data.binder.PropertyId;
import com.vaadin.flow.data.renderer.LocalDateRenderer;
import com.vaadin.flow.router.PageTitle;
import com.vaadin.flow.router.Route;

import br.com.fjsistemas.backend.Cliente;
import br.com.fjsistemas.backend.FormasDePagamento;
import br.com.fjsistemas.backend.Produto;
import br.com.fjsistemas.backend.Venda;
import br.com.fjsistemas.main.MainView;
import br.com.fjsistemas.repository.ClienteRepository;
import br.com.fjsistemas.repository.FormaDePagamentoRepository;
import br.com.fjsistemas.repository.ProdutoRepository;
import br.com.fjsistemas.service.VendaService;

@Route(value = "venda-view", layout = MainView.class)
@PageTitle("Lançamento de Vendas")
public class VendaView extends VerticalLayout {

	private static final long serialVersionUID = 1L;

	private HorizontalLayout hltVenda = new HorizontalLayout();
	Grid<Venda> grdVenda = new Grid<>(Venda.class, false);

	private HorizontalLayout hltBarraBotoes = new HorizontalLayout();
	Button btnNovo = new Button("Novo");
	Button btnAlterar = new Button("Alterar");
	Button btnExcluir = new Button("Excluir");

	private Dialog dlgJanela = new Dialog();

	Div superior = new Div();
	Div centro = new Div();
	Div inferior = new Div();

	HorizontalLayout primeiraLinhaDivSuperior = new HorizontalLayout();
	HorizontalLayout segundaLinhaDivSuperior = new HorizontalLayout();
	HorizontalLayout adicionarProdutos = new HorizontalLayout();

	double somaValores;

	@PropertyId("dataVenda")
	private DatePicker txtDataVenda = new DatePicker("Data Venda");

	@PropertyId("cliente")
	private ComboBox<Cliente> txtNomeCliente = new ComboBox<>("Cliente");

	@PropertyId("telefone")
	private TextField txtTelefone = new TextField("Telefone");

	@PropertyId("celular")
	private TextField txtCelular = new TextField("Celular");

	@PropertyId("endereco")
	private TextField txtEndereco = new TextField("Endereço");

	@PropertyId("numero")
	private TextField txtNumero = new TextField("Nº");

	@PropertyId("bairro")
	private TextField txtBairro = new TextField("Bairro");

	@PropertyId("cidade")
	TextField txtCidade = new TextField("Cidade");

	@PropertyId("estado")
	TextField txtEstado = new TextField("Estado");

	@PropertyId("formasPagamento")
	private ComboBox<FormasDePagamento> txtFormasPagamento = new ComboBox<>("Formas de Pagamento");

	@PropertyId("valorTotalVenda")
	private TextField campoSomaValores = new TextField();

	private HorizontalLayout htlDlgBarraBotoes = new HorizontalLayout();
	private Button btnSalvar = new Button("Salvar");
	private Button btnFechar = new Button("Fechar");
	private Button btnAdicionarItem = new Button("+ Item");

	@Autowired
	VendaService vendaService;

	@Autowired
	ClienteRepository clienteRepository;

	@Autowired
	FormaDePagamentoRepository formaDePagamentoRepository;

	@Autowired
	ProdutoRepository produtoRepository;

	private List<Venda> listaVendas;
	private List<TextField> valores = new ArrayList<>();
	private Venda venda;

	Binder<Venda> binderVenda = new Binder<>(Venda.class);

	public VendaView() {

	}

	@PostConstruct
	public void init() {
		configuraTela();

	}

	private void configuraTela() {

		setMargin(false);
		setPadding(false);

		configuraHltVenda();
		configuraFltBarraBotoes();
		configuraDlgJanela();
		populaGrdVenda();
		configuraBinder();

		add(hltVenda, hltBarraBotoes);
	}

	private void configuraFltBarraBotoes() {

		btnNovo.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
		btnNovo.addClickListener(e -> {
			novoClick();
		});

		btnAlterar.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
		btnAlterar.addClickListener(e -> {
			alterarClick();
		});

		btnExcluir.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
		btnExcluir.addClickListener(e -> {
			excluirClick();
		});

		hltBarraBotoes.add(btnNovo, btnAlterar, btnExcluir);
	}

	private void excluirClick() {

		if (venda != null) {
			listaVendas.remove(venda);
			vendaService.delete(venda);
			atualizaGrdVenda();
		}
	}

	private void configuraHltVenda() {
		hltVenda.setWidthFull();
		configuraGrdVenda();
		hltVenda.add(grdVenda);
	}

	private void configuraGrdVenda() {
		grdVenda.setHeight("820px");
		grdVenda.setWidthFull();

		grdVenda.addColumn(Venda::getId).setHeader("ID:").setAutoWidth(true);

		grdVenda.addColumn(new LocalDateRenderer<>(Venda::getDataVenda, DateTimeFormatter.ofPattern("dd/MM/yyy")))
				.setHeader("Data Venda").setAutoWidth(true);

		grdVenda.addColumn(venda -> venda.getCliente().getNome()).setHeader("Nome:").setAutoWidth(true)
				.setKey("cliente.nome");

		grdVenda.addColumn(Venda::getValorTotalVenda).setHeader("Valor Total:").setAutoWidth(true)
				.setKey("valorTotalVenda");

		grdVenda.addThemeVariants(GridVariant.LUMO_COMPACT, GridVariant.LUMO_COLUMN_BORDERS);

		grdVenda.getColumns().forEach(col -> col.setAutoWidth(true).setSortable(true).setResizable(true));

		grdVenda.addItemClickListener(e -> {
			venda = e.getItem();
		});

	}

	private void configuraDlgJanela() {

		dlgJanela.setHeightFull();
		dlgJanela.setWidthFull();
		dlgJanela.setCloseOnEsc(false);
		dlgJanela.setCloseOnOutsideClick(false);

		superior.setHeight("170px");
		superior.setWidthFull();

		txtNomeCliente.setWidth("350px");
		txtNomeCliente.setLabel("Nome Cliente");

		txtNomeCliente.setItemLabelGenerator(cliente -> {
			if (cliente == null || cliente.getNome() == null) {
				return " ";

			} else {
				return cliente.getNome();
			}
		});

		List<Cliente> listaDeClientes = clienteRepository.findAll();

		txtNomeCliente.setItems(listaDeClientes);
		txtNomeCliente.addValueChangeListener(event -> {
			if (event.getValue() == null || event.getValue().getFone() == null) {
				txtTelefone.setValue(" ");
			} else {
				txtTelefone.setValue(event.getValue().getFone());
			}
			if (event.getValue() == null || event.getValue().getCelular() == null) {
				txtCelular.setValue(" ");
			} else {
				txtCelular.setValue(event.getValue().getCelular());
			}
			if (event.getValue() == null || event.getValue().getEndereco() == null) {
				txtEndereco.setValue(" ");
			} else {
				txtEndereco.setValue(event.getValue().getEndereco());
			}
			if (event.getValue() == null || event.getValue().getNumero() == null) {
				txtNumero.setValue(" ");
			} else {
				txtNumero.setValue(event.getValue().getNumero());
			}
			if (event.getValue() == null || event.getValue().getBairro() == null) {
				txtBairro.setValue(" ");
			} else {
				txtBairro.setValue(event.getValue().getBairro());
			}
			if (event.getValue() == null || event.getValue().getCidade() == null) {
				txtCidade.setValue(" ");
			} else {
				txtCidade.setValue(event.getValue().getCidade());
			}
			if (event.getValue() == null || event.getValue().getEstado() == null) {
				txtEstado.setValue(" ");
			} else {
				txtEstado.setValue(event.getValue().getEstado());
			}

		});

		new CustomStringBlockFormatter.Builder().blocks(0, 2, 4, 4).delimiters("(", ")", "-").numeric().build()
				.extend(txtTelefone);

		new CustomStringBlockFormatter.Builder().blocks(0, 2, 5, 4).delimiters("(", ")", "-").numeric().build()
				.extend(txtCelular);

		primeiraLinhaDivSuperior.add(txtDataVenda, txtNomeCliente, txtTelefone, txtCelular, txtEndereco, txtNumero,
				txtBairro, txtCidade);

		txtNumero.setWidth("140px");

		txtFormasPagamento.setLabel("Formas de Pagamento");
		List<FormasDePagamento> listaPagamento = formaDePagamentoRepository.findAll();
		txtFormasPagamento.setItemLabelGenerator(FormasDePagamento::getForma);
		txtFormasPagamento.setItems(listaPagamento);

		segundaLinhaDivSuperior.add(txtEstado, txtFormasPagamento);
		superior.add(primeiraLinhaDivSuperior, segundaLinhaDivSuperior);

		centro.setHeight("660px");
		centro.getStyle().set("border-style", "ridge");
		centro.getStyle().set("overflow-y", "scroll");
		centro.setWidthFull();

		btnSalvar.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
		btnSalvar.getStyle().set("margin-top", "0em");
		btnSalvar.getStyle().set("margin-left", "1em");
		btnSalvar.addClickListener(e -> {
			salvarClick();
			limparCampos();
		});

		btnFechar.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
		btnFechar.getStyle().set("margin-top", "0em");
		btnFechar.addClickListener(e -> {
			dlgJanela.close();
			limparCampos();
		});

		btnAdicionarItem.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
		btnAdicionarItem.getStyle().set("margin-top", "0em");
		btnAdicionarItem.addClickListener(e -> {
			adicionaProduto();
		});

		Label text = new Label("Valor Total");
		text.getElement().getStyle().set("fontWeight", "bold");
		text.getStyle().set("margin-top", "0.8em");
		text.getStyle().set("margin-left", "2em");
		text.getStyle().set("text-align", "center");
		campoSomaValores.getStyle().set("margin-top", "0em");
		campoSomaValores.getStyle().set("margin-right", "0.2em");
		campoSomaValores.setWidth("30em");

		htlDlgBarraBotoes.add(btnSalvar, btnFechar, btnAdicionarItem, text, campoSomaValores);

		inferior.getStyle().set("margin-top", "0px");
		inferior.setHeight("45px");
		inferior.setWidthFull();
		inferior.add(htlDlgBarraBotoes);

		dlgJanela.add(superior, centro, inferior);

	}

	private void salvarClick() {

		venda = binderVenda.getBean();

		boolean adicionarLista = venda.getId() == null ? true : false;

		vendaService.create(venda);

		if (adicionarLista) {
			listaVendas.add(venda);
		}
		atualizaGrdVenda();
		novaVenda();
		txtNomeCliente.focus();

		binderVenda.setBean(venda);

		if (adicionarLista) {
			dlgJanela.close();
		}
	}

	private void populaGrdVenda() {

		listaVendas = vendaService.read();
		atualizaGrdVenda();
	}

	private void atualizaGrdVenda() {
		grdVenda.setItems(listaVendas);
	}

	private void configuraBinder() {

		binderVenda.bindInstanceFields(this);

	}

	private void novoClick() {

		novaVenda();
		binderVenda.setBean(venda);

		dlgJanela.open();
		txtNomeCliente.focus();
	}

	private void alterarClick() {

		if (venda != null) {
			binderVenda.setBean(venda);

			dlgJanela.open();

		}
	}

	private void adicionaProduto() {

		ComboBox<Produto> txtProdutos = new ComboBox<>();

		NumberField txtQuantidade = new NumberField("Quantidade");

		TextField txtValorUnitario = new TextField("Valor Unitário");

		TextField txtValorTotalItem = new TextField("Valor Total Item");

		txtProdutos.setWidth("370px");
		txtProdutos.setLabel("Produtos");
		List<Produto> listaDeProdutos = produtoRepository.findAll();
		txtProdutos.setItemLabelGenerator(Produto::getNome);
		txtProdutos.setItems(listaDeProdutos);
		txtProdutos.addValueChangeListener(event -> {

			NumberFormat formatter = NumberFormat.getCurrencyInstance(new Locale("pt", "BR"));
			try {

				txtValorUnitario.setValue(formatter.format(event.getValue().getValor()));

			} catch (Exception e) {
				e.printStackTrace();
			}

		});

//==========================================================================================================================

		txtQuantidade.setHasControls(true);
		txtQuantidade.setValue(null);
		txtQuantidade.setMin(1);

		txtQuantidade.addValueChangeListener(event -> {

			NumberFormat formatter = NumberFormat.getCurrencyInstance(new Locale("pt", "BR"));
			double valorTotal = 0;

			try {
				valorTotal = formatter.parse(txtValorUnitario.getValue()).doubleValue() * txtQuantidade.getValue();
			} catch (ParseException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

			txtValorTotalItem.setValue(formatter.format(valorTotal));

			double soma = 0;
			for (TextField tf : valores) {
				try {
					soma += formatter.parse(tf.getValue()).doubleValue();

				} catch (ParseException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}

			}

			campoSomaValores.setValue(formatter.format(soma));

		});

		adicionarProdutos = new HorizontalLayout();
		adicionarProdutos.add(txtProdutos, txtQuantidade, txtValorUnitario, txtValorTotalItem);

		centro.add(adicionarProdutos);
		valores.add(txtValorTotalItem);
	}

	private void limparCampos() {
		centro.removeAll();
	}

	private void novaVenda() {
		venda = new Venda();
		venda.setCliente(null);
		dlgJanela.close();

	}
}

197 Respostas

R

Observação: O mesmo erro ocorre quando quero apenas visualizar o pedido, (não altera-lo)…Os produtos estão limpos.

Código para visualizar:

grdVenda.addItemDoubleClickListener(event -> {
			if(venda != null) {
				binderVenda.readBean(venda);
				dlgJanela.open();
			}
		});
R

Bom dia pessoal, se alguém puder ajudar com esta questão, fico grato…obg!!

R

@RoinujNosde

Bom dia!!! Vc poderia me ajudar?? Novamente…rs

R

Você tem algum código pra carregar os produtos da venda e exibi-los?

R

@RoinujNosde

Eu tenho esse código para cadastrar produtos:

package br.com.fjsistemas.backend;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@AllArgsConstructor
@NoArgsConstructor
@Data
@Entity
public class Produto {
	

	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	private Long id;
	private String nome;
	private String marca;
	private String modelo;
	private Double valor;

}

Tenho este outro código, que é a tela de cadastros de produtos:

package br.com.fjsistemas.cadastros.view;

import java.util.List;
import java.util.Locale;

import javax.annotation.PostConstruct;

import org.springframework.beans.factory.annotation.Autowired;

import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.button.ButtonVariant;
import com.vaadin.flow.component.dialog.Dialog;
import com.vaadin.flow.component.formlayout.FormLayout;
import com.vaadin.flow.component.grid.Grid;
import com.vaadin.flow.component.grid.GridVariant;
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.component.textfield.NumberField;
import com.vaadin.flow.component.textfield.TextField;
import com.vaadin.flow.data.binder.Binder;
import com.vaadin.flow.data.binder.PropertyId;
import com.vaadin.flow.data.renderer.NumberRenderer;
import com.vaadin.flow.router.PageTitle;
import com.vaadin.flow.router.Route;

import br.com.fjsistemas.backend.Produto;
import br.com.fjsistemas.main.MainView;
import br.com.fjsistemas.service.ProdutoService;

@Route(value = "produto-view", layout = MainView.class)
@PageTitle("Cadastro de Produtos")
public class ProdutoView extends VerticalLayout {

	private static final long serialVersionUID = 1L;
	private HorizontalLayout hltProduto = new HorizontalLayout();
	Grid<Produto> grdProduto = new Grid<>(Produto.class, false);

	private HorizontalLayout hltBarraBotoes = new HorizontalLayout();
	Button btnNovo = new Button("Novo");
	Button btnAlterar = new Button("Alterar");
	Button btnExcluir = new Button("Excluir");

	private Dialog dlgJanela = new Dialog();
	private FormLayout fltCamposProduto = new FormLayout();

	@PropertyId("nome")
	private TextField txtNome = new TextField("Nome");

	@PropertyId("marca")
	private TextField txtMarca = new TextField("Marca");

	@PropertyId("modelo")
	private TextField txtModelo = new TextField("Modelo");

	@PropertyId("valor")
	private NumberField nbfValor = new NumberField("Valor Unitário");

	private HorizontalLayout htlDlgBarraBotoes = new HorizontalLayout();
	private Button btnSalvar = new Button("Salvar");
	private Button btnFechar = new Button("Fechar");

	@Autowired
	ProdutoService produtoService;

	private List<Produto> listaProduto;
	private Produto produto;

	Binder<Produto> binderProduto = new Binder<>(Produto.class);

	public ProdutoView() {

	}

	@PostConstruct
	public void init() {
		configuraTela();

	}

	private void configuraTela() {

		setMargin(false);
		setPadding(false);

		configuraHltProduto();
		configuraFltBarraBotoes();
		configuraDlgJanela();
		populaGrdProduto();
		configuraBinder();

		add(hltProduto, hltBarraBotoes);
	}

	private void configuraFltBarraBotoes() {

		btnNovo.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
		btnNovo.addClickListener(e -> {
			novoClick();
		});

		btnAlterar.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
		btnAlterar.addClickListener(e -> {
			alterarClick();
		});

		btnExcluir.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
		btnExcluir.addClickListener(e -> {
			excluirClick();
		});

		hltBarraBotoes.add(btnNovo, btnAlterar, btnExcluir);
	}

	private void excluirClick() {

		if (produto != null) {
			listaProduto.remove(produto);
			produtoService.delete(produto);
			atualizaGrdProduto();
		}
	}

	private void configuraHltProduto() {
		hltProduto.setWidthFull();
		configuraGrdProduto();
		hltProduto.add(grdProduto);
	}

	private void configuraGrdProduto() {
		grdProduto.setHeight("820px");
		grdProduto.setWidthFull();
	
		
		grdProduto.addColumn(Produto::getId).setHeader("ID:").setAutoWidth(true);

		grdProduto.addColumn(Produto::getNome).setHeader("Produto:").setAutoWidth(true).setKey("nome");

		grdProduto.addColumn(Produto::getMarca).setHeader("Marca:").setAutoWidth(true).setKey("marca");

		grdProduto.addColumn(Produto::getModelo).setHeader("Modelo:").setAutoWidth(true).setKey("modelo");
		
		grdProduto.addColumn(new NumberRenderer<>(Produto::getValor, "R$ %(,.2f", Locale.getDefault(), "R$ 0.00"))
				.setHeader("Valor Unitário:").setAutoWidth(true).setKey("valor");

		grdProduto.addThemeVariants(GridVariant.LUMO_COMPACT, GridVariant.LUMO_COLUMN_BORDERS);

		grdProduto.getColumns().forEach(col -> col.setAutoWidth(true).setSortable(true).setResizable(true));
		
		grdProduto.addItemClickListener(e -> {
			produto = e.getItem();
		});

	}

	private void configuraDlgJanela() {

		btnSalvar.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
		btnSalvar.getStyle().set("margin-top", "25px");
		btnSalvar.addClickListener(e -> {
			salvarClick();
		});

		btnFechar.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
		btnFechar.getStyle().set("margin-top", "25px");
		btnFechar.addClickListener(e -> {
			dlgJanela.close();
		});
		
		fltCamposProduto.add(txtNome, txtMarca, txtModelo, nbfValor);
		htlDlgBarraBotoes.add(btnSalvar, btnFechar);

		dlgJanela.add(fltCamposProduto, htlDlgBarraBotoes);
	}

	private void salvarClick() {

		produto = binderProduto.getBean();

		boolean adicionarLista = produto.getId() == null ? true : false;

		produtoService.create(produto);

		if (adicionarLista) {
			listaProduto.add(produto);
		}
		atualizaGrdProduto();
		novoProduto();
		txtNome.focus();

		binderProduto.setBean(produto);

		if (adicionarLista) {
			dlgJanela.close();
		}
	}

	private void populaGrdProduto() {

		listaProduto = produtoService.read();
		atualizaGrdProduto();
	}

	private void atualizaGrdProduto() {
		grdProduto.setItems(listaProduto);
	}

	private void configuraBinder() {

		binderProduto.bindInstanceFields(this);
		binderProduto.toString().toUpperCase();

	}

	private void novoClick() {

		novoProduto();
		binderProduto.setBean(produto);

		dlgJanela.open();
		txtNome.focus();
	}

	private void alterarClick() {

		if (produto != null) {
			binderProduto.setBean(produto);

			dlgJanela.open();

		}
	}

	private void novoProduto() {
		produto = new Produto();
		produto.setNome(" ");
		dlgJanela.close();

	}
}

e aqui, tenho o código da tela de vendas, e neste código vendas acabo chamando a classe produto para realizar a venda…veja o metodo adicionaProduto();

package br.com.fjsistemas.compraVenda;

import java.text.NumberFormat;
import java.text.ParseException;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

import javax.annotation.PostConstruct;

import org.springframework.beans.factory.annotation.Autowired;
import org.vaadin.textfieldformatter.CustomStringBlockFormatter;

import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.button.ButtonVariant;
import com.vaadin.flow.component.combobox.ComboBox;
import com.vaadin.flow.component.datepicker.DatePicker;
import com.vaadin.flow.component.dialog.Dialog;
import com.vaadin.flow.component.grid.Grid;
import com.vaadin.flow.component.grid.GridVariant;
import com.vaadin.flow.component.html.Div;
import com.vaadin.flow.component.html.Label;
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.component.textfield.NumberField;
import com.vaadin.flow.component.textfield.TextField;
import com.vaadin.flow.data.binder.Binder;
import com.vaadin.flow.data.binder.PropertyId;
import com.vaadin.flow.data.renderer.LocalDateRenderer;
import com.vaadin.flow.router.PageTitle;
import com.vaadin.flow.router.Route;

import br.com.fjsistemas.backend.Cliente;
import br.com.fjsistemas.backend.FormaDePagamento;
import br.com.fjsistemas.backend.Produto;
import br.com.fjsistemas.backend.Venda;
import br.com.fjsistemas.main.MainView;
import br.com.fjsistemas.repository.ClienteRepository;
import br.com.fjsistemas.repository.FormaDePagamentoRepository;
import br.com.fjsistemas.repository.ProdutoRepository;
import br.com.fjsistemas.service.VendaService;

@Route(value = "venda-view", layout = MainView.class)
@PageTitle("Lançamento de Vendas")
public class VendaView extends VerticalLayout {

	private static final long serialVersionUID = 1L;

	private HorizontalLayout hltVenda = new HorizontalLayout();
	Grid<Venda> grdVenda = new Grid<>(Venda.class, false);

	private HorizontalLayout hltBarraBotoes = new HorizontalLayout();
	Button btnNovo = new Button("Novo");
	Button btnAlterar = new Button("Alterar");
	Button btnExcluir = new Button("Excluir");

	private Dialog dlgJanela = new Dialog();

	Div superior = new Div();
	Div centro = new Div();
	Div inferior = new Div();

	HorizontalLayout primeiraLinhaDivSuperior = new HorizontalLayout();
	HorizontalLayout segundaLinhaDivSuperior = new HorizontalLayout();
	HorizontalLayout adicionarProdutos = new HorizontalLayout();

	double somaValores;

	@PropertyId("dataVenda")
	private DatePicker txtDataVenda = new DatePicker("Data Venda");

	@PropertyId("cliente")
	private ComboBox<Cliente> txtNomeCliente = new ComboBox<>("Cliente");

	@PropertyId("telefone")
	private TextField txtTelefone = new TextField("Telefone");

	@PropertyId("celular")
	private TextField txtCelular = new TextField("Celular");

	@PropertyId("endereco")
	private TextField txtEndereco = new TextField("Endereço");

	@PropertyId("numero")
	private TextField txtNumero = new TextField("Nº");

	@PropertyId("bairro")
	private TextField txtBairro = new TextField("Bairro");

	@PropertyId("cidade")
	TextField txtCidade = new TextField("Cidade");

	@PropertyId("estado")
	TextField txtEstado = new TextField("Estado");

	@PropertyId("formaDePagamento")
	private ComboBox<FormaDePagamento> txtFormasPagamento = new ComboBox<>("Formas de Pagamento");
	
	//@PropertyId("produtoVendido")
	//private ComboBox<ProdutoVendido> txtProdutoVendido = new ComboBox<>();

	@PropertyId("valorTotalVenda")
	private TextField campoSomaValores = new TextField();

	private HorizontalLayout htlDlgBarraBotoes = new HorizontalLayout();
	private Button btnSalvar = new Button("Salvar");
	private Button btnFechar = new Button("Fechar");
	private Button btnAdicionarItem = new Button("+ Item");

	@Autowired
	VendaService vendaService;

	@Autowired
	ClienteRepository clienteRepository;

	@Autowired
	FormaDePagamentoRepository formaDePagamentoRepository;
	
	//@Autowired
	//ProdutoVendidoRepository produtoVendidoRepository;

	@Autowired
	ProdutoRepository produtoRepository;

	private List<Venda> listaVendas;
	private List<TextField> valores = new ArrayList<>();
	private Venda venda;

	Binder<Venda> binderVenda = new Binder<>(Venda.class);

	public VendaView() {

	}

	@PostConstruct
	public void init() {
		configuraTela();

	}

	private void configuraTela() {

		setMargin(false);
		setPadding(false);

		configuraHltVenda();
		configuraFltBarraBotoes();
		configuraDlgJanela();
		populaGrdVenda();
		configuraBinder();

		add(hltVenda, hltBarraBotoes);
	}

	private void configuraFltBarraBotoes() {

		btnNovo.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
		btnNovo.addClickListener(e -> {
			novoClick();
		});

		btnAlterar.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
		btnAlterar.addClickListener(e -> {
			alterarClick();
		});

		btnExcluir.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
		btnExcluir.addClickListener(e -> {
			excluirClick();
		});

		hltBarraBotoes.add(btnNovo, btnAlterar, btnExcluir);
	}

	private void excluirClick() {

		if (venda != null) {
			listaVendas.remove(venda);
			vendaService.delete(venda);
			atualizaGrdVenda();
		}
	}

	private void configuraHltVenda() {
		hltVenda.setWidthFull();
		configuraGrdVenda();
		hltVenda.add(grdVenda);
	}

	private void configuraGrdVenda() {
		grdVenda.setHeight("820px");
		grdVenda.setWidthFull();

		grdVenda.addColumn(Venda::getId).setHeader("ID:").setAutoWidth(true);

		grdVenda.addColumn(new LocalDateRenderer<>(Venda::getDataVenda, DateTimeFormatter.ofPattern("dd/MM/yyy")))
				.setHeader("Data Venda").setAutoWidth(true);

		grdVenda.addColumn(venda -> venda.getCliente().getNome()).setHeader("Nome:").setAutoWidth(true)
				.setKey("cliente.nome");

		grdVenda.addColumn(Venda::getValorTotalVenda).setHeader("Valor Total:").setAutoWidth(true)
				.setKey("valorTotalVenda");

		grdVenda.addColumn(venda -> venda.getFormaDePagamento().getFormaDePagamento()).setHeader("Forma de Pagamento")
				.setAutoWidth(true).setKey("formaDePagamento");

		grdVenda.addThemeVariants(GridVariant.LUMO_COMPACT, GridVariant.LUMO_COLUMN_BORDERS);

		grdVenda.getColumns().forEach(col -> col.setAutoWidth(true).setSortable(true).setResizable(true));

		grdVenda.addItemClickListener(e -> {
			venda = e.getItem();
		});

		grdVenda.addItemDoubleClickListener(event -> {
			if (venda != null) {
				binderVenda.readBean(venda);
				dlgJanela.open();

			}
		});

	}

	private void configuraDlgJanela() {

		dlgJanela.setHeightFull();
		dlgJanela.setWidthFull();
		dlgJanela.setCloseOnEsc(false);
		dlgJanela.setCloseOnOutsideClick(false);

		superior.setHeight("170px");
		superior.setWidthFull();

		txtNomeCliente.setWidth("350px");
		txtNomeCliente.setLabel("Nome Cliente");

		txtNomeCliente.setItemLabelGenerator(cliente -> {
			if (cliente == null || cliente.getNome() == null) {
				return " ";

			} else {
				return cliente.getNome();
			}
		});

		List<Cliente> listaDeClientes = clienteRepository.findAll();

		txtNomeCliente.setItems(listaDeClientes);
		txtNomeCliente.addValueChangeListener(event -> {
			if (event.getValue() == null || event.getValue().getFone() == null) {
				txtTelefone.setValue(" ");
			} else {
				txtTelefone.setValue(event.getValue().getFone());
			}
			if (event.getValue() == null || event.getValue().getCelular() == null) {
				txtCelular.setValue(" ");
			} else {
				txtCelular.setValue(event.getValue().getCelular());
			}
			if (event.getValue() == null || event.getValue().getEndereco() == null) {
				txtEndereco.setValue(" ");
			} else {
				txtEndereco.setValue(event.getValue().getEndereco());
			}
			if (event.getValue() == null || event.getValue().getNumero() == null) {
				txtNumero.setValue(" ");
			} else {
				txtNumero.setValue(event.getValue().getNumero());
			}
			if (event.getValue() == null || event.getValue().getBairro() == null) {
				txtBairro.setValue(" ");
			} else {
				txtBairro.setValue(event.getValue().getBairro());
			}
			if (event.getValue() == null || event.getValue().getCidade() == null) {
				txtCidade.setValue(" ");
			} else {
				txtCidade.setValue(event.getValue().getCidade());
			}
			if (event.getValue() == null || event.getValue().getEstado() == null) {
				txtEstado.setValue(" ");
			} else {
				txtEstado.setValue(event.getValue().getEstado());
			}

		});

		new CustomStringBlockFormatter.Builder().blocks(0, 2, 4, 4).delimiters("(", ")", "-").numeric().build()
				.extend(txtTelefone);

		new CustomStringBlockFormatter.Builder().blocks(0, 2, 5, 4).delimiters("(", ")", "-").numeric().build()
				.extend(txtCelular);

		primeiraLinhaDivSuperior.add(txtDataVenda, txtNomeCliente, txtTelefone, txtCelular, txtEndereco, txtNumero,
				txtBairro, txtCidade);

		txtNumero.setWidth("140px");

		txtFormasPagamento.setLabel("Formas de Pagamento");

		List<FormaDePagamento> listaPagamento = formaDePagamentoRepository.findAll();
		txtFormasPagamento.setItemLabelGenerator(FormaDePagamento::getFormaDePagamento);
		txtFormasPagamento.setItems(listaPagamento);

		segundaLinhaDivSuperior.add(txtEstado, txtFormasPagamento);
		superior.add(primeiraLinhaDivSuperior, segundaLinhaDivSuperior);

		centro.setHeight("660px");
		centro.getStyle().set("border-style", "ridge");
		centro.getStyle().set("overflow-y", "scroll");
		centro.setWidthFull();

		btnSalvar.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
		btnSalvar.getStyle().set("margin-top", "0em");
		btnSalvar.getStyle().set("margin-left", "1em");
		btnSalvar.addClickListener(e -> {
			salvarClick();

		});

		btnFechar.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
		btnFechar.getStyle().set("margin-top", "0em");
		btnFechar.addClickListener(e -> {
			dlgJanela.close();
			limparCampos();
		});

		btnAdicionarItem.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
		btnAdicionarItem.getStyle().set("margin-top", "0em");
		btnAdicionarItem.addClickListener(e -> {
			adicionaProduto();
		});

		Label text = new Label("Valor Total");
		text.getElement().getStyle().set("fontWeight", "bold");
		text.getStyle().set("margin-top", "0.8em");
		text.getStyle().set("margin-left", "2em");
		text.getStyle().set("text-align", "center");
		campoSomaValores.getStyle().set("margin-top", "0em");
		campoSomaValores.getStyle().set("margin-right", "0.2em");
		campoSomaValores.setWidth("30em");

		htlDlgBarraBotoes.add(btnSalvar, btnFechar, btnAdicionarItem, text, campoSomaValores);

		inferior.getStyle().set("margin-top", "0px");
		inferior.setHeight("45px");
		inferior.setWidthFull();
		inferior.add(htlDlgBarraBotoes);

		dlgJanela.add(superior, centro, inferior);

	}

	private void salvarClick() {

		venda = binderVenda.getBean();

		boolean adicionarLista = venda.getId() == null ? true : false;

		vendaService.create(venda);

		if (adicionarLista) {
			listaVendas.add(venda);

		}
		atualizaGrdVenda();
		novaVenda();
		txtNomeCliente.focus();

		binderVenda.setBean(venda);

		if (adicionarLista) {

			dlgJanela.close();
		}
	}

	private void populaGrdVenda() {

		listaVendas = vendaService.read();
		atualizaGrdVenda();
	}

	private void atualizaGrdVenda() {
		grdVenda.setItems(listaVendas);
	}

	private void configuraBinder() {

		binderVenda.bindInstanceFields(this);

	}

	private void novoClick() {

		novaVenda();
		binderVenda.setBean(venda);

		dlgJanela.open();
		txtNomeCliente.focus();
	}

	private void alterarClick() {

		if (venda != null) {
			binderVenda.setBean(venda);

			dlgJanela.open();

		}
	}

	private void adicionaProduto() {

		ComboBox<Produto> txtProdutos = new ComboBox<>();

		NumberField txtQuantidade = new NumberField("Quantidade");

		TextField txtValorUnitario = new TextField("Valor Unitário");

		TextField txtValorTotalItem = new TextField("Valor Total Item");

		txtProdutos.setWidth("370px");
		txtProdutos.setLabel("Produtos");
		List<Produto> listaDeProdutos = produtoRepository.findAll();
		txtProdutos.setItemLabelGenerator(Produto::getNome);
		txtProdutos.setItems(listaDeProdutos);
		txtProdutos.addValueChangeListener(event -> {

			NumberFormat formatter = NumberFormat.getCurrencyInstance(new Locale("pt", "BR"));
			try {

				txtValorUnitario.setValue(formatter.format(event.getValue().getValor()));

			} catch (Exception e) {
				e.printStackTrace();
			}

		});

//==========================================================================================================================

		txtQuantidade.setHasControls(true);
		txtQuantidade.setValue(null);
		txtQuantidade.setMin(1);

		txtQuantidade.addValueChangeListener(event -> {

			NumberFormat formatter = NumberFormat.getCurrencyInstance(new Locale("pt", "BR"));
			double valorTotal = 0;

			try {
				valorTotal = formatter.parse(txtValorUnitario.getValue()).doubleValue() * txtQuantidade.getValue();
			} catch (ParseException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

			txtValorTotalItem.setValue(formatter.format(valorTotal));

			double soma = 0;
			for (TextField tf : valores) {
				try {
					soma += formatter.parse(tf.getValue()).doubleValue();

				} catch (ParseException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}

			}

			campoSomaValores.setValue(formatter.format(soma));

		});
				
		adicionarProdutos = new HorizontalLayout();
		adicionarProdutos.add(txtProdutos, txtQuantidade, txtValorUnitario, txtValorTotalItem);
		
		centro.add(adicionarProdutos);
		valores.add(txtValorTotalItem);
	}

	private void limparCampos() {
		centro.removeAll();
	}

	private void novaVenda() {
		venda = new Venda();
		venda.setCliente(null);
		venda.setFormaDePagamento(null);
		dlgJanela.close();

	}
}

agora eu fiquei na duvida se deveria criar uma classe, por exemplo ProdutoVendido com seus atributos(nome, quantidade, valorunitario e valorTotal)…ou se eu uso a classe venda(que é a resposavel por armazenar as vendas)

Classe Venda:

package br.com.fjsistemas.backend;

import java.time.LocalDate;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@AllArgsConstructor
@NoArgsConstructor
@Data
@Entity
public class Venda {

	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	private Long id;

	private LocalDate dataVenda = LocalDate.now();

	@ManyToOne
	private Cliente cliente;
	
	@ManyToOne
	private FormaDePagamento formaDePagamento;
	
	private String valorTotalVenda;
}
R

Eu quero dizer: você vai clicar numa venda, o programa pega os dados dela do banco e armazena na sua entidade Venda.
Nessa entidade tem uma lista de produtos, certo?
Você não parece estar fazendo nenhum carregamento desses produtos na tela, por isso dá esse problema.
O único método que você tem é adicionarProduto(), mas esse sozinho não “dá conta”.

R

@RoinujNosde

não…na entidade Venda não há uma lista, então neste caso o primeiro passo será criar uma List

private List<Produto> produtoVendido = new ArrayList<>();

é isso?

R

Sim, você vai por alguma anotação nela também.

R

@RoinujNosde

com relação a anotação, não sei se meu pensamento está correto, me corrija caso esteja…

Como podem ser muitos produtos para uma venda a anotação deve ser

@ManyToOne?

R

Se for fazer a classe ProdutoVendido (que é interessante), acho que seria OneToMany.

R

@RoinujNosde

Ok então ficou assim minha entidade Venda:

package br.com.fjsistemas.backend;

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@AllArgsConstructor
@NoArgsConstructor
@Data
@Entity
public class Venda {

	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	private Long id;

	private LocalDate dataVenda = LocalDate.now();

	@ManyToOne
	private Cliente cliente;
	
	@ManyToOne
	private FormaDePagamento formaDePagamento;
	
	@OneToMany 
	private List<Produto> produtoVendido = new ArrayList<>();
	
	private String valorTotalVenda;
}

Até aqui ta tudo certo?

R

Não ia ser a classe ProdutoVendido?

R

@RoinujNosde

eu tinha entendido que era pra fazer a lista na classe venda…mas não por isso…então só pra deixar claro, na classe Venda não haverá nenhuma lista, correto?

Vou criar uma classe ProdutoVendido, com os atributos e a lista…correto?

R

@RoinujNosde

se estiver tudo correto, ficou assim:

package br.com.fjsistemas.backend;

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

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@AllArgsConstructor
@NoArgsConstructor
@Data
@Entity
public class ProdutoVendido {
	
	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	private Long id;

	private String produtoVendido;
	private String quantidadeVendida;
	private Double valorUnitarioVendido;
	private Double valorTotalVendido;
	
	@OneToMany
	private List<Produto> listaVendidos = new ArrayList<>();
}
R
Classe Venda:
    private List<ProdutoVendido> produtos
R

@RoinujNosde

Classe Venda:

package br.com.fjsistemas.backend;

import java.time.LocalDate;
import java.util.List;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@AllArgsConstructor
@NoArgsConstructor
@Data
@Entity
public class Venda {

	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	private Long id;

	private LocalDate dataVenda = LocalDate.now();

	@ManyToOne
	private Cliente cliente;
	
	@ManyToOne
	private FormaDePagamento formaDePagamento;
	
	@OneToMany
private List<ProdutoVendido> produtos;
	
	private String valorTotalVenda;
}

Classe ProdutoVendido:

package br.com.fjsistemas.backend;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@AllArgsConstructor
@NoArgsConstructor
@Data
@Entity
public class ProdutoVendido {
	
	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	private Long id;

	private String produtoVendido;
	private String quantidadeVendida;
	private Double valorUnitarioVendido;
	private Double valorTotalVendido;
	
	
}

Correto?

R

Acredito que sim.
Agora precisa implementar uma lógica para carregar esses produtos na tela quando for alterar/exibir a Venda

R

@RoinujNosde

algo assim por exemplo?:

Na classe Venda:

package br.com.fjsistemas.backend;

import java.time.LocalDate;
import java.util.List;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@AllArgsConstructor
@NoArgsConstructor
@Data
@Entity
public class Venda {

	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	private Long id;

	private LocalDate dataVenda = LocalDate.now();

	@ManyToOne
	private Cliente cliente;

	@ManyToOne
	private FormaDePagamento formaDePagamento;

	@OneToMany
	private List<ProdutoVendido> produtos;
	
	public void addProduto(Produto produto) {
		ProdutoVendido produtoVenda = new ProdutoVendido(this, produto);
		produtos.add(produtoVenda);
	}

	private String valorTotalVenda;
}

Classe ProdutoVendido

package br.com.fjsistemas.backend;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@AllArgsConstructor
@NoArgsConstructor
@Data
@Entity
public class ProdutoVendido {
	
	

	public ProdutoVendido(Venda venda, Produto produto) {
		super();
		this.venda = venda;
		this.produto = produto;
	}
	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	private Long id;

	private String produtoVendido;
	private String quantidadeVendida;
	private Double valorUnitarioVendido;
	private Double valorTotalVendido;
	
	private Venda venda;
	private Produto produto;

}

Correto desta forma?

R

Aparentemente sim

R

@RoinujNosde

e como eu chamo este metodo que esta na classe Venda? Digo, minha tela de vendas está em outra classe VendaView, dentro desta VendaView há o método adicionaProduto, que é o responsável por adicionar os produtos na venda…como “linkar” estas situações?

A penas venda.addProduto();? dentro de adicionaProduto?

R

Sim
Lembre-se de criar uma lógica pra remover produtos.

R

@RoinujNosde

ok, fui testar como fizemos…

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Invocation of init method failed; nested exception is javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory; nested exception is org.hibernate.MappingException: Could not determine type for: br.com.fjsistemas.backend.Produto, at table: produto_vendido, for columns: [org.hibernate.mapping.Column(produto)]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1788) ~[spring-beans-5.3.3.jar:5.3.3]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:609) ~[spring-beans-5.3.3.jar:5.3.3]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:531) ~[spring-beans-5.3.3.jar:5.3.3]
	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) ~[spring-beans-5.3.3.jar:5.3.3]
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.3.3.jar:5.3.3]
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) ~[spring-beans-5.3.3.jar:5.3.3]
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) ~[spring-beans-5.3.3.jar:5.3.3]
	at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1159) ~[spring-context-5.3.3.jar:5.3.3]
	at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:913) ~[spring-context-5.3.3.jar:5.3.3]
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:588) ~[spring-context-5.3.3.jar:5.3.3]
	at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:144) ~[spring-boot-2.4.2.jar:2.4.2]
	at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:767) ~[spring-boot-2.4.2.jar:2.4.2]
	at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:759) ~[spring-boot-2.4.2.jar:2.4.2]
	at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:426) ~[spring-boot-2.4.2.jar:2.4.2]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:326) ~[spring-boot-2.4.2.jar:2.4.2]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1311) ~[spring-boot-2.4.2.jar:2.4.2]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1300) ~[spring-boot-2.4.2.jar:2.4.2]
	at br.com.fjsistemas.Application.main(Application.java:11) ~[classes/:na]
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
	at java.base/java.lang.reflect.Method.invoke(Method.java:567) ~[na:na]
	at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49) ~[spring-boot-devtools-2.4.2.jar:2.4.2]
Caused by: javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory; nested exception is org.hibernate.MappingException: Could not determine type for: br.com.fjsistemas.backend.Produto, at table: produto_vendido, for columns: [org.hibernate.mapping.Column(produto)]
	at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:421) ~[spring-orm-5.3.3.jar:5.3.3]
	at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:396) ~[spring-orm-5.3.3.jar:5.3.3]
	at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:341) ~[spring-orm-5.3.3.jar:5.3.3]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1847) ~[spring-beans-5.3.3.jar:5.3.3]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1784) ~[spring-beans-5.3.3.jar:5.3.3]
	... 22 common frames omitted
Caused by: org.hibernate.MappingException: Could not determine type for: br.com.fjsistemas.backend.Produto, at table: produto_vendido, for columns: [org.hibernate.mapping.Column(produto)]
	at org.hibernate.mapping.SimpleValue.getType(SimpleValue.java:499) ~[hibernate-core-5.4.27.Final.jar:5.4.27.Final]
	at org.hibernate.mapping.SimpleValue.isValid(SimpleValue.java:466) ~[hibernate-core-5.4.27.Final.jar:5.4.27.Final]
	at org.hibernate.mapping.Property.isValid(Property.java:227) ~[hibernate-core-5.4.27.Final.jar:5.4.27.Final]
	at org.hibernate.mapping.PersistentClass.validate(PersistentClass.java:624) ~[hibernate-core-5.4.27.Final.jar:5.4.27.Final]
	at org.hibernate.mapping.RootClass.validate(RootClass.java:267) ~[hibernate-core-5.4.27.Final.jar:5.4.27.Final]
	at org.hibernate.boot.internal.MetadataImpl.validate(MetadataImpl.java:354) ~[hibernate-core-5.4.27.Final.jar:5.4.27.Final]
	at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:465) ~[hibernate-core-5.4.27.Final.jar:5.4.27.Final]
	at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:1259) ~[hibernate-core-5.4.27.Final.jar:5.4.27.Final]
	at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:58) ~[spring-orm-5.3.3.jar:5.3.3]
	at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:365) ~[spring-orm-5.3.3.jar:5.3.3]
	at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:409) ~[spring-orm-5.3.3.jar:5.3.3]
	... 26 common frames omitted
R

Classe ProdutoVendido
Tá faltando anotação para a variável Produto

R

@RoinujNosde

Bom dia, ok corrigi o problema, as anotações estão corretas?

Classe ProdutoVendido:

package br.com.fjsistemas.backend;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@AllArgsConstructor
@NoArgsConstructor
@Data
@Entity
public class ProdutoVendido {
	
	

	public ProdutoVendido(Venda venda, Produto produto) {
		super();
		this.venda = venda;
		this.produto = produto;
	}
	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	private Long id;

	private String produtoVendido;
	private String quantidadeVendida;
	private Double valorUnitarioVendido;
	private Double valorTotalVendido;
	
	@ManyToOne
	private Venda venda;
	
	@ManyToOne
	private Produto produto;

}

Fui testar para ver se estava tudo correto, e agora recebi este stack:

java.lang.NullPointerException: null
	at br.com.fjsistemas.backend.Venda.addProduto(Venda.java:41) ~[classes/:na]
	at br.com.fjsistemas.compraVendaView.VendaView.adicionaProduto(VendaView.java:477) ~[classes/:na]
	at br.com.fjsistemas.compraVendaView.VendaView.lambda$16(VendaView.java:328) ~[classes/:na]
	at com.vaadin.flow.component.ComponentEventBus.fireEventForListener(ComponentEventBus.java:205) ~[flow-server-2.4.6.jar:2.4.6]
	at com.vaadin.flow.component.ComponentEventBus.handleDomEvent(ComponentEventBus.java:373) ~[flow-server-2.4.6.jar:2.4.6]
	at com.vaadin.flow.component.ComponentEventBus.lambda$addDomTrigger$dd1b7957$1(ComponentEventBus.java:264) ~[flow-server-2.4.6.jar:2.4.6]
	at com.vaadin.flow.internal.nodefeature.ElementListenerMap.lambda$fireEvent$2(ElementListenerMap.java:441) ~[flow-server-2.4.6.jar:2.4.6]
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1507) ~[na:na]
	at com.vaadin.flow.internal.nodefeature.ElementListenerMap.fireEvent(ElementListenerMap.java:441) ~[flow-server-2.4.6.jar:2.4.6]
	at com.vaadin.flow.server.communication.rpc.EventRpcHandler.handleNode(EventRpcHandler.java:59) ~[flow-server-2.4.6.jar:2.4.6]
	at com.vaadin.flow.server.communication.rpc.AbstractRpcInvocationHandler.handle(AbstractRpcInvocationHandler.java:64) ~[flow-server-2.4.6.jar:2.4.6]
	at com.vaadin.flow.server.communication.ServerRpcHandler.handleInvocationData(ServerRpcHandler.java:409) ~[flow-server-2.4.6.jar:2.4.6]
	at com.vaadin.flow.server.communication.ServerRpcHandler.lambda$handleInvocations$1(ServerRpcHandler.java:390) ~[flow-server-2.4.6.jar:2.4.6]
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1507) ~[na:na]
	at com.vaadin.flow.server.communication.ServerRpcHandler.handleInvocations(ServerRpcHandler.java:390) ~[flow-server-2.4.6.jar:2.4.6]
	at com.vaadin.flow.server.communication.ServerRpcHandler.handleRpc(ServerRpcHandler.java:317) ~[flow-server-2.4.6.jar:2.4.6]
	at com.vaadin.flow.server.communication.UidlRequestHandler.synchronizedHandleRequest(UidlRequestHandler.java:89) ~[flow-server-2.4.6.jar:2.4.6]
	at com.vaadin.flow.server.SynchronizedRequestHandler.handleRequest(SynchronizedRequestHandler.java:40) ~[flow-server-2.4.6.jar:2.4.6]
	at com.vaadin.flow.server.VaadinService.handleRequest(VaadinService.java:1547) ~[flow-server-2.4.6.jar:2.4.6]
	at com.vaadin.flow.server.VaadinServlet.service(VaadinServlet.java:247) ~[flow-server-2.4.6.jar:2.4.6]
	at com.vaadin.flow.spring.SpringServlet.service(SpringServlet.java:111) ~[vaadin-spring-12.3.2.jar:na]
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:733) ~[tomcat-embed-core-9.0.41.jar:4.0.FR]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:712) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:459) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:352) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:312) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.springframework.web.servlet.mvc.ServletForwardingController.handleRequestInternal(ServletForwardingController.java:141) ~[spring-webmvc-5.3.3.jar:5.3.3]
	at org.springframework.web.servlet.mvc.AbstractController.handleRequest(AbstractController.java:177) ~[spring-webmvc-5.3.3.jar:5.3.3]
	at org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.java:52) ~[spring-webmvc-5.3.3.jar:5.3.3]
	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1060) ~[spring-webmvc-5.3.3.jar:5.3.3]
	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:962) ~[spring-webmvc-5.3.3.jar:5.3.3]
	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) ~[spring-webmvc-5.3.3.jar:5.3.3]
	at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909) ~[spring-webmvc-5.3.3.jar:5.3.3]
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:652) ~[tomcat-embed-core-9.0.41.jar:4.0.FR]
	at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) ~[spring-webmvc-5.3.3.jar:5.3.3]
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:733) ~[tomcat-embed-core-9.0.41.jar:4.0.FR]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) ~[tomcat-embed-websocket-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-5.3.3.jar:5.3.3]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.3.jar:5.3.3]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-5.3.3.jar:5.3.3]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.3.jar:5.3.3]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-5.3.3.jar:5.3.3]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.3.jar:5.3.3]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:542) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:143) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:374) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:888) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1597) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) ~[na:na]
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) ~[na:na]
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at java.base/java.lang.Thread.run(Thread.java:830) ~[na:na]

fui verificar a linha 477 da classe VendaView

vi que estava null, então fui passar os atributos para serem add(txtProduto, txtQuantidade, etc)

agora ja não sei mais o que fazer…rs

R
Bora analisar esse erro que o IDE mostrou:

The method addProduto(Produto) in the type Venda is not applicable for the arguments (ComboBox, NumberField, TextField, TextField)

Em português: O método addProduto(Produto) no tipo Venda não é aplicável para os argumentos (ComboBox, NumberField, TextField, TextField)

addProduto(Produto)
Nome do método: addProduto
Parâmetros (quantidade = 1): Produto

Você tentou passar 4 argumentos (ele só pede 1) e os tipos não batem.
O método precisa de um Produto e encontrou ComboBox, NumberField, TextField e TextField.

R

@RoinujNosde

sim, entendo…mas o produto precisa ser salvo na venda com os 4 parâmetros…a venda possui um produto, este produto possui valor unitário, a venda possui a quantidade vendida e o valor total gerado pela multiplicação de unitário por quantidade

então tentei criar este metodo na classe Venda:

public void addProduto(ComboBox<Produto> txtProdutos, NumberField txtQuantidade, TextField txtValorUnitario,
			TextField txtValorTotalItem) {
		ProdutoVendido produtoVenda = new ProdutoVendido();
		produtos.add(produtoVenda);
		
	}

O erro de compilação, deixou de existir…porém ao tentar testar a aplicação:

java.lang.NullPointerException: null
	at br.com.fjsistemas.backend.Venda.addProduto(Venda.java:58) ~[classes/:na]
	at br.com.fjsistemas.compraVendaView.VendaView.adicionaProduto(VendaView.java:477) ~[classes/:na]
	at br.com.fjsistemas.compraVendaView.VendaView.lambda$16(VendaView.java:328) ~[classes/:na]
	at com.vaadin.flow.component.ComponentEventBus.fireEventForListener(ComponentEventBus.java:205) ~[flow-server-2.4.6.jar:2.4.6]
	at com.vaadin.flow.component.ComponentEventBus.handleDomEvent(ComponentEventBus.java:373) ~[flow-server-2.4.6.jar:2.4.6]
	at com.vaadin.flow.component.ComponentEventBus.lambda$addDomTrigger$dd1b7957$1(ComponentEventBus.java:264) ~[flow-server-2.4.6.jar:2.4.6]
	at com.vaadin.flow.internal.nodefeature.ElementListenerMap.lambda$fireEvent$2(ElementListenerMap.java:441) ~[flow-server-2.4.6.jar:2.4.6]
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1507) ~[na:na]
	at com.vaadin.flow.internal.nodefeature.ElementListenerMap.fireEvent(ElementListenerMap.java:441) ~[flow-server-2.4.6.jar:2.4.6]
	at com.vaadin.flow.server.communication.rpc.EventRpcHandler.handleNode(EventRpcHandler.java:59) ~[flow-server-2.4.6.jar:2.4.6]
	at com.vaadin.flow.server.communication.rpc.AbstractRpcInvocationHandler.handle(AbstractRpcInvocationHandler.java:64) ~[flow-server-2.4.6.jar:2.4.6]
	at com.vaadin.flow.server.communication.ServerRpcHandler.handleInvocationData(ServerRpcHandler.java:409) ~[flow-server-2.4.6.jar:2.4.6]
	at com.vaadin.flow.server.communication.ServerRpcHandler.lambda$handleInvocations$1(ServerRpcHandler.java:390) ~[flow-server-2.4.6.jar:2.4.6]
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1507) ~[na:na]
	at com.vaadin.flow.server.communication.ServerRpcHandler.handleInvocations(ServerRpcHandler.java:390) ~[flow-server-2.4.6.jar:2.4.6]
	at com.vaadin.flow.server.communication.ServerRpcHandler.handleRpc(ServerRpcHandler.java:317) ~[flow-server-2.4.6.jar:2.4.6]
	at com.vaadin.flow.server.communication.UidlRequestHandler.synchronizedHandleRequest(UidlRequestHandler.java:89) ~[flow-server-2.4.6.jar:2.4.6]
	at com.vaadin.flow.server.SynchronizedRequestHandler.handleRequest(SynchronizedRequestHandler.java:40) ~[flow-server-2.4.6.jar:2.4.6]
	at com.vaadin.flow.server.VaadinService.handleRequest(VaadinService.java:1547) ~[flow-server-2.4.6.jar:2.4.6]
	at com.vaadin.flow.server.VaadinServlet.service(VaadinServlet.java:247) ~[flow-server-2.4.6.jar:2.4.6]
	at com.vaadin.flow.spring.SpringServlet.service(SpringServlet.java:111) ~[vaadin-spring-12.3.2.jar:na]
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:733) ~[tomcat-embed-core-9.0.41.jar:4.0.FR]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:712) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:459) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:352) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:312) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.springframework.web.servlet.mvc.ServletForwardingController.handleRequestInternal(ServletForwardingController.java:141) ~[spring-webmvc-5.3.3.jar:5.3.3]
	at org.springframework.web.servlet.mvc.AbstractController.handleRequest(AbstractController.java:177) ~[spring-webmvc-5.3.3.jar:5.3.3]
	at org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.java:52) ~[spring-webmvc-5.3.3.jar:5.3.3]
	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1060) ~[spring-webmvc-5.3.3.jar:5.3.3]
	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:962) ~[spring-webmvc-5.3.3.jar:5.3.3]
	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) ~[spring-webmvc-5.3.3.jar:5.3.3]
	at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909) ~[spring-webmvc-5.3.3.jar:5.3.3]
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:652) ~[tomcat-embed-core-9.0.41.jar:4.0.FR]
	at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) ~[spring-webmvc-5.3.3.jar:5.3.3]
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:733) ~[tomcat-embed-core-9.0.41.jar:4.0.FR]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) ~[tomcat-embed-websocket-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-5.3.3.jar:5.3.3]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.3.jar:5.3.3]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-5.3.3.jar:5.3.3]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.3.jar:5.3.3]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-5.3.3.jar:5.3.3]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.3.jar:5.3.3]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:542) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:143) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:374) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:888) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1597) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) ~[na:na]
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) ~[na:na]
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at java.base/java.lang.Thread.run(Thread.java:830) ~[na:na]
R

Você pediu todos esses parâmetros e não faz nada com eles.

O erro está na linha produtos.add(produtoVenda), né? Consegue ver o que está null?

R

@RoinujNosde

o erro ocorre no momento em que clico em “+Item” para adicionar o produto na tela de vendas

quando clico no “+ Item”, da este erro:

java.lang.NullPointerException: null
	at br.com.fjsistemas.backend.Venda.addProduto(Venda.java:46) ~[classes/:na]
	at br.com.fjsistemas.compraVendaView.VendaView.adicionaProduto(VendaView.java:478) ~[classes/:na]
	at br.com.fjsistemas.compraVendaView.VendaView.lambda$16(VendaView.java:329) ~[classes/:na]
	at com.vaadin.flow.component.ComponentEventBus.fireEventForListener(ComponentEventBus.java:205) ~[flow-server-2.4.6.jar:2.4.6]
	at com.vaadin.flow.component.ComponentEventBus.handleDomEvent(ComponentEventBus.java:373) ~[flow-server-2.4.6.jar:2.4.6]
	at com.vaadin.flow.component.ComponentEventBus.lambda$addDomTrigger$dd1b7957$1(ComponentEventBus.java:264) ~[flow-server-2.4.6.jar:2.4.6]
	at com.vaadin.flow.internal.nodefeature.ElementListenerMap.lambda$fireEvent$2(ElementListenerMap.java:441) ~[flow-server-2.4.6.jar:2.4.6]
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1507) ~[na:na]
	at com.vaadin.flow.internal.nodefeature.ElementListenerMap.fireEvent(ElementListenerMap.java:441) ~[flow-server-2.4.6.jar:2.4.6]
	at com.vaadin.flow.server.communication.rpc.EventRpcHandler.handleNode(EventRpcHandler.java:59) ~[flow-server-2.4.6.jar:2.4.6]
	at com.vaadin.flow.server.communication.rpc.AbstractRpcInvocationHandler.handle(AbstractRpcInvocationHandler.java:64) ~[flow-server-2.4.6.jar:2.4.6]
	at com.vaadin.flow.server.communication.ServerRpcHandler.handleInvocationData(ServerRpcHandler.java:409) ~[flow-server-2.4.6.jar:2.4.6]
	at com.vaadin.flow.server.communication.ServerRpcHandler.lambda$handleInvocations$1(ServerRpcHandler.java:390) ~[flow-server-2.4.6.jar:2.4.6]
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1507) ~[na:na]
	at com.vaadin.flow.server.communication.ServerRpcHandler.handleInvocations(ServerRpcHandler.java:390) ~[flow-server-2.4.6.jar:2.4.6]
	at com.vaadin.flow.server.communication.ServerRpcHandler.handleRpc(ServerRpcHandler.java:317) ~[flow-server-2.4.6.jar:2.4.6]
	at com.vaadin.flow.server.communication.UidlRequestHandler.synchronizedHandleRequest(UidlRequestHandler.java:89) ~[flow-server-2.4.6.jar:2.4.6]
	at com.vaadin.flow.server.SynchronizedRequestHandler.handleRequest(SynchronizedRequestHandler.java:40) ~[flow-server-2.4.6.jar:2.4.6]
	at com.vaadin.flow.server.VaadinService.handleRequest(VaadinService.java:1547) ~[flow-server-2.4.6.jar:2.4.6]
	at com.vaadin.flow.server.VaadinServlet.service(VaadinServlet.java:247) ~[flow-server-2.4.6.jar:2.4.6]
	at com.vaadin.flow.spring.SpringServlet.service(SpringServlet.java:111) ~[vaadin-spring-12.3.2.jar:na]
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:733) ~[tomcat-embed-core-9.0.41.jar:4.0.FR]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:712) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:459) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:352) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:312) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.springframework.web.servlet.mvc.ServletForwardingController.handleRequestInternal(ServletForwardingController.java:141) ~[spring-webmvc-5.3.3.jar:5.3.3]
	at org.springframework.web.servlet.mvc.AbstractController.handleRequest(AbstractController.java:177) ~[spring-webmvc-5.3.3.jar:5.3.3]
	at org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.java:52) ~[spring-webmvc-5.3.3.jar:5.3.3]
	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1060) ~[spring-webmvc-5.3.3.jar:5.3.3]
	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:962) ~[spring-webmvc-5.3.3.jar:5.3.3]
	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) ~[spring-webmvc-5.3.3.jar:5.3.3]
	at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909) ~[spring-webmvc-5.3.3.jar:5.3.3]
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:652) ~[tomcat-embed-core-9.0.41.jar:4.0.FR]
	at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) ~[spring-webmvc-5.3.3.jar:5.3.3]
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:733) ~[tomcat-embed-core-9.0.41.jar:4.0.FR]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) ~[tomcat-embed-websocket-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-5.3.3.jar:5.3.3]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.3.jar:5.3.3]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-5.3.3.jar:5.3.3]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.3.jar:5.3.3]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-5.3.3.jar:5.3.3]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.3.jar:5.3.3]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:542) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:143) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:374) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:888) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1597) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) ~[na:na]
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) ~[na:na]
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at java.base/java.lang.Thread.run(Thread.java:830) ~[na:na]

Respondendo sua pergunta, sim o erro está na linha produtos.add(produtoVenda), e não, não consigo ver o que está null

R

A NullPointerException é jogada (não apenas) quando você tenta acessar um método em uma referência nula.

No seu caso:
produtos.add(produtoVenda)
produtos -> referência
add -> método
produtoVenda -> argumento

Ou seja, sua referência “produtos” é nula.

R

@RoinujNosde

entao, mas essa referencia “produtos” é a lista que vc me sugeriu criar ontem na classe venda

@OneToMany
	private List<ProdutoVendido> produtos;
R

Você não atribuiu (sinal de =) nada a ela.
O valor padrão para campos não-primitivos (objetos) é null.

R

@RoinujNosde

@OneToMany
	private List<ProdutoVendido> produtos;

	public void addProduto(ComboBox<Produto> txtProdutos, NumberField txtQuantidade, TextField txtValorUnitario,
			TextField txtValorTotalItem) {
		ProdutoVendido produtoVenda = new ProdutoVendido();
		produtos.add(produtoVenda);
	}

aqui está o código da lista e do metodo, entao no código do metodo em vez de produtos.add(produtoVenda);…devo fazer produtos = ??

R
class Foo {
    //campos
    private List list1; //null, não atribuí nada
    private List list2 = new ArrayList(); //não-null, atribuí um novo objeto ArrayList
    
    void bar() {
        list1.add("Oi"); //seu erro, list1 é null, não pode chamar métodos
        list2.add("Oi"); //funciona, pois list2 não é null
    }
}
R

@RoinujNosde

certo, entendi…fiz as alterações(veja se está correto) e veja o resultado

R

Sua lista é de ProdutoVendido e no método add() você está passando ComboBox.
Tem que passar ProdutoVendido.

R

@RoinujNosde

entao…fiz o seguinte

Classe Venda:

@OneToMany
	private List<ProdutoVendido> produtos = new ArrayList<>();

	public void addProduto(ProdutoVendido txtProdutos, NumberField txtQuantidade, TextField txtValorUnitario,
			TextField txtValorTotalItem) {
		ProdutoVendido produtoVenda = new ProdutoVendido(id, valorTotalVenda, valorTotalVenda, null, null, null, null);
		produtos.add(produtoVenda);
	}

Mas ao fazer a mudança na classe Venda, a classe VendaView da este erro:

R

tbm tentei isso: Classe Venda

@OneToMany
	private List<ProdutoVendido> produtos = new ArrayList<>();

	public void addProduto(ProdutoVendido produtoVendido) {
		ProdutoVendido produtoVenda = new ProdutoVendido();
		produtos.add(produtoVenda);
	}

Classe VendaView

L

@rafaspara2017 evite ficar mandando a imagem do código (isso não facilita para quem tah ajudando). Tente, sempre que possível, mandar como texto mesmo. Tente mandar somente a parte do código em que está a dúvida (ou erro).

R

Leia o que diz o erro.
“O método addProduto(ProdutoVendido) não é aplicável para os argumentos (ComboBox, NumberField, TextField, TextField)”

Eu já expliquei acima. O método quer 1 argumento do tipo ProdutoVendido e vc está passando 4 argumentos de tipos diferentes.

R

@RoinujNosde

o que eu não entendo é

adicionarProdutos = new HorizontalLayout();
		adicionarProdutos.add(txtProdutos, txtQuantidade, txtValorUnitario, txtValorTotalItem);
		
		//venda.addProduto();

as variaveis txtProdutos, txtQuantidade, txtValorUnitario, txtValorTotalitem…elas são as responsaveis por definir o produto a ser vendido, a quantidade, o valor unitario do produto definido e o valor total da venda respctivamente.

Então como faço para passar essas variaveis, que estão armazenando os valores, produtos e quantidade para o metodo addProduto() da classe Venda? Não entendo quando vc me fala pra passar 1 argumento de produto vendido…

Na classe ProdutoVendido

package br.com.fjsistemas.backend;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@AllArgsConstructor
@NoArgsConstructor
@Data
@Entity
public class ProdutoVendido {
	
	

	public ProdutoVendido(Venda venda, Produto produto) {
		super();
		this.venda = venda;
		this.produto = produto;
	}
	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	private Long id;
	
	@ManyToOne
	private Venda venda;
	
	@ManyToOne
	private Produto produto;

}

Na Classe Venda:

package br.com.fjsistemas.backend;

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@AllArgsConstructor
@NoArgsConstructor
@Data
@Entity
public class Venda {

	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	private Long id;

	private LocalDate dataVenda = LocalDate.now();

	@ManyToOne
	private Cliente cliente;

	@ManyToOne
	private FormaDePagamento formaDePagamento;

	@OneToMany
	private List<ProdutoVendido> produtos = new ArrayList<>();

	public void addProduto() {
		ProdutoVendido produtoVenda = new ProdutoVendido();
		produtos.add(produtoVenda);
	}

	private String valorTotalVenda;

}
L

Vc tem razão, mas há umas coisas estranhas:

  • O produto está definido como um txtProdutos. Nesse caso, o produto deveria ser o ID que referencia o produto no banco, ou a propria entidade Produto carregada do banco.
R

@Lucas_Camara

Eu sei que vc não gosta que poste imagens, mas não tem outra forma para te mostrar…rs

Veja meu banco

Produto:

Cliente:

FormaDePagamento:

Venda:

L

Tranquilo man. Digo mais quando é código. E não é soh por mim (de forma geral, o pessoal acha melhor o texto também). Para ler o código, e até mesmo testar qdo é possível, as imagens não ajudam muito.

R

@Lucas_Camara e @RoinujNosde

Como vcs me orientam para resolver este problema?

L

Nessa parte:

adicionarProdutos = new HorizontalLayout();
adicionarProdutos.add(txtProdutos, txtQuantidade, txtValorUnitario, txtValorTotalItem);

Qual o valor que vem na variável txtProdutos?

R

@Lucas_Camara

Nesta variavel, vem o nome/descrição do produto

veja se fica mais claro

tela de vendas, vou fazer uma venda do ZERO

Abro a tela, clico em preencho cliente e forma de pagamento agora vou add produtos para serem vendidos, clico em “+ item”

ao clicar em “+item”, aparece 4 campos Produtos(txtProdutos), Quantidade(txtQuantidade), Valor Unitario(txtValorUnitario) e Valor Total Item(txtValorTotalItem)…preencho o produto:

ao selecionar o produto, ja recebo seu valor unitario

defino a quantidade e ja recebo o valor total daquele item:

se houver mais de um item na venda, basta repetir todo o processo:

ao lado dos botoes tenho um campo que recebe a soma de todos os itens

L

Vc deveria está sempre com, ou o ID do produto ou com o instancia de objeto referente ao produto, qdo for adicionar. Pois o que a base de dados precisa para vincular o produto à venda é do produto propriamente dito, e vc consegue o produto é pelo ID dele.

No nomento em que o produto é adicionado, tu seleciona ele numa combobox. Essa combobox deveria te fornecer, no mínimo, o ID do produto selecionado.

Com isso, vc conseguiria recuperar o produto do banco e adicionar na lista de produtos da venda.

R

Nota: aqui não é onde ele tem o erro, isso é código de view.

Ele tá com erro na classe Venda. (Entidade)
Quer adicionar produtos nela.

R

@RoinujNosde

exato

R

@Lucas_Camara, entendi…mas como resolver o problema?
o que devo fazer?

R

@Lucas_Camara

aquele comboBox busca o produto nesta tabela…veja que o produto tem o ID gerado…

L

Sim, pq na view ele não tem os valores no formato que a venda espera. Ele está passando tudo como string basicamente. E o txtProdutos é somente a descrição do, o que soh serve para mostrar na tela.

R

@RoinujNosde e @Lucas_Camara

tentei isso tbm na classe VendaView, dentro do metodo adicionaProduto()

venda.addProduto(txtProdutos.getValue().getId());

mas da erro:

The method addProduto() in the type Venda is not applicable for the arguments (Long)

R

Ele tem um ComboBox<Produto>, chamando o getValue() nele retorna um objeto Produto. Daí deve conseguir pegar id, etc.

L

Vc teria que fazer algo assim:

Long idProduto = txtProdutos.getValue().getId()
Produto produto = produtoRepository.findById(idProduto);
venda.addProduto(produto);
R

@Lucas_Camara

isso na classe Venda? Devo fazer isso

Long idProduto = txtProdutos.getValue().getId()
Produto produto = produtoRepository.findById(idProduto);
venda.addProduto(produto);

substituir isso:

public void addProduto() {
		ProdutoVendido produtoVenda = new ProdutoVendido();
		produtos.add(produtoVenda);
	}

Correto?

L

Isso na tela msm, qdo o produto fosse adicionado. O melhor, é a venda não conhecer nenhum elemento de tela.

R

@Lucas_Camara

então isso:

Long idProduto = txtProdutos.getValue().getId()

Produto produto = produtoRepository.findById(idProduto);

venda.addProduto(produto);

na VendaView(que é a tela de vendas)

R

@Lucas_Camara

tentei o código que vc passou, mas da um erro

este trecho do código está sublinhado em vermelho:

produtoRepository.findById(idProduto);

com essa msg:

Type mismatch: cannot convert from Optional to Produto

change type of ‘produto’ to ‘Optional’

L

Ah sim. O findById retorna um Optional. Em vez dele, tu pode usar o getOne.

Com o optional, tb funciona, basta fazer assim:

Optional<Produto> produto = produtoRepository.findById(idProduto);

if (produto.isPresent()) {
    venda.adicionarProduto(produto.get());
}

// ou 

produto.ifPresent(p -> venda.adicionarProduto(p));
R

@Lucas_Camara acho que não precisa usar o findById.
No comboBox ele já tá setando os produtos direto do repositório, então já são managed.
Só um combobox.getValue() já serviria.

L

@RoinujNosde Verdade, nem me toquei disso.

@rafaspara2017 faz soh:

venda.adicionarProduto(txtProdutos.getValue())

que já resolve.

R

@Lucas_Camara ou @RoinujNosde

org.springframework.dao.InvalidDataAccessApiUsageException: org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: br.com.fjsistemas.backend.ProdutoVendido; nested exception is java.lang.IllegalStateException: org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: br.com.fjsistemas.backend.ProdutoVendido
	at org.springframework.orm.jpa.EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible(EntityManagerFactoryUtils.java:371) ~[spring-orm-5.3.3.jar:5.3.3]
	at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:235) ~[spring-orm-5.3.3.jar:5.3.3]
	at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:566) ~[spring-orm-5.3.3.jar:5.3.3]
	at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:743) ~[spring-tx-5.3.3.jar:5.3.3]
	at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:711) ~[spring-tx-5.3.3.jar:5.3.3]
	at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:654) ~[spring-tx-5.3.3.jar:5.3.3]
	at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:407) ~[spring-tx-5.3.3.jar:5.3.3]
	at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119) ~[spring-tx-5.3.3.jar:5.3.3]
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.3.jar:5.3.3]
	at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:137) ~[spring-tx-5.3.3.jar:5.3.3]
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.3.jar:5.3.3]
	at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:174) ~[spring-data-jpa-2.4.3.jar:2.4.3]
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.3.jar:5.3.3]
	at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:97) ~[spring-aop-5.3.3.jar:5.3.3]
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.3.jar:5.3.3]
	at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:215) ~[spring-aop-5.3.3.jar:5.3.3]
	at com.sun.proxy.$Proxy111.save(Unknown Source) ~[na:na]
	at br.com.fjsistemas.service.VendaService.create(VendaService.java:20) ~[classes/:na]
	at br.com.fjsistemas.compraVendaView.VendaView.salvarClick(VendaView.java:357) ~[classes/:na]
	at br.com.fjsistemas.compraVendaView.VendaView.lambda$14(VendaView.java:314) ~[classes/:na]
	at com.vaadin.flow.component.ComponentEventBus.fireEventForListener(ComponentEventBus.java:205) ~[flow-server-2.4.6.jar:2.4.6]
	at com.vaadin.flow.component.ComponentEventBus.handleDomEvent(ComponentEventBus.java:373) ~[flow-server-2.4.6.jar:2.4.6]
	at com.vaadin.flow.component.ComponentEventBus.lambda$addDomTrigger$dd1b7957$1(ComponentEventBus.java:264) ~[flow-server-2.4.6.jar:2.4.6]
	at com.vaadin.flow.internal.nodefeature.ElementListenerMap.lambda$fireEvent$2(ElementListenerMap.java:441) ~[flow-server-2.4.6.jar:2.4.6]
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1507) ~[na:na]
	at com.vaadin.flow.internal.nodefeature.ElementListenerMap.fireEvent(ElementListenerMap.java:441) ~[flow-server-2.4.6.jar:2.4.6]
	at com.vaadin.flow.server.communication.rpc.EventRpcHandler.handleNode(EventRpcHandler.java:59) ~[flow-server-2.4.6.jar:2.4.6]
	at com.vaadin.flow.server.communication.rpc.AbstractRpcInvocationHandler.handle(AbstractRpcInvocationHandler.java:64) ~[flow-server-2.4.6.jar:2.4.6]
	at com.vaadin.flow.server.communication.ServerRpcHandler.handleInvocationData(ServerRpcHandler.java:409) ~[flow-server-2.4.6.jar:2.4.6]
	at com.vaadin.flow.server.communication.ServerRpcHandler.lambda$handleInvocations$1(ServerRpcHandler.java:390) ~[flow-server-2.4.6.jar:2.4.6]
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1507) ~[na:na]
	at com.vaadin.flow.server.communication.ServerRpcHandler.handleInvocations(ServerRpcHandler.java:390) ~[flow-server-2.4.6.jar:2.4.6]
	at com.vaadin.flow.server.communication.ServerRpcHandler.handleRpc(ServerRpcHandler.java:317) ~[flow-server-2.4.6.jar:2.4.6]
	at com.vaadin.flow.server.communication.UidlRequestHandler.synchronizedHandleRequest(UidlRequestHandler.java:89) ~[flow-server-2.4.6.jar:2.4.6]
	at com.vaadin.flow.server.SynchronizedRequestHandler.handleRequest(SynchronizedRequestHandler.java:40) ~[flow-server-2.4.6.jar:2.4.6]
	at com.vaadin.flow.server.VaadinService.handleRequest(VaadinService.java:1547) ~[flow-server-2.4.6.jar:2.4.6]
	at com.vaadin.flow.server.VaadinServlet.service(VaadinServlet.java:247) ~[flow-server-2.4.6.jar:2.4.6]
	at com.vaadin.flow.spring.SpringServlet.service(SpringServlet.java:111) ~[vaadin-spring-12.3.2.jar:na]
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:733) ~[tomcat-embed-core-9.0.41.jar:4.0.FR]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:712) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:459) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:352) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:312) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.springframework.web.servlet.mvc.ServletForwardingController.handleRequestInternal(ServletForwardingController.java:141) ~[spring-webmvc-5.3.3.jar:5.3.3]
	at org.springframework.web.servlet.mvc.AbstractController.handleRequest(AbstractController.java:177) ~[spring-webmvc-5.3.3.jar:5.3.3]
	at org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.java:52) ~[spring-webmvc-5.3.3.jar:5.3.3]
	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1060) ~[spring-webmvc-5.3.3.jar:5.3.3]
	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:962) ~[spring-webmvc-5.3.3.jar:5.3.3]
	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) ~[spring-webmvc-5.3.3.jar:5.3.3]
	at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909) ~[spring-webmvc-5.3.3.jar:5.3.3]
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:652) ~[tomcat-embed-core-9.0.41.jar:4.0.FR]
	at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) ~[spring-webmvc-5.3.3.jar:5.3.3]
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:733) ~[tomcat-embed-core-9.0.41.jar:4.0.FR]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) ~[tomcat-embed-websocket-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-5.3.3.jar:5.3.3]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.3.jar:5.3.3]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-5.3.3.jar:5.3.3]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.3.jar:5.3.3]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-5.3.3.jar:5.3.3]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.3.jar:5.3.3]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:542) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:143) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:374) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:888) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1597) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) ~[na:na]
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) ~[na:na]
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at java.base/java.lang.Thread.run(Thread.java:830) ~[na:na]
Caused by: java.lang.IllegalStateException: org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: br.com.fjsistemas.backend.ProdutoVendido
	at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:151) ~[hibernate-core-5.4.27.Final.jar:5.4.27.Final]
	at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:181) ~[hibernate-core-5.4.27.Final.jar:5.4.27.Final]
	at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:188) ~[hibernate-core-5.4.27.Final.jar:5.4.27.Final]
	at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1366) ~[hibernate-core-5.4.27.Final.jar:5.4.27.Final]
	at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:453) ~[hibernate-core-5.4.27.Final.jar:5.4.27.Final]
	at org.hibernate.internal.SessionImpl.flushBeforeTransactionCompletion(SessionImpl.java:3212) ~[hibernate-core-5.4.27.Final.jar:5.4.27.Final]
	at org.hibernate.internal.SessionImpl.beforeTransactionCompletion(SessionImpl.java:2380) ~[hibernate-core-5.4.27.Final.jar:5.4.27.Final]
	at org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.beforeTransactionCompletion(JdbcCoordinatorImpl.java:447) ~[hibernate-core-5.4.27.Final.jar:5.4.27.Final]
	at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.beforeCompletionCallback(JdbcResourceLocalTransactionCoordinatorImpl.java:183) ~[hibernate-core-5.4.27.Final.jar:5.4.27.Final]
	at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.access$300(JdbcResourceLocalTransactionCoordinatorImpl.java:40) ~[hibernate-core-5.4.27.Final.jar:5.4.27.Final]
	at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.commit(JdbcResourceLocalTransactionCoordinatorImpl.java:281) ~[hibernate-core-5.4.27.Final.jar:5.4.27.Final]
	at org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:101) ~[hibernate-core-5.4.27.Final.jar:5.4.27.Final]
	at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:562) ~[spring-orm-5.3.3.jar:5.3.3]
	... 85 common frames omitted
Caused by: org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: br.com.fjsistemas.backend.ProdutoVendido
	at org.hibernate.engine.internal.ForeignKeys.getEntityIdentifierIfNotUnsaved(ForeignKeys.java:347) ~[hibernate-core-5.4.27.Final.jar:5.4.27.Final]
	at org.hibernate.type.EntityType.getIdentifier(EntityType.java:507) ~[hibernate-core-5.4.27.Final.jar:5.4.27.Final]
	at org.hibernate.type.EntityType.nullSafeSet(EntityType.java:280) ~[hibernate-core-5.4.27.Final.jar:5.4.27.Final]
	at org.hibernate.persister.collection.AbstractCollectionPersister.writeElement(AbstractCollectionPersister.java:930) ~[hibernate-core-5.4.27.Final.jar:5.4.27.Final]
	at org.hibernate.persister.collection.AbstractCollectionPersister.recreate(AbstractCollectionPersister.java:1352) ~[hibernate-core-5.4.27.Final.jar:5.4.27.Final]
	at org.hibernate.action.internal.CollectionRecreateAction.execute(CollectionRecreateAction.java:52) ~[hibernate-core-5.4.27.Final.jar:5.4.27.Final]
	at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:604) ~[hibernate-core-5.4.27.Final.jar:5.4.27.Final]
	at org.hibernate.engine.spi.ActionQueue.lambda$executeActions$1(ActionQueue.java:478) ~[hibernate-core-5.4.27.Final.jar:5.4.27.Final]
	at java.base/java.util.LinkedHashMap.forEach(LinkedHashMap.java:684) ~[na:na]
	at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:475) ~[hibernate-core-5.4.27.Final.jar:5.4.27.Final]
	at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:348) ~[hibernate-core-5.4.27.Final.jar:5.4.27.Final]
	at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:40) ~[hibernate-core-5.4.27.Final.jar:5.4.27.Final]
	at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:102) ~[hibernate-core-5.4.27.Final.jar:5.4.27.Final]
	at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1362) ~[hibernate-core-5.4.27.Final.jar:5.4.27.Final]
	... 94 common frames omitted

Classe Venda

package br.com.fjsistemas.backend;

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@AllArgsConstructor
@NoArgsConstructor
@Data
@Entity
public class Venda {

	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	private Long id;

	private LocalDate dataVenda = LocalDate.now();

	@ManyToOne
	private Cliente cliente;

	@ManyToOne
	private FormaDePagamento formaDePagamento;
	
	@ManyToOne
	private ProdutoVendido produtoVendido;

	@OneToMany
	private List<ProdutoVendido> produtos = new ArrayList<>();

	public void addProduto(Produto produto) {
		ProdutoVendido produtoVenda = new ProdutoVendido();
		produtos.add(produtoVenda);
	}

	private String valorTotalVenda;

}

Classe VendaView (somente o metodo adicionar produto)

private void adicionaProduto() {

		ComboBox<Produto> txtProdutos = new ComboBox<>();

		NumberField txtQuantidade = new NumberField("Quantidade");

		TextField txtValorUnitario = new TextField("Valor Unitário");

		TextField txtValorTotalItem = new TextField("Valor Total Item");

		txtProdutos.setWidth("370px");
		txtProdutos.setLabel("Produtos");
		List<Produto> listaDeProdutos = produtoRepository.findAll();
		txtProdutos.setItemLabelGenerator(Produto::getNome);
		txtProdutos.setItems(listaDeProdutos);
		txtProdutos.addValueChangeListener(event -> {

			NumberFormat formatter = NumberFormat.getCurrencyInstance(new Locale("pt", "BR"));
			try {

				txtValorUnitario.setValue(formatter.format(event.getValue().getValor()));

			} catch (Exception e) {
				e.printStackTrace();
			}

		});

//==========================================================================================================================

		txtQuantidade.setHasControls(true);
		txtQuantidade.setValue(null);
		txtQuantidade.setMin(1);

		txtQuantidade.addValueChangeListener(event -> {

			NumberFormat formatter = NumberFormat.getCurrencyInstance(new Locale("pt", "BR"));
			double valorTotal = 0;

			try {
				valorTotal = formatter.parse(txtValorUnitario.getValue()).doubleValue() * txtQuantidade.getValue();
			} catch (ParseException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

			txtValorTotalItem.setValue(formatter.format(valorTotal));

			double soma = 0;
			for (TextField tf : valores) {
				try {
					soma += formatter.parse(tf.getValue()).doubleValue();

				} catch (ParseException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}

			}

			campoSomaValores.setValue(formatter.format(soma));

		});

		adicionarProdutos = new HorizontalLayout();
		adicionarProdutos.add(txtProdutos, txtQuantidade, txtValorUnitario, txtValorTotalItem);
		
		venda.addProduto(txtProdutos.getValue());

		centro.add(adicionarProdutos);
		valores.add(txtValorTotalItem);
	}
L

Ta quase. Agora altera a anotação dos produtos vendidos para:

@OneToMany(cascade = CascadeType.PERSIST)

Isso vai fazer com que o JPA salve os elementos da lista (filhos) quando a entidade (pai) for salva também.

R

@Lucas_Camara

fiz a alteração

e deu este stack:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Invocation of init method failed; nested exception is org.hibernate.AnnotationException: Illegal attempt to map a non collection as a @OneToMany, @ManyToMany or @CollectionOfElements: br.com.fjsistemas.backend.Venda.produtoVendido
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1788) ~[spring-beans-5.3.3.jar:5.3.3]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:609) ~[spring-beans-5.3.3.jar:5.3.3]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:531) ~[spring-beans-5.3.3.jar:5.3.3]
	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) ~[spring-beans-5.3.3.jar:5.3.3]
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.3.3.jar:5.3.3]
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) ~[spring-beans-5.3.3.jar:5.3.3]
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) ~[spring-beans-5.3.3.jar:5.3.3]
	at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1159) ~[spring-context-5.3.3.jar:5.3.3]
	at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:913) ~[spring-context-5.3.3.jar:5.3.3]
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:588) ~[spring-context-5.3.3.jar:5.3.3]
	at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:144) ~[spring-boot-2.4.2.jar:2.4.2]
	at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:767) ~[spring-boot-2.4.2.jar:2.4.2]
	at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:759) ~[spring-boot-2.4.2.jar:2.4.2]
	at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:426) ~[spring-boot-2.4.2.jar:2.4.2]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:326) ~[spring-boot-2.4.2.jar:2.4.2]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1311) ~[spring-boot-2.4.2.jar:2.4.2]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1300) ~[spring-boot-2.4.2.jar:2.4.2]
	at br.com.fjsistemas.Application.main(Application.java:11) ~[classes/:na]
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
	at java.base/java.lang.reflect.Method.invoke(Method.java:567) ~[na:na]
	at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49) ~[spring-boot-devtools-2.4.2.jar:2.4.2]
Caused by: org.hibernate.AnnotationException: Illegal attempt to map a non collection as a @OneToMany, @ManyToMany or @CollectionOfElements: br.com.fjsistemas.backend.Venda.produtoVendido
	at org.hibernate.cfg.annotations.CollectionBinder.getCollectionBinder(CollectionBinder.java:324) ~[hibernate-core-5.4.27.Final.jar:5.4.27.Final]
	at org.hibernate.cfg.AnnotationBinder.processElementAnnotations(AnnotationBinder.java:1953) ~[hibernate-core-5.4.27.Final.jar:5.4.27.Final]
	at org.hibernate.cfg.AnnotationBinder.processIdPropertiesIfNotAlready(AnnotationBinder.java:975) ~[hibernate-core-5.4.27.Final.jar:5.4.27.Final]
	at org.hibernate.cfg.AnnotationBinder.bindClass(AnnotationBinder.java:802) ~[hibernate-core-5.4.27.Final.jar:5.4.27.Final]
	at org.hibernate.boot.model.source.internal.annotations.AnnotationMetadataSourceProcessorImpl.processEntityHierarchies(AnnotationMetadataSourceProcessorImpl.java:248) ~[hibernate-core-5.4.27.Final.jar:5.4.27.Final]
	at org.hibernate.boot.model.process.spi.MetadataBuildingProcess$1.processEntityHierarchies(MetadataBuildingProcess.java:239) ~[hibernate-core-5.4.27.Final.jar:5.4.27.Final]
	at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:282) ~[hibernate-core-5.4.27.Final.jar:5.4.27.Final]
	at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:1224) ~[hibernate-core-5.4.27.Final.jar:5.4.27.Final]
	at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:1255) ~[hibernate-core-5.4.27.Final.jar:5.4.27.Final]
	at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:58) ~[spring-orm-5.3.3.jar:5.3.3]
	at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:365) ~[spring-orm-5.3.3.jar:5.3.3]
	at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:409) ~[spring-orm-5.3.3.jar:5.3.3]
	at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:396) ~[spring-orm-5.3.3.jar:5.3.3]
	at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:341) ~[spring-orm-5.3.3.jar:5.3.3]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1847) ~[spring-beans-5.3.3.jar:5.3.3]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1784) ~[spring-beans-5.3.3.jar:5.3.3]
	... 22 common frames omitted

Se eu entendi, vc pediu para alterar na classe Venda a anotação, foi o que fiz…classe venda neste momento:

package br.com.fjsistemas.backend;

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@AllArgsConstructor
@NoArgsConstructor
@Data
@Entity
public class Venda {

	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	private Long id;

	private LocalDate dataVenda = LocalDate.now();

	@ManyToOne
	private Cliente cliente;

	@ManyToOne
	private FormaDePagamento formaDePagamento;
	
	@OneToMany(cascade = CascadeType.PERSIST)										
	private ProdutoVendido produtoVendido;

	@OneToMany
	private List<ProdutoVendido> produtos = new ArrayList<>();

	public void addProduto(Produto produto) {
		ProdutoVendido produtoVenda = new ProdutoVendido();
		produtos.add(produtoVenda);
	}

	private String valorTotalVenda;

}
R

@Lucas_Camara

Se eu passar a anotação:

@OneToMany(cascade = CascadeType.PERSIST) para lista, o stack deixa de existir, então a classe Venda ficaria assim:

package br.com.fjsistemas.backend;

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@AllArgsConstructor
@NoArgsConstructor
@Data
@Entity
public class Venda {

	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	private Long id;

	private LocalDate dataVenda = LocalDate.now();

	@ManyToOne
	private Cliente cliente;

	@ManyToOne
	private FormaDePagamento formaDePagamento;
	
	@ManyToOne										
	private ProdutoVendido produtoVendido;

	@OneToMany(cascade = CascadeType.PERSIST)
	private List<ProdutoVendido> produtos = new ArrayList<>();

	public void addProduto(Produto produto) {
		ProdutoVendido produtoVenda = new ProdutoVendido();
		produtos.add(produtoVenda);
	}

	private String valorTotalVenda;

}

Desta forma não há erros de compilação ou execução…mas o sistema ainda não exibe os produtos vendidos na tela…veja:

L

Esse é o certo. O @OneToMany tem que ficar na lista.

Esse mapeamento serve para vc gravar os produtos relacionados à venda, no momento em que a venda é salva.

Ao editar uma venda, e vc quiser ver os produtos que foram vendidos, vc tera que carregar a venda e ler essa lista de produtos vendidos dela.

R

@Lucas_Camara

entendi o conceito e a ideia, mas não sei como colocar em pratica, poderia me ajudar?

L

Como que vc faz para editar uma venda? Como que vc carrega ela do banco?

R

@Lucas_Camara

Na minha View(VendaView) tenho este método para salvar as vendas:

private void salvarClick() {

		venda = binderVenda.getBean();

		boolean adicionarLista = venda.getId() == null ? true : false;

		vendaService.create(venda);

		if (adicionarLista) {
			listaVendas.add(venda);

		}
		atualizaGrdVenda();
		novaVenda();
		txtNomeCliente.focus();

		binderVenda.setBean(venda);

		if (adicionarLista) {
			
			dlgJanela.close();
		}
	}
R

este método altera

private void alterarClick() {

		if (venda != null) {
			binderVenda.setBean(venda);

			dlgJanela.open();

		}
	}
R

VendaView Completa:

package br.com.fjsistemas.compraVendaView;

import java.text.NumberFormat;
import java.text.ParseException;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

import javax.annotation.PostConstruct;

import org.springframework.beans.factory.annotation.Autowired;
import org.vaadin.textfieldformatter.CustomStringBlockFormatter;

import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.button.ButtonVariant;
import com.vaadin.flow.component.combobox.ComboBox;
import com.vaadin.flow.component.datepicker.DatePicker;
import com.vaadin.flow.component.dialog.Dialog;
import com.vaadin.flow.component.grid.Grid;
import com.vaadin.flow.component.grid.GridVariant;
import com.vaadin.flow.component.html.Div;
import com.vaadin.flow.component.html.Label;
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.component.textfield.NumberField;
import com.vaadin.flow.component.textfield.TextField;
import com.vaadin.flow.data.binder.Binder;
import com.vaadin.flow.data.binder.PropertyId;
import com.vaadin.flow.data.renderer.LocalDateRenderer;
import com.vaadin.flow.router.PageTitle;
import com.vaadin.flow.router.Route;

import br.com.fjsistemas.backend.Cliente;
import br.com.fjsistemas.backend.FormaDePagamento;
import br.com.fjsistemas.backend.Produto;
import br.com.fjsistemas.backend.Venda;
import br.com.fjsistemas.main.MainView;
import br.com.fjsistemas.repository.ClienteRepository;
import br.com.fjsistemas.repository.FormaDePagamentoRepository;
import br.com.fjsistemas.repository.ProdutoRepository;
import br.com.fjsistemas.service.VendaService;

@Route(value = "venda-view", layout = MainView.class)
@PageTitle("Lançamento de Vendas")
public class VendaView extends VerticalLayout {

	private static final long serialVersionUID = 1L;

	private HorizontalLayout hltVenda = new HorizontalLayout();
	Grid<Venda> grdVenda = new Grid<>(Venda.class, false);

	private HorizontalLayout hltBarraBotoes = new HorizontalLayout();
	Button btnNovo = new Button("Novo");
	Button btnAlterar = new Button("Alterar");
	Button btnExcluir = new Button("Excluir");

	private Dialog dlgJanela = new Dialog();

	Div superior = new Div();
	Div centro = new Div();
	Div inferior = new Div();

	HorizontalLayout primeiraLinhaDivSuperior = new HorizontalLayout();
	HorizontalLayout segundaLinhaDivSuperior = new HorizontalLayout();
	HorizontalLayout adicionarProdutos = new HorizontalLayout();

	double somaValores;

	@PropertyId("dataVenda")
	private DatePicker txtDataVenda = new DatePicker("Data Venda");

	@PropertyId("cliente")
	private ComboBox<Cliente> txtNomeCliente = new ComboBox<>("Cliente");

	@PropertyId("telefone")
	private TextField txtTelefone = new TextField("Telefone");

	@PropertyId("celular")
	private TextField txtCelular = new TextField("Celular");

	@PropertyId("endereco")
	private TextField txtEndereco = new TextField("Endereço");

	@PropertyId("numero")
	private TextField txtNumero = new TextField("Nº");

	@PropertyId("bairro")
	private TextField txtBairro = new TextField("Bairro");

	@PropertyId("cidade")
	TextField txtCidade = new TextField("Cidade");

	@PropertyId("estado")
	TextField txtEstado = new TextField("Estado");

	@PropertyId("formaDePagamento")
	private ComboBox<FormaDePagamento> txtFormasPagamento = new ComboBox<>("Formas de Pagamento");

	@PropertyId("valorTotalVenda")
	private TextField campoSomaValores = new TextField();

	private HorizontalLayout htlDlgBarraBotoes = new HorizontalLayout();
	private Button btnSalvar = new Button("Salvar");
	private Button btnFechar = new Button("Fechar");
	private Button btnAdicionarItem = new Button("+ Item");

	@Autowired
	VendaService vendaService;

	@Autowired
	ClienteRepository clienteRepository;

	@Autowired
	FormaDePagamentoRepository formaDePagamentoRepository;

	@Autowired
	ProdutoRepository produtoRepository;

	private List<Venda> listaVendas;
	private List<TextField> valores = new ArrayList<>();
	private Venda venda;

	Binder<Venda> binderVenda = new Binder<>(Venda.class);

	public VendaView() {

	}

	@PostConstruct
	public void init() {
		configuraTela();

	}

	private void configuraTela() {

		setMargin(false);
		setPadding(false);

		configuraHltVenda();
		configuraFltBarraBotoes();
		configuraDlgJanela();
		populaGrdVenda();
		configuraBinder();

		add(hltVenda, hltBarraBotoes);
	}

	private void configuraFltBarraBotoes() {

		btnNovo.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
		btnNovo.addClickListener(e -> {
			novoClick();
		});

		btnAlterar.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
		btnAlterar.addClickListener(e -> {
			alterarClick();
		});

		btnExcluir.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
		btnExcluir.addClickListener(e -> {
			excluirClick();
		});

		hltBarraBotoes.add(btnNovo, btnAlterar, btnExcluir);
	}

	private void excluirClick() {

		if (venda != null) {
			listaVendas.remove(venda);
			vendaService.delete(venda);
			atualizaGrdVenda();
		}
	}

	private void configuraHltVenda() {
		hltVenda.setWidthFull();
		configuraGrdVenda();
		hltVenda.add(grdVenda);
	}

	private void configuraGrdVenda() {
		grdVenda.setHeight("820px");
		grdVenda.setWidthFull();

		grdVenda.addColumn(Venda::getId).setHeader("ID:").setAutoWidth(true);

		grdVenda.addColumn(new LocalDateRenderer<>(Venda::getDataVenda, DateTimeFormatter.ofPattern("dd/MM/yyy")))
				.setHeader("Data Venda").setAutoWidth(true);

		grdVenda.addColumn(venda -> venda.getCliente().getNome()).setHeader("Nome:").setAutoWidth(true)
				.setKey("cliente.nome");

		grdVenda.addColumn(Venda::getValorTotalVenda).setHeader("Valor Total:").setAutoWidth(true)
				.setKey("valorTotalVenda");

		grdVenda.addColumn(venda -> venda.getFormaDePagamento().getFormaDePagamento()).setHeader("Forma de Pagamento").setAutoWidth(true).setKey("formaDePagamento");
				
		grdVenda.addThemeVariants(GridVariant.LUMO_COMPACT, GridVariant.LUMO_COLUMN_BORDERS);

		grdVenda.getColumns().forEach(col -> col.setAutoWidth(true).setSortable(true).setResizable(true));

		grdVenda.addItemClickListener(e -> {
			venda = e.getItem();
		});

		grdVenda.addItemDoubleClickListener(event -> {
			if (venda != null) {
				binderVenda.readBean(venda);
				dlgJanela.open();

			}
		});

	}

	private void configuraDlgJanela() {

		dlgJanela.setHeightFull();
		dlgJanela.setWidthFull();
		dlgJanela.setCloseOnEsc(false);
		dlgJanela.setCloseOnOutsideClick(false);

		superior.setHeight("170px");
		superior.setWidthFull();

		txtNomeCliente.setWidth("350px");
		txtNomeCliente.setLabel("Nome Cliente");

		txtNomeCliente.setItemLabelGenerator(cliente -> {
			if (cliente == null || cliente.getNome() == null) {
				return " ";

			} else {
				return cliente.getNome();
			}
		});

		List<Cliente> listaDeClientes = clienteRepository.findAll();

		txtNomeCliente.setItems(listaDeClientes);
		txtNomeCliente.addValueChangeListener(event -> {
			if (event.getValue() == null || event.getValue().getFone() == null) {
				txtTelefone.setValue(" ");
			} else {
				txtTelefone.setValue(event.getValue().getFone());
			}
			if (event.getValue() == null || event.getValue().getCelular() == null) {
				txtCelular.setValue(" ");
			} else {
				txtCelular.setValue(event.getValue().getCelular());
			}
			if (event.getValue() == null || event.getValue().getEndereco() == null) {
				txtEndereco.setValue(" ");
			} else {
				txtEndereco.setValue(event.getValue().getEndereco());
			}
			if (event.getValue() == null || event.getValue().getNumero() == null) {
				txtNumero.setValue(" ");
			} else {
				txtNumero.setValue(event.getValue().getNumero());
			}
			if (event.getValue() == null || event.getValue().getBairro() == null) {
				txtBairro.setValue(" ");
			} else {
				txtBairro.setValue(event.getValue().getBairro());
			}
			if (event.getValue() == null || event.getValue().getCidade() == null) {
				txtCidade.setValue(" ");
			} else {
				txtCidade.setValue(event.getValue().getCidade());
			}
			if (event.getValue() == null || event.getValue().getEstado() == null) {
				txtEstado.setValue(" ");
			} else {
				txtEstado.setValue(event.getValue().getEstado());
			}

		});

		new CustomStringBlockFormatter.Builder().blocks(0, 2, 4, 4).delimiters("(", ")", "-").numeric().build()
				.extend(txtTelefone);

		new CustomStringBlockFormatter.Builder().blocks(0, 2, 5, 4).delimiters("(", ")", "-").numeric().build()
				.extend(txtCelular);

		primeiraLinhaDivSuperior.add(txtDataVenda, txtNomeCliente, txtTelefone, txtCelular, txtEndereco, txtNumero,
				txtBairro, txtCidade);

		txtNumero.setWidth("140px");

		txtFormasPagamento.setLabel("Formas de Pagamento");

		List<FormaDePagamento> listaPagamento = formaDePagamentoRepository.findAll();
		txtFormasPagamento.setItemLabelGenerator(FormaDePagamento::getFormaDePagamento);
		txtFormasPagamento.setItems(listaPagamento);

		segundaLinhaDivSuperior.add(txtEstado, txtFormasPagamento);
		superior.add(primeiraLinhaDivSuperior, segundaLinhaDivSuperior);

		centro.setHeight("660px");
		centro.getStyle().set("border-style", "ridge");
		centro.getStyle().set("overflow-y", "scroll");
		centro.setWidthFull();

		btnSalvar.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
		btnSalvar.getStyle().set("margin-top", "0em");
		btnSalvar.getStyle().set("margin-left", "1em");
		btnSalvar.addClickListener(e -> {
			salvarClick();

		});

		btnFechar.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
		btnFechar.getStyle().set("margin-top", "0em");
		btnFechar.addClickListener(e -> {
			dlgJanela.close();
			limparCampos();
		});

		btnAdicionarItem.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
		btnAdicionarItem.getStyle().set("margin-top", "0em");
		btnAdicionarItem.addClickListener(e -> {
			adicionaProduto();
		});

		Label text = new Label("Valor Total");
		text.getElement().getStyle().set("fontWeight", "bold");
		text.getStyle().set("margin-top", "0.8em");
		text.getStyle().set("margin-left", "2em");
		text.getStyle().set("text-align", "center");
		campoSomaValores.getStyle().set("margin-top", "0em");
		campoSomaValores.getStyle().set("margin-right", "0.2em");
		campoSomaValores.setWidth("30em");

		htlDlgBarraBotoes.add(btnSalvar, btnFechar, btnAdicionarItem, text, campoSomaValores);

		inferior.getStyle().set("margin-top", "0px");
		inferior.setHeight("45px");
		inferior.setWidthFull();
		inferior.add(htlDlgBarraBotoes);

		dlgJanela.add(superior, centro, inferior);

	}

	private void salvarClick() {

		venda = binderVenda.getBean();

		boolean adicionarLista = venda.getId() == null ? true : false;

		vendaService.create(venda);

		if (adicionarLista) {
			listaVendas.add(venda);

		}
		atualizaGrdVenda();
		novaVenda();
		txtNomeCliente.focus();

		binderVenda.setBean(venda);

		if (adicionarLista) {
			
			dlgJanela.close();
		}
	}

	private void populaGrdVenda() {

		listaVendas = vendaService.read();
		atualizaGrdVenda();
	}

	private void atualizaGrdVenda() {
		grdVenda.setItems(listaVendas);
	}

	private void configuraBinder() {

		binderVenda.bindInstanceFields(this);

	}

	private void novoClick() {

		novaVenda();
		binderVenda.setBean(venda);

		dlgJanela.open();
		txtNomeCliente.focus();
	}

	private void alterarClick() {

		if (venda != null) {
			binderVenda.setBean(venda);

			dlgJanela.open();

		}
	}

	private void adicionaProduto() {

		ComboBox<Produto> txtProdutos = new ComboBox<>();

		NumberField txtQuantidade = new NumberField("Quantidade");

		TextField txtValorUnitario = new TextField("Valor Unitário");

		TextField txtValorTotalItem = new TextField("Valor Total Item");

		txtProdutos.setWidth("370px");
		txtProdutos.setLabel("Produtos");
		List<Produto> listaDeProdutos = produtoRepository.findAll();
		txtProdutos.setItemLabelGenerator(Produto::getNome);
		txtProdutos.setItems(listaDeProdutos);
		txtProdutos.addValueChangeListener(event -> {

			NumberFormat formatter = NumberFormat.getCurrencyInstance(new Locale("pt", "BR"));
			try {

				txtValorUnitario.setValue(formatter.format(event.getValue().getValor()));

			} catch (Exception e) {
				e.printStackTrace();
			}

		});

//==========================================================================================================================

		txtQuantidade.setHasControls(true);
		txtQuantidade.setValue(null);
		txtQuantidade.setMin(1);

		txtQuantidade.addValueChangeListener(event -> {

			NumberFormat formatter = NumberFormat.getCurrencyInstance(new Locale("pt", "BR"));
			double valorTotal = 0;

			try {
				valorTotal = formatter.parse(txtValorUnitario.getValue()).doubleValue() * txtQuantidade.getValue();
			} catch (ParseException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

			txtValorTotalItem.setValue(formatter.format(valorTotal));

			double soma = 0;
			for (TextField tf : valores) {
				try {
					soma += formatter.parse(tf.getValue()).doubleValue();

				} catch (ParseException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}

			}

			campoSomaValores.setValue(formatter.format(soma));

		});

		adicionarProdutos = new HorizontalLayout();
		adicionarProdutos.add(txtProdutos, txtQuantidade, txtValorUnitario, txtValorTotalItem);
		
		venda.addProduto(txtProdutos.getValue());

		centro.add(adicionarProdutos);
		valores.add(txtValorTotalItem);
	}

	private void limparCampos() {
		centro.removeAll();
	}

	private void novaVenda() {
		venda = new Venda();
		venda.setCliente(null);
		venda.setFormaDePagamento(null);
		dlgJanela.close();

	}
}
R

Venda Completa:

package br.com.fjsistemas.backend;

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@AllArgsConstructor
@NoArgsConstructor
@Data
@Entity
public class Venda {

	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	private Long id;

	private LocalDate dataVenda = LocalDate.now();

	@ManyToOne
	private Cliente cliente;

	@ManyToOne
	private FormaDePagamento formaDePagamento;
	
	@ManyToOne										
	private ProdutoVendido produtoVendido;

	@OneToMany(cascade = CascadeType.PERSIST)
	private List<ProdutoVendido> produtos = new ArrayList<>();

	public void addProduto(Produto produto) {
		ProdutoVendido produtoVenda = new ProdutoVendido();
		produtos.add(produtoVenda);
	}

	private String valorTotalVenda;

}
R

ProdutoVendido COmpleto

package br.com.fjsistemas.backend;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@AllArgsConstructor
@NoArgsConstructor
@Data
@Entity
public class ProdutoVendido {
	
	

	public ProdutoVendido(Venda venda, Produto produto) {
		super();
		this.venda = venda;
		this.produto = produto;
	}
	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	private Long id;
	
	@ManyToOne
	private Venda venda;
	
	@ManyToOne
	private Produto produto;

}
L

Ao alterar uma venda, vc deve ler a lista de produtos e montar a view:

private void alterarClick() {
	if (venda != null) {
		binderVenda.setBean(venda);
		montarListaProdutos(venda.getProdutosVendidos());
		
		dlgJanela.open();
	}
}

E no método montarListaProdutos, vc pega os produtos e monta a view com as informações do produto.

R

@Lucas_Camara

a declaração do metodo está correta?

private void montarListaProdutos(ProdutoVendido produtoVendido) {
		
		
	}
L

Não, pois como uma venda pode ter vários produtos vendidos (lembre-se que uma venda possui uma lista de produtos vendidos), esse método deve receber uma lista de produtosVendidos, para poder montar a tela corretamente.

R

@Lucas_Camara

tentei isso, mas não deu certo…não sei como fazer

private void montarListaProdutos(ProdutoVendido produtoVendido) {
		produtoVendido = (ProdutoVendido) venda.getProdutos();
		
	}
L

Tenta assim:

private void montarListaProdutos(List<ProdutoVendido> produtosVendidos) {
	for (ProdutoVendido pv : produtosVendidos) {
		Produto produto = pv.getProduto();
		// vai montando a lista de produtos na tela com as informações do produto
	}
}
R

@Lucas_Camara

Veja o que acontece

L

Uai, mas a venda não possui apenas um produto vendido. Uma venda pode ter mais de um produto vendido, certo?

Na classe venda, se vc tiver alguma propriedade ProdutoVendido, remova ele, e deixe apenas a lista List<ProdutoVendido> produtosVendidos.

R

@Lucas_Camara

Sim uma venda pode ter vários produtos vendidos

package br.com.fjsistemas.backend;

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@AllArgsConstructor
@NoArgsConstructor
@Data
@Entity
public class Venda {

	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	private Long id;

	private LocalDate dataVenda = LocalDate.now();

	@ManyToOne
	private Cliente cliente;

	@ManyToOne
	private FormaDePagamento formaDePagamento;
	
	//@ManyToOne										
	//private ProdutoVendido produtoVendido;  REMOVIDO

	@OneToMany(cascade = CascadeType.PERSIST)
	private List<ProdutoVendido> produtos = new ArrayList<>();

	public void addProduto(Produto produto) {
		ProdutoVendido produtoVenda = new ProdutoVendido();
		produtos.add(produtoVenda);
	}

	private String valorTotalVenda;

}

Agora está certo a classe Venda?

L
public void addProduto(Produto produto) { 
	ProdutoVendido produtoVenda = new ProdutoVendido(); 
	produtos.add(produtoVenda); 
}

Essa parte ainda está errada. Você esta ignorando o parâmetro produto.

O objetivo do método addProduto, é vincular o produto à venda. E isso é feito pela classe ProdutoVendido. Ou seja, vc deve criar um produto vendido a partir do cliente e a venda, e depois adicionar na lista. Assim:

public void addProduto(Produto produto) { 
	ProdutoVendido produtoVenda = new ProdutoVendido(this, produto); // repare que aqui é chamado um construtor que recebe a venda e o produto
	produtos.add(produtoVenda); 
}

E na classe ProdutoVendido

public class ProdutoVendido {

	private Venda venda;
	private Produto produto;
	
	// Aqui é o construtor que irá criar o produto vendido a partir da venda e do produto
	// essa classe é responsável por vincular o produto à venda
	public ProdutoVendido(Venda venda, Produto produto) {
		this.venda = venda;
		this.produto = produto;
	}

	// getters and setters
}

obs: Na classe ProdutoVendido não coloquei as anotações do mapeamento, mas vc deve colocar para ficar correto.

R

@Lucas_Camara

Correto agora?

Classe Venda:

package br.com.fjsistemas.backend;

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@AllArgsConstructor
@NoArgsConstructor
@Data
@Entity
public class Venda {

	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	private Long id;

	private LocalDate dataVenda = LocalDate.now();

	@ManyToOne
	private Cliente cliente;

	@ManyToOne
	private FormaDePagamento formaDePagamento;

	/*
	 * @ManyToOne private ProdutoVendido produtoVendido; //REMOVIDO
	 */

	@OneToMany(cascade = CascadeType.PERSIST)
	private List<ProdutoVendido> produtos = new ArrayList<>();

	public void addProduto(Produto produto) {
		ProdutoVendido produtoVenda = new ProdutoVendido(this, produto);																			
		produtos.add(produtoVenda);
	}

	private String valorTotalVenda;

}
R

@Lucas_Camara

Classe ProdutoVendido

package br.com.fjsistemas.backend;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@AllArgsConstructor
@NoArgsConstructor
@Data
@Entity
public class ProdutoVendido {

	public ProdutoVendido(Venda venda, Produto produto) {
		this.venda = venda;
		this.produto = produto;
	}

	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	private Long id;

	@ManyToOne
	private Venda venda;

	@ManyToOne
	private Produto produto;

}
R

@Lucas_Camara

Deixei assim as classes:

Classe Venda:

package br.com.fjsistemas.backend;

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
@Data
@Entity
public class Venda {

	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	private Long id;

	private LocalDate dataVenda = LocalDate.now();

	@ManyToOne
	private Cliente cliente;

	@ManyToOne
	private FormaDePagamento formaDePagamento;

	@OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.PERSIST)
	private List<ProdutoVendido> produtos = new ArrayList<>();

	public void addProduto(Produto produto) {
		ProdutoVendido produtoVenda = new ProdutoVendido(this, produto);																			
		produtos.add(produtoVenda);
	}

	private String valorTotalVenda;

}

Classe ProdutoVendido:

package br.com.fjsistemas.backend;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
@Data
@Entity
public class ProdutoVendido {

	public ProdutoVendido(Venda venda, Produto produto) {
		this.venda = venda;
		this.produto = produto;
	}

	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	private Long id;

	@ManyToOne
	private Venda venda;

	@ManyToOne
	private Produto produto;

}

Classe VendaView(apenas o metodo adicionaProduto, metodo Alterar e montarListaProdutos)

private void alterarClick() {
		if (venda != null) {
			binderVenda.setBean(venda);
			montarListaProdutos(venda.getProdutos());

			dlgJanela.open();
		}
	}

	private void montarListaProdutos(List<ProdutoVendido> produtos) {
		for (ProdutoVendido pv : produtos) {
			Produto produto = pv.getProduto();
			venda.addProduto(produto);
		}
	}

	private void adicionaProduto() {

		ComboBox<Produto> txtProdutos = new ComboBox<>();

		NumberField txtQuantidade = new NumberField("Quantidade");

		TextField txtValorUnitario = new TextField("Valor Unitário");

		TextField txtValorTotalItem = new TextField("Valor Total Item");

		txtProdutos.setWidth("370px");
		txtProdutos.setLabel("Produtos");
		List<Produto> listaDeProdutos = produtoRepository.findAll();
		txtProdutos.setItemLabelGenerator(Produto::getNome);
		txtProdutos.setItems(listaDeProdutos);
		txtProdutos.addValueChangeListener(event -> {

			NumberFormat formatter = NumberFormat.getCurrencyInstance(new Locale("pt", "BR"));
			try {

				txtValorUnitario.setValue(formatter.format(event.getValue().getValor()));

			} catch (Exception e) {
				e.printStackTrace();
			}

		});

//==========================================================================================================================

		txtQuantidade.setHasControls(true);
		txtQuantidade.setValue(null);
		txtQuantidade.setMin(1);

		txtQuantidade.addValueChangeListener(event -> {

			NumberFormat formatter = NumberFormat.getCurrencyInstance(new Locale("pt", "BR"));
			double valorTotal = 0;

			try {
				valorTotal = formatter.parse(txtValorUnitario.getValue()).doubleValue() * txtQuantidade.getValue();
			} catch (ParseException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

			txtValorTotalItem.setValue(formatter.format(valorTotal));

			double soma = 0;
			for (TextField tf : valores) {
				try {
					soma += formatter.parse(tf.getValue()).doubleValue();

				} catch (ParseException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}

			}

			campoSomaValores.setValue(formatter.format(soma));

		});

feito desta forma, fui tentar rodar a aplicação para ver se dava certo, mas da este stack

java.util.ConcurrentModificationException: null
	at java.base/java.util.ArrayList$Itr.checkForComodification(ArrayList.java:1009) ~[na:na]
	at java.base/java.util.ArrayList$Itr.next(ArrayList.java:963) ~[na:na]
	at org.hibernate.collection.internal.AbstractPersistentCollection$IteratorProxy.next(AbstractPersistentCollection.java:883) ~[hibernate-core-5.4.27.Final.jar:5.4.27.Final]
	at br.com.fjsistemas.compraVendaView.VendaView.montarListaProdutos(VendaView.java:412) ~[classes/:na]
	at br.com.fjsistemas.compraVendaView.VendaView.alterarClick(VendaView.java:405) ~[classes/:na]
	at br.com.fjsistemas.compraVendaView.VendaView.lambda$1(VendaView.java:160) ~[classes/:na]
	at com.vaadin.flow.component.ComponentEventBus.fireEventForListener(ComponentEventBus.java:205) ~[flow-server-2.4.6.jar:2.4.6]
	at com.vaadin.flow.component.ComponentEventBus.handleDomEvent(ComponentEventBus.java:373) ~[flow-server-2.4.6.jar:2.4.6]
	at com.vaadin.flow.component.ComponentEventBus.lambda$addDomTrigger$dd1b7957$1(ComponentEventBus.java:264) ~[flow-server-2.4.6.jar:2.4.6]
	at com.vaadin.flow.internal.nodefeature.ElementListenerMap.lambda$fireEvent$2(ElementListenerMap.java:441) ~[flow-server-2.4.6.jar:2.4.6]
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1507) ~[na:na]
	at com.vaadin.flow.internal.nodefeature.ElementListenerMap.fireEvent(ElementListenerMap.java:441) ~[flow-server-2.4.6.jar:2.4.6]
	at com.vaadin.flow.server.communication.rpc.EventRpcHandler.handleNode(EventRpcHandler.java:59) ~[flow-server-2.4.6.jar:2.4.6]
	at com.vaadin.flow.server.communication.rpc.AbstractRpcInvocationHandler.handle(AbstractRpcInvocationHandler.java:64) ~[flow-server-2.4.6.jar:2.4.6]
	at com.vaadin.flow.server.communication.ServerRpcHandler.handleInvocationData(ServerRpcHandler.java:409) ~[flow-server-2.4.6.jar:2.4.6]
	at com.vaadin.flow.server.communication.ServerRpcHandler.lambda$handleInvocations$1(ServerRpcHandler.java:390) ~[flow-server-2.4.6.jar:2.4.6]
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1507) ~[na:na]
	at com.vaadin.flow.server.communication.ServerRpcHandler.handleInvocations(ServerRpcHandler.java:390) ~[flow-server-2.4.6.jar:2.4.6]
	at com.vaadin.flow.server.communication.ServerRpcHandler.handleRpc(ServerRpcHandler.java:317) ~[flow-server-2.4.6.jar:2.4.6]
	at com.vaadin.flow.server.communication.UidlRequestHandler.synchronizedHandleRequest(UidlRequestHandler.java:89) ~[flow-server-2.4.6.jar:2.4.6]
	at com.vaadin.flow.server.SynchronizedRequestHandler.handleRequest(SynchronizedRequestHandler.java:40) ~[flow-server-2.4.6.jar:2.4.6]
	at com.vaadin.flow.server.VaadinService.handleRequest(VaadinService.java:1547) ~[flow-server-2.4.6.jar:2.4.6]
	at com.vaadin.flow.server.VaadinServlet.service(VaadinServlet.java:247) ~[flow-server-2.4.6.jar:2.4.6]
	at com.vaadin.flow.spring.SpringServlet.service(SpringServlet.java:111) ~[vaadin-spring-12.3.2.jar:na]
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:733) ~[tomcat-embed-core-9.0.41.jar:4.0.FR]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:712) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:459) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:352) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:312) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.springframework.web.servlet.mvc.ServletForwardingController.handleRequestInternal(ServletForwardingController.java:141) ~[spring-webmvc-5.3.3.jar:5.3.3]
	at org.springframework.web.servlet.mvc.AbstractController.handleRequest(AbstractController.java:177) ~[spring-webmvc-5.3.3.jar:5.3.3]
	at org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.java:52) ~[spring-webmvc-5.3.3.jar:5.3.3]
	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1060) ~[spring-webmvc-5.3.3.jar:5.3.3]
	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:962) ~[spring-webmvc-5.3.3.jar:5.3.3]
	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) ~[spring-webmvc-5.3.3.jar:5.3.3]
	at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909) ~[spring-webmvc-5.3.3.jar:5.3.3]
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:652) ~[tomcat-embed-core-9.0.41.jar:4.0.FR]
	at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) ~[spring-webmvc-5.3.3.jar:5.3.3]
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:733) ~[tomcat-embed-core-9.0.41.jar:4.0.FR]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) ~[tomcat-embed-websocket-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-5.3.3.jar:5.3.3]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.3.jar:5.3.3]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-5.3.3.jar:5.3.3]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.3.jar:5.3.3]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-5.3.3.jar:5.3.3]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.3.jar:5.3.3]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:542) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:143) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:374) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:888) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1597) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) ~[na:na]
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) ~[na:na]
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at java.base/java.lang.Thread.run(Thread.java:830) ~[na:na]
L

Essa parte está errada ainda:

private void montarListaProdutos(List<ProdutoVendido> produtos) {
		for (ProdutoVendido pv : produtos) {
			Produto produto = pv.getProduto();
			venda.addProduto(produto);
		}
	}

Vc está recebendo a lista de produtos da venda e adicionando na venda novamente.

Nessa parte vc deveria montar a view dos produtos vinculados à venda. Que imagino que seja aqui:

txtProdutos.setItems(produtos);

Se vc estiver usando java versão 8 ou superior, tu pode fazer o método para ficar assim:

private void montarListaProdutos(List<ProdutoVendido> produtosVendidos) {
	List<Produto> produtos = produtosVendidos.stream()
		.map(pv -> pv.getProduto())
		.collect(Collectors.toList());
		
	txtProdutos.setItems(produtos);
}
R

@Lucas_Camara

Acontece que essa variavel txtProdutos, é uma variavel declarada dentro do metodo adicionaProduto(linha 422)

tentei declarar ela fora, la no começo do código, porém ao declarar ela fora, não consigo adicionar 2 ou mais produtos na venda…consigo add apenas 1 produto por venda

L

Ah, essa txtProduto é a combobox, entendi. Vacilo meu.

Qual o elemento que apresenta os produtos da venda? É uma tabela?

R

@Lucas_Camara

os produtos para venda são listados nesta comboBox, nesta combo estão todos os produtos disponíveis para venda

L

O que tava querendo dizer é algo assim:

private void montarListaProdutos(List<ProdutoVendido> produtosVendidos) {
	HorizontalLayout adicionarProdutos = new HorizontalLayout();
	
	for (ProdutoVendido pv : produtosVendidos) {
		Produto p = pv.getProduto();
		adicionarProdutos.add(p.getDescricao(), pv.getQuantidade(), p.getValorUnitario(), p.getValorTotalItem());
	}
	
	centro.add(adicionarProdutos);
}

A partir dos produtos vendidos vinculados à venda, vc vai motar o layout que irá apresentar os dados desses produtos.

obs.: Tem que corrigir os parâmetros do método add

obs2: E esse nome adicionarProdutos não seria menos confuso se fosse layoutProdutosVenda (ou algo semelhante)?

L

Ah sim. Esses códigos usando os elementos do Vaadin que to colocando, é mais como forma de passar a ideia do que fazer, mas eu não sei como fazer pois nunca usei esse Vaadin, blz.

Com isso, para pegar cada produto e colocar na tela usando os componentes do Vaadin, tu tem que usar o elemento de acordo com o que tu jah conhece desse framework.

R

@Lucas_Camara

blz, vou ver se consigo deixar td certinho…muito obg por tudo!!! Foi de grande ajuda!!!

R

@Lucas_Camara

acho que estou chegando perto, veja o que acontece aqui:

Classe Venda:

package br.com.fjsistemas.backend;

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
@Data
@Entity
public class Venda {

	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	private Long id;

	private LocalDate dataVenda = LocalDate.now();

	@ManyToOne
	private Cliente cliente;

	@ManyToOne
	private FormaDePagamento formaDePagamento;

	@OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.PERSIST)
	private List<ProdutoVendido> produtos = new ArrayList<>();

	public void addProduto(Produto produto) {
		ProdutoVendido produtoVenda = new ProdutoVendido(id, this, produto, 0, null, null);																			
		produtos.add(produtoVenda);
	}

	private String valorTotalVenda;

}

Classe ProdutoVendido:

package br.com.fjsistemas.backend;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

@AllArgsConstructor
@NoArgsConstructor
@Data
@Getter
@Setter
@Entity
public class ProdutoVendido {

	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	private Long id;
	
	@ManyToOne
	private Venda venda;
	
	@ManyToOne
	private Produto produto;
	
	private int quantidade;
	private Double valorUnitario;
	private Double valorTotalItem;
}

Classe VendaView(apenas metodo montarLista):

private void montarListaProdutos(List<ProdutoVendido> produtosVendidos) {
		HorizontalLayout adicionarProdutos = new HorizontalLayout();
		
		for (ProdutoVendido pv : produtosVendidos) {
			Produto p = pv.getProduto();
			adicionarProdutos.add(pv.getProduto(), pv.getQuantidade(), pv.getValorUnitario(), pv.getValorTotalItem());
		}
		
		centro.add(adicionarProdutos);
	}

Imagem do metodo montarListaProdutos:

Como resolver este erro:?

L

Está no caminho. Esse método add, imagino que seja para adicionar algum elemento de tela, como um textfield, por exemplo.

Se vc for adicionar a descrição do produto, imagino que vc tenha que adicionar um textfield com a descricao do produto como valor.

No seu caso, vc terá que criar elementos de tela para dada informação que deverá aparecer nesse HorizontalLayout.

R

@Lucas_Camara

Isso, o metodo add, irá adicionar as informações (nome do produto, quantidade vendida, valor unitário e valor total do item) dentro de uma Div(centro), que será exibida quando o usuario quiser visualizar ou alterar uma venda.

Se eu entendi corretamente, o certo agora é um declarar um TextField lá no começo do código e depois setar o valor nesta nova textfield…é isso?

L

tu não pode declarar no comeco do codigo, pq podem ser vários produtos. Se tu usar o mesmo textfield qdo for mais de um produto, o valor de um produto pode sobrescrever o outro.

Pensa assim: Se tu for apresentar 2 produtos nesse HorizontalLayout, onde para cada produto, serão apresentados 4 dados, vc terá 8 elementos na tela para isso.

Essas informações da tela serão apenas para apresentar os dados, ou o usuário poderá editar também?

R

@Lucas_Camara

Apenas para apresentar…sem alterar nada

L

Bão, fica mais fácil. Basta ir adicionando os textfields dentro do loop mesmo.

Algo mais ou menos assim:

for (ProdutoVendido pv : produtosVendidos) {
    layoutProdutos.add(new Textfield(pv.getProduto().getDescricao());
}

obs.: Nao sei como se cria textfield no vaadin

R

@Lucas_Camara

ficou assim:

private void montarListaProdutos(List<ProdutoVendido> produtosVendidos) {
		HorizontalLayout adicionarProdutos = new HorizontalLayout();
		
				
		for (ProdutoVendido pv : produtosVendidos) {
			adicionarProdutos.add(new TextField(pv.getProduto().getNome()));
		}
		
		centro.add(adicionarProdutos);
	}

não há erros de compilação ou execução, mas os produtos continuam sem salvar / exibir

Tela Após Venda Realizada


L

Ah, não está nem salvando os produtos na venda? Como está o método que salva a venda?

R

@Lucas_Camara

private void salvarClick() {

		venda = binderVenda.getBean();

		boolean adicionarLista = venda.getId() == null ? true : false;

		vendaService.create(venda);

		if (adicionarLista) {
			listaVendas.add(venda);

		}
		atualizaGrdVenda();
		novaVenda();
		txtNomeCliente.focus();

		binderVenda.setBean(venda);

		if (adicionarLista) {

			dlgJanela.close();
		}
	}
L

Quando vc debuga o codigo, nessa linha:

venda = binderVenda.getBean();

A venda vem com a lista de produtos vendidos preenchida?

L

E o que esse método faz?

vendaService.create(venda);
R

R

cria a venda

L

No print não está sendo apresentado os valores que tem na venda.

R

@Lucas_Camara
eu vou baixar o eclipse novamente, acho que ele está zuado…

L

não precisa. tu tem que fazer a view aparecer. Acho que no menu window > show view. Dai deve ter variable (ou algo assim)

Veja:

image

R

@Lucas_Camara
meu eclipse simplesmente nao debuga

R

@Lucas_Camara

consegui debugar, mas nao mostra nada

R

@Lucas_Camara

agora foi

L

Agora tu tem que ir “andando” o debug (acho que é a tecla F6) até que a variável venda seja preenchida, para que vc consiga ver, no painel variables, com quais valores estão suas propriedades.

R

@Lucas_Camara

em nenhum momento apareceu a variavel venda, dei varios F6 devagar, fui olhada e nada…

L

Ah sim, como ela está declarada como atributo de classe, ela vai está dentro do this (esse this se refere à classe em que o breakpoint está) lah no painel variables.

R

@Lucas_Camara

L

E a propriedade produtos tem quantos elementos? Se tiver algum produto, mostra tb as propriedades dele.

R

@Lucas_Camara

a unica propriedade produtos que tem, está dentro de venda, porem dentro de produto não há nada

L

Deve ser por isso que os produtos não estão sendo persistidos. A lista de produtos da venda está vazia. Qdo vc adiciona o produto na venda, vc usou aquele método que adiciona o produto (addProduto)?

R

@Lucas_Camara

não sei se entendi direito sua pergunta mas vou responder assim:

dentro da minha Venda View(tela de vendas) tem o metodo que adicionaProduto

private void adicionaProduto() {

		ComboBox<Produto> txtProdutos = new ComboBox<>();

		NumberField txtQuantidade = new NumberField("Quantidade");

		TextField txtValorUnitario = new TextField("Valor Unitário");

		TextField txtValorTotalItem = new TextField("Valor Total Item");

		txtProdutos.setWidth("370px");
		txtProdutos.setLabel("Produtos");
		List<Produto> listaDeProdutos = produtoRepository.findAll();
		txtProdutos.setItemLabelGenerator(Produto::getNome);
		txtProdutos.setItems(listaDeProdutos);
		txtProdutos.addValueChangeListener(event -> {

			NumberFormat formatter = NumberFormat.getCurrencyInstance(new Locale("pt", "BR"));
			try {

				txtValorUnitario.setValue(formatter.format(event.getValue().getValor()));

			} catch (Exception e) {
				e.printStackTrace();
			}

		});

//==========================================================================================================================

		txtQuantidade.setHasControls(true);
		txtQuantidade.setValue(null);
		txtQuantidade.setMin(1);

		txtQuantidade.addValueChangeListener(event -> {

			NumberFormat formatter = NumberFormat.getCurrencyInstance(new Locale("pt", "BR"));
			double valorTotal = 0;

			try {
				valorTotal = formatter.parse(txtValorUnitario.getValue()).doubleValue() * txtQuantidade.getValue();
			} catch (ParseException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

			txtValorTotalItem.setValue(formatter.format(valorTotal));

			double soma = 0;// interna
			for (TextField tf : valores) {
				try {
					soma += formatter.parse(tf.getValue()).doubleValue();

				} catch (ParseException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}

			}

			campoSomaValores.setValue(formatter.format(soma));// externa

		});

		adicionarProdutos = new HorizontalLayout();
		adicionarProdutos.add(txtProdutos, txtQuantidade, txtValorUnitario, txtValorTotalItem);

		centro.add(adicionarProdutos);
		valores.add(txtValorTotalItem);
	}

logo na sequencia, ainda em VendaView tenho o metodo montarListaProdutos

private void montarListaProdutos(List<ProdutoVendido> produtosVendidos) {
			HorizontalLayout adicionarProdutos = new HorizontalLayout();
			
					
			for (ProdutoVendido pv : produtosVendidos) {
				adicionarProdutos.add(new TextField(pv.getProduto().getNome()));
			}
			
			centro.add(adicionarProdutos);
		}

Na entidade Venda

package br.com.fjsistemas.backend;

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;

@Entity
public class Venda {

	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	private Long id;

	private LocalDate dataVenda = LocalDate.now();

	@ManyToOne
	private Cliente cliente;

	@ManyToOne
	private FormaDePagamento formaDePagamento;

	@OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.PERSIST)
	private List<ProdutoVendido> produtos = new ArrayList<>();

	private String valorTotalVenda;

	public Venda() {

	}

	public Venda(Long id, LocalDate dataVenda, Cliente cliente, FormaDePagamento formaDePagamento,
			List<ProdutoVendido> produtos, String valorTotalVenda) {

		this.id = id;
		this.dataVenda = dataVenda;
		this.cliente = cliente;
		this.formaDePagamento = formaDePagamento;
		this.produtos = produtos;
		this.valorTotalVenda = valorTotalVenda;
	}

	public Long getId() {
		return id;
	}

	public void setId(Long id) {
		this.id = id;
	}

	public LocalDate getDataVenda() {
		return dataVenda;
	}

	public void setDataVenda(LocalDate dataVenda) {
		this.dataVenda = dataVenda;
	}

	public Cliente getCliente() {
		return cliente;
	}

	public void setCliente(Cliente cliente) {
		this.cliente = cliente;
	}

	public FormaDePagamento getFormaDePagamento() {
		return formaDePagamento;
	}

	public void setFormaDePagamento(FormaDePagamento formaDePagamento) {
		this.formaDePagamento = formaDePagamento;
	}

	public List<ProdutoVendido> getProdutos() {
		return produtos;
	}

	public void setProdutos(List<ProdutoVendido> produtos) {
		this.produtos = produtos;
	}

	public String getValorTotalVenda() {
		return valorTotalVenda;
	}

	public void setValorTotalVenda(String valorTotalVenda) {
		this.valorTotalVenda = valorTotalVenda;
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((cliente == null) ? 0 : cliente.hashCode());
		result = prime * result + ((dataVenda == null) ? 0 : dataVenda.hashCode());
		result = prime * result + ((formaDePagamento == null) ? 0 : formaDePagamento.hashCode());
		result = prime * result + ((id == null) ? 0 : id.hashCode());
		result = prime * result + ((produtos == null) ? 0 : produtos.hashCode());
		result = prime * result + ((valorTotalVenda == null) ? 0 : valorTotalVenda.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Venda other = (Venda) obj;
		if (cliente == null) {
			if (other.cliente != null)
				return false;
		} else if (!cliente.equals(other.cliente))
			return false;
		if (dataVenda == null) {
			if (other.dataVenda != null)
				return false;
		} else if (!dataVenda.equals(other.dataVenda))
			return false;
		if (formaDePagamento == null) {
			if (other.formaDePagamento != null)
				return false;
		} else if (!formaDePagamento.equals(other.formaDePagamento))
			return false;
		if (id == null) {
			if (other.id != null)
				return false;
		} else if (!id.equals(other.id))
			return false;
		if (produtos == null) {
			if (other.produtos != null)
				return false;
		} else if (!produtos.equals(other.produtos))
			return false;
		if (valorTotalVenda == null) {
			if (other.valorTotalVenda != null)
				return false;
		} else if (!valorTotalVenda.equals(other.valorTotalVenda))
			return false;
		return true;
	}

	public void addProduto(Produto produto) {
		ProdutoVendido produtoVenda = new ProdutoVendido();
		produtos.add(produtoVenda);
	}

}
R

na entidade Venda o ultimo metodo

L

E onde vc está chamando o método addProduto?

R

@Lucas_Camara
em nenhum lugar…não sei onde chama-lo

L

vc não pode se preocupar apenas com a parte da tela. O que mais importa no sistema eh o dominio dele (que é a possibilidade de ser fazer venda de produtos). Ou seja, qdo um produto fosse adicionado na tela, vc tem, de alguma forma, recuperar esses produtos da tela e adicionar na entidade venda.

R

@Lucas_Camara

fiz assim:

private void adicionaProduto() {

		ComboBox<Produto> txtProdutos = new ComboBox<>();

		NumberField txtQuantidade = new NumberField("Quantidade");

		TextField txtValorUnitario = new TextField("Valor Unitário");

		TextField txtValorTotalItem = new TextField("Valor Total Item");

		txtProdutos.setWidth("370px");
		txtProdutos.setLabel("Produtos");
		List<Produto> listaDeProdutos = produtoRepository.findAll();
		txtProdutos.setItemLabelGenerator(Produto::getNome);
		txtProdutos.setItems(listaDeProdutos);
		txtProdutos.addValueChangeListener(event -> {

			NumberFormat formatter = NumberFormat.getCurrencyInstance(new Locale("pt", "BR"));
			try {

				txtValorUnitario.setValue(formatter.format(event.getValue().getValor()));

			} catch (Exception e) {
				e.printStackTrace();
			}

		});

//==========================================================================================================================

		txtQuantidade.setHasControls(true);
		txtQuantidade.setValue(null);
		txtQuantidade.setMin(1);

		txtQuantidade.addValueChangeListener(event -> {

			NumberFormat formatter = NumberFormat.getCurrencyInstance(new Locale("pt", "BR"));
			double valorTotal = 0;

			try {
				valorTotal = formatter.parse(txtValorUnitario.getValue()).doubleValue() * txtQuantidade.getValue();
			} catch (ParseException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

			txtValorTotalItem.setValue(formatter.format(valorTotal));

			double soma = 0;// interna
			for (TextField tf : valores) {
				try {
					soma += formatter.parse(tf.getValue()).doubleValue();

				} catch (ParseException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}

			}

			campoSomaValores.setValue(formatter.format(soma));// externa

		});

		adicionarProdutos = new HorizontalLayout();
		adicionarProdutos.add(txtProdutos, txtQuantidade, txtValorUnitario, txtValorTotalItem);
		centro.add(adicionarProdutos);
		valores.add(txtValorTotalItem);
		venda.addProduto(txtProdutos.getValue());
	}
R

mas recebo na hora de salvar:

java.lang.NullPointerException: null
	at br.com.fjsistemas.compraVenda.VendaView.montarListaProdutos(VendaView.java:485) ~[classes/:na]
	at br.com.fjsistemas.compraVenda.VendaView.lambda$10(VendaView.java:214) ~[classes/:na]
	at com.vaadin.flow.component.ComponentEventBus.fireEventForListener(ComponentEventBus.java:205) ~[flow-server-2.4.6.jar:2.4.6]
	at com.vaadin.flow.component.ComponentEventBus.handleDomEvent(ComponentEventBus.java:373) ~[flow-server-2.4.6.jar:2.4.6]
	at com.vaadin.flow.component.ComponentEventBus.lambda$addDomTrigger$dd1b7957$1(ComponentEventBus.java:264) ~[flow-server-2.4.6.jar:2.4.6]
	at com.vaadin.flow.internal.nodefeature.ElementListenerMap.lambda$fireEvent$2(ElementListenerMap.java:441) ~[flow-server-2.4.6.jar:2.4.6]
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1507) ~[na:na]
	at com.vaadin.flow.internal.nodefeature.ElementListenerMap.fireEvent(ElementListenerMap.java:441) ~[flow-server-2.4.6.jar:2.4.6]
	at com.vaadin.flow.server.communication.rpc.EventRpcHandler.handleNode(EventRpcHandler.java:59) ~[flow-server-2.4.6.jar:2.4.6]
	at com.vaadin.flow.server.communication.rpc.AbstractRpcInvocationHandler.handle(AbstractRpcInvocationHandler.java:64) ~[flow-server-2.4.6.jar:2.4.6]
	at com.vaadin.flow.server.communication.ServerRpcHandler.handleInvocationData(ServerRpcHandler.java:409) ~[flow-server-2.4.6.jar:2.4.6]
	at com.vaadin.flow.server.communication.ServerRpcHandler.lambda$handleInvocations$1(ServerRpcHandler.java:390) ~[flow-server-2.4.6.jar:2.4.6]
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1507) ~[na:na]
	at com.vaadin.flow.server.communication.ServerRpcHandler.handleInvocations(ServerRpcHandler.java:390) ~[flow-server-2.4.6.jar:2.4.6]
	at com.vaadin.flow.server.communication.ServerRpcHandler.handleRpc(ServerRpcHandler.java:317) ~[flow-server-2.4.6.jar:2.4.6]
	at com.vaadin.flow.server.communication.UidlRequestHandler.synchronizedHandleRequest(UidlRequestHandler.java:89) ~[flow-server-2.4.6.jar:2.4.6]
	at com.vaadin.flow.server.SynchronizedRequestHandler.handleRequest(SynchronizedRequestHandler.java:40) ~[flow-server-2.4.6.jar:2.4.6]
	at com.vaadin.flow.server.VaadinService.handleRequest(VaadinService.java:1547) ~[flow-server-2.4.6.jar:2.4.6]
	at com.vaadin.flow.server.VaadinServlet.service(VaadinServlet.java:247) ~[flow-server-2.4.6.jar:2.4.6]
	at com.vaadin.flow.spring.SpringServlet.service(SpringServlet.java:111) ~[vaadin-spring-12.3.2.jar:na]
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:733) ~[tomcat-embed-core-9.0.41.jar:4.0.FR]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:712) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:459) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:352) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:312) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.springframework.web.servlet.mvc.ServletForwardingController.handleRequestInternal(ServletForwardingController.java:141) ~[spring-webmvc-5.3.3.jar:5.3.3]
	at org.springframework.web.servlet.mvc.AbstractController.handleRequest(AbstractController.java:177) ~[spring-webmvc-5.3.3.jar:5.3.3]
	at org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.java:52) ~[spring-webmvc-5.3.3.jar:5.3.3]
	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1060) ~[spring-webmvc-5.3.3.jar:5.3.3]
	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:962) ~[spring-webmvc-5.3.3.jar:5.3.3]
	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) ~[spring-webmvc-5.3.3.jar:5.3.3]
	at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909) ~[spring-webmvc-5.3.3.jar:5.3.3]
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:652) ~[tomcat-embed-core-9.0.41.jar:4.0.FR]
	at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) ~[spring-webmvc-5.3.3.jar:5.3.3]
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:733) ~[tomcat-embed-core-9.0.41.jar:4.0.FR]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) ~[tomcat-embed-websocket-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-5.3.3.jar:5.3.3]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.3.jar:5.3.3]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-5.3.3.jar:5.3.3]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.3.jar:5.3.3]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-5.3.3.jar:5.3.3]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.3.jar:5.3.3]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:542) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:143) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:374) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:888) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1597) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) ~[na:na]
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) ~[na:na]
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at java.base/java.lang.Thread.run(Thread.java:830) ~[na:na]
L

Provavelmente a venda está NULL nesse ponto:

venda.addProduto(txtProdutos.getValue());
^^^^^

Para evitar esse erro, seria o caso de vc já ter a venda instanciada no momento em que a tela fosse aberta, mas vai depender de como vc fez a tela, senão talvez tenha que alterar muita coisa.


Tentar pensar de forma. Quando vc for salvar a venda, vc consegue recuperar os IDs de todos os produtos que foram adicionados na tela?

R

na verdade está dando null aqui

adicionarProdutos.add(new TextField(pv.getProduto().getNome()));

L

Parece que tu tah fazendo confusão no fluxo da tela qdo for criar uma venda nova e quando for editar uma venda existente.

Tu não consegue jogar esse projeto no github pra gente ver ele melhor não?

R

Não sei usar git

R

@Lucas_Camara

se tu quiser, te mando via whats ou email

R

manda um email pra mim [email removido]

R

@Lucas_Camara

Bom dia, seque git para vc dar uma olhada

R

null por quê? Tem que passar os produtos para o método.

R

@RoinujNosde

Bom dia, então, mas eu estou passando eles aqui:

private void montarListaProdutos(List<ProdutoVendido> produtosVendidos) {
		HorizontalLayout adicionarProdutos = new HorizontalLayout();

		for (ProdutoVendido pv : produtosVendidos) {
			adicionarProdutos.add(new TextField(pv.getProduto().getNome()));
			
		}

		centro.add(adicionarProdutos);
	}

aqui estou passando null pq foi a unica forma que não deu erro de compilação:

grdVenda.addItemDoubleClickListener(event -> {
			if (venda != null) {
				binderVenda.readBean(venda);
				dlgJanela.open();
				montarListaProdutos(null);

			}
		});

	}

qualquer coisa que não seja null, da erro de compilação

R

Você está confundindo declaração com chamada de método.

private void montarListaProdutos(List<ProdutoVendido> produtosVendidos) {
	...	
}

No código acima você não está passando nada, você está apenas declarando.
O que é declarar? Informar o nome do método (montarListaProdutos), o que ele precisa pra funcionar (Lista de ProdutoVendido) e o que ele retorna (void nesse caso).

Só declarar não executa, não “passa” nada. Quem faz isso é a chamada de método: montarListaProdutos(parametros);.

Então nessa linha aqui:

montarListaProdutos(null);

Você está chamando o método e passando null, quando na verdade deveria passar uma List.

Onde está essa lista? Não é no objeto Venda?

montarListaProdutos(venda.getProdutosVendidos());

R

@RoinujNosde eu ja havia feito desta forma, esqueci de te falar, mas vamos la.

Fazendo da forma como vc falou:

Aqui é um print da tela de vendas, depois da venda já salva, é a tela que se abre ao dar um duplo click na grid.

repare que não foi salva nada(produtos, quantidade, unitario e total item)

o código:

grdVenda.addItemDoubleClickListener(event -> {
			if (venda != null) {
				binderVenda.readBean(venda);
				dlgJanela.open();
				montarListaProdutos(venda.getProdutos()); //LINHA 214

			}
		});

private void montarListaProdutos(List<ProdutoVendido> produtosVendidos) {
	HorizontalLayout adicionarProdutos = new HorizontalLayout();

	for (ProdutoVendido pv : produtosVendidos) {
		adicionarProdutos.add(new TextField(pv.getProduto().getNome())); // LINHA 355
		
	}

	centro.add(adicionarProdutos);
}

e ainda da este stack quando dou o duplo click:

java.lang.NullPointerException: null
	at br.com.fjsistemas.compraVenda.VendaView.montarListaProdutos(VendaView.java:355) ~[classes/:na]
	at br.com.fjsistemas.compraVenda.VendaView.lambda$10(VendaView.java:214) ~[classes/:na]
	at com.vaadin.flow.component.ComponentEventBus.fireEventForListener(ComponentEventBus.java:205) ~[flow-server-2.4.6.jar:2.4.6]
	at com.vaadin.flow.component.ComponentEventBus.handleDomEvent(ComponentEventBus.java:373) ~[flow-server-2.4.6.jar:2.4.6]
	at com.vaadin.flow.component.ComponentEventBus.lambda$addDomTrigger$dd1b7957$1(ComponentEventBus.java:264) ~[flow-server-2.4.6.jar:2.4.6]
	at com.vaadin.flow.internal.nodefeature.ElementListenerMap.lambda$fireEvent$2(ElementListenerMap.java:441) ~[flow-server-2.4.6.jar:2.4.6]
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1507) ~[na:na]
	at com.vaadin.flow.internal.nodefeature.ElementListenerMap.fireEvent(ElementListenerMap.java:441) ~[flow-server-2.4.6.jar:2.4.6]
	at com.vaadin.flow.server.communication.rpc.EventRpcHandler.handleNode(EventRpcHandler.java:59) ~[flow-server-2.4.6.jar:2.4.6]
	at com.vaadin.flow.server.communication.rpc.AbstractRpcInvocationHandler.handle(AbstractRpcInvocationHandler.java:64) ~[flow-server-2.4.6.jar:2.4.6]
	at com.vaadin.flow.server.communication.ServerRpcHandler.handleInvocationData(ServerRpcHandler.java:409) ~[flow-server-2.4.6.jar:2.4.6]
	at com.vaadin.flow.server.communication.ServerRpcHandler.lambda$handleInvocations$1(ServerRpcHandler.java:390) ~[flow-server-2.4.6.jar:2.4.6]
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1507) ~[na:na]
	at com.vaadin.flow.server.communication.ServerRpcHandler.handleInvocations(ServerRpcHandler.java:390) ~[flow-server-2.4.6.jar:2.4.6]
	at com.vaadin.flow.server.communication.ServerRpcHandler.handleRpc(ServerRpcHandler.java:317) ~[flow-server-2.4.6.jar:2.4.6]
	at com.vaadin.flow.server.communication.UidlRequestHandler.synchronizedHandleRequest(UidlRequestHandler.java:89) ~[flow-server-2.4.6.jar:2.4.6]
	at com.vaadin.flow.server.SynchronizedRequestHandler.handleRequest(SynchronizedRequestHandler.java:40) ~[flow-server-2.4.6.jar:2.4.6]
	at com.vaadin.flow.server.VaadinService.handleRequest(VaadinService.java:1547) ~[flow-server-2.4.6.jar:2.4.6]
	at com.vaadin.flow.server.VaadinServlet.service(VaadinServlet.java:247) ~[flow-server-2.4.6.jar:2.4.6]
	at com.vaadin.flow.spring.SpringServlet.service(SpringServlet.java:111) ~[vaadin-spring-12.3.2.jar:na]
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:733) ~[tomcat-embed-core-9.0.41.jar:4.0.FR]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:712) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:459) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:352) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:312) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.springframework.web.servlet.mvc.ServletForwardingController.handleRequestInternal(ServletForwardingController.java:141) ~[spring-webmvc-5.3.3.jar:5.3.3]
	at org.springframework.web.servlet.mvc.AbstractController.handleRequest(AbstractController.java:177) ~[spring-webmvc-5.3.3.jar:5.3.3]
	at org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.java:52) ~[spring-webmvc-5.3.3.jar:5.3.3]
	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1060) ~[spring-webmvc-5.3.3.jar:5.3.3]
	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:962) ~[spring-webmvc-5.3.3.jar:5.3.3]
	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) ~[spring-webmvc-5.3.3.jar:5.3.3]
	at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909) ~[spring-webmvc-5.3.3.jar:5.3.3]
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:652) ~[tomcat-embed-core-9.0.41.jar:4.0.FR]
	at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) ~[spring-webmvc-5.3.3.jar:5.3.3]
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:733) ~[tomcat-embed-core-9.0.41.jar:4.0.FR]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) ~[tomcat-embed-websocket-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-5.3.3.jar:5.3.3]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.3.jar:5.3.3]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-5.3.3.jar:5.3.3]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.3.jar:5.3.3]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-5.3.3.jar:5.3.3]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.3.jar:5.3.3]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:542) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:143) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:374) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:888) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1597) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) ~[na:na]
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) ~[na:na]
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at java.base/java.lang.Thread.run(Thread.java:830) ~[na:na]
R

no stack Overflow falaram isso:

java - Não economizando produtos - Stack Overflow

R
<aside class="onebox githubblob">
  <header class="source">
      <a href="https://github.com/fjdesenvolvimento/Sistema-Vendas-Vaadin/blob/b24bd0a9e816cdd2b551b7d89d48d95ecb112206/src/main/java/br/com/fjsistemas/compraVenda/VendaView.java#L489" target="_blank">github.com</a>
  </header>
  <article class="onebox-body">
    <h4><a href="https://github.com/fjdesenvolvimento/Sistema-Vendas-Vaadin/blob/b24bd0a9e816cdd2b551b7d89d48d95ecb112206/src/main/java/br/com/fjsistemas/compraVenda/VendaView.java#L489" target="_blank">fjdesenvolvimento/Sistema-Vendas-Vaadin/blob/b24bd0a9e816cdd2b551b7d89d48d95ecb112206/src/main/java/br/com/fjsistemas/compraVenda/VendaView.java#L489</a></h4>
<pre class="onebox"><code class="lang-java"><ol class="start lines" start="479" style="counter-reset: li-counter 478 ;">
<li>			}</li>
<li>
</li>
<li>			campoSomaValores.setValue(formatter.format(soma));// externa</li>
<li>
</li>
<li>		});</li>
<li>
</li>
<li>		adicionarProdutos = new HorizontalLayout();</li>
<li>		adicionarProdutos.add(txtProdutos, txtQuantidade, txtValorUnitario, txtValorTotalItem);</li>
<li>		centro.add(adicionarProdutos);</li>
<li>		valores.add(txtValorTotalItem);</li>
<li class="selected">		venda.addProduto(txtProdutos.getValue());</li>
<li>	}</li>
<li>
</li>
<li>	private void limparCampos() {</li>
<li>		centro.removeAll();</li>
<li>	}</li>
<li>
</li>
<li>	private void novaVenda() {</li>
<li>		venda = new Venda();</li>
<li>		venda.setCliente(null);</li>
<li>		venda.setFormaDePagamento(null);</li>
</ol>
Aqui você está adicionando um Produto null na Venda, pois o ComboBox não tem nada selecionado ainda, então o getValue() retorna null. Vc tem que adicionar na Venda quando o Usuario selecionar algum produto.
R

@RoinujNosde

Metodo adiciona produto

txtProdutos.setWidth("370px");
		txtProdutos.setLabel("Produtos");
		List<Produto> listaDeProdutos = produtoRepository.findAll();
		txtProdutos.setItemLabelGenerator(Produto::getNome);
		txtProdutos.setItems(listaDeProdutos);
		txtProdutos.addValueChangeListener(event -> {
			venda.addProduto(txtProdutos.getValue()); // LINHA 437
			NumberFormat formatter = NumberFormat.getCurrencyInstance(new Locale("pt", "BR"));
			try {

				txtValorUnitario.setValue(formatter.format(event.getValue().getValor()));

			} catch (Exception e) {
				e.printStackTrace();
			}

		});

		// ==========================================================================================================================

		txtQuantidade.setHasControls(true);
		txtQuantidade.setValue(null);
		txtQuantidade.setMin(1);

		txtQuantidade.addValueChangeListener(event -> {

			NumberFormat formatter = NumberFormat.getCurrencyInstance(new Locale("pt", "BR"));
			double valorTotal = 0;

			try {
				valorTotal = formatter.parse(txtValorUnitario.getValue()).doubleValue() * txtQuantidade.getValue();
			} catch (ParseException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

			txtValorTotalItem.setValue(formatter.format(valorTotal));

			double soma = 0;// interna
			for (TextField tf : valores) {
				try {
					soma += formatter.parse(tf.getValue()).doubleValue();

				} catch (ParseException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}

			}

			campoSomaValores.setValue(formatter.format(soma));// externa

		});

		adicionarProdutos = new HorizontalLayout();
		adicionarProdutos.add(txtProdutos, txtQuantidade, txtValorUnitario, txtValorTotalItem);
		centro.add(adicionarProdutos);
		valores.add(txtValorTotalItem);

	}

resultado:

mas pq não trouxe a descrição do produto?

R

Você escreveu alguma lógica pra isso?

L

Clonei seu projeto e rodei aqui. Da forma como vc está manipulando os produtos na venda, realmente, vai ser muito difícil para vc persistir eles.

Basicamente vc está apenas trabalhando com elementos de tela e esquecendo dos objetos de domínio (no caso, a venda e os produtos).

Pelo que testei, qdo o botão +Item é acionado, ele cria os elementos na tela para poder escolher as características do produto, e só. Depois disso, não há uma forma de concretizar essa inclusão na venda. Isso poderia ser feito com algum botão de confirmar, ou se vc recuperar todas as informações dos produtos adicionados no momento em que vc salvar a venda, é possível fazer isso através do componente adicionarProdutos (nome estranho, mas é o componente de layout HorizontalLayout).

Veja:

image

Com o código:

adicionarProdutos.getChildren().collect(Collectors.toList())

vc consegue recuperar os elementos adicionados onde vc vai conseguir recuperar os dados de cada produto adicionado e adicionar na venda (convertendo para a entidade ProdutoVendido).

Porém, acho que essa não é a melhor forma de fazer isso, pois, pelo que vi, se vc adicionar mais de um produto, vc terá dificuldades de recuperar os dados de todos esses produtos. Talvez uma melhor forma seja alguma modal para adicionar esses produtos ou algo para confirmar a ação.

R

@Lucas_Camara

vc então poderia me ajudar a criar tudo para que funcione o sistema? Eu entendi o que vc disse, mas gostaria de ter alguém me orientando “passo a passo”. Caso seja possível me ajudar, qual o primeiro passo para resolver a questão? Posso mudar tudo, não estou preso a nada…podemos excluir classes, criar classes, métodos, funções…o que for necessário

L

Para vc não ter que mudar muito seu código (até pq acho que falta pouco para fazer funcionar), acho que tu pode abrir uma modal qdo o botão +Item fosse acionado. Nessa modal, teria os campos com os dados do produto e, ao confirmar, vc adicionaria o produto à venda.

R

@Lucas_Camara

Ok, mas como faço esse modal?

L

Tu já fez uma modal lah no sistema. Acho que tu consegue fazer outra em cima dessa que já existe.

R

@RoinujNosde

Aqui eu consegui salvar os 4 objetos(por enquanto somente a descricao), mas ele está meio “apagado”

R

Como você mostrava um produto na tela antes e como mostra agora? Compare.

R

@RoinujNosde
Então, lembra que antes não mostrava nada? Antes eu apenas conseguia adicionar os produtos, mas eles não eram salvos. Agora está sendo salvo, mas está meio apagado.

código para “mostrar”

private void montarListaProdutos(List<ProdutoVendido> produtosVendidos) {
		HorizontalLayout adicionarProdutos = new HorizontalLayout();

		for (ProdutoVendido pv : produtosVendidos) {
			adicionarProdutos.add(new HorizontalLayout(new TextField("Produtos:", (pv.getProduto().getNome()))));
			adicionarProdutos.add(new HorizontalLayout(new TextField("Quantidade:", String.valueOf(pv.getQuantidade()))));
			adicionarProdutos.add(new HorizontalLayout(new TextField("Valor Unitário:", String.valueOf(pv.getValorUnitario()))));
			adicionarProdutos.add(new HorizontalLayout(new TextField("Valor Total Item:", String.valueOf(pv.getValorTotalItem()))));
			
		}
		adicionarProdutos.getChildren().collect(Collectors.toList());
		centro.add(adicionarProdutos);
	}

duplo click na grid:

grdVenda.addItemDoubleClickListener(event -> {
			if (venda != null) {
				binderVenda.readBean(venda);
				dlgJanela.open();
				montarListaProdutos(venda.getProdutos());

			}
		});

	}
R

Quando está criando uma Venda, fica apagado tbm? Não, né? É esse código que tô perguntando.

Está ficando apagando quando tenta editar uma Venda já salva, não é?

R

@RoinujNosde

Não…este duplo clique não é para Editar/Alterar nada…é apenas para visualizar

Quando estou criando a venda não, não fica apagado neste caso o código que vc se refere é este:

private void adicionaProduto() {

		ComboBox<Produto> txtProdutos = new ComboBox<>();

		IntegerField txtQuantidade = new IntegerField("Quantidade");

		TextField txtValorUnitario = new TextField("Valor Unitário");

		TextField txtValorTotalItem = new TextField("Valor Total Item");

		txtProdutos.setWidth("370px");
		txtProdutos.setLabel("Produtos");
		List<Produto> listaDeProdutos = produtoRepository.findAll();
		txtProdutos.setItemLabelGenerator(Produto::getNome);
		txtProdutos.setItems(listaDeProdutos);
		txtProdutos.addValueChangeListener(event -> {
			venda.addProduto(txtProdutos.getValue()); // LINHA 437
			NumberFormat formatter = NumberFormat.getCurrencyInstance(new Locale("pt", "BR"));
			try {

				txtValorUnitario.setValue(formatter.format(event.getValue().getValor()));

			} catch (Exception e) {
				e.printStackTrace();
			}

		});

		// ==========================================================================================================================

		txtQuantidade.setHasControls(true);
		txtQuantidade.setValue(null);
		txtQuantidade.setMin(1);

		txtQuantidade.addValueChangeListener(event -> {
			
			NumberFormat formatter = NumberFormat.getCurrencyInstance(new Locale("pt", "BR"));
			double valorTotal = 0;

			try {
				valorTotal = formatter.parse(txtValorUnitario.getValue()).doubleValue() * txtQuantidade.getValue();
			} catch (ParseException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

			txtValorTotalItem.setValue(formatter.format(valorTotal));

			double soma = 0;// interna
			for (TextField tf : valores) {
				try {
					soma += formatter.parse(tf.getValue()).doubleValue();

				} catch (ParseException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}

			}

			campoSomaValores.setValue(formatter.format(soma));// externa

		});

		adicionarProdutos = new HorizontalLayout();
		adicionarProdutos.add(txtProdutos, txtQuantidade, txtValorUnitario, txtValorTotalItem);
		centro.add(adicionarProdutos);
		valores.add(txtValorTotalItem);

	}
R

Ah, certo. Confundi.

Será que tá apagado porque não são campos editáveis?

R

@RoinujNosde

pode ser que seja mesmo…obg por sua ajuda até aqui!!!

@Lucas_Camara

a vc tbm, muito obg por sua ajuda!!!

R

@RoinujNosde e @Lucas_Camara

Eu fiz algumas modificações no código, mas não sei se irá facilitar as coisas, gostaria da opinião de vcs.

Fiz o seguinte:

Deletei a classe ProdutoVendido, só para vcs lembrarem esta ERA a classe ProdutoVendido:

package br.com.fjsistemas.backend;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

@AllArgsConstructor
@NoArgsConstructor
@Data
@Getter
@Setter
@Entity
public class ProdutoVendido {

	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	private Long id;
	
	@ManyToOne
	private Venda venda;
	
	@ManyToOne
	private Produto produto;
	
	private int quantidade;
	private Double valorUnitario;
	private Double valorTotalItem;
}

Na classe Venda(Entidade), antes estava assim:

package br.com.fjsistemas.backend;

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
@Data
@Entity
public class Venda {

	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	private Long id;

	private LocalDate dataVenda = LocalDate.now();

	@ManyToOne
	private Cliente cliente;

	@ManyToOne
	private FormaDePagamento formaDePagamento;

	@OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.PERSIST)
	private List<ProdutoVendido> produtos = new ArrayList<>();

	public void addProduto(Produto produto) {
		ProdutoVendido produtoVenda = new ProdutoVendido(id, this, produto, 0, null, null);																			
		produtos.add(produtoVenda);
	}

	private String valorTotalVenda;

}

AGORA a classe Venda ESTÁ assim:

package br.com.fjsistemas.backend;

import java.time.LocalDate;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
@Data
@Entity
public class Venda {

	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	private Long id;

	private LocalDate dataVenda = LocalDate.now();

	@ManyToOne
	private Cliente cliente;

	@ManyToOne
	private FormaDePagamento formaDePagamento;

	private String valorTotalVenda;
	private String descricao;
	private String quantidade;
	private Double valorUnitario;
	private Double valorTotalItem;
}

E por fim na classe VendaView eu tirei aquela Div enorme que recebia os produtos para venda, em seu lugar coloquei uma grid:

Aqui eu pensei em fazer da seguinte forma:

Para adicionar Produtos, Quantidade, Valor Unitário e total do item, basta o usuario clicar no botão Add Produtos, mas em vez de abrir uma janela, pensei em atribuir os dados diretamente na grid, eu vi no site Vaandin que tem alguns exemplos:

Mas nestes exemplos só falam como adicionar dados fornecidos pelo sistema e não pelo usuario.

Será que há alguma forma de atribuir dados na grid, onde o usuario passe as informações?

minha ideia(visualmente falando) é essa:

O que acham destas mudanças?

L

+1 por ter colocado uma tabela no lugar do HorizontalLayout que estava.

Mas isso te deixa com o mesmo problema. Qdo um produto for adicionado, como vc vai relacionar o produto à venda? E é exatamente o que a classe ProdutoVendido fazia (junto com o método addProduto que tinha na venda).

Pense bem, num sistema de vendas, o relacionamento entre um produto e uma venda, geralmente, é feita por uma tabela intermediária, pois um mesmo produto pode ser vendido várias vezes, e uma venda pode ser usada para vender mais de um produto.

Venda --> ProdutoVendido <-- Produto

Nesse exemplo, a tabela ProdutoVendido servirá de vínculo, não tem como vc não ter algo assim.

O problema que vc tem é na sua tela. Na forma como vc “amarra” a usabilidade da tela com as classes do domínio (que são Venda, Produto e ProdutoVendido).

R

@Lucas_Camara

Vc tem sido um cara muito prestativo, mas vou te confessar uma coisa…quando eu leio o que vc posta, parece que vc está falando grego…kkk…o problema não é vc, longe disso, sou eu…tenho muita dificuldade em entender, apenas lendo…

Se vc puder, se vc quiser, poderia me ajudar codificando tudo, passo a passo? Pois toda vez que vejo o código, ai sim eu consigo entender o que foi feito, o pq foi feito, as vantagens e desvantagens…etc etc. Como eu disse antes, podemos mudar tudo o que vc achar necessário

L

Hehe, tranquilo. Sei como é essa dificuldade.

Nesse print que vc mandou:

No oitavo passo que vc descreveu:

Após salvar, os produtos ficam expostos e salvos na grid.

Vc não pode focar apenas na tela. Está muito preocupado em que o produto apareça na tela e esquecendo do motor do sistema. A modelagem das classes Venda, ProdutoVendido e Produto é mais importante do que a tela.

Se vc conseguir fazer salvar os produtos da venda (esquece tela por enquanto), vc vai conseguir resolver o problema da tela depois com mais facilidade.

R

@Lucas_Camara

Ok, vamos esquecer a tela neste primeiro momento…o que devo fazer para obter os comportamentos necessários para rodar o programa?

L

Qdo o botão de salvar for acionado, vc deve ter um objeto Venda preenchido com uma lista de produtos vendidos (igual estava antes).

DICA: Para testar, tu pode até mesmo criar de forma fixa:

private void salvarClick() {
	venda = binderVenda.getBean();
	
	// faça isso fixo soh para ver se vai gravar no banco de dados mesmo
	// isso irá validar se o mapeamento das classes está correto
	venda.addProduto(new Produto(/* aqui vc passa uns valores fixo soh para testar */));
	venda.addProduto(new Produto(/* aqui vc passa uns valores fixo soh para testar */));
	venda.addProduto(new Produto(/* aqui vc passa uns valores fixo soh para testar */));
	venda.addProduto(new Produto(/* aqui vc passa uns valores fixo soh para testar */));
	
	boolean adicionarLista = venda.getId() == null ? true : false;
	vendaService.create(venda);
	
	if (adicionarLista) {
		listaVendas.add(venda);
	}
	
	atualizaGrdVenda();
	novaVenda();
	txtNomeCliente.focus();
	
	binderVenda.setBean(venda);
	
	if (adicionarLista) {
		dlgJanela.close();
	}
}
R

@Lucas_Camara

ok feito:

private void salvarClick() {

		venda = binderVenda.getBean();
		
		// faça isso fixo soh para ver se vai gravar no banco de dados mesmo
		// isso irá validar se o mapeamento das classes está correto
		venda.addProduto(new Produto(null, "Produto", "Marca", "Modelo", 1000.00));
		venda.addProduto(new Produto(null, "Produto2", "Marca2", "Modelo2", 1500.00));
		venda.addProduto(new Produto(null, "Produto3", "Marca3", "Modelo3", 2000.00));
		venda.addProduto(new Produto(null, "Produto4", "Marca4", "Modelo4", 2500.00));
		
		boolean adicionarLista = venda.getId() == null ? true : false;
		vendaService.create(venda);
		
		if (adicionarLista) {
			listaVendas.add(venda);
		}
		
		atualizaGrdVenda();
		novaVenda();
		txtNomeCliente.focus();
		
		binderVenda.setBean(venda);
	}
L

Ao mandar salvar essa venda, os produtos aparecem gravados corretamente?

R

@Lucas_Camara

não acontece nada, só da este stack:

org.springframework.dao.InvalidDataAccessApiUsageException: org.hibernate.TransientPropertyValueException: object references an unsaved transient instance - save the transient instance before flushing : br.com.fjsistemas.backend.ProdutoVendido.produto -> br.com.fjsistemas.backend.Produto; nested exception is java.lang.IllegalStateException: org.hibernate.TransientPropertyValueException: object references an unsaved transient instance - save the transient instance before flushing : br.com.fjsistemas.backend.ProdutoVendido.produto -> br.com.fjsistemas.backend.Produto
	at org.springframework.orm.jpa.EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible(EntityManagerFactoryUtils.java:371) ~[spring-orm-5.3.3.jar:5.3.3]
	at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:235) ~[spring-orm-5.3.3.jar:5.3.3]
	at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:566) ~[spring-orm-5.3.3.jar:5.3.3]
	at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:743) ~[spring-tx-5.3.3.jar:5.3.3]
	at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:711) ~[spring-tx-5.3.3.jar:5.3.3]
	at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:654) ~[spring-tx-5.3.3.jar:5.3.3]
	at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:407) ~[spring-tx-5.3.3.jar:5.3.3]
	at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119) ~[spring-tx-5.3.3.jar:5.3.3]
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.3.jar:5.3.3]
	at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:137) ~[spring-tx-5.3.3.jar:5.3.3]
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.3.jar:5.3.3]
	at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:174) ~[spring-data-jpa-2.4.3.jar:2.4.3]
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.3.jar:5.3.3]
	at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:97) ~[spring-aop-5.3.3.jar:5.3.3]
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.3.jar:5.3.3]
	at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:215) ~[spring-aop-5.3.3.jar:5.3.3]
	at com.sun.proxy.$Proxy110.save(Unknown Source) ~[na:na]
	at br.com.fjsistemas.service.VendaService.create(VendaService.java:20) ~[classes/:na]
	at br.com.fjsistemas.compraVenda.VendaView.salvarClick(VendaView.java:373) ~[classes/:na]
	at br.com.fjsistemas.compraVenda.VendaView.lambda$14(VendaView.java:299) ~[classes/:na]
	at com.vaadin.flow.component.ComponentEventBus.fireEventForListener(ComponentEventBus.java:205) ~[flow-server-2.4.6.jar:2.4.6]
	at com.vaadin.flow.component.ComponentEventBus.handleDomEvent(ComponentEventBus.java:373) ~[flow-server-2.4.6.jar:2.4.6]
	at com.vaadin.flow.component.ComponentEventBus.lambda$addDomTrigger$dd1b7957$1(ComponentEventBus.java:264) ~[flow-server-2.4.6.jar:2.4.6]
	at com.vaadin.flow.internal.nodefeature.ElementListenerMap.lambda$fireEvent$2(ElementListenerMap.java:441) ~[flow-server-2.4.6.jar:2.4.6]
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1507) ~[na:na]
	at com.vaadin.flow.internal.nodefeature.ElementListenerMap.fireEvent(ElementListenerMap.java:441) ~[flow-server-2.4.6.jar:2.4.6]
	at com.vaadin.flow.server.communication.rpc.EventRpcHandler.handleNode(EventRpcHandler.java:59) ~[flow-server-2.4.6.jar:2.4.6]
	at com.vaadin.flow.server.communication.rpc.AbstractRpcInvocationHandler.handle(AbstractRpcInvocationHandler.java:64) ~[flow-server-2.4.6.jar:2.4.6]
	at com.vaadin.flow.server.communication.ServerRpcHandler.handleInvocationData(ServerRpcHandler.java:409) ~[flow-server-2.4.6.jar:2.4.6]
	at com.vaadin.flow.server.communication.ServerRpcHandler.lambda$handleInvocations$1(ServerRpcHandler.java:390) ~[flow-server-2.4.6.jar:2.4.6]
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1507) ~[na:na]
	at com.vaadin.flow.server.communication.ServerRpcHandler.handleInvocations(ServerRpcHandler.java:390) ~[flow-server-2.4.6.jar:2.4.6]
	at com.vaadin.flow.server.communication.ServerRpcHandler.handleRpc(ServerRpcHandler.java:317) ~[flow-server-2.4.6.jar:2.4.6]
	at com.vaadin.flow.server.communication.UidlRequestHandler.synchronizedHandleRequest(UidlRequestHandler.java:89) ~[flow-server-2.4.6.jar:2.4.6]
	at com.vaadin.flow.server.SynchronizedRequestHandler.handleRequest(SynchronizedRequestHandler.java:40) ~[flow-server-2.4.6.jar:2.4.6]
	at com.vaadin.flow.server.VaadinService.handleRequest(VaadinService.java:1547) ~[flow-server-2.4.6.jar:2.4.6]
	at com.vaadin.flow.server.VaadinServlet.service(VaadinServlet.java:247) ~[flow-server-2.4.6.jar:2.4.6]
	at com.vaadin.flow.spring.SpringServlet.service(SpringServlet.java:111) ~[vaadin-spring-12.3.2.jar:na]
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:733) ~[tomcat-embed-core-9.0.41.jar:4.0.FR]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:712) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:459) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:352) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:312) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.springframework.web.servlet.mvc.ServletForwardingController.handleRequestInternal(ServletForwardingController.java:141) ~[spring-webmvc-5.3.3.jar:5.3.3]
	at org.springframework.web.servlet.mvc.AbstractController.handleRequest(AbstractController.java:177) ~[spring-webmvc-5.3.3.jar:5.3.3]
	at org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.java:52) ~[spring-webmvc-5.3.3.jar:5.3.3]
	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1060) ~[spring-webmvc-5.3.3.jar:5.3.3]
	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:962) ~[spring-webmvc-5.3.3.jar:5.3.3]
	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) ~[spring-webmvc-5.3.3.jar:5.3.3]
	at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909) ~[spring-webmvc-5.3.3.jar:5.3.3]
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:652) ~[tomcat-embed-core-9.0.41.jar:4.0.FR]
	at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) ~[spring-webmvc-5.3.3.jar:5.3.3]
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:733) ~[tomcat-embed-core-9.0.41.jar:4.0.FR]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) ~[tomcat-embed-websocket-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-5.3.3.jar:5.3.3]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.3.jar:5.3.3]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-5.3.3.jar:5.3.3]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.3.jar:5.3.3]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-5.3.3.jar:5.3.3]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.3.jar:5.3.3]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:542) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:143) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:374) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:888) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1597) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) ~[na:na]
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) ~[na:na]
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
	at java.base/java.lang.Thread.run(Thread.java:830) ~[na:na]
Caused by: java.lang.IllegalStateException: org.hibernate.TransientPropertyValueException: object references an unsaved transient instance - save the transient instance before flushing : br.com.fjsistemas.backend.ProdutoVendido.produto -> br.com.fjsistemas.backend.Produto
	at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:151) ~[hibernate-core-5.4.27.Final.jar:5.4.27.Final]
	at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:181) ~[hibernate-core-5.4.27.Final.jar:5.4.27.Final]
	at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:188) ~[hibernate-core-5.4.27.Final.jar:5.4.27.Final]
	at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1366) ~[hibernate-core-5.4.27.Final.jar:5.4.27.Final]
	at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:453) ~[hibernate-core-5.4.27.Final.jar:5.4.27.Final]
	at org.hibernate.internal.SessionImpl.flushBeforeTransactionCompletion(SessionImpl.java:3212) ~[hibernate-core-5.4.27.Final.jar:5.4.27.Final]
	at org.hibernate.internal.SessionImpl.beforeTransactionCompletion(SessionImpl.java:2380) ~[hibernate-core-5.4.27.Final.jar:5.4.27.Final]
	at org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.beforeTransactionCompletion(JdbcCoordinatorImpl.java:447) ~[hibernate-core-5.4.27.Final.jar:5.4.27.Final]
	at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.beforeCompletionCallback(JdbcResourceLocalTransactionCoordinatorImpl.java:183) ~[hibernate-core-5.4.27.Final.jar:5.4.27.Final]
	at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.access$300(JdbcResourceLocalTransactionCoordinatorImpl.java:40) ~[hibernate-core-5.4.27.Final.jar:5.4.27.Final]
	at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.commit(JdbcResourceLocalTransactionCoordinatorImpl.java:281) ~[hibernate-core-5.4.27.Final.jar:5.4.27.Final]
	at org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:101) ~[hibernate-core-5.4.27.Final.jar:5.4.27.Final]
	at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:562) ~[spring-orm-5.3.3.jar:5.3.3]
	... 85 common frames omitted
Caused by: org.hibernate.TransientPropertyValueException: object references an unsaved transient instance - save the transient instance before flushing : br.com.fjsistemas.backend.ProdutoVendido.produto -> br.com.fjsistemas.backend.Produto
	at org.hibernate.engine.spi.CascadingActions$8.noCascade(CascadingActions.java:379) ~[hibernate-core-5.4.27.Final.jar:5.4.27.Final]
	at org.hibernate.engine.internal.Cascade.cascade(Cascade.java:167) ~[hibernate-core-5.4.27.Final.jar:5.4.27.Final]
	at org.hibernate.event.internal.AbstractSaveEventListener.cascadeBeforeSave(AbstractSaveEventListener.java:427) ~[hibernate-core-5.4.27.Final.jar:5.4.27.Final]
	at org.hibernate.event.internal.DefaultPersistEventListener.justCascade(DefaultPersistEventListener.java:167) ~[hibernate-core-5.4.27.Final.jar:5.4.27.Final]
	at org.hibernate.event.internal.DefaultPersistEventListener.entityIsPersistent(DefaultPersistEventListener.java:160) ~[hibernate-core-5.4.27.Final.jar:5.4.27.Final]
	at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:124) ~[hibernate-core-5.4.27.Final.jar:5.4.27.Final]
	at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:113) ~[hibernate-core-5.4.27.Final.jar:5.4.27.Final]
	at org.hibernate.internal.SessionImpl.persistOnFlush(SessionImpl.java:765) ~[hibernate-core-5.4.27.Final.jar:5.4.27.Final]
	at org.hibernate.engine.spi.CascadingActions$8.cascade(CascadingActions.java:341) ~[hibernate-core-5.4.27.Final.jar:5.4.27.Final]
	at org.hibernate.engine.internal.Cascade.cascadeToOne(Cascade.java:492) ~[hibernate-core-5.4.27.Final.jar:5.4.27.Final]
	at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:416) ~[hibernate-core-5.4.27.Final.jar:5.4.27.Final]
	at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:218) ~[hibernate-core-5.4.27.Final.jar:5.4.27.Final]
	at org.hibernate.engine.internal.Cascade.cascadeCollectionElements(Cascade.java:525) ~[hibernate-core-5.4.27.Final.jar:5.4.27.Final]
	at org.hibernate.engine.internal.Cascade.cascadeCollection(Cascade.java:456) ~[hibernate-core-5.4.27.Final.jar:5.4.27.Final]
	at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:419) ~[hibernate-core-5.4.27.Final.jar:5.4.27.Final]
	at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:218) ~[hibernate-core-5.4.27.Final.jar:5.4.27.Final]
	at org.hibernate.engine.internal.Cascade.cascade(Cascade.java:151) ~[hibernate-core-5.4.27.Final.jar:5.4.27.Final]
	at org.hibernate.event.internal.AbstractFlushingEventListener.cascadeOnFlush(AbstractFlushingEventListener.java:158) ~[hibernate-core-5.4.27.Final.jar:5.4.27.Final]
	at org.hibernate.event.internal.AbstractFlushingEventListener.prepareEntityFlushes(AbstractFlushingEventListener.java:148) ~[hibernate-core-5.4.27.Final.jar:5.4.27.Final]
	at org.hibernate.event.internal.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:81) ~[hibernate-core-5.4.27.Final.jar:5.4.27.Final]
	at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:39) ~[hibernate-core-5.4.27.Final.jar:5.4.27.Final]
	at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:102) ~[hibernate-core-5.4.27.Final.jar:5.4.27.Final]
	at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1362) ~[hibernate-core-5.4.27.Final.jar:5.4.27.Final]
	... 94 common frames omitted
L

Ah sim, foi falha minha. Na verdade, o certo seria recuperar o produto do banco pelo ID (ou informar algum ID de produto que já esteja cadastrado):

// em vez de NULL, passe algum ID de produto que já esteja cadastrado
venda.addProduto(new Produto(null, "Produto", "Marca", "Modelo", 1000.00));
                               ^

Ou recupere um produto do banco:

Produto produtoTeste = produtoRepository.findById(1);
venda.addProduto(produtoTeste);
R

@Lucas_Camara

OU

L

Deixa o que busca pelo id mesmo. Apenas faça assim: findById(6L); (coloca um L depois do número)

R

@Lucas_Camara

R

Alterando um pouco o código acho que da certo…testei isso

Optional<Produto> produtoTeste = produtoRepository.findById(6L);
		venda.addProduto(produtoTeste);

e na Entidade Venda

public void addProduto(Optional<Produto> produtoTeste) {
		ProdutoVendido produtoVenda = new ProdutoVendido(id, null, null, 0, null, null);
		produtos.add(produtoVenda);
	}

No Banco:

L

hehe, sempre tem um detalhe neh. Esse método findById retorna um Optional.

O certo seria assim:

Optional<Produto> produtoTeste = produtoRepository.findById(6L);

if (produto.isPresent()) {
	venda.addProduto(produtoTeste.get());
}
R

@Lucas_Camara

Alterei aqui para forma como vc passou, não deu erros ou stack e no banco:

L

Faz commit e push do código. Vou ver aqui.

L

nessa parte:

De onde está vindo esse id do ProdutoVendido? Ele não está declarado em lugar nenhum.

R

@Lucas_Camara

aqui o id está declarado na classe(entidade) ProdutoVendido

public void addProduto(Optional<Produto> produtoTeste) { 
    ProdutoVendido produtoVenda = new ProdutoVendido(id, null, null, 0, null, null); 
    produtos.add(produtoVenda); 
}
L

Entendi.

Deixe o método addProduto assim:

public void addProduto(Produto produto) {
	ProdutoVendido produtoVenda = new ProdutoVendido(id, this, produto, 1, produto.getValor(), produto.getValor());
	produtos.add(produtoVenda);
}
R

@Lucas_Camara

L

Blz! Agora sabemos que o mapeamento está correto, ou seja, não precise mexer, por enquanto, em mais nada na venda, produto e produtoVendido.

Agora a ideia e conseguir uma forma da tela funcionar ao criar uma nova venda, ou visualizar uma venda existente.

R

@Lucas_Camara

Maravilha…estou no seu aguardo para saber como prosseguir

L

Estava tentando entender no código, onde que vc pega uma venda existente selecionada e popula a tela com os dados da venda.

R

@Lucas_Camara

quando mudei o código, tirando aquela div, eu deletei muita coisa e deixei somente o básico, então neste momento não tem nenhum código para pegar uma venda existente e popular a tela com dados da venda

Apaguei tudo para começar “do zero”

L

Entendi. Agora vc está usando uma tabela para apresentar os produtos da venda, certo? Se for, tenta recuperar os produtos da venda e adicioná-los nessa tabela, no momento em que a venda for selecionada.

R

@Lucas_Camara

Sim

R

@Lucas_Camara

no momento em que ela for salva, certo?

L

Para agora, no momento em que ela for carregada para ser visualizada. Para ver se vc consegue apresentar os dados do produto que foi salvo no teste que vc fez.

No momento em que uma venda for selecionada, vc deve fazer algo assim:

List<ProdutosVendidos> produtosVendidos = venda.getProdutos();

// supondo que vc tenha algum método que popule a tabela de produtos
popularTabela(produtosVendidos);

algo mais ou menos assim viu. Dá uma pensada ai em como implementar de acordo em como está seu código.

R

@Lucas_Camara

Não tem nenhum metodo para popular a tabela produtos

então devo criar um metodo na View e dentro deste metodo add este código que vc passou?

L

Vc terá que selecionar uma venda para visualizar os dados dela. O código que exemplifiquei, vc deve colocar nesse momento.

O método popularTabela é soh um exemplo. Vc pode ou não criar esse método.

R

@Lucas_Camara

para visualizar uma venda, dou um duplo click na grid

grdVenda.addItemDoubleClickListener(event -> {
			if (venda != null) {
				binderVenda.readBean(venda);
				dlgJanela.open();
				

			}
		});

Então se eu entendi o que vc falou, devo deixar o código assim?:

grdVenda.addItemDoubleClickListener(event -> {
			if (venda != null) {
				binderVenda.readBean(venda);
				dlgJanela.open();
				List<ProdutoVendido> produtosVendidos = venda.getProdutos();

			}
		});
R

@Lucas_Camara

Até o momento o sistema está desta forma:

1º chamar a tela de vendas através do menu lateral:

2º clicar no botão novo para lançar as informações sobre a venda(nome do cliente, forma de pagamento)

após clicar no botão novo abre a janela:

o usuario fornece os dados iniciais (nome cliente, forma de pagamento)

agora tem 3 botoes:

+Item = está sem nenhuma lógica.

salvar, que está com esta lógica:

btnSalvar.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
		btnSalvar.getStyle().set("margin-top", "2.3em");
		btnSalvar.getStyle().set("margin-left", "1em");
		btnSalvar.setWidth("190px");
		btnSalvar.addClickListener(e -> {
			salvarClick();

		});

Lógica de salvarClick:

private void salvarClick() {

		venda = binderVenda.getBean();

		Optional<Produto> produtoTeste = produtoRepository.findById(6L);

		if (produtoTeste.isPresent()) {
			venda.addProduto(produtoTeste.get());
		}
		
		boolean adicionarLista = venda.getId() == null ? true : false;
		vendaService.create(venda);
		
		if (adicionarLista) {
			listaVendas.add(venda);
		}
		
		atualizaGrdVenda();
		novaVenda();
		txtNomeCliente.focus();
		
		binderVenda.setBean(venda);
	}

e por fim tem o botão fechar:

btnFechar.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
		btnFechar.getStyle().set("margin-top", "2.3em");
		btnFechar.setWidth("190px");
		btnFechar.addClickListener(e -> {
			dlgJanela.close();

		});
L

Ok, então vamos tentar fazer gravar uma venda nova e depois vamos para a visualização de uma venda existente (que é o que eu estava pensando em fazer).

Tente implementar a lógica do botão +Item. Quando o botão for acionado, o sistema deverá pedir as informações do produto vendido e adicioná-lo na venda. A tabela de produtos deverá apresentar os produtos que foram adicionados na venda.

L

Para adicionar os produtos na venda, achei essa ideia que tu teve muito boa, mas acho que soh precisaria de algum clique para confirmar a ação. Com esse clique de confirmação, vc conseguiria adicionar o produto na venda. O que vc acha?

R

@Lucas_Camara

isso, seria perfeito…mas como colocamos em pratica?rs

L

Uai, tu tinha mandado o link do exemplo. Primeiro tem que ver como a grid funciona.

R

@Lucas_Camara

este é o exemplo no site vaadin

List<Person> personList = getItems();

// Providing a bean-type generates columns for all of it's properties
Grid<Person> grid = new Grid<>();
grid.setItems(personList);

Grid.Column<Person> firstNameColumn = grid
        .addColumn(Person::getFirstName).setHeader("First Name");
Grid.Column<Person> lastNameColumn = grid.addColumn(Person::getLastName)
        .setHeader("Last Name");
grid.addColumn(Person::getAge).setHeader("Age");

Button addButton = new Button("Add Item", event -> {

    personList.add(new Person(10000, "X", "Y", 16,
            new Address("95632", "New York"), "187-338-588"));
    // The dataProvider knows which List it is based on, so when you
    // edit the list
    // you edit the dataprovider.
    grid.getDataProvider().refreshAll();

});

Button removeButton = new Button("Remove last", event -> {

    personList.remove(personList.size() - 1);
    // The dataProvider knows which List it is based on, so when you
    // edit the list
    // you edit the dataprovider.
    grid.getDataProvider().refreshAll();
});

FooterRow footerRow = grid.appendFooterRow();
footerRow.getCell(firstNameColumn).setComponent(addButton);
footerRow.getCell(lastNameColumn).setComponent(removeButton);
add(grid, addButton, removeButton);

Esta é a Entidade de exemplo do site vaadin:

public static class Person implements Cloneable {
    private int id;
    private String firstName;
    private String lastName;
    private int age;
    private Address address;
    private String phoneNumber;
    private MaritalStatus maritalStatus;
    private LocalDate birthDate;
    private boolean isSubscriber;
    private String email;

    public Person() {

    }

    public Person(int id, String firstName, String lastName, int age,
                  Address address, String phoneNumber) {
        super();
        this.id = id;
        this.firstName = firstName;
        this.lastName = lastName;
        this.age = age;
        this.address = address;
        this.phoneNumber = phoneNumber;
    }

    public Person(int id, String firstName, String lastName, int age,
                  Address address, String phoneNumber,
                  MaritalStatus maritalStatus, LocalDate birthDate) {
        super();
        this.id = id;
        this.firstName = firstName;
        this.lastName = lastName;
        this.age = age;
        this.address = address;
        this.phoneNumber = phoneNumber;
        this.maritalStatus = maritalStatus;
        this.birthDate = birthDate;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getPhoneNumber() {
        return phoneNumber;
    }

    public void setPhoneNumber(String phoneNumber) {
        this.phoneNumber = phoneNumber;
    }

    public Address getAddress() {
        return address;
    }

    public void setAddress(Address address) {
        this.address = address;
    }

    public MaritalStatus getMaritalStatus() {
        return maritalStatus;
    }

    public void setMaritalStatus(MaritalStatus maritalStatus) {
        this.maritalStatus = maritalStatus;
    }

    public LocalDate getBirthDate() {
        return birthDate;
    }

    public void setBirthDate(LocalDate birthDate) {
        this.birthDate = birthDate;
    }

    public String getImage() {
        return "https://randomuser.me/api/portraits/men/" + getId()
                + ".jpg";
    }

    public boolean isSubscriber() {
        return isSubscriber;
    }

    public void setSubscriber(boolean isSubscriber) {
        this.isSubscriber = isSubscriber;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    @Override
    public int hashCode() {
        return id;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (!(obj instanceof Person)) {
            return false;
        }
        Person other = (Person) obj;
        return id == other.id;
    }

    @Override
    public String toString() {
        return firstName;
    }

    @Override
    public Person clone() { //NOSONAR
        try {
            return (Person) super.clone();
        } catch (CloneNotSupportedException e) {
            throw new RuntimeException(
                    "The Person object could not be cloned.", e);
        }
    }
}

public static class Address {
    private String street;
    private int number;
    private String postalCode;
    private String city;

    public Address() {

    }

    public Address(String postalCode, String city) {
        this.postalCode = postalCode;
        this.city = city;
    }

    public String getStreet() {
        return street;
    }

    public void setStreet(String street) {
        this.street = street;
    }

    public int getNumber() {
        return number;
    }

    public void setNumber(int number) {
        this.number = number;
    }

    public String getPostalCode() {
        return postalCode;
    }

    public void setPostalCode(String postalCode) {
        this.postalCode = postalCode;
    }

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }

    @Override
    public String toString() {
        return String.format("%s %s", postalCode, city);
    }

}

public enum MaritalStatus {
    MARRIED, SINGLE;
}
L

Acho que teria que fazer uma mescla com esses componentes:

Permite editar a linha na propria tabela
https://vaadin.com/components/vaadin-grid/java-examples/grid-editor

O que vc passou que permite ter os botões para adicionar novas linhas
https://vaadin.com/components/vaadin-grid/java-examples/assigning-data

Brabo que nunca usei o vaadin, teria que olhar com calma e estou meio enrolado no trampo aqui.

Tente fazer a tabela funcionar por partes. Pega o exemplo do site e vai trocando as classes pelas suas, ex.:

// onde tiver
Grid<Person> grid = new Grid<>();

// muda para 
Grid<ProdutoVendido> grid = new Grid<>();

// e vai fazendo a mesma coisa com o resto

Qdo tiver um tempinho tento dá uma lida na doc aqui.

R

@Lucas_Camara

tranquilo!!

R

@Lucas_Camara

Com este código:

List<ProdutoVendido> produtosVendidosList = new ArrayList<ProdutoVendido>();

		Grid<ProdutoVendido> grid = new Grid<>();
		grid.setItems(produtosVendidosList);
		grid.setHeight("650px");
		
		grid.addColumn(ProdutoVendido::getProduto).setHeader("Produto:").setAutoWidth(true);
		grid.addColumn(ProdutoVendido::getQuantidade).setHeader("Quantidade:");
		grid.addColumn(ProdutoVendido::getValorUnitario).setHeader("Valor Unitário:");
		grid.addColumn(ProdutoVendido::getValorTotalItem).setHeader("Valor Total do Item:");

		Button addButton = new Button("Adicionar Produto");
		addButton.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
		addButton.addClickListener(event -> {
			produtosVendidosList.add(new ProdutoVendido());
			grid.getDataProvider().refreshAll();
		});

		Button removeButton = new Button("Remover Produto");
		removeButton.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
		removeButton.addClickListener(event -> {
			produtosVendidosList.remove(produtosVendidosList.size() - 1);
			grid.getDataProvider().refreshAll();
		});

		Label text = new Label("Valor Total");
		text.getElement().getStyle().set("fontWeight", "bold");
		text.getStyle().set("margin-top", "1em");
		text.getStyle().set("margin-left", "1em");
		text.getStyle().set("text-align", "center");
		campoSomaValores.getStyle().set("margin-top", "0.5em");
		campoSomaValores.getStyle().set("margin-right", "0.2em");
		campoSomaValores.setWidth("30em");

		barraLayoutDlgInferior.add(text, campoSomaValores);
		superior.add(primeiraLinhaDivSuperior, segundaLinhaDivSuperior);
		barraBotoesGridVendidos.setJustifyContentMode(JustifyContentMode.START);
		barraBotoesGridVendidos.add(addButton, removeButton);

		dlgJanela.add(superior, grid, barraBotoesGridVendidos);

Consegui fazer a grid funcionar, ela está funcionando desta forma:

toda vez que clico no botão Adicionar Produto, acontece isso:

3 clicks:

agora precisamos bolar alguma forma de editar a própria grid, estou vendo se consigo fazer

L

Boa! É isso ai! Sobre conseguir editar diretamente na tabela, tinha visto isso na doc do vaadin: https://vaadin.com/components/vaadin-grid/java-examples/grid-editor

F

@rafaspara2017 depois de 200 mensagens em 20 dias, depois pega a conta do @RoinujNosde e do @Lucas_Camara para transferir um cachê pela consultoria.
:sweat_smile: :joy:

R

Se vc tiver outra duvida abre um novo tópico.

Criado 19 de abril de 2021
Ultima resposta 15 de mai. de 2021
Respostas 197
Participantes 5
Alura O que é Python? — um guia completo para iniciar nessa linguagem de programação Acesse agora o guia sobre Python e inicie sua jornada nessa linguagem de programação: o que é e para que serve, sua sintaxe e como iniciar nela!
Casa do Codigo Back-end Java: Microsservicos, Spring Boot e Kubernetes Por Eduardo Felipe Zambom Santana — Casa do Codigo
Fiap Pos-Tech: Arquitetura e Desenvolvimento Java Uma jornada especialmente pensada para profissionais que desejam dar os próximos passos na área...