Boa Noite, estou com o seguinte problema, muitíssimo chato, o Spring não está conseguindo CONVERTER o <form:input type="date" para o Calendar da minha "Entity", já tentei de diversas formas e nada, e por isso solicito mais uma vez a ajuda de vocês se possível, a exception:
org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBindingResult: 1 errors
Field error in object 'produtoPorFornecedor' on field 'dataVencimento': rejected value [2017-07-10]; codes [typeMismatch.produtoPorFornecedor.dataVencimento,typeMismatch.dataVencimento,typeMismatch.java.util.Calendar,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [produtoPorFornecedor.dataVencimento,dataVencimento]; arguments []; default message [dataVencimento]]; default message [Failed to convert property value of type 'java.lang.String' to required type 'java.util.Calendar' for property 'dataVencimento'; nested exception is org.springframework.core.convert.ConversionFailedException: Failed to convert from type java.lang.String to type @org.springframework.format.annotation.DateTimeFormat java.util.Calendar for value '2017-07-10'; nested exception is java.lang.IllegalArgumentException: Unable to parse '2017-07-10']
at org.springframework.web.method.annotation.ModelAttributeMethodProcessor.resolveArgument(ModelAttributeMethodProcessor.java:112)
at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:79)
at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:157)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:124)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:781)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:721)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:83)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:943)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:877)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:961)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:863)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:661)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:837)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:742)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:88)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:118)
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:84)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:113)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:103)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:113)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:154)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:45)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:199)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:110)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.csrf.CsrfFilter.doFilterInternal(CsrfFilter.java:105)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:57)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:50)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:192)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:344)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:261)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:199)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:475)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:80)
at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:624)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:498)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:796)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1368)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Unknown Source)
JSP: (Se eu enviar a data sem o "type=date" ai o spring consegue converter, mas com o DATE ele deixa de uma forma fácil para colocar a data, gostaria de saber se tem como resolver esse erro)
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib tagdir="/WEB-INF/tags" prefix="tags" %>
<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form" %>
<%@ taglib uri="http://www.springframework.org/tags" prefix="s" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<tags:pageTemplate titulo="Dar Baixa">
<form:form action="${s:mvcUrl('EAC#adicionaAvariados').build()}" method="POST" commandName="produtoPorFornecedor" >
<div class="container">
<div class="form-group">
<label>Empresa</label>
<select name="empresa.nome" >
<c:forEach items="${empresas}" var="empresaLista">
<option>
${empresaLista.nome}
</option>
</c:forEach>
</select>
</div>
<!-- Busca todos os fornecedores e coloca em um ListBox -->
<div class="form-group">
<label>Fornecedor</label>
<select name="fornecedor.nome">
<c:forEach items="${fornecedores}" var="fornecedor">
<option>${fornecedor.nome}</option>
</c:forEach>
</select>
</div>
<div class="form-group">
<label>Quantidade</label>
<form:input path="quantidadeTotal" class="form-control" />
</div>
<div class="form-group">
<label>Código de Barra</label>
<form:input path="produto.codBarra" class="form-control" />
</div>
<div class="form-group">
<label>Descrição Produto</label>
<form:input path="produto.nome" class="form-control" />
</div>
<div class="form-group">
<label>Data Vencido</label>
<form:input type="date" path="dataVencimento" class="form-control" />
</div>
<button type="submit" class="btn btn-primary">Cadastrar</button>
</div>
</form:form>
${sucesso}
</tags:pageTemplate>
ENTIDADE --------------------------------
package br.com.model;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import org.springframework.format.annotation.DateTimeFormat;
@Entity
public class ProdutoPorFornecedor {
/*
* Fornecedor terá um List dessa classe para indicar quantidadeTotal de produtos por FORNECEDOR
*/
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private Long id;
@ManyToOne
private Produto produto;
@ManyToOne(fetch=FetchType.EAGER)
private Fornecedor fornecedor;
private int quantidadeTotal;
@DateTimeFormat
private Calendar dataVencimento;
@ManyToOne
private Empresa empresa;
// CONSTRUCTOR
@Deprecated
public ProdutoPorFornecedor() {
}
public ProdutoPorFornecedor(Long id) {
this.id = id;
}
// GET / SET
public Empresa getEmpresa() {
return empresa;
}
public void setEmpresa(Empresa empresa) {
this.empresa = empresa;
}
public Calendar getDataVencimento() {
return dataVencimento;
}
public void setDataVencimento(Calendar dataVencimento) {
this.dataVencimento = dataVencimento;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Produto getProduto() {
return produto;
}
public void setProduto(Produto produto) {
this.produto = produto;
}
public Fornecedor getFornecedor() {
return fornecedor;
}
public String getFornecedorNome() {
return fornecedor.getNome();
}
public void setFornecedor(Fornecedor fornecedor) {
this.fornecedor = fornecedor;
}
public int getQuantidadeTotal() {
return quantidadeTotal;
}
public void setQuantidadeTotal(int quantidadeTotal) {
this.quantidadeTotal += quantidadeTotal;
}
}
CONTROLLER---------------------------------
package br.com.controller;
import javax.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import br.com.dao.EmpresaDAO;
import br.com.dao.FornecedorDAO;
import br.com.dao.ProdutoDAO;
import br.com.dao.ProdutoPorFornecedorDAO;
import br.com.model.Empresa;
import br.com.model.Produto;
import br.com.model.ProdutoPorFornecedor;
@Controller
@RequestMapping("/entradaAvariados")
@Scope(value=WebApplicationContext.SCOPE_REQUEST) // OLHAR INFO (BEAN/SCOPE) = Aqui diz que cada usuário que faça uma REQUISIÇÃO que utilize essa classe, irá instânciar essa classe para cada usuário. (Por padrão seria utilizado essa mesma classe com a mesma requisição para todos os usuários)
public class EntradaAvariadosController {
@Autowired
private EmpresaDAO empresaDao;
@Autowired
private ProdutoDAO produtoDao;
@Autowired
private FornecedorDAO fornecedorDao;
@Autowired
private ProdutoPorFornecedorDAO produtoPorFornecedorDao;
// Tela de entrada dos AVARIADOS
@RequestMapping(method=RequestMethod.GET)
public ModelAndView indexAvariados(ProdutoPorFornecedor produtoPorFornecedor){
// Busca todos fornecedores
ModelAndView mv = new ModelAndView("entradas/entrada_avariados");
mv.addObject("fornecedores",fornecedorDao.findAll());
mv.addObject("empresas",empresaDao.findAll());
return mv;
}
// MÉTODOS
@RequestMapping(value="add",method=RequestMethod.POST)
@CacheEvict(value={"AllProdutos" , "produtoEspecifico", "AllEntradas", "entradaEspecifica", "entradaEspecifica2"}, allEntries=true)
public ModelAndView adicionaAvariados(ProdutoPorFornecedor produtoPorFornecedor, HttpServletRequest req, RedirectAttributes attributes){
gravaAlteracoes(produtoPorFornecedor, req);
// produtoPorFornecedorDao.grava(produtoPorFornecedor); // (Ainda está fazendo 1 busca para cada OBJECT dentro dele, e depois fazendo o insert (Por enquanto))
ModelAndView mv = new ModelAndView("redirect:/entradaAvariados");
attributes.addFlashAttribute("sucesso", "Fornecedor adicionado com sucesso");
return mv;
}
private void gravaAlteracoes(ProdutoPorFornecedor produtoPorFornecedor, HttpServletRequest req) {
String empresaNome = req.getParameter("empresa.nome");
String fornecedorNome = req.getParameter("fornecedor.nome");
String produtoCodBarra = req.getParameter("produto.codBarra");
String produtoNome = req.getParameter("produto.nome");
Empresa empresa = empresaDao.find(empresaNome);
Produto produto = produtoDao.find(produtoCodBarra, produtoNome, empresaNome, fornecedorNome);
System.out.println("PASSOU PRODUTO");
produtoPorFornecedorDao.find(empresa, fornecedorNome, produtoPorFornecedor, produto, produtoPorFornecedor.getQuantidadeTotal());
}
}
CONF - WEB
package br.com.conf;
import java.util.concurrent.TimeUnit;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.guava.GuavaCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
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.client.RestTemplate;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import com.google.common.cache.CacheBuilder;
import br.com.controller.HomeController;
import br.com.dao.FornecedorDAO;
import br.com.model.Fornecedor;
@EnableWebMvc // Indica que essa classe trata todos os trabalhos referente WEB do SPRING
@ComponentScan(basePackageClasses={HomeController.class, Fornecedor.class, FornecedorDAO.class}) // Colocar uma classe de cada package que utilize annotation do SPRING, ex: (@Controller, @Repository, @File)
@EnableCaching
public class AppWebConfiguration extends WebMvcConfigurerAdapter {
// Mostra ao SPRING o local das VIEWS
@Bean
public InternalResourceViewResolver internalResourceViewResolver(){
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/views/"); // Local das Views
resolver.setSuffix(".jsp"); // Tirando a obrigatoriedade de digitar ".jsp" ao se referênciar a uma view
return resolver;
}
// Para que o spring libere as requisições referentes ao CSS/FONTS/SCRIP (Método herdado de WebMvcConfigurerAdapter)
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
// FAZENDO QUE A FORMATAÇÃO(pattern) DO @DateTimeFormat SEJA POR DEFAULT ABAIXO:
@Bean
public FormattingConversionService mvcConversionService(){
DefaultFormattingConversionService conversionService =
new DefaultFormattingConversionService(); // Responsável pelo serviço de conversão de formato.
DateFormatterRegistrar registrar = new DateFormatterRegistrar();
registrar.setFormatter(new DateFormatter("yyyy/MM/dd")); // Fará o registro do formato de data usado para a conversão. Este segundo objeto espera receber outro objeto do tipo DateFormatter que será quem efetivamente guarda o padrão da data
registrar.registerFormatters(conversionService); // Usar o registrador para registar o padrão de data no serviço de conversão.
return conversionService; // Como agora ele está "Registrado" pode retorna-lo, pois agora ele tem o "pattern" padrão.
}
// 1.2 CACHÊ MANAGER - PARA HABILITAR O "Cacheable" (Ensinando para o Spring, para que o spring consiga injetar o Cacheable)
@Bean
public CacheManager cacheManager(){
// return new ConcurrentMapCacheManager(); // (Utilizado para testes) Criando um MAP(KEY,VALUE) para guardar nosso CACHE em um CACHE MANAGER
CacheBuilder<Object, Object> builder = CacheBuilder.newBuilder() // 1.1 CRIA UM CACHE MANAGER
.maximumSize(100).expireAfterAccess(5, TimeUnit.MINUTES); // 1.2 ESPECIFICA O TAMANHO MÁXIMO DE ELEMENTOS QUE CABE NESSE "CACHE MANAGER" e ESPECIFICANDO QUE IRÁ EXPIRAR ESSE CACHÊ EM 5 MINUTOS (Mas em produção pode botar para 1 dia)
GuavaCacheManager manager = new GuavaCacheManager();
manager.setCacheBuilder(builder); // 1.3 Guarda o CACHE MANAGER criado, dentro do GUAVA do google e retorna (É preciso colocar as DEPENDENCY do GUAVA).
return manager;
}
// CRIADO PARA QUE O SPRING SAIBA INJETAR A DEPENDÊNCIA REFERENTE A ESSA CLASS (JPAProductionConfiguration)
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
}