6
respostas

Java 8 (LocalDate) - Erro ao persistir dado

Ao tentar persistir os dados utilizando a configuração apresentada no exercício (mvcConversionService), o dado não é mais persistido, acusando sempre erro no campo dataLancamento.

Alguém passou por isso? Segue o erro capturado no controller (bindingResult.getAllErrors()):

[Field error in object 'produto' on field 'dataLancamento': rejected value [22/11/1988]; codes [typeMismatch.produto.dataLancamento,typeMismatch.dataLancamento,typeMismatch.java.time.LocalDate,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [produto.dataLancamento,dataLancamento]; arguments []; default message [dataLancamento]]; default message [Failed to convert property value of type 'java.lang.String' to required type 'java.time.LocalDate' for property 'dataLancamento'; nested exception is java.lang.IllegalStateException: Cannot convert value of type 'java.lang.String' to required type 'java.time.LocalDate' for property 'dataLancamento': no matching editors or conversion strategy found]]

Pelo que entendi, ele não está conseguindo converter a string para LocalDate

Failed to convert property value of type 'java.lang.String' to required type 'java.time.LocalDate' for property 'dataLancamento

Segue o código do controller:

@Controller
@RequestMapping("/produto")
public class ProdutoController {

    @Autowired
    private ProdutoRepository produtoRepository;

    @InitBinder
    public void bindValidation(WebDataBinder binder) {
        binder.addValidators(new ProdutoValidator());
    }

    @RequestMapping("/form")
    public ModelAndView form() {
        ModelAndView modelAndView = new ModelAndView("produto/form");
        modelAndView.addObject("tipos", TipoPreco.values());

        return modelAndView;
    }

    @RequestMapping(method = RequestMethod.POST)
    public ModelAndView save(@Valid Produto produto, BindingResult bindingResult, RedirectAttributes redirectAttributes) {
        ModelAndView retorno;
        if (bindingResult.hasErrors()) {
            retorno = form();
        } else {

            produtoRepository.save(produto);

            redirectAttributes.addFlashAttribute("successMessage", "Produto cadastrado com sucesso!");

            retorno = new ModelAndView("redirect:/produto");
        }

        return retorno;
    }

    @RequestMapping(method = RequestMethod.GET)
    public ModelAndView list() {
        List<Produto> produtos = produtoRepository.list();

        ModelAndView modelAndView = new ModelAndView("produto/list");
        modelAndView.addObject("produtos", produtos);

        return modelAndView;
    }

}

Configuração

@EnableWebMvc
@ComponentScan(basePackageClasses = {HomeController.class, ProdutoRepository.class})
public class AppConfig {

    @Bean
    public InternalResourceViewResolver internalResourceViewResolver() {
        InternalResourceViewResolver resolver = new InternalResourceViewResolver();
        resolver.setPrefix("/WEB-INF/views/");
        resolver.setSuffix(".jsp");
        return resolver;
    }

    @Bean
    public MessageSource messageSource() {
        ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
        messageSource.setBasename("/WEB-INF/messages");
        messageSource.setDefaultEncoding("UTF-8");
        messageSource.setCacheSeconds(1);

        return messageSource;
    }

    @Bean
    public FormattingConversionService mvcConversionService() {
        FormattingConversionService conversionService = new FormattingConversionService();

        DateFormatterRegistrar formatterRegistrar = new DateFormatterRegistrar();
        formatterRegistrar.setFormatter(new DateFormatter("dd/MM/yyyy"));

        formatterRegistrar.registerFormatters(conversionService);

        return conversionService;
    }
}

Modelo:

@Entity
public class Produto {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    Long id;

    String titulo;
    String descricao;
    int paginas;

    @ElementCollection
    List<Preco> precos;

    @DateTimeFormat
    LocalDate dataLancamento;

    //getters e setters
}
6 respostas

Pode ser que a versão do spring usada ainda não dê suporte a LocalDate... pode ser também que o formato de data que está vindo na requisição não é o mesmo definido. Se você usou o campo de formulário do tipo date, o formato é yyyy-MM-dd

Eu usei um input type='text', então no formato eu estou passando o valor no formato (ex: 11/01/2017)

Será que pode ser a versão do spring? Estou na 4.3.8.RELEASE (spring spring-webmvc e spring-orm). Eu tentei a mesma coisa, porém com o atributo anotado com @DateTimeFormat(pattern = "dd/MM/yyyy") e funcionou normal...

Você tem alguma ideia?

Opa, preciso tentar isolar o caso, olhando assim não vejo motivo para não funcionar :(.

Alberto, subi o código no github, se vc puder dar uma olhada e conseguir me ajudar com o que está acontecendo, seria de grande ajuda:

https://github.com/jmsstudio/aprendendo-spring-mvc

Opa, olhei o projeto aqui... A configuração realmente não é aplicada quando você usa o LocalDate... troquei para Calendar e funcionou... acho que é apenas um fato que vamos precisar lidar...

Alberto, eu tentei também incluir um converter, mas não funcionou...

Você tem alguma ideia de algo que possa funcionar? Até agora ele ta funcionando com o atributo anotado com @DateTimeFormat(pattern = "dd/MM/yyyy")

Mas o ponto do exercício era justamente não colocar a anotação em todos os atributos, deixar isso global na aplicação...