{"id":69639,"date":"2017-10-13T10:32:27","date_gmt":"2017-10-13T07:32:27","guid":{"rendered":"https:\/\/www.javacodegeeks.com\/?p=69639"},"modified":"2017-10-13T10:32:27","modified_gmt":"2017-10-13T07:32:27","slug":"spring-batch-csv-processing","status":"publish","type":"post","link":"https:\/\/www.javacodegeeks.com\/2017\/10\/spring-batch-csv-processing.html","title":{"rendered":"Spring Batch CSV Processing"},"content":{"rendered":"<h2>Overview<\/h2>\n<p>Topics we will be discussing include the essential concepts of batch processing with Spring Batch and how to import the data from a CSV into a database.<\/p>\n<h2>0 \u2013 Spring Batch CSV Processing Example Application<\/h2>\n<p>We are building an application that demonstrates the basics of Spring Batch for processing CSV files. Our demo application will allow us to process a CSV file that contains hundreds of records of Japanese anime titles.<\/p>\n<h3>0.1 \u2013 The CSV<\/h3>\n<p>I have downloaded the CSV we will be using from this <a href=\"https:\/\/github.com\/jieverson\/animeapi\/blob\/master\/data\/animes.csv\">Github repository<\/a>, and it provides a pretty comprehensive list of animes.<\/p>\n<p>Here is a screenshot of the CSV open in Microsoft Excel<\/p>\n<p><a href=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/10\/Screen-Shot-2017-10-12-at-8.19.19-AM.png\"><img decoding=\"async\" class=\"aligncenter size-full wp-image-69648\" src=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/10\/Screen-Shot-2017-10-12-at-8.19.19-AM.png\" alt=\"\" width=\"851\" height=\"107\" srcset=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/10\/Screen-Shot-2017-10-12-at-8.19.19-AM.png 851w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/10\/Screen-Shot-2017-10-12-at-8.19.19-AM-300x38.png 300w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/10\/Screen-Shot-2017-10-12-at-8.19.19-AM-768x97.png 768w\" sizes=\"(max-width: 851px) 100vw, 851px\" \/><\/a><\/p>\n<p><b>View and Download the code from <\/b><a href=\"https:\/\/github.com\/michaelcgood\/Spring-Batch-CSV-Example\">Github<\/a><\/p>\n<h2>1 \u2013 Project Structure<\/h2>\n<p><a href=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/10\/Screen-Shot-2017-10-12-at-7.33.41-AM.png\"><img decoding=\"async\" class=\"aligncenter size-full wp-image-69649\" src=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/10\/Screen-Shot-2017-10-12-at-7.33.41-AM.png\" alt=\"\" width=\"327\" height=\"392\" srcset=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/10\/Screen-Shot-2017-10-12-at-7.33.41-AM.png 327w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/10\/Screen-Shot-2017-10-12-at-7.33.41-AM-250x300.png 250w\" sizes=\"(max-width: 327px) 100vw, 327px\" \/><\/a><\/p>\n<h2>2 \u2013 Project Dependencies<\/h2>\n<p>Besides typical Spring Boot dependencies, we include spring-boot-starter-batch, which is the dependency for Spring Batch as the name suggests, and hsqldb for an in-memory database. We also include commons-lang3 for ToStringBuilder.<\/p>\n<pre class=\"brush:xml\">&lt;?xml version=\"1.0\" encoding=\"UTF-8\"?&gt;\r\n&lt;project xmlns=\"http:\/\/maven.apache.org\/POM\/4.0.0\" xmlns:xsi=\"http:\/\/www.w3.org\/2001\/XMLSchema-instance\"\r\n\txsi:schemaLocation=\"http:\/\/maven.apache.org\/POM\/4.0.0 http:\/\/maven.apache.org\/xsd\/maven-4.0.0.xsd\"&gt;\r\n\t&lt;modelVersion&gt;4.0.0&lt;\/modelVersion&gt;\r\n\r\n\t&lt;groupId&gt;com.michaelcgood&lt;\/groupId&gt;\r\n\t&lt;artifactId&gt;michaelcgood-spring-batch-csv&lt;\/artifactId&gt;\r\n\t&lt;version&gt;0.0.1&lt;\/version&gt;\r\n\t&lt;packaging&gt;jar&lt;\/packaging&gt;\r\n\r\n\t&lt;name&gt;michaelcgood-spring-batch-csv&lt;\/name&gt;\r\n\t&lt;description&gt;Michael C  Good - Spring Batch CSV Example Application&lt;\/description&gt;\r\n\r\n\t&lt;parent&gt;\r\n\t\t&lt;groupId&gt;org.springframework.boot&lt;\/groupId&gt;\r\n\t\t&lt;artifactId&gt;spring-boot-starter-parent&lt;\/artifactId&gt;\r\n\t\t&lt;version&gt;1.5.7.RELEASE&lt;\/version&gt;\r\n\t\t&lt;relativePath \/&gt; &lt;!-- lookup parent from repository --&gt;\r\n\t&lt;\/parent&gt;\r\n\r\n\t&lt;properties&gt;\r\n\t\t&lt;project.build.sourceEncoding&gt;UTF-8&lt;\/project.build.sourceEncoding&gt;\r\n\t\t&lt;project.reporting.outputEncoding&gt;UTF-8&lt;\/project.reporting.outputEncoding&gt;\r\n\t\t&lt;java.version&gt;1.8&lt;\/java.version&gt;\r\n\t&lt;\/properties&gt;\r\n\r\n\t&lt;dependencies&gt;\r\n\t\t&lt;dependency&gt;\r\n\t\t\t&lt;groupId&gt;org.springframework.boot&lt;\/groupId&gt;\r\n\t\t\t&lt;artifactId&gt;spring-boot-starter-batch&lt;\/artifactId&gt;\r\n\t\t&lt;\/dependency&gt;\r\n\t\t&lt;dependency&gt;\r\n\t\t\t&lt;groupId&gt;org.springframework.boot&lt;\/groupId&gt;\r\n\t\t\t&lt;artifactId&gt;spring-boot-starter-data-jpa&lt;\/artifactId&gt;\r\n\t\t&lt;\/dependency&gt;\r\n\t\t&lt;dependency&gt;\r\n\t\t\t&lt;groupId&gt;org.springframework.boot&lt;\/groupId&gt;\r\n\t\t\t&lt;artifactId&gt;spring-boot-starter-web&lt;\/artifactId&gt;\r\n\t\t&lt;\/dependency&gt;\r\n\r\n\t\t&lt;dependency&gt;\r\n\t\t\t&lt;groupId&gt;org.hsqldb&lt;\/groupId&gt;\r\n\t\t\t&lt;artifactId&gt;hsqldb&lt;\/artifactId&gt;\r\n\t\t&lt;\/dependency&gt;\r\n\t\t&lt;dependency&gt;\r\n\t\t\t&lt;groupId&gt;org.springframework.boot&lt;\/groupId&gt;\r\n\t\t\t&lt;artifactId&gt;spring-boot-starter-test&lt;\/artifactId&gt;\r\n\t\t\t&lt;scope&gt;test&lt;\/scope&gt;\r\n\t\t&lt;\/dependency&gt;\r\n\t\t&lt;!-- https:\/\/mvnrepository.com\/artifact\/org.apache.commons\/commons-lang3 --&gt;\r\n\t\t&lt;dependency&gt;\r\n\t\t\t&lt;groupId&gt;org.apache.commons&lt;\/groupId&gt;\r\n\t\t\t&lt;artifactId&gt;commons-lang3&lt;\/artifactId&gt;\r\n\t\t\t&lt;version&gt;3.6&lt;\/version&gt;\r\n\t\t&lt;\/dependency&gt;\r\n\t&lt;\/dependencies&gt;\r\n\r\n\t&lt;build&gt;\r\n\t\t&lt;plugins&gt;\r\n\t\t\t&lt;plugin&gt;\r\n\t\t\t\t&lt;groupId&gt;org.springframework.boot&lt;\/groupId&gt;\r\n\t\t\t\t&lt;artifactId&gt;spring-boot-maven-plugin&lt;\/artifactId&gt;\r\n\t\t\t&lt;\/plugin&gt;\r\n\t\t&lt;\/plugins&gt;\r\n\t&lt;\/build&gt;\r\n\r\n\r\n&lt;\/project&gt;<\/pre>\n<h2>3 \u2013 Model<\/h2>\n<p>This is a POJO that models the fields of an anime. The fields are:<\/p>\n<ul>\n<li>ID. For the sake of simplicity, we treat the ID as a String. However, this could be changed to another data type such as an Integer or Long.<\/li>\n<li>Title. This is the title of the anime and it is appropriate for it to be a String.<\/li>\n<li>Description. This is the description of the anime, which is longer than the title, and it can also be treated as a String.<\/li>\n<\/ul>\n<p>What is important to note is our class constructor for the three fields: public AnimeDTO(String id, String title, String description). This will be used in our application. Also, as usual, we need to make a default constructor with no parameters or else Java will throw an error.<\/p>\n<pre class=\"brush:java\">package com.michaelcgood;\r\n\r\nimport org.apache.commons.lang3.builder.ToStringBuilder;\r\n\/**\r\n * Contains the information of a single anime\r\n *\r\n * @author Michael C Good michaelcgood.com\r\n *\/\r\n\r\npublic class AnimeDTO {\r\n\t\r\n\tpublic String getId() {\r\n\t\treturn id;\r\n\t}\r\n\r\n\tpublic void setId(String id) {\r\n\t\tthis.id = id;\r\n\t}\r\n\r\n\tpublic String getTitle() {\r\n\t\treturn title;\r\n\t}\r\n\r\n\tpublic void setTitle(String title) {\r\n\t\tthis.title = title;\r\n\t}\r\n\r\n\tpublic String getDescription() {\r\n\t\treturn description;\r\n\t}\r\n\r\n\tpublic void setDescription(String description) {\r\n\t\tthis.description = description;\r\n\t}\r\n\r\n\r\n\r\n\tprivate String id;\r\n\t\r\n\r\n\r\n\r\n\tprivate String title;\r\n\tprivate String description;\r\n\t\r\n\tpublic AnimeDTO(){\r\n\t\t\r\n\t}\r\n\t\r\n\tpublic AnimeDTO(String id, String title, String description){\r\n\t\tthis.id = id;\r\n\t\tthis.title = title;\r\n\t\tthis.description = title;\r\n\t}\r\n\t\r\n\r\n\t\r\n\t   @Override\r\n\t    public String toString() {\r\n\t\t   return new ToStringBuilder(this)\r\n\t\t\t\t   .append(\"id\", this.id)\r\n\t\t\t\t   .append(\"title\", this.title)\r\n\t\t\t\t   .append(\"description\", this.description)\r\n\t\t\t\t   .toString();\r\n\t   }\r\n\r\n\r\n}<\/pre>\n<h2>4 \u2013 CSV File to Database Configuration<\/h2>\n<p>There is a lot going on in this class and it is not all written at once, so we are going to go through the code in steps. Visit <a href=\"https:\/\/github.com\/michaelcgood\/Spring-Batch-CSV-Example\" target=\"_blank\" rel=\"noopener\">Github<\/a> to see the code in its entirety.<div style=\"display:inline-block; margin: 15px 0;\"> <div id=\"adngin-JavaCodeGeeks_incontent_video-0\" style=\"display:inline-block;\"><\/div> <\/div><\/p>\n<h3>4.1 \u2013 Reader<\/h3>\n<p>As the <a href=\"https:\/\/docs.spring.io\/spring-batch\/trunk\/reference\/html\/readersAndWriters.html\" target=\"_blank\" rel=\"noopener\">Spring Batch documentation<\/a> states FlatFileIteamReader will \u201cread lines of data from a flat file that typically describe records with fields of data defined by fixed positions in the file or delimited by some special character (e.g. Comma)\u201d.<\/p>\n<p>We are dealing with a CSV, so of course the data is delimited by a comma, making this the perfect for use with our file.<\/p>\n<pre class=\"brush:java\">@Bean\r\n    public FlatFileItemReader&lt;AnimeDTO&gt; csvAnimeReader(){\r\n        FlatFileItemReader&lt;AnimeDTO&gt; reader = new FlatFileItemReader&lt;AnimeDTO&gt;();\r\n        reader.setResource(new ClassPathResource(\"animescsv.csv\"));\r\n        reader.setLineMapper(new DefaultLineMapper&lt;AnimeDTO&gt;() {{\r\n            setLineTokenizer(new DelimitedLineTokenizer() {{\r\n                setNames(new String[] { \"id\", \"title\", \"description\" });\r\n            }});\r\n            setFieldSetMapper(new BeanWrapperFieldSetMapper&lt;AnimeDTO&gt;() {{\r\n                setTargetType(AnimeDTO.class);\r\n            }});\r\n        }});\r\n        return reader;\r\n    }<\/pre>\n<p>Important points:<\/p>\n<ul>\n<li style=\"list-style-type: none\">\n<ul>\n<li>FlatFileItemReader is parameterized with a model. In our case, this is AnimeDTO.<\/li>\n<li>FlatFileItemReader must set a resource. It uses <em>setResource<\/em> method. Here we set the resource to <em>animescsv.csv<\/em><\/li>\n<li><em>setLineMapper<\/em> method converts Strings to objects representing the item. Our String will be an anime record consisting of an id, title, and description. This String is made into an object. Note that <em>DefaultLineMapper<\/em> is parameterized with our model, AnimeDTO.<\/li>\n<li>However, LineMapper is given a raw line, which means there is work that needs to be done to map the fields appropriately. The line must be tokenized into a FieldSet, which <em>DelimitedLineTokenizer<\/em> takes care of. DelimitedLineTokenizer returns a FieldSet.<\/li>\n<li>Now that we have a FieldSet, we need to map it. <em>setFieldSetMapper<\/em> is used for taking the FieldSet object and mapping its contents to a DTO, which is AnimeDTO in our case.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<h3>4.2 \u2013 Processor<\/h3>\n<p>If we want to transform the data before writing it to the database, an ItemProcessor is necessary. Our code does not actually apply any business logic to transform the data, but we allow for the capability to.<\/p>\n<h4>4.2.1 \u2013 Processor in CsvFileToDatabaseConfig.Java<\/h4>\n<p><em>csvAnimeProcessor<\/em> returns a new instance of the AnimeProcessor object which we review below.<\/p>\n<pre class=\"brush:java\">@Bean\r\n\tItemProcessor&lt;AnimeDTO, AnimeDTO&gt; csvAnimeProcessor() {\r\n\t\treturn new AnimeProcessor();\r\n\t}<\/pre>\n<h4>4.2.2 \u2013 AnimeProcessor.Java<\/h4>\n<p>If we wanted to apply business logic before writing to the database, you could manipulate the Strings before writing to the database. For instance, you could add <em>toUpperCase()<\/em> after <em>getTitle<\/em> to make the title upper case before writing to the database. However, I decided not to do that or apply any other business logic for this example processor, so no manipulation is being done. The Processor is here simply for demonstration.<\/p>\n<pre class=\"brush:java\">package com.michaelcgood;\r\n\r\nimport org.slf4j.Logger;\r\nimport org.slf4j.LoggerFactory;\r\n\r\nimport org.springframework.batch.item.ItemProcessor;\r\n\r\npublic class AnimeProcessor implements ItemProcessor&lt;AnimeDTO, AnimeDTO&gt; {\r\n\t\r\n    private static final Logger log = LoggerFactory.getLogger(AnimeProcessor.class);\r\n    \r\n    @Override\r\n    public AnimeDTO process(final AnimeDTO AnimeDTO) throws Exception {\r\n    \t\r\n    \tfinal String id = AnimeDTO.getId();\r\n        final String title = AnimeDTO.getTitle();\r\n        final String description = AnimeDTO.getDescription();\r\n\r\n        final AnimeDTO transformedAnimeDTO = new AnimeDTO(id, title, description);\r\n\r\n        log.info(\"Converting (\" + AnimeDTO + \") into (\" + transformedAnimeDTO + \")\");\r\n\r\n        return transformedAnimeDTO;\r\n    }\r\n\r\n}<\/pre>\n<h3>4.3 \u2013 Writer<\/h3>\n<p>The <em>csvAnimeWriter<\/em> method is responsible for actually writing the values into our database. Our database is an in-memory HSQLDB however this application allows us to easily swap out one database for another. The <em>dataSource<\/em> is autowired.<\/p>\n<pre class=\"brush:java\">@Bean\r\n\tpublic JdbcBatchItemWriter&lt;AnimeDTO&gt; csvAnimeWriter() {\r\n\t\t JdbcBatchItemWriter&lt;AnimeDTO&gt; excelAnimeWriter = new JdbcBatchItemWriter&lt;AnimeDTO&gt;();\r\n\t\t excelAnimeWriter.setItemSqlParameterSourceProvider(new BeanPropertyItemSqlParameterSourceProvider&lt;AnimeDTO&gt;());\r\n\t\t excelAnimeWriter.setSql(\"INSERT INTO animes (id, title, description) VALUES (:id, :title, :description)\");\r\n\t\t excelAnimeWriter.setDataSource(dataSource);\r\n\t        return excelAnimeWriter;\r\n\t}<\/pre>\n<h3>4.4 \u2013 Step<\/h3>\n<p>A <a href=\"https:\/\/docs.spring.io\/spring-batch\/trunk\/reference\/html\/configureStep.html\" target=\"_blank\" rel=\"noopener\">Step<\/a> is a domain object that contains an independent, sequential phase of a batch job and contains all of the information needed to define and control the actual batch processing.<\/p>\n<p>Now that we\u2019ve created the reader and processor for data we need to write it. For the reading, we\u2019ve been using chunk-oriented processing, meaning we\u2019ve been reading the data one at a time. Chunk-oriented processing also includes creating \u2018chunks\u2019 that will be written out, within a transaction boundary. For chunk-oriented processing, you set a commit interval and once the number of items read equals the commit interval that has been set, the entire chunk is written out via the ItemWriter, and the transaction is committed. We set the chunk interval size to 1.<\/p>\n<p>I suggest reading the <a href=\"https:\/\/docs.spring.io\/spring-batch\/trunk\/reference\/html\/configureStep.html#chunkOrientedProcessing\" target=\"_blank\" rel=\"noopener\">Spring Batch documentation about chunk-oriented processing<\/a>.<\/p>\n<p>Then the reader, processor, and writer call the methods we wrote.<\/p>\n<pre class=\"brush:java\">@Bean\r\n\tpublic Step csvFileToDatabaseStep() {\r\n\t\treturn stepBuilderFactory.get(\"csvFileToDatabaseStep\")\r\n\t\t\t\t.&lt;AnimeDTO, AnimeDTO&gt;chunk(1)\r\n\t\t\t\t.reader(csvAnimeReader())\r\n\t\t\t\t.processor(csvAnimeProcessor())\r\n\t\t\t\t.writer(csvAnimeWriter())\r\n\t\t\t\t.build();\r\n\t}<\/pre>\n<h3>4.5 \u2013 Job<\/h3>\n<p>A Job consists of Steps. We pass a parameter into the Job below because we want to track the completion of the Job.<\/p>\n<pre class=\"brush:java\">@Bean\r\n\tJob csvFileToDatabaseJob(JobCompletionNotificationListener listener) {\r\n\t\treturn jobBuilderFactory.get(\"csvFileToDatabaseJob\")\r\n\t\t\t\t.incrementer(new RunIdIncrementer())\r\n\t\t\t\t.listener(listener)\r\n\t\t\t\t.flow(csvFileToDatabaseStep())\r\n\t\t\t\t.end()\r\n\t\t\t\t.build();\r\n\t}<\/pre>\n<p>&nbsp;<\/p>\n<h2>5 \u2013 Job Completion Notification Listener<\/h2>\n<p>The class below autowires the JdbcTemplate because we\u2019ve already set the dataSource and we want to easily make our query. The results of our are query are a list of AnimeDTO objects. For each object returned, we will create a message in our console to show that the item has been written to the database.<\/p>\n<pre class=\"brush:java\">package com.michaelcgood;\r\n\r\nimport java.sql.ResultSet;\r\nimport java.sql.SQLException;\r\nimport java.util.List;\r\n\r\nimport org.slf4j.Logger;\r\nimport org.slf4j.LoggerFactory;\r\n\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.beans.factory.annotation.Autowired;\r\nimport org.springframework.jdbc.core.JdbcTemplate;\r\nimport org.springframework.jdbc.core.RowMapper;\r\nimport org.springframework.stereotype.Component;\r\n\r\n@Component\r\npublic class JobCompletionNotificationListener extends JobExecutionListenerSupport {\r\n\r\n\tprivate static final Logger log = LoggerFactory.getLogger(JobCompletionNotificationListener.class);\r\n\r\n\tprivate final JdbcTemplate jdbcTemplate;\r\n\r\n\t@Autowired\r\n\tpublic JobCompletionNotificationListener(JdbcTemplate jdbcTemplate) {\r\n\t\tthis.jdbcTemplate = jdbcTemplate;\r\n\t}\r\n\r\n\t@Override\r\n\tpublic void afterJob(JobExecution jobExecution) {\r\n\t\tif(jobExecution.getStatus() == BatchStatus.COMPLETED) {\r\n\t\t\tlog.info(\"============ JOB FINISHED ============ Verifying the results....\\n\");\r\n\r\n\t\t\tList&lt;AnimeDTO&gt; results = jdbcTemplate.query(\"SELECT id, title, description FROM animes\", new RowMapper&lt;AnimeDTO&gt;() {\r\n\t\t\t\t@Override\r\n\t\t\t\tpublic AnimeDTO mapRow(ResultSet rs, int row) throws SQLException {\r\n\t\t\t\t\treturn new AnimeDTO(rs.getString(1), rs.getString(2), rs.getString(3));\r\n\t\t\t\t}\r\n\t\t\t});\r\n\r\n\t\t\tfor (AnimeDTO AnimeDTO : results) {\r\n\t\t\t\tlog.info(\"Discovered &lt;\" + AnimeDTO + \"&gt; in the database.\");\r\n\t\t\t}\r\n\r\n\t\t}\r\n\t}\r\n\t\r\n}<\/pre>\n<h2>6 \u2013 SQL<\/h2>\n<p>We need to create a schema for our database. As mentioned, we have made all fields Strings for ease of use, so we have made their data types VARCHAR.<\/p>\n<pre class=\"brush:sql\">DROP TABLE animes IF EXISTS;\r\nCREATE TABLE animes  (\r\n    id VARCHAR(10),\r\n    title VARCHAR(400),\r\n    description VARCHAR(999)\r\n);<\/pre>\n<h2>6 \u2013 Main<\/h2>\n<p>This is a standard class with main(). As the Spring Documentation states, <em>@SpringBootApplication<\/em> is a convenience annotation that includes <em>@Configuration<\/em>, <em>@EnableAutoConfiguration<\/em>, <em>@EnableWebMvc<\/em>, and <em>@ComponentScan<\/em>.<\/p>\n<pre class=\"brush:java\">package com.michaelcgood;\r\n\r\nimport org.springframework.boot.SpringApplication;\r\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\r\n\r\n@SpringBootApplication\r\npublic class SpringBatchCsvApplication {\r\n\r\n\tpublic static void main(String[] args) {\r\n\t\tSpringApplication.run(SpringBatchCsvApplication.class, args);\r\n\t}\r\n}<\/pre>\n<h2>7 \u2013 Demo<\/h2>\n<h3>7.1 \u2013 Converting<\/h3>\n<p>The FieldSet is fed through the processor and \u201cConverting\u201d is printed to the console.<br \/>\n<a href=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/10\/Screen-Shot-2017-10-12-at-7.53.11-AM.png\"><img decoding=\"async\" class=\"aligncenter wp-image-69650\" src=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/10\/Screen-Shot-2017-10-12-at-7.53.11-AM.png\" alt=\"\" width=\"860\" height=\"188\" srcset=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/10\/Screen-Shot-2017-10-12-at-7.53.11-AM.png 1024w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/10\/Screen-Shot-2017-10-12-at-7.53.11-AM-300x66.png 300w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/10\/Screen-Shot-2017-10-12-at-7.53.11-AM-768x168.png 768w\" sizes=\"(max-width: 860px) 100vw, 860px\" \/><\/a><\/p>\n<h3>7.2 \u2013 Discovering New Items In Database<\/h3>\n<p>When the Spring Batch Job is finished, we select all the records and print them out to the console individually.<br \/>\n<a href=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/10\/Screen-Shot-2017-10-12-at-7.54.01-AM.png\"><img decoding=\"async\" class=\"aligncenter wp-image-69651\" src=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/10\/Screen-Shot-2017-10-12-at-7.54.01-AM.png\" alt=\"\" width=\"860\" height=\"134\" srcset=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/10\/Screen-Shot-2017-10-12-at-7.54.01-AM.png 1024w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/10\/Screen-Shot-2017-10-12-at-7.54.01-AM-300x47.png 300w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2017\/10\/Screen-Shot-2017-10-12-at-7.54.01-AM-768x120.png 768w\" sizes=\"(max-width: 860px) 100vw, 860px\" \/><\/a><\/p>\n<h3>7.3 \u2013 Batch Process Complete<\/h3>\n<p>When the Batch Process is complete this is what is printed to the console.<\/p>\n<pre class=\"brush:java\">Job: [FlowJob: [name=csvFileToDatabaseJob]] completed with the following parameters: [{run.id=1, -spring.output.ansi.enabled=always}] and the following status: [COMPLETED]\r\nStarted SpringBatchCsvApplication in 36.0 seconds (JVM running for 46.616)<\/pre>\n<h2>8 \u2013 Conclusion<\/h2>\n<p>Spring Batch builds upon the POJO-based development approach and user-friendliness of the Spring Framework\u2019s to make it easy for developers to create enterprise grade batch processing.<\/p>\n<p><b>The source code is on<\/b> <a href=\"https:\/\/github.com\/michaelcgood\/Spring-Batch-CSV-Example\">Github<\/a><\/p>\n<div class=\"attribution\">\n<table>\n<tbody>\n<tr>\n<td>Published on Java Code Geeks with permission by Michael Good, partner at our <a href=\"http:\/\/www.javacodegeeks.com\/join-us\/jcg\/\" target=\"_blank\" rel=\"noopener\">JCG program<\/a>. See the original article here: <a href=\"http:\/\/michaelcgood.com\/spring-batch-csv-processing\/\" target=\"_blank\" rel=\"noopener\">Spring Batch CSV Processing<\/a><\/p>\n<p>Opinions expressed by Java Code Geeks contributors are their own.<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>Overview Topics we will be discussing include the essential concepts of batch processing with Spring Batch and how to import the data from a CSV into a database. 0 \u2013 Spring Batch CSV Processing Example Application We are building an application that demonstrates the basics of Spring Batch for processing CSV files. Our demo application &hellip;<\/p>\n","protected":false},"author":5558,"featured_media":240,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[8],"tags":[30,691],"class_list":["post-69639","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-enterprise-java","tag-spring","tag-spring-batch"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.5 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Spring Batch CSV Processing - Java Code Geeks<\/title>\n<meta name=\"description\" content=\"Overview Topics we will be discussing include the essential concepts of batch processing with Spring Batch and how to import the data from a CSV into a\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.javacodegeeks.com\/2017\/10\/spring-batch-csv-processing.html\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Spring Batch CSV Processing - Java Code Geeks\" \/>\n<meta property=\"og:description\" content=\"Overview Topics we will be discussing include the essential concepts of batch processing with Spring Batch and how to import the data from a CSV into a\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.javacodegeeks.com\/2017\/10\/spring-batch-csv-processing.html\" \/>\n<meta property=\"og:site_name\" content=\"Java Code Geeks\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/javacodegeeks\" \/>\n<meta property=\"article:published_time\" content=\"2017-10-13T07:32:27+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-logo.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"150\" \/>\n\t<meta property=\"og:image:height\" content=\"150\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Michael Good\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@javacodegeeks\" \/>\n<meta name=\"twitter:site\" content=\"@javacodegeeks\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Michael Good\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"10 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2017\\\/10\\\/spring-batch-csv-processing.html#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2017\\\/10\\\/spring-batch-csv-processing.html\"},\"author\":{\"name\":\"Michael Good\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/person\\\/d13cc729556b91450ae21878a82139ed\"},\"headline\":\"Spring Batch CSV Processing\",\"datePublished\":\"2017-10-13T07:32:27+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2017\\\/10\\\/spring-batch-csv-processing.html\"},\"wordCount\":1111,\"commentCount\":1,\"publisher\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2017\\\/10\\\/spring-batch-csv-processing.html#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/spring-logo.jpg\",\"keywords\":[\"Spring\",\"Spring Batch\"],\"articleSection\":[\"Enterprise Java\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.javacodegeeks.com\\\/2017\\\/10\\\/spring-batch-csv-processing.html#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2017\\\/10\\\/spring-batch-csv-processing.html\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2017\\\/10\\\/spring-batch-csv-processing.html\",\"name\":\"Spring Batch CSV Processing - Java Code Geeks\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2017\\\/10\\\/spring-batch-csv-processing.html#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2017\\\/10\\\/spring-batch-csv-processing.html#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/spring-logo.jpg\",\"datePublished\":\"2017-10-13T07:32:27+00:00\",\"description\":\"Overview Topics we will be discussing include the essential concepts of batch processing with Spring Batch and how to import the data from a CSV into a\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2017\\\/10\\\/spring-batch-csv-processing.html#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.javacodegeeks.com\\\/2017\\\/10\\\/spring-batch-csv-processing.html\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2017\\\/10\\\/spring-batch-csv-processing.html#primaryimage\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/spring-logo.jpg\",\"contentUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/spring-logo.jpg\",\"width\":150,\"height\":150,\"caption\":\"spring-interview-questions-answers\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2017\\\/10\\\/spring-batch-csv-processing.html#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Java\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/category\\\/java\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Enterprise Java\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/category\\\/java\\\/enterprise-java\"},{\"@type\":\"ListItem\",\"position\":4,\"name\":\"Spring Batch CSV Processing\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#website\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\",\"name\":\"Java Code Geeks\",\"description\":\"Java Developers Resource Center\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\"},\"alternateName\":\"JCG\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.javacodegeeks.com\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\",\"name\":\"Exelixis Media P.C.\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2022\\\/06\\\/exelixis-logo.png\",\"contentUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2022\\\/06\\\/exelixis-logo.png\",\"width\":864,\"height\":246,\"caption\":\"Exelixis Media P.C.\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/logo\\\/image\\\/\"},\"sameAs\":[\"https:\\\/\\\/www.facebook.com\\\/javacodegeeks\",\"https:\\\/\\\/x.com\\\/javacodegeeks\"]},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/person\\\/d13cc729556b91450ae21878a82139ed\",\"name\":\"Michael Good\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/dc6ef7dbff80afe08a3cdc3b0677aaa26021085e041ce1873dc2141bc581b623?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/dc6ef7dbff80afe08a3cdc3b0677aaa26021085e041ce1873dc2141bc581b623?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/dc6ef7dbff80afe08a3cdc3b0677aaa26021085e041ce1873dc2141bc581b623?s=96&d=mm&r=g\",\"caption\":\"Michael Good\"},\"description\":\"Michael is a software engineer located in the Washington DC area that is interested in Java, cyber security, and open source technologies. Follow his personal blog to read more from Michael.\",\"sameAs\":[\"http:\\\/\\\/www.michaelcgood.com\"],\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/author\\\/michael-good\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Spring Batch CSV Processing - Java Code Geeks","description":"Overview Topics we will be discussing include the essential concepts of batch processing with Spring Batch and how to import the data from a CSV into a","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.javacodegeeks.com\/2017\/10\/spring-batch-csv-processing.html","og_locale":"en_US","og_type":"article","og_title":"Spring Batch CSV Processing - Java Code Geeks","og_description":"Overview Topics we will be discussing include the essential concepts of batch processing with Spring Batch and how to import the data from a CSV into a","og_url":"https:\/\/www.javacodegeeks.com\/2017\/10\/spring-batch-csv-processing.html","og_site_name":"Java Code Geeks","article_publisher":"https:\/\/www.facebook.com\/javacodegeeks","article_published_time":"2017-10-13T07:32:27+00:00","og_image":[{"width":150,"height":150,"url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-logo.jpg","type":"image\/jpeg"}],"author":"Michael Good","twitter_card":"summary_large_image","twitter_creator":"@javacodegeeks","twitter_site":"@javacodegeeks","twitter_misc":{"Written by":"Michael Good","Est. reading time":"10 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.javacodegeeks.com\/2017\/10\/spring-batch-csv-processing.html#article","isPartOf":{"@id":"https:\/\/www.javacodegeeks.com\/2017\/10\/spring-batch-csv-processing.html"},"author":{"name":"Michael Good","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/person\/d13cc729556b91450ae21878a82139ed"},"headline":"Spring Batch CSV Processing","datePublished":"2017-10-13T07:32:27+00:00","mainEntityOfPage":{"@id":"https:\/\/www.javacodegeeks.com\/2017\/10\/spring-batch-csv-processing.html"},"wordCount":1111,"commentCount":1,"publisher":{"@id":"https:\/\/www.javacodegeeks.com\/#organization"},"image":{"@id":"https:\/\/www.javacodegeeks.com\/2017\/10\/spring-batch-csv-processing.html#primaryimage"},"thumbnailUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-logo.jpg","keywords":["Spring","Spring Batch"],"articleSection":["Enterprise Java"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.javacodegeeks.com\/2017\/10\/spring-batch-csv-processing.html#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.javacodegeeks.com\/2017\/10\/spring-batch-csv-processing.html","url":"https:\/\/www.javacodegeeks.com\/2017\/10\/spring-batch-csv-processing.html","name":"Spring Batch CSV Processing - Java Code Geeks","isPartOf":{"@id":"https:\/\/www.javacodegeeks.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.javacodegeeks.com\/2017\/10\/spring-batch-csv-processing.html#primaryimage"},"image":{"@id":"https:\/\/www.javacodegeeks.com\/2017\/10\/spring-batch-csv-processing.html#primaryimage"},"thumbnailUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-logo.jpg","datePublished":"2017-10-13T07:32:27+00:00","description":"Overview Topics we will be discussing include the essential concepts of batch processing with Spring Batch and how to import the data from a CSV into a","breadcrumb":{"@id":"https:\/\/www.javacodegeeks.com\/2017\/10\/spring-batch-csv-processing.html#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.javacodegeeks.com\/2017\/10\/spring-batch-csv-processing.html"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.javacodegeeks.com\/2017\/10\/spring-batch-csv-processing.html#primaryimage","url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-logo.jpg","contentUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-logo.jpg","width":150,"height":150,"caption":"spring-interview-questions-answers"},{"@type":"BreadcrumbList","@id":"https:\/\/www.javacodegeeks.com\/2017\/10\/spring-batch-csv-processing.html#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.javacodegeeks.com\/"},{"@type":"ListItem","position":2,"name":"Java","item":"https:\/\/www.javacodegeeks.com\/category\/java"},{"@type":"ListItem","position":3,"name":"Enterprise Java","item":"https:\/\/www.javacodegeeks.com\/category\/java\/enterprise-java"},{"@type":"ListItem","position":4,"name":"Spring Batch CSV Processing"}]},{"@type":"WebSite","@id":"https:\/\/www.javacodegeeks.com\/#website","url":"https:\/\/www.javacodegeeks.com\/","name":"Java Code Geeks","description":"Java Developers Resource Center","publisher":{"@id":"https:\/\/www.javacodegeeks.com\/#organization"},"alternateName":"JCG","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.javacodegeeks.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.javacodegeeks.com\/#organization","name":"Exelixis Media P.C.","url":"https:\/\/www.javacodegeeks.com\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/logo\/image\/","url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","contentUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","width":864,"height":246,"caption":"Exelixis Media P.C."},"image":{"@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/javacodegeeks","https:\/\/x.com\/javacodegeeks"]},{"@type":"Person","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/person\/d13cc729556b91450ae21878a82139ed","name":"Michael Good","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/dc6ef7dbff80afe08a3cdc3b0677aaa26021085e041ce1873dc2141bc581b623?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/dc6ef7dbff80afe08a3cdc3b0677aaa26021085e041ce1873dc2141bc581b623?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/dc6ef7dbff80afe08a3cdc3b0677aaa26021085e041ce1873dc2141bc581b623?s=96&d=mm&r=g","caption":"Michael Good"},"description":"Michael is a software engineer located in the Washington DC area that is interested in Java, cyber security, and open source technologies. Follow his personal blog to read more from Michael.","sameAs":["http:\/\/www.michaelcgood.com"],"url":"https:\/\/www.javacodegeeks.com\/author\/michael-good"}]}},"_links":{"self":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts\/69639","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/users\/5558"}],"replies":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/comments?post=69639"}],"version-history":[{"count":0,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts\/69639\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/media\/240"}],"wp:attachment":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/media?parent=69639"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/categories?post=69639"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/tags?post=69639"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}