Solucionado (ver solução)
Solucionado
(ver solução)
1
resposta

No mapping for GET /produtos/produtos (mapeamento duplicado)

Boa segunda de carnaval prezados, quem mais esta aproveitando o feriado para estudar??? xP

Tive problemas na aula 7 do curso Spring MVC I.

Meu projeto esta ligeiramente diferente do existente no curso pois estou usando springboot e h2 como banco, e o padrao repository ao inves do Dao para persistir os dados, mas creio que o erro nao se deva a isto.

O meu problema ocorre quando tento salvar um produto a partir do form de cadastro, ele tenta fazer um get para produtos/produtos apos o controller passar pelo metodo grava e persistir com sucesso os dados em banco. Sendo o problema a partir do return new ModelAndView("redirect:produtos");

Meu ProdutosController esta assim:

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.GetMapping;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import br.com.casadocodigo.loja.models.Produto;
import br.com.casadocodigo.loja.models.TipoPreco;
import br.com.casadocodigo.loja.repository.ProdutosRepository;
import br.com.casadocodigo.loja.validation.ProdutoValidation;

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

    @Autowired
    private ProdutosRepository repository;

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

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

    @PostMapping
    public ModelAndView grava(@Valid Produto produto, BindingResult result, RedirectAttributes redirectAttributes) {
        if(result.hasErrors())
            return form(produto);
        repository.save(produto);
        redirectAttributes.addFlashAttribute("sucesso", "Produto cadastrado com sucesso!");

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

    @GetMapping
    public ModelAndView lista() {
        List<Produto> produtos = repository.findAll();
        ModelAndView modelAndView = new ModelAndView("/produtos/lista");
        modelAndView.addObject("produtos", produtos);

        return modelAndView;
    }
}

Meu form esta assim:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form" %>
<%@ taglib uri="http://www.springframework.org/tags" prefix="s" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Livros de Java, Android, iPhone, Ruby, PHP e muito mais - Casa do Código</title>
</head>
<body>

    <form:form action="${s:mvcUrl('PC#grava').build() }" method="POST" modelAttribute="produto">
        <div>
            <label>Titulo</label>
            <form:errors path="titulo" />
            <form:input path="titulo" />
        </div>
        <div>
            <label>Descricao</label>
            <form:errors path="descricao" />
            <form:textarea path="descricao" rows="10" cols="20" />
        </div>
        <div>
            <label>Paginas</label>
            <form:errors path="paginas" />
            <form:input path="paginas" />
        </div>
        <div>
            <label>Data de Lancamento</label>
            <form:errors path="dataLancamento" />
            <form:input path="dataLancamento" />
        </div>
        <c:forEach items="${tipos }" var="tipoPreco" varStatus="status">
            <div>
                <label>${tipoPreco }</label>
                <form:input path="precos[${status.index }].valor" />
                <form:hidden path="precos[${status.index }].tipo" value="${tipoPreco }" />
            </div>
        </c:forEach>
        <button type="submit">Cadastrar</button>
    </form:form>

</body>
</html>

Parece que estourei o limite de caracteres, se acharem necessario posto o meu pom.xml e meu application.properties para olharem em comentarios. mas basicamente as diferencas esclareci acima.

1 resposta
solução!

Resolvido, por algum motivo preciso em meu codigo usar o /produtos no redirect ficando o retorno do metodo grava do ProdutosController:

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