{"id":5558,"date":"2025-09-11T08:58:07","date_gmt":"2025-09-11T08:58:07","guid":{"rendered":"https:\/\/codethataint.com\/blog\/?p=5558"},"modified":"2025-09-15T12:43:07","modified_gmt":"2025-09-15T12:43:07","slug":"5558-2","status":"publish","type":"post","link":"https:\/\/codethataint.com\/blog\/5558-2\/","title":{"rendered":"Spring Batch &#8211; Interview Questions"},"content":{"rendered":"<p><strong>Frequently Asked Questions<\/strong><\/p>\n<p><strong class=\"ctaHeader3\">Job Execution vs Job Instance?<\/strong><br \/>\nJob instance is like blueprint. Job Execution is actual job.<\/p>\n<blockquote><p>Job instance is Unique by Job Name + Parameters<br \/>\nJob Execution need not be Unique incase of failed Execution<\/p><\/blockquote>\n<p><strong class=\"ctaHeader3\">Why Job Instance should be Unique?<\/strong><br \/>\nSpring Batch uses job name + parameters to identify a job instance. This prevents accidental duplicate processing\u2014especially important in financial, ETL, or reporting systems. If you try to run the same job with the same parameters again &#8211; Spring Batch sees that the Job Instance already completed.- It prevents re-execution to avoid duplicate processing or unintended side effects (e.g., writing the same data twice).<\/p>\n<p><strong class=\"ctaHeader3\">Why Job Execution may not be Unique?<\/strong><br \/>\nIf a job execution fails, you can restart it with the same parameters. Spring Batch will:<\/p>\n<ol>\n<li>Reuse the same job instance<\/li>\n<li>Create a new job execution<\/li>\n<li>Resume from where it left off (if configured<\/li>\n<\/ol>\n<p>Let\u2019s say you run a job called &#8220;dataImportJob&#8221; with parameters {file=data.csv}:<\/p>\n<ol>\n<li>\u274cFirst run Fails \u2192 JobInstance ID = 101, JobExecution ID = 201<\/li>\n<li>\u2705You retry \u2192 JobExecution ID = 202 (still linked to JobInstance ID = 101)<\/li>\n<li>\u2705You run with {file=data_v2.csv} \u2192 New JobInstance ID = 102, JobExecution ID = 203<\/li>\n<\/ol>\n<p>So: JobInstance 101 \u2192 has executions 201 and 202, JobInstance 102 \u2192 has execution 203<\/p>\n<p><strong>Why This Matters<\/strong><\/p>\n<ol>\n<li>You can track retries and failures per job instance.<\/li>\n<li>You can restart a failed job execution without creating a new instance.<\/li>\n<li>You can query historical runs by instance or execution ID.<\/li>\n<\/ol>\n<p><strong class=\"ctaHeader3\">How Job Instance and Execution are Stored in DB?<\/strong><br \/>\nJobInstance, JobExecution, JobParameters, and StepExecution map to BATCH_JOB_INSTANCE, BATCH_JOB_EXECUTION, BATCH_JOB_EXECUTION_PARAMS, and BATCH_STEP_EXECUTION respectively<br \/>\nBATCH_JOB_EXECUTION_PARAMS table always refers parameters at Job Execution Level rather than Job Instance Level. This is done so each execution can retain a complete and independent record of the inputs used\u2014even if those parameters are the same across multiple executions of the same job instance. Though the identity of a job instance is based on its parameters storing them only at the instance level would create a few limitations.<\/p>\n<p>Executions wouldn\u2019t have their own copy of parameters, making it harder to audit or debug individual runsRetries or restarts would have no way to track what parameters were used during each attempt.Execution-level metadata (like timestamps, exit codes, and logs) would be disconnected from the parameters that triggered them.<\/p>\n<p><strong class=\"ctaHeader3\">Difference between Tasklet Step and Chunk Oriented Step?<\/strong><br \/>\n<em>Tasklet<\/em> &#8211; Executes one discrete action (e.g., delete a file, call a stored procedure) and ideal for non-repetitive tasks. I.E. File cleanup, Sending emails, Running shell scripts, Database maintenance<br \/>\n<em>Chunk <\/em> &#8211; processing is designed for handling large datasets by breaking them into manageable pieces.Uses ItemReader, ItemProcessor, and ItemWriter.Commits after processing a defined number of items. I.E. Reading from a database or file and writing to another source, High-volume data processing<\/p>\n<blockquote><p>If you&#8217;re building a job that just needs to do one thing\u2014like clean up a directory\u2014go with a Tasklet. If you&#8217;re processing thousands of records, Chunk-Oriented is your best bet.<\/p><\/blockquote>\n<p><strong>JobConfig.java<\/strong><\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\n    .\r\n    .\r\n    .\r\n    @Bean\r\n    public Job job(JobRepository jobRepository, PlatformTransactionManager transactionManager) {\r\n        return new JobBuilder(&quot;job&quot;, jobRepository)\r\n                .incrementer(new RunIdIncrementer())\r\n                .start(simpleTaskletStep(jobRepository, transactionManager))\r\n                .next(simpleChunkStep(jobRepository, transactionManager))\r\n                .build();\r\n    }\r\n\r\n    @Bean\r\n    public Step simpleTaskletStep(JobRepository jobRepository, PlatformTransactionManager transactionManager) {\r\n        StepBuilder stepBuilderOne = new StepBuilder(&quot;Tasklet Oriented Step&quot;, jobRepository);\r\n        return stepBuilderOne\r\n                .tasklet(simpleTaskLet(), transactionManager)\r\n                .build();\r\n    }\r\n\r\n    @Bean\r\n    public Tasklet simpleTaskLet(){\r\n        return (StepContribution contribution, ChunkContext chunkContext) -&gt; {\r\n            return RepeatStatus.FINISHED;\r\n        };\r\n    }\r\n\r\n    @Bean\r\n    public Step simpleChunkStep(JobRepository jobRepository, PlatformTransactionManager transactionManager) {\r\n        StepBuilder stepBuilderOne = new StepBuilder(&quot;Chunk Oriented Step&quot;, jobRepository);\r\n        return stepBuilderOne\r\n                .chunk(3, transactionManager)\r\n                .reader(simpleJobReader)\r\n                .processor(simpleJobProcessor)\r\n                .writer(simpleJobWriter)\r\n                .build();\r\n    }\r\n<\/pre>\n<p><strong  class=\"ctaHeader3\">Difference between ItemReader and ItemWriter?<\/strong><br \/>\n<strong>ItemReader<\/strong> reads one item at a time and called repeatedly until it returns null, signaling no more data. <strong>ItemWriter<\/strong> Writes a list of processed items to a destination (like a file, database, or message queue) and it is called once per chunk with a list of items.<\/p>\n<p>\ud83d\udd04 ItemReader brings the ingredients to the kitchen,<br \/>\n\ud83e\uddd1\u200d\ud83c\udf73 ItemProcessor cooks them,<br \/>\n\ud83d\udce6 ItemWriter packs and delivers the final dish<\/p>\n<p><strong  class=\"ctaHeader3\">Why ItemReader reads each row one after another whereas ItemWriter writes in chunk?<\/strong><br \/>\n<strong>ItemReader<\/strong> is to process each item individually\u2014transforming, validating, or enriching it\u2014before it&#8217;s added to a chunk for writing whereas ItemWriter on other hand writes in bulk as it is faster and reduces overhead\u2014especially for I\/O operations like database inserts or file writes.<\/p>\n<p><strong  class=\"ctaHeader3\">How to prevent spring batch jobs run on start?<\/strong><\/p>\n<pre>\r\n.\r\n.\r\nspring.batch.job.enabled=false\r\n.\r\n.\r\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Frequently Asked Questions Job Execution vs Job Instance? Job instance is like blueprint. Job Execution is actual job. Job instance is Unique by Job Name + Parameters Job Execution need not be Unique incase of failed Execution Why Job Instance should be Unique? Spring Batch uses job name + parameters to identify a job instance.&hellip; <a href=\"https:\/\/codethataint.com\/blog\/5558-2\/\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[371],"tags":[],"class_list":["post-5558","post","type-post","status-publish","format-standard","hentry","category-spring-batch"],"_links":{"self":[{"href":"https:\/\/codethataint.com\/blog\/wp-json\/wp\/v2\/posts\/5558","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/codethataint.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/codethataint.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/codethataint.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/codethataint.com\/blog\/wp-json\/wp\/v2\/comments?post=5558"}],"version-history":[{"count":5,"href":"https:\/\/codethataint.com\/blog\/wp-json\/wp\/v2\/posts\/5558\/revisions"}],"predecessor-version":[{"id":5585,"href":"https:\/\/codethataint.com\/blog\/wp-json\/wp\/v2\/posts\/5558\/revisions\/5585"}],"wp:attachment":[{"href":"https:\/\/codethataint.com\/blog\/wp-json\/wp\/v2\/media?parent=5558"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/codethataint.com\/blog\/wp-json\/wp\/v2\/categories?post=5558"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/codethataint.com\/blog\/wp-json\/wp\/v2\/tags?post=5558"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}