{"id":14983132,"url":"https://github.com/chrisgleissner/spring-batch-rest","last_synced_at":"2025-04-05T01:06:51.145Z","repository":{"id":53280215,"uuid":"147162839","full_name":"chrisgleissner/spring-batch-rest","owner":"chrisgleissner","description":"REST API for Spring Batch using Spring Boot 2.2","archived":false,"fork":false,"pushed_at":"2024-09-30T18:33:54.000Z","size":363,"stargazers_count":88,"open_issues_count":5,"forks_count":43,"subscribers_count":8,"default_branch":"master","last_synced_at":"2025-03-29T00:09:34.896Z","etag":null,"topics":["batch","batch-processing","hateoas","java","java-11","java-8","rest","rest-api","spring-batch","spring-boot","spring-mvc","swagger2"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/chrisgleissner.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-09-03T06:45:19.000Z","updated_at":"2025-02-19T13:47:45.000Z","dependencies_parsed_at":"2024-09-28T08:40:47.550Z","dependency_job_id":"7e46e041-f841-4faa-9217-4a978f442867","html_url":"https://github.com/chrisgleissner/spring-batch-rest","commit_stats":{"total_commits":236,"total_committers":5,"mean_commits":47.2,"dds":0.2838983050847458,"last_synced_commit":"a11c45be88ada011f529cbd896a669e2f2b14656"},"previous_names":[],"tags_count":20,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chrisgleissner%2Fspring-batch-rest","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chrisgleissner%2Fspring-batch-rest/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chrisgleissner%2Fspring-batch-rest/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chrisgleissner%2Fspring-batch-rest/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/chrisgleissner","download_url":"https://codeload.github.com/chrisgleissner/spring-batch-rest/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247271530,"owners_count":20911587,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["batch","batch-processing","hateoas","java","java-11","java-8","rest","rest-api","spring-batch","spring-boot","spring-mvc","swagger2"],"created_at":"2024-09-24T14:06:46.967Z","updated_at":"2025-04-05T01:06:51.126Z","avatar_url":"https://github.com/chrisgleissner.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# spring-batch-rest\n\n[![Maven Central](https://img.shields.io/maven-central/v/com.github.chrisgleissner/spring-batch-rest-api)](https://search.maven.org/artifact/com.github.chrisgleissner/spring-batch-rest-api/)\n[![Javadocs](https://www.javadoc.io/badge/com.github.chrisgleissner/spring-batch-rest-api.svg)](https://www.javadoc.io/doc/com.github.chrisgleissner/spring-batch-rest-api)\n[![Build Status](https://github.com/chrisgleissner/spring-batch-rest/actions/workflows/build.yml/badge.svg)](https://github.com/chrisgleissner/spring-batch-rest/actions)\n[![Coverage Status](https://coveralls.io/repos/github/chrisgleissner/spring-batch-rest/badge.svg?branch=master)](https://coveralls.io/github/chrisgleissner/spring-batch-rest?branch=master)\n[![Maintainability](https://api.codeclimate.com/v1/badges/2267ddd7cbbfc5e22b86/maintainability)](https://codeclimate.com/github/chrisgleissner/spring-batch-rest/maintainability)\n\nREST API for \u003ca href=\"https://spring.io/projects/spring-batch\"\u003eSpring Batch\u003c/a\u003e based on \u003ca href=\"https://github.com/spring-projects/spring-boot\"\u003eSpring Boot 2.2\u003c/a\u003e and \u003ca href=\"https://github.com/spring-projects/spring-hateoas\"\u003eSpring HATOEAS\u003c/a\u003e. It comes with an OpenAPI 3 documentation provided by \u003ca href=\"https://github.com/springdoc/springdoc-openapi\"\u003eSpringdoc\u003c/a\u003e.\n\nSupports Java 8 and above. Tested on OpenJDK 8 and 11.\n\n## Features\n- Get information on jobs, job executions, and Quartz schedules\n- Start job execution (synchronous or asynchronous) with optional job property overrides. The job properties can\neither be obtained via a custom API or via standard Spring Batch job parameters, accessible from \u003ca href=\"https://docs.spring.io/spring-batch/trunk/apidocs/org/springframework/batch/core/scope/StepScope.html\"\u003estep-scoped beans\u003c/a\u003e.\n\n## Getting Started\n\nTo integrate the REST API in your Spring Boot project, first ensure you have an entry point to your application such as\n \n```java\n@SpringBootApplication\npublic class SpringBootApp {\n    public static void main(String[] args) {\n        SpringApplication.run(SpringBootApp.class, args);\n    }\n}\n``` \n \nThen, simply add one of the following two dependencies to your project:\n\n### Core API\n\nThe `spring-batch-rest-api` dependency comes with `jobs` and `jobExecutions` REST endpoints. It is recommended if you\ndon't require Quartz for scheduling your jobs.\n\nMaven:\n```xml\n\u003cdependency\u003e\n    \u003cgroupId\u003ecom.github.chrisgleissner\u003c/groupId\u003e\n    \u003cartifactId\u003espring-batch-rest-api\u003c/artifactId\u003e\n    \u003cversion\u003e1.5.1\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\nGradle:\n```\nimplementation 'com.github.chrisgleissner:spring-batch-rest-api:1.5.1'\n```\n\n### Quartz API\n\nThe `spring-batch-rest-quartz-api` dependency includes everything above and and additionally exposes Quartz schedules \nvia the `jobDetails` REST endpoint.\n\nMaven:\n```xml\n\u003cdependency\u003e\n    \u003cgroupId\u003ecom.github.chrisgleissner\u003c/groupId\u003e\n    \u003cartifactId\u003espring-batch-rest-quartz-api\u003c/artifactId\u003e\n    \u003cversion\u003e1.5.1\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\nGradle:\n```\nimplementation 'com.github.chrisgleissner:spring-batch-rest-quartz-api:1.5.1'\n```\n\n### See it in Action\n\nTo see `spring-batch-rest-api` in action, first install Java 8 or 11 as well as Maven, then run\n```text\nmvn install -Dmaven.test.skip; java -jar example/api/target/*.jar\n```\n\nFor `spring-batch-rest-quartz-api`, run\n```text\nmvn install -Dmaven.test.skip; java -jar example/quartz-api/target/*.jar\n```\n \nOnce it's up, check the Swagger REST API docs at \n[http://localhost:8080/swagger-ui.html](http://localhost:8080/swagger-ui.html).\n\n### Sample Walkthrough\n\nHere's how to run a [sample job](https://github.com/chrisgleissner/spring-batch-rest/tree/master/example/api/src/main/java/com/github/chrisgleissner/springbatchrest/example/core/PersonJobConfig.java), assuming\nyou've started the API as described above:\n\n* Click on `POST` to the left of `/jobExecutions`, then on `Try it Out` on the right-hand side. Replace the contents of the `Request body` with `{\"name\": \"personJob\"}`, then click `Execute`.\n* The job has now been triggered. When it completes, you'll get a response body similar to:\n```\n{\n  \"jobExecution\": {\n    \"id\": 0,\n    \"jobId\": 0,\n    \"jobName\": \"personJob\",\n    \"startTime\": \"2023-09-01T19:01:55.264\",\n    \"endTime\": \"2023-09-01T19:01:55.317\",\n    \"exitCode\": \"COMPLETED\",\n    \"exitDescription\": \"\",\n    \"status\": \"COMPLETED\",\n    \"exceptions\": []\n  },\n  \"_links\": {\n    \"self\": {\n      \"href\": \"http://localhost:8080/jobExecutions/0\"\n    }\n  }\n}\n```\n* You can now view this and other recently completed jobs by clicking on `GET` to the left of `/jobExecutions`, then on `Try it Out` followed by `Execute`. You should see something like:\n```\n{\n  \"_embedded\": {\n    \"jobExecutionResourceList\": [\n      {\n        \"jobExecution\": {\n          \"id\": 0,\n          \"jobId\": 0,\n          \"jobName\": \"personJob\",\n          \"startTime\": \"2023-09-01T19:01:55.264\",\n          \"endTime\": \"2023-09-01T19:01:55.317\",\n          \"exitCode\": \"COMPLETED\",\n          \"exitDescription\": \"\",\n          \"status\": \"COMPLETED\",\n          \"exceptions\": []\n        },\n        \"_links\": {\n          \"self\": {\n            \"href\": \"http://localhost:8080/jobExecutions/0\"\n          }\n        }\n      }\n    ]\n  },\n  \"_links\": {\n    \"self\": {\n      \"href\": \"http://localhost:8080/jobExecutions?limitPerJob=3\"\n    }\n  }\n}\n```\n\n## REST Endpoints\n\nThe following REST endpoints are available:\n\n### Jobs\n\n| HTTP Method  | Path                   | Description  |\n|--------------|------------------------|--------------|\n| GET          | /jobs                  | All jobs  |\n| GET          | /jobs/{jobName}        | Single job  |\n\n### Job Executions\n\n| HTTP Method  | Path                   | Description  |\n|--------------|------------------------|--------------|\n| GET          | /jobExecutions         | Latest 3 executions for each job, sorted by descending end time (or start time if still running) |\n| GET          | /jobExecutions/{id}    | Single job execution |\n| POST         | /jobExecutions         | Start job execution with optional property overrides |\n\n#### Request Parameters for GET `/jobExecutions` \n\n| Parameter | Default Value | Description |\n|-----------|---------------|-------------|\n| jobName | empty | \u003ca href=\"https://docs.oracle.com/javase/7/docs/api/java/util/regex/Pattern.html\"\u003eRegular expression\u003c/a\u003e of the job names to consider. If empty, all job names are used. |\n| exitCode | empty | Exit code of the job execution. Can be `COMPLETED`, `EXECUTING`, `FAILED`, `NOOP`, `STOPPED` or `UNKNOWN` as per \u003ca href=\"https://docs.spring.io/spring-batch/trunk/apidocs/org/springframework/batch/core/ExitStatus.html\"\u003eExitStatus\u003c/a\u003e. If empty, all exit codes are used. |\n| limitPerJob | 3 | Maximum number of job executions to return for each job. |\n\n#### Examples\n\n| HTTP Method  | Path                   | Description  |\n|--------------|------------------------|--------------|\n| GET          | /jobExecutions?limitPerJob=50  | Latest 50 executions for each job |\n| GET          | /jobExecutions?jobName=foo\u0026exitCode=FAILED | Latest 3 failed executions for 'foo' job |\n| GET          | /jobExecutions?jobName=foo.*\u0026exitCode=FAILED\u0026limitPerJob=10 | Latest 10 failed executions for jobs with a name starting with 'foo' |\n\n### Quartz Schedules\n\nAs mentioned above, these endpoints are only exposed if you're using the `spring-batch-rest-quartz-api` dependency:\n\n| HTTP Method  | Path                   | Description  |\n|--------------|------------------------|--------------|\n| GET          | /jobDetails            | All Quartz schedules   |\n| GET          | /jobsDetails/{quartzGroupName}/{quartzJobName}  | Single Quartz schedule |\n\n## Error Handling\n\nWhere possible, subclasses of the Spring Batch \u003ca href=\"https://docs.spring.io/spring-batch/trunk/apidocs/org/springframework/batch/core/JobExecutionException.html\"\u003eJobExecutionException\u003c/a\u003e\nare mapped to an appropriate HTTP status code and the response body contains further details. \n\nFor example, trying to start a nonexistent job results in a response with a 404 status code and the following response body:\n```\n{\n  \"status\": \"404 NOT_FOUND\",\n  \"message\": \"No job configuration with the name [foo] was registered\",\n  \"exception\": \"NoSuchJobException\",\n  \"detail\": \"Failed to start job 'foo' with JobConfig(name=foo, properties={foo=baz10}, asynchronous=false). Reason: No job configuration with the name [foo] was registered\"\n}\n```\n\n## Configuration\n\nThe default behaviour of the REST API can be tweaked via several Spring properties which can be placed in `application.properties`.\n\n### Job Execution Caching\n\n`com.github.chrisgleissner.springbatchrest.jobExecutionCacheSize` (default: 100)\n\nFor performance reasons, `/jobExecutions` queries are performed against an in-memory cache of recent \njob executions. If the `limitPerJob` request parameter is larger than the value of this property, the cache is bypassed and the\nSpring Batch \u003ca href=\"https://docs.spring.io/spring-batch/4.0.x/api/index.html?org/springframework/batch/core/explore/JobExplorer.html\"\u003eJobExplorer\u003c/a\u003e is used instead.\n\nLarge `jobExecutionCacheSize` values will result in increased heap use, but small values combined with large `limitSize` request parameters\nwill cause increased REST query latencies. Thus, if you increase this property value, you may also want to increase your heap size. \n\nThe cache only contains job executions since the Spring context creation, ie. it is not warmed up from the JobExplorer and the DB this may rely on. If you want to be able to query job executions that were performed earlier, eg. during a prior JVM execution, you may want to disable caching. To do so, simply set the property to 0.\n\n\n### Repeated Job Execution\n\n`com.github.chrisgleissner.springbatchrest.addUniqueJobParameter` (default: true)\n\nSpring Batch prevents repeated invocations of a job unless you use different properties (aka job parameters) each time. To bypass this, a unique property (ie. a random UUID) is added to each job invocation. You can disable this by setting the property to false. \n\n### Disable Spring Batch REST API REST Endpoints\n\n`com.github.chrisgleissner.springbatchrest.enabled=false` (default: true)\n\nUseful if you only want to expose the REST API in certain environments.\n\n### Disable Swagger UI \n\n`springdoc.swagger-ui.enabled=false` (default: true)\n\nSee https://github.com/springdoc/springdoc-openapi for further config options.\n\n### Disable Custom Exception Handling \n\n`com.github.chrisgleissner.springbatchrest.controllerAdvice=false` (default: true)\n\nThis disables the global exception handling via `com.github.chrisgleissner.springbatchrest.api.core.jobexecution.ResponseExceptionHandler`. \n\n## Job Property Overrides\n\nProperties can be overridden when starting a job via REST. You can then access these overrides in one of the following ways.\n\n### @Value\n\nAnnotate your Spring bean method with `@StepScope` and use the `@Value` annotation on a method parameter \nto specify the desired job parameter name. \n\nPlease note that this approach won't transparently fall back to Spring environment properties. Thus,\nif this is desired, you should manually check if a job parameter is `null` and in this case return it from the Spring `Environment` instance. \n\nExample:\n```java\n@Bean @StepScope  \nItemWriter\u003cObject\u003e writer(@Value(\"#{jobParameters['sampleProperty']}\") String sampleProperty) {\n    // ... \n}\n```\n\n### PropertyResolver\n\nWhen using `AdhocStarter`, you can create a `Job` using a `JobBuilder` and pass in a `Consumer\u003cPropertyResolver\u003e`. \n\nProperties looked up from this `PropertyResolver` transparently fall back to the Spring environment if properties can't be found in the job parameters.\n\nExample:\n```java\nJob job = jobBuilder.createJob(\"sampleJob\", propertyResolver -\u003e {\n    String propertyValue = propertyResolver.getProperty(\"sampleProperty\");\n    // ...\n});\n```\n\n### JobProperties\n\nIn case you don't execute the same job concurrently, you may also look up properties from the `JobProperties` singleton. \n\nProperties looked up from this singleton transparently fall back to the Spring environment if properties can't be found in the \njob parameters. \n\nThis approach is *deprecated* as it doesn't work with concurrent execution of the same job. Therefore, it is recommended to use one\nof the other approaches.\n\nExample:\n```java\n@Bean\nItemWriter\u003cObject\u003e writer() {\n    return new ItemWriter\u003cObject\u003e() {\n        @Override\n        public void write(List\u003c?\u003e items) throws Exception {\n           String sampleProperty = JobPropertyResolvers.JobProperties.of(\"sampleJob\").getProperty(\"sampleProperty\");\n           // ...\n        }\n    }\n}\n```\n\n## Utilities\n\nThe \u003ca href=\"https://github.com/chrisgleissner/spring-batch-rest/tree/master/util/src/main/java/com/github/chrisgleissner/springbatchrest/util\"\u003eutil module\u003c/a\u003e contains code for registering, starting and scheduling jobs:\n\n[JobBuilder](https://github.com/chrisgleissner/spring-batch-rest/blob/master/util/src/main/java/com/github/chrisgleissner/springbatchrest/util/core/JobBuilder.java) builds a simple job based on a \u003ca href=\"https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/Runnable.html\"\u003eRunnable\u003c/a\u003e:\n\n```java\nJob job = jobBuilder.createJob(\"jobName\", () -\u003e System.out.println(\"Running job\"));\n```\n\n[AdHocScheduler](https://github.com/chrisgleissner/spring-batch-rest/blob/master/util/src/main/java/com/github/chrisgleissner/springbatchrest/util/quartz/AdHocScheduler.java) registers and triggers a job using a Quartz CRON trigger. This can be performed at \nrun-time rather than Spring wiring time which allows for simplified set-up of a large number of jobs that only \ndiffer slightly:\n\n```java\nadHocScheduler.schedule(\"jobName\", job, \"0/30 * * * * ?\");\n```\n\n[AdHocStarter](https://github.com/chrisgleissner/spring-batch-rest/blob/master/util/src/main/java/com/github/chrisgleissner/springbatchrest/util/core/AdHocStarter.java) is similar to AdHocScheduler, but used for immediately starting a job:\n\n```java\nadHocStarter.start(job);\n\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchrisgleissner%2Fspring-batch-rest","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fchrisgleissner%2Fspring-batch-rest","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchrisgleissner%2Fspring-batch-rest/lists"}