{"id":5636,"date":"2025-09-23T14:02:00","date_gmt":"2025-09-23T14:02:00","guid":{"rendered":"https:\/\/codethataint.com\/blog\/?p=5636"},"modified":"2025-09-23T14:04:57","modified_gmt":"2025-09-23T14:04:57","slug":"using-item-reader-and-writer-to-read-and-write-from-csv-json-jdbc-and-flat-text-file","status":"publish","type":"post","link":"https:\/\/codethataint.com\/blog\/using-item-reader-and-writer-to-read-and-write-from-csv-json-jdbc-and-flat-text-file\/","title":{"rendered":"Using Item Reader and Writer to Read and Write from CSV, JSON, JDBC and Flat Text File"},"content":{"rendered":"<p><strong>jobconfig.java<\/strong><\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\npackage com.mugil.org.config;\r\n\r\nimport com.fasterxml.jackson.core.JsonProcessingException;\r\nimport com.fasterxml.jackson.databind.ObjectMapper;\r\nimport com.fasterxml.jackson.databind.SerializationFeature;\r\nimport com.mugil.org.model.Employee;\r\nimport com.mugil.org.model.EmployeeCSV;\r\nimport com.mugil.org.model.EmployeeJSON;\r\nimport com.mugil.org.model.EmployeeJdbc;\r\nimport org.springframework.batch.core.*;\r\nimport org.springframework.batch.core.job.builder.JobBuilder;\r\nimport org.springframework.batch.core.launch.support.RunIdIncrementer;\r\nimport org.springframework.batch.core.repository.JobRepository;\r\nimport org.springframework.batch.core.step.builder.StepBuilder;\r\nimport org.springframework.batch.item.ItemProcessor;\r\nimport org.springframework.batch.item.database.BeanPropertyItemSqlParameterSourceProvider;\r\nimport org.springframework.batch.item.database.JdbcBatchItemWriter;\r\nimport org.springframework.batch.item.database.JdbcCursorItemReader;\r\nimport org.springframework.batch.item.database.builder.JdbcBatchItemWriterBuilder;\r\nimport org.springframework.batch.item.database.builder.JdbcCursorItemReaderBuilder;\r\nimport org.springframework.batch.item.file.FlatFileItemReader;\r\nimport org.springframework.batch.item.file.FlatFileItemWriter;\r\nimport org.springframework.batch.item.file.LineMapper;\r\nimport org.springframework.batch.item.file.builder.FlatFileItemReaderBuilder;\r\nimport org.springframework.batch.item.file.builder.FlatFileItemWriterBuilder;\r\nimport org.springframework.batch.item.file.mapping.BeanWrapperFieldSetMapper;\r\nimport org.springframework.batch.item.file.mapping.DefaultLineMapper;\r\nimport org.springframework.batch.item.file.transform.BeanWrapperFieldExtractor;\r\nimport org.springframework.batch.item.file.transform.DelimitedLineAggregator;\r\nimport org.springframework.batch.item.file.transform.DelimitedLineTokenizer;\r\nimport org.springframework.batch.item.file.transform.LineAggregator;\r\nimport org.springframework.batch.item.json.JacksonJsonObjectReader;\r\nimport org.springframework.batch.item.json.JsonItemReader;\r\nimport org.springframework.batch.item.json.builder.JsonItemReaderBuilder;\r\nimport org.springframework.beans.factory.annotation.Autowired;\r\nimport org.springframework.context.annotation.Bean;\r\nimport org.springframework.context.annotation.Configuration;\r\nimport org.springframework.core.io.FileSystemResource;\r\nimport org.springframework.jdbc.core.BeanPropertyRowMapper;\r\nimport org.springframework.transaction.PlatformTransactionManager;\r\n\r\nimport javax.sql.DataSource;\r\nimport java.util.Date;\r\n\r\n@Configuration\r\npublic class JobConfig {\r\n    @Autowired\r\n    ItemProcessor simpleJobProcessor;\r\n\r\n    @Autowired\r\n    DataSource dataSource;\r\n\r\n    @Bean\r\n    public Job job(JobRepository jobRepository, PlatformTransactionManager transactionManager) {\r\n        return new JobBuilder(&quot;job&quot;, jobRepository)\r\n                .incrementer(new RunIdIncrementer())\r\n                .start(simpleChunkStep(jobRepository, transactionManager))\r\n                .build();\r\n    }\r\n\r\n    @Bean\r\n    public Step simpleChunkStep(JobRepository jobRepository, PlatformTransactionManager transactionManager) {\r\n        StepBuilder stepBuilderOne = new StepBuilder(&quot;Chunk Oriented Step&quot;, jobRepository);\r\n        return stepBuilderOne\r\n                .chunk(3, transactionManager)\r\n                .reader(flatFileItemReader())\r\n                .processor(simpleJobProcessor)\r\n                .writer(jdbcWriter())\r\n                .build();\r\n    }\r\n\r\n    @Bean\r\n    public JsonItemReader&lt;EmployeeJSON&gt; jsonFileReader() {\r\n        return new JsonItemReaderBuilder&lt;EmployeeJSON&gt;()\r\n                .name(&quot;employeeJSONReader&quot;)\r\n                .jsonObjectReader(new JacksonJsonObjectReader&lt;&gt;(EmployeeJSON.class))\r\n                .currentItemCount(1)  \/\/Skip the first item\r\n                .maxItemCount(3) \/\/Limit reading to a maximum of 3 items from the file\r\n                .resource(new FileSystemResource(&quot;EmployeeList.json&quot;))\r\n                .build();\r\n    }\r\n\r\n    @Bean\r\n    public FlatFileItemWriter&lt;EmployeeJSON&gt; jsonFileWriter() {\r\n        ObjectMapper objectMapper = new ObjectMapper();\r\n        objectMapper.enable(SerializationFeature.INDENT_OUTPUT); \/\/ Optional: pretty print\r\n\r\n        LineAggregator&lt;EmployeeJSON&gt; jsonLineAggregator = item -&gt; {\r\n            try {\r\n                return objectMapper.writeValueAsString(item);\r\n            } catch (JsonProcessingException e) {\r\n                throw new RuntimeException(&quot;Error converting Employee to JSON&quot;, e);\r\n            }\r\n        };\r\n\r\n        return new FlatFileItemWriterBuilder&lt;EmployeeJSON&gt;()\r\n                .name(&quot;employeeJsonTxtWriter&quot;)\r\n                .resource(new FileSystemResource(&quot;OutputFiles\/employees.json&quot;))\r\n                .lineAggregator(jsonLineAggregator)\r\n                .build();\r\n    }\r\n\r\n    @Bean\r\n    public FlatFileItemReader&lt;Employee&gt; flatFileItemReader() {\r\n        FlatFileItemReader&lt;Employee&gt; flatFileItemReader = new FlatFileItemReader&lt;&gt;();\r\n        flatFileItemReader.setResource(new FileSystemResource(&quot;InputFiles\/EmployeeList.txt&quot;));\r\n        flatFileItemReader.setLineMapper(lineMapper());\r\n        return flatFileItemReader;\r\n    }\r\n\r\n    @Bean\r\n    public FlatFileItemWriter&lt;Employee&gt; flatFileWriter() {\r\n        BeanWrapperFieldExtractor&lt;Employee&gt; fieldExtractor = new BeanWrapperFieldExtractor&lt;&gt;();\r\n        fieldExtractor.setNames(new String&#x5B;] {&quot;id&quot;, &quot;name&quot;, &quot;location&quot;, &quot;age&quot;});\r\n\r\n        FileSystemResource fileSystemResource = new FileSystemResource(&quot;OutputFiles\/employeeList.txt&quot;);\r\n\r\n        DelimitedLineAggregator&lt;Employee&gt; lineAggregator = new DelimitedLineAggregator&lt;&gt;();\r\n        lineAggregator.setDelimiter(&quot;,&quot;);\r\n        lineAggregator.setFieldExtractor(fieldExtractor);\r\n\r\n        return new FlatFileItemWriterBuilder&lt;Employee&gt;()\r\n                .name(&quot;flatFileItemWriter&quot;) \/\/helps to uniquely recognize a job incase of need for retry\r\n                .resource(fileSystemResource)\r\n                .lineAggregator(lineAggregator)\r\n                .footerCallback(writer -&gt; writer.write(&quot;Created @ &quot; + new Date()))\r\n                .build();\r\n    }\r\n\r\n    @Bean\r\n    public FlatFileItemReader&lt;EmployeeCSV&gt; csvFileReader() {\r\n        return new FlatFileItemReaderBuilder&lt;EmployeeCSV&gt;()\r\n                .name(&quot;employeeCSVReader&quot;)\r\n                .resource(new FileSystemResource(&quot;EmployeeList.csv&quot;))\r\n                .linesToSkip(1)\r\n                .delimited()\r\n                .names(&quot;ID&quot;, &quot;Name&quot;, &quot;Location&quot;, &quot;Age&quot;)\r\n                .targetType(EmployeeCSV.class)\r\n                .build();\r\n    }\r\n\r\n    @Bean\r\n    public FlatFileItemWriter&lt;Employee&gt; csvFileWriter() {\r\n        BeanWrapperFieldExtractor&lt;Employee&gt; fieldExtractor = new BeanWrapperFieldExtractor&lt;&gt;();\r\n        fieldExtractor.setNames(new String&#x5B;] {&quot;id&quot;, &quot;name&quot;, &quot;location&quot;, &quot;age&quot;});\r\n\r\n        FileSystemResource fileSystemResource = new FileSystemResource(&quot;OutputFiles\/EmployeeList.csv&quot;);\r\n\r\n        DelimitedLineAggregator&lt;Employee&gt; lineAggregator = new DelimitedLineAggregator&lt;&gt;();\r\n        lineAggregator.setDelimiter(&quot;,&quot;);\r\n        lineAggregator.setFieldExtractor(fieldExtractor);\r\n\r\n        return new FlatFileItemWriterBuilder&lt;Employee&gt;()\r\n                .name(&quot;csvItemWriter&quot;)\r\n                .resource(fileSystemResource)\r\n                .lineAggregator(lineAggregator)\r\n                .headerCallback(writer -&gt; writer.write(&quot;ID,Name,Age,Location&quot;))\r\n                .build();\r\n    }\r\n\r\n\r\n    @Bean\r\n    public JdbcCursorItemReader&lt;EmployeeJdbc&gt; jdbcReader() {\r\n        return new JdbcCursorItemReaderBuilder&lt;EmployeeJdbc&gt;()\r\n                .name(&quot;employeeJDBCReader&quot;)\r\n                .dataSource(dataSource)\r\n                .sql(&quot;SELECT id, name, age, location FROM public.tblemployee&quot;)\r\n                .rowMapper(new BeanPropertyRowMapper&lt;&gt;(EmployeeJdbc.class))\r\n                .build();\r\n    }\r\n\r\n    @Bean\r\n    public JdbcBatchItemWriter&lt;Employee&gt; jdbcWriter() {\r\n        return new JdbcBatchItemWriterBuilder&lt;Employee&gt;()\r\n                .itemSqlParameterSourceProvider(new BeanPropertyItemSqlParameterSourceProvider&lt;&gt;())\r\n                .sql(&quot;INSERT INTO tblemployee (id, name, location, age) VALUES (:id, :name, :location, :age)&quot;)\r\n                .dataSource(dataSource)\r\n                .build();\r\n    }\r\n\r\n    @Bean\r\n    public LineMapper&lt;Employee&gt; lineMapper() {\r\n        DefaultLineMapper&lt;Employee&gt; lineMapper = new DefaultLineMapper&lt;&gt;();\r\n\r\n        \/\/ Step 1: Tokenize the line\r\n        DelimitedLineTokenizer tokenizer = new DelimitedLineTokenizer();\r\n        tokenizer.setDelimiter(&quot;,&quot;); \/\/ Default is comma\r\n        tokenizer.setNames(&quot;ID&quot;, &quot;Name&quot;, &quot;Location&quot;, &quot;Age&quot;); \/\/ Must match CSV header\r\n\r\n        \/\/ Step 2: Map tokens to bean properties\r\n        BeanWrapperFieldSetMapper&lt;Employee&gt; fieldSetMapper = new BeanWrapperFieldSetMapper&lt;&gt;();\r\n        fieldSetMapper.setTargetType(Employee.class);\r\n        fieldSetMapper.setStrict(true); \/\/ Optional: disables fuzzy matching\r\n\r\n        \/\/ Step 3: Combine tokenizer and mapper\r\n        lineMapper.setLineTokenizer(tokenizer);\r\n        lineMapper.setFieldSetMapper(fieldSetMapper);\r\n\r\n        return lineMapper;\r\n    }\r\n}\r\n<\/pre>\n<p><strong>SimpleJobProcessor.java<\/strong><\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\nimport com.mugil.org.model.Employee;\r\nimport org.springframework.batch.item.ItemProcessor;\r\nimport org.springframework.stereotype.Component;\r\n\r\n@Component\r\npublic class SimpleJobProcessor implements ItemProcessor&lt;Employee, Employee&gt; {\r\n    @Override\r\n    public Employee process(Employee item) throws Exception {\r\n        System.out.println(&quot;Inside Job Processor&quot;);\r\n        String employeeDetails = &quot;The Employee Name is &quot; + item.getName() + &quot;, his Age is &quot; + item.getAge() + &quot; and location is &quot; + item.getLocation();\r\n        System.out.println(employeeDetails);\r\n\r\n        Employee objEmp = new Employee(item.getId(), item.getName(), item.getLocation(), item.getAge());\r\n\r\n        return objEmp;\r\n    }\r\n}\r\n<\/pre>\n<p><a href=\"https:\/\/codethataint.com\/blog\/wp-content\/uploads\/2025\/09\/FlatFileReader.7z\">Download Source<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>jobconfig.java package com.mugil.org.config; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; import com.mugil.org.model.Employee; import com.mugil.org.model.EmployeeCSV; import com.mugil.org.model.EmployeeJSON; import com.mugil.org.model.EmployeeJdbc; import org.springframework.batch.core.*; import org.springframework.batch.core.job.builder.JobBuilder; import org.springframework.batch.core.launch.support.RunIdIncrementer; import org.springframework.batch.core.repository.JobRepository; import org.springframework.batch.core.step.builder.StepBuilder; import org.springframework.batch.item.ItemProcessor; import org.springframework.batch.item.database.BeanPropertyItemSqlParameterSourceProvider; import org.springframework.batch.item.database.JdbcBatchItemWriter; import org.springframework.batch.item.database.JdbcCursorItemReader; import org.springframework.batch.item.database.builder.JdbcBatchItemWriterBuilder; import org.springframework.batch.item.database.builder.JdbcCursorItemReaderBuilder; import org.springframework.batch.item.file.FlatFileItemReader; import org.springframework.batch.item.file.FlatFileItemWriter; import org.springframework.batch.item.file.LineMapper; import org.springframework.batch.item.file.builder.FlatFileItemReaderBuilder; import org.springframework.batch.item.file.builder.FlatFileItemWriterBuilder; import org.springframework.batch.item.file.mapping.BeanWrapperFieldSetMapper; import org.springframework.batch.item.file.mapping.DefaultLineMapper; import org.springframework.batch.item.file.transform.BeanWrapperFieldExtractor;&hellip; <a href=\"https:\/\/codethataint.com\/blog\/using-item-reader-and-writer-to-read-and-write-from-csv-json-jdbc-and-flat-text-file\/\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[371],"tags":[],"class_list":["post-5636","post","type-post","status-publish","format-standard","hentry","category-spring-batch"],"_links":{"self":[{"href":"https:\/\/codethataint.com\/blog\/wp-json\/wp\/v2\/posts\/5636","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/codethataint.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/codethataint.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/codethataint.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/codethataint.com\/blog\/wp-json\/wp\/v2\/comments?post=5636"}],"version-history":[{"count":2,"href":"https:\/\/codethataint.com\/blog\/wp-json\/wp\/v2\/posts\/5636\/revisions"}],"predecessor-version":[{"id":5640,"href":"https:\/\/codethataint.com\/blog\/wp-json\/wp\/v2\/posts\/5636\/revisions\/5640"}],"wp:attachment":[{"href":"https:\/\/codethataint.com\/blog\/wp-json\/wp\/v2\/media?parent=5636"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/codethataint.com\/blog\/wp-json\/wp\/v2\/categories?post=5636"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/codethataint.com\/blog\/wp-json\/wp\/v2\/tags?post=5636"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}