├── .gitattributes
├── .github
└── workflows
│ ├── build-main.yml
│ └── release-to-maven-central.yml
├── .gitignore
├── LICENSE.TXT
├── README.md
├── batch-web-spring-boot-autoconfigure
├── pom.xml
└── src
│ ├── main
│ ├── java
│ │ └── de
│ │ │ └── codecentric
│ │ │ └── batch
│ │ │ ├── configuration
│ │ │ ├── AutomaticJobRegistrarConfiguration.java
│ │ │ ├── AutomaticJobRegistrarConfigurationSupport.java
│ │ │ ├── BatchConfigurationProperties.java
│ │ │ ├── BatchWebAutoConfiguration.java
│ │ │ ├── Jsr352BatchConfiguration.java
│ │ │ ├── ListenerProvider.java
│ │ │ ├── MetricsConfiguration.java
│ │ │ ├── StepExecutionJacksonMixIn.java
│ │ │ ├── TaskExecutorBatchConfiguration.java
│ │ │ ├── TaskExecutorConfiguration.java
│ │ │ └── WebConfig.java
│ │ │ ├── jsr352
│ │ │ └── CustomJsrJobOperator.java
│ │ │ ├── listener
│ │ │ ├── AddListenerToJobService.java
│ │ │ ├── JobLoggingApplicationListener.java
│ │ │ ├── LoggingAfterJobListener.java
│ │ │ ├── LoggingListener.java
│ │ │ ├── ProtocolListener.java
│ │ │ └── RunningExecutionTrackerListener.java
│ │ │ ├── logging
│ │ │ ├── DefaultJobLogFileNameCreator.java
│ │ │ └── JobLogFileNameCreator.java
│ │ │ ├── metrics
│ │ │ ├── AbstractBatchMetricsAspect.java
│ │ │ ├── BatchMetrics.java
│ │ │ ├── BatchMetricsImpl.java
│ │ │ ├── MetricsListener.java
│ │ │ ├── MetricsOutputFormatter.java
│ │ │ └── ReaderProcessorWriterMetricsAspect.java
│ │ │ ├── monitoring
│ │ │ └── RunningExecutionTracker.java
│ │ │ ├── scheduling
│ │ │ └── concurrent
│ │ │ │ └── MdcThreadPoolTaskExecutor.java
│ │ │ └── web
│ │ │ ├── JobMonitoringController.java
│ │ │ └── JobOperationsController.java
│ └── resources
│ │ ├── META-INF
│ │ ├── additional-spring-configuration-metadata.json
│ │ └── spring.factories
│ │ ├── batch-web-spring-boot-autoconfigure.properties
│ │ └── logback-batch-base.xml
│ └── test
│ ├── java
│ └── de
│ │ └── codecentric
│ │ └── batch
│ │ ├── AutoconfigureBatchWebStarter.java
│ │ ├── MetricsTestApplication.java
│ │ ├── TestApplication.java
│ │ ├── TestConfiguration.java
│ │ ├── TestListenerConfiguration.java
│ │ ├── item
│ │ ├── DelayItemProcessor.java
│ │ ├── DummyItemReader.java
│ │ ├── LogItemProcessor.java
│ │ ├── LogItemWriteListener.java
│ │ ├── LogItemWriter.java
│ │ └── MetricsItemProcessor.java
│ │ ├── jobs
│ │ ├── DelayJobConfiguration.java
│ │ ├── FlatFileJobConfiguration.java
│ │ ├── FlatFileToDbNoSkipJobConfiguration.java
│ │ ├── FlatFileToDbSkipJobConfiguration.java
│ │ ├── FlatFileToDbSkipProcessorNonTransactionalJobConfiguration.java
│ │ ├── FlatFileToDbSkipReaderTransactionalJobConfiguration.java
│ │ ├── IncrementerJobConfiguration.java
│ │ ├── SimpleBatchMetricsJobConfiguration.java
│ │ └── SimpleJobConfiguration.java
│ │ ├── listener
│ │ ├── ProtocolListenerTest.java
│ │ └── TestListener.java
│ │ ├── metrics
│ │ ├── Action.java
│ │ ├── BatchMetricsImplTest.java
│ │ ├── Item.java
│ │ ├── ListenerMetricsAspect.java
│ │ ├── MetricNames.java
│ │ ├── MetricsTestException.java
│ │ └── item
│ │ │ ├── MetricsTestChunkListener.java
│ │ │ ├── MetricsTestItemProcessListener.java
│ │ │ ├── MetricsTestItemProcessor.java
│ │ │ ├── MetricsTestItemReadListener.java
│ │ │ ├── MetricsTestItemReader.java
│ │ │ ├── MetricsTestItemWriteListener.java
│ │ │ ├── MetricsTestItemWriter.java
│ │ │ └── MetricsTestSkipListener.java
│ │ ├── scheduling
│ │ └── concurrent
│ │ │ └── MdcThreadPoolTaskExecutorTest.java
│ │ └── test
│ │ ├── FlatFileJobTest.java
│ │ ├── JavaConfigIntegrationTest.java
│ │ ├── JobParametersIncrementerIntegrationTest.java
│ │ ├── Jsr352IntegrationTest.java
│ │ ├── ListenerProviderIntegrationTest.java
│ │ ├── PartitionedFlatFileJobTest.java
│ │ ├── StopJobIntegrationTest.java
│ │ ├── XmlIntegrationTest.java
│ │ └── metrics
│ │ ├── BatchMetricsAspectIntegrationTest.java
│ │ ├── BatchMetricsExporterIntegrationTest.java
│ │ ├── BatchMetricsFlatFileToDbIntegrationTest.java
│ │ ├── MetricValidator.java
│ │ └── MetricValidatorBuilder.java
│ └── resources
│ ├── META-INF
│ ├── batch-jobs
│ │ └── simpleJsr352Job.xml
│ └── spring
│ │ └── batch
│ │ └── jobs
│ │ ├── flat-file-2-job.xml
│ │ ├── flat-file-job.xml
│ │ └── partitioned-flat-file-job.xml
│ ├── application.properties
│ ├── in-javaconfig.txt
│ ├── in-xmlconfig.txt
│ ├── logback.xml
│ ├── metrics
│ ├── create-schema.sql
│ ├── flatFileToDbNoSkipJob_Failed.csv
│ ├── flatFileToDbNoSkipJob_Restart_FirstRun.csv
│ ├── flatFileToDbNoSkipJob_Restart_SecondRun.csv
│ ├── flatFileToDbNoSkipJob_Success.csv
│ ├── flatFileToDbSkipJob_SkipInProcess.csv
│ ├── flatFileToDbSkipJob_SkipInProcess_Failed.csv
│ ├── flatFileToDbSkipJob_SkipInRead.csv
│ └── flatFileToDbSkipJob_SkipInWrite.csv
│ ├── partition-1.txt
│ └── partition-2.txt
├── batch-web-spring-boot-build
└── pom.xml
├── batch-web-spring-boot-dependencies
└── pom.xml
├── batch-web-spring-boot-docs
├── deploy-gh-pages.sh
├── pom.xml
└── src
│ └── main
│ └── asciidoc
│ └── index.adoc
├── batch-web-spring-boot-samples
├── batch-boot-file-to-db
│ ├── .gitignore
│ ├── README.md
│ ├── pom.xml
│ ├── src
│ │ ├── main
│ │ │ ├── java
│ │ │ │ └── de
│ │ │ │ │ └── codecentric
│ │ │ │ │ └── batch
│ │ │ │ │ └── filetodb
│ │ │ │ │ ├── Application.java
│ │ │ │ │ ├── configuration
│ │ │ │ │ └── DataSourceConfiguration.java
│ │ │ │ │ ├── domain
│ │ │ │ │ └── Partner.java
│ │ │ │ │ └── item
│ │ │ │ │ ├── ExampleService.java
│ │ │ │ │ └── LogItemProcessor.java
│ │ │ └── resources
│ │ │ │ ├── META-INF
│ │ │ │ └── spring
│ │ │ │ │ └── batch
│ │ │ │ │ └── jobs
│ │ │ │ │ └── flatfile-job-context.xml
│ │ │ │ ├── application.properties
│ │ │ │ ├── logback.xml
│ │ │ │ ├── partner-import.csv
│ │ │ │ └── schema-partner.sql
│ │ └── test
│ │ │ └── java
│ │ │ └── de
│ │ │ └── codecentric
│ │ │ └── batch
│ │ │ └── filetodb
│ │ │ ├── ApplicationTests.java
│ │ │ └── FlatFileJobIntegrationTest.java
│ └── startBatchApplication.launch
├── batch-boot-simple-jsr352
│ ├── .gitignore
│ ├── pom.xml
│ └── src
│ │ ├── main
│ │ ├── java
│ │ │ └── de
│ │ │ │ └── codecentric
│ │ │ │ └── batch
│ │ │ │ └── simplejsr
│ │ │ │ ├── Application.java
│ │ │ │ └── item
│ │ │ │ ├── DummyItemReader.java
│ │ │ │ ├── LogItemProcessor.java
│ │ │ │ ├── LogItemWriter.java
│ │ │ │ ├── PartitionedItemReader.java
│ │ │ │ └── SimplePartitionMapper.java
│ │ └── resources
│ │ │ ├── META-INF
│ │ │ ├── batch-jobs
│ │ │ │ ├── partitionMapperJobNoDI.xml
│ │ │ │ ├── partitionMapperJobSpringDI.xml
│ │ │ │ ├── partitionMapperJobSpringDIBatchXml.xml
│ │ │ │ ├── partitionedJobNoDI.xml
│ │ │ │ ├── partitionedJobSpringDI.xml
│ │ │ │ └── simpleJob.xml
│ │ │ └── batch.xml
│ │ │ ├── application.properties
│ │ │ └── logback.xml
│ │ └── test
│ │ └── java
│ │ └── de
│ │ └── codecentric
│ │ └── batch
│ │ └── simplejsr
│ │ ├── ApplicationTests.java
│ │ └── TraditionalJsr352Test.java
├── batch-boot-simple
│ ├── .gitignore
│ ├── pom.xml
│ └── src
│ │ ├── main
│ │ ├── java
│ │ │ └── de
│ │ │ │ └── codecentric
│ │ │ │ └── batch
│ │ │ │ └── simple
│ │ │ │ ├── Application.java
│ │ │ │ ├── item
│ │ │ │ ├── DummyItemReader.java
│ │ │ │ ├── LogItemProcessor.java
│ │ │ │ └── LogItemWriter.java
│ │ │ │ └── job
│ │ │ │ └── SimpleJobConfiguration.java
│ │ └── resources
│ │ │ ├── application.properties
│ │ │ ├── logback.xml
│ │ │ ├── monitoring.http
│ │ │ └── operations.http
│ │ └── test
│ │ └── java
│ │ └── de
│ │ └── codecentric
│ │ └── batch
│ │ └── simple
│ │ └── ApplicationTests.java
└── pom.xml
├── batch-web-spring-boot-starter
└── pom.xml
└── pom.xml
/.gitattributes:
--------------------------------------------------------------------------------
1 | # All text files should have the "lf" (Unix) line endings
2 | * text eol=lf
3 |
4 | # Explicitly declare text files you want to always be normalized and converted
5 | # to native line endings on checkout.
6 | *.java text
7 | *.js text
8 | *.css text
9 | *.html text
10 | *.properties text
11 | *.xml text
12 | *.yml text
13 |
14 | # Denote all files that are truly binary and should not be modified.
15 | *.png binary
16 | *.jpg binary
17 | *.jar binary
18 |
--------------------------------------------------------------------------------
/.github/workflows/build-main.yml:
--------------------------------------------------------------------------------
1 | name: build main
2 |
3 | on:
4 | push:
5 | branches:
6 | - master
7 |
8 | jobs:
9 | build:
10 | strategy:
11 | matrix:
12 | os: [ubuntu-latest]
13 |
14 | runs-on: ${{ matrix.os }}
15 | steps:
16 |
17 | - uses: actions/checkout@v3
18 |
19 | - name: Set up JDK 8
20 | uses: actions/setup-java@v3
21 | with:
22 | distribution: 'temurin'
23 | java-version: '8'
24 |
25 | - name: Cache local Maven repository
26 | uses: actions/cache@v2.1.7
27 | env:
28 | cache-name: cache-mvn
29 | with:
30 | path: ~/.m2/repository
31 | key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/pom.xml') }}
32 | restore-keys: |
33 | ${{ runner.os }}-build-${{ env.cache-name }}-
34 | ${{ runner.os }}-build-
35 | ${{ runner.os }}-
36 |
37 | - name: Build Tag with Maven
38 | if: ${{ github.ref_type == 'tag' }}
39 | run: |
40 | mvn -B clean verify -Pcoverage -Drevision=${{ github.ref_name }}
41 |
42 | - name: Build Branch with Maven
43 | if: ${{ github.ref_type == 'branch' }}
44 | run: |
45 | mvn -B clean verify -Pcoverage
46 |
47 | - uses: codecov/codecov-action@v2
48 | with:
49 | files: "**/target/site/jacoco/jacoco.xml"
50 |
51 | publish-snapshot:
52 | needs: build
53 | runs-on: ubuntu-latest
54 |
55 | steps:
56 | - uses: actions/checkout@v3
57 |
58 | - name: Set up settings.xml for GitHub Packages
59 | uses: actions/setup-java@v3
60 | with:
61 | distribution: 'temurin'
62 | java-version: '8'
63 |
64 | - name: Cache local Maven repository
65 | uses: actions/cache@v2.1.7
66 | env:
67 | cache-name: cache-mvn
68 | with:
69 | path: ~/.m2/repository
70 | key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/pom.xml') }}
71 | restore-keys: |
72 | ${{ runner.os }}-build-${{ env.cache-name }}-
73 | ${{ runner.os }}-build-
74 | ${{ runner.os }}-
75 |
76 | - name: Publish SNAPSHOT version to GitHub Packages (we can skip tests, since we only deploy, if the build workflow succeeded)
77 | run: mvn -B --no-transfer-progress deploy -DskipTests
78 | env:
79 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
80 |
81 | - name: Extract Maven project version for Asciidoc GitHub Pages directory naming
82 | run: echo ::set-output name=version::$(mvn -q -Dexec.executable=echo -Dexec.args='${project.version}' --non-recursive exec:exec)
83 | id: project
84 |
85 | - name: Show extracted Maven project version
86 | run: echo ${{ steps.project.outputs.version }}
87 |
88 | - name: Deploy Asciidoc docs output to GitHub Pages
89 | uses: JamesIves/github-pages-deploy-action@v4.3.3
90 | with:
91 | branch: gh-pages # The branch the action should deploy to.
92 | folder: batch-web-spring-boot-docs/target/generated-docs # The folder the action should deploy.
93 | target-folder: ${{ steps.project.outputs.version }}
94 | clean: true # Automatically remove deleted files from the deploy branch
95 |
--------------------------------------------------------------------------------
/.github/workflows/release-to-maven-central.yml:
--------------------------------------------------------------------------------
1 | name: release-to-maven-central
2 |
3 | on:
4 | workflow_dispatch:
5 | inputs:
6 | releaseversion:
7 | description: 'Release version'
8 | required: true
9 | default: '2.4.0'
10 |
11 | jobs:
12 | publish-central-and-pages:
13 | runs-on: ubuntu-latest
14 | steps:
15 | - run: echo "Will start a Maven Central upload with version ${{ github.event.inputs.releaseversion }}"
16 |
17 | - uses: actions/checkout@v3
18 |
19 | - name: Set up settings.xml for Maven Central Repository
20 | uses: actions/setup-java@v3
21 | with:
22 | distribution: 'temurin'
23 | java-version: '8'
24 | server-id: oss.sonatype.org
25 | server-username: MAVEN_USERNAME
26 | server-password: MAVEN_PASSWORD
27 | gpg-private-key: ${{ secrets.MAVEN_GPG_PRIVATE_KEY }}
28 | gpg-passphrase: MAVEN_GPG_PASSPHRASE
29 |
30 | - name: Cache local Maven repository
31 | uses: actions/cache@v2.1.7
32 | env:
33 | cache-name: cache-mvn
34 | with:
35 | path: ~/.m2/repository
36 | key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/pom.xml') }}
37 | restore-keys: |
38 | ${{ runner.os }}-build-${{ env.cache-name }}-
39 | ${{ runner.os }}-build-
40 | ${{ runner.os }}-
41 |
42 | - name: Set projects Maven version to GitHub Action GUI set version
43 | run: mvn versions:set "-DnewVersion=${{ github.event.inputs.releaseversion }}" --no-transfer-progress
44 |
45 | - name: Publish package
46 | run: mvn --batch-mode clean deploy --no-transfer-progress -P central-deploy -DskipTests=true
47 | env:
48 | MAVEN_USERNAME: ${{ secrets.OSS_SONATYPE_USERNAME }}
49 | MAVEN_PASSWORD: ${{ secrets.OSS_SONATYPE_PASSWORD }}
50 | MAVEN_GPG_PASSPHRASE: ${{ secrets.MAVEN_GPG_PASSPHRASE }}
51 |
52 | - name: Deploy Asciidoc docs output to GitHub Pages
53 | uses: JamesIves/github-pages-deploy-action@v4.3.3
54 | with:
55 | branch: gh-pages # The branch the action should deploy to.
56 | folder: batch-web-spring-boot-docs/target/generated-docs # The folder the action should deploy.
57 | target-folder: ${{ github.event.inputs.releaseversion }}
58 | clean: true # Automatically remove deleted files from the deploy branch
59 |
60 |
61 | publish-github-release:
62 | needs: publish-central-and-pages
63 | runs-on: ubuntu-latest
64 |
65 | steps:
66 | - uses: actions/checkout@v3
67 |
68 | - name: Generate changelog
69 | id: changelog
70 | uses: metcalfc/changelog-generator@v3.0.0
71 | with:
72 | myToken: ${{ secrets.GITHUB_TOKEN }}
73 |
74 | - name: Create GitHub Release
75 | id: create_release
76 | uses: actions/create-release@v1
77 | env:
78 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
79 | with:
80 | tag_name: ${{ github.event.inputs.releaseversion }}
81 | release_name: ${{ github.event.inputs.releaseversion }}
82 | body: |
83 | Grab the new version from Maven central https://repo1.maven.org/maven2/de/codecentric/
84 |
85 | Current docs at https://codecentric.github.io/spring-boot-starter-batch-web/${{ github.event.inputs.releaseversion }}/
86 |
87 | ### Things that changed in this release
88 | ${{ steps.changelog.outputs.changelog }}
89 | draft: false
90 | prerelease: ${{ contains(github.event.inputs.releaseversion, '-') }}
91 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Maven
2 | target/
3 | .flattened-pom.xml
4 |
5 | # Eclipse
6 | .settings/
7 | .classpath
8 | .project
9 | .factorypath
10 |
11 | # Intellij
12 | .idea/
13 | *.iml
14 | *.iws
15 |
16 | # Apple
17 | .DS_Store
18 |
19 | # GnuPG keyring
20 | /.gnupg
21 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Enterprise-ready production-ready batch applications powered by Spring Boot
2 | =============================
3 | [](https://github.com/codecentric/spring-boot-starter-batch-web/actions/workflows/build-main.yml)
4 | [](https://codecov.io/gh/codecentric/spring-boot-starter-batch-web)
5 | [](https://maven-badges.herokuapp.com/maven-central/de.codecentric/batch-web-spring-boot-starter/)
6 | [](http://www.apache.org/licenses/LICENSE-2.0.html)
7 |
8 | The project batch-web-spring-boot-starter is a Spring Boot starter for Spring Batch taking care of everything except writing the jobs.
9 |
10 | See the documentation for detailed infos, examples and operational details.
11 | * [Latest Snapshot](http://codecentric.github.io/spring-boot-starter-batch-web/2.4.0.SNAPSHOT/)
12 | * [Version 2.3.0](http://codecentric.github.io/spring-boot-starter-batch-web/2.3.0/)
13 | * [Version 1.4.0.RELEASE](http://codecentric.github.io/spring-boot-starter-batch-web/1.4.0.RELEASE/)
14 |
15 | Features include:
16 |
17 | * Starting up a web application and automatically deploying batch jobs to it (JavaConfig, XML or JSR-352).
18 | * Log file separation, one log file for each job execution.
19 | * An operations http endpoint for starting and stopping jobs, for retrieving the BatchStatus and the log file.
20 | * A monitoring http endpoint for retrieving detailed information on a job execution, for knowing all deployed jobs and all running job executions.
21 |
22 | Take a look at the [Getting Started page](http://codecentric.github.io/spring-boot-starter-batch-web/current/#_getting_started).
23 |
24 | There are the following samples available:
25 |
26 | [batch-boot-simple](/batch-web-spring-boot-samples/batch-boot-simple): a very simple JavaConfig sample with an embedded database.
27 |
28 | [batch-boot-file-to-db](/batch-web-spring-boot-samples/batch-boot-file-to-db): a job configured in xml using job parameters that reads from a file and writes to a database. This sample demonstrates the usage of an external database.
29 |
30 | [batch-boot-simple-jsr352](/batch-web-spring-boot-samples/batch-boot-simple-jsr352): job samples in JSR-352 style.
31 |
--------------------------------------------------------------------------------
/batch-web-spring-boot-autoconfigure/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
20 | 4.0.0
21 | batch-web-spring-boot-autoconfigure
22 | Batch Web Spring Boot Autoconfigure
23 |
24 | de.codecentric
25 | batch-web-spring-boot-build
26 | ${revision}
27 | ../batch-web-spring-boot-build
28 |
29 |
30 |
31 | org.springframework.boot
32 | spring-boot-starter
33 |
34 |
35 | org.springframework.boot
36 | spring-boot-starter-batch
37 |
38 |
39 | org.springframework.boot
40 | spring-boot-starter-actuator
41 |
42 |
43 | org.springframework.boot
44 | spring-boot-starter-web
45 |
46 |
47 | org.springframework.boot
48 | spring-boot-starter-jdbc
49 |
50 |
51 | org.springframework.boot
52 | spring-boot-starter-aop
53 |
54 |
55 | org.springframework.boot
56 | spring-boot-configuration-processor
57 | true
58 |
59 |
60 | org.springframework
61 | spring-messaging
62 |
63 |
64 | org.apache.commons
65 | commons-lang3
66 |
67 |
68 |
69 |
70 | org.springframework.boot
71 | spring-boot-starter-test
72 | test
73 |
74 |
75 | commons-io
76 | commons-io
77 | 2.11.0
78 | test
79 |
80 |
81 | org.hsqldb
82 | hsqldb
83 | test
84 |
85 |
86 |
87 |
--------------------------------------------------------------------------------
/batch-web-spring-boot-autoconfigure/src/main/java/de/codecentric/batch/configuration/AutomaticJobRegistrarConfigurationSupport.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package de.codecentric.batch.configuration;
18 |
19 | import javax.annotation.PostConstruct;
20 |
21 | import org.springframework.batch.core.configuration.support.ApplicationContextFactory;
22 | import org.springframework.batch.core.configuration.support.AutomaticJobRegistrar;
23 | import org.springframework.beans.factory.annotation.Autowired;
24 | import org.springframework.core.Ordered;
25 |
26 | /**
27 | * Extend this class to add custom {@link ApplicationContextFactory}.
28 | *
29 | * @author Thomas Bosch
30 | */
31 | public abstract class AutomaticJobRegistrarConfigurationSupport {
32 |
33 | @Autowired
34 | private AutomaticJobRegistrar automaticJobRegistrar;
35 |
36 | @PostConstruct
37 | public void initialize() throws Exception {
38 | // Default order for the AutomaticJobRegistrar is Ordered.LOWEST_PRECEDENCE. Since we want to register
39 | // listeners after the jobs are registered through the AutomaticJobRegistrar, we need to decrement its
40 | // order value by one. The creation of the AutomaticJobRegistrar bean is hidden deep in the automatic
41 | // batch configuration, so we unfortunately have to do it here.
42 | automaticJobRegistrar.setOrder(Ordered.LOWEST_PRECEDENCE - 1);
43 | addApplicationContextFactories(automaticJobRegistrar);
44 | }
45 |
46 | /**
47 | * Add ApplicationContextFactories to the given job registrar.
48 | *
49 | * @param automaticJobRegistrar
50 | * Bean
51 | * @throws Exception
52 | * Some error.
53 | */
54 | protected abstract void addApplicationContextFactories(AutomaticJobRegistrar automaticJobRegistrar)
55 | throws Exception;
56 |
57 | }
58 |
--------------------------------------------------------------------------------
/batch-web-spring-boot-autoconfigure/src/main/java/de/codecentric/batch/configuration/Jsr352BatchConfiguration.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package de.codecentric.batch.configuration;
17 |
18 | import org.springframework.batch.core.configuration.JobRegistry;
19 | import org.springframework.batch.core.explore.JobExplorer;
20 | import org.springframework.batch.core.jsr.JsrJobParametersConverter;
21 | import org.springframework.batch.core.repository.JobRepository;
22 | import org.springframework.beans.factory.annotation.Autowired;
23 | import org.springframework.context.annotation.Bean;
24 | import org.springframework.context.annotation.Configuration;
25 | import org.springframework.core.task.TaskExecutor;
26 | import org.springframework.transaction.PlatformTransactionManager;
27 |
28 | import de.codecentric.batch.jsr352.CustomJsrJobOperator;
29 |
30 | import javax.sql.DataSource;
31 |
32 | /**
33 | * This configuration creates the components needed for starting JSR-352 style jobs.
34 | *
35 | * @author Tobias Flohre
36 | */
37 | @Configuration
38 | public class Jsr352BatchConfiguration {
39 |
40 | @Autowired
41 | private JobExplorer jobExplorer;
42 |
43 | @Autowired
44 | private JobRepository jobRepository;
45 |
46 | @Autowired
47 | private DataSource dataSource;
48 |
49 | @Autowired
50 | private TaskExecutor taskExecutor;
51 |
52 | @Autowired
53 | private BatchWebAutoConfiguration batchWebAutoConfiguration;
54 |
55 | @Bean
56 | public CustomJsrJobOperator jsrJobOperator(PlatformTransactionManager transactionManager) throws Exception {
57 | CustomJsrJobOperator jsrJobOperator = new CustomJsrJobOperator(jobExplorer, jobRepository, jsrJobParametersConverter(),
58 | batchWebAutoConfiguration.addListenerToJobService(), transactionManager);
59 | jsrJobOperator.setTaskExecutor(taskExecutor);
60 | return jsrJobOperator;
61 | }
62 |
63 | public JsrJobParametersConverter jsrJobParametersConverter() throws Exception {
64 | JsrJobParametersConverter jsrJobParametersConverter = new JsrJobParametersConverter(dataSource);
65 | jsrJobParametersConverter.afterPropertiesSet();
66 | return jsrJobParametersConverter;
67 | }
68 |
69 | }
70 |
--------------------------------------------------------------------------------
/batch-web-spring-boot-autoconfigure/src/main/java/de/codecentric/batch/configuration/ListenerProvider.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package de.codecentric.batch.configuration;
17 |
18 | import java.util.Set;
19 |
20 | import org.springframework.batch.core.JobExecutionListener;
21 | import org.springframework.batch.core.StepExecutionListener;
22 |
23 | /**
24 | * spring-boot-starter-batch-web automatically registers JobExecutionListeners and StepExecutionListeners at each Job
25 | * provided by Spring beans implementing this interface.
26 | *
27 | * @author Tobias Flohre
28 | */
29 | public interface ListenerProvider {
30 |
31 | /**
32 | * Returns a set of JobExecutionListeners that will be added to each Job. May not return null.
33 | *
34 | * @return Returns a set of JobExecutionListeners that will be added to each Job. May not return null.
35 | */
36 | public Set jobExecutionListeners();
37 |
38 | /**
39 | * Returns a set of StepExecutionListeners that will be added to each Job. May not return null.
40 | *
41 | * @return Returns a set of StepExecutionListeners that will be added to each Job. May not return null.
42 | */
43 | public Set stepExecutionListeners();
44 |
45 | }
46 |
--------------------------------------------------------------------------------
/batch-web-spring-boot-autoconfigure/src/main/java/de/codecentric/batch/configuration/MetricsConfiguration.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package de.codecentric.batch.configuration;
17 |
18 | import java.util.HashSet;
19 | import java.util.Set;
20 |
21 | import org.springframework.batch.core.JobExecutionListener;
22 | import org.springframework.batch.core.StepExecutionListener;
23 | import org.springframework.beans.factory.annotation.Autowired;
24 | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
25 | import org.springframework.context.annotation.Bean;
26 | import org.springframework.context.annotation.Configuration;
27 |
28 | import de.codecentric.batch.metrics.BatchMetricsImpl;
29 | import de.codecentric.batch.metrics.MetricsListener;
30 | import de.codecentric.batch.metrics.ReaderProcessorWriterMetricsAspect;
31 | import io.micrometer.core.instrument.MeterRegistry;
32 |
33 | /**
34 | * Configuration containing all metrics stuff. Can be activated by setting the property batch.metrics.enabled to true.
35 | *
36 | * @author Tobias Flohre
37 | */
38 | @ConditionalOnProperty("batch.metrics.enabled")
39 | @Configuration
40 | public class MetricsConfiguration implements ListenerProvider {
41 |
42 | @Autowired
43 | private MeterRegistry meterRegistry;
44 |
45 | @Bean
46 | public BatchMetricsImpl batchMetrics() {
47 | return new BatchMetricsImpl();
48 | }
49 |
50 | @ConditionalOnProperty("batch.metrics.profiling.readprocesswrite.enabled")
51 | @Bean
52 | public ReaderProcessorWriterMetricsAspect batchMetricsAspects() {
53 | return new ReaderProcessorWriterMetricsAspect(meterRegistry);
54 | }
55 |
56 | @Bean
57 | public MetricsListener metricsListener() {
58 | return new MetricsListener(meterRegistry);
59 | }
60 |
61 | @Override
62 | public Set jobExecutionListeners() {
63 | Set listeners = new HashSet<>();
64 | listeners.add(metricsListener());
65 | return listeners;
66 | }
67 |
68 | @Override
69 | public Set stepExecutionListeners() {
70 | Set listeners = new HashSet<>();
71 | listeners.add(metricsListener());
72 | return listeners;
73 | }
74 |
75 | }
76 |
--------------------------------------------------------------------------------
/batch-web-spring-boot-autoconfigure/src/main/java/de/codecentric/batch/configuration/StepExecutionJacksonMixIn.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012-2014 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package de.codecentric.batch.configuration;
18 |
19 | import org.springframework.batch.core.JobExecution;
20 | import org.springframework.batch.core.StepExecution;
21 |
22 | import com.fasterxml.jackson.annotation.JsonIgnore;
23 |
24 | /**
25 | * Jackson MixIn for {@link StepExecution} serialization. This MixIn excludes the {@link JobExecution} from being
26 | * serialized. This is due to the fact that it would cause a {@link StackOverflowError} due to a circular reference.
27 | *
28 | * Taken from Spring XD.
29 | *
30 | * @author Gunnar Hillert
31 | */
32 | public abstract class StepExecutionJacksonMixIn {
33 |
34 | @JsonIgnore
35 | abstract JobExecution getJobExecution();
36 | }
37 |
--------------------------------------------------------------------------------
/batch-web-spring-boot-autoconfigure/src/main/java/de/codecentric/batch/configuration/TaskExecutorConfiguration.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package de.codecentric.batch.configuration;
17 |
18 | import org.springframework.beans.factory.annotation.Autowired;
19 | import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
20 | import org.springframework.context.annotation.Bean;
21 | import org.springframework.context.annotation.Configuration;
22 | import org.springframework.core.task.TaskExecutor;
23 | import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
24 |
25 | import de.codecentric.batch.scheduling.concurrent.MdcThreadPoolTaskExecutor;
26 |
27 | /**
28 | * This is the default configuration for a {@link org.springframework.core.task.TaskExecutor} used in the
29 | * {@link org.springframework.batch.core.launch.support.SimpleJobLauncher} for starting jobs asynchronously. Its core
30 | * thread pool is configured to five threads by default, which can be changed by setting the property
31 | * batch.core.pool.size to a different number.
32 | *
33 | * Please note the following rules of the ThreadPoolExecutor: If the number of threads is less than the corePoolSize,
34 | * the executor creates a new thread to run a new task. If the number of threads is equal (or greater than) the
35 | * corePoolSize, the executor puts the task into the queue. If the queue is full and the number of threads is less than
36 | * the maxPoolSize, the executor creates a new thread to run a new task. If the queue is full and the number of threads
37 | * is greater than or equal to maxPoolSize, reject the task.
38 | *
39 | * So with the default configuration there will be only 5 jobs/threads at the same time.
40 | *
41 | * The {@link org.springframework.core.task.TaskExecutor} may also be used in job configurations for multi-threaded job
42 | * execution. In XML you can use it by name, which is taskExecutor. In JavaConfig, you can either autowire
43 | * {@link org.springframework.core.task.TaskExecutor} or, if you want to know where it's configured, this class.
44 | *
45 | * @author Dennis Schulte
46 | *
47 | */
48 | @Configuration
49 | @ConditionalOnMissingBean(TaskExecutor.class)
50 | public class TaskExecutorConfiguration {
51 |
52 | @Autowired
53 | private BatchConfigurationProperties batchConfig;
54 |
55 | @Bean
56 | public TaskExecutor taskExecutor() {
57 | ThreadPoolTaskExecutor taskExecutor = new MdcThreadPoolTaskExecutor();
58 | taskExecutor.setCorePoolSize(batchConfig.getTaskExecutor().getCorePoolSize());
59 | taskExecutor.setQueueCapacity(batchConfig.getTaskExecutor().getQueueCapacity());
60 | taskExecutor.setMaxPoolSize(batchConfig.getTaskExecutor().getMaxPoolSize());
61 | taskExecutor.afterPropertiesSet();
62 | return taskExecutor;
63 | }
64 |
65 | }
66 |
--------------------------------------------------------------------------------
/batch-web-spring-boot-autoconfigure/src/main/java/de/codecentric/batch/configuration/WebConfig.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package de.codecentric.batch.configuration;
18 |
19 | import java.util.List;
20 |
21 | import de.codecentric.batch.monitoring.RunningExecutionTracker;
22 | import org.springframework.batch.core.StepExecution;
23 | import org.springframework.batch.core.configuration.JobRegistry;
24 | import org.springframework.batch.core.explore.JobExplorer;
25 | import org.springframework.batch.core.jsr.launch.JsrJobOperator;
26 | import org.springframework.batch.core.launch.JobLauncher;
27 | import org.springframework.batch.core.launch.JobOperator;
28 | import org.springframework.batch.core.repository.JobRepository;
29 | import org.springframework.beans.factory.annotation.Autowired;
30 | import org.springframework.context.annotation.Bean;
31 | import org.springframework.context.annotation.Configuration;
32 | import org.springframework.http.converter.HttpMessageConverter;
33 | import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
34 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
35 |
36 | import de.codecentric.batch.web.JobMonitoringController;
37 | import de.codecentric.batch.web.JobOperationsController;
38 |
39 | /**
40 | * This configuration adds the controllers for the two endpoints, and it adds a Jackson MixIn to the message converter
41 | * to avoid a stack overflow through circular references in the JobExecution / StepExecution.
42 | *
43 | * @author Tobias Flohre
44 | */
45 | @Configuration
46 | public class WebConfig implements WebMvcConfigurer {
47 |
48 | @Autowired
49 | private JobOperator jobOperator;
50 |
51 | @Autowired
52 | private JobExplorer jobExplorer;
53 |
54 | @Autowired
55 | private JobRegistry jobRegistry;
56 |
57 | @Autowired
58 | private JobRepository jobRepository;
59 |
60 | @Autowired
61 | private JobLauncher jobLauncher;
62 |
63 | @Autowired
64 | private RunningExecutionTracker runningExecutionTracker;
65 |
66 | @Autowired(required = false)
67 | private JsrJobOperator jsrJobOperator;
68 |
69 | @Override
70 | public void configureMessageConverters(List> converters) {
71 | for (HttpMessageConverter> httpMessageConverter : converters) {
72 | if (httpMessageConverter instanceof MappingJackson2HttpMessageConverter) {
73 | final MappingJackson2HttpMessageConverter converter = (MappingJackson2HttpMessageConverter) httpMessageConverter;
74 | converter.getObjectMapper().addMixIn(StepExecution.class, StepExecutionJacksonMixIn.class);
75 | }
76 | }
77 | }
78 |
79 | @Bean
80 | public JobMonitoringController jobMonitoringController() {
81 | return new JobMonitoringController(jobOperator, jobExplorer, runningExecutionTracker);
82 | }
83 |
84 | @Bean
85 | public JobOperationsController jobOperationsController() {
86 | return new JobOperationsController(jobOperator, jobExplorer, jobRegistry, jobRepository, jobLauncher, jsrJobOperator);
87 | }
88 |
89 | }
90 |
--------------------------------------------------------------------------------
/batch-web-spring-boot-autoconfigure/src/main/java/de/codecentric/batch/listener/JobLoggingApplicationListener.java:
--------------------------------------------------------------------------------
1 | package de.codecentric.batch.listener;
2 |
3 | import java.io.File;
4 |
5 | import org.apache.commons.lang3.StringUtils;
6 | import org.springframework.boot.context.event.ApplicationPreparedEvent;
7 | import org.springframework.context.ApplicationListener;
8 | import org.springframework.core.Ordered;
9 |
10 | /**
11 | * This ApplicationListener makes the batch.joblog.path available before the LoggingSystem is started.
12 | *
13 | * @author Johannes Stelzer
14 | */
15 | public class JobLoggingApplicationListener implements ApplicationListener, Ordered {
16 |
17 | @Override
18 | public void onApplicationEvent(ApplicationPreparedEvent event) {
19 | String jobLogPath = event.getApplicationContext().getEnvironment().getProperty("batch.joblog.path");
20 | if (!StringUtils.isEmpty(jobLogPath)) {
21 | if (!jobLogPath.endsWith(File.separator)) {
22 | jobLogPath = jobLogPath + File.separator;
23 | }
24 | System.setProperty("JOB_LOG_PATH", jobLogPath);
25 | }
26 | }
27 |
28 | @Override
29 | public int getOrder() {
30 | return Ordered.HIGHEST_PRECEDENCE + 11;
31 | }
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/batch-web-spring-boot-autoconfigure/src/main/java/de/codecentric/batch/listener/LoggingAfterJobListener.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package de.codecentric.batch.listener;
18 |
19 | import org.slf4j.MDC;
20 | import org.springframework.batch.core.JobExecution;
21 | import org.springframework.batch.core.JobExecutionListener;
22 | import org.springframework.beans.factory.annotation.Autowired;
23 | import org.springframework.core.Ordered;
24 |
25 | import de.codecentric.batch.logging.DefaultJobLogFileNameCreator;
26 | import de.codecentric.batch.logging.JobLogFileNameCreator;
27 |
28 | /**
29 | * This extra listener is needed, because the {@link LoggingListener} removes the variable from the MDC in its afterStep
30 | * method. We re-set it here at the beginning of the execution of all afterJob methods of JobExecutionListeners.
31 | *
32 | * @see LoggingListener
33 | *
34 | * @author Tobias Flohre
35 | *
36 | */
37 | public class LoggingAfterJobListener implements JobExecutionListener, Ordered {
38 |
39 | private JobLogFileNameCreator jobLogFileNameCreator = new DefaultJobLogFileNameCreator();
40 |
41 | @Override
42 | public void beforeJob(JobExecution jobExecution) {
43 | }
44 |
45 | private void insertValuesIntoMDC(JobExecution jobExecution) {
46 | MDC.put(LoggingListener.JOBLOG_FILENAME, jobLogFileNameCreator.getBaseName(jobExecution));
47 | }
48 |
49 | @Override
50 | public void afterJob(JobExecution jobExecution) {
51 | insertValuesIntoMDC(jobExecution);
52 | }
53 |
54 | @Override
55 | public int getOrder() {
56 | return Ordered.LOWEST_PRECEDENCE;
57 | }
58 |
59 | @Autowired(required = false)
60 | public void setJobLogFileNameCreator(JobLogFileNameCreator jobLogFileNameCreator) {
61 | this.jobLogFileNameCreator = jobLogFileNameCreator;
62 | }
63 |
64 | }
65 |
--------------------------------------------------------------------------------
/batch-web-spring-boot-autoconfigure/src/main/java/de/codecentric/batch/listener/LoggingListener.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package de.codecentric.batch.listener;
18 |
19 | import org.slf4j.MDC;
20 | import org.springframework.batch.core.ExitStatus;
21 | import org.springframework.batch.core.JobExecution;
22 | import org.springframework.batch.core.JobExecutionListener;
23 | import org.springframework.batch.core.StepExecution;
24 | import org.springframework.batch.core.StepExecutionListener;
25 | import org.springframework.beans.factory.annotation.Autowired;
26 | import org.springframework.core.Ordered;
27 |
28 | import de.codecentric.batch.logging.DefaultJobLogFileNameCreator;
29 | import de.codecentric.batch.logging.JobLogFileNameCreator;
30 |
31 | /**
32 | * This listener writes the job log file name to the MDC so that it can be picked up by the logging framework for
33 | * logging to it. It's a {@link JobExecutionListener} and a {@link StepExecutionListener} because in partitioning we may
34 | * have a lot of {@link StepExecution}s running in different threads. Due to the fact that the afterStep - method would
35 | * remove the variable from the MDC in single threaded execution we need to re-set it, that's what's the
36 | * {@link LoggingAfterJobListener} is for. Note that, of the three local parallelization features in Spring Batch, log
37 | * file separation only works for partitioning and parallel step, not for multi-threaded step.
38 | *
39 | * The log file name is determined by a {@link JobLogFileNameCreator}. It's default implementation
40 | * {@link DefaultJobLogFileNameCreator} is used when there's no other bean of this type in the ApplicationContext.
41 | *
42 | * @author Tobias Flohre
43 | *
44 | */
45 | public class LoggingListener implements JobExecutionListener, StepExecutionListener, Ordered {
46 |
47 | private JobLogFileNameCreator jobLogFileNameCreator = new DefaultJobLogFileNameCreator();
48 |
49 | public static final String JOBLOG_FILENAME = "jobLogFileName";
50 |
51 | @Override
52 | public void beforeJob(JobExecution jobExecution) {
53 | insertValuesIntoMDC(jobExecution);
54 | }
55 |
56 | private void insertValuesIntoMDC(JobExecution jobExecution) {
57 | MDC.put(JOBLOG_FILENAME, jobLogFileNameCreator.getBaseName(jobExecution));
58 | }
59 |
60 | @Override
61 | public void afterJob(JobExecution jobExecution) {
62 | removeValuesFromMDC();
63 | }
64 |
65 | private void removeValuesFromMDC() {
66 | MDC.remove(JOBLOG_FILENAME);
67 | }
68 |
69 | @Override
70 | public void beforeStep(StepExecution stepExecution) {
71 | insertValuesIntoMDC(stepExecution.getJobExecution());
72 | }
73 |
74 | @Override
75 | public ExitStatus afterStep(StepExecution stepExecution) {
76 | removeValuesFromMDC();
77 | return null;
78 | }
79 |
80 | @Override
81 | public int getOrder() {
82 | return Ordered.HIGHEST_PRECEDENCE;
83 | }
84 |
85 | @Autowired(required = false)
86 | public void setJobLogFileNameCreator(JobLogFileNameCreator jobLogFileNameCreator) {
87 | this.jobLogFileNameCreator = jobLogFileNameCreator;
88 | }
89 |
90 | }
91 |
--------------------------------------------------------------------------------
/batch-web-spring-boot-autoconfigure/src/main/java/de/codecentric/batch/listener/RunningExecutionTrackerListener.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package de.codecentric.batch.listener;
18 |
19 | import org.springframework.batch.core.JobExecution;
20 | import org.springframework.batch.core.JobExecutionListener;
21 |
22 | import de.codecentric.batch.monitoring.RunningExecutionTracker;
23 |
24 | /**
25 | * This listener is needed for tracking the running JobExecutions on this server.
26 | *
27 | *
28 | * It's easy to find out which jobs are running in general by looking into the database, but it has some drawbacks:
29 | *
30 | *
Data in the database might be corrupted. A job may be in status STARTED simply because someone killed the process
31 | * and Spring Batch didn't have the chance to update the status.
32 | *
We cannot tell from the database on which server the job is running.
33 | *
We might just use an in-memory database, then we cannot access it.
34 | *
35 | *
36 | *
37 | * This listener uses the {@link RunningExecutionTracker} to keep this information in memory and accessible for the http
38 | * endpoints.
39 | *
40 | * @author Tobias Flohre
41 | *
42 | */
43 | public class RunningExecutionTrackerListener implements JobExecutionListener {
44 |
45 | private RunningExecutionTracker runningExecutionTracker;
46 |
47 | public RunningExecutionTrackerListener(RunningExecutionTracker runningExecutionTracker) {
48 | super();
49 | this.runningExecutionTracker = runningExecutionTracker;
50 | }
51 |
52 | @Override
53 | public void beforeJob(JobExecution jobExecution) {
54 | runningExecutionTracker.addRunningExecution(jobExecution.getJobInstance().getJobName(), jobExecution.getId());
55 | }
56 |
57 | @Override
58 | public void afterJob(JobExecution jobExecution) {
59 | runningExecutionTracker.removeRunningExecution(jobExecution.getId());
60 | }
61 |
62 | }
63 |
--------------------------------------------------------------------------------
/batch-web-spring-boot-autoconfigure/src/main/java/de/codecentric/batch/logging/DefaultJobLogFileNameCreator.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package de.codecentric.batch.logging;
18 |
19 | import org.springframework.batch.core.JobExecution;
20 |
21 | /**
22 | * Default implementation used when there's no other Spring bean implementing {@link JobLogFileNameCreator} in the
23 | * ApplicationContext.
24 | *
25 | * @author Tobias Flohre
26 | * @author Dennis Schulte
27 | *
28 | */
29 | public class DefaultJobLogFileNameCreator implements JobLogFileNameCreator {
30 |
31 | private static final String DEFAULT_EXTENSION = ".log";
32 |
33 | @Override
34 | public String getName(JobExecution jobExecution) {
35 | return getBaseName(jobExecution) + getExtension();
36 | }
37 |
38 | @Override
39 | public String getBaseName(JobExecution jobExecution) {
40 | return "batch-" + jobExecution.getJobInstance().getJobName() + "-" + Long.toString(jobExecution.getId());
41 | }
42 |
43 | @Override
44 | public String getExtension() {
45 | return DEFAULT_EXTENSION;
46 | }
47 |
48 | }
49 |
--------------------------------------------------------------------------------
/batch-web-spring-boot-autoconfigure/src/main/java/de/codecentric/batch/logging/JobLogFileNameCreator.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package de.codecentric.batch.logging;
18 |
19 | import org.springframework.batch.core.JobExecution;
20 |
21 | /**
22 | * Components implementing this interface specify the name of the job run specific log file. Data from the JobExecution
23 | * may be used to compose the name. There are also methods to get the specific parts (basename and extension) of the
24 | * filename. Default implementation used when there's no other Spring bean implementing this interface is the
25 | * {@link DefaultJobLogFileNameCreator}.
26 | *
27 | * @author Tobias Flohre
28 | * @author Dennis Schulte
29 | *
30 | */
31 | public interface JobLogFileNameCreator {
32 |
33 | public String getName(JobExecution jobExecution);
34 |
35 | public String getBaseName(JobExecution jobExecution);
36 |
37 | public String getExtension();
38 |
39 | }
40 |
--------------------------------------------------------------------------------
/batch-web-spring-boot-autoconfigure/src/main/java/de/codecentric/batch/metrics/AbstractBatchMetricsAspect.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package de.codecentric.batch.metrics;
17 |
18 | import java.util.Arrays;
19 |
20 | import org.aspectj.lang.ProceedingJoinPoint;
21 | import org.springframework.batch.core.StepExecution;
22 | import org.springframework.batch.core.scope.context.StepContext;
23 | import org.springframework.batch.core.scope.context.StepSynchronizationManager;
24 | import org.springframework.util.ClassUtils;
25 |
26 | import io.micrometer.core.instrument.ImmutableTag;
27 | import io.micrometer.core.instrument.MeterRegistry;
28 | import io.micrometer.core.instrument.Timer;
29 |
30 | /**
31 | * This is a helper class for implementing method level profiling. See {@link ReaderProcessorWriterMetricsAspect} for an
32 | * aspect extending this class. All calls to an adviced method are tracked in a RichGauge, so you'll see average
33 | * duration time, maximum / minimum time, number of method calls and so on. For the name of the metric a special naming
34 | * scheme is used so that our {@link MetricsListener} picks up the gauge and writes it to the ExecutionContext of the
35 | * StepExecution and to the log.
36 | *
37 | * Job configurations need to enable auto-proxying so that aspects may be applied. In JavaConfig just add
38 | * {@code @EnableAspectJAutoProxy(proxyTargetClass=true)} as a class level annotation. In xml add
39 | * {@code } to the xml configuration file. This needs to be done
40 | * because jobs reside in child application contexts and don't inherit this kind of configuration from the parent.
41 | * proxyTargetClass=true means using CGLIB as proxy mechanism which allows us to proxy classes without interfaces.
42 | *
43 | * @author Tobias Flohre
44 | */
45 | public abstract class AbstractBatchMetricsAspect {
46 |
47 | private MeterRegistry meterRegistry;
48 |
49 | public AbstractBatchMetricsAspect(MeterRegistry meterRegistry) {
50 | this.meterRegistry = meterRegistry;
51 | }
52 |
53 | protected Object profileMethod(ProceedingJoinPoint pjp) throws Throwable {
54 | Timer.Sample sample = Timer.start(meterRegistry);
55 | try {
56 | return pjp.proceed();
57 | } finally {
58 | sample.stop(meterRegistry.timer(MetricsListener.METRIC_NAME, Arrays.asList(//
59 | new ImmutableTag("context", getStepIdentifier()), //
60 | new ImmutableTag("method", ClassUtils.getShortName(pjp.getTarget().getClass()) + "."
61 | + pjp.getSignature().getName()))));
62 | }
63 | }
64 |
65 | private String getStepIdentifier() {
66 | StepContext stepContext = StepSynchronizationManager.getContext();
67 | StepExecution stepExecution = StepSynchronizationManager.getContext().getStepExecution();
68 | return stepContext.getJobName() + "." + stepExecution.getStepName();
69 | }
70 |
71 | }
--------------------------------------------------------------------------------
/batch-web-spring-boot-autoconfigure/src/main/java/de/codecentric/batch/metrics/MetricsOutputFormatter.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package de.codecentric.batch.metrics;
17 |
18 | import java.util.Collection;
19 |
20 | import io.micrometer.core.instrument.Gauge;
21 | import io.micrometer.core.instrument.Timer;
22 |
23 | /**
24 | * Used in {@link MetricsListener} to define the format of the metrics log. A component implementing this interface may
25 | * be added to the ApplicationContext to override the default behaviour.
26 | *
27 | * @author Tobias Flohre
28 | */
29 | public interface MetricsOutputFormatter {
30 |
31 | public String format(Collection gauges, Collection timers);
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/batch-web-spring-boot-autoconfigure/src/main/java/de/codecentric/batch/metrics/ReaderProcessorWriterMetricsAspect.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package de.codecentric.batch.metrics;
17 |
18 | import org.aspectj.lang.ProceedingJoinPoint;
19 | import org.aspectj.lang.annotation.Around;
20 | import org.aspectj.lang.annotation.Aspect;
21 |
22 | import io.micrometer.core.instrument.MeterRegistry;
23 |
24 | /**
25 | * Central aspect-configuration to profile Spring Batch Jobs with AspectJ and Spring Boot Metrics.
26 | *
27 | * @author Dennis Schulte
28 | */
29 | @Aspect
30 | public class ReaderProcessorWriterMetricsAspect extends AbstractBatchMetricsAspect {
31 |
32 | public ReaderProcessorWriterMetricsAspect(MeterRegistry meterRegistry) {
33 | super(meterRegistry);
34 | }
35 |
36 | @Around("execution(* org.springframework.batch.item.ItemReader.read(..))")
37 | public Object profileReadMethods(ProceedingJoinPoint pjp) throws Throwable {
38 | return profileMethod(pjp);
39 | }
40 |
41 | @Around("execution(* org.springframework.batch.item.ItemProcessor.process(..))")
42 | public Object profileProcessMethods(ProceedingJoinPoint pjp) throws Throwable {
43 | return profileMethod(pjp);
44 | }
45 |
46 | @Around("execution(* org.springframework.batch.item.ItemWriter.write(..))")
47 | public Object profileWriteMethods(ProceedingJoinPoint pjp) throws Throwable {
48 | return profileMethod(pjp);
49 | }
50 |
51 | }
--------------------------------------------------------------------------------
/batch-web-spring-boot-autoconfigure/src/main/java/de/codecentric/batch/monitoring/RunningExecutionTracker.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package de.codecentric.batch.monitoring;
18 |
19 | import java.util.HashSet;
20 | import java.util.Map;
21 | import java.util.Map.Entry;
22 | import java.util.Set;
23 | import java.util.concurrent.ConcurrentHashMap;
24 |
25 | import de.codecentric.batch.listener.RunningExecutionTrackerListener;
26 | import de.codecentric.batch.web.JobMonitoringController;
27 |
28 | /**
29 | * Container for keeping track of running JobExecutions in this application.
30 | *
31 | * @see RunningExecutionTrackerListener
32 | * @see JobMonitoringController
33 | * @author Tobias Flohre
34 | *
35 | */
36 | public class RunningExecutionTracker {
37 |
38 | private Map runningExecutions = new ConcurrentHashMap<>();
39 |
40 | public void addRunningExecution(String jobName, Long executionId) {
41 | runningExecutions.put(executionId, jobName);
42 | }
43 |
44 | public void removeRunningExecution(Long executionId) {
45 | runningExecutions.remove(executionId);
46 | }
47 |
48 | public Set getAllRunningExecutionIds() {
49 | return new HashSet<>(runningExecutions.keySet());
50 | }
51 |
52 | public Set getRunningExecutionIdsForJobName(String jobName) {
53 | Set runningExecutionIds = new HashSet<>();
54 | for (Entry entry : runningExecutions.entrySet()) {
55 | if (entry.getValue().equals(jobName)) {
56 | runningExecutionIds.add(entry.getKey());
57 | }
58 | }
59 | return runningExecutionIds;
60 | }
61 |
62 | }
63 |
--------------------------------------------------------------------------------
/batch-web-spring-boot-autoconfigure/src/main/java/de/codecentric/batch/scheduling/concurrent/MdcThreadPoolTaskExecutor.java:
--------------------------------------------------------------------------------
1 | package de.codecentric.batch.scheduling.concurrent;
2 |
3 | import java.util.Map;
4 | import java.util.concurrent.ThreadPoolExecutor;
5 |
6 | import org.slf4j.MDC;
7 | import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
8 |
9 | /**
10 | * A SLF4J MDC-compatible {@link ThreadPoolExecutor}.
11 | *
12 | * In general, MDC is used to store diagnostic information (e.g. logfile name) in per-thread variables, to facilitate
13 | * logging. However, although MDC data is passed to thread children, this doesn't work when threads are reused in a
14 | * thread pool. This is a drop-in replacement for {@link ThreadPoolTaskExecutor} sets MDC data before each task
15 | * appropriately.
16 | *
17 | *
18 | * @author Dennis Schulte
19 | */
20 | public class MdcThreadPoolTaskExecutor extends ThreadPoolTaskExecutor {
21 |
22 | private static final long serialVersionUID = 1L;
23 |
24 | private boolean useFixedContext = false;
25 |
26 | private Map fixedContext;
27 |
28 | public MdcThreadPoolTaskExecutor() {
29 | super();
30 | }
31 |
32 | public MdcThreadPoolTaskExecutor(Map fixedContext) {
33 | super();
34 | this.fixedContext = fixedContext;
35 | useFixedContext = (fixedContext != null);
36 | }
37 |
38 | private Map getContextForTask() {
39 | return useFixedContext ? fixedContext : MDC.getCopyOfContextMap();
40 | }
41 |
42 | /**
43 | * All executions will have MDC injected. {@code ThreadPoolExecutor}'s submission methods ({@code submit()} etc.)
44 | * all delegate to this.
45 | */
46 | @Override
47 | public void execute(Runnable command) {
48 | super.execute(wrap(command, getContextForTask()));
49 | }
50 |
51 | public static Runnable wrap(final Runnable runnable, final Map context) {
52 | return () -> {
53 | Map previous = MDC.getCopyOfContextMap();
54 | if (context == null) {
55 | MDC.clear();
56 | } else {
57 | MDC.setContextMap(context);
58 | }
59 | try {
60 | runnable.run();
61 | } finally {
62 | if (previous == null) {
63 | MDC.clear();
64 | } else {
65 | MDC.setContextMap(previous);
66 | }
67 | }
68 | };
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/batch-web-spring-boot-autoconfigure/src/main/resources/META-INF/additional-spring-configuration-metadata.json:
--------------------------------------------------------------------------------
1 | {
2 | "properties": [
3 | {
4 | "name": "batch.metrics.enabled",
5 | "type": "java.lang.Boolean",
6 | "description": "Whether the transaction safe batch metrics framework is activated so that BatchMetrics may be injected and used",
7 | "default": false
8 | },
9 | {
10 | "name": "batch.web.operations.base",
11 | "type": "java.lang.String",
12 | "description": "URL part to operational methods on batch jobs, like starting, stopping, etc. of jobs",
13 | "default": "/batch/operations"
14 | },
15 | {
16 | "name": "batch.web.monitoring.base",
17 | "type": "java.lang.String",
18 | "description": "URL part to monitoring methods on batch jobs, like viewing the state of jobs",
19 | "default": "/batch/monitoring"
20 | },
21 | {
22 | "name": "batch.metrics.profiling.readprocesswrite.enabled",
23 | "type": "java.lang.Boolean",
24 | "description": "Readers, Processors and Writers are profiled with RichGauges when set to true",
25 | "default": false
26 | }
27 | ]
28 | }
--------------------------------------------------------------------------------
/batch-web-spring-boot-autoconfigure/src/main/resources/META-INF/spring.factories:
--------------------------------------------------------------------------------
1 | # AutoConfigurations
2 | org.springframework.boot.autoconfigure.EnableAutoConfiguration=de.codecentric.batch.configuration.BatchWebAutoConfiguration
3 |
4 | # Application Listeners
5 | org.springframework.context.ApplicationListener=de.codecentric.batch.listener.JobLoggingApplicationListener
--------------------------------------------------------------------------------
/batch-web-spring-boot-autoconfigure/src/main/resources/batch-web-spring-boot-autoconfigure.properties:
--------------------------------------------------------------------------------
1 | spring.batch.job.enabled=false
2 |
--------------------------------------------------------------------------------
/batch-web-spring-boot-autoconfigure/src/main/resources/logback-batch-base.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | jobLogFileName
10 | batch-default
11 |
12 |
13 |
14 | ${JOB_LOG_PATH}${jobLogFileName}.log
15 | true
16 |
17 | ${FILE_LOG_PATTERN}
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/batch-web-spring-boot-autoconfigure/src/test/java/de/codecentric/batch/AutoconfigureBatchWebStarter.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package de.codecentric.batch;
18 |
19 | import java.lang.annotation.Documented;
20 | import java.lang.annotation.ElementType;
21 | import java.lang.annotation.Inherited;
22 | import java.lang.annotation.Retention;
23 | import java.lang.annotation.RetentionPolicy;
24 | import java.lang.annotation.Target;
25 |
26 | import org.springframework.boot.actuate.autoconfigure.metrics.MetricsAutoConfiguration;
27 | import org.springframework.boot.actuate.autoconfigure.metrics.export.simple.SimpleMetricsExportAutoConfiguration;
28 | import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
29 | import org.springframework.boot.autoconfigure.aop.AopAutoConfiguration;
30 | import org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration;
31 | import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
32 | import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
33 | import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
34 |
35 | import de.codecentric.batch.configuration.BatchWebAutoConfiguration;
36 |
37 | /**
38 | *
39 | * {@link AutoImportConfoguration} for typical BatchWebStarter tests. Restricts the loaded Autoconfiguration to the
40 | * BatchWebStarter parts and respects the correct ordering.
41 | *
42 | * @author Johannes Edmeier
43 | */
44 | @Target(ElementType.TYPE)
45 | @Retention(RetentionPolicy.RUNTIME)
46 | @Documented
47 | @Inherited
48 | @ImportAutoConfiguration({ BatchWebAutoConfiguration.class, DataSourceAutoConfiguration.class,
49 | HibernateJpaAutoConfiguration.class,
50 | // since the BatchAutoConfiguration is ordered after HibernateJpaAutoConfiguration we need to
51 | // include it otherwise it will be executed before DataSourceAutoConfiguration
52 | BatchAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class, MetricsAutoConfiguration.class,
53 | AopAutoConfiguration.class, SimpleMetricsExportAutoConfiguration.class })
54 | public @interface AutoconfigureBatchWebStarter {
55 | }
56 |
--------------------------------------------------------------------------------
/batch-web-spring-boot-autoconfigure/src/test/java/de/codecentric/batch/MetricsTestApplication.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package de.codecentric.batch;
17 |
18 | import java.util.Collection;
19 |
20 | import org.springframework.beans.factory.annotation.Autowired;
21 | import org.springframework.boot.SpringApplication;
22 | import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
23 | import org.springframework.context.annotation.Bean;
24 | import org.springframework.context.annotation.Configuration;
25 | import org.springframework.context.annotation.Import;
26 |
27 | import de.codecentric.batch.metrics.ListenerMetricsAspect;
28 | import de.codecentric.batch.metrics.MetricsOutputFormatter;
29 | import io.micrometer.core.instrument.Gauge;
30 | import io.micrometer.core.instrument.MeterRegistry;
31 | import io.micrometer.core.instrument.Timer;
32 |
33 | /**
34 | * Application for integration testing.
35 | *
36 | * @author Tobias Flohre
37 | */
38 | @Configuration
39 | @EnableAutoConfiguration
40 | @Import(TestListenerConfiguration.class)
41 | public class MetricsTestApplication {
42 |
43 | public static void main(String[] args) {
44 | SpringApplication.run(MetricsTestApplication.class, args);
45 | }
46 |
47 | @Autowired
48 | private MeterRegistry meterRegistry;
49 |
50 | @Bean
51 | public ListenerMetricsAspect listenerMetricsAspect() {
52 | return new ListenerMetricsAspect(meterRegistry);
53 | }
54 |
55 | @Bean
56 | public MetricsOutputFormatter metricsOutputFormatter() {
57 | return new MetricsOutputFormatter() {
58 |
59 | @Override
60 | public String format(Collection gauges, Collection timers) {
61 | StringBuilder builder = new StringBuilder(
62 | "\n########## Personal Header for metrics! #####\n########## Metrics Start ##########\n");
63 | gauges.stream().forEach(gauge -> {
64 | builder.append("Gauge [" + gauge.getId() + "]: ");
65 | builder.append(gauge.value() + "\n");
66 | });
67 | timers.stream().forEach(timer -> {
68 | builder.append("Timer [" + timer.getId() + "]: ");
69 | builder.append(
70 | "totalTime=" + timer.totalTime(timer.baseTimeUnit()) + " " + timer.baseTimeUnit() + "\n");
71 | });
72 | builder.append("########## Metrics End ############");
73 | return builder.toString();
74 | }
75 |
76 | };
77 | }
78 |
79 | }
80 |
--------------------------------------------------------------------------------
/batch-web-spring-boot-autoconfigure/src/test/java/de/codecentric/batch/TestApplication.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package de.codecentric.batch;
17 |
18 | import org.springframework.boot.SpringApplication;
19 | import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
20 | import org.springframework.context.annotation.Configuration;
21 | import org.springframework.context.annotation.Import;
22 |
23 | /**
24 | * Application for integration testing.
25 | *
26 | * @author Tobias Flohre
27 | */
28 | @Configuration
29 | @EnableAutoConfiguration
30 | @Import(TestListenerConfiguration.class)
31 | public class TestApplication {
32 |
33 | public static void main(String[] args) {
34 | SpringApplication.run(TestApplication.class, args);
35 | }
36 |
37 | }
38 |
--------------------------------------------------------------------------------
/batch-web-spring-boot-autoconfigure/src/test/java/de/codecentric/batch/TestConfiguration.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package de.codecentric.batch;
18 |
19 | import org.springframework.context.annotation.Configuration;
20 |
21 | @Configuration
22 | public class TestConfiguration {
23 | }
24 |
--------------------------------------------------------------------------------
/batch-web-spring-boot-autoconfigure/src/test/java/de/codecentric/batch/TestListenerConfiguration.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package de.codecentric.batch;
17 |
18 | import java.util.HashSet;
19 | import java.util.Set;
20 |
21 | import org.springframework.batch.core.JobExecutionListener;
22 | import org.springframework.batch.core.StepExecutionListener;
23 | import org.springframework.context.annotation.Bean;
24 | import org.springframework.context.annotation.Configuration;
25 |
26 | import de.codecentric.batch.configuration.ListenerProvider;
27 | import de.codecentric.batch.listener.TestListener;
28 |
29 | /**
30 | * @author Tobias Flohre
31 | */
32 | @Configuration
33 | public class TestListenerConfiguration implements ListenerProvider {
34 |
35 | /*
36 | * (non-Javadoc)
37 | *
38 | * @see de.codecentric.batch.configuration.ListenerProvider#jobExecutionListeners()
39 | */
40 | @Override
41 | public Set jobExecutionListeners() {
42 | Set listeners = new HashSet();
43 | listeners.add(testListener());
44 | return listeners;
45 | }
46 |
47 | /*
48 | * (non-Javadoc)
49 | *
50 | * @see de.codecentric.batch.configuration.ListenerProvider#stepExecutionListeners()
51 | */
52 | @Override
53 | public Set stepExecutionListeners() {
54 | return new HashSet();
55 | }
56 |
57 | @Bean
58 | public TestListener testListener() {
59 | return new TestListener();
60 | }
61 |
62 | }
63 |
--------------------------------------------------------------------------------
/batch-web-spring-boot-autoconfigure/src/test/java/de/codecentric/batch/item/DelayItemProcessor.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package de.codecentric.batch.item;
17 |
18 | import org.slf4j.Logger;
19 | import org.slf4j.LoggerFactory;
20 | import org.springframework.batch.item.ItemProcessor;
21 |
22 | /**
23 | * Dummy {@link ItemProcessor} which waits some time before proceeding.
24 | *
25 | * @author Tobias Flohre
26 | */
27 | public class DelayItemProcessor implements ItemProcessor {
28 |
29 | private static final Logger LOGGER = LoggerFactory.getLogger(DelayItemProcessor.class);
30 |
31 | @Override
32 | public String process(String item) throws Exception {
33 | LOGGER.info(item);
34 | Thread.sleep(1000);
35 | return item;
36 | }
37 |
38 | }
39 |
--------------------------------------------------------------------------------
/batch-web-spring-boot-autoconfigure/src/test/java/de/codecentric/batch/item/DummyItemReader.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package de.codecentric.batch.item;
17 |
18 | import org.slf4j.Logger;
19 | import org.slf4j.LoggerFactory;
20 | import org.springframework.batch.item.ItemReader;
21 |
22 | /**
23 | * {@link ItemReader} with hard-coded input data.
24 | */
25 | public class DummyItemReader implements ItemReader {
26 |
27 | private static final Logger LOGGER = LoggerFactory.getLogger(DummyItemReader.class);
28 |
29 | private String[] input = { "Good", "morning!", "This", "is", "your", "ItemReader", "speaking!" };
30 |
31 | private int index = 0;
32 |
33 | /**
34 | * Reads next record from input
35 | */
36 | @Override
37 | public String read() throws Exception {
38 | String item = null;
39 | if (index < input.length) {
40 | item = input[index++];
41 | LOGGER.info(item);
42 | return item;
43 | } else {
44 | return null;
45 | }
46 |
47 | }
48 |
49 | }
50 |
--------------------------------------------------------------------------------
/batch-web-spring-boot-autoconfigure/src/test/java/de/codecentric/batch/item/LogItemProcessor.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package de.codecentric.batch.item;
17 |
18 | import org.slf4j.Logger;
19 | import org.slf4j.LoggerFactory;
20 | import org.springframework.batch.item.ItemProcessor;
21 |
22 | /**
23 | * Dummy {@link ItemProcessor} which only logs data it receives.
24 | */
25 | public class LogItemProcessor implements ItemProcessor {
26 |
27 | private static final Logger LOGGER = LoggerFactory.getLogger(LogItemProcessor.class);
28 |
29 | @Override
30 | public String process(String item) throws Exception {
31 | LOGGER.info(item);
32 | return item;
33 | }
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/batch-web-spring-boot-autoconfigure/src/test/java/de/codecentric/batch/item/LogItemWriteListener.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package de.codecentric.batch.item;
17 |
18 | import java.util.List;
19 |
20 | import org.slf4j.Logger;
21 | import org.slf4j.LoggerFactory;
22 | import org.springframework.batch.core.ItemWriteListener;
23 |
24 | /**
25 | * @author Tobias Flohre
26 | */
27 | public class LogItemWriteListener implements ItemWriteListener {
28 |
29 | private static final Logger LOGGER = LoggerFactory.getLogger(LogItemWriteListener.class);
30 |
31 | @Override
32 | public void beforeWrite(List extends String> items) {
33 | for (String item : items) {
34 | LOGGER.debug("Item: {}", item);
35 | }
36 | }
37 |
38 | @Override
39 | public void afterWrite(List extends String> items) {
40 | for (String item : items) {
41 | LOGGER.debug("Item: {}", item);
42 | }
43 | }
44 |
45 | @Override
46 | public void onWriteError(Exception exception, List extends String> items) {
47 | for (String item : items) {
48 | LOGGER.debug("Item: {}", item);
49 | }
50 | }
51 |
52 | }
53 |
--------------------------------------------------------------------------------
/batch-web-spring-boot-autoconfigure/src/test/java/de/codecentric/batch/item/LogItemWriter.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package de.codecentric.batch.item;
17 |
18 | import java.util.List;
19 |
20 | import org.slf4j.Logger;
21 | import org.slf4j.LoggerFactory;
22 | import org.springframework.batch.item.ItemWriter;
23 |
24 | /**
25 | * Dummy {@link ItemWriter} which only logs data it receives.
26 | */
27 | public class LogItemWriter implements ItemWriter