{"id":2011,"date":"2017-05-13T09:55:59","date_gmt":"2017-05-13T07:55:59","guid":{"rendered":"http:\/\/blog.rabahi.net\/?page_id=2011"},"modified":"2018-12-01T16:29:27","modified_gmt":"2018-12-01T15:29:27","slug":"java-spring-batch","status":"publish","type":"page","link":"https:\/\/blog.rabahi.net\/?page_id=2011","title":{"rendered":"JAVA SPRING &#8211; Batch"},"content":{"rendered":"<p>Here is a short example about Spring Batch that show how to convert a csv file to an xml file.<\/p>\n<div id=\"toc_container\" class=\"no_bullets\"><p class=\"toc_title\">Contents<\/p><ul class=\"toc_list\"><li><a href=\"#Prerequistes\"><span class=\"toc_number toc_depth_1\">1<\/span> Prerequistes<\/a><\/li><li><a href=\"#Configuration\"><span class=\"toc_number toc_depth_1\">2<\/span> Configuration<\/a><\/li><li><a href=\"#Buisness\"><span class=\"toc_number toc_depth_1\">3<\/span> Buisness<\/a><\/li><li><a href=\"#Implementation\"><span class=\"toc_number toc_depth_1\">4<\/span> Implementation<\/a><ul><li><a href=\"#Model\"><span class=\"toc_number toc_depth_2\">4.1<\/span> Model<\/a><\/li><li><a href=\"#Batch_Processor\"><span class=\"toc_number toc_depth_2\">4.2<\/span> Batch Processor<\/a><\/li><li><a href=\"#JobExecution_Listener\"><span class=\"toc_number toc_depth_2\">4.3<\/span> JobExecution Listener<\/a><\/li><li><a href=\"#Configuration-2\"><span class=\"toc_number toc_depth_2\">4.4<\/span> Configuration<\/a><\/li><\/ul><\/li><li><a href=\"#Run_Job\"><span class=\"toc_number toc_depth_1\">5<\/span> Run Job<\/a><\/li><li><a href=\"#Result\"><span class=\"toc_number toc_depth_1\">6<\/span> Result<\/a><\/li><\/ul><\/div>\n<h1><span id=\"Prerequistes\">Prerequistes<\/span><\/h1>\n<h1><span id=\"Configuration\">Configuration<\/span><\/h1>\n<p>If you use maven, add this to your pom.xml<\/p>\n<pre lang=\"xml\">\r\n<dependencies>\r\n(...)\r\n\r\n  <dependency>\r\n    <groupId>org.springframework.boot<\/groupId>\r\n    <artifactId>spring-boot-starter-batch<\/artifactId>\r\n  <\/dependency>\r\n\r\n  <dependency>\r\n    <groupId>org.springframework<\/groupId>\r\n    <artifactId>spring-oxm<\/artifactId>\r\n  <\/dependency>\r\n\r\n(...)\r\n<\/dependencies>\r\n<\/pre>\n<h1><span id=\"Buisness\">Buisness<\/span><\/h1>\n<p>Buisness team have the following csv file named users.csv :<\/p>\n<pre lang=\"csv\">\r\n10,John,Doe\r\n20,Jane,Doe\r\n30,Albert,Einstein\r\n<\/pre>\n<p>We can see that :<\/p>\n<ul>\n<li>the first column is the id<\/li>\n<li>the second column is the fist name<\/li>\n<li>the third column is the last name<\/li>\n<\/ul>\n<h1><span id=\"Implementation\">Implementation<\/span><\/h1>\n<h2><span id=\"Model\">Model<\/span><\/h2>\n<p>Let&#8217;s deal with the following implementation :<\/p>\n<pre lang=\"java\">\r\nimport javax.xml.bind.annotation.XmlRootElement;\r\n\r\nimport lombok.Data;\r\n\r\n@Data\r\n@XmlRootElement(name = \"user\")\r\npublic class User {\r\n\t\r\n    private Integer id;\r\n    private String lastName;\r\n    private String firstName;\r\n\r\n}\r\n<\/pre>\n<h2><span id=\"Batch_Processor\">Batch Processor<\/span><\/h2>\n<p>The batch processor allows you to make any operation about your model.<br \/>\nFor example, you can uppercase all last names.<br \/>\nYou have to return a new model object, so this batch processor is immutable).<\/p>\n<p>In the example we only diplay the processed user in the LOGGER::info appender.<\/p>\n<pre lang=\"java\">\r\nimport org.springframework.batch.item.ItemProcessor;\r\n\r\nimport lombok.extern.slf4j.Slf4j;\r\n\r\n@Slf4j\r\npublic class UserItemProcessor implements ItemProcessor<User, User> {\r\n\r\n\t@Override\r\n\tpublic User process(final User user) throws Exception {\r\n\t\tLOGGER.info(\"User processed : {}\", user);\r\n\t\treturn user;\r\n\t}\r\n}\r\n<\/pre>\n<h2><span id=\"JobExecution_Listener\">JobExecution Listener<\/span><\/h2>\n<p>You can implement a listener to handle &#8216;before&#8217; and &#8216;after&#8217; jobs execution.<\/p>\n<pre lang=\"java\">\r\nimport org.springframework.batch.core.BatchStatus;\r\nimport org.springframework.batch.core.JobExecution;\r\nimport org.springframework.batch.core.listener.JobExecutionListenerSupport;\r\nimport org.springframework.stereotype.Component;\r\n\r\nimport lombok.extern.slf4j.Slf4j;\r\n\r\n@Component\r\n@Slf4j\r\npublic class JobCompletionNotificationListener extends JobExecutionListenerSupport {\r\n\r\n\t@Override\r\n\tpublic void beforeJob(JobExecution jobExecution) {\t\t\r\n\t\tLOGGER.info(\"Before job process...\");\r\n\t}\r\n\t\r\n\t@Override\r\n\tpublic void afterJob(JobExecution jobExecution) {\r\n\t\tLOGGER.info(\"After job process...\");\r\n\t\tif(jobExecution.getStatus() == BatchStatus.COMPLETED) {\r\n\t\t\tLOGGER.info(\"Job completed.\");\r\n\t\t}\r\n\t}\r\n}\r\n<\/pre>\n<h2><span id=\"Configuration-2\">Configuration<\/span><\/h2>\n<p>Now let&#8217;s configure our batch :<\/p>\n<pre lang=\"java\">\r\n\r\nimport java.io.File;\r\n\r\nimport javax.inject.Inject;\r\n\r\nimport org.springframework.batch.core.Job;\r\nimport org.springframework.batch.core.Step;\r\nimport org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;\r\nimport org.springframework.batch.core.configuration.annotation.JobBuilderFactory;\r\nimport org.springframework.batch.core.configuration.annotation.StepBuilderFactory;\r\nimport org.springframework.batch.item.file.FlatFileItemReader;\r\nimport org.springframework.batch.item.file.builder.FlatFileItemReaderBuilder;\r\nimport org.springframework.batch.item.file.mapping.BeanWrapperFieldSetMapper;\r\nimport org.springframework.batch.item.xml.StaxEventItemWriter;\r\nimport org.springframework.batch.item.xml.builder.StaxEventItemWriterBuilder;\r\nimport org.springframework.context.annotation.Bean;\r\nimport org.springframework.context.annotation.Configuration;\r\nimport org.springframework.core.io.ClassPathResource;\r\nimport org.springframework.core.io.FileSystemResource;\r\nimport org.springframework.oxm.Marshaller;\r\nimport org.springframework.oxm.jaxb.Jaxb2Marshaller;\r\n\r\n@Configuration\r\n@EnableBatchProcessing\r\npublic class BatchConfiguration {\r\n\r\n\t@Inject\r\n\tpublic JobBuilderFactory jobBuilderFactory;\r\n\r\n\t@Inject\r\n\tpublic StepBuilderFactory stepBuilderFactory;\r\n\r\n\t\/**\r\n\t * Read csv file.\r\n\t * @return FlatFileItemReader\r\n\t *\/\r\n\t@Bean\r\n\tpublic FlatFileItemReader<User> reader() {\r\n\t\t\r\n\t\tBeanWrapperFieldSetMapper<User> bean = new BeanWrapperFieldSetMapper<>();\r\n\t\tbean.setTargetType(User.class);\r\n\t\t\r\n\t\treturn new FlatFileItemReaderBuilder<User>()\r\n\t\t\t\t.name(\"userItemReader\")\r\n\t\t\t\t.resource(new ClassPathResource(\"users.csv\"))\r\n\t\t\t\t.delimited()\r\n\t\t\t\t.names(new String[]{\"id\" , \"firstName\", \"lastName\"})\r\n\t\t\t\t.fieldSetMapper(bean)\r\n\t\t\t\t.build();\r\n\t}\r\n\t\r\n\t@Bean\r\n\tpublic UserItemProcessor processor() {\r\n\t\treturn new UserItemProcessor();\r\n\t}\r\n\r\n\t@Bean\r\n\tpublic Marshaller marshaller() {\t\t\r\n\t\tJaxb2Marshaller marshaller = new Jaxb2Marshaller();\r\n\r\n\t\tmarshaller.setClassesToBeBound(User.class);\r\n\t\t\r\n\t\treturn marshaller;\r\n\t}\t\r\n\t\r\n\t\/**\r\n\t * Write result to xml file.\r\n\t * @return StaxEventItemWriter\r\n\t *\/\r\n\t@Bean\r\n\tpublic StaxEventItemWriter<User> writer() {\r\n\t\treturn new StaxEventItemWriterBuilder<User>()\r\n\t\t\t\t.name(\"userItemWriter\")\r\n\t\t\t\t.resource(new FileSystemResource(new File(TEMP_DIR,\"users.xml\")))\r\n\t\t\t\t.marshaller(marshaller())\r\n\t\t\t\t.rootTagName(\"users\")\r\n\t\t\t\t.build();\r\n\t}\r\n\t\r\n\t@Bean\r\n\tpublic Job csvToXmlJob() {\r\n\t\t\r\n\t\treturn jobBuilderFactory\r\n\t\t\t\t.get(\"csvToXmlJob\")\r\n\t\t\t\t.flow(step1())\r\n\t\t\t\t.end()\r\n\t\t\t\t.build();\r\n\t}\r\n\r\n\t@Bean\r\n\tpublic Step step1() {\r\n\t\treturn stepBuilderFactory\r\n\t\t\t\t.get(\"step1\")\r\n\t\t\t\t.<User, User>chunk(10)\r\n\t\t\t\t.reader(reader())\r\n\t\t\t\t.writer(writer())\r\n\t\t\t\t.processor(processor())\r\n\t\t\t\t.build();\r\n\t}\r\n}\r\n<\/pre>\n<h1><span id=\"Run_Job\">Run Job<\/span><\/h1>\n<p>To run the job, you can do like this :<\/p>\n<pre lang=\"java\">\r\n@Component\r\npublic final class JobComponent {\r\n\r\n\t@Inject\r\n\tJobLauncher jobLauncher;\r\n\r\n\t@Inject\r\n\tJob job;\r\n\r\n\t@RequestMapping(\"\/runMyJob\")\r\n\tpublic void runMyJob() throws Exception {\r\n\t\tjobLauncher.run(job, new JobParameters());\r\n\t}\r\n\r\n}\r\n<\/pre>\n<h1><span id=\"Result\">Result<\/span><\/h1>\n<pre lang=\"xml\">\r\n<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n<users>\r\n\t<user>\r\n\t\t<id>10<\/id>\r\n\t\t<lastName>Doe<\/lastName>\r\n\t\t<firstName>John<\/firstName>\r\n\t<\/user>\r\n\t<user>\r\n\t\t<id>20<\/id>\r\n\t\t<lastName>Doe<\/lastName>\r\n\t\t<firstName>Jane<\/firstName>\r\n\t<\/user>\r\n\t<user>\r\n\t\t<id>30<\/id>\r\n\t\t<lastName>Einstein<\/lastName>\r\n\t\t<firstName>Albert<\/firstName>\r\n\t<\/user>\r\n<\/users>\r\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Here is a short example about Spring Batch that show how to convert a csv file to an xml file. Contents1 Prerequistes2 Configuration3 Buisness4 Implementation4.1 Model4.2 Batch Processor4.3 JobExecution Listener4.4 Configuration5 Run Job6 Result Prerequistes Configuration If you use maven, add this to your pom.xml (&#8230;) org.springframework.boot spring-boot-starter-batch org.springframework spring-oxm (&#8230;) Buisness Buisness team have [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":1547,"menu_order":1,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-2011","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/blog.rabahi.net\/index.php?rest_route=\/wp\/v2\/pages\/2011","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.rabahi.net\/index.php?rest_route=\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/blog.rabahi.net\/index.php?rest_route=\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/blog.rabahi.net\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.rabahi.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=2011"}],"version-history":[{"count":13,"href":"https:\/\/blog.rabahi.net\/index.php?rest_route=\/wp\/v2\/pages\/2011\/revisions"}],"predecessor-version":[{"id":2061,"href":"https:\/\/blog.rabahi.net\/index.php?rest_route=\/wp\/v2\/pages\/2011\/revisions\/2061"}],"up":[{"embeddable":true,"href":"https:\/\/blog.rabahi.net\/index.php?rest_route=\/wp\/v2\/pages\/1547"}],"wp:attachment":[{"href":"https:\/\/blog.rabahi.net\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=2011"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}