8
respostas

Erro 500 - Problema <c:forEach

Olá, Optei por pegar o arquivo "detalhe" pronto, com as alterações já feitas no HTML. Mas, depois de fazer as configurações no "ProdutosController", ao tentar acessar a URL com id dos produtos, estou recebendo a seguinte mensagem de erro 500:

Servlet.service() for servlet [dispatcher] in context with path [/casadocodigo] threw exception [An exception occurred processing [/WEB-INF/views/produtos/detalhe.jsp] at line [77]

74:             <form action="/carrinho/add" method="post" class="container">
75:                 <input type="hidden" value="${produto.id }" name="produtoId" >
76:                 <ul id="variants" class="clearfix">
77:                     <c:forEach items="${produto.precos }" var="precos">
78:                         <li class="buy-option">
79:                             <input type="radio" name="tipoPreco" class="variant-radio" id="tipoPreco" value="${preco.tipo }" checked="checked" /> 
80:                             <label class="variant-label" >${preco.tipo }</label> 

O que fazer para resolver?

8 respostas

Olá Rodrigo, tudo bem com você?

Observando essa parte, acredito que tem algo estranho, você pode dar uma checada?

<c:forEach items="${produto.precos }" var="precos">

Aqui você declarou o forEach utilizando a variavel precos, entretanto:

<input type="radio" name="tipoPreco" class="variant-radio" id="tipoPreco" value="${preco.tipo }" checked="checked" /> 
<label class="variant-label" >${preco.tipo }</label> 

Depois a variável está sendo utilizado como preco

Na verdade no c:ForEach era para ser var="preco" para que tenha essa "compatibilidade"

Você pode fazer essa mundaça e dizer se funcionou corretamente ?

Abraços e Bons Estudos!

Olá Geovani!

Fiz as alterações, mas o problema persiste. O código ficou da seguinte forma:

<section class="buy-options clearfix">
            <form action="/carrinho/add" method="post" class="container">
                <input type="hidden" value="${produto.id }" name="produtoId" >
                <ul id="variants" class="clearfix">
                    <c:forEach items="${produto.precos }" var="preco">
                        <li class="buy-option">
                            <input type="radio" name="tipo" class="variant-radio" id="tipo" value="${preco.tipo }" checked /> 
                            <label class="variant-label" >${preco.tipo }</label> 
                            <small class="compare-at-price">R$ 39,90</small>
                            <p class="variant-price">${preco.valor }</p>
                        </li>
                    </c:forEach>

Olá Rodrigo, tranquilo?

Peço perdão pela demora, infelizmente fiquei sem conexão em casa, e não consegui responder :/

Cara, agora a sua .jsp está correta, então pode dar uma checada no controller, para ver se a variável passada está correta?

dentro do detalhe em ProdutosController.java é necessário estár criando um:

Produto produto = dao.find(id);
modelAndView.addObject("produto", produto);

Se aqui estiver "produtos" ainda teríamos problema com a jsp não encontrar esse atributo, uma outra razão pode ser dentro de nosso model ( mas acredito que seja mais díficil)

Veja se está:

@ElementCollection
private List<Preco> precos

Se estiver com outro nome ai pode ser também uma razão, pois ai na jsp no items não seria produto.precos

Mas sinceramente penso que deve ser no atributo passado para o Controller que possa estar havendo diferenças :)

Pode dar uma olhada e me dizer se aconteceu algo do tipo?

Abraços e Bons Estudos!

Olá Geovani! Verifiquei os dois códigos, e me parece que eles estão corretos. Vou colocar eles aqui pra ti dar uma olhada: ProdutosController.java

package br.com.casadocodigo.loja.controllers;

import java.util.List;

import javax.validation.Valid;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import br.com.casadocodigo.loja.daos.ProdutoDAO;
import br.com.casadocodigo.loja.infra.FileSaver;
import br.com.casadocodigo.loja.models.Produto;
import br.com.casadocodigo.loja.models.TipoPreco;
import br.com.casadocodigo.loja.validation.ProdutoValidation;

@Controller
@RequestMapping("/produtos")
public class ProdutosController {

    @Autowired
    private ProdutoDAO produtoDao;

    @Autowired
    private FileSaver fileSaver;

    @InitBinder
    public void initBinder(WebDataBinder binder) {
        binder.addValidators(new ProdutoValidation());
    }

    @RequestMapping("/form")
    public ModelAndView form(Produto produto) {
        ModelAndView modelAndView = new ModelAndView("produtos/form");
        modelAndView.addObject("tipos", TipoPreco.values());

        return modelAndView;

    }

    @RequestMapping(method = RequestMethod.POST)
    public ModelAndView grava(MultipartFile sumario,@Valid Produto produto, BindingResult result, RedirectAttributes redirectAttributes) {

        System.out.println(sumario.getOriginalFilename());

        if (result.hasErrors()) {
            return form(produto);
        }

        String path = fileSaver.write("arquivos-sumario", sumario);
        produto.setSumarioPath(path);

        produtoDao.gravar(produto);

        redirectAttributes.addFlashAttribute("sucesso", "Produto cadastrado com sucesso!");

        return new ModelAndView("redirect:produtos");
    }

    @RequestMapping(method = RequestMethod.GET)
    public ModelAndView listar() {
        List<Produto> produtos = produtoDao.listar();
        ModelAndView modelAndView = new ModelAndView("produtos/lista");
        modelAndView.addObject("produtos", produtos);

        return modelAndView;
    }

    @RequestMapping("/detalhe")
    public ModelAndView detalhe (Integer id) {
        ModelAndView modelAndView = new ModelAndView("produtos/detalhe");
        Produto produto = produtoDao.find(id);
        modelAndView.addObject("produto", produto);

        return modelAndView;

    }

}

Produto.java

package br.com.casadocodigo.loja.models;

import java.util.Calendar;
import java.util.List;

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

import org.springframework.format.annotation.DateTimeFormat;

@Entity
public class Produto {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;

    private String titulo;
    private String descricao;
    private int paginas;

    @DateTimeFormat
    private Calendar dataLancamento;

    @ElementCollection
    private List<Preco> precos;

    private String sumarioPath;

    public String getTitulo() {
        return titulo;
    }

    public void setTitulo(String titulo) {
        this.titulo = titulo;
    }

    public String getDescricao() {
        return descricao;
    }

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

    public int getPaginas() {
        return paginas;
    }

    public void setPaginas(int paginas) {
        this.paginas = paginas;
    }

    public int getId() {
        return id;
    }

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

    public List<Preco> getPrecos() {
        return precos;
    }

    public void setPrecos(List<Preco> precos) {
        this.precos = precos;
    }

    public Calendar getDataLancamento() {
        return dataLancamento;
    }

    public void setDataLancamento(Calendar dataLancamento) {
        this.dataLancamento = dataLancamento;
    }

    @Override
    public String toString() {
        return "Produto [nome=" + titulo + ", descricao=" + descricao + ", paginas=" + paginas + "]";
    }

    public String getSumarioPath() {
        return sumarioPath;
    }

    public void setSumarioPath(String sumarioPath) {
        this.sumarioPath = sumarioPath;
    }

}

Opa Rodrigo,

Agora temos algo complicado hahahaha!

Eu peguei a sua .jsp e o seu método detalhe do Controller para o projeto do curso, e fiz a troca, e funcionou corretamente, sem nenhum erro e mostrando todas as informações na página

Será que não escapou nada de aulas passadas? Agora a única coisa que pode estar trazendo esse problema seria no dao mas acredito que o método também deve estar correto...

Uma coisa que eu te recomendaria, seria pegar o projeto inicial da Aula 11 aqui e daria uma olhada em todos os arquivos para ver se em algum momento não houve algo de errado, mas as vezes acontecem alguns bugs, e nisso você poderia aproveitar o projeto a partir dai (algumas vezes aconteceu isso comigo com a .jsp)

Mas sinceramente fora o primeiro erro que tinha na .jsp o resto está correto, muito estranho mesmo não estar funcionando...

Abraços!

Oi Geovani. Como também não estou conseguindo encontrar onde está com o problema, baixei o projeto pronto da aula 11 para continuar o curso a partir daí. Agora consigo visualizar as páginas dos produtos, mas não consigo mais cadastrar um produto novo através do formulário. Aparece o seguinte erro:

GRAVE: Servlet.service() for servlet [dispatcher] in context with path [/casadocodigo] threw exception [Request processing failed; nested exception is java.lang.RuntimeException: java.io.IOException: java.io.FileNotFoundException: C:\Users\rodri\eclipse-workspace\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps\casadocodigo\arquivos-sumario (Acesso negado)] with root cause
java.io.FileNotFoundException: C:\Users\rodri\eclipse-workspace\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps\casadocodigo\arquivos-sumario (Acesso negado)

Tem como arrumar isso?

Eu fiz um teste agora e cadastrei um produto com envio de arquivo e funcionou... apenas sem enviar o arquivo que ele não cadastra. Então acredito que o projeto esteja funcionando. Vou continuar o curso deste ponto então. Obrigado pela ajuda. :-)

Opa Rodrigo,

Realmente temos esse problema de não cadastrar sem o envio de arquivo, realmente essa abordagem de copiar e colar os arquivos htmls dificultou muito e gerou diversos bugs

Entretanto, a Alura está regravando esses cursos de SpringMVC para ficar na mesma qualidade do API Rest com Springboot e deixar totalmente atualizado, é apensa questão de tempo :)

Abraços e Bons Estudos!!