{"id":5586,"date":"2025-09-15T13:05:10","date_gmt":"2025-09-15T13:05:10","guid":{"rendered":"https:\/\/codethataint.com\/blog\/?p=5586"},"modified":"2025-09-15T17:02:06","modified_gmt":"2025-09-15T17:02:06","slug":"triggering-spring-batch-job-from-rest-endpoints","status":"publish","type":"post","link":"https:\/\/codethataint.com\/blog\/triggering-spring-batch-job-from-rest-endpoints\/","title":{"rendered":"Triggering and Stopping Spring Batch Job from Rest Endpoints"},"content":{"rendered":"<p>To Stop the job from automatic run at the time of server start we should add the below property in application.properties<\/p>\n<ol>\n<li>Jobs would be created in JobsConfig.java and available as Bean<\/li>\n<li>JobService.java helps in launching the job. <strong>startJob<\/strong> method reads the json parameter and passed them as jobparameter to job<\/li>\n<li>JobController.java takes jobname as parameter along with json object in body<\/li>\n<li>JSON body contains JobParamsRequest datatype as argument<\/li>\n<li><strong class=\"ctaNote\">@EnableAsync<\/strong> is a Spring annotation that activates asynchronous method execution in application. Spring starts scanning for methods annotated with <strong  class=\"ctaNote\">@Async<\/strong> and runs them in separate threads, allowing your app to perform tasks without blocking the main thread\n<\/li>\n<li>@Async annotation is used over startJob in jobService.java<\/li>\n<li>createJobParam method uses builder method which builds job parameters<\/li>\n<li>JSON should be supplied with paramKey and paramValue<\/li>\n<\/ol>\n<p><strong>application.properties<\/strong><\/p>\n<pre>\r\n.\r\n.\r\nspring.batch.job.enabled=false\r\n.\r\n.\r\n<\/pre>\n<p><strong>json as in bruno<\/strong><\/p>\n<pre>\r\n[\r\n  {\r\n    \"paramKey\": \"Name\",\r\n    \"paramValue\": \"Mugil\"\r\n  },\r\n  {\r\n    \"paramKey\": \"Age\",\r\n    \"paramValue\": 38\r\n  },\r\n  {\r\n    \"paramKey\": \"Location\",\r\n    \"paramValue\": \"Chennai\"\r\n  }\r\n]\r\n<\/pre>\n<p><strong>SpringBatchWithRestApp.java<\/strong><\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\n@SpringBootApplication\r\n@EnableBatchProcessing\r\n@EnableAsync\r\npublic class SpringBatchWithRestApp {\r\n\tpublic static void main(String&#x5B;] args) {\r\n\t\tSpringApplication.run(SpringBatchWithRestApp.class, args);\r\n\t}\r\n}\r\n<\/pre>\n<p><strong>JobController.java<\/strong><\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\n@RestController\r\n@RequestMapping(&quot;\/jobs\/&quot;)\r\npublic class JobController {\r\n\r\n    @Autowired\r\n    JobService jobService;\r\n\r\n    @PostMapping(&quot;\/{jobName}&quot;)\r\n    public String triggerJob(@PathVariable String jobName, @RequestBody List&lt;JobParamsRequest&gt; jobParamsRequestList) throws Exception {\r\n        jobService.startJob(jobName, jobParamsRequestList);\r\n        return &quot;Job Started... .&quot;;\r\n    }\r\n}\r\n<\/pre>\n<p><strong>JobService.java<\/strong><\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\n@Service\r\npublic class JobService {\r\n\r\n    @Autowired\r\n    JobLauncher jobLauncher;\r\n\r\n    @Autowired\r\n    Job simpleTaskLetJob;\r\n\r\n    @Async\r\n    public void startJob(String jobName, List&lt;JobParamsRequest&gt; jobParamsRequestList) throws Exception {\r\n        JobExecution jobExecution = null;\r\n\r\n        \/\/Thread Added for Testing Async Behaviour\r\n        Thread.sleep(3000);\r\n\r\n        try {\r\n            if(jobName.equals(&quot;TaskletJob&quot;)){\r\n                jobExecution = jobLauncher.run(simpleTaskLetJob, createJobParam(jobParamsRequestList));\r\n                System.out.println(&quot;Job Execution ID = &quot; + jobExecution.getId());\r\n            }else{\r\n                System.out.println(&quot;Invalid Job Name&quot;);\r\n            }\r\n        } catch (Exception e) {\r\n            System.out.println(&quot;Exception while starting job &quot;+ e.getMessage());\r\n        }\r\n    }\r\n\r\n    public JobParameters createJobParam(List&lt;JobParamsRequest&gt; arrRequset) {\r\n        JobParametersBuilder jobParametersBuilder = new JobParametersBuilder();\r\n        arrRequset.forEach(jobParamsRequest -&gt; jobParametersBuilder\r\n                                                    .addString(jobParamsRequest.getParamKey(), jobParamsRequest.getParamValue())\r\n                                                    .addLong(&quot;time&quot;, System.currentTimeMillis()));\r\n        return jobParametersBuilder.toJobParameters();\r\n    }\r\n}\r\n<\/pre>\n<p><strong>JobParamsRequest.java<\/strong><\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\n@Setter\r\n@Getter\r\npublic class JobParamsRequest {\r\n    private String paramKey;\r\n    private String paramValue;\r\n}\r\n<\/pre>\n<p><strong>JobsConfig.java<\/strong><\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\n@Configuration\r\npublic class JobsConfig {\r\n    @Bean\r\n    public Job simpleTaskLetJob(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                .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<\/pre>\n<p><strong>Output<\/strong><\/p>\n<pre>\r\n2025-09-15T18:20:12.052+05:30  INFO 25776 --- [FileChecker] [         task-1] o.s.b.c.l.s.TaskExecutorJobLauncher      : Job: [SimpleJob: [name=job]] launched with the following parameters: [{'time':'{value=1757940612019, type=class java.lang.Long, identifying=true}','Age':'{value=38, type=class java.lang.String, identifying=true}','Name':'{value=Mugil, type=class java.lang.String, identifying=true}','Location':'{value=Chennai, type=class java.lang.String, identifying=true}'}]\r\n2025-09-15T18:20:12.063+05:30  INFO 25776 --- [FileChecker] [         task-1] o.s.batch.core.job.SimpleStepHandler     : Executing step: [Tasklet Oriented Step]\r\n2025-09-15T18:20:12.068+05:30  INFO 25776 --- [FileChecker] [         task-1] o.s.batch.core.step.AbstractStep         : Step: [Tasklet Oriented Step] executed in 5ms\r\n2025-09-15T18:20:12.071+05:30  INFO 25776 --- [FileChecker] [         task-1] o.s.b.c.l.s.TaskExecutorJobLauncher      : Job: [SimpleJob: [name=job]] completed with the following parameters: [{'time':'{value=1757940612019, type=class java.lang.Long, identifying=true}','Age':'{value=38, type=class java.lang.String, identifying=true}','Name':'{value=Mugil, type=class java.lang.String, identifying=true}','Location':'{value=Chennai, type=class java.lang.String, identifying=true}'}] and the following status: [COMPLETED] in 13ms\r\nJob Execution ID = 56\r\n<\/pre>\n<p><img decoding=\"async\" src=\"https:\/\/codethataint.com\/blog\/wp-content\/uploads\/2025\/09\/SpringBatchUsingRest.png\" alt=\"\" \/><\/p>\n<p><img decoding=\"async\" src=\"https:\/\/codethataint.com\/blog\/wp-content\/uploads\/2025\/09\/SpringBatchUsingRest2.png\" alt=\"\" \/><\/p>\n<p><img decoding=\"async\" src=\"https:\/\/codethataint.com\/blog\/wp-content\/uploads\/2025\/09\/JobController.png\" alt=\"\" \/><\/p>\n<p><strong class=\"ctaHeader3\">Stopping Spring Batch Job<\/strong><br \/>\n<strong>JobController.java<\/strong><\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\n@RestController\r\n@RequestMapping(&quot;\/jobs&quot;)\r\npublic class JobController {\r\n\r\n    @Autowired\r\n    JobService jobService;\r\n\r\n    @Autowired\r\n    JobOperator jobOperator;\r\n\r\n    @PostMapping(&quot;\/start\/{jobName}&quot;)\r\n    public String triggerJob(@PathVariable String jobName, @RequestBody List&lt;JobParamsRequest&gt; jobParamsRequestList) throws Exception {\r\n        jobService.startJob(jobName, jobParamsRequestList);\r\n        return &quot;Job Started... .&quot;;\r\n    }\r\n\r\n\r\n    @GetMapping(&quot;\/stop\/{jobExecutionId}&quot;)\r\n    public String StopJob(@PathVariable Long jobExecutionId) throws Exception {\r\n        jobOperator.stop(jobExecutionId);\r\n        return &quot;Job Stopped...&quot;;\r\n    }\r\n}\r\n<\/pre>\n<p><strong class=\"ctaNote\">Note<\/strong>:<br \/>\nTo Stop a running job, jobexecutionId should be passed as a parameter which could be fetched from <strong>batch_job_execution <\/strong>table in DB which has status as <strong>STARTED<\/strong><\/p>\n","protected":false},"excerpt":{"rendered":"<p>To Stop the job from automatic run at the time of server start we should add the below property in application.properties Jobs would be created in JobsConfig.java and available as Bean JobService.java helps in launching the job. startJob method reads the json parameter and passed them as jobparameter to job JobController.java takes jobname as parameter&hellip; <a href=\"https:\/\/codethataint.com\/blog\/triggering-spring-batch-job-from-rest-endpoints\/\">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-5586","post","type-post","status-publish","format-standard","hentry","category-spring-batch"],"_links":{"self":[{"href":"https:\/\/codethataint.com\/blog\/wp-json\/wp\/v2\/posts\/5586","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=5586"}],"version-history":[{"count":5,"href":"https:\/\/codethataint.com\/blog\/wp-json\/wp\/v2\/posts\/5586\/revisions"}],"predecessor-version":[{"id":5601,"href":"https:\/\/codethataint.com\/blog\/wp-json\/wp\/v2\/posts\/5586\/revisions\/5601"}],"wp:attachment":[{"href":"https:\/\/codethataint.com\/blog\/wp-json\/wp\/v2\/media?parent=5586"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/codethataint.com\/blog\/wp-json\/wp\/v2\/categories?post=5586"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/codethataint.com\/blog\/wp-json\/wp\/v2\/tags?post=5586"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}