{"id":19522,"date":"2013-12-12T22:00:28","date_gmt":"2013-12-12T20:00:28","guid":{"rendered":"http:\/\/www.javacodegeeks.com\/?p=19522"},"modified":"2013-12-12T21:56:55","modified_gmt":"2013-12-12T19:56:55","slug":"scaling-spring-batch-step-partitioning","status":"publish","type":"post","link":"https:\/\/www.javacodegeeks.com\/2013\/12\/scaling-spring-batch-step-partitioning.html","title":{"rendered":"Scaling Spring Batch &#8211; Step Partitioning"},"content":{"rendered":"<p>We have talked about how to get up and running with Spring Batch in a few of previous articles. Now, we\u2019re going to start discussing some of the strategies available for scaling Spring Batch.<\/p>\n<p>This article will focus on partitioning a step so that the step has several threads that are each processing a chunk of data in parallel. This is beneficial if you have a large chunk of data that can be logically split up into smaller chunks that can be processed in parallel. The way this works is that you will define a master step that is responsible for determining the basis of the chunks, and then farming all of those chunks out to a set of slave steps to process each chunk.<\/p>\n<h2>Partitioning<\/h2>\n<p>If I could go back in time to a previous experience, a perfect example of this would be processing all of the daily invoices for each company within a large procurement system. Our data that would be processed could be split up logically by each company being processed. Let\u2019s say that there are 250 companies that participate in this procurement system and our partitioned step has been defined to have 15 threads. Our <strong>Partitioner<\/strong> would likely run a query to find all of the companies that have invoices waiting to be processed for that day. The Partitioner\u2019s responsibility at that point would be to create an <strong>ExecutionContext<\/strong> for each of those companies and add that to a map with a unique key. That ExecutionContext should contain any information required to process invoices for that company, such as the company ID and any other relevant information. When the Partitioner returns the map of ExecutionContexts, Spring Batch will then create a new <strong>Step<\/strong> for each entry in the map and use the key value as part of the step name. Based upon the configuration, such as 15 threads, it will then create a pool of 15 threads and start executing the steps in parallel 15 at a time. For example, if you had 85 steps, Spring Batch would start executing 15 steps and as each step completed, the thread that had completed the step would pick up the next step and begin execution until all steps have been completed.<\/p>\n<h2>An Example<\/h2>\n<p>So now that we have a basic understanding of how partitioning works, let\u2019s take a look at a simple example. For our use case, we\u2019re going to be inspecting an inbound directory where incoming vendor catalog files will be dumped. So to create a spring batch partitioner, we\u2019ll need to create a class that implements the Spring Batch\u2019s Partitioner interface. Since this is something generic and can be made reusable, we\u2019re going to call this class <strong>MultiFileResourcePartitioner<\/strong>, which is a simple POJO and has only one field name <strong>\u201cinboundDir\u201d<\/strong> representing the path to the directory that contains the files to be processed. The Partitioner interfaces specifies that the class should implement a method named <strong>\u201cpartition\u201d<\/strong> that takes an int parameter representing the grid size and returns a Map that holds the ExecutionContext.<\/p>\n<p>Here\u2019s the class listing for MultiFileResourcePartitioner:<\/p>\n<pre class=\" brush:java\">package com.keyhole.example.partition;\r\n\r\nimport java.io.File;\r\nimport java.util.HashMap;\r\nimport java.util.Map;\r\n\r\nimport org.springframework.batch.core.partition.support.Partitioner;\r\nimport org.springframework.batch.item.ExecutionContext;\r\nimport org.springframework.core.io.FileSystemResource;\r\n\r\npublic class MultiFileResourcePartitioner implements Partitioner {\r\n\r\n\tprivate String inboundDir;\r\n\r\n\t@Override\r\n\tpublic Map&lt;String, ExecutionContext&gt; partition(int gridSize) {\r\n\r\n\t\tMap&lt;String, ExecutionContext&gt; partitionMap = new HashMap&lt;String, ExecutionContext&gt;();\r\n\t\tFile dir = new File(inboundDir);\r\n\t\tif (dir.isDirectory()) {\r\n\t\t\tFile[] files = dir.listFiles();\r\n\t\t\tfor (File file : files) {\r\n\t\t\t\tExecutionContext context = new ExecutionContext();\r\n\t\t\t\tcontext.put(\"fileResource\", file.toURI().toString());\r\n\t\t\t\tpartitionMap.put(file.getName(), context);\r\n\t\t\t}\r\n\t\t}\r\n\t\treturn partitionMap;\r\n\t}\r\n\r\n\tpublic String getInboundDir() {\r\n\t\treturn inboundDir;\r\n\t}\r\n\r\n\tpublic void setInboundDir(String inboundDir) {\r\n\t\tthis.inboundDir = inboundDir;\r\n\t}\r\n\r\n}<\/pre>\n<p>The configuration for this bean in our application context will look like this:<div style=\"display:inline-block; margin: 15px 0;\"> <div id=\"adngin-JavaCodeGeeks_incontent_video-0\" style=\"display:inline-block;\"><\/div> <\/div><\/p>\n<pre class=\" brush:xml\">&lt;bean id=\"inventoryFilePartitioner\"\r\n\t\tclass=\"com.keyhole.example.partition.MultiFileResourcePartitioner\"\r\n\t\tscope=\"step\"&gt;\r\n\t\t&lt;property name=\"inboundDir\" value=\"\/data\/inbound\" \/&gt;\r\n&lt;\/bean&gt;<\/pre>\n<p>Looking at the partition method that is implemented, we\u2019re simply going to list all of the files that are found in the specified inbound directory and create an ExecutionContext for each file that is found add it to the map that is returned. The unique key that is used to place each ExecutionContext into the map will also become part of the step name that is created for each entry in the map. Spring Batch will use that partition map to create a slave step from each of the keys that are found in the map.<\/p>\n<p>To partition a step, you need to first create the step that will be referenced by the partition configuration. This step should configured just like any other step within a Spring Batch and for this example we\u2019ll define a <strong>FlatFileItemReader<\/strong> and a simple <strong>ItemWriter<\/strong> that will just call the <strong>toString()<\/strong> method and log it to the console.<\/p>\n<p>Here are the configuration details for the step and its associated spring beans. The important thing to note here is that we have the ItemReader scoped at the step level so that we don\u2019t run into any issues with multiple threads using the same beans to process the data. We also need them scoped that way so that we can use the Spring late binding to specify the value holding the file resource in the Step\u2019s ExecutionContext.<\/p>\n<pre class=\" brush:xml\">&lt;batch:step id=\"inventoryLoadStep\"\r\n\txmlns=\"http:\/\/www.springframework.org\/schema\/batch\"&gt;\r\n\t&lt;batch:tasklet transaction-manager=\"transactionManager\"&gt;\r\n\t\t&lt;batch:chunk reader=\"inventoryLoadReader\" writer=\"logItemWriter\"\r\n\t\t\tcommit-interval=\"5000\" \/&gt;\r\n\t&lt;\/batch:tasklet&gt;\r\n&lt;\/batch:step&gt;\r\n&lt;bean name=\"inventoryLoadReader\" scope=\"step\"\r\n\tclass=\"org.springframework.batch.item.file.FlatFileItemReader\"&gt;\r\n\t&lt;property name=\"resource\"\r\n\t\tvalue=\"#{stepExecutionContext['fileResource']}\" \/&gt;\r\n\t&lt;property name=\"lineMapper\" ref=\"inventoryLineMapper\" \/&gt;\r\n&lt;property name=\"linesToSkip\" value=\"1\" \/&gt;\r\n&lt;\/bean&gt;\r\n\r\n&lt;bean name=\"inventoryLineMapper\"\r\n\tclass=\"org.springframework.batch.item.file.mapping.DefaultLineMapper\"&gt;\r\n\t&lt;property name=\"fieldSetMapper\" ref=\"inventoryFieldMapper\" \/&gt;\r\n\t&lt;property name=\"lineTokenizer\" ref=\"inventoryLineTokenizer\" \/&gt;\r\n&lt;\/bean&gt;\r\n\r\n&lt;bean name=\"inventoryLineTokenizer\" \t\tclass=\"org.springframework.batch.item.file.transform.DelimitedLineTokenizer\" \/&gt;<\/pre>\n<p>Since we are reading and processing comma delimited text files in this example, we have very little code to write for this step configuration. The only code we\u2019ll need to implement is the <strong>FieldSetMapper<\/strong> required to map the contents of the line to the object representing the file record. Each line in the file will contain the fields \u201ccategory\u201d,\u201dsub category\u201d,\u201ddescription\u201d,\u201dcatalog num\u201d,\u201dcolor\u201d,\u201dsize\u201d,\u201dprice\u201d and \u201cqty.\u201d So our object will contain those fields and our FieldSetMapper code listing will look like this.<\/p>\n<pre class=\" brush:java\">package com.keyhole.example.partition;\r\n\r\nimport org.springframework.batch.item.file.mapping.FieldSetMapper;\r\nimport org.springframework.batch.item.file.transform.FieldSet;\r\nimport org.springframework.stereotype.Component;\r\nimport org.springframework.validation.BindException;\r\n\r\n@Component(\"inventoryFieldMapper\")\r\npublic class InventoryItemFieldSetMapper implements FieldSetMapper&lt;InventoryItem&gt; {\r\n\r\n\t@Override\r\n\tpublic InventoryItem mapFieldSet(FieldSet fieldSet) throws BindException {\r\n\t\tInventoryItem item = new InventoryItem();\r\n\t\titem.setCategory(fieldSet.readString(0));\r\n\t\titem.setSubCategory(fieldSet.readString(1));\r\n\t\titem.setDescription(fieldSet.readString(2));\r\n\t\titem.setCatalogNum(fieldSet.readString(3));\r\n\t\titem.setColor(fieldSet.readString(4));\r\n\t\titem.setSize(fieldSet.readString(5));\r\n\t\titem.setPrice(fieldSet.readDouble(6));\r\n\t\titem.setQty(fieldSet.readInt(7));\r\n\t\treturn item;\r\n\t}\r\n\r\n}<\/pre>\n<p>Now that we have the Partitioner and Step created and configured, all that remains left to do is configure the partitioned step itself! And it\u2019s as easy as this:<\/p>\n<pre class=\" brush:xml\">&lt;batch:job id=\"InventoryLoader\"&gt;\r\n\t&lt;batch:step id=\"partitionedInventoryLoadStep\"&gt;\r\n\t\t&lt;batch:partition step=\"inventoryLoadStep\" partitioner=\"inventoryFilePartitioner\"&gt;\r\n\t\t\t&lt;batch:handler grid-size=\"10\" task-executor=\"inventoryLoadTaskExecutor\" \/&gt;\r\n\t\t&lt;\/batch:partition&gt;\r\n\t&lt;\/batch:step&gt;\r\n&lt;\/batch:job&gt;<\/pre>\n<p>When configuring the partitioned step, you define a step just as you would any other step by giving it an ID and if required a next step value. Instead of defining the contents of a step as a normal chunk or tasklet, Spring Batch provides a partition tag that requires you to specify the job step to be partitioned and the Partitioner that will be used to determine the chunks of data. You will also need to define the partition handler that will be processing those steps, in this case we\u2019ll be using a <strong>ThreadPoolTaskExecutor<\/strong> which will have a thread pool size of 10 and allow them to timeout if they aren\u2019t being used.<\/p>\n<pre class=\" brush:xml\">&lt;bean id=\"inventoryLoadTaskExecutor\"\r\n\tclass=\"org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor\"&gt;\r\n\t&lt;property name=\"corePoolSize\" value=\"10\" \/&gt;\r\n\t&lt;property name=\"maxPoolSize\" value=\"10\" \/&gt;\r\n\t&lt;property name=\"allowCoreThreadTimeOut\" value=\"true\" \/&gt;\r\n&lt;\/bean&gt;<\/pre>\n<p>So, if you have a Spring Batch process that has a step processing a large amount of records and you\u2019re interested in improving the performance, consider giving step partitioning a try. It should be easy to implement and provide you with some additional performance to help speed up processing times.<\/p>\n<h2>Additional Resources<\/h2>\n<p>For the example code associated with this article, I have uploaded the source code to a github repository at\u00a0<a href=\"https:\/\/github.com\/jonny-hackett\/batch-example\" target=\"_blank\">https:\/\/github.com\/jonny-hackett\/batch-example<\/a>. To execute the example code related to this article, there is a JUnit test name\u00a0<strong>InventoryLoadTest<\/strong>. The data files are located under src\/test\/resources\/data\/inbound and need to be placed into a local directory that matches the Partitioner inbound directory. Also, check out\u00a0<a href=\"http:\/\/docs.spring.io\/spring-batch\/reference\/html\/scalability.html\" target=\"_blank\">http:\/\/docs.spring.io\/spring-batch\/reference\/html\/scalability.html<\/a>.<br \/>\n&nbsp;<\/p>\n<div style=\"border: 1px solid #D8D8D8; background: #FAFAFA; width: 100%; padding-left: 5px;\"><b><i>Reference: <\/i><\/b><a href=\"http:\/\/keyholesoftware.com\/2013\/12\/09\/spring-batch-partitioning\/\">Scaling Spring Batch &#8211; Step Partitioning<\/a> from our <a href=\"http:\/\/www.javacodegeeks.com\/jcg\">JCG partner<\/a> Keyhole Software at the <a href=\"http:\/\/keyholesoftware.com\/\">Keyhole Software<\/a> blog.<\/div>\n","protected":false},"excerpt":{"rendered":"<p>We have talked about how to get up and running with Spring Batch in a few of previous articles. Now, we\u2019re going to start discussing some of the strategies available for scaling Spring Batch. This article will focus on partitioning a step so that the step has several threads that are each processing a chunk &hellip;<\/p>\n","protected":false},"author":471,"featured_media":240,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[8],"tags":[30,691],"class_list":["post-19522","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>Scaling Spring Batch - Step Partitioning<\/title>\n<meta name=\"description\" content=\"We have talked about how to get up and running with Spring Batch in a few of previous articles. Now, we\u2019re going to start discussing some of the\" \/>\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\/2013\/12\/scaling-spring-batch-step-partitioning.html\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Scaling Spring Batch - Step Partitioning\" \/>\n<meta property=\"og:description\" content=\"We have talked about how to get up and running with Spring Batch in a few of previous articles. Now, we\u2019re going to start discussing some of the\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.javacodegeeks.com\/2013\/12\/scaling-spring-batch-step-partitioning.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:author\" content=\"http:\/\/facebook.com\/keyholesoftware\" \/>\n<meta property=\"article:published_time\" content=\"2013-12-12T20:00:28+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=\"Keyhole Software\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@http:\/\/twitter.com\/keyholesoftware\" \/>\n<meta name=\"twitter:site\" content=\"@javacodegeeks\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Keyhole Software\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"8 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2013\\\/12\\\/scaling-spring-batch-step-partitioning.html#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2013\\\/12\\\/scaling-spring-batch-step-partitioning.html\"},\"author\":{\"name\":\"Keyhole Software\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/person\\\/621b02d9eb189f8d1aec83b2bcfa14d6\"},\"headline\":\"Scaling Spring Batch &#8211; Step Partitioning\",\"datePublished\":\"2013-12-12T20:00:28+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2013\\\/12\\\/scaling-spring-batch-step-partitioning.html\"},\"wordCount\":1149,\"commentCount\":1,\"publisher\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2013\\\/12\\\/scaling-spring-batch-step-partitioning.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\\\/2013\\\/12\\\/scaling-spring-batch-step-partitioning.html#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2013\\\/12\\\/scaling-spring-batch-step-partitioning.html\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2013\\\/12\\\/scaling-spring-batch-step-partitioning.html\",\"name\":\"Scaling Spring Batch - Step Partitioning\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2013\\\/12\\\/scaling-spring-batch-step-partitioning.html#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2013\\\/12\\\/scaling-spring-batch-step-partitioning.html#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/spring-logo.jpg\",\"datePublished\":\"2013-12-12T20:00:28+00:00\",\"description\":\"We have talked about how to get up and running with Spring Batch in a few of previous articles. Now, we\u2019re going to start discussing some of the\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2013\\\/12\\\/scaling-spring-batch-step-partitioning.html#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.javacodegeeks.com\\\/2013\\\/12\\\/scaling-spring-batch-step-partitioning.html\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2013\\\/12\\\/scaling-spring-batch-step-partitioning.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\\\/2013\\\/12\\\/scaling-spring-batch-step-partitioning.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\":\"Scaling Spring Batch &#8211; Step Partitioning\"}]},{\"@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\\\/621b02d9eb189f8d1aec83b2bcfa14d6\",\"name\":\"Keyhole Software\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/68be341bef51b95ced09befd6a7e0ca930461d95f3a64285e03e7925b8f5de47?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/68be341bef51b95ced09befd6a7e0ca930461d95f3a64285e03e7925b8f5de47?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/68be341bef51b95ced09befd6a7e0ca930461d95f3a64285e03e7925b8f5de47?s=96&d=mm&r=g\",\"caption\":\"Keyhole Software\"},\"description\":\"Keyhole is a midwest-based consulting firm with a tight-knit technical team. We work primarily with Java, JavaScript and .NET technologies, specializing in application development. We love the challenge that comes in consulting and blog often regarding some of the technical situations and technologies we face.\",\"sameAs\":[\"http:\\\/\\\/keyholesoftware.com\\\/\",\"http:\\\/\\\/facebook.com\\\/keyholesoftware\",\"http:\\\/\\\/linkedin.com\\\/company\\\/keyhole-software\",\"https:\\\/\\\/x.com\\\/http:\\\/\\\/twitter.com\\\/keyholesoftware\"],\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/author\\\/keyhole-software\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Scaling Spring Batch - Step Partitioning","description":"We have talked about how to get up and running with Spring Batch in a few of previous articles. Now, we\u2019re going to start discussing some of the","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\/2013\/12\/scaling-spring-batch-step-partitioning.html","og_locale":"en_US","og_type":"article","og_title":"Scaling Spring Batch - Step Partitioning","og_description":"We have talked about how to get up and running with Spring Batch in a few of previous articles. Now, we\u2019re going to start discussing some of the","og_url":"https:\/\/www.javacodegeeks.com\/2013\/12\/scaling-spring-batch-step-partitioning.html","og_site_name":"Java Code Geeks","article_publisher":"https:\/\/www.facebook.com\/javacodegeeks","article_author":"http:\/\/facebook.com\/keyholesoftware","article_published_time":"2013-12-12T20:00:28+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":"Keyhole Software","twitter_card":"summary_large_image","twitter_creator":"@http:\/\/twitter.com\/keyholesoftware","twitter_site":"@javacodegeeks","twitter_misc":{"Written by":"Keyhole Software","Est. reading time":"8 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.javacodegeeks.com\/2013\/12\/scaling-spring-batch-step-partitioning.html#article","isPartOf":{"@id":"https:\/\/www.javacodegeeks.com\/2013\/12\/scaling-spring-batch-step-partitioning.html"},"author":{"name":"Keyhole Software","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/person\/621b02d9eb189f8d1aec83b2bcfa14d6"},"headline":"Scaling Spring Batch &#8211; Step Partitioning","datePublished":"2013-12-12T20:00:28+00:00","mainEntityOfPage":{"@id":"https:\/\/www.javacodegeeks.com\/2013\/12\/scaling-spring-batch-step-partitioning.html"},"wordCount":1149,"commentCount":1,"publisher":{"@id":"https:\/\/www.javacodegeeks.com\/#organization"},"image":{"@id":"https:\/\/www.javacodegeeks.com\/2013\/12\/scaling-spring-batch-step-partitioning.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\/2013\/12\/scaling-spring-batch-step-partitioning.html#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.javacodegeeks.com\/2013\/12\/scaling-spring-batch-step-partitioning.html","url":"https:\/\/www.javacodegeeks.com\/2013\/12\/scaling-spring-batch-step-partitioning.html","name":"Scaling Spring Batch - Step Partitioning","isPartOf":{"@id":"https:\/\/www.javacodegeeks.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.javacodegeeks.com\/2013\/12\/scaling-spring-batch-step-partitioning.html#primaryimage"},"image":{"@id":"https:\/\/www.javacodegeeks.com\/2013\/12\/scaling-spring-batch-step-partitioning.html#primaryimage"},"thumbnailUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-logo.jpg","datePublished":"2013-12-12T20:00:28+00:00","description":"We have talked about how to get up and running with Spring Batch in a few of previous articles. Now, we\u2019re going to start discussing some of the","breadcrumb":{"@id":"https:\/\/www.javacodegeeks.com\/2013\/12\/scaling-spring-batch-step-partitioning.html#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.javacodegeeks.com\/2013\/12\/scaling-spring-batch-step-partitioning.html"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.javacodegeeks.com\/2013\/12\/scaling-spring-batch-step-partitioning.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\/2013\/12\/scaling-spring-batch-step-partitioning.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":"Scaling Spring Batch &#8211; Step Partitioning"}]},{"@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\/621b02d9eb189f8d1aec83b2bcfa14d6","name":"Keyhole Software","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/68be341bef51b95ced09befd6a7e0ca930461d95f3a64285e03e7925b8f5de47?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/68be341bef51b95ced09befd6a7e0ca930461d95f3a64285e03e7925b8f5de47?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/68be341bef51b95ced09befd6a7e0ca930461d95f3a64285e03e7925b8f5de47?s=96&d=mm&r=g","caption":"Keyhole Software"},"description":"Keyhole is a midwest-based consulting firm with a tight-knit technical team. We work primarily with Java, JavaScript and .NET technologies, specializing in application development. We love the challenge that comes in consulting and blog often regarding some of the technical situations and technologies we face.","sameAs":["http:\/\/keyholesoftware.com\/","http:\/\/facebook.com\/keyholesoftware","http:\/\/linkedin.com\/company\/keyhole-software","https:\/\/x.com\/http:\/\/twitter.com\/keyholesoftware"],"url":"https:\/\/www.javacodegeeks.com\/author\/keyhole-software"}]}},"_links":{"self":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts\/19522","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\/471"}],"replies":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/comments?post=19522"}],"version-history":[{"count":0,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts\/19522\/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=19522"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/categories?post=19522"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/tags?post=19522"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}