Solucionado (ver solução)
Solucionado
(ver solução)
3
respostas

Formulário bootstrap não funciona

Ao tentar colocar css nas divs e inputs do form, aparece o seguinte erro:

Exception

org.apache.jasper.JasperException: An exception occurred processing [/WEB-INF/views/produtos/form.jsp] at line [39]

36:         <form:form action="${s:mvcUrl('PC#gravar').build() }" method="post" modelAttribute="produto" enctype="multipart/form-data">
37:             <div class="form-group">
38:                 <label>Título</label>
39:                 <form:input path="titulo" cssClass="form-control" />
40:                 <form:errors path="titulo" />
41:             </div>
42:             <div class="form-group">


Stacktrace:
    org.apache.jasper.servlet.JspServletWrapper.handleJspException(JspServletWrapper.java:626)
    org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:510)
    org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:385)
    org.apache.jasper.servlet.JspServlet.service(JspServlet.java:329)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
    org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
    org.springframework.web.servlet.view.InternalResourceView.renderMergedOutputModel(InternalResourceView.java:171)
    org.springframework.web.servlet.view.AbstractView.render(AbstractView.java:316)
    org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1373)
    org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1118)
    org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1057)
    org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943)
    org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
    org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:634)
    org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
    org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
    org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
    org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
Root Cause

java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'produto' available as request attribute
    org.springframework.web.servlet.support.BindStatus.<init>(BindStatus.java:153)
    org.springframework.web.servlet.tags.form.AbstractDataBoundFormElementTag.getBindStatus(AbstractDataBoundFormElementTag.java:178)
    org.springframework.web.servlet.tags.form.AbstractDataBoundFormElementTag.getPropertyPath(AbstractDataBoundFormElementTag.java:199)
    org.springframework.web.servlet.tags.form.AbstractDataBoundFormElementTag.getName(AbstractDataBoundFormElementTag.java:164)
    org.springframework.web.servlet.tags.form.AbstractDataBoundFormElementTag.autogenerateId(AbstractDataBoundFormElementTag.java:149)
    org.springframework.web.servlet.tags.form.AbstractDataBoundFormElementTag.resolveId(AbstractDataBoundFormElementTag.java:139)
    org.springframework.web.servlet.tags.form.AbstractDataBoundFormElementTag.writeDefaultAttributes(AbstractDataBoundFormElementTag.java:122)
    org.springframework.web.servlet.tags.form.AbstractHtmlElementTag.writeDefaultAttributes(AbstractHtmlElementTag.java:460)
    org.springframework.web.servlet.tags.form.InputTag.writeTagContent(InputTag.java:357)
    org.springframework.web.servlet.tags.form.AbstractFormTag.doStartTagInternal(AbstractFormTag.java:87)
    org.springframework.web.servlet.tags.RequestContextAwareTag.doStartTag(RequestContextAwareTag.java:83)
    org.apache.jsp.WEB_002dINF.views.produtos.form_jsp._jspx_meth_form_005finput_005f0(form_jsp.java:463)
3 respostas

Código JSP

<%@ 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, PHP e muito mais</title>

<c:url value="/resources/css" var="cssPath"/>
<link rel="stylesheet" href="${cssPath}/bootstrap.min.css">
<link rel="stylesheet" href="${cssPath}/bootstrap-reboot.min.css">
<link rel="stylesheet" href="${cssPath}/bootstrap-grid.min.css">
<link rel="stylesheet" href="${cssPath}/style.css">
</head>
<body>

    <div class="container">

        <nav class="navbar navbar-expand-lg navbar-light bg-light">
          <a class="navbar-brand" href="#">Casa do Código</a>
          <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNavAltMarkup" aria-controls="navbarNavAltMarkup" aria-expanded="false" aria-label="Toggle navigation">
            <span class="navbar-toggler-icon"></span>
          </button>
          <div class="collapse navbar-collapse" id="navbarNavAltMarkup">
            <div class="navbar-nav">
              <a class="nav-item nav-link active" href="${s:mvcUrl('PC#listar').build() }">Listar<span class="sr-only">(current)</span></a>
              <a class="nav-item nav-link" href="${s:mvcUrl('PC#form').build() }">Cadastrar</a>
            </div>
          </div>
        </nav>

        <h1>Cadastro de Produto</h1>
        <form:form action="${s:mvcUrl('PC#gravar').build() }" method="post" modelAttribute="produto" enctype="multipart/form-data">
            <div class="form-group">
                <label>Título</label>
                <form:input path="titulo" cssClass="form-control" />
                <form:errors path="titulo" />
            </div>
            <div class="form-group">
                <label>Descrição</label>
                <form:textarea path="descricao" cssClass="form-control" />
                <form:errors path="descricao" />
            </div>
            <div class="form-group">
                <label>Páginas</label>
                <form:input path="paginas" />
                <form:errors path="paginas" />
            </div>
            <div class="form-group">
                <label>Data de Lançamento</label>
                <form:input path="dataLancamento" cssClass="form-control" />
                <form:errors path="dataLancamento" />
            </div>
            <c:forEach items="${tipos}" var="tipoPreco" varStatus="status">
                <div class="form-group">
                    <label>${tipoPreco}</label>
                    <form:input path="precos[${status.index}].valor" cssClass="form-control" />
                    <form:hidden path="precos[${status.index}].tipo" value="${tipoPreco}" />
                </div>
            </c:forEach>

            <div class="form-group">
                <label>Sumário</label>
                <input name="sumario" type="file" class="form-control" />
            </div>
            <button type="submit" class="btn btn-primary">Cadastrar</button>
        </form:form>

    </div>

</body>
</html>

Controller

package br.com.casadocodigo.loja.controllers;

import java.util.List;

import javax.validation.Valid;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
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.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
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 {

    //    Marca o ponto de injeção na classe, é colocada sobre atributos ou construtor com argumentos
    @Autowired
    private ProdutoDAO produtoDao;
    @Autowired
    private FileSaver fileSaver;

    //    Este método fará a ligação entre o @Valid do método grava() e a classe ProdutoValidation
    @InitBinder
    public void initBinder(WebDataBinder binder) {
        binder.addValidators(new ProdutoValidation());

    }

    @RequestMapping("/form")
    public ModelAndView form() {
        ModelAndView modelAndView = new ModelAndView("produtos/form");
        modelAndView.addObject("tipos", TipoPreco.values());
        System.out.println();
        return modelAndView;
    }

    //    O Spring faz o biding, isto é, o name no JSP é igual ao parâmetro no Controller
    @RequestMapping(method=RequestMethod.POST)
    @CacheEvict(value="produtosHome", allEntries = true)
    public ModelAndView gravar(MultipartFile sumario, @Valid Produto produto, BindingResult result, 
            RedirectAttributes redirectAttributes) {

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

        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/{id}")
    public ModelAndView detalhe(@PathVariable("id") Integer id) {
        ModelAndView modelAndView = new ModelAndView("produtos/detalhe");
        Produto produto = produtoDao.find(id);
        modelAndView.addObject("produto", produto);
        return modelAndView;
    }

}
solução!

Problema resolvido.