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

Spring não converte MultipartFile para String

Todas as vezes que mando o arquivo para o servidor o objeto do BindingResult me retorna esse erro:

org.springframework.validation.BeanPropertyBindingResult: 1 errors Field error in object 'produto' on field 'capa': rejected value [org.springframework.web.multipart.support.StandardMultipartHttpServletRequest$StandardMultipartFile@6f7c32fb]; codes [typeMismatch.produto.capa,typeMismatch.capa,typeMismatch.java.lang.String,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [produto.capa,capa]; arguments []; default message [capa]]; default message [Failed to convert property value of type 'org.springframework.web.multipart.support.StandardMultipartHttpServletRequest$StandardMultipartFile' to required type 'java.lang.String' for property 'capa'; nested exception is java.lang.IllegalStateException: Cannot convert value of type [org.springframework.web.multipart.support.StandardMultipartHttpServletRequest$StandardMultipartFile] to required type [java.lang.String] for property 'capa': no matching editors or conversion strategy found]

Basicamente o erro diz que não consegue fazer a conversão de um multpart para uma String..... Até agora estou tentando entende o pq. Qualquer ajuda é bem-vinda

Segue as classes criadas:

Cara eu fiz isso tá aqui o código:

Produtos:

package br.com.casadocodigo.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 int paginas;

    private String autor;

    @ElementCollection
    //Diz que essa lista é uma composição e que os indices dessa lista são atributos da classe e da tabela

    private List<Preco> precos;

    @DateTimeFormat

    private Calendar dataDeLancamento;

    private String capa; 

    public List<Preco> getPrecos() {

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

        this.precos = precos;
    }
    public int getId() {

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

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

        return paginas;
    }
    public void setPaginas(int paginas) {

        this.paginas = paginas;
    }
    public String getAutor() {

        return autor;
    }
    public void setAutor(String autor) {

        this.autor = autor;
    }

    public Calendar getDataDeLancamento() {

        return dataDeLancamento;
    }
    public void setDataDeLancamento(Calendar dataDeLancamento) {

        this.dataDeLancamento = dataDeLancamento;
    }


    public String getCapa() {

        return capa;
    }
    public void setCapa(String capa) {

        this.capa = capa;
    }
    @Override

    public String toString() {

        return "Produto [titulo=" + titulo + ", paginas=" + paginas + ", autor=" + autor + "]";
    }
}
/-------------------------------------------------------------------/ ProdutosContorller:

package br.com.casadocodigo.controlles;

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.dao.ProdutoDAO;
import br.com.casadocodigo.infra.FileSaver;
import br.com.casadocodigo.models.Produto;
import br.com.casadocodigo.models.TipoPreco;
import br.com.casadocodigo.validation.ProdutoValidation;

@Controller
@RequestMapping("/produtos")

public class ProdutosController {

    @Autowired

    private ProdutoDAO pDAO;

    @Autowired

    private FileSaver fs;

    @InitBinder

    private void initBinder(WebDataBinder binder) {

        binder.addValidators( new ProdutoValidation());

    }

    @RequestMapping("cadastraproduto")

    public ModelAndView cadastraProduto(Produto p){

        ModelAndView mav = new 
ModelAndView("produtos/cadastraproduto");

        mav.addObject("tipos", TipoPreco.values());
        return mav ;

    }

    @RequestMapping(method=RequestMethod.POST)

    public ModelAndView gravar(MultipartFile capa,@Valid Produto p, 

BindingResult result, RedirectAttributes produtocadastrado){

        if(result.hasErrors()){

            return cadastraProduto(p);

        }
        System.out.println(capa.getOriginalFilename()); 

        String path = fs.write("capas", capa);

        p.setCapa(path);

        pDAO.gravar(p);

        produtocadastrado.addFlashAttribute("produtocadastrado", "Livro 

"+ p.getTitulo() + " Cadastrado com sucesso"); 

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

    @RequestMapping(method=RequestMethod.GET)

    public ModelAndView listar(){

        List<Produto> produtos = pDAO.listar();

        ModelAndView mav = new 

ModelAndView("produtos/listarprodutos");

        mav.addObject("produtos", produtos); 

        return mav;
    }

}
/------------------------------------------------------------/ FileSaver:

package br.com.casadocodigo.infra;

import java.io.File;
import java.io.IOException;

import javax.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

@Component
public class FileSaver {

    @Autowired

    public HttpServletRequest request; 


    public String write(String pastaBase, MultipartFile file){

        try {

            String realPath = 

request.getServletContext().getRealPath("/"+pastaBase);

            String path = realPath +"/" + file.getOriginalFilename();

            file.transferTo(new File(path));

            return pastaBase + "/" + file.getOriginalFilename();



        } catch (IllegalStateException | IOException e) {

            throw new RuntimeException(e);
        }
    }
}
/------------------------------------------------------------/ AppWebConfiguration:

package br.com.casadocodigo.conf;

import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.support.ReloadableResourceBundleMessageSource;
import org.springframework.format.datetime.DateFormatter;
import org.springframework.format.datetime.DateFormatterRegistrar;
import org.springframework.format.support.DefaultFormattingConversionService;
import org.springframework.format.support.FormattingConversionService;
import org.springframework.web.multipart.MultipartResolver;
import org.springframework.web.multipart.support.StandardServletMultipartResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.view.InternalResourceViewResolver;

import br.com.casadocodigo.controlles.HomeController;
import br.com.casadocodigo.dao.ProdutoDAO;
import br.com.casadocodigo.infra.FileSaver;

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


    @Bean

    public InternalResourceViewResolver internalResourceViewResolver(){

        InternalResourceViewResolver resolver = new 

InternalResourceViewResolver();

        resolver.setPrefix("/WEB-INF/views/");

        resolver.setSuffix(".jsp");

        return resolver;
    }

     @Bean

     public MessageSource messageSource() {

         ReloadableResourceBundleMessageSource ms =

                 new ReloadableResourceBundleMessageSource();

         ms.setBasename("/WEB-INF/messages");

         ms.setDefaultEncoding("UTF-8");

         ms.setCacheSeconds(1);

         return ms;
     }


     @Bean

     public FormattingConversionService mvcConversionService(){

         DefaultFormattingConversionService dataDefault = new 

DefaultFormattingConversionService();

         DateFormatterRegistrar registrar = new DateFormatterRegistrar(); 

         registrar.setFormatter(new DateFormatter("dd/MM/yyyy"));

         registrar.registerFormatters(dataDefault);

         return dataDefault;

     }

 @Bean 

     public MultipartResolver multipartResolver(){

         return new StandardServletMultipartResolver();
     }
}
/--------------------------------------------------------------------/ ServletSpringMVC:

package br.com.casadocodigo.conf;

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

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

public class ServletSpringMVC extends 

AbstractAnnotationConfigDispatcherServletInitializer{

    @Override

    protected Class<?>[] getRootConfigClasses() {

        // TODO Auto-generated method stub
        return null;
    }

    @Override

    protected Class<?>[] getServletConfigClasses() {

        // TODO Auto-generated method stub

        return new Class[] 

{AppWebConfiguration.class,JPAConfiguration.class};
    }

    @Override

    protected String[] getServletMappings() {

        // TODO Auto-generated method stub

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

    @Override

    protected Filter[] getServletFilters() {

        CharacterEncodingFilter encoding = new CharacterEncodingFilter();

        encoding.setEncoding("UTF-8");

        return new Filter[] {encoding};
    }

    protected void customizeRegistration(Dynamic registration) {

        registration.setMultipartConfig(new MultipartConfigElement(""));

    }

}

/----------------------------------------------------------------/ cadastraprodutos.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" prefix="t"%>
<%@ taglib uri="http://www.springframework.org/tags/form" prefix="f"%>

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Casa do Código</title>
</head>
<body>

    <f:form action="${t:mvcUrl('PC#gravar').build()}" method="POST"
    commandName="produto" enctype="multipart/form-data">
        <div>
            <label>Titulo do Livro</label>
            <f:input path="titulo"/>
            <f:errors path = "titulo"/>
        </div>

        <div>
            <label>Autor</label>
            <f:input path="autor" />
            <f:errors path = "autor"/>
        </div>

        <div>
            <label>Nº de páginas</label>
            <f:input path="paginas" />
            <f:errors path = "paginas"/>
        </div>

        <div>
            <label>Data de Lançamento</label>
            <f:input path="dataDeLancamento"/>
            <f:errors path="dataDeLancamento"/>
        </div>

        <c:forEach items="${tipos}" var="tipoPreco"  varStatus="st">
            <label>${tipoPreco}</label>
            <f:input path="precos[${st.index}].valor"/>
            <f:hidden path="precos[${st.index}].tipo" value="${tipoPreco}" />
        </c:forEach>

        <div>
            <label>Capa do Livro</label>
            <input name="capa" type="file">
            <f:errors path="capa"/>    
        </div>

        <button type="submit">Cadastrar</button>
</f:form>

</body>
</html>

Fiz tudo que manda o Curso de SpringMVC mas ainda sim não funciona.... pf alguém me de uma luz!!!

Att, Pedro

2 respostas
solução!

Ola Pedro,

Seu modelo Produto já tem uma propriedade (String) chamada capa. E a referência do MultipartFile que você quer receber no controller também chama capa. Desta forma o Spring está se perdendo:

@RequestMapping(method=RequestMethod.POST)
public ModelAndView gravar(MultipartFile capa, @Valid Produto produto, BindingResult result, RedirectAttributes produtocadastrado){
    ...
}

O spring está tentando passar a referência do arquivo (<input type="file" name="capa">) para a propriedade capa do Produto, dando erro de conversão.

Altere o nome da propriedade no produto por algum outro - arquivoCapa - por exemplo, assim como seus getters and setters. Assim o Spring já vai entender que a referência não é do Produto e sim do MultipartFile capa no método do controller.

Espero ter ajudado. Abraço!

Cara, muito obrigado!!!

Quer mergulhar em tecnologia e aprendizagem?

Receba a newsletter que o nosso CEO escreve pessoalmente, com insights do mercado de trabalho, ciência e desenvolvimento de software