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

enctype="multipart/form-data" faz o código parar de funcionar

Quando coloco o enctype="multipart/form-data" o meu formulário não é mais validado, e não consigo mais salvar os arquivos no banco de dados. Não aparece nenhuma exceção, mas o título e a descrição não são validados (como se não tivessem sido passados) e se tento fazer um "sysout" nos valores, eles são nulos. Se eu tiro o "enctype," o cadastro anterior volta a funcionar.

Seguem os códigos:

package br.com.casadocodigo.loja.controllers;

import java.util.List;

import javax.transaction.Transactional;
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.dao.ProductDAO;
import br.com.casadocodigo.loja.models.BookType;
import br.com.casadocodigo.loja.models.Product;
import br.com.casadocodigo.loja.validation.ProductValidator;

@RequestMapping("/produtos")
@Controller
@Transactional
public class ProductController {

    @InitBinder
    protected void initBinder(WebDataBinder binder) {
        binder.setValidator(new ProductValidator());
    }

    @Autowired
    private FileSaver fileSaver;

    @Autowired
    private ProductDAO productDAO;

    @RequestMapping(method = RequestMethod.POST, name = "saveProduct")
    public ModelAndView save(MultipartFile summary, @Valid Product product, BindingResult bindingResult, RedirectAttributes attributes) {

        System.out.println(product.getTitle());

        if (bindingResult.hasErrors()) {
            return form(product);
        }

        attributes.addFlashAttribute("sucesso", "Livro cadastrado com sucesso");

        String webPath = fileSaver.write("uploaded-images", summary);
        product.setSummaryPath(webPath);
        productDAO.save(product);
        return new ModelAndView("redirect:produtos");
    }

    @RequestMapping("/form")
    public ModelAndView form(Product product) {
        ModelAndView modelAndView = new ModelAndView("products/form");
        modelAndView.addObject("types", BookType.values());

        return modelAndView;
    }

    @RequestMapping(method = RequestMethod.GET)
    public ModelAndView list() {
        List<Product> products = productDAO.getProducts();
        ModelAndView modelAndView = new ModelAndView("products/list");
        modelAndView.addObject("books", products);
        modelAndView.addObject("prices", BookType.values());

        return modelAndView;
    }

}

Jsp:

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib uri="http://www.springframework.org/tags" prefix="spring"%>
<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form"%>


<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Formulário</title>
</head>
<body>

    <form:form action="/casadocodigo/produtos" method="POST" enctype="multipart/form-data" modelAttribute="product" >
        <div>
            <label for="title">Título</label>
            <form:input path="title"/>
            <form:errors path="title" />
        </div>
        <div>
            <label for="description">Descrição</label>
            <form:textarea rows="10" cols="20" path="description"></form:textarea>
            <form:errors path="description" />
        </div>
        <div>
            <label for="pages">Páginas</label>
            <form:input path="pages" />
            <form:errors path="pages" />
        </div>
        <div>
            <label for="releaseDate">Data de Lançamento</label>
            <form:input type="date" path="releaseDate" />
            <form:errors path="releaseDate" />
        </div>
        <c:forEach items="${types}" var="bookType" varStatus="status">
            <div>
                <label>${bookType}</label> <input type="text"
                    name="prices[${status.index}].value" /> <input type="hidden"
                    name="prices[${status.index}].bookType" value="${bookType}" />
            </div>
        </c:forEach>
        <div>
            <label for="summary">Sumário</label>
            <input type="file" name="summary" />
            <form:errors path="summaryPath"/>
            </div>
        <button type="submit">Cadastrar</button>
    </form:form>
</body>
</html>
4 respostas

Opa, esse é um projeto Spring MVC tradicional, sem spring boot né? Rola você mostrar a classe de configuração do Spring para suportar o Multipart?

É sim, sem spring boot....Claro, seguem as classes

package br.com.casadocodigo.loja.config;

import javax.servlet.MultipartConfigElement;
import javax.servlet.ServletRegistration.Dynamic;

import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;

public class ServletSpringMVC extends AbstractAnnotationConfigDispatcherServletInitializer {

    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class[] { AppWebConfiguration.class, JPAConfiguration.class };
    }

    @Override
    protected Class<?>[] getServletConfigClasses() {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    protected String[] getServletMappings() {

        return new String[] { "/" };
    }

    @Override
    protected void customizeRegistration(Dynamic registration) {
        registration.setMultipartConfig(new MultipartConfigElement(""));

    }
}

E a outra....

@EnableWebMvc
@ComponentScan(basePackageClasses = { HomeController.class, ProductDAO.class, FileSaver.class})
public class AppWebConfiguration {

    @Bean
    public MultipartResolver multipartResolver(){
        return new StandardServletMultipartResolver();
    }

Oi Gabriel, você pode disponibilizar um link com o zip do seu projeto ou colocar no github e me passar o endereço? Tem algum detalhe aí na configuração que meus olhos não estão pegando...

solução!

Alberto, apelei, tava caçando essa resposta tem uns 5 dias, apaguei o projeto e recriei do 0, gastei um tempo....coloquei as classes lado a lado e parece tudo igual, mas desta vez funcionou, talvez alguma coisa de servidor.... Independente disso, muito obrigado pela atenção (te enchi até no twitter). Grande abraço.