{"id":38153,"date":"2015-03-17T13:51:14","date_gmt":"2015-03-17T11:51:14","guid":{"rendered":"http:\/\/www.javacodegeeks.com\/?p=38153"},"modified":"2023-12-05T16:34:20","modified_gmt":"2023-12-05T14:34:20","slug":"spring-batch-tutorial","status":"publish","type":"post","link":"https:\/\/www.javacodegeeks.com\/spring-batch-tutorial.html","title":{"rendered":"Spring Batch Tutorial \u2013 The ULTIMATE Guide"},"content":{"rendered":"<p>This is&nbsp;&nbsp;Spring batch&nbsp;tutorial which is part of the Spring framework. <\/p>\n<p><a href=\"http:\/\/projects.spring.io\/spring-batch\/\">Spring Batch<\/a> provides reusable functions that are essential in processing large volumes of records, including logging\/tracing, transaction management, job processing statistics, job restart, skip, and resource management. It also provides more advanced technical services and features that will enable extremely high-volume and high-performance batch jobs through optimization and partitioning techniques.<\/p>\n<p>Here, you can find a clear explanation about its main components and concepts and several working examples. This tutorial is not about the Spring framework in general; it is expected that you are familiar with mechanisms like Inversion of Control and Dependency Injection, that are the main pillars of the Spring framework. It is also assumed that you know how to configure the Spring framework context for basic applications and that you are used to work with both annotations and configuration files based Spring projects.<\/p>\n<p>If this is not the case, I would really recommend going to the Spring framework official page and learn the basic tutorials before starting to learn what is Spring batch and how it works. In <a href=\"http:\/\/docs.spring.io\/docs\/Spring-MVC-step-by-step\/\">spring docs<\/a> you can find a good one.<\/p>\n<p>At the end of this tutorial, you can find a compressed file with all the examples listed and some extras.<\/p>\n<p>The software used in the elaboration of this tutorial is listed below:<\/p>\n<ul class=\"wp-block-list\">\n<li>Java update 8 Version 3.1<\/li>\n<li>Apache Maven 3.2.5<\/li>\n<li>Eclipse Luna 4.4.1<\/li>\n<li>Spring Batch 3.0.3 and all its dependencies (I really recommend to use Maven or Gradle to resolve all the required dependencies and avoid headaches)<\/li>\n<li>Spring Boot 1.2.2 and all its dependencies (I really recommend to use Maven or Gradle to resolve all the required dependencies and avoid headaches)<\/li>\n<li>MySQL Community Server version 5.6.22<\/li>\n<li>MongoDB 2.6.8<\/li>\n<li>HSQLDB version 1.8.0.10<\/li>\n<\/ul>\n<div class=\"toc\">\n<h2>Table Of Contents<\/h2>\n<dl>\n<dt><a href=\"#intro \">1. Introduction<\/a><\/dt>\n<dt><a href=\"#concepts \">2. Concepts<\/a><\/dt>\n<dt><a href=\"#uses \">3. Use Cases<\/a><\/dt>\n<dt><a href=\"#flow \">4 Controlling flow<\/a><\/dt>\n<dt><a href=\"#custom \">5. Custom Writers, Readers and Processors<\/a><\/dt>\n<dt><a href=\"#example_flat \">6. Flat file example<\/a><\/dt>\n<dt><a href=\"#example_mysql \">7. MySQL example<\/a><\/dt>\n<dt><a href=\"#example_hsqldb \">8. In Memory example<\/a><\/dt>\n<dt><a href=\"#unit_testing \">9. Unit testing<\/a><\/dt>\n<dt><a href=\"#error \">10. Error Handling<\/a><\/dt>\n<dt><a href=\"#parallel \">11. Parallel Processing<\/a><\/dt>\n<dt><a href=\"#repeat \">12. Repeating jobs<\/a><\/dt>\n<dt><a href=\"#jsr352 \">13. JSR 352<\/a><\/dt>\n<dt><a href=\"#summary \">14. Summary<\/a><\/dt>\n<dt><a href=\"#resources \">15. Resources<\/a><\/dt>\n<dt><a href=\"#download\">16. Download the source code<\/a><\/dt>\n<\/dl>\n<\/div>\n<p>This tutorial will not explain how to use Maven although it is used for solving dependencies, compiling, and executing the examples provided. You can learn more in our <a href=\"https:\/\/examples.javacodegeeks.com\/enterprise-java\/maven\/log4j-maven-example\/\">Log4j Maven example<\/a>.<\/p>\n<p>The module Spring boot is also heavily used in the examples, for more information about it please refer to the official <a href=\"http:\/\/projects.spring.io\/spring-boot\/\">Spring Boot documentation<\/a>.<\/p>\n<h2 class=\"wp-block-heading\" id=\"intro\">1. Introduction<\/h2>\n<p>Spring Batch is an open source framework for batch processing. It is built as a module within the Spring framework and depends on this framework (among others). Before continuing with Spring Batch we are going to put here the definition of batch processing:<\/p>\n<p><i>\u201cBatch processing is the execution of a series of programs (&#8220;jobs&#8221;) on a computer without manual intervention\u201d<\/i> (From the Wikipedia).<\/p>\n<p>So, for our matter, a batch application executes a series of jobs (iterative or in parallel), where input data is read, processed and written without any interaction. We are going to see how Spring Batch can help us with this purpose.<\/p>\n<p>Spring Batch provides mechanisms for processing large amount of data like transaction management, job processing, resource management, logging, tracing, conversion of data, interfaces, etc. These functionalities are available out of the box and can be reused by applications containing the Spring Batch framework. By using these diverse techniques, the framework takes care of the performance and the scalability while processing the records.<\/p>\n<p>Normally a batch application can be divided in three main parts:<\/p>\n<ul class=\"wp-block-list\">\n<li>Reading the data (from a database, file system, etc.)<\/li>\n<li>Processing the data (filtering, grouping, calculating, validating\u2026)<\/li>\n<li>Writing the data (to a database, reporting, distributing\u2026)<\/li>\n<\/ul>\n<p>Spring Batch contains features and abstractions (as we will explain in this article) for automating these basic steps and allowing the application programmers to configure them, repeat them, retry them, stop them, executing them as a single element or grouped (transaction management), etc.<\/p>\n<p>It also contains classes and interfaces for the main data formats, industry standards and providers like XML, CSV, SQL, Mongo DB, etc.<\/p>\n<p>In the next chapters of this tutorial we are going to explain and provide examples of all these steps and the difference possibilities that Spring Batch offers.<\/p>\n<h2 class=\"wp-block-heading\" id=\"concepts\">2. Concepts<\/h2>\n<p>Here are the most important concepts in the Spring Batch framework:<\/p>\n<h3 class=\"wp-block-heading\">Jobs<\/h3>\n<p>Jobs are abstractions to represent batch processes, that is, sequences of actions or commands that have to be executed within the batch application.<\/p>\n<p>Spring batch contains an interface to <a href=\"http:\/\/docs.spring.io\/spring-batch\/apidocs\/org\/springframework\/batch\/core\/Job.html\">represent Jobs<\/a>. Simple Jobs contain a list of steps and these are executed sequentially or in parallel.<\/p>\n<p>In order to configure a Job it is enough to initialize the list of steps, this is an example of an xml based configuration for a dummy Job:<\/p>\n<pre class=\"wp-block-preformatted brush:xml\">&lt;job id=\"eatJob\" xmlns=\"http:\/\/www.springframework.org\/schema\/batch\"&gt;\n\t&lt;step id=\"stepCook\" next=\"stepEntries\"&gt;\n\t  &lt;tasklet&gt;\n\t\t&lt;chunk reader=\"cookReader\" writer=\"cookProcessor\"  \n                    processor=\"cookWriter\" commit-interval=\"1\" \/&gt;\n\t  &lt;\/tasklet&gt;\n\t&lt;\/step&gt;\n\t&lt;step id=\"stepEntries\" next=\"stepMeat\"&gt;\n\t  &lt;tasklet&gt;\n\t\t&lt;chunk reader=\"entriesReader\" writer=\"entriesProcessor\"  \n                    processor=\"entriesWriter\" commit-interval=\"1\" \/&gt;\n\t  &lt;\/tasklet&gt;\n\t&lt;\/step&gt;\n\t&lt;step id=\"stepMeat\" next=\"stepWine\"&gt;\n\t  &lt;tasklet ref=\"drinkSomeWine\" \/&gt;\n\t&lt;\/step&gt;\n\t&lt;step id=\"stepWine\" next=\"clean\"&gt;\n\t  &lt;tasklet&gt;\n\t\t&lt;chunk reader=\"wineReader\" writer=\"wineProcessor\"  \n                    processor=\"wineWriter\" commit-interval=\"1\" \/&gt;\n\t  &lt;\/tasklet&gt;\n\t&lt;\/step&gt;\n\t&lt;step id=\"clean\"&gt;\n\t\t&lt;tasklet ref=\"cleanTheTable\" \/&gt;\n\t&lt;\/step&gt;\n  &lt;\/job&gt;\n<\/pre>\n<h3 class=\"wp-block-heading\">Job launcher<\/h3>\n<p>This <a href=\"http:\/\/docs.spring.io\/spring-batch\/apidocs\/org\/springframework\/batch\/core\/launch\/JobLauncher.html\">interface<\/a> represents a Job Launcher. Implementations of its run() method takes care of starting job executions for the given jobs and job parameters.<\/p>\n<h3 class=\"wp-block-heading\">Job instance<\/h3>\n<p>This is an abstraction representing a single run for a given Job. It is unique and identifiable. The class representing this abstraction is <a href=\"http:\/\/docs.spring.io\/spring-batch\/apidocs\/org\/springframework\/batch\/core\/JobInstance.html\">http:\/\/docs.spring.io\/spring-batch\/apidocs\/org\/springframework\/batch\/core\/JobInstance.html<\/a>.<\/p>\n<p>Job instances can be restarted in case they were not completed successfully and if the Job is restart able. Otherwise an error will be raised.<\/p>\n<h3 class=\"wp-block-heading\">Steps<\/h3>\n<p>Steps are mainly the parts that compose a Job (and a Job instance). A <code>Step<\/code> is a part of a <code>Job<\/code> and contains all the necessary information to execute the batch processing actions that are expected to be done at that phase of the job. Steps in Spring Batch are composed of <code>ItemReader<\/code>, <code>ItemProcessor<\/code> and <code>ItemWriter<\/code> and can be very simple or extremely complicated depending on the complexity of their members.<\/p>\n<p>Steps also contain configuration options for their processing strategy, commit interval, transaction mechanism or job repositories that may be used. Spring Batch uses normally chunk processing, that is reading all data at one time and processing and writing \u201cchunks\u201d of this data on a preconfigured interval, called commit interval.<\/p>\n<p>Here is a very basic example of a xml based step configuration using an interval of 10:<\/p>\n<pre class=\"wp-block-preformatted brush:xml\">&lt;step id=\"step\" next=\"nextStep\"&gt;\n  &lt;tasklet&gt;\n    &lt;chunk reader=\"customItemReader\" writer=\"customItemWriter\" processor=\"customItemProcessor\" commit-interval=\"10\" \/&gt;\n  &lt;\/tasklet&gt;\n&lt;\/step&gt;\n<\/pre>\n<p>And the following snippet is the annotation based version defining the readers, writers and processors involved, a chunk processing strategy and a commit interval of 10 (this is the one that we are using in the majority of examples in this tutorial):<\/p>\n<pre class=\"wp-block-preformatted brush:java\">@Bean\npublic Step step1(StepBuilderFactory stepBuilderFactory,\n\t\tItemReader reader, ItemWriter writer,\n\t\tItemProcessor processor) {\n\t\/* it handles bunches of 10 units *\/\n\treturn stepBuilderFactory.get(\"step1\")\n\t\t\t. chunk(10).reader(reader)\n\t\t\t.processor(processor).writer(writer).build();\n}\n<\/pre>\n<h3 class=\"wp-block-heading\">Job Repositories<\/h3>\n<p>Job repositories are abstractions responsible for storing and updating metadata information related to Job instance executions and Job contexts. The basic interface that has to be implemented in order to configure a Job Repository <a href=\"\/\/docs.spring.io\/spring-batch\/apidocs\/org\/springframework\/batch\/core\/repository\/JobRepository.html\">can be found here<\/a>.<\/p>\n<p>Spring stores as metadata information about their executions, the results obtained their instances, the parameters used for the Jobs executed, and the context where the processing runs. The table names are very intuitive and similar to their domain classes counterparts, <a href=\"http:\/\/docs.spring.io\/spring-batch\/reference\/html\/images\/meta-data-erd.png\">in this link<\/a>, there is an image with a very good summary of these tables.<\/p>\n<p>Please visit the <a href=\"http:\/\/docs.spring.io\/spring-batch\/reference\/html\/metaDataSchema.html\">Spring Batch metadata schema<\/a> for more information.<\/p>\n<h3 class=\"wp-block-heading\">Item Readers<\/h3>\n<p>Readers are abstractions responsible of the data retrieval. They provide batch processing applications with the needed input data. We will see in this tutorial how to create custom readers and we will see how to use some of the most important Spring Batch predefined ones. Here is a list of some readers provided by Spring Batch:<\/p>\n<ul class=\"wp-block-list\">\n<li>AmqpItemReader<\/li>\n<li>AggregateItemReader<\/li>\n<li>FlatFileItemReader<\/li>\n<li>HibernateCursorItemReader<\/li>\n<li>HibernatePagingItemReader<\/li>\n<li>IbatisPagingItemReader<\/li>\n<li>ItemReaderAdapter<\/li>\n<li>JdbcCursorItemReader<\/li>\n<li>JdbcPagingItemReader<\/li>\n<li>JmsItemReader<\/li>\n<li>JpaPagingItemReader<\/li>\n<li>ListItemReader<\/li>\n<li>MongoItemReader<\/li>\n<li>Neo4jItemReader<\/li>\n<li>RepositoryItemReader<\/li>\n<li>StoredProcedureItemReader<\/li>\n<li>StaxEventItemReader<\/li>\n<\/ul>\n<p>We can see that Spring Batch already provides readers for many of the formatting standards and database industry providers. It is recommended to use the abstractions provided by Spring Batch in your applications rather than creating your own ones.<\/p>\n<h3 class=\"wp-block-heading\">Item Writers<\/h3>\n<p>Writers are abstractions responsible of writing the data to the desired output database or system. The same that we explained for Readers is applicable to Writers: Spring Batch already provides classes and interfaces to deal with many of the most used databases, these should be used. Here is a list of some of these provided writers:<\/p>\n<ul class=\"wp-block-list\">\n<li>AbstractItemStreamItemWriter<\/li>\n<li>AmqpItemWriter<\/li>\n<li>CompositeItemWriter<\/li>\n<li>FlatFileItemWriter<\/li>\n<li>GemfireItemWriter<\/li>\n<li>HibernateItemWriter<\/li>\n<li>IbatisBatchItemWriter<\/li>\n<li>ItemWriterAdapter<\/li>\n<li>JdbcBatchItemWriter<\/li>\n<li>JmsItemWriter<\/li>\n<li>JpaItemWriter<\/li>\n<li>MimeMessageItemWriter<\/li>\n<li>MongoItemWriter<\/li>\n<li>Neo4jItemWriter<\/li>\n<li>StaxEventItemWriter<\/li>\n<li>RepositoryItemWriter<\/li>\n<\/ul>\n<p>In this article we will show how to create custom writers and how to use some of the listed ones.<\/p>\n<h3 class=\"wp-block-heading\">Item Processors<\/h3>\n<p>Processors are in charge of modifying the data records converting them from the input format to the output desired one. The main interfaces used for Item Processors configuration can be found <a href=\"http:\/\/docs.spring.io\/spring-batch\/trunk\/apidocs\/org\/springframework\/batch\/item\/ItemProcessor.html\">here<\/a>.<\/p>\n<p>In this article we will see how to create our custom item processors.<\/p>\n<p>The following picture (from the <a href=\"http:\/\/docs.spring.io\/spring-batch\/reference\/html\/images\/spring-batch-reference-model.png\">Spring batch documentation<\/a>) gives a very good summary of all these concepts and how the basic Spring Batch architecture is designed:<\/p>\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter\"><a href=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2015\/03\/spring-batch-reference-model.png\"><img decoding=\"async\" width=\"738\" height=\"294\" src=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2015\/03\/spring-batch-reference-model.png\" alt=\"Spring Batch Tutorial: Spring Batch Reference Model\" class=\"wp-image-38367\" srcset=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2015\/03\/spring-batch-reference-model.png 738w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2015\/03\/spring-batch-reference-model-300x120.png 300w\" sizes=\"(max-width: 738px) 100vw, 738px\" \/><\/a><figcaption>Spring Batch Reference Model<\/figcaption><\/figure>\n<\/div>\n<h2 class=\"wp-block-heading\" id=\"uses\">3. Use Cases<\/h2>\n<p>Although it is difficult to categorize the use cases where batch processing can be applied in the real world, I am going to try to list in this chapter the most important ones:<\/p>\n<ul class=\"wp-block-list\">\n<li><strong>Conversion Applications:<\/strong> These are applications that convert input records into the required structure or format. These applications can be used in all the phases of the batch processing (reading, processing and writing).<\/li>\n<li><strong>Filtering or validation applications:<\/strong> These are programs with the goal of filtering valid records for further processing. Normally validation happens in the first phases of the batch processing.<\/li>\n<li><strong>Database extractors:<\/strong> These are applications that read data from a database or input files and write the desired filtered data to an output file or to other database. There are also applications that updates large amounts of data in the same database where the input records come from. As a real life example we can think of a system that analyzes log files with different end user behaviors and, using this data, produces reports with statistics about most active users, most active periods of time, etc.<\/li>\n<li><strong>Reporting:<\/strong> These are applications that read large amounts of data from a database or input files, process this data and produce formatted documents based on that data that are suitable for printing or sending via other systems. Accounting and Legal Banking systems can be part of this category: at the end of the business day, these systems read information from the databases, extract the data required and write this data into legal documents that may be sent to different authorities.<\/li>\n<\/ul>\n<p>Spring Batch provides mechanisms to support all these scenarios, with the elements and components listed in the previous chapter programmers can implement batch applications for conversion of data, filtering records, validation, extracting information from databases or input files and reporting.<div style=\"display:inline-block; margin: 15px 0;\"> <div id=\"adngin-JavaCodeGeeks_incontent_video-0\" style=\"display:inline-block;\"><\/div> <\/div><\/p>\n<h2 class=\"wp-block-heading\" id=\"flow\">4. Controlling flow<\/h2>\n<p>Before starting talking about specific Jobs and Steps I am going to show how a Spring Batch configuration class looks like. The next snippet contains a configuration class with all the components needed for batch processing using Spring Batch. It contains readers, writers, processors, job flows, steps and all other needed beans.<\/p>\n<p>During this tutorial we will show how to modify this configuration class in order to use different abstractions for our different purposes. The class bellow is pasted without comments and specific code, for the working class example please go to the download section in this tutorial where you can download all the sources:<\/p>\n<pre class=\"wp-block-preformatted brush:java\">@Configuration\n@EnableBatchProcessing\npublic class SpringBatchTutorialConfiguration {\n\n@Bean\npublic ItemReader reader() {\n\treturn new CustomItemReader();\n}\n\n@Bean\npublic ItemProcessor processor() {\n\treturn new CustomItemProcessor();\n}\n\n@Bean\npublic ItemWriter writer(DataSource dataSource) {\n\treturn new CustomItemItemWriter(dataSource);\n}\n\n@Bean\npublic Job job1(JobBuilderFactory jobs, Step step1) {\n\treturn jobs.get(\"job1\").incrementer(new RunIdIncrementer())\n\t\t\t.flow(step1).end().build();\n}\n\n@Bean\npublic Step step1(StepBuilderFactory stepBuilderFactory,\n\t\tItemReader reader, ItemWriter writer,\n\t\tItemProcessor processor) {\n\t\/* it handles bunches of 10 units *\/\n\treturn stepBuilderFactory.get(\"step1\")\n\t\t\t. chunk(10).reader(reader)\n\t\t\t.processor(processor).writer(writer).build();\n}\n\n@Bean\npublic JdbcTemplate jdbcTemplate(DataSource dataSource) {\n\treturn new JdbcTemplate(dataSource);\n}\n\n\n@Bean\npublic DataSource mysqlDataSource() throws SQLException {\nfinal DriverManagerDataSource dataSource = new DriverManagerDataSource();\n\tdataSource.setDriverClassName(\"com.mysql.jdbc.Driver\");\n\tdataSource.setUrl(\"jdbc:mysql:\/\/localhost\/spring_batch_annotations\");\n\tdataSource.setUsername(\"root\");\n\tdataSource.setPassword(\"root\");\n\treturn dataSource;\n}\n\n...\n<\/pre>\n<p>In order to launch our spring context and execute the configured batch shown before we are going to use Spring Boot. Here is an example of a program that takes care of launching our application and initializing the Spring context with the proper configuration. This program is used with all the examples shown in this tutorial:<\/p>\n<pre class=\"wp-block-preformatted brush:java\">@SpringBootApplication\npublic class SpringBatchTutorialMain implements CommandLineRunner {\n\n\tpublic static void main(String[] args) {\n\n\t\tSpringApplication.run(SpringBatchTutorialMain.class, args);\n\t}\n\n\t\n\t@Override\n\tpublic void run(String... strings) throws Exception {\n\n\t\tSystem.out.println(\"running...\");\n\t}\n\n}\n<\/pre>\n<p>I am using Maven to resolve all the dependencies and launching the application using Spring boot. Here is the used <code>pom.xml<\/code>:<\/p>\n<pre class=\"wp-block-preformatted brush:xml\">&lt;?xml version=\"1.0\" encoding=\"UTF-8\"?&gt;\n&lt;project xmlns=\"http:\/\/maven.apache.org\/POM\/4.0.0\" xmlns:xsi=\"http:\/\/www.w3.org\/2001\/XMLSchema-instance\"\n    xsi:schemaLocation=\"http:\/\/maven.apache.org\/POM\/4.0.0 http:\/\/maven.apache.org\/xsd\/maven-4.0.0.xsd\"&gt;\n    &lt;modelVersion&gt;4.0.0&lt;\/modelVersion&gt;\n\n    &lt;groupId&gt;com.danibuiza.javacodegeeks&lt;\/groupId&gt;\n    &lt;artifactId&gt;Spring-Batch-Tutorial-Annotations&lt;\/artifactId&gt;\n    &lt;version&gt;0.1.0&lt;\/version&gt;\n\n    &lt;parent&gt;\n        &lt;groupId&gt;org.springframework.boot&lt;\/groupId&gt;\n        &lt;artifactId&gt;spring-boot-starter-parent&lt;\/artifactId&gt;\n        &lt;version&gt;1.2.1.RELEASE&lt;\/version&gt;\n    &lt;\/parent&gt;\n\n    &lt;dependencies&gt;\n        &lt;dependency&gt;\n            &lt;groupId&gt;org.springframework.boot&lt;\/groupId&gt;\n            &lt;artifactId&gt;spring-boot-starter-batch&lt;\/artifactId&gt;\n        &lt;\/dependency&gt;\n        &lt;dependency&gt;\n            &lt;groupId&gt;org.hsqldb&lt;\/groupId&gt;\n            &lt;artifactId&gt;hsqldb&lt;\/artifactId&gt;\n        &lt;\/dependency&gt;\n        &lt;dependency&gt;\n\t\t\t&lt;groupId&gt;mysql&lt;\/groupId&gt;\n\t\t\t&lt;artifactId&gt;mysql-connector-java&lt;\/artifactId&gt;\n\t\t&lt;\/dependency&gt;\n    &lt;\/dependencies&gt;\n\n\n    &lt;build&gt;\n        &lt;plugins&gt;\n            &lt;plugin&gt;\n                &lt;groupId&gt;org.springframework.boot&lt;\/groupId&gt;\n                &lt;artifactId&gt;spring-boot-maven-plugin&lt;\/artifactId&gt;\n            &lt;\/plugin&gt;\n        &lt;\/plugins&gt;\n    &lt;\/build&gt;\n&lt;\/project&gt;\n\n<\/pre>\n<p>And the goal used is:<\/p>\n<pre class=\"wp-block-preformatted\">mvn spring-boot:run\n<\/pre>\n<p>Now we are going to go through the configuration file shown above step by step. First of all we are going to explain how <code>Jobs<\/code> and <code>Steps<\/code> are executed and what rules they follow.<\/p>\n<p>In the example application pasted above we can see how a Job and a first step are configured. Here we extract the related piece of code:<\/p>\n<pre class=\"wp-block-preformatted brush:java\">\t@Bean\n\tpublic Job job1(JobBuilderFactory jobs, Step step1) {\n\t\treturn jobs.get(\"job1\").incrementer(new RunIdIncrementer())\n\t\t\t\t.flow(step1).end().build();\n\t}\n\n\t@Bean\n\tpublic Step step1(StepBuilderFactory stepBuilderFactory,\n\t\t\tItemReader reader, ItemWriter writer,\n\t\t\tItemProcessor processor) {\n\t\t\/* it handles bunches of 10 units *\/\n\t\treturn stepBuilderFactory.get(\"step1\")\n\t\t\t\t. chunk(10).reader(reader)\n\t\t\t\t.processor(processor).writer(writer).build();\n\t}\n<\/pre>\n<p>We can observe how a Job with the name \u201cjob1\u201d is configured using just one step; in this case an step called \u201cstep1\u201d. The class <a href=\"http:\/\/docs.spring.io\/spring-batch\/apidocs\/org\/springframework\/batch\/core\/configuration\/annotation\/JobBuilderFactory.html\">JobBuilderFactory<\/a> creates a job builder and initializes the job repository. The method <code>flow()<\/code> of the class <a href=\"http:\/\/docs.spring.io\/spring-batch\/apidocs\/org\/springframework\/batch\/core\/job\/builder\/JobBuilder.html\">JobBuilder<\/a> creates an instance of the class <a href=\"http:\/\/docs.spring.io\/spring-batch\/apidocs\/org\/springframework\/batch\/core\/job\/builder\/JobFlowBuilder.html\">JobFlowBuilder<\/a> using the step1 method shown. This way the whole context is initialized and the Job \u201cjob1\u201d is executed.<\/p>\n<p>The step processes (using the processor) in chunks of 10 units the <code>CustomPojo<\/code> records provided by the reader and writes them using the past writer. All dependencies are injected in runtime, Spring takes care of that since the class where all this happens is marked as a configuration class using the annotation <code> org.springframework.context.annotation.Configuration <\/code>.<\/p>\n<h2 class=\"wp-block-heading\">5. Custom Writers, Readers and Processors<\/h2>\n<p>As we already mentioned in this tutorial, Spring Batch applications consist basically of three steps: reading data, processing data and writing data. We also explained that in order to support these 3 operations Spring Batch provides 3 abstractions in form of interfaces:<\/p>\n<ul class=\"wp-block-list\">\n<li><a href=\"\/\/docs.spring.io\/spring-batch\/trunk\/apidocs\/org\/springframework\/batch\/item\/ItemReader.html\">ItemReader<\/a><\/li>\n<li><a href=\"http:\/\/docs.spring.io\/spring-batch\/trunk\/apidocs\/org\/springframework\/batch\/item\/ItemWriter.html\">ItemWriter<\/a><\/li>\n<li><a href=\"http:\/\/docs.spring.io\/spring-batch\/trunk\/apidocs\/org\/springframework\/batch\/item\/ItemProcessor.html\">ItemProcessor<\/a><\/li>\n<\/ul>\n<p>Programmers should implement these interfaces in order to read, process and write data in their batch application jobs and steps. In this chapter we are going to explain how to create custom implementations for these abstractions.<\/p>\n<h3 class=\"wp-block-heading\" id=\"custom\">Custom Reader<\/h3>\n<p>The abstraction provided by Spring Batch for reading records of data is the interface <code>ItemReader<\/code>. It only has one method (<code>read()<\/code>) and it is supposed to be executed several times; it does not need to be thread safe, this fact is very important to know by applications using these methods.<\/p>\n<p>The method <code>read()<\/code> of the interface <code>ItemReader<\/code> has to be implemented. This method expects no input parameters, is supposed to read one record of the data from the desired queue and returns it. This method is not supposed to do any transformation or data processing. If null is returned, no further data has to be read or analyzed.<\/p>\n<pre class=\"wp-block-preformatted brush:java\">public class CustomItemReader implements ItemReader {\n\n\tprivate List pojos;\n\n\tprivate Iterator iterator;\n\n\t@Override\n\tpublic CustomPojo read() throws Exception, UnexpectedInputException,\n\t\t\tParseException, NonTransientResourceException {\n\n\t\tif (getIterator().hasNext()) {\n\t\t\treturn getIterator().next();\n\t\t}\n\t\treturn null;\n\n\t}\n. . .\n<\/pre>\n<p>The custom reader above reads the next element in the internal list of <code>pojos<\/code>, this is only possible if the iterator is initialized or injected when the custom reader is created, if the iterator is instantiated every time the <code>read()<\/code> method is called, the job using this reader will never end and cause problems.<\/p>\n<h3 class=\"wp-block-heading\">Custom Processor<\/h3>\n<p>The interface provided by Spring Batch for data processing expects one input item and produces one output item. The type of both of them can be different but does not have to be different. Producing null means that the item is not required for further processing any more in case of concatenation.<\/p>\n<p>In order to implement this interface, it is only necessary to implement the <code>process()<\/code> method. Here is a dummy example:<\/p>\n<pre class=\"wp-block-preformatted brush:java\">public class CustomItemProcessor implements ItemProcessor {\n\n\t@Override\n\tpublic CustomPojo process(final CustomPojo pojo) throws Exception {\n\t\tfinal String id = encode(pojo.getId());\n\t\tfinal String desc = encode(pojo.getDescription());\n\n\t\tfinal CustomPojo encodedPojo = new CustomPojo(id, desc);\n\n\t\treturn encodedPojo;\n\n\t}\n\n\tprivate String encode(String word) {\n\t\tStringBuffer str = new StringBuffer(word);\n\t\treturn str.reverse().toString();\n\t}\n\n}\n<\/pre>\n<p>The class above may not be useful in any real life scenario but shows how to override the <code>ItemProcessor<\/code> interface and do whatever actions (in this case reversing the input pojo members) are needed in the process method.<\/p>\n<h3 class=\"wp-block-heading\">Custom Writer<\/h3>\n<p>In order to create a custom writer programmers need to implement the interface <code>ItemWriter<\/code>. This interface only contains one method <code>write()<\/code> that expects an input item and returns <code>void<\/code>. The write method can do whatever actions are wanted: writing in the database, writing in a csv file, sending an email, creating a formatted document etc. The implementations of this interface are in charge of flushing the data and leave structures in a safe state.<\/p>\n<p>Here is an example of a custom writer where the input item is written in the standard console:<\/p>\n<pre class=\"wp-block-preformatted brush:java\">public class CustomItemWriter implements ItemWriter {\n\n\t@Override\n\tpublic void write(List pojo) throws Exception {\n\t\tSystem.out.println(\"writing Pojo \" + pojo);\n\t}\n\n}\n<\/pre>\n<p>Also not very useful in real life, only for learning purposes.<\/p>\n<p>It is also important to mention that for almost all real life scenarios Spring Batch already provides specific abstractions that cope with most of the problems. For example Spring Batch contains classes to read data from MySQL databases, or to write data to a HSQLDB database, or to convert data from XML to CSV using JAXB; and many others. The code is clean, fully tested, standard and adopted by the industry, so I can just recommend to use them.<\/p>\n<p>These classes can also be overridden in our applications in order to fulfil our wishes without the need of re implement the whole logic. Implementing the provided classes by Spring may be also useful for testing, debugging, logging or reporting purposes. So before discovering the wheel again and again, it would be worth to check the Spring Batch documentation and tutorials because probably we will find a better and cleaner way to solve our specific problems.<\/p>\n<h2 class=\"wp-block-heading\" id=\"example_flat\">6. Flat file example<\/h2>\n<p>Using the example above, we are going to modify the readers and writers in order to be able to read from a csv file and write into a flat file as well. The following snippet shows how we should configure the reader in order to provide a reader that extracts the data from a flat file, csv in this case. For this purpose Spring already provides the class <a href=\"http:\/\/docs.spring.io\/spring-batch\/trunk\/apidocs\/org\/springframework\/batch\/item\/file\/FlatFileItemReader.html\">FlatFileItemReader<\/a> that needs a resource property where the data should be coming from and a line mapper to be able to parse the data contained in that resource. The code is quite intuitive:<\/p>\n<pre class=\"wp-block-preformatted brush:java\">@Bean\npublic ItemReader reader() {\n\tif (\"flat\".equals(this.mode)) {\n\t\t\/\/ flat file item reader (using an csv extractor)\n\t\tFlatFileItemReader reader = new FlatFileItemReader();\n\t\t\/\/setting resource and line mapper\n\t\treader.setResource(new ClassPathResource(\"input.csv\"));\n\t\treader.setLineMapper(new DefaultLineMapper() {\n\t\t{\n\t\t\t\/\/default line mapper with a line tokenizer and a field mapper\n\t\t\tsetLineTokenizer(new DelimitedLineTokenizer() {\n\t\t\t{\n\t\t\t\tsetNames(new String[] { \"id\", \"description\" });\n\t\t\t}});\n\t\t\tsetFieldSetMapper(new BeanWrapperFieldSetMapper() {\n\t\t\t{\n\t\t\t\tsetTargetType(CustomPojo.class);\n\t\t\t}});\n\t\t}\n\t\t});\n\treturn reader;\n\t} \n\telse {\n\t\t\t. . .\n<\/pre>\n<p>The following piece of code shows the modifications that are needed in the writer. In this case we are going to use a writer of the class <a href=\"http:\/\/docs.spring.io\/spring-batch\/trunk\/apidocs\/org\/springframework\/batch\/item\/file\/FlatFileItemWriter.html\">FlatFileItemWriter<\/a> that needs an output file to write to and an extractor mechanism. The extractor can be configured as shown in the snippet:<\/p>\n<pre class=\"wp-block-preformatted brush:java\">@Bean\npublic ItemWriter writer(DataSource dataSource) {\n\t...\n\telse if (\"flat\".equals(this.mode)) {\n\t\t\/\/ FlatFileItemWriter writer\n\t\tFlatFileItemWriter writer = new FlatFileItemWriter ();\n\t\twriter.setResource(new ClassPathResource(\"output.csv\"));\n\t\tBeanWrapperFieldExtractor fieldExtractor = new CustomFieldExtractor();\n\t\tfieldExtractor.setNames(new String[] { \"id\", \"description\" });\n\t\tDelimitedLineAggregator delLineAgg = new CustomDelimitedAggregator();\n\t\tdelLineAgg.setDelimiter(\",\");\n\t\tdelLineAgg.setFieldExtractor(fieldExtractor);\n\t\twriter.setLineAggregator(delLineAgg);\n\t\treturn writer;\n\t} \n\telse {\n\t. . .\n\t}\n\t\n<\/pre>\n<h2 class=\"wp-block-heading\" id=\"example_mysql\">7. MySQL example<\/h2>\n<p>In this chapter we are going to see how to modify our writer and our data source in order to write processed records to a local MySQL DB.<\/p>\n<p>If we want to read data from a MySQL DB we first need to modify the configuration of the data source bean with the needed connection parameters:<\/p>\n<pre class=\"wp-block-preformatted brush:java\">@Bean\npublic DataSource dataSource() throws SQLException {\n. . .\nelse if (\"mysql\".equals(this.mode)) {\n\t\/\/ mysql data source\n\tfinal DriverManagerDataSource dataSource = new DriverManagerDataSource();\n\tdataSource.setDriverClassName(\"com.mysql.jdbc.Driver\");\n\tdataSource.setUrl(\"jdbc:mysql:\/\/localhost\/spring_batch_annotations\");\n\tdataSource.setUsername(\"root\");\n\tdataSource.setPassword(\"root\");\n\treturn dataSource;\n} else {\n. . .\n<\/pre>\n<p>Here is how the writer can be modified using an SQL statement and a <code> JdbcBatchItemWriter<\/code> that gets initialized with the data source shown above:<\/p>\n<pre class=\"wp-block-preformatted brush:bash\">@Bean\npublic ItemWriter writer(DataSource dataSource) {\n...\t\t\nelse if (\"mysql\".equals(this.mode)) {\n\tJdbcBatchItemWriter writer = new JdbcBatchItemWriter();\n\twriter.setSql(\"INSERT INTO pojo (id, description) VALUES (:id, :description)\");\n\twriter.setDataSource(dataSource);\n\twriter.setItemSqlParameterSourceProvider(\n\t\tnew BeanPropertyItemSqlParameterSourceProvider());\n\treturn writer;\n}\n.. .\n<\/pre>\n<p>It is good to mention here, that there are problems with the required <a href=\"http:\/\/stackoverflow.com\/questions\/28627206\/spring-batch-exception-cannot-construct-java-util-mapentry\">Jettison library<\/a>.<\/p>\n<p>[ulp id=&#8217;oiCtu6x3AwpaVNPI&#8217;]<\/p>\n<p>&nbsp;<\/p>\n<h2 class=\"wp-block-heading\">8. In Memory DB (HSQLDB) example<\/h2>\n<p>As third example we are going to show how to create readers and writers in order to use an in memory database, this is very useful for testing scenarios. By default, if nothing else is specified, Spring Batch choose HSQLDB as data source.<\/p>\n<p>The data source to be used is in this case the same one as for a MySQL DB but with different parameters (containing the HSQLDB configuration):<\/p>\n<pre class=\"wp-block-preformatted brush:java\">@Bean\npublic DataSource dataSource() throws SQLException {\n\t. . .\n\t} else {\n\t\t\/\/ hsqldb datasource\nfinal DriverManagerDataSource dataSource = new DriverManagerDataSource();\n\t\tdataSource.setDriverClassName(\"org.hsqldb.jdbcDriver\");\n\t\tdataSource.setUrl(\"jdbc:hsqldb:mem:test\");\n\t\tdataSource.setUsername(\"sa\");\n\t\tdataSource.setPassword(\"\");\n\t\treturn dataSource;\n\t\t}\n\t}\n<\/pre>\n<p>The writer does not differ (almost) from the MySQL one:<\/p>\n<pre class=\"wp-block-preformatted brush:java\">@Bean\npublic ItemWriter writer(DataSource dataSource) {\n\tif (\"hsqldb\".equals(this.mode)) {\n\t\t\/\/ hsqldb writer using JdbcBatchItemWriter (the difference is the\n\t\t\/\/ datasource)\n\t\tJdbcBatchItemWriter writer = new JdbcBatchItemWriter();\n\t\twriter.setItemSqlParameterSourceProvider(new BeanPropertyItemSqlParameterSourceProvider());\n\t\twriter.setSql(\"INSERT INTO pojo (id, description) VALUES (:id, :description)\");\n\t\twriter.setDataSource(dataSource);\n\t\treturn writer;\n\t} else\n\t. . .\n<\/pre>\n<p>If we want that Spring takes care of the initialization of the DB to be used we can create an script with the name schema-all.sql (for all providers, schema-hsqldb.sql for Hsqldb, schema-mysql.sql for MySQL, etc.) in the resources project of our project:<\/p>\n<pre class=\"wp-block-preformatted brush:bash\">DROP TABLE IF EXISTS POJO;\n\nCREATE TABLE POJO  (\n    id VARCHAR(20),\n    description VARCHAR(20)\n);\n<\/pre>\n<p>This script is also provided in the download section at the end of the tutorial.<\/p>\n<h2 class=\"wp-block-heading\" id=\"unit_testing\">9. Unit testing<\/h2>\n<p>In this chapter we are going to see briefly how to test Batch applications using the Spring Batch testing capabilities. This chapter does not explain how to test Java applications in general or Spring based ones in particular. It only covers how to test from end to end Spring Batch applications, only Jobs or Steps testing is covered; that is why unit testing of single elements like item processors, readers or writers is excluded, since this does not differ from normal unit testing.<\/p>\n<p>The Spring Batch Test Project contains abstractions that facilitate the unit testing of batch applications.<\/p>\n<p>Two annotations are basic when running unit tests (using Junit in this case) in Spring:<\/p>\n<ul class=\"wp-block-list\">\n<li>@RunWith(SpringJUnit4ClassRunner.class): Junit annotation to execute all methods marked as tests. With the <code>SpringJunit4ClassRunner<\/code> class passed as parameter we are indicating that this class can use all spring testing capabilities.<\/li>\n<li>@ContextConfiguration(locations = {. . .}): we will not use the &#8220;locations&#8221; property because we are not using xml configuration files but configuration classes directly.<\/li>\n<\/ul>\n<p>Instances of the <a href=\"http:\/\/docs.spring.io\/spring-batch\/trunk\/apidocs\/org\/springframework\/batch\/test\/JobLauncherTestUtils.html\">class<\/a> can be used for launching jobs and single steps inside the unit test methods (among many other functionalities. Its method <code>launchJob()<\/code> executes a Job and its method <code>launchStep(\"name\")<\/code> executes an step from end to end. In the following example you can see how to use these methods in real jUnit tests:<\/p>\n<pre class=\"wp-block-preformatted brush:java\">@RunWith(SpringJUnit4ClassRunner.class)\n@ContextConfiguration(classes=SpringBatchTutorialConfiguration.class, loader=AnnotationConfigContextLoader.class)\npublic class SpringBatchUnitTest {\n\n\t@Autowired\n\tprivate JobLauncherTestUtils jobLauncherTestUtils;\n\t\n\t@Autowired\n\tJdbcTemplate jdbcTemplate;\n\n\t@Test\n\tpublic void testLaunchJob() throws Exception {\n\n\t\t\/\/ test a complete job\n\t\tJobExecution jobExecution = jobLauncherTestUtils.launchJob();\n\t\tassertEquals(BatchStatus.COMPLETED, jobExecution.getStatus());\n\n\t}\n\n\t@Test\n\tpublic void testLaunchStep() {\n\n\t\t\/\/ test a individual step\n\t\tJobExecution jobExecution = jobLauncherTestUtils.launchStep(\"step1\");\n\t\tassertEquals(BatchStatus.COMPLETED, jobExecution.getStatus());\n\t}\n}\n\n<\/pre>\n<p>You can assert or validate the tests checking the status of the Job execution for complete Jobs unit tests or asserting the results of the writer for single steps tests. In the example shown we do not use any xml configuration file, instead we use the already mentioned configuration class. In order to indicate the unit test to load this configuration, the annotation <code> ContextConfiguration<\/code> with the properties &#8220;classes&#8221; and &#8220;loader&#8221; is used:<\/p>\n<pre class=\"wp-block-preformatted brush:bash\">@ContextConfiguration(classes=SpringBatchTutorialConfiguration.class, \n\tloader=AnnotationConfigContextLoader.class)\n<\/pre>\n<p>More information about Spring Batch unit testing can be found in the following tutorial: <a href=\"http:\/\/docs.spring.io\/spring-batch\/trunk\/reference\/html\/testing.html\"> http:\/\/docs.spring.io\/spring-batch\/trunk\/reference\/html\/testing.html<\/a>.<\/p>\n<h2 class=\"wp-block-heading\" id=\"error\">10. Error handling and retrying Jobs<\/h2>\n<p>Spring provides mechanisms for retrying Jobs but since the release 2.2.0 is not anymore part of the Spring Batch framework but included in the <a href=\"http:\/\/docs.spring.io\/spring-retry\/docs\/api\/current\/\">Spring Retry<\/a>. A very good tutorial can be found <a href=\"http:\/\/docs.spring.io\/spring-batch\/trunk\/reference\/html\/retry.html\">here<\/a>.<\/p>\n<p>Retry policies, callbacks and recovery mechanism are part of the framework.<\/p>\n<h2 class=\"wp-block-heading\" id=\"parallel\">11. Parallel Processing<\/h2>\n<p>Spring Batch supports parallel processing in two possible variations (single process and multi process) that we can separate into the following categories. In this chapter we are just going to list these categories and explain briefly how Spring Batch provides solutions to them:<\/p>\n<ul class=\"wp-block-list\">\n<li><strong>Multi-threaded Step (single process):<\/strong> Programmers can implement their readers and writers in a thread safe way, so multi threading can be used and the step processing can be executed in different threats. Spring batch provides out of the box several <code>ItemWriter<\/code> and <code>ItemReader<\/code> implementations. In their description is stated normally if they are thread safe or not. In case this information is not provided or the implementations clearly state that they are not thread safe, programmers can always synchronize the call to the <code>read()<\/code> method. This way, several records can be processed in parallel.<\/li>\n<li><strong>Parallel Steps (single process):<\/strong> If an application modules can be executed in parallel because their logic do not collapse, these different modules can be executed in different steps in a parallel way. This is different to the scenario explained in the last point where each step execution process different records in parallel; here, different steps run in parallel.<br \/>Spring Batch supports this scenario with the element <code>split<\/code>.Here is an example configuration that may help to understand it better:\n<p>&nbsp;<\/p>\n<pre class=\"brush:xml\">        \n&lt;job id=\"havingLunchJob\"&gt;\n&lt;split id=\"split1\" task-executor=\"taskExecutor\" next=\"cleanTableStep\"&gt;\n        &lt;flow&gt;\n            &lt;step id=\"step1\" parent=\"s1\" next=\"eatCakeStep\"\/&gt;\n            &lt;step id=\" eatCakeStep \" parent=\"s2\"\/&gt;\n        &lt;\/flow&gt;\n        &lt;flow&gt;\n            &lt;step id=\"drinkWineStep\" parent=\"s3\"\/&gt;\n        &lt;\/flow&gt;\n&lt;\/split&gt;\n&lt;step id=\" cleanTableStep\" parent=\"parentStep1\"\/&gt;\n. . .\n<\/pre>\n<\/li>\n<li><strong>Remote Chunking of Step (single process):<\/strong> In this mode, steps are separated in different processes, these are communicated with each other using some middleware system (for example JMX). Basically there is a master component running locally and several multiple remote processes, called slaves. The master component is a normal Spring Batch Step, its writer knows how to send chunks of items as messages using the middleware mentioned before. The slaves are implementations of item writers and item processors with the ability to process the messages. The master component should not be a bottleneck, the standard way to implement this pattern is to leave the expensive parts in the processors and writers and light parts in the readers.<\/li>\n<li><strong>Partitioning a Step (single or multi process):<\/strong> Spring Batch offers the possibility to partition Steps and execute them remotely. The remote instances are Steps.<\/li>\n<\/ul>\n<p>These are the main options that Spring Batch offers to programmers to allow them to process their batch applications somehow in parallel. But parallelism in general and specifically parallelism in batch processing is a very deep and complicate topic that is out of the scope of this document.<\/p>\n<h2 class=\"wp-block-heading\" id=\"repeat\">12. Repeating jobs<\/h2>\n<p>Spring Batch offers the possibility to repeat Jobs and Tasks in a programmatic and configurable way. In other words, it is possible to configure our batch applications to repeat Jobs or Steps until specific conditions are met (or until specific conditions are not yet met). Several abstractions are available for this purpose:<\/p>\n<ul class=\"wp-block-list\">\n<li><strong>Repeat Operations:<\/strong> The interface <a href=\"\/\/docs.spring.io\/spring-batch\/trunk\/apidocs\/org\/springframework\/batch\/repeat\/RepeatOperations.html\">RepeatOperations<\/a> is the basis for all the repeat mechanism in Spring Batch. It contains a method to be implemented where a callback is passed. This callback is executed in each iteration. It looks like the following:\n<pre class=\"brush:java\">public interface RepeatOperations {     RepeatStatus iterate(RepeatCallback callback) throws RepeatException; } <\/pre>\n<p>The <a href=\"http:\/\/docs.spring.io\/spring-batch\/trunk\/apidocs\/org\/springframework\/batch\/repeat\/RepeatCallback.html\">RepeatCallback<\/a> interface contains the functional logic that has to be repeated in the Batch:<\/p>\n<pre class=\"brush:java\">public interface RepeatCallback {     RepeatStatus doInIteration(RepeatContext context) throws Exception; } <\/pre>\n<p>The <code>RepeatStatus<\/code> returned in their <code>iterate()<\/code> and <code>doInIteration()<\/code> respectively should be <code>RepeatStatus.CONTINUABLE<\/code> in case the Batch should continue iterating or <code>RepeatStatus.FINIHSED<\/code> in case the Batch processing should be terminated.<\/p>\n<p>Spring already provides some basic implementations for the <code>RepeatCallBack<\/code> interface.<\/p>\n<\/li>\n<li><strong>Repeat Templates:<\/strong> The class <a href=\"\/\/docs.spring.io\/spring-batch\/trunk\/apidocs\/org\/springframework\/batch\/repeat\/support\/RepeatTemplate.html\">RepeatTemplate<\/a> is a very useful implementation of the <code>RepeatOperations<\/code> interface that can be used as starting point in our batch applications. It contains basic functionalities and default behavior for error handling and finalization mechanisms. Applications that do not want this default behavior should implement their custom Completion Policies.<br \/>Here is an example of how to use a repeat template with a fixed chunk termination policy and a dummy iterate method:\n<p>&nbsp;<\/p>\n<pre class=\"brush:java\">RepeatTemplate template = new RepeatTemplate(); template.setCompletionPolicy(new FixedChunkSizeCompletionPolicy(10)); template.iterate(new RepeatCallback() {     public ExitStatus doInIteration(RepeatContext context) {          int x = 10;          x *= 10;          x \/= 10;          return ExitStatus.CONTINUABLE;     } }); <\/pre>\n<p>In this case the batch will terminate after 10 iterations since the iterate() method returns always <code>CONTINUABLE<\/code> and leaves the responsibility of the termination to the completion policy.<\/p>\n<\/li>\n<li><strong>Repeat Status:<\/strong> Spring contains an enumeration with the possible continuation status:<code>RepeatStatus .CONTINUABLE<\/code><br \/><code>RepeatStatus.FINISHED<\/code> Indicating that the processing should <a href=\"http:\/\/docs.spring.io\/spring-batch\/trunk\/apidocs\/org\/springframework\/batch\/repeat\/RepeatStatus.html\">continue<\/a> or it is finished can be successful or unsuccessful.<\/li>\n<li><strong>Repeat Context:<\/strong> It is possible to store transient data in the Repeat Context, this context is passed as parameter to the Repeat Callback <code>doInIteration()<\/code> method. Spring Batch provides the abstraction <a href=\"\/\/docs.spring.io\/spring-batch\/trunk\/apidocs\/org\/springframework\/batch\/repeat\/RepeatContext.html\">RepeatContext<\/a> for this purpose.<br \/>After the <code>iterate()<\/code> method is called, the context no longer exists. The repeat context have a parent context in case iterations are nested, in these cases, it is possible to use the parent context in order to store information that can be shared between different iterations, like counters or decision variables.<\/li>\n<li><strong>Repeat Policy:<\/strong> Repeat template termination mechanism is determined by a <a href=\"\/\/docs.spring.io\/spring-batch\/trunk\/apidocs\/org\/springframework\/batch\/repeat\/CompletionPolicy.html\">CompletionPolicy<\/a>. This policy is also in charge of creating a <code>RepeatContext<\/code> and pass it to the callback in every iteration. Once an iteration is completed, the template calls the completion policy and updates its state, which will be stored in the repeat context. After that, the template asks the policy to check if the processing is complete.Spring contains several implementations for this interface, one of the most simple ones is the <a href=\"\/\/docs.spring.io\/spring-batch\/trunk\/apidocs\/org\/springframework\/batch\/repeat\/policy\/SimpleCompletionPolicy.html\">SimpleCompletionPolicy<\/a>; which offers the possibility to execute the Batch just a fixed number of iterations.<\/li>\n<\/ul>\n<h2 class=\"wp-block-heading\" id=\"jsr352\">13. JSR 352 Batch Applications for the Java Platform<\/h2>\n<p>Since Java 7, batch processing is included in the Java Platform. The JSR 352 (<a href=\"https:\/\/jcp.org\/en\/jsr\/detail?id=352\">Batch applications for the Java Platform<\/a>) specifies a model for batch applications and a runtime for scheduling and executing jobs. At the moment of writing this tutorial, the Spring Batch implementation (3.0) implements completely the specification of the JSR-352.<\/p>\n<p>The domain model and the vocabulary used is pretty similar to the one used in Spring Batch.<br \/>JSR 352: Batch Applications for the Java Platform: <code>Jobs<\/code>, <code>Steps<\/code>, <code>Chunks<\/code>, <code>Items<\/code>, <code>ItemReaders<\/code>, <code>ItemWriters<\/code>, <code>ItemProcessors<\/code> etc. are present in the Java Platform JSR 352 model as well. The differences are minor between both frameworks and configuration files looks almost the same.<\/p>\n<p>This is a good thing for both programmers and the industry; since the industry profits from the fact that a standard has been created in the Java Platform, using as basis a very good library like Spring Batch, which is widely used and well tested. Programmers benefit because in case Spring Batch is discontinued or cannot be used for any reason in their applications (compatibility, company policies, size restrictions\u2026) they can choose the Java standard implementation for Batch processing without much changes in their systems.<\/p>\n<p>You can learn more information about <a href=\"http:\/\/docs.spring.io\/spring-batch\/reference\/html\/jsr-352.html\">how Spring Batch has been adapter to the JSR 352<\/a>.<\/p>\n<h2 class=\"wp-block-heading\" id=\"summary\">14. Summary<\/h2>\n<p>So that\u2019s it. I hope you have enjoyed it and you are able now to configure and implement batch applications using Spring Batch. I am going to summarize here the most important points explained in this article:<\/p>\n<ul class=\"wp-block-list\">\n<li>Spring Batch is a batch processing framework built upon the Spring Framework.<\/li>\n<li>Mainly (simplifying!) it is composed of &lt;code&lt;Jobs, containing <code>Steps<\/code>, where <code>Readers<\/code>, <code>Processors<\/code> and <code>Writers<\/code> and configured and concatenated to execute the desired actions.<\/li>\n<li>Spring Batch contains mechanism that allow programmers to work with the main providers like MySQL, Mongo DB and formats like SQL, CSV or XML out of the box.<\/li>\n<li>Spring Batch contains features for error handling, repeating <code>Jobs<\/code> and <code>Steps<\/code> and retrying <code>Jobs<\/code> and <code>Steps<\/code>.<\/li>\n<li>It also offers possibilities for parallel processing.<\/li>\n<li>It contains classes and interfaces for batch applications unit testing.<\/li>\n<\/ul>\n<p>In this tutorial I used no xml file (apart from some examples) for configuring the spring context, everything was done via annotations. I did it this way for clarity reasons but I do not recommend to do this in real life applications since xml configuration files may be useful in specific scenarios. As I said, this was a tutorial about Spring Batch and not about Spring in general.<\/p>\n<h2 class=\"wp-block-heading\" id=\"resources\">15. Resources<\/h2>\n<p>The following links contain a lot of information and theoretical examples where you can learn all the features of the Spring Batch module:<\/p>\n<ul class=\"wp-block-list\">\n<li><a href=\"http:\/\/docs.spring.io\/spring-batch\/reference\/html\/index.html\">http:\/\/docs.spring.io\/spring-batch\/reference\/html\/index.html<\/a><\/li>\n<li><a href=\"https:\/\/jcp.org\/en\/jsr\/detail?id=352\">https:\/\/jcp.org\/en\/jsr\/detail?id=352<\/a><\/li>\n<li><a href=\"\/\/spring.io\/guides\/gs\/batch-processing\/\">https:\/\/spring.io\/guides\/gs\/batch-processing\/<\/a><\/li>\n<li><a href=\"https:\/\/kb.iu.edu\/d\/afrx\">https:\/\/kb.iu.edu\/d\/afrx<\/a><\/li>\n<\/ul>\n<h2 class=\"wp-block-heading\" id=\"download\">16. Download&nbsp;the Source Code<\/h2>\n<div class=\"download\"><strong>Download<\/strong><br \/>You can download the full source code of this Spring Batch Tutorial here: <strong><a href=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2015\/03\/spring_batch_tutorial.zip\">Spring Batch Tutorial \u2013 The ULTIMATE Guide<\/a><\/strong><\/div>\n<p><strong>Last updated on Apr. 29th, 2021<\/strong><\/p>\n","protected":false},"excerpt":{"rendered":"<p>This is&nbsp;&nbsp;Spring batch&nbsp;tutorial which is part of the Spring framework. Spring Batch provides reusable functions that are essential in processing large volumes of records, including logging\/tracing, transaction management, job processing statistics, job restart, skip, and resource management. It also provides more advanced technical services and features that will enable extremely high-volume and high-performance batch jobs &hellip;<\/p>\n","protected":false},"author":601,"featured_media":240,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[8],"tags":[30,691,1039],"class_list":["post-38153","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-enterprise-java","tag-spring","tag-spring-batch","tag-ultimate"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.5 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Spring Batch Tutorial \u2013 The ULTIMATE Guide - Java Code Geeks<\/title>\n<meta name=\"description\" content=\"Check out our detailed spring batch tutorial where all major parts, like jobs &amp; processing, are explained to quickly get started!\" \/>\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\/spring-batch-tutorial.html\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Spring Batch Tutorial \u2013 The ULTIMATE Guide - Java Code Geeks\" \/>\n<meta property=\"og:description\" content=\"Check out our detailed spring batch tutorial where all major parts, like jobs &amp; processing, are explained to quickly get started!\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.javacodegeeks.com\/spring-batch-tutorial.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=\"2015-03-17T11:51:14+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2023-12-05T14:34:20+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=\"Dani Buiza\" \/>\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=\"Dani Buiza\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"22 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/spring-batch-tutorial.html#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/spring-batch-tutorial.html\"},\"author\":{\"name\":\"Dani Buiza\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/person\\\/c1d18d0e5a1ad668bab93bb4124027e5\"},\"headline\":\"Spring Batch Tutorial \u2013 The ULTIMATE Guide\",\"datePublished\":\"2015-03-17T11:51:14+00:00\",\"dateModified\":\"2023-12-05T14:34:20+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/spring-batch-tutorial.html\"},\"wordCount\":4791,\"commentCount\":18,\"publisher\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/spring-batch-tutorial.html#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/spring-logo.jpg\",\"keywords\":[\"Spring\",\"Spring Batch\",\"Ultimate\"],\"articleSection\":[\"Enterprise Java\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.javacodegeeks.com\\\/spring-batch-tutorial.html#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/spring-batch-tutorial.html\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/spring-batch-tutorial.html\",\"name\":\"Spring Batch Tutorial \u2013 The ULTIMATE Guide - Java Code Geeks\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/spring-batch-tutorial.html#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/spring-batch-tutorial.html#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/spring-logo.jpg\",\"datePublished\":\"2015-03-17T11:51:14+00:00\",\"dateModified\":\"2023-12-05T14:34:20+00:00\",\"description\":\"Check out our detailed spring batch tutorial where all major parts, like jobs & processing, are explained to quickly get started!\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/spring-batch-tutorial.html#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.javacodegeeks.com\\\/spring-batch-tutorial.html\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/spring-batch-tutorial.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\\\/spring-batch-tutorial.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 Tutorial \u2013 The ULTIMATE Guide\"}]},{\"@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\\\/c1d18d0e5a1ad668bab93bb4124027e5\",\"name\":\"Dani Buiza\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/5ad57f031b639d68a6e473652c4907bb6ee1fd4b691e97dff4c14c6ea4d9188c?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/5ad57f031b639d68a6e473652c4907bb6ee1fd4b691e97dff4c14c6ea4d9188c?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/5ad57f031b639d68a6e473652c4907bb6ee1fd4b691e97dff4c14c6ea4d9188c?s=96&d=mm&r=g\",\"caption\":\"Dani Buiza\"},\"description\":\"Daniel Gutierrez Diez holds a Master in Computer Science Engineering from the University of Oviedo (Spain) and a Post Grade as Specialist in Foreign Trade from the UNED (Spain). Daniel has been working for different clients and companies in several Java projects as programmer, designer, trainer, consultant and technical lead.\",\"sameAs\":[\"http:\\\/\\\/danibuiza.github.io\\\/yo\\\/\"],\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/author\\\/dani-buiza\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Spring Batch Tutorial \u2013 The ULTIMATE Guide - Java Code Geeks","description":"Check out our detailed spring batch tutorial where all major parts, like jobs & processing, are explained to quickly get started!","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\/spring-batch-tutorial.html","og_locale":"en_US","og_type":"article","og_title":"Spring Batch Tutorial \u2013 The ULTIMATE Guide - Java Code Geeks","og_description":"Check out our detailed spring batch tutorial where all major parts, like jobs & processing, are explained to quickly get started!","og_url":"https:\/\/www.javacodegeeks.com\/spring-batch-tutorial.html","og_site_name":"Java Code Geeks","article_publisher":"https:\/\/www.facebook.com\/javacodegeeks","article_published_time":"2015-03-17T11:51:14+00:00","article_modified_time":"2023-12-05T14:34:20+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":"Dani Buiza","twitter_card":"summary_large_image","twitter_creator":"@javacodegeeks","twitter_site":"@javacodegeeks","twitter_misc":{"Written by":"Dani Buiza","Est. reading time":"22 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.javacodegeeks.com\/spring-batch-tutorial.html#article","isPartOf":{"@id":"https:\/\/www.javacodegeeks.com\/spring-batch-tutorial.html"},"author":{"name":"Dani Buiza","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/person\/c1d18d0e5a1ad668bab93bb4124027e5"},"headline":"Spring Batch Tutorial \u2013 The ULTIMATE Guide","datePublished":"2015-03-17T11:51:14+00:00","dateModified":"2023-12-05T14:34:20+00:00","mainEntityOfPage":{"@id":"https:\/\/www.javacodegeeks.com\/spring-batch-tutorial.html"},"wordCount":4791,"commentCount":18,"publisher":{"@id":"https:\/\/www.javacodegeeks.com\/#organization"},"image":{"@id":"https:\/\/www.javacodegeeks.com\/spring-batch-tutorial.html#primaryimage"},"thumbnailUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-logo.jpg","keywords":["Spring","Spring Batch","Ultimate"],"articleSection":["Enterprise Java"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.javacodegeeks.com\/spring-batch-tutorial.html#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.javacodegeeks.com\/spring-batch-tutorial.html","url":"https:\/\/www.javacodegeeks.com\/spring-batch-tutorial.html","name":"Spring Batch Tutorial \u2013 The ULTIMATE Guide - Java Code Geeks","isPartOf":{"@id":"https:\/\/www.javacodegeeks.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.javacodegeeks.com\/spring-batch-tutorial.html#primaryimage"},"image":{"@id":"https:\/\/www.javacodegeeks.com\/spring-batch-tutorial.html#primaryimage"},"thumbnailUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-logo.jpg","datePublished":"2015-03-17T11:51:14+00:00","dateModified":"2023-12-05T14:34:20+00:00","description":"Check out our detailed spring batch tutorial where all major parts, like jobs & processing, are explained to quickly get started!","breadcrumb":{"@id":"https:\/\/www.javacodegeeks.com\/spring-batch-tutorial.html#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.javacodegeeks.com\/spring-batch-tutorial.html"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.javacodegeeks.com\/spring-batch-tutorial.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\/spring-batch-tutorial.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 Tutorial \u2013 The ULTIMATE Guide"}]},{"@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\/c1d18d0e5a1ad668bab93bb4124027e5","name":"Dani Buiza","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/5ad57f031b639d68a6e473652c4907bb6ee1fd4b691e97dff4c14c6ea4d9188c?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/5ad57f031b639d68a6e473652c4907bb6ee1fd4b691e97dff4c14c6ea4d9188c?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/5ad57f031b639d68a6e473652c4907bb6ee1fd4b691e97dff4c14c6ea4d9188c?s=96&d=mm&r=g","caption":"Dani Buiza"},"description":"Daniel Gutierrez Diez holds a Master in Computer Science Engineering from the University of Oviedo (Spain) and a Post Grade as Specialist in Foreign Trade from the UNED (Spain). Daniel has been working for different clients and companies in several Java projects as programmer, designer, trainer, consultant and technical lead.","sameAs":["http:\/\/danibuiza.github.io\/yo\/"],"url":"https:\/\/www.javacodegeeks.com\/author\/dani-buiza"}]}},"_links":{"self":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts\/38153","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\/601"}],"replies":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/comments?post=38153"}],"version-history":[{"count":0,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts\/38153\/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=38153"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/categories?post=38153"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/tags?post=38153"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}