I'm trying to read a CSV file with dates with Spring Batch, but I am having trouble parsing a date into a LocalDateTime Object:
Field error in object 'target' on field 'date': rejected value [2017-07-20 04:15:25.0]; codes [typeMismatch.target.date,typeMismatch.date,typeMismatch.java.time.LocalDateTime,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [target.date,date]; arguments []; default message [date]]; default message [Failed to convert property value of type 'java.lang.String' to required type 'java.time.LocalDateTime' for property 'date'; nested exception is java.lang.IllegalStateException: Cannot convert value of type 'java.lang.String' to required type 'java.time.LocalDateTime' for property 'date': no matching editors or conversion strategy found]
Main.java:
public class Main {
    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext(SpringBatchDateParseConfig.class);
        JobLauncher jobLauncher = context.getBean(JobLauncher.class);
        Job job = context.getBean("job", Job.class);
        JobParameters jobParameters = new JobParametersBuilder().toJobParameters();
        try {
            JobExecution jobExecution = jobLauncher.run(job, jobParameters);
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    }
}
SpringBatchDateParseConfig.java:
@Configuration
@EnableBatchProcessing
public class SpringBatchDateParseConfig {
    @Inject
    private JobBuilderFactory jobBuilderFactory;
    @Inject
    private StepBuilderFactory stepBuilderFactory;
    @Bean
    public Step step1() {
        return stepBuilderFactory.get("step1")
                                 .<TestClass, TestClass>chunk(2)
                                 .reader(testClassItemReader())
                                 .writer(testClassItemWriter())
                                 .build();
    }
    @Bean
    public Job job(Step step1) {
        return jobBuilderFactory.get("job")
                .start(step1)
                .build();
    }
    @Bean
    FlatFileItemReader<TestClass> testClassItemReader() {
        FlatFileItemReader<TestClass> flatFileItemReader = new FlatFileItemReader<>();
        flatFileItemReader.setResource(new ClassPathResource("test.csv"));
        flatFileItemReader.setLinesToSkip(1);
        DefaultLineMapper defaultLineMapper = new DefaultLineMapper();
        DelimitedLineTokenizer delimitedLineTokenizer = new DelimitedLineTokenizer();
        delimitedLineTokenizer.setNames(new String[]{"foo", "bar", "date"});
        BeanWrapperFieldSetMapper<TestClass> fieldSetMapper = new BeanWrapperFieldSetMapper<>();
        fieldSetMapper.setTargetType(TestClass.class);
        defaultLineMapper.setLineTokenizer(delimitedLineTokenizer);
        defaultLineMapper.setFieldSetMapper(fieldSetMapper);
        flatFileItemReader.setLineMapper(defaultLineMapper);
        return flatFileItemReader;
    }
    @Bean
    ItemWriter<TestClass> testClassItemWriter() {
        return new ItemWriter<TestClass>() {
            @Override
            public void write(List<? extends TestClass> items) throws Exception {
                for (TestClass TestClass : items) {
                    System.out.println(TestClass.toString());
                }
            }
        };
    }
}
TestClass.java:
public class TestClass {
    private String foo;
    private String bar;
    @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME, pattern = "yyyy-MM-dd H:m:s.S")
    private LocalDateTime date;
    public String getFoo() {
        return foo;
    }
    public void setFoo(String foo) {
        this.foo = foo;
    }
    public String getBar() {
        return bar;
    }
    public void setBar(String bar) {
        this.bar = bar;
    }
    public LocalDateTime getDate() {
        return date;
    }
    public void setDate(LocalDateTime date) {
        this.date = date;
    }
}
test.csv:
foo,bar,date
asdf,fdsa,2017-07-20 04:15:25.0
qwerty,ytrewq,2017-07-20 04:15:25.0
Am I missing something?
You can override method initBinder of BeanWrapperFieldSetMapper<T>:
public class BeanWrapperFieldSetMapperCustom<T> extends BeanWrapperFieldSetMapper<T> {
    @Override
    protected void initBinder(DataBinder binder) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
        binder.registerCustomEditor(LocalDate.class, new PropertyEditorSupport() {
            @Override
            public void setAsText(String text) throws IllegalArgumentException {
                if (StringUtils.isNotEmpty(text)) {
                    setValue(LocalDate.parse(text, formatter));
                } else {
                    setValue(null);
                }
            }
            @Override
            public String getAsText() throws IllegalArgumentException {
                Object date = getValue();
                if (date != null) {
                    return formatter.format((LocalDate) date);
                } else {
                    return "";
                }
            }
        });
    }
}
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With