diff --git a/.github/workflows/artifactory-milestone-release.yml b/.github/workflows/artifactory-milestone-release.yml
deleted file mode 100644
index 4c368a39a4..0000000000
--- a/.github/workflows/artifactory-milestone-release.yml
+++ /dev/null
@@ -1,38 +0,0 @@
-name: Artifactory Milestone Release
-
-on:
- workflow_dispatch:
- inputs:
- releaseVersion:
- description: "Milestone release version"
- required: true
-
-jobs:
- build:
- name: Release milestone to Artifactory
- runs-on: ubuntu-latest
- steps:
- - name: Checkout source code
- uses: actions/checkout@v3
-
- - name: Set up JDK 17
- uses: actions/setup-java@v3
- with:
- java-version: '17'
- distribution: 'temurin'
- cache: 'maven'
-
- - name: Capture release version
- run: echo RELEASE_VERSION=${{ github.event.inputs.releaseVersion }} >> $GITHUB_ENV
-
- - name: Update release version
- run: mvn versions:set -DgenerateBackupPoms=false -DnewVersion=$RELEASE_VERSION
-
- - name: Enforce release rules
- run: mvn org.apache.maven.plugins:maven-enforcer-plugin:enforce -Drules=requireReleaseDeps
-
- - name: Build with Maven and deploy to Artifactory's milestone repository
- env:
- ARTIFACTORY_USERNAME: ${{ secrets.ARTIFACTORY_USERNAME }}
- ARTIFACTORY_PASSWORD: ${{ secrets.ARTIFACTORY_PASSWORD }}
- run: mvn -P artifactory-milestone -s settings.xml --batch-mode -Dmaven.test.skip=true deploy
diff --git a/.github/workflows/artifactory-staging.yml b/.github/workflows/artifactory-staging.yml
index ae8a04859c..00d80b927d 100644
--- a/.github/workflows/artifactory-staging.yml
+++ b/.github/workflows/artifactory-staging.yml
@@ -4,7 +4,7 @@ on:
workflow_dispatch:
inputs:
releaseVersion:
- description: "Release version"
+ description: "Release version (5.0.x)"
required: true
jobs:
@@ -14,6 +14,8 @@ jobs:
steps:
- name: Checkout source code
uses: actions/checkout@v3
+ with:
+ ref: '5.0.x'
- name: Set up JDK 17
uses: actions/setup-java@v3
diff --git a/.github/workflows/continuous-inspection.yml b/.github/workflows/continuous-inspection.yml
deleted file mode 100644
index f496eba5c9..0000000000
--- a/.github/workflows/continuous-inspection.yml
+++ /dev/null
@@ -1,32 +0,0 @@
-name: Continuous inspection build
-
-on:
- schedule:
- - cron: '0 10 * * *' # Once per day at 10am UTC
- workflow_dispatch:
-
-jobs:
- code-quality-analysis:
- name: code quality analysis report
- runs-on: ubuntu-latest
- steps:
- - name: Checkout source code
- uses: actions/checkout@v3
-
- - name: Set up JDK 17
- uses: actions/setup-java@v3
- with:
- java-version: '17'
- distribution: 'temurin'
- cache: 'maven'
-
- - name: Analyse test coverage with Jacoco
- run: mvn -P test-coverage verify
-
- - name: Analyse code quality with Sonar
- if: github.repository == 'spring-projects/spring-batch'
- env:
- SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
- SONAR_HOST_URL: ${{ secrets.SONAR_URL }}
- run: mvn sonar:sonar -Dsonar.host.url=$SONAR_HOST_URL -Dsonar.login=$SONAR_TOKEN
-
diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration-50x.yml
similarity index 78%
rename from .github/workflows/continuous-integration.yml
rename to .github/workflows/continuous-integration-50x.yml
index 08e9d43564..9744e02581 100644
--- a/.github/workflows/continuous-integration.yml
+++ b/.github/workflows/continuous-integration-50x.yml
@@ -1,16 +1,18 @@
-name: CI/CD build
+name: CI/CD build for 5.0.x
on:
push:
- branches: [ "main" ]
+ branches: [ "5.0.x" ]
jobs:
build:
- name: Build Main branch
+ name: Build 5.0.x branch
runs-on: ubuntu-latest
steps:
- name: Checkout source code
uses: actions/checkout@v3
+ with:
+ ref: '5.0.x'
- name: Set up JDK 17
uses: actions/setup-java@v3
@@ -50,8 +52,10 @@ jobs:
DOCS_HOST: ${{ secrets.DOCS_HOST }}
DOCS_PATH: ${{ secrets.DOCS_PATH }}
DOCS_USERNAME: ${{ secrets.DOCS_USERNAME }}
- working-directory: spring-batch-docs
+ working-directory: spring-batch-docs/target
run: |
- cd target && unzip spring-batch-$PROJECT_VERSION-docs.zip
+ unzip spring-batch-$PROJECT_VERSION-docs.zip
+ ssh -i $HOME/.ssh/key $DOCS_USERNAME@$DOCS_HOST "cd $DOCS_PATH && mkdir -p $PROJECT_VERSION"
scp -i $HOME/.ssh/key -r api $DOCS_USERNAME@$DOCS_HOST:$DOCS_PATH/$PROJECT_VERSION
scp -i $HOME/.ssh/key -r reference $DOCS_USERNAME@$DOCS_HOST:$DOCS_PATH/$PROJECT_VERSION
+ ssh -i $HOME/.ssh/key $DOCS_USERNAME@$DOCS_HOST "cd $DOCS_PATH && rm 5.0.x-SNAPSHOT && ln -s $PROJECT_VERSION 5.0.x-SNAPSHOT"
diff --git a/.github/workflows/documentation-upload.yml b/.github/workflows/documentation-upload.yml
index ecbbb01246..9ec72c93ed 100644
--- a/.github/workflows/documentation-upload.yml
+++ b/.github/workflows/documentation-upload.yml
@@ -4,7 +4,7 @@ on:
workflow_dispatch:
inputs:
releaseVersion:
- description: "Release version"
+ description: "Release version (5.0.x)"
required: true
jobs:
@@ -17,6 +17,8 @@ jobs:
- name: Checkout source code
uses: actions/checkout@v3
+ with:
+ ref: '5.0.x'
- name: Set up JDK 17
uses: actions/setup-java@v3
@@ -25,6 +27,9 @@ jobs:
distribution: 'temurin'
cache: 'maven'
+ - name: Update release version
+ run: mvn versions:set -DgenerateBackupPoms=false -DnewVersion=$RELEASE_VERSION
+
- name: Generate Java docs
run: mvn javadoc:aggregate
@@ -52,9 +57,10 @@ jobs:
working-directory: spring-batch-docs/target
run: |
unzip spring-batch-$RELEASE_VERSION-docs.zip
- ssh -i $HOME/.ssh/key $DOCS_USERNAME@$DOCS_HOST cd $DOCS_PATH && mkdir $RELEASE_VERSION
- scp -i $HOME/.ssh/key -r api reference $DOCS_USERNAME@$DOCS_HOST:$DOCS_PATH/$RELEASE_VERSION
- ssh -i $HOME/.ssh/key $DOCS_USERNAME@$DOCS_HOST rm current && ln -s $RELEASE_VERSION current
+ ssh -i $HOME/.ssh/key $DOCS_USERNAME@$DOCS_HOST "cd $DOCS_PATH && mkdir -p $RELEASE_VERSION"
+ scp -i $HOME/.ssh/key -r api $DOCS_USERNAME@$DOCS_HOST:$DOCS_PATH/$RELEASE_VERSION
+ scp -i $HOME/.ssh/key -r reference $DOCS_USERNAME@$DOCS_HOST:$DOCS_PATH/$RELEASE_VERSION
+ ssh -i $HOME/.ssh/key $DOCS_USERNAME@$DOCS_HOST "cd $DOCS_PATH && rm 5.0.x && ln -s $RELEASE_VERSION 5.0.x"
unzip spring-batch-$RELEASE_VERSION-schemas.zip
scp -i $HOME/.ssh/key batch/*.xsd $DOCS_USERNAME@$DOCS_HOST:$BATCH_SCHEMA_PATH
diff --git a/.github/workflows/maven-central-release.yml b/.github/workflows/maven-central-release.yml
deleted file mode 100644
index 6d3905dea2..0000000000
--- a/.github/workflows/maven-central-release.yml
+++ /dev/null
@@ -1,81 +0,0 @@
-name: Maven Central Release
-
-on:
- workflow_dispatch:
- inputs:
- releaseVersion:
- description: "Release version"
- required: true
-
-jobs:
- build:
- runs-on: ubuntu-latest
- steps:
-
- - name: Capture release version
- run: echo RELEASE_VERSION=${{ github.event.inputs.releaseVersion }} >> $GITHUB_ENV
-
- - name: Prepare directory structure
- run: |
- mkdir -p nexus/org/springframework/batch/spring-batch-bom/$RELEASE_VERSION
- mkdir -p nexus/org/springframework/batch/spring-batch-infrastructure/$RELEASE_VERSION
- mkdir -p nexus/org/springframework/batch/spring-batch-core/$RELEASE_VERSION
- mkdir -p nexus/org/springframework/batch/spring-batch-test/$RELEASE_VERSION
- mkdir -p nexus/org/springframework/batch/spring-batch-integration/$RELEASE_VERSION
-
- - name: Download release files from Artifactory
- env:
- ARTIFACTORY_URL: "https://repo.spring.io/libs-staging-local/org/springframework/batch"
- run: |
- echo "Downloading BOM artifacts"
- cd nexus/org/springframework/batch/spring-batch-bom/$RELEASE_VERSION
- wget $ARTIFACTORY_URL/spring-batch-bom/$RELEASE_VERSION/spring-batch-bom-$RELEASE_VERSION.pom
-
- echo "Downloading infrastructure artifacts"
- cd ../../../../../..
- cd nexus/org/springframework/batch/spring-batch-infrastructure/$RELEASE_VERSION
- wget $ARTIFACTORY_URL/spring-batch-infrastructure/$RELEASE_VERSION/spring-batch-infrastructure-$RELEASE_VERSION.pom
- wget $ARTIFACTORY_URL/spring-batch-infrastructure/$RELEASE_VERSION/spring-batch-infrastructure-$RELEASE_VERSION.jar
- wget $ARTIFACTORY_URL/spring-batch-infrastructure/$RELEASE_VERSION/spring-batch-infrastructure-$RELEASE_VERSION-javadoc.jar
- wget $ARTIFACTORY_URL/spring-batch-infrastructure/$RELEASE_VERSION/spring-batch-infrastructure-$RELEASE_VERSION-sources.jar
-
- echo "Downloading core artifacts"
- cd ../../../../../..
- cd nexus/org/springframework/batch/spring-batch-core/$RELEASE_VERSION
- wget $ARTIFACTORY_URL/spring-batch-core/$RELEASE_VERSION/spring-batch-core-$RELEASE_VERSION.pom
- wget $ARTIFACTORY_URL/spring-batch-core/$RELEASE_VERSION/spring-batch-core-$RELEASE_VERSION.jar
- wget $ARTIFACTORY_URL/spring-batch-core/$RELEASE_VERSION/spring-batch-core-$RELEASE_VERSION-javadoc.jar
- wget $ARTIFACTORY_URL/spring-batch-core/$RELEASE_VERSION/spring-batch-core-$RELEASE_VERSION-sources.jar
-
- echo "Downloading test artifacts"
- cd ../../../../../..
- cd nexus/org/springframework/batch/spring-batch-test/$RELEASE_VERSION
- wget $ARTIFACTORY_URL/spring-batch-test/$RELEASE_VERSION/spring-batch-test-$RELEASE_VERSION.pom
- wget $ARTIFACTORY_URL/spring-batch-test/$RELEASE_VERSION/spring-batch-test-$RELEASE_VERSION.jar
- wget $ARTIFACTORY_URL/spring-batch-test/$RELEASE_VERSION/spring-batch-test-$RELEASE_VERSION-javadoc.jar
- wget $ARTIFACTORY_URL/spring-batch-test/$RELEASE_VERSION/spring-batch-test-$RELEASE_VERSION-sources.jar
-
- echo "Downloading integration artifacts"
- cd ../../../../../..
- cd nexus/org/springframework/batch/spring-batch-integration/$RELEASE_VERSION
- wget $ARTIFACTORY_URL/spring-batch-integration/$RELEASE_VERSION/spring-batch-integration-$RELEASE_VERSION.pom
- wget $ARTIFACTORY_URL/spring-batch-integration/$RELEASE_VERSION/spring-batch-integration-$RELEASE_VERSION.jar
- wget $ARTIFACTORY_URL/spring-batch-integration/$RELEASE_VERSION/spring-batch-integration-$RELEASE_VERSION-javadoc.jar
- wget $ARTIFACTORY_URL/spring-batch-integration/$RELEASE_VERSION/spring-batch-integration-$RELEASE_VERSION-sources.jar
-
- - name: Sign artifacts and release them to Maven Central
- uses: jvalkeal/nexus-sync@v0
- id: nexus
- with:
- url: ${{ secrets.OSSRH_URL }}
- username: ${{ secrets.OSSRH_S01_TOKEN_USERNAME }}
- password: ${{ secrets.OSSRH_S01_TOKEN_PASSWORD }}
- staging-profile-name: ${{ secrets.OSSRH_STAGING_PROFILE_NAME }}
- create: true
- upload: true
- close: true
- release: true
- generate-checksums: true
- pgp-sign: true
- pgp-sign-passphrase: ${{ secrets.GPG_PASSPHRASE }}
- pgp-sign-private-key: ${{ secrets.GPG_PRIVATE_KEY }}
diff --git a/.github/workflows/maven-central-stage.yml b/.github/workflows/maven-central-stage.yml
deleted file mode 100644
index e01f26c54d..0000000000
--- a/.github/workflows/maven-central-stage.yml
+++ /dev/null
@@ -1,58 +0,0 @@
-name: Maven Central Staging
-
-on:
- workflow_dispatch:
- inputs:
- buildName:
- description: "Artifactory build name"
- required: true
- buildNumber:
- description: "Artifactory build number"
- required: true
-
-jobs:
- build:
- runs-on: ubuntu-latest
- steps:
-
- # to get spec file in .github
- - uses: actions/checkout@v2
-
- # Setup jfrog cli
- - uses: jfrog/setup-jfrog-cli@v1
- with:
- version: 1.43.2
- env:
- JF_ARTIFACTORY_SPRING: ${{ secrets.JF_ARTIFACTORY_SPRING }}
-
- # Extract build id from input
- - name: Extract Build Id
- run: |
- echo JFROG_CLI_BUILD_NAME=${{ github.event.inputs.buildName }} >> $GITHUB_ENV
- echo JFROG_CLI_BUILD_NUMBER=${{ github.event.inputs.buildNumber }} >> $GITHUB_ENV
-
- # Download released files
- - name: Download Release Files
- run: |
- jfrog rt download \
- --spec .github/release-files-spec.json \
- --spec-vars "buildname=$JFROG_CLI_BUILD_NAME;buildnumber=$JFROG_CLI_BUILD_NUMBER"
-
- # Create checksums, signatures and create staging repo on central and upload
- - uses: jvalkeal/nexus-sync@v0
- id: nexus
- with:
- url: ${{ secrets.OSSRH_URL }}
- username: ${{ secrets.OSSRH_S01_TOKEN_USERNAME }}
- password: ${{ secrets.OSSRH_S01_TOKEN_PASSWORD }}
- staging-profile-name: ${{ secrets.OSSRH_STAGING_PROFILE_NAME }}
- create: true
- upload: true
- generate-checksums: true
- pgp-sign: true
- pgp-sign-passphrase: ${{ secrets.GPG_PASSPHRASE }}
- pgp-sign-private-key: ${{ secrets.GPG_PRIVATE_KEY }}
-
- # Print staging repo id
- - name: Print Staging Repo Id
- run: echo ${{ steps.nexus.outputs.staged-repository-id }}
diff --git a/.github/workflows/release-notes-generation.yml b/.github/workflows/release-notes-generation.yml
deleted file mode 100644
index fa601a05fa..0000000000
--- a/.github/workflows/release-notes-generation.yml
+++ /dev/null
@@ -1,54 +0,0 @@
-name: Generate Release notes
-
-on:
- workflow_dispatch:
- inputs:
- milestoneNumber:
- description: "Milestone title"
- required: true
- generatorVersion:
- description: "Changelog Generator version"
- required: true
-
-jobs:
- build:
- name: Generate release notes
- runs-on: ubuntu-latest
- steps:
- - name: Capture milestone number and generator version
- run: |
- echo MILESTONE_NUMBER=${{ github.event.inputs.milestoneNumber }} >> $GITHUB_ENV
- echo GENERATOR_VERSION=${{ github.event.inputs.generatorVersion }} >> $GITHUB_ENV
-
- - name: Download changelog generator
- run: wget https://github.com/spring-io/github-changelog-generator/releases/download/v$GENERATOR_VERSION/github-changelog-generator.jar
-
- - name: Set up JDK 17
- uses: actions/setup-java@v3
- with:
- java-version: '17'
- distribution: 'temurin'
-
- - name: Prepare configuration file
- run: |
- cat << EOF > application.yml
- changelog:
- repository: spring-projects/spring-batch
- sections:
- - title: ":star: New features"
- labels: [ "type: feature" ]
- - title: ":rocket: Enhancements"
- labels: [ "type: enhancement" ]
- - title: ":lady_beetle: Bug fixes"
- labels: [ "type: bug" ]
- - title: ":notebook_with_decorative_cover: Documentation"
- labels: [ "in: documentation" ]
- - title: ":hammer: Tasks"
- labels: [ "type: task" ]
- EOF
-
- - name: Generate release notes
- run: java -jar github-changelog-generator.jar $MILESTONE_NUMBER release-notes.md
-
- - name: Print release notes
- run: cat release-notes.md
diff --git a/pom.xml b/pom.xml
index 390eab4dbe..66915893eb 100644
--- a/pom.xml
+++ b/pom.xml
@@ -8,7 +8,7 @@
designed to enable the development of robust batch applications vital
for the daily operations of enterprise systems. Spring Batch is part of
the Spring Portfolio.
-
the type of object returned by the builder (by default a Flow) * @@ -107,7 +108,8 @@ public Q build() { /** * Transition to the next step on successful completion of the current step. All other - * outcomes are treated as failures. + * outcomes are treated as failures. If no steps are registered yet, then this method + * will behave in the same way as {@link #start(Step)}. * @param step the next step * @return this to enable chaining */ @@ -250,26 +252,32 @@ private void doNext(Object input) { if (this.currentState == null) { doStart(input); } - State next = createState(input); - addTransition("COMPLETED", next); - addTransition("*", failedState); - this.currentState = next; + else { + State next = createState(input); + addTransition("COMPLETED", next); + addTransition("*", failedState); + this.currentState = next; + } } private void doStart(Object input) { if (this.currentState != null) { doFrom(input); } - this.currentState = createState(input); + else { + this.currentState = createState(input); + } } private void doFrom(Object input) { if (currentState == null) { doStart(input); } - State state = createState(input); - tos.put(currentState.getName(), currentState); - this.currentState = state; + else { + State state = createState(input); + tos.put(currentState.getName(), currentState); + this.currentState = state; + } } private State createState(Object input) { diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/job/builder/JobBuilder.java b/spring-batch-core/src/main/java/org/springframework/batch/core/job/builder/JobBuilder.java index 67fb991f53..d00372346a 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/job/builder/JobBuilder.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/job/builder/JobBuilder.java @@ -62,7 +62,7 @@ public SimpleJobBuilder start(Step step) { /** * Create a new job builder that will execute a flow. * @param flow a flow to execute - * @return a {@link SimpleJobBuilder} + * @return a {@link JobFlowBuilder} */ public JobFlowBuilder start(Flow flow) { return new FlowJobBuilder(this).start(flow); @@ -71,7 +71,7 @@ public JobFlowBuilder start(Flow flow) { /** * Create a new job builder that will execute a step or sequence of steps. * @param step a step to execute - * @return a {@link SimpleJobBuilder} + * @return a {@link JobFlowBuilder} */ public JobFlowBuilder flow(Step step) { return new FlowJobBuilder(this).start(step); diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/support/SimpleFlow.java b/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/support/SimpleFlow.java index 2101c171d4..f66ce004c2 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/support/SimpleFlow.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/support/SimpleFlow.java @@ -48,6 +48,7 @@ * @author Dave Syer * @author Michael Minella * @author Mahmoud Ben Hassine + * @author Taeik Lim * @since 2.0 */ public class SimpleFlow implements Flow, InitializingBean { @@ -124,9 +125,7 @@ public CollectiongetStates() { */ @Override public void afterPropertiesSet() throws Exception { - if (startState == null) { - initializeTransitions(); - } + initializeTransitionsIfNotInitialized(); } /** @@ -134,9 +133,8 @@ public void afterPropertiesSet() throws Exception { */ @Override public FlowExecution start(FlowExecutor executor) throws FlowExecutionException { - if (startState == null) { - initializeTransitions(); - } + initializeTransitionsIfNotInitialized(); + State state = startState; String stateName = state.getName(); return resume(stateName, executor); @@ -262,6 +260,12 @@ protected boolean isFlowContinued(State state, FlowExecutionStatus status, StepE return continued; } + private synchronized void initializeTransitionsIfNotInitialized() { + if (startState == null) { + initializeTransitions(); + } + } + /** * Analyse the transitions provided and generate all the information needed to execute * the flow. diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/launch/support/JobOperatorFactoryBean.java b/spring-batch-core/src/main/java/org/springframework/batch/core/launch/support/JobOperatorFactoryBean.java index ce2ef8e4f2..a3c07375ec 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/launch/support/JobOperatorFactoryBean.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/launch/support/JobOperatorFactoryBean.java @@ -1,5 +1,5 @@ /* - * Copyright 2022-2023 the original author or authors. + * Copyright 2022-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -71,7 +71,7 @@ public class JobOperatorFactoryBean implements FactoryBean , Initial public void afterPropertiesSet() throws Exception { Assert.notNull(this.transactionManager, "TransactionManager must not be null"); Assert.notNull(this.jobLauncher, "JobLauncher must not be null"); - Assert.notNull(this.jobRegistry, "JobLocator must not be null"); + Assert.notNull(this.jobRegistry, "JobRegistry must not be null"); Assert.notNull(this.jobExplorer, "JobExplorer must not be null"); Assert.notNull(this.jobRepository, "JobRepository must not be null"); if (this.transactionAttributeSource == null) { diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/listener/OrderedComposite.java b/spring-batch-core/src/main/java/org/springframework/batch/core/listener/OrderedComposite.java index abd24cbc77..75f9c2516c 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/listener/OrderedComposite.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/listener/OrderedComposite.java @@ -83,7 +83,7 @@ else if (!unordered.contains(item)) { * @return an iterator over the list of items */ public Iterator iterator() { - return new ArrayList<>(list).iterator(); + return Collections.unmodifiableList(list).iterator(); } /** diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/repository/dao/Jackson2ExecutionContextStringSerializer.java b/spring-batch-core/src/main/java/org/springframework/batch/core/repository/dao/Jackson2ExecutionContextStringSerializer.java index 9748d469a1..3e5fe34e2c 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/repository/dao/Jackson2ExecutionContextStringSerializer.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/repository/dao/Jackson2ExecutionContextStringSerializer.java @@ -174,6 +174,9 @@ private abstract class JobParametersMixIn { @JsonIgnore abstract boolean isEmpty(); + @JsonIgnore + abstract Map> getIdentifyingParameters(); + } private class JobParameterSerializer extends StdSerializer { @@ -295,7 +298,8 @@ static class TrustedTypeIdResolver implements TypeIdResolver { "java.lang.Byte", "java.lang.Short", "java.lang.Integer", "java.lang.Long", "java.lang.Double", "java.lang.Float", "java.math.BigDecimal", "java.math.BigInteger", "java.lang.String", "java.lang.Character", "java.lang.CharSequence", "java.util.Properties", "[Ljava.util.Properties;", - "org.springframework.batch.core.JobParameter", "org.springframework.batch.core.JobParameters"); + "org.springframework.batch.core.JobParameter", "org.springframework.batch.core.JobParameters", + "java.util.concurrent.ConcurrentHashMap", "java.sql.Date"); private final Set trustedClassNames = new LinkedHashSet<>(TRUSTED_CLASS_NAMES); diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/repository/support/SimpleJobRepository.java b/spring-batch-core/src/main/java/org/springframework/batch/core/repository/support/SimpleJobRepository.java index 20eaacafe6..48610fbf77 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/repository/support/SimpleJobRepository.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/repository/support/SimpleJobRepository.java @@ -1,5 +1,5 @@ /* - * Copyright 2006-2023 the original author or authors. + * Copyright 2006-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,7 +21,6 @@ import org.springframework.batch.core.BatchStatus; import org.springframework.batch.core.JobExecution; import org.springframework.batch.core.JobInstance; -import org.springframework.batch.core.JobParameter; import org.springframework.batch.core.JobParameters; import org.springframework.batch.core.StepExecution; import org.springframework.batch.core.repository.JobExecutionAlreadyRunningException; @@ -54,6 +53,7 @@ * @author Mahmoud Ben Hassine * @author Baris Cubukcuoglu * @author Parikshit Dutta + * @author Mark John Moreno * @see JobRepository * @see JobInstanceDao * @see JobExecutionDao @@ -151,15 +151,14 @@ public JobExecution createJobExecution(String jobName, JobParameters jobParamete + "The last execution ended with a failure that could not be rolled back, " + "so it may be dangerous to proceed. Manual intervention is probably necessary."); } - Collection > allJobParameters = execution.getJobParameters().getParameters().values(); - long identifyingJobParametersCount = allJobParameters.stream() - .filter(JobParameter::isIdentifying) - .count(); - if (identifyingJobParametersCount > 0 + JobParameters allJobParameters = execution.getJobParameters(); + JobParameters identifyingJobParameters = new JobParameters(allJobParameters.getIdentifyingParameters()); + if (!identifyingJobParameters.isEmpty() && (status == BatchStatus.COMPLETED || status == BatchStatus.ABANDONED)) { throw new JobInstanceAlreadyCompleteException( - "A job instance already exists and is complete for parameters=" + jobParameters - + ". If you want to run this job again, change the parameters."); + "A job instance already exists and is complete for identifying parameters=" + + identifyingJobParameters + ". If you want to run this job again, " + + "change the parameters."); } } executionContext = ecDao.getExecutionContext(jobExecutionDao.getLastJobExecution(jobInstance)); @@ -329,7 +328,7 @@ public void deleteJobExecution(JobExecution jobExecution) { @Override public void deleteJobInstance(JobInstance jobInstance) { - List jobExecutions = this.jobExecutionDao.findJobExecutions(jobInstance); + List jobExecutions = findJobExecutions(jobInstance); for (JobExecution jobExecution : jobExecutions) { deleteJobExecution(jobExecution); } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/step/builder/AbstractTaskletStepBuilder.java b/spring-batch-core/src/main/java/org/springframework/batch/core/step/builder/AbstractTaskletStepBuilder.java index 8ab4fb2a14..eb61b652d1 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/step/builder/AbstractTaskletStepBuilder.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/step/builder/AbstractTaskletStepBuilder.java @@ -49,6 +49,7 @@ * @author Dave Syer * @author Michael Minella * @author Mahmoud Ben Hassine + * @author Ilpyo Yang * @since 2.2 * @param the type of builder represented */ @@ -74,6 +75,23 @@ public AbstractTaskletStepBuilder(StepBuilderHelper> parent) { super(parent); } + /** + * Create a new builder initialized with any properties in the parent. The parent is + * copied, so it can be re-used. + * @param parent a parent helper containing common step properties + */ + public AbstractTaskletStepBuilder(AbstractTaskletStepBuilder> parent) { + super(parent); + this.chunkListeners = parent.chunkListeners; + this.stepOperations = parent.stepOperations; + this.transactionManager = parent.transactionManager; + this.transactionAttribute = parent.transactionAttribute; + this.streams.addAll(parent.streams); + this.exceptionHandler = parent.exceptionHandler; + this.throttleLimit = parent.throttleLimit; + this.taskExecutor = parent.taskExecutor; + } + protected abstract Tasklet createTasklet(); /** @@ -199,9 +217,10 @@ public B taskExecutor(TaskExecutor taskExecutor) { * in the job repository for this step. * @param throttleLimit maximum number of concurrent tasklet executions allowed * @return this for fluent chaining - * @deprecated since 5.0, scheduled for removal in 6.0. Use a pooled - * {@link TaskExecutor} implementation with a limited capacity of its task queue - * instead. + * @deprecated with no replacement since 5.0, scheduled for removal in 6.0. Use a + * custom {@link RepeatOperations} implementation (based on a {@link TaskExecutor} + * with a bounded task queue) and set it on the step with + * {@link #stepOperations(RepeatOperations)}. */ @Deprecated(since = "5.0", forRemoval = true) public B throttleLimit(int throttleLimit) { diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/step/builder/SimpleStepBuilder.java b/spring-batch-core/src/main/java/org/springframework/batch/core/step/builder/SimpleStepBuilder.java index 9bf252cbd2..088b17ca5f 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/step/builder/SimpleStepBuilder.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/step/builder/SimpleStepBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright 2006-2022 the original author or authors. + * Copyright 2006-2023 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -58,8 +58,8 @@ /** * Step builder for simple item processing (chunk oriented) steps. Items are read and - * cached in chunks, and then processed (transformed) and written (optionally either the - * processor or the writer can be omitted) all in the same transaction. + * cached in chunks, and then processed (transformed) and written (optionally the + * processor can be omitted) all in the same transaction. * * @see FaultTolerantStepBuilder for a step that handles retry and skip of failed items * @author Dave Syer @@ -114,7 +114,6 @@ protected SimpleStepBuilder(SimpleStepBuilder parent) { this.itemListeners = parent.itemListeners; this.readerTransactionalQueue = parent.readerTransactionalQueue; this.meterRegistry = parent.meterRegistry; - this.transactionManager(parent.getTransactionManager()); } public FaultTolerantStepBuilder faultTolerant() { diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/FaultTolerantChunkProcessor.java b/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/FaultTolerantChunkProcessor.java index f1eb7321f5..ecb797111c 100755 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/FaultTolerantChunkProcessor.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/FaultTolerantChunkProcessor.java @@ -1,5 +1,5 @@ /* - * Copyright 2006-2023 the original author or authors. + * Copyright 2006-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -306,7 +306,9 @@ else if (shouldSkip(itemProcessSkipPolicy, e, contribution.getStepSkipCount())) break; } } - + if (inputs.isEnd()) { + outputs.setEnd(); + } return outputs; } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/SimpleChunkProcessor.java b/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/SimpleChunkProcessor.java index 813b6eb403..101945bb22 100755 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/SimpleChunkProcessor.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/SimpleChunkProcessor.java @@ -1,5 +1,5 @@ /* - * Copyright 2006-2022 the original author or authors. + * Copyright 2006-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -340,6 +340,9 @@ protected Chunk transform(StepContribution contribution, Chunk inputs) thr iterator.remove(); } } + if (inputs.isEnd()) { + outputs.setEnd(); + } return outputs; } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/step/job/DefaultJobParametersExtractor.java b/spring-batch-core/src/main/java/org/springframework/batch/core/step/job/DefaultJobParametersExtractor.java index 948b144712..f37de435a5 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/step/job/DefaultJobParametersExtractor.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/step/job/DefaultJobParametersExtractor.java @@ -79,6 +79,9 @@ public JobParameters getJobParameters(Job job, StepExecution stepExecution) { if (executionContext.containsKey(key)) { properties.setProperty(key, executionContext.getString(key)); } + else if (jobParameters.containsKey(key)) { + builder.addJobParameter(key, jobParameters.get(key)); + } } builder.addJobParameters(this.jobParametersConverter.getJobParameters(properties)); return builder.toJobParameters(); diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/step/tasklet/SystemCommandTasklet.java b/spring-batch-core/src/main/java/org/springframework/batch/core/step/tasklet/SystemCommandTasklet.java index b35a228a4d..4499279e8e 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/step/tasklet/SystemCommandTasklet.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/step/tasklet/SystemCommandTasklet.java @@ -1,5 +1,5 @@ /* - * Copyright 2006-2023 the original author or authors. + * Copyright 2006-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -60,6 +60,7 @@ * @author Robert Kasanicky * @author Will Schipp * @author Mahmoud Ben Hassine + * @author Injae Kim */ public class SystemCommandTasklet implements StepExecutionListener, StoppableTasklet, InitializingBean { @@ -121,8 +122,15 @@ public RepeatStatus execute(StepContribution contribution, ChunkContext chunkCon } if (systemCommandTask.isDone()) { - contribution.setExitStatus(systemProcessExitCodeMapper.getExitStatus(systemCommandTask.get())); - return RepeatStatus.FINISHED; + Integer exitCode = systemCommandTask.get(); + ExitStatus exitStatus = systemProcessExitCodeMapper.getExitStatus(exitCode); + contribution.setExitStatus(exitStatus); + if (ExitStatus.FAILED.equals(exitStatus)) { + throw new SystemCommandException("Execution of system command failed with exit code " + exitCode); + } + else { + return RepeatStatus.FINISHED; + } } else if (System.currentTimeMillis() - t0 > timeout) { systemCommandTask.cancel(interruptOnCancel); diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/step/tasklet/TaskletStep.java b/spring-batch-core/src/main/java/org/springframework/batch/core/step/tasklet/TaskletStep.java index b5941c1ecc..58a22395c4 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/step/tasklet/TaskletStep.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/step/tasklet/TaskletStep.java @@ -431,7 +431,9 @@ public RepeatStatus doInTransaction(TransactionStatus status) { try { // Going to attempt a commit. If it fails this flag will // stay false and we can use that later. - getJobRepository().updateExecutionContext(stepExecution); + if (stepExecution.getExecutionContext().isDirty()) { + getJobRepository().updateExecutionContext(stepExecution); + } stepExecution.incrementCommitCount(); if (logger.isDebugEnabled()) { logger.debug("Saving step execution before commit: " + stepExecution); diff --git a/spring-batch-core/src/main/resources/org/springframework/batch/core/migration/5.0/migration-h2.sql b/spring-batch-core/src/main/resources/org/springframework/batch/core/migration/5.0/migration-h2.sql index 8916a0f04e..5bdac69327 100644 --- a/spring-batch-core/src/main/resources/org/springframework/batch/core/migration/5.0/migration-h2.sql +++ b/spring-batch-core/src/main/resources/org/springframework/batch/core/migration/5.0/migration-h2.sql @@ -5,9 +5,12 @@ ALTER TABLE BATCH_JOB_EXECUTION_PARAMS DROP COLUMN DATE_VAL; ALTER TABLE BATCH_JOB_EXECUTION_PARAMS DROP COLUMN LONG_VAL; ALTER TABLE BATCH_JOB_EXECUTION_PARAMS DROP COLUMN DOUBLE_VAL; -ALTER TABLE BATCH_JOB_EXECUTION_PARAMS MODIFY COLUMN TYPE_CD PARAMETER_TYPE VARCHAR(100); -ALTER TABLE BATCH_JOB_EXECUTION_PARAMS MODIFY COLUMN KEY_NAME PARAMETER_NAME VARCHAR(100); -ALTER TABLE BATCH_JOB_EXECUTION_PARAMS MODIFY COLUMN STRING_VAL PARAMETER_VALUE VARCHAR(2500); +ALTER TABLE BATCH_JOB_EXECUTION_PARAMS ALTER COLUMN TYPE_CD RENAME TO PARAMETER_TYPE; +ALTER TABLE BATCH_JOB_EXECUTION_PARAMS ALTER COLUMN PARAMETER_TYPE SET DATA TYPE VARCHAR(100); +ALTER TABLE BATCH_JOB_EXECUTION_PARAMS ALTER COLUMN KEY_NAME RENAME TO PARAMETER_NAME; +ALTER TABLE BATCH_JOB_EXECUTION_PARAMS ALTER COLUMN PARAMETER_NAME SET DATA TYPE VARCHAR(100); +ALTER TABLE BATCH_JOB_EXECUTION_PARAMS ALTER COLUMN STRING_VAL RENAME TO PARAMETER_VALUE; +ALTER TABLE BATCH_JOB_EXECUTION_PARAMS ALTER COLUMN PARAMETER_VALUE SET DATA TYPE VARCHAR(2500); ALTER TABLE BATCH_JOB_EXECUTION ALTER COLUMN CREATE_TIME SET DATA TYPE TIMESTAMP(9); ALTER TABLE BATCH_JOB_EXECUTION ALTER COLUMN START_TIME SET DATA TYPE TIMESTAMP(9); @@ -17,4 +20,4 @@ ALTER TABLE BATCH_JOB_EXECUTION ALTER COLUMN LAST_UPDATED SET DATA TYPE TIMESTAM ALTER TABLE BATCH_STEP_EXECUTION ALTER COLUMN CREATE_TIME SET DATA TYPE TIMESTAMP(9); ALTER TABLE BATCH_STEP_EXECUTION ALTER COLUMN START_TIME SET DATA TYPE TIMESTAMP(9); ALTER TABLE BATCH_STEP_EXECUTION ALTER COLUMN END_TIME SET DATA TYPE TIMESTAMP(9); -ALTER TABLE BATCH_STEP_EXECUTION ALTER COLUMN LAST_UPDATED SET DATA TYPE TIMESTAMP(9); \ No newline at end of file +ALTER TABLE BATCH_STEP_EXECUTION ALTER COLUMN LAST_UPDATED SET DATA TYPE TIMESTAMP(9); diff --git a/spring-batch-core/src/main/resources/org/springframework/batch/core/schema-drop-sqlserver.sql b/spring-batch-core/src/main/resources/org/springframework/batch/core/schema-drop-sqlserver.sql index d217ec569b..247ae20760 100644 --- a/spring-batch-core/src/main/resources/org/springframework/batch/core/schema-drop-sqlserver.sql +++ b/spring-batch-core/src/main/resources/org/springframework/batch/core/schema-drop-sqlserver.sql @@ -7,6 +7,6 @@ DROP TABLE BATCH_JOB_EXECUTION_PARAMS; DROP TABLE BATCH_JOB_EXECUTION; DROP TABLE BATCH_JOB_INSTANCE; -DROP TABLE BATCH_STEP_EXECUTION_SEQ; -DROP TABLE BATCH_JOB_EXECUTION_SEQ; -DROP TABLE BATCH_JOB_SEQ; +DROP SEQUENCE BATCH_STEP_EXECUTION_SEQ; +DROP SEQUENCE BATCH_JOB_EXECUTION_SEQ; +DROP SEQUENCE BATCH_JOB_SEQ; diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/JobParametersBuilderTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/JobParametersBuilderTests.java index a79efcca41..220dfc4724 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/JobParametersBuilderTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/JobParametersBuilderTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2008-2023 the original author or authors. + * Copyright 2008-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,6 +22,7 @@ import java.util.Map; import java.util.Set; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -61,7 +62,7 @@ class JobParametersBuilderTests { @BeforeEach void initialize() { this.job = new SimpleJob("simpleJob"); - this.jobExplorer = mock(JobExplorer.class); + this.jobExplorer = mock(); this.jobInstanceList = new ArrayList<>(1); this.jobExecutionList = new ArrayList<>(1); this.parametersBuilder = new JobParametersBuilder(this.jobExplorer); @@ -85,6 +86,13 @@ void testAddingExistingJobParameters() { assertEquals(finalParams.getString("baz"), "quix"); } + @Test + void testAddingNullJobParameters() { + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, + () -> new JobParametersBuilder().addString("foo", null).toJobParameters()); + Assertions.assertEquals("Value for parameter 'foo' must not be null", exception.getMessage()); + } + @Test void testNonIdentifyingParameters() { this.parametersBuilder.addDate("SCHEDULE_DATE", date, false); diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/JobParametersTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/JobParametersTests.java index b3a4b310d8..28c70c7615 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/JobParametersTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/JobParametersTests.java @@ -187,6 +187,25 @@ void testSerialization() { assertEquals(params, SerializationUtils.clone(params)); } + @Test + void testGetIdentifyingParameters() { + // given + Map > parametersMap = new HashMap<>(); + JobParameter jobParameter1 = new JobParameter<>("value1", String.class, true); + JobParameter jobParameter2 = new JobParameter<>("value2", String.class, false); + parametersMap.put("key1", jobParameter1); + parametersMap.put("key2", jobParameter2); + JobParameters parameters = new JobParameters(parametersMap); + + // when + Map > identifyingParameters = parameters.getIdentifyingParameters(); + + // then + assertEquals(1, identifyingParameters.size()); + JobParameter> key1 = identifyingParameters.get("key1"); + assertEquals(jobParameter1, key1); + } + @Test void testLongReturnsNullWhenKeyDoesntExit() { assertNull(new JobParameters().getLong("keythatdoesntexist")); diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/annotation/BatchRegistrarTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/annotation/BatchRegistrarTests.java index 066db5b3c7..b07fc71e7e 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/annotation/BatchRegistrarTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/annotation/BatchRegistrarTests.java @@ -179,7 +179,7 @@ public static class JobConfigurationWithoutTransactionManager { @Bean public DataSource dataSource() { - return Mockito.mock(DataSource.class); + return Mockito.mock(); } } @@ -190,27 +190,27 @@ public static class JobConfigurationWithUserDefinedInfrastructureBeans { @Bean public JobRepository jobRepository() { - return Mockito.mock(JobRepository.class); + return Mockito.mock(); } @Bean public JobExplorer jobExplorer() { - return Mockito.mock(JobExplorer.class); + return Mockito.mock(); } @Bean public JobLauncher jobLauncher() { - return Mockito.mock(JobLauncher.class); + return Mockito.mock(); } @Bean public JobRegistry jobRegistry() { - return Mockito.mock(JobRegistry.class); + return Mockito.mock(); } @Bean public JobOperator jobOperator() { - return Mockito.mock(JobOperator.class); + return Mockito.mock(); } } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/support/AutomaticJobRegistrarTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/support/AutomaticJobRegistrarTests.java index c58894659f..61112f4768 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/support/AutomaticJobRegistrarTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/support/AutomaticJobRegistrarTests.java @@ -183,7 +183,7 @@ void testStartStopRunning() { @Test void testStartStopRunningWithCallback() { - Runnable callback = Mockito.mock(Runnable.class); + Runnable callback = Mockito.mock(); Resource[] jobPaths = new Resource[] { new ClassPathResource("org/springframework/batch/core/launch/support/2jobs.xml") }; setUpApplicationContextFactories(jobPaths, null); diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/converter/DefaultJobParametersConverterTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/converter/DefaultJobParametersConverterTests.java index e413162a41..d39b9ad5eb 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/converter/DefaultJobParametersConverterTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/converter/DefaultJobParametersConverterTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2006-2023 the original author or authors. + * Copyright 2006-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,6 +20,7 @@ import org.junit.jupiter.api.Test; +import org.springframework.batch.core.JobParameter; import org.springframework.batch.core.JobParameters; import org.springframework.batch.core.JobParametersBuilder; import org.springframework.util.StringUtils; @@ -129,6 +130,22 @@ void testGetParametersWithBogusLong() { } } + @Test + void testGetParametersWithEmptyValue() { + // given + String[] args = new String[] { "parameter=" }; + + // when + JobParameters jobParameters = factory.getJobParameters(StringUtils.splitArrayElementsIntoProperties(args, "=")); + + // then + assertEquals(1, jobParameters.getParameters().size()); + JobParameter> parameter = jobParameters.getParameters().get("parameter"); + assertEquals("", parameter.getValue()); + assertEquals(String.class, parameter.getType()); + assertTrue(parameter.isIdentifying()); + } + @Test void testGetParametersWithDoubleValueDeclaredAsLong() { diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/explore/support/JobExplorerFactoryBeanTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/explore/support/JobExplorerFactoryBeanTests.java index fa7cef0e7c..5f8b13913b 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/explore/support/JobExplorerFactoryBeanTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/explore/support/JobExplorerFactoryBeanTests.java @@ -54,8 +54,8 @@ class JobExplorerFactoryBeanTests { void setUp() { factory = new JobExplorerFactoryBean(); - DataSource dataSource = mock(DataSource.class); - PlatformTransactionManager transactionManager = mock(PlatformTransactionManager.class); + DataSource dataSource = mock(); + PlatformTransactionManager transactionManager = mock(); factory.setDataSource(dataSource); factory.setTransactionManager(transactionManager); factory.setTablePrefix(tablePrefix); @@ -73,7 +73,7 @@ void testDefaultJdbcOperations() throws Exception { @Test void testCustomJdbcOperations() throws Exception { - JdbcOperations customJdbcOperations = mock(JdbcOperations.class); + JdbcOperations customJdbcOperations = mock(); factory.setJdbcOperations(customJdbcOperations); factory.afterPropertiesSet(); assertEquals(customJdbcOperations, ReflectionTestUtils.getField(factory, "jdbcOperations")); @@ -111,7 +111,7 @@ void testCreateExplorer() throws Exception { @Test public void testCustomTransactionAttributesSource() throws Exception { // given - TransactionAttributeSource transactionAttributeSource = Mockito.mock(TransactionAttributeSource.class); + TransactionAttributeSource transactionAttributeSource = Mockito.mock(); this.factory.setTransactionAttributeSource(transactionAttributeSource); this.factory.afterPropertiesSet(); diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/explore/support/SimpleJobExplorerTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/explore/support/SimpleJobExplorerTests.java index 8b275d9c7d..7e7122d0b0 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/explore/support/SimpleJobExplorerTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/explore/support/SimpleJobExplorerTests.java @@ -65,10 +65,10 @@ class SimpleJobExplorerTests { @BeforeEach void setUp() { - jobExecutionDao = mock(JobExecutionDao.class); - jobInstanceDao = mock(JobInstanceDao.class); - stepExecutionDao = mock(StepExecutionDao.class); - ecDao = mock(ExecutionContextDao.class); + jobExecutionDao = mock(); + jobInstanceDao = mock(); + stepExecutionDao = mock(); + ecDao = mock(); jobExplorer = new SimpleJobExplorer(jobInstanceDao, jobExecutionDao, stepExecutionDao, ecDao); diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/job/CompositeJobParametersValidatorTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/job/CompositeJobParametersValidatorTests.java index 767df315e3..93694fc764 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/job/CompositeJobParametersValidatorTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/job/CompositeJobParametersValidatorTests.java @@ -52,7 +52,7 @@ void testValidatorsCanNotBeEmpty() { @Test void testDelegateIsInvoked() throws JobParametersInvalidException { - JobParametersValidator validator = mock(JobParametersValidator.class); + JobParametersValidator validator = mock(); validator.validate(parameters); compositeJobParametersValidator.setValidators(Arrays.asList(validator)); compositeJobParametersValidator.validate(parameters); @@ -60,7 +60,7 @@ void testDelegateIsInvoked() throws JobParametersInvalidException { @Test void testDelegatesAreInvoked() throws JobParametersInvalidException { - JobParametersValidator validator = mock(JobParametersValidator.class); + JobParametersValidator validator = mock(); validator.validate(parameters); validator.validate(parameters); compositeJobParametersValidator.setValidators(Arrays.asList(validator, validator)); diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/job/SimpleJobTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/job/SimpleJobTests.java index ff0ea2a720..29b359ab47 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/job/SimpleJobTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/job/SimpleJobTests.java @@ -416,7 +416,7 @@ void testRestart() throws Exception { void testInterruptWithListener() { step1.setProcessException(new JobInterruptedException("job interrupted!")); - JobExecutionListener listener = mock(JobExecutionListener.class); + JobExecutionListener listener = mock(); listener.beforeJob(jobExecution); listener.afterJob(jobExecution); diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/job/builder/FlowBuilderTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/job/builder/FlowBuilderTests.java index cfe457aae1..dd47b49999 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/job/builder/FlowBuilderTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/job/builder/FlowBuilderTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2022 the original author or authors. + * Copyright 2012-2023 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,6 +19,7 @@ import org.junit.jupiter.api.Test; +import org.springframework.batch.core.BatchStatus; import org.springframework.batch.core.ExitStatus; import org.springframework.batch.core.JobExecution; import org.springframework.batch.core.JobInterruptedException; @@ -34,26 +35,79 @@ import org.springframework.batch.core.step.StepSupport; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; /** * @author Dave Syer * @author Michael Minella * @author Mahmoud Ben Hassine + * @author Injae Kim * */ class FlowBuilderTests { @Test - void test() throws Exception { + void testNext() throws Exception { FlowBuilder builder = new FlowBuilder<>("flow"); JobRepository jobRepository = new JobRepositorySupport(); JobExecution execution = jobRepository.createJobExecution("foo", new JobParameters()); - builder.start(new StepSupport("step") { - @Override - public void execute(StepExecution stepExecution) - throws JobInterruptedException, UnexpectedJobExecutionException { - } - }).end().start(new JobFlowExecutor(jobRepository, new SimpleStepHandler(jobRepository), execution)); + + builder.next(createCompleteStep("stepA")) + .end() + .start(new JobFlowExecutor(jobRepository, new SimpleStepHandler(jobRepository), execution)); + + Iterator stepExecutions = execution.getStepExecutions().iterator(); + assertEquals(stepExecutions.next().getStepName(), "stepA"); + assertFalse(stepExecutions.hasNext()); + } + + @Test + void testMultipleNext() throws Exception { + FlowBuilder builder = new FlowBuilder<>("flow"); + JobRepository jobRepository = new JobRepositorySupport(); + JobExecution execution = jobRepository.createJobExecution("foo", new JobParameters()); + + builder.next(createCompleteStep("stepA")) + .next(createCompleteStep("stepB")) + .next(createCompleteStep("stepC")) + .end() + .start(new JobFlowExecutor(jobRepository, new SimpleStepHandler(jobRepository), execution)); + + Iterator stepExecutions = execution.getStepExecutions().iterator(); + assertEquals(stepExecutions.next().getStepName(), "stepA"); + assertEquals(stepExecutions.next().getStepName(), "stepB"); + assertEquals(stepExecutions.next().getStepName(), "stepC"); + assertFalse(stepExecutions.hasNext()); + } + + @Test + void testStart() throws Exception { + FlowBuilder builder = new FlowBuilder<>("flow"); + JobRepository jobRepository = new JobRepositorySupport(); + JobExecution execution = jobRepository.createJobExecution("foo", new JobParameters()); + + builder.start(createCompleteStep("stepA")) + .end() + .start(new JobFlowExecutor(jobRepository, new SimpleStepHandler(jobRepository), execution)); + + Iterator stepExecutions = execution.getStepExecutions().iterator(); + assertEquals(stepExecutions.next().getStepName(), "stepA"); + assertFalse(stepExecutions.hasNext()); + } + + @Test + void testFrom() throws Exception { + FlowBuilder builder = new FlowBuilder<>("flow"); + JobRepository jobRepository = new JobRepositorySupport(); + JobExecution execution = jobRepository.createJobExecution("foo", new JobParameters()); + + builder.from(createCompleteStep("stepA")) + .end() + .start(new JobFlowExecutor(jobRepository, new SimpleStepHandler(jobRepository), execution)); + + Iterator stepExecutions = execution.getStepExecutions().iterator(); + assertEquals(stepExecutions.next().getStepName(), "stepA"); + assertFalse(stepExecutions.hasNext()); } @Test @@ -66,7 +120,7 @@ void testTransitionOrdering() throws Exception { @Override public void execute(StepExecution stepExecution) throws JobInterruptedException, UnexpectedJobExecutionException { - stepExecution.setExitStatus(new ExitStatus("FAILED")); + stepExecution.setExitStatus(ExitStatus.FAILED); } }; @@ -94,10 +148,20 @@ public void execute(StepExecution stepExecution) .start(new JobFlowExecutor(jobRepository, new SimpleStepHandler(jobRepository), execution)); Iterator stepExecutions = execution.getStepExecutions().iterator(); - StepExecution stepExecutionA = stepExecutions.next(); - assertEquals(stepExecutionA.getStepName(), "stepA"); - StepExecution stepExecutionC = stepExecutions.next(); - assertEquals(stepExecutionC.getStepName(), "stepC"); + assertEquals(stepExecutions.next().getStepName(), "stepA"); + assertEquals(stepExecutions.next().getStepName(), "stepC"); + assertFalse(stepExecutions.hasNext()); + } + + private static StepSupport createCompleteStep(String name) { + return new StepSupport(name) { + @Override + public void execute(StepExecution stepExecution) + throws JobInterruptedException, UnexpectedJobExecutionException { + stepExecution.upgradeStatus(BatchStatus.COMPLETED); + stepExecution.setExitStatus(ExitStatus.COMPLETED); + } + }; } } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/job/builder/FlowJobBuilderTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/job/builder/FlowJobBuilderTests.java index 3b1068d225..34c8663548 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/job/builder/FlowJobBuilderTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/job/builder/FlowJobBuilderTests.java @@ -142,6 +142,15 @@ void testBuildSingleFlow() { assertEquals(2, execution.getStepExecutions().size()); } + @Test + void testBuildSingleFlowAddingStepsViaNext() { + Flow flow = new FlowBuilder ("subflow").next(step1).next(step2).build(); + FlowJobBuilder builder = new JobBuilder("flow", jobRepository).start(flow).end().preventRestart(); + builder.build().execute(execution); + assertEquals(BatchStatus.COMPLETED, execution.getStatus()); + assertEquals(2, execution.getStepExecutions().size()); + } + @Test void testBuildOverTwoLines() { FlowJobBuilder builder = new JobBuilder("flow", jobRepository).start(step1).on("COMPLETED").to(step2).end(); diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/job/flow/support/state/SplitStateTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/job/flow/support/state/SplitStateTests.java index 0e89afd8d8..c864d1fbab 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/job/flow/support/state/SplitStateTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/job/flow/support/state/SplitStateTests.java @@ -43,8 +43,8 @@ class SplitStateTests { void testBasicHandling() throws Exception { Collection flows = new ArrayList<>(); - Flow flow1 = mock(Flow.class); - Flow flow2 = mock(Flow.class); + Flow flow1 = mock(); + Flow flow2 = mock(); flows.add(flow1); flows.add(flow2); @@ -61,8 +61,8 @@ void testBasicHandling() throws Exception { @Test void testConcurrentHandling() throws Exception { - Flow flow1 = mock(Flow.class); - Flow flow2 = mock(Flow.class); + Flow flow1 = mock(); + Flow flow2 = mock(); SplitState state = new SplitState(Arrays.asList(flow1, flow2), "foo"); state.setTaskExecutor(new SimpleAsyncTaskExecutor()); diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/launch/TaskExecutorJobLauncherTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/launch/TaskExecutorJobLauncherTests.java index a1109852c6..2d8863826e 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/launch/TaskExecutorJobLauncherTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/launch/TaskExecutorJobLauncherTests.java @@ -72,7 +72,7 @@ public void execute(JobExecution execution) { void setUp() { jobLauncher = new TaskExecutorJobLauncher(); - jobRepository = mock(JobRepository.class); + jobRepository = mock(); jobLauncher.setJobRepository(jobRepository); } @@ -265,13 +265,13 @@ void testRunStepStatusStopping() { private void testRestartStepExecutionInvalidStatus(BatchStatus status) throws Exception { String jobName = "test_job"; - JobRepository jobRepository = mock(JobRepository.class); + JobRepository jobRepository = mock(); JobParameters parameters = new JobParametersBuilder().addLong("runtime", System.currentTimeMillis()) .toJobParameters(); - JobExecution jobExecution = mock(JobExecution.class); - Job job = mock(Job.class); - JobParametersValidator validator = mock(JobParametersValidator.class); - StepExecution stepExecution = mock(StepExecution.class); + JobExecution jobExecution = mock(); + Job job = mock(); + JobParametersValidator validator = mock(); + StepExecution stepExecution = mock(); when(job.getName()).thenReturn(jobName); when(job.isRestartable()).thenReturn(true); diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/launch/support/DataFieldMaxValueJobParametersIncrementerTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/launch/support/DataFieldMaxValueJobParametersIncrementerTests.java index 60d55e1680..a56457d06f 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/launch/support/DataFieldMaxValueJobParametersIncrementerTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/launch/support/DataFieldMaxValueJobParametersIncrementerTests.java @@ -31,7 +31,7 @@ */ class DataFieldMaxValueJobParametersIncrementerTests { - private final DataFieldMaxValueIncrementer incrementer = mock(DataFieldMaxValueIncrementer.class); + private final DataFieldMaxValueIncrementer incrementer = mock(); @Test void testInvalidKey() { diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/launch/support/JobOperatorFactoryBeanTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/launch/support/JobOperatorFactoryBeanTests.java index b984fe438e..c09cbe5925 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/launch/support/JobOperatorFactoryBeanTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/launch/support/JobOperatorFactoryBeanTests.java @@ -39,17 +39,17 @@ */ class JobOperatorFactoryBeanTests { - private final PlatformTransactionManager transactionManager = Mockito.mock(PlatformTransactionManager.class); + private final PlatformTransactionManager transactionManager = Mockito.mock(); - private final JobRepository jobRepository = Mockito.mock(JobRepository.class); + private final JobRepository jobRepository = Mockito.mock(); - private final JobLauncher jobLauncher = Mockito.mock(JobLauncher.class); + private final JobLauncher jobLauncher = Mockito.mock(); - private final JobRegistry jobRegistry = Mockito.mock(JobRegistry.class); + private final JobRegistry jobRegistry = Mockito.mock(); - private final JobExplorer jobExplorer = Mockito.mock(JobExplorer.class); + private final JobExplorer jobExplorer = Mockito.mock(); - private final JobParametersConverter jobParametersConverter = Mockito.mock(JobParametersConverter.class); + private final JobParametersConverter jobParametersConverter = Mockito.mock(); @Test public void testJobOperatorCreation() throws Exception { @@ -76,7 +76,7 @@ public void testJobOperatorCreation() throws Exception { @Test public void testCustomTransactionAttributesSource() throws Exception { // given - TransactionAttributeSource transactionAttributeSource = Mockito.mock(TransactionAttributeSource.class); + TransactionAttributeSource transactionAttributeSource = Mockito.mock(); JobOperatorFactoryBean jobOperatorFactoryBean = new JobOperatorFactoryBean(); jobOperatorFactoryBean.setTransactionManager(this.transactionManager); jobOperatorFactoryBean.setJobLauncher(this.jobLauncher); diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/launch/support/SimpleJobOperatorTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/launch/support/SimpleJobOperatorTests.java index 32f01dae7a..d5d3951c2c 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/launch/support/SimpleJobOperatorTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/launch/support/SimpleJobOperatorTests.java @@ -120,11 +120,11 @@ public Set getJobNames() { jobOperator.setJobLauncher( (job, jobParameters) -> new JobExecution(new JobInstance(123L, job.getName()), 999L, jobParameters)); - jobExplorer = mock(JobExplorer.class); + jobExplorer = mock(); jobOperator.setJobExplorer(jobExplorer); - jobRepository = mock(JobRepository.class); + jobRepository = mock(); jobOperator.setJobRepository(jobRepository); jobOperator.setJobParametersConverter(new DefaultJobParametersConverter() { @@ -288,7 +288,7 @@ public void testGetJobInstanceWithNameAndParameters() { // given String jobName = "job"; JobParameters jobParameters = new JobParameters(); - JobInstance jobInstance = mock(JobInstance.class); + JobInstance jobInstance = mock(); // when when(this.jobExplorer.getJobInstance(jobName, jobParameters)).thenReturn(jobInstance); @@ -338,14 +338,14 @@ void testStop() throws Exception { void testStopTasklet() throws Exception { JobInstance jobInstance = new JobInstance(123L, job.getName()); JobExecution jobExecution = new JobExecution(jobInstance, 111L, jobParameters); - StoppableTasklet tasklet = mock(StoppableTasklet.class); + StoppableTasklet tasklet = mock(); TaskletStep taskletStep = new TaskletStep(); taskletStep.setTasklet(tasklet); MockJob job = new MockJob(); job.taskletStep = taskletStep; - JobRegistry jobRegistry = mock(JobRegistry.class); - TaskletStep step = mock(TaskletStep.class); + JobRegistry jobRegistry = mock(); + TaskletStep step = mock(); when(step.getTasklet()).thenReturn(tasklet); when(step.getName()).thenReturn("test_job.step1"); @@ -363,9 +363,9 @@ void testStopTasklet() throws Exception { void testStopTaskletWhenJobNotRegistered() throws Exception { JobInstance jobInstance = new JobInstance(123L, job.getName()); JobExecution jobExecution = new JobExecution(jobInstance, 111L, jobParameters); - StoppableTasklet tasklet = mock(StoppableTasklet.class); - JobRegistry jobRegistry = mock(JobRegistry.class); - TaskletStep step = mock(TaskletStep.class); + StoppableTasklet tasklet = mock(); + JobRegistry jobRegistry = mock(); + TaskletStep step = mock(); when(step.getTasklet()).thenReturn(tasklet); when(jobRegistry.getJob(job.getName())).thenThrow(new NoSuchJobException("Unable to find job")); @@ -399,8 +399,8 @@ public void stop() { MockJob job = new MockJob(); job.taskletStep = taskletStep; - JobRegistry jobRegistry = mock(JobRegistry.class); - TaskletStep step = mock(TaskletStep.class); + JobRegistry jobRegistry = mock(); + TaskletStep step = mock(); when(step.getTasklet()).thenReturn(tasklet); when(step.getName()).thenReturn("test_job.step1"); diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/listener/CompositeChunkListenerTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/listener/CompositeChunkListenerTests.java index 3d1284b060..1ae514a1a1 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/listener/CompositeChunkListenerTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/listener/CompositeChunkListenerTests.java @@ -39,7 +39,7 @@ class CompositeChunkListenerTests { @BeforeEach void setUp() { chunkContext = new ChunkContext(null); - listener = mock(ChunkListener.class); + listener = mock(); compositeListener = new CompositeChunkListener(); compositeListener.register(listener); } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/listener/CompositeItemProcessListenerTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/listener/CompositeItemProcessListenerTests.java index ed00b162a4..c9703acad0 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/listener/CompositeItemProcessListenerTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/listener/CompositeItemProcessListenerTests.java @@ -37,7 +37,7 @@ class CompositeItemProcessListenerTests { @SuppressWarnings("unchecked") @BeforeEach void setUp() { - listener = mock(ItemProcessListener.class); + listener = mock(); compositeListener = new CompositeItemProcessListener<>(); compositeListener.register(listener); } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/listener/CompositeItemReadListenerTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/listener/CompositeItemReadListenerTests.java index f559b8a3ca..ac9bd41bac 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/listener/CompositeItemReadListenerTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/listener/CompositeItemReadListenerTests.java @@ -38,7 +38,7 @@ class CompositeItemReadListenerTests { @SuppressWarnings("unchecked") @BeforeEach void setUp() { - listener = mock(ItemReadListener.class); + listener = mock(); compositeListener = new CompositeItemReadListener<>(); compositeListener.register(listener); } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/listener/CompositeItemWriteListenerTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/listener/CompositeItemWriteListenerTests.java index 714f48bc32..6531b4ef35 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/listener/CompositeItemWriteListenerTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/listener/CompositeItemWriteListenerTests.java @@ -40,7 +40,7 @@ class CompositeItemWriteListenerTests { @SuppressWarnings("unchecked") @BeforeEach void setUp() { - listener = mock(ItemWriteListener.class); + listener = mock(); compositeListener = new CompositeItemWriteListener<>(); compositeListener.register(listener); } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/JdbcExecutionContextDaoTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/JdbcExecutionContextDaoTests.java index d43b250122..b7f69611bc 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/JdbcExecutionContextDaoTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/JdbcExecutionContextDaoTests.java @@ -30,7 +30,7 @@ class JdbcExecutionContextDaoTests extends AbstractExecutionContextDaoTests { @Test void testNullSerializer() { JdbcExecutionContextDao jdbcExecutionContextDao = new JdbcExecutionContextDao(); - jdbcExecutionContextDao.setJdbcTemplate(mock(JdbcOperations.class)); + jdbcExecutionContextDao.setJdbcTemplate(mock()); Exception exception = assertThrows(IllegalArgumentException.class, () -> jdbcExecutionContextDao.setSerializer(null)); assertEquals("Serializer must not be null", exception.getMessage()); diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/repository/support/JobRepositoryFactoryBeanTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/repository/support/JobRepositoryFactoryBeanTests.java index d28daf95a2..26591735c9 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/repository/support/JobRepositoryFactoryBeanTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/repository/support/JobRepositoryFactoryBeanTests.java @@ -78,11 +78,11 @@ class JobRepositoryFactoryBeanTests { void setUp() { factory = new JobRepositoryFactoryBean(); - dataSource = mock(DataSource.class); - transactionManager = mock(PlatformTransactionManager.class); + dataSource = mock(); + transactionManager = mock(); factory.setDataSource(dataSource); factory.setTransactionManager(transactionManager); - incrementerFactory = mock(DataFieldMaxValueIncrementerFactory.class); + incrementerFactory = mock(); factory.setIncrementerFactory(incrementerFactory); factory.setTablePrefix(tablePrefix); @@ -91,8 +91,8 @@ void setUp() { @Test void testNoDatabaseType() throws Exception { - DatabaseMetaData dmd = mock(DatabaseMetaData.class); - Connection con = mock(Connection.class); + DatabaseMetaData dmd = mock(); + Connection con = mock(); when(dataSource.getConnection()).thenReturn(con); when(con.getMetaData()).thenReturn(dmd); when(dmd.getDatabaseProductName()).thenReturn("Oracle"); @@ -115,7 +115,7 @@ void testOracleLobHandler() throws Exception { factory.setDatabaseType("ORACLE"); - incrementerFactory = mock(DataFieldMaxValueIncrementerFactory.class); + incrementerFactory = mock(); when(incrementerFactory.isSupportedIncrementerType("ORACLE")).thenReturn(true); when(incrementerFactory.getIncrementer("ORACLE", tablePrefix + "JOB_SEQ")).thenReturn(new StubIncrementer()); when(incrementerFactory.getIncrementer("ORACLE", tablePrefix + "JOB_EXECUTION_SEQ")) @@ -135,7 +135,7 @@ void testCustomLobHandler() throws Exception { factory.setDatabaseType("ORACLE"); - incrementerFactory = mock(DataFieldMaxValueIncrementerFactory.class); + incrementerFactory = mock(); when(incrementerFactory.isSupportedIncrementerType("ORACLE")).thenReturn(true); when(incrementerFactory.getIncrementer("ORACLE", tablePrefix + "JOB_SEQ")).thenReturn(new StubIncrementer()); when(incrementerFactory.getIncrementer("ORACLE", tablePrefix + "JOB_EXECUTION_SEQ")) @@ -158,7 +158,7 @@ void tesDefaultSerializer() throws Exception { factory.setDatabaseType("ORACLE"); - incrementerFactory = mock(DataFieldMaxValueIncrementerFactory.class); + incrementerFactory = mock(); when(incrementerFactory.isSupportedIncrementerType("ORACLE")).thenReturn(true); when(incrementerFactory.getIncrementer("ORACLE", tablePrefix + "JOB_SEQ")).thenReturn(new StubIncrementer()); when(incrementerFactory.getIncrementer("ORACLE", tablePrefix + "JOB_EXECUTION_SEQ")) @@ -178,7 +178,7 @@ void testCustomSerializer() throws Exception { factory.setDatabaseType("ORACLE"); - incrementerFactory = mock(DataFieldMaxValueIncrementerFactory.class); + incrementerFactory = mock(); when(incrementerFactory.isSupportedIncrementerType("ORACLE")).thenReturn(true); when(incrementerFactory.getIncrementer("ORACLE", tablePrefix + "JOB_SEQ")).thenReturn(new StubIncrementer()); when(incrementerFactory.getIncrementer("ORACLE", tablePrefix + "JOB_EXECUTION_SEQ")) @@ -199,7 +199,7 @@ void testDefaultJdbcOperations() throws Exception { factory.setDatabaseType("ORACLE"); - incrementerFactory = mock(DataFieldMaxValueIncrementerFactory.class); + incrementerFactory = mock(); when(incrementerFactory.isSupportedIncrementerType("ORACLE")).thenReturn(true); when(incrementerFactory.getIncrementer("ORACLE", tablePrefix + "JOB_SEQ")).thenReturn(new StubIncrementer()); when(incrementerFactory.getIncrementer("ORACLE", tablePrefix + "JOB_EXECUTION_SEQ")) @@ -219,7 +219,7 @@ void testCustomJdbcOperations() throws Exception { factory.setDatabaseType("ORACLE"); - incrementerFactory = mock(DataFieldMaxValueIncrementerFactory.class); + incrementerFactory = mock(); when(incrementerFactory.isSupportedIncrementerType("ORACLE")).thenReturn(true); when(incrementerFactory.getIncrementer("ORACLE", tablePrefix + "JOB_SEQ")).thenReturn(new StubIncrementer()); when(incrementerFactory.getIncrementer("ORACLE", tablePrefix + "JOB_EXECUTION_SEQ")) @@ -228,7 +228,7 @@ void testCustomJdbcOperations() throws Exception { .thenReturn(new StubIncrementer()); factory.setIncrementerFactory(incrementerFactory); - JdbcOperations customJdbcOperations = mock(JdbcOperations.class); + JdbcOperations customJdbcOperations = mock(); factory.setJdbcOperations(customJdbcOperations); factory.afterPropertiesSet(); @@ -313,7 +313,7 @@ void testTransactionAttributesForCreateMethod() throws Exception { DefaultTransactionDefinition.PROPAGATION_REQUIRES_NEW); transactionDefinition.setIsolationLevel(DefaultTransactionDefinition.ISOLATION_SERIALIZABLE); when(transactionManager.getTransaction(transactionDefinition)).thenReturn(null); - Connection conn = mock(Connection.class); + Connection conn = mock(); when(dataSource.getConnection()).thenReturn(conn); Exception exception = assertThrows(IllegalArgumentException.class, () -> repository.createJobExecution("foo", new JobParameters())); @@ -331,7 +331,7 @@ void testSetTransactionAttributesForCreateMethod() throws Exception { DefaultTransactionDefinition.PROPAGATION_REQUIRES_NEW); transactionDefinition.setIsolationLevel(DefaultTransactionDefinition.ISOLATION_READ_UNCOMMITTED); when(transactionManager.getTransaction(transactionDefinition)).thenReturn(null); - Connection conn = mock(Connection.class); + Connection conn = mock(); when(dataSource.getConnection()).thenReturn(conn); Exception exception = assertThrows(IllegalArgumentException.class, () -> repository.createJobExecution("foo", new JobParameters())); @@ -341,7 +341,7 @@ void testSetTransactionAttributesForCreateMethod() throws Exception { @Test public void testCustomTransactionAttributesSource() throws Exception { // given - TransactionAttributeSource transactionAttributeSource = Mockito.mock(TransactionAttributeSource.class); + TransactionAttributeSource transactionAttributeSource = Mockito.mock(); this.factory.setTransactionAttributeSource(transactionAttributeSource); // when diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/repository/support/SimpleJobRepositoryIntegrationTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/repository/support/SimpleJobRepositoryIntegrationTests.java index 53c33b178e..eb81dbd246 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/repository/support/SimpleJobRepositoryIntegrationTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/repository/support/SimpleJobRepositoryIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2008-2022 the original author or authors. + * Copyright 2008-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -32,12 +32,13 @@ import java.time.LocalDateTime; import java.time.temporal.ChronoUnit; -import java.util.Arrays; +import java.util.List; +import java.util.Map; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.fail; /** * Repository tests using JDBC DAOs (rather than mocks). @@ -152,11 +153,7 @@ void testGetStepExecutionCountAndLastStepExecution() throws Exception { @Transactional @Test void testSaveExecutionContext() throws Exception { - ExecutionContext ctx = new ExecutionContext() { - { - putLong("crashedPosition", 7); - } - }; + ExecutionContext ctx = new ExecutionContext(Map.of("crashedPosition", 7)); JobExecution jobExec = jobRepository.createJobExecution(job.getName(), jobParameters); jobExec.setStartTime(LocalDateTime.now()); jobExec.setExecutionContext(ctx); @@ -169,11 +166,6 @@ void testSaveExecutionContext() throws Exception { StepExecution retrievedStepExec = jobRepository.getLastStepExecution(jobExec.getJobInstance(), step.getName()); assertEquals(stepExec, retrievedStepExec); assertEquals(ctx, retrievedStepExec.getExecutionContext()); - - // JobExecution retrievedJobExec = - // jobRepository.getLastJobExecution(jobExec.getJobInstance()); - // assertEquals(jobExec, retrievedJobExec); - // assertEquals(ctx, retrievedJobExec.getExecutionContext()); } /* @@ -205,7 +197,7 @@ void testGetLastJobExecution() throws Exception { jobExecution = jobRepository.createJobExecution(job.getName(), jobParameters); StepExecution stepExecution = new StepExecution("step1", jobExecution); jobRepository.add(stepExecution); - jobExecution.addStepExecutions(Arrays.asList(stepExecution)); + jobExecution.addStepExecutions(List.of(stepExecution)); assertEquals(jobExecution, jobRepository.getLastJobExecution(job.getName(), jobParameters)); assertEquals(stepExecution, jobExecution.getStepExecutions().iterator().next()); } @@ -233,42 +225,41 @@ void testReExecuteWithSameJobParameters() throws Exception { */ @Transactional @Test - public void testReExecuteWithSameJobParametersWhenRunning() throws Exception { + void testReExecuteWithSameJobParametersWhenRunning() throws Exception { JobParameters jobParameters = new JobParametersBuilder().addString("stringKey", "stringValue") .toJobParameters(); // jobExecution with status STARTING JobExecution jobExecution = jobRepository.createJobExecution(job.getName(), jobParameters); - try { - jobRepository.createJobExecution(job.getName(), jobParameters); - fail(); - } - catch (JobExecutionAlreadyRunningException e) { - // expected - } + assertThrows(JobExecutionAlreadyRunningException.class, + () -> jobRepository.createJobExecution(job.getName(), jobParameters)); // jobExecution with status STARTED jobExecution.setStatus(BatchStatus.STARTED); jobExecution.setStartTime(LocalDateTime.now()); jobRepository.update(jobExecution); - try { - jobRepository.createJobExecution(job.getName(), jobParameters); - fail(); - } - catch (JobExecutionAlreadyRunningException e) { - // expected - } + assertThrows(JobExecutionAlreadyRunningException.class, + () -> jobRepository.createJobExecution(job.getName(), jobParameters)); // jobExecution with status STOPPING jobExecution.setStatus(BatchStatus.STOPPING); jobRepository.update(jobExecution); - try { - jobRepository.createJobExecution(job.getName(), jobParameters); - fail(); - } - catch (JobExecutionAlreadyRunningException e) { - // expected - } + assertThrows(JobExecutionAlreadyRunningException.class, + () -> jobRepository.createJobExecution(job.getName(), jobParameters)); + } + + @Transactional + @Test + void testDeleteJobInstance() throws Exception { + var jobParameters = new JobParametersBuilder().addString("foo", "bar").toJobParameters(); + var jobExecution = jobRepository.createJobExecution(job.getName(), jobParameters); + var stepExecution = new StepExecution("step", jobExecution); + jobRepository.add(stepExecution); + + jobRepository.deleteJobInstance(jobExecution.getJobInstance()); + + assertEquals(0, jobRepository.findJobInstancesByName(job.getName(), 0, 1).size()); + assertNull(jobRepository.getLastJobExecution(job.getName(), jobParameters)); } } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/repository/support/SimpleJobRepositoryTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/repository/support/SimpleJobRepositoryTests.java index 99d0429e42..5b903d0f14 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/repository/support/SimpleJobRepositoryTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/repository/support/SimpleJobRepositoryTests.java @@ -96,10 +96,10 @@ class SimpleJobRepositoryTests { @BeforeEach void setUp() { - jobExecutionDao = mock(JobExecutionDao.class); - jobInstanceDao = mock(JobInstanceDao.class); - stepExecutionDao = mock(StepExecutionDao.class); - ecDao = mock(ExecutionContextDao.class); + jobExecutionDao = mock(); + jobInstanceDao = mock(); + stepExecutionDao = mock(); + ecDao = mock(); jobRepository = new SimpleJobRepository(jobInstanceDao, jobExecutionDao, stepExecutionDao, ecDao); @@ -348,9 +348,9 @@ public void testGetJobInstanceWithNameAndParameters() { @Test void testDeleteJobExecution() { // given - StepExecution stepExecution1 = mock(StepExecution.class); - StepExecution stepExecution2 = mock(StepExecution.class); - JobExecution jobExecution = mock(JobExecution.class); + StepExecution stepExecution1 = mock(); + StepExecution stepExecution2 = mock(); + JobExecution jobExecution = mock(); when(jobExecution.getStepExecutions()).thenReturn(Arrays.asList(stepExecution1, stepExecution2)); // when @@ -369,9 +369,9 @@ void testDeleteJobExecution() { @Test void testDeleteJobInstance() { // given - JobExecution jobExecution1 = mock(JobExecution.class); - JobExecution jobExecution2 = mock(JobExecution.class); - JobInstance jobInstance = mock(JobInstance.class); + JobExecution jobExecution1 = mock(); + JobExecution jobExecution2 = mock(); + JobInstance jobInstance = mock(); when(this.jobExecutionDao.findJobExecutions(jobInstance)) .thenReturn(Arrays.asList(jobExecution1, jobExecution2)); diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/step/builder/AbstractTaskletStepBuilderTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/step/builder/AbstractTaskletStepBuilderTests.java new file mode 100644 index 0000000000..6cd6f2374e --- /dev/null +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/step/builder/AbstractTaskletStepBuilderTests.java @@ -0,0 +1,88 @@ +/* + * Copyright 2024 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.step.builder; + +import org.junit.jupiter.api.Test; + +import org.springframework.batch.core.repository.JobRepository; +import org.springframework.batch.core.step.tasklet.TaskletStep; +import org.springframework.batch.item.ItemProcessor; +import org.springframework.batch.item.ItemReader; +import org.springframework.batch.item.ItemWriter; +import org.springframework.batch.repeat.support.TaskExecutorRepeatTemplate; +import org.springframework.core.task.SimpleAsyncTaskExecutor; +import org.springframework.test.util.ReflectionTestUtils; +import org.springframework.transaction.PlatformTransactionManager; + +import static org.junit.jupiter.api.Assertions.assertInstanceOf; +import static org.mockito.Mockito.mock; + +/** + * Test cases for verifying the {@link AbstractTaskletStepBuilder} and faultTolerant() + * functionality. + * + * Issue: https://github.com/spring-projects/spring-batch/issues/4438 + * + * @author Ilpyo Yang + * @author Mahmoud Ben Hassine + */ +public class AbstractTaskletStepBuilderTests { + + private final JobRepository jobRepository = mock(JobRepository.class); + + private final PlatformTransactionManager transactionManager = mock(PlatformTransactionManager.class); + + private final int chunkSize = 10; + + private final ItemReader itemReader = mock(ItemReader.class); + + private final ItemProcessor itemProcessor = mock(ItemProcessor.class); + + private final ItemWriter itemWriter = mock(ItemWriter.class); + + private final SimpleAsyncTaskExecutor taskExecutor = new SimpleAsyncTaskExecutor(); + + @Test + void testSetTaskExecutorBeforeFaultTolerant() { + TaskletStep step = new StepBuilder("step-name", jobRepository) + . chunk(chunkSize, transactionManager) + .taskExecutor(taskExecutor) + .reader(itemReader) + .processor(itemProcessor) + .writer(itemWriter) + .faultTolerant() + .build(); + + Object stepOperations = ReflectionTestUtils.getField(step, "stepOperations"); + assertInstanceOf(TaskExecutorRepeatTemplate.class, stepOperations); + } + + @Test + void testSetTaskExecutorAfterFaultTolerant() { + TaskletStep step = new StepBuilder("step-name", jobRepository) + . chunk(chunkSize, transactionManager) + .reader(itemReader) + .processor(itemProcessor) + .writer(itemWriter) + .faultTolerant() + .taskExecutor(taskExecutor) + .build(); + + Object stepOperations = ReflectionTestUtils.getField(step, "stepOperations"); + assertInstanceOf(TaskExecutorRepeatTemplate.class, stepOperations); + } + +} diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/FaultTolerantChunkProcessorTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/FaultTolerantChunkProcessorTests.java index 5070b277a4..d30e06917e 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/FaultTolerantChunkProcessorTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/FaultTolerantChunkProcessorTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2008-2023 the original author or authors. + * Copyright 2008-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,6 +18,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; import java.util.ArrayList; @@ -97,6 +98,16 @@ public String process(String item) throws Exception { assertEquals(1, contribution.getFilterCount()); } + @Test + void testTransformChunkEnd() throws Exception { + Chunk inputs = new Chunk<>(Arrays.asList("1", "2")); + inputs.setEnd(); + processor.initializeUserData(inputs); + Chunk outputs = processor.transform(contribution, inputs); + assertEquals(Arrays.asList("1", "2"), outputs.getItems()); + assertTrue(outputs.isEnd()); + } + @Test void testFilterCountOnSkip() throws Exception { processor.setProcessSkipPolicy(new AlwaysSkipItemSkipPolicy()); diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/FaultTolerantStepFactoryBeanNonBufferingTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/FaultTolerantStepFactoryBeanNonBufferingTests.java index f775d86cf7..78e138272c 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/FaultTolerantStepFactoryBeanNonBufferingTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/FaultTolerantStepFactoryBeanNonBufferingTests.java @@ -88,7 +88,7 @@ void setUp() throws Exception { @Test void testSkip() throws Exception { @SuppressWarnings("unchecked") - SkipListener skipListener = mock(SkipListener.class); + SkipListener skipListener = mock(); skipListener.onSkipInWrite("3", exception); skipListener.onSkipInWrite("4", exception); diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/SimpleChunkProcessorTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/SimpleChunkProcessorTests.java index e9a7e0e678..5ebcb49ced 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/SimpleChunkProcessorTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/SimpleChunkProcessorTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2008-2023 the original author or authors. + * Copyright 2008-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,6 +16,7 @@ package org.springframework.batch.core.step.item; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; import java.util.ArrayList; import java.util.Arrays; @@ -76,4 +77,15 @@ void testProcess() throws Exception { assertEquals(2, contribution.getWriteCount()); } + @Test + void testTransform() throws Exception { + Chunk inputs = new Chunk<>(); + inputs.add("foo"); + inputs.add("bar"); + inputs.setEnd(); + Chunk outputs = processor.transform(contribution, inputs); + assertEquals(Arrays.asList("foo", "bar"), outputs.getItems()); + assertTrue(outputs.isEnd()); + } + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/step/job/DefaultJobParametersExtractorTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/step/job/DefaultJobParametersExtractorTests.java index 1f124694d1..c94a6d2de5 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/step/job/DefaultJobParametersExtractorTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/step/job/DefaultJobParametersExtractorTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2006-2022 the original author or authors. + * Copyright 2006-2023 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,10 +18,12 @@ import org.junit.jupiter.api.Test; import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.JobParameter; import org.springframework.batch.core.JobParameters; import org.springframework.batch.core.JobParametersBuilder; import org.springframework.batch.core.StepExecution; +import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; @@ -109,4 +111,25 @@ void testDontUseParentParameters() { assertNotNull(jobParameters.getParameter("foo").getValue()); } + @Test + public void testGetKeysFromParentParametersWhenNotInExecutionContext() { + DefaultJobParametersExtractor extractor = new DefaultJobParametersExtractor(); + extractor.setUseAllParentParameters(false); + + JobExecution jobExecution = new JobExecution(0L, + new JobParametersBuilder().addString("parentParam", "val").addDouble("foo", 22.2).toJobParameters()); + + StepExecution stepExecution = new StepExecution("step", jobExecution); + + stepExecution.getExecutionContext().put("foo", "11.1,java.lang.Double"); + extractor.setKeys(new String[] { "foo", "parentParam" }); + + JobParameters jobParameters = extractor.getJobParameters(null, stepExecution); + + assertThat(jobParameters.getParameter("parentParam")).isNotNull() + .extracting(JobParameter::getValue) + .isEqualTo("val"); + assertEquals(11.1, jobParameters.getDouble("foo")); + } + } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/step/tasklet/MethodInvokingTaskletAdapterTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/step/tasklet/MethodInvokingTaskletAdapterTests.java index 5adc41058a..246e91bdc1 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/step/tasklet/MethodInvokingTaskletAdapterTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/step/tasklet/MethodInvokingTaskletAdapterTests.java @@ -42,8 +42,8 @@ class MethodInvokingTaskletAdapterTests { @BeforeEach void setUp() { - stepContribution = new StepContribution(mock(StepExecution.class)); - chunkContext = mock(ChunkContext.class); + stepContribution = new StepContribution(mock()); + chunkContext = mock(); tasklet = new TestTasklet(); adapter = new MethodInvokingTaskletAdapter(); adapter.setTargetObject(tasklet); diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/step/tasklet/SystemCommandTaskletIntegrationTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/step/tasklet/SystemCommandTaskletIntegrationTests.java index f4b401ba3e..b703d91ee3 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/step/tasklet/SystemCommandTaskletIntegrationTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/step/tasklet/SystemCommandTaskletIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2008-2023 the original author or authors. + * Copyright 2008-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -292,8 +292,8 @@ private boolean isRunningOnWindows() { @Test public void testExecuteWithSuccessfulCommandRunnerMockExecution() throws Exception { StepContribution stepContribution = stepExecution.createStepContribution(); - CommandRunner commandRunner = mock(CommandRunner.class); - Process process = mock(Process.class); + CommandRunner commandRunner = mock(); + Process process = mock(); String[] command = new String[] { "invalid command" }; when(commandRunner.exec(eq(command), any(), any())).thenReturn(process); @@ -312,8 +312,8 @@ public void testExecuteWithSuccessfulCommandRunnerMockExecution() throws Excepti @Test public void testExecuteWithFailedCommandRunnerMockExecution() throws Exception { StepContribution stepContribution = stepExecution.createStepContribution(); - CommandRunner commandRunner = mock(CommandRunner.class); - Process process = mock(Process.class); + CommandRunner commandRunner = mock(); + Process process = mock(); String[] command = new String[] { "invalid command" }; when(commandRunner.exec(eq(command), any(), any())).thenReturn(process); @@ -323,9 +323,8 @@ public void testExecuteWithFailedCommandRunnerMockExecution() throws Exception { tasklet.setCommand(command); tasklet.afterPropertiesSet(); - RepeatStatus exitStatus = tasklet.execute(stepContribution, null); - - assertEquals(RepeatStatus.FINISHED, exitStatus); + Exception exception = assertThrows(SystemCommandException.class, () -> tasklet.execute(stepContribution, null)); + assertTrue(exception.getMessage().contains("failed with exit code")); assertEquals(ExitStatus.FAILED, stepContribution.getExitStatus()); } diff --git a/spring-batch-docs/pom.xml b/spring-batch-docs/pom.xml index f59eb521be..a437241444 100644 --- a/spring-batch-docs/pom.xml +++ b/spring-batch-docs/pom.xml @@ -4,7 +4,7 @@ org.springframework.batch spring-batch -5.0.3-SNAPSHOT +5.0.7-SNAPSHOT spring-batch-docs Spring Batch Docs diff --git a/spring-batch-docs/src/main/asciidoc/domain.adoc b/spring-batch-docs/src/main/asciidoc/domain.adoc index c544b10539..10f78d4284 100644 --- a/spring-batch-docs/src/main/asciidoc/domain.adoc +++ b/spring-batch-docs/src/main/asciidoc/domain.adoc @@ -557,6 +557,12 @@ As noted in the comment, `ecStep` does not equal `ecJob`. They are two different `ExecutionContexts`. The one scoped to the `Step` is saved at every commit point in the `Step`, whereas the one scoped to the Job is saved in between every `Step` execution. +NOTE: In the `ExecutionContext`, all non-transient entries must be `Serializable`. +Proper serialization of the execution context underpins the restart capability of steps and jobs. +Should you use keys or values that are not natively serializable, you are required to +employ a tailored serialization approach. Failing to serialize the execution context +may jeopardize the state persistence process, making failed jobs impossible to recover properly. + === JobRepository `JobRepository` is the persistence mechanism for all of the stereotypes mentioned earlier. diff --git a/spring-batch-docs/src/main/asciidoc/images/meta-data-erd.png b/spring-batch-docs/src/main/asciidoc/images/meta-data-erd.png old mode 100755 new mode 100644 index ff099a67c4..4c2a858131 Binary files a/spring-batch-docs/src/main/asciidoc/images/meta-data-erd.png and b/spring-batch-docs/src/main/asciidoc/images/meta-data-erd.png differ diff --git a/spring-batch-docs/src/main/asciidoc/job.adoc b/spring-batch-docs/src/main/asciidoc/job.adoc index 94f3aab23c..91049567d7 100644 --- a/spring-batch-docs/src/main/asciidoc/job.adoc +++ b/spring-batch-docs/src/main/asciidoc/job.adoc @@ -449,6 +449,7 @@ public class MyJobConfiguration { return new JdbcTransactionManager(dataSource); } + @Bean public Job job(JobRepository jobRepository) { return new JobBuilder("myJob", jobRepository) //define job flow as needed diff --git a/spring-batch-docs/src/main/asciidoc/scalability.adoc b/spring-batch-docs/src/main/asciidoc/scalability.adoc index 4a387f8e5b..6d8928fa24 100644 --- a/spring-batch-docs/src/main/asciidoc/scalability.adoc +++ b/spring-batch-docs/src/main/asciidoc/scalability.adoc @@ -121,6 +121,29 @@ Note also that there may be limits placed on concurrency by any pooled resources your step, such as a `DataSource`. Be sure to make the pool in those resources at least as large as the desired number of concurrent threads in the step. +[WARNING] +.Throttle limit deprecation +==== +As of v5.0, the throttle limit is deprecated with no replacement. If you want to replace the +current throttling mechanism in the default `TaskExecutorRepeatTemplate`, you need to provide +a custom `RepeatOperations` implementation (based on a `TaskExecutor` with a bounded task queue) +and set it on the step with `StepBuilder#stepOperations`: + +.Java Configuration +[source, java] +---- +@Bean +public Step sampleStep(RepeatOperations customRepeatOperations, JobRepository jobRepository, PlatformTransactionManager transactionManager) { + return new StepBuilder("sampleStep", jobRepository) + .chunk(10, transactionManager) + .reader(itemReader()) + .writer(itemWriter()) + .stepOperations(customRepeatOperations) + .build(); +} +---- +==== + There are some practical limitations of using multi-threaded `Step` implementations for some common batch use cases. Many participants in a `Step` (such as readers and writers) are stateful. If the state is not segregated by thread, those components are not @@ -315,8 +338,8 @@ configuration: [source, java, role="javaContent"] ---- @Bean -public Step step1Manager() { - return stepBuilderFactory.get("step1.manager") +public Step step1Manager(JobRepository jobRepository) { + return new StepBuilder("step1.manager", jobRepository) . partitioner("step1", partitioner()) .step(step1()) .gridSize(10) diff --git a/spring-batch-docs/src/main/asciidoc/step.adoc b/spring-batch-docs/src/main/asciidoc/step.adoc index 9825377c7f..4c746bffe7 100644 --- a/spring-batch-docs/src/main/asciidoc/step.adoc +++ b/spring-batch-docs/src/main/asciidoc/step.adoc @@ -1184,9 +1184,10 @@ public interface ItemWriteListener extends StepListener { ---- The `beforeWrite` method is called before `write` on the `ItemWriter` and is handed the -list of items that is written. The `afterWrite` method is called after the item has been -successfully written. If there was an error while writing, the `onWriteError` method is -called. The exception encountered and the item that was attempted to be written are +list of items that is written. The `afterWrite` method is called after the items have been +successfully written, but before committing the transaction associated with the chunk's processing. +If there was an error while writing, the `onWriteError` method is called. +The exception encountered and the item that was attempted to be written are provided, so that they can be logged. The annotations corresponding to this interface are: @@ -1373,7 +1374,7 @@ public class FileDeletingTasklet implements Tasklet, InitializingBean { public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception { File dir = directory.getFile(); - Assert.state(dir.isDirectory()); + Assert.state(dir.isDirectory(), "The resource must be a directory"); File[] files = dir.listFiles(); for (int i = 0; i < files.length; i++) { @@ -1391,7 +1392,7 @@ public class FileDeletingTasklet implements Tasklet, InitializingBean { } public void afterPropertiesSet() throws Exception { - Assert.state(directory != null, "directory must be set"); + Assert.state(directory != null, "Directory must be set"); } } ---- @@ -1689,14 +1690,14 @@ the condition of the execution having skipped records, as the following example [source, java] ---- -public class SkipCheckingListener extends StepExecutionListenerSupport { +public class SkipCheckingListener implements StepExecutionListener { + @Override public ExitStatus afterStep(StepExecution stepExecution) { String exitCode = stepExecution.getExitStatus().getExitCode(); if (!exitCode.equals(ExitStatus.FAILED.getExitCode()) && - stepExecution.getSkipCount() > 0) { + stepExecution.getSkipCount() > 0) { return new ExitStatus("COMPLETED WITH SKIPS"); - } - else { + } else { return null; } } diff --git a/spring-batch-infrastructure/pom.xml b/spring-batch-infrastructure/pom.xml index 432a276385..3dc7b43bb2 100644 --- a/spring-batch-infrastructure/pom.xml +++ b/spring-batch-infrastructure/pom.xml @@ -4,7 +4,7 @@org.springframework.batch spring-batch -5.0.3-SNAPSHOT +5.0.7-SNAPSHOT spring-batch-infrastructure jar diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/Chunk.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/Chunk.java index 4cdfa1c7e6..aababa36c2 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/Chunk.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/Chunk.java @@ -1,5 +1,5 @@ /* - * Copyright 2006-2023 the original author or authors. + * Copyright 2006-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -154,6 +154,13 @@ public int size() { /** * Flag to indicate if the source data is exhausted. + * + *+ * Note: This may return false if the last chunk has the same number of items as the + * configured commit interval. Consequently, in such cases,there will be a last empty + * chunk that won't be processed. It is recommended to consider this behavior when + * utilizing this method. + *
* @return true if there is no more data to process */ public boolean isEnd() { diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ExecutionContext.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ExecutionContext.java index 49f0d348fb..393e31da42 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ExecutionContext.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/ExecutionContext.java @@ -29,8 +29,9 @@ * that allows optionally for type safety on reads. It also allows for dirty checking by * setting a 'dirty' flag whenever any put is called. *- * Note that putting
* diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/support/RepeatTemplate.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/support/RepeatTemplate.java index 4e81315d14..7b7af3fc68 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/support/RepeatTemplate.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/support/RepeatTemplate.java @@ -286,8 +286,15 @@ private void doHandle(Throwable throwable, RepeatContext context, Collectionnull
value is equivalent to removing the entry for the - * given key. + * Non-transient entries should be serializable, otherwise a custom serializer should be + * used. Note that puttingnull
value is equivalent to removing the entry for + * the given key. * * @author Lucas Ward * @author Douglas Kaminsky diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/SimpleBinaryBufferedReaderFactory.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/SimpleBinaryBufferedReaderFactory.java index 098ff06eb5..2ec50d2dc8 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/SimpleBinaryBufferedReaderFactory.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/SimpleBinaryBufferedReaderFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2006-2023 the original author or authors. + * Copyright 2006-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -114,25 +114,24 @@ private boolean isEndOfLine(StringBuilder buffer, StringBuilder candidate, int n } char c = (char) next; - if (ending.charAt(0) == c || candidate.length() > 0) { + if (ending.charAt(0) == c || !candidate.isEmpty()) { candidate.append(c); } - - if (candidate.length() == 0) { + else { buffer.append(c); return false; } - boolean end = ending.equals(candidate.toString()); - if (end) { + if (ending.contentEquals(candidate)) { candidate.delete(0, candidate.length()); + return true; } - else if (candidate.length() >= ending.length()) { - buffer.append(candidate); - candidate.delete(0, candidate.length()); + while (!ending.startsWith(candidate.toString())) { + buffer.append(candidate.charAt(0)); + candidate.delete(0, 1); } - return end; + return false; } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/DefaultFieldSet.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/DefaultFieldSet.java index c0e833831c..4ec95e4d53 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/DefaultFieldSet.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/DefaultFieldSet.java @@ -33,9 +33,9 @@ import org.springframework.util.StringUtils; /** - * Default implementation of {@link FieldSet} using Java using Java primitive and standard - * types and utilities. Strings are trimmed before parsing by default, and so are plain - * String values. + * Default implementation of {@link FieldSet} using Java primitive and standard types and + * utilities. Strings are trimmed before parsing by default, and so are plain String + * values. * * @author Rob Harrop * @author Dave Syer @@ -65,8 +65,8 @@ public class DefaultFieldSet implements FieldSet { private Listnames; /** - * The {@link NumberFormat} to use for parsing numbers. If unset the US locale will be - * used ('.' as decimal place). + * The {@link NumberFormat} to use for parsing numbers. If unset the {@link Locale#US} + * will be used ('.' as decimal place). * @param numberFormat the {@link NumberFormat} to use for number parsing */ public final void setNumberFormat(NumberFormat numberFormat) { @@ -78,8 +78,8 @@ public final void setNumberFormat(NumberFormat numberFormat) { } /** - * The {@link DateFormat} to use for parsing numbers. If unset the default pattern is - * ISO standard yyyy/MM/dd
. + * The {@link DateFormat} to use for parsing dates. If unset the default pattern is + * ISO standardyyyy-MM-dd
. * @param dateFormat the {@link DateFormat} to use for date parsing */ public void setDateFormat(DateFormat dateFormat) { diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/DefaultFieldSetFactory.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/DefaultFieldSetFactory.java index 7ef0fca1bb..a958f50a1f 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/DefaultFieldSetFactory.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/DefaultFieldSetFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2009-2012 the original author or authors. + * Copyright 2009-2023 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,6 +23,7 @@ * {@link FieldSet} required. Returns a {@link DefaultFieldSet} from both factory methods. * * @author Dave Syer + * @author Mahmoud Ben Hassine * */ public class DefaultFieldSetFactory implements FieldSetFactory { @@ -32,8 +33,8 @@ public class DefaultFieldSetFactory implements FieldSetFactory { private NumberFormat numberFormat; /** - * The {@link NumberFormat} to use for parsing numbers. If unset the default locale - * will be used. + * The {@link NumberFormat} to use for parsing numbers. If unset then + * {@link java.util.Locale#US} will be used. * @param numberFormat the {@link NumberFormat} to use for number parsing */ public void setNumberFormat(NumberFormat numberFormat) { @@ -41,8 +42,8 @@ public void setNumberFormat(NumberFormat numberFormat) { } /** - * The {@link DateFormat} to use for parsing numbers. If unset the default pattern is - * ISO standardyyyy/MM/dd
. + * The {@link DateFormat} to use for parsing dates. If unset the default pattern is + * ISO standardyyyy-MM-dd
. * @param dateFormat the {@link DateFormat} to use for date parsing */ public void setDateFormat(DateFormat dateFormat) { diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/mail/SimpleMailMessageItemWriter.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/mail/SimpleMailMessageItemWriter.java index 1964276b72..65cf843acb 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/mail/SimpleMailMessageItemWriter.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/mail/SimpleMailMessageItemWriter.java @@ -1,5 +1,5 @@ /* - * Copyright 2006-2022 the original author or authors. + * Copyright 2006-2023 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -40,8 +40,8 @@ * Delegates the actual sending of messages to a {@link MailSender}, using the batch * method {@link MailSender#send(SimpleMailMessage[])}, which normally uses a single * server connection for the whole batch (depending on the implementation). The efficiency - * of for large volumes of messages (repeated calls to the item writer) might be improved - * by the use of a special {@link MailSender} that caches connections to the server in + * for large volumes of messages (repeated calls to the item writer) might be improved by + * the use of a special {@link MailSender} that caches connections to the server in * between calls. *{ }); - Session session = mock(Session.class); - MessageConsumer consumer = mock(MessageConsumer.class); - Message message = mock(Message.class); + Session session = mock(); + MessageConsumer consumer = mock(); + Message message = mock(); // Expect two calls to consumer (chunk size)... when(session.getTransacted()).thenReturn(true); @@ -73,8 +73,8 @@ void testReceiveAndExecuteWithCallbackReturningNull() throws Exception { template.setCompletionPolicy(new SimpleCompletionPolicy(2)); container = getContainer(template); - Session session = mock(Session.class); - MessageConsumer consumer = mock(MessageConsumer.class); + Session session = mock(); + MessageConsumer consumer = mock(); Message message = null; // Expect one call to consumer (chunk size is 2 but terminates on @@ -119,7 +119,7 @@ void testNonTransactionalReceiveAndExecuteWithCallbackThrowingError() throws Exc } private BatchMessageListenerContainer getContainer(RepeatTemplate template) { - ConnectionFactory connectionFactory = mock(ConnectionFactory.class); + ConnectionFactory connectionFactory = mock(); // Yuck: we need to turn these method in base class to no-ops because the invoker // is a private class // we can't create for test purposes... @@ -151,9 +151,9 @@ private boolean doTestWithException(final Throwable t, boolean expectRollback, i throw (Error) t; }); - Session session = mock(Session.class); - MessageConsumer consumer = mock(MessageConsumer.class); - Message message = mock(Message.class); + Session session = mock(); + MessageConsumer consumer = mock(); + Message message = mock(); if (expectGetTransactionCount > 0) { when(session.getTransacted()).thenReturn(true); diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/amqp/AmqpItemReaderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/amqp/AmqpItemReaderTests.java index 3838ef6463..a941cd276b 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/amqp/AmqpItemReaderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/amqp/AmqpItemReaderTests.java @@ -44,7 +44,7 @@ void testNullAmqpTemplate() { @Test void testNoItemType() { - final AmqpTemplate amqpTemplate = mock(AmqpTemplate.class); + final AmqpTemplate amqpTemplate = mock(); when(amqpTemplate.receiveAndConvert()).thenReturn("foo"); final AmqpItemReader amqpItemReader = new AmqpItemReader<>(amqpTemplate); @@ -53,7 +53,7 @@ void testNoItemType() { @Test void testNonMessageItemType() { - final AmqpTemplate amqpTemplate = mock(AmqpTemplate.class); + final AmqpTemplate amqpTemplate = mock(); when(amqpTemplate.receiveAndConvert()).thenReturn("foo"); final AmqpItemReader amqpItemReader = new AmqpItemReader<>(amqpTemplate); @@ -65,8 +65,8 @@ void testNonMessageItemType() { @Test void testMessageItemType() { - final AmqpTemplate amqpTemplate = mock(AmqpTemplate.class); - final Message message = mock(Message.class); + final AmqpTemplate amqpTemplate = mock(); + final Message message = mock(); when(amqpTemplate.receive()).thenReturn(message); @@ -79,7 +79,7 @@ void testMessageItemType() { @Test void testTypeMismatch() { - final AmqpTemplate amqpTemplate = mock(AmqpTemplate.class); + final AmqpTemplate amqpTemplate = mock(); when(amqpTemplate.receiveAndConvert()).thenReturn("foo"); @@ -93,7 +93,7 @@ void testTypeMismatch() { @Test void testNullItemType() { - final AmqpTemplate amqpTemplate = mock(AmqpTemplate.class); + final AmqpTemplate amqpTemplate = mock(); final AmqpItemReader amqpItemReader = new AmqpItemReader<>(amqpTemplate); assertThrows(IllegalArgumentException.class, () -> amqpItemReader.setItemType(null)); diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/amqp/AmqpItemWriterTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/amqp/AmqpItemWriterTests.java index eb81d9139e..49b505c3a0 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/amqp/AmqpItemWriterTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/amqp/AmqpItemWriterTests.java @@ -42,7 +42,7 @@ void testNullAmqpTemplate() { @Test void voidTestWrite() throws Exception { - AmqpTemplate amqpTemplate = mock(AmqpTemplate.class); + AmqpTemplate amqpTemplate = mock(); amqpTemplate.convertAndSend("foo"); diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/amqp/builder/AmqpItemReaderBuilderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/amqp/builder/AmqpItemReaderBuilderTests.java index 40efe3f763..bba60288b7 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/amqp/builder/AmqpItemReaderBuilderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/amqp/builder/AmqpItemReaderBuilderTests.java @@ -59,7 +59,7 @@ void testNonMessageItemType() { @Test void testMessageItemType() { - final Message message = mock(Message.class); + final Message message = mock(); when(this.amqpTemplate.receive()).thenReturn(message); diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/amqp/builder/AmqpItemWriterBuilderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/amqp/builder/AmqpItemWriterBuilderTests.java index 493c8f4368..c5bc741ce7 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/amqp/builder/AmqpItemWriterBuilderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/amqp/builder/AmqpItemWriterBuilderTests.java @@ -43,7 +43,7 @@ void testNullAmqpTemplate() { @Test void voidTestWrite() throws Exception { - AmqpTemplate amqpTemplate = mock(AmqpTemplate.class); + AmqpTemplate amqpTemplate = mock(); AmqpItemWriter amqpItemWriter = new AmqpItemWriterBuilder ().amqpTemplate(amqpTemplate).build(); amqpItemWriter.write(Chunk.of("foo", "bar")); diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/data/MongoItemWriterTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/data/MongoItemWriterTests.java index 208ceb3bb8..eaedf43165 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/data/MongoItemWriterTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/data/MongoItemWriterTests.java @@ -252,9 +252,9 @@ void testResourceKeyCollision() { final String[] results = new String[limit]; for (int i = 0; i < limit; i++) { final int index = i; - MongoOperations mongoOperations = mock(MongoOperations.class); - BulkOperations bulkOperations = mock(BulkOperations.class); - MongoConverter mongoConverter = mock(MongoConverter.class); + MongoOperations mongoOperations = mock(); + BulkOperations bulkOperations = mock(); + MongoConverter mongoConverter = mock(); when(mongoOperations.bulkOps(any(), any(Class.class))).thenReturn(bulkOperations); when(mongoOperations.getConverter()).thenReturn(mongoConverter); diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/data/RepositoryItemReaderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/data/RepositoryItemReaderTests.java index 70b49f668a..8513ebf26f 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/data/RepositoryItemReaderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/data/RepositoryItemReaderTests.java @@ -228,7 +228,7 @@ void testInvalidMethodName() { @Test void testDifferentTypes() throws Exception { - TestRepository differentRepository = mock(TestRepository.class); + TestRepository differentRepository = mock(); RepositoryItemReader reader = new RepositoryItemReader<>(); sorts = Collections.singletonMap("id", Direction.ASC); reader.setRepository(differentRepository); diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/ExtendedConnectionDataSourceProxyTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/ExtendedConnectionDataSourceProxyTests.java index 0439f2ad22..dc362b28ce 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/ExtendedConnectionDataSourceProxyTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/ExtendedConnectionDataSourceProxyTests.java @@ -48,8 +48,8 @@ class ExtendedConnectionDataSourceProxyTests { @Test void testOperationWithDataSourceUtils() throws SQLException { - Connection con = mock(Connection.class); - DataSource ds = mock(DataSource.class); + Connection con = mock(); + DataSource ds = mock(); when(ds.getConnection()).thenReturn(con); // con1 con.close(); @@ -94,8 +94,8 @@ void testOperationWithDataSourceUtils() throws SQLException { @Test void testOperationWithDirectCloseCall() throws SQLException { - Connection con = mock(Connection.class); - DataSource ds = mock(DataSource.class); + Connection con = mock(); + DataSource ds = mock(); when(ds.getConnection()).thenReturn(con); // con1 con.close(); @@ -126,10 +126,10 @@ void testOperationWithDirectCloseCall() throws SQLException { @Test void testSuppressOfCloseWithJdbcTemplate() throws Exception { - Connection con = mock(Connection.class); - DataSource ds = mock(DataSource.class); - Statement stmt = mock(Statement.class); - ResultSet rs = mock(ResultSet.class); + Connection con = mock(); + DataSource ds = mock(); + Statement stmt = mock(); + ResultSet rs = mock(); // open and start suppressing close when(ds.getConnection()).thenReturn(con); diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/HibernateCursorItemReaderStatefulIntegrationTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/HibernateCursorItemReaderStatefulIntegrationTests.java index 714295a12b..cc361b11f3 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/HibernateCursorItemReaderStatefulIntegrationTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/HibernateCursorItemReaderStatefulIntegrationTests.java @@ -44,9 +44,9 @@ protected boolean isUseStatelessSession() { @SuppressWarnings("unchecked") void testStatefulClose() { - SessionFactory sessionFactory = mock(SessionFactory.class); - Session session = mock(Session.class); - Query scrollableResults = mock(Query.class); + SessionFactory sessionFactory = mock(); + Session session = mock(); + Query scrollableResults = mock(); HibernateCursorItemReader itemReader = new HibernateCursorItemReader<>(); itemReader.setSessionFactory(sessionFactory); itemReader.setQueryString("testQuery"); diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/HibernateItemReaderHelperTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/HibernateItemReaderHelperTests.java index 85ed47e53e..fd2d54f75e 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/HibernateItemReaderHelperTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/HibernateItemReaderHelperTests.java @@ -36,12 +36,12 @@ class HibernateItemReaderHelperTests { private final HibernateItemReaderHelper helper = new HibernateItemReaderHelper<>(); - private final SessionFactory sessionFactory = mock(SessionFactory.class); + private final SessionFactory sessionFactory = mock(); @Test void testOneSessionForAllPages() { - StatelessSession session = mock(StatelessSession.class); + StatelessSession session = mock(); when(sessionFactory.openStatelessSession()).thenReturn(session); helper.setSessionFactory(sessionFactory); @@ -55,7 +55,7 @@ void testOneSessionForAllPages() { @Test void testSessionReset() { - StatelessSession session = mock(StatelessSession.class); + StatelessSession session = mock(); when(sessionFactory.openStatelessSession()).thenReturn(session); helper.setSessionFactory(sessionFactory); diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/HibernateItemWriterTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/HibernateItemWriterTests.java index f95791a721..9d4272130f 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/HibernateItemWriterTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/HibernateItemWriterTests.java @@ -46,8 +46,8 @@ class HibernateItemWriterTests { @BeforeEach void setUp() { writer = new HibernateItemWriter<>(); - factory = mock(SessionFactory.class); - currentSession = mock(Session.class); + factory = mock(); + currentSession = mock(); when(this.factory.getCurrentSession()).thenReturn(this.currentSession); } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcBatchItemWriterClassicTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcBatchItemWriterClassicTests.java index a9b49f588a..bc5eb0cc7a 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcBatchItemWriterClassicTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcBatchItemWriterClassicTests.java @@ -55,7 +55,7 @@ class JdbcBatchItemWriterClassicTests { @BeforeEach void setUp() { - ps = mock(PreparedStatement.class); + ps = mock(); jdbcTemplate = new JdbcTemplate() { @Override public T execute(String sql, PreparedStatementCallback action) throws DataAccessException { diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcBatchItemWriterNamedParameterTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcBatchItemWriterNamedParameterTests.java index 33e1ee9ae7..5cf270059c 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcBatchItemWriterNamedParameterTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcBatchItemWriterNamedParameterTests.java @@ -85,7 +85,7 @@ public void setBar(String bar) { @BeforeEach void setUp() { - namedParameterJdbcOperations = mock(NamedParameterJdbcOperations.class); + namedParameterJdbcOperations = mock(); writer.setSql(sql); writer.setJdbcTemplate(namedParameterJdbcOperations); writer.setItemSqlParameterSourceProvider(new BeanPropertyItemSqlParameterSourceProvider<>()); diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcCursorItemReaderConfigTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcCursorItemReaderConfigTests.java index 978ff3534d..0a63671333 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcCursorItemReaderConfigTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JdbcCursorItemReaderConfigTests.java @@ -41,10 +41,10 @@ class JdbcCursorItemReaderConfigTests { */ @Test void testUsesCurrentTransaction() throws Exception { - DataSource ds = mock(DataSource.class); - Connection con = mock(Connection.class); + DataSource ds = mock(); + Connection con = mock(); when(con.getAutoCommit()).thenReturn(false); - PreparedStatement ps = mock(PreparedStatement.class); + PreparedStatement ps = mock(); when(con.prepareStatement("select foo from bar", ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY, ResultSet.HOLD_CURSORS_OVER_COMMIT)) .thenReturn(ps); @@ -71,10 +71,10 @@ void testUsesCurrentTransaction() throws Exception { @Test void testUsesItsOwnTransaction() throws Exception { - DataSource ds = mock(DataSource.class); - Connection con = mock(Connection.class); + DataSource ds = mock(); + Connection con = mock(); when(con.getAutoCommit()).thenReturn(false); - PreparedStatement ps = mock(PreparedStatement.class); + PreparedStatement ps = mock(); when(con.prepareStatement("select foo from bar", ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY)) .thenReturn(ps); when(ds.getConnection()).thenReturn(con); @@ -98,10 +98,10 @@ void testOverrideConnectionAutoCommit() throws Exception { boolean initialAutoCommit = false; boolean neededAutoCommit = true; - DataSource ds = mock(DataSource.class); - Connection con = mock(Connection.class); + DataSource ds = mock(); + Connection con = mock(); when(con.getAutoCommit()).thenReturn(initialAutoCommit); - PreparedStatement ps = mock(PreparedStatement.class); + PreparedStatement ps = mock(); when(con.prepareStatement("select foo from bar", ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY)) .thenReturn(ps); when(ds.getConnection()).thenReturn(con); diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JpaItemWriterTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JpaItemWriterTests.java index cab71bf656..d5a8fdffad 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JpaItemWriterTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/JpaItemWriterTests.java @@ -51,7 +51,7 @@ void setUp() { TransactionSynchronizationManager.clearSynchronization(); } writer = new JpaItemWriter<>(); - emf = mock(EntityManagerFactory.class, "emf"); + emf = mock(); writer.setEntityManagerFactory(emf); } @@ -65,7 +65,7 @@ void testAfterPropertiesSet() { @Test void testWriteAndFlushSunnyDay() { - EntityManager em = mock(EntityManager.class, "em"); + EntityManager em = mock(); em.contains("foo"); em.contains("bar"); em.merge("bar"); @@ -82,7 +82,7 @@ void testWriteAndFlushSunnyDay() { @Test void testPersist() { writer.setUsePersist(true); - EntityManager em = mock(EntityManager.class, "em"); + EntityManager em = mock(); TransactionSynchronizationManager.bindResource(emf, new EntityManagerHolder(em)); Chunk chunk = Chunk.of("persist1", "persist2"); writer.write(chunk); @@ -94,7 +94,7 @@ void testPersist() { @Test void testWriteAndFlushWithFailure() { final RuntimeException ex = new RuntimeException("ERROR"); - EntityManager em = mock(EntityManager.class, "em"); + EntityManager em = mock(); em.contains("foo"); em.contains("bar"); em.merge("bar"); diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/StoredprocedureItemReaderConfigTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/StoredprocedureItemReaderConfigTests.java index 50a02a9c04..c561addcfe 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/StoredprocedureItemReaderConfigTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/StoredprocedureItemReaderConfigTests.java @@ -41,14 +41,14 @@ class StoredprocedureItemReaderConfigTests { */ @Test void testUsesCurrentTransaction() throws Exception { - DataSource ds = mock(DataSource.class); - DatabaseMetaData dmd = mock(DatabaseMetaData.class); + DataSource ds = mock(); + DatabaseMetaData dmd = mock(); when(dmd.getDatabaseProductName()).thenReturn("Oracle"); - Connection con = mock(Connection.class); + Connection con = mock(); when(con.getMetaData()).thenReturn(dmd); when(con.getMetaData()).thenReturn(dmd); when(con.getAutoCommit()).thenReturn(false); - CallableStatement cs = mock(CallableStatement.class); + CallableStatement cs = mock(); when(con.prepareCall("{call foo_bar()}", ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY, ResultSet.HOLD_CURSORS_OVER_COMMIT)) .thenReturn(cs); @@ -75,14 +75,14 @@ void testUsesCurrentTransaction() throws Exception { @Test void testUsesItsOwnTransaction() throws Exception { - DataSource ds = mock(DataSource.class); - DatabaseMetaData dmd = mock(DatabaseMetaData.class); + DataSource ds = mock(); + DatabaseMetaData dmd = mock(); when(dmd.getDatabaseProductName()).thenReturn("Oracle"); - Connection con = mock(Connection.class); + Connection con = mock(); when(con.getMetaData()).thenReturn(dmd); when(con.getMetaData()).thenReturn(dmd); when(con.getAutoCommit()).thenReturn(false); - CallableStatement cs = mock(CallableStatement.class); + CallableStatement cs = mock(); when(con.prepareCall("{call foo_bar()}", ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY)) .thenReturn(cs); when(ds.getConnection()).thenReturn(con); @@ -107,14 +107,14 @@ void testUsesItsOwnTransaction() throws Exception { @Test void testHandlesRefCursorPosition() throws Exception { - DataSource ds = mock(DataSource.class); - DatabaseMetaData dmd = mock(DatabaseMetaData.class); + DataSource ds = mock(); + DatabaseMetaData dmd = mock(); when(dmd.getDatabaseProductName()).thenReturn("Oracle"); - Connection con = mock(Connection.class); + Connection con = mock(); when(con.getMetaData()).thenReturn(dmd); when(con.getMetaData()).thenReturn(dmd); when(con.getAutoCommit()).thenReturn(false); - CallableStatement cs = mock(CallableStatement.class); + CallableStatement cs = mock(); when(con.prepareCall("{call foo_bar(?, ?)}", ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY)) .thenReturn(cs); when(ds.getConnection()).thenReturn(con); diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/builder/StoredProcedureItemReaderBuilderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/builder/StoredProcedureItemReaderBuilderTests.java index 57bf5d0322..b522f2b9be 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/builder/StoredProcedureItemReaderBuilderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/builder/StoredProcedureItemReaderBuilderTests.java @@ -38,7 +38,7 @@ */ class StoredProcedureItemReaderBuilderTests { - private final DataSource dataSource = Mockito.mock(DataSource.class); + private final DataSource dataSource = Mockito.mock(); @Test void testConfiguration() { diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/orm/JpaNamedQueryProviderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/orm/JpaNamedQueryProviderTests.java index 3e98b2e875..ac659c8f31 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/orm/JpaNamedQueryProviderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/orm/JpaNamedQueryProviderTests.java @@ -69,8 +69,8 @@ void testJpaNamedQueryProviderEntityClassIsProvided() { void testNamedQueryCreation() throws Exception { // given String namedQuery = "allFoos"; - TypedQuery query = mock(TypedQuery.class); - EntityManager entityManager = Mockito.mock(EntityManager.class); + TypedQuery query = mock(); + EntityManager entityManager = Mockito.mock(); when(entityManager.createNamedQuery(namedQuery, Foo.class)).thenReturn(query); JpaNamedQueryProvider jpaNamedQueryProvider = new JpaNamedQueryProvider<>(); jpaNamedQueryProvider.setEntityManager(entityManager); diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/ColumnMapExecutionContextRowMapperTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/ColumnMapExecutionContextRowMapperTests.java index da677d07a7..8a05a6a09f 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/ColumnMapExecutionContextRowMapperTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/ColumnMapExecutionContextRowMapperTests.java @@ -39,7 +39,7 @@ class ColumnMapExecutionContextRowMapperTests { @BeforeEach void setUp() { - ps = mock(PreparedStatement.class); + ps = mock(); mapper = new ColumnMapItemPreparedStatementSetter(); key = new LinkedHashMap<>(2); diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/DefaultDataFieldMaxValueIncrementerFactoryTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/DefaultDataFieldMaxValueIncrementerFactoryTests.java index 542714a12d..f819ff06d1 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/DefaultDataFieldMaxValueIncrementerFactoryTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/DefaultDataFieldMaxValueIncrementerFactoryTests.java @@ -48,7 +48,7 @@ class DefaultDataFieldMaxValueIncrementerFactoryTests { @BeforeEach void setUp() { - DataSource dataSource = mock(DataSource.class); + DataSource dataSource = mock(); factory = new DefaultDataFieldMaxValueIncrementerFactory(dataSource); } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/DerbyPagingQueryProviderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/DerbyPagingQueryProviderTests.java index f2be2f7437..5bd891ddfa 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/DerbyPagingQueryProviderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/DerbyPagingQueryProviderTests.java @@ -43,9 +43,9 @@ class DerbyPagingQueryProviderTests extends AbstractSqlPagingQueryProviderTests @Test void testInit() throws Exception { - DataSource ds = mock(DataSource.class); - Connection con = mock(Connection.class); - DatabaseMetaData dmd = mock(DatabaseMetaData.class); + DataSource ds = mock(); + Connection con = mock(); + DatabaseMetaData dmd = mock(); when(dmd.getDatabaseProductVersion()).thenReturn("10.4.1.3"); when(con.getMetaData()).thenReturn(dmd); when(ds.getConnection()).thenReturn(con); @@ -54,9 +54,9 @@ void testInit() throws Exception { @Test void testInitWithRecentVersion() throws Exception { - DataSource ds = mock(DataSource.class); - Connection con = mock(Connection.class); - DatabaseMetaData dmd = mock(DatabaseMetaData.class); + DataSource ds = mock(); + Connection con = mock(); + DatabaseMetaData dmd = mock(); when(dmd.getDatabaseProductVersion()).thenReturn("10.10.1.1"); when(con.getMetaData()).thenReturn(dmd); when(ds.getConnection()).thenReturn(con); @@ -65,9 +65,9 @@ void testInitWithRecentVersion() throws Exception { @Test void testInitWithUnsupportedVersion() throws Exception { - DataSource ds = mock(DataSource.class); - Connection con = mock(Connection.class); - DatabaseMetaData dmd = mock(DatabaseMetaData.class); + DataSource ds = mock(); + Connection con = mock(); + DatabaseMetaData dmd = mock(); when(dmd.getDatabaseProductVersion()).thenReturn("10.2.9.9"); when(con.getMetaData()).thenReturn(dmd); when(ds.getConnection()).thenReturn(con); diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/HibernateNativeQueryProviderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/HibernateNativeQueryProviderTests.java index 22bf07b1ab..a03276fd0e 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/HibernateNativeQueryProviderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/HibernateNativeQueryProviderTests.java @@ -47,8 +47,8 @@ void testCreateQueryWithStatelessSession() { String sqlQuery = "select * from T_FOOS"; hibernateQueryProvider.setSqlQuery(sqlQuery); - StatelessSession session = mock(StatelessSession.class); - NativeQuery query = mock(NativeQuery.class); + StatelessSession session = mock(); + NativeQuery query = mock(); when(session.createNativeQuery(sqlQuery)).thenReturn(query); when(query.addEntity(Foo.class)).thenReturn(query); @@ -64,8 +64,8 @@ void shouldCreateQueryWithStatefulSession() { String sqlQuery = "select * from T_FOOS"; hibernateQueryProvider.setSqlQuery(sqlQuery); - Session session = mock(Session.class); - NativeQuery query = mock(NativeQuery.class); + Session session = mock(); + NativeQuery query = mock(); when(session.createNativeQuery(sqlQuery)).thenReturn(query); when(query.addEntity(Foo.class)).thenReturn(query); diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/JpaNativeQueryProviderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/JpaNativeQueryProviderTests.java index 0b48f7d65e..4c25edbf8a 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/JpaNativeQueryProviderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/database/support/JpaNativeQueryProviderTests.java @@ -49,8 +49,8 @@ void testCreateQuery() { String sqlQuery = "select * from T_FOOS where value >= :limit"; jpaQueryProvider.setSqlQuery(sqlQuery); - EntityManager entityManager = mock(EntityManager.class); - Query query = mock(Query.class); + EntityManager entityManager = mock(); + Query query = mock(); when(entityManager.createNativeQuery(sqlQuery, Foo.class)).thenReturn(query); diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/SimpleBinaryBufferedReaderFactoryTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/SimpleBinaryBufferedReaderFactoryTests.java index 0a814af5aa..202fcc6476 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/SimpleBinaryBufferedReaderFactoryTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/SimpleBinaryBufferedReaderFactoryTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2006-2022 the original author or authors. + * Copyright 2006-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,6 +21,8 @@ import java.io.BufferedReader; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; import org.springframework.core.io.ByteArrayResource; /** @@ -75,16 +77,27 @@ void testCreateWithLineEndingAtEnd() throws Exception { assertNull(reader.readLine()); } - @Test - void testCreateWithFalseLineEnding() throws Exception { + @ParameterizedTest + @ValueSource(strings = { "||", "|||" }) + void testCreateWithFalseLineEnding(String lineEnding) throws Exception { SimpleBinaryBufferedReaderFactory factory = new SimpleBinaryBufferedReaderFactory(); - factory.setLineEnding("||"); + factory.setLineEnding(lineEnding); @SuppressWarnings("resource") - BufferedReader reader = factory.create(new ByteArrayResource("a|b||".getBytes()), "UTF-8"); + BufferedReader reader = factory.create(new ByteArrayResource(("a|b" + lineEnding).getBytes()), "UTF-8"); assertEquals("a|b", reader.readLine()); assertNull(reader.readLine()); } + @Test + void testCreateWithFalseMixedCharacterLineEnding() throws Exception { + SimpleBinaryBufferedReaderFactory factory = new SimpleBinaryBufferedReaderFactory(); + factory.setLineEnding("#@"); + @SuppressWarnings("resource") + BufferedReader reader = factory.create(new ByteArrayResource(("a##@").getBytes()), "UTF-8"); + assertEquals("a#", reader.readLine()); + assertNull(reader.readLine()); + } + @Test void testCreateWithIncompleteLineEnding() throws Exception { SimpleBinaryBufferedReaderFactory factory = new SimpleBinaryBufferedReaderFactory(); diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/builder/FlatFileItemWriterBuilderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/builder/FlatFileItemWriterBuilderTests.java index 1f94531a7a..855876c322 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/builder/FlatFileItemWriterBuilderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/builder/FlatFileItemWriterBuilderTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2022 the original author or authors. + * Copyright 2016-2023 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,7 +19,7 @@ import java.io.File; import java.io.IOException; import java.io.InputStreamReader; -import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; import org.junit.jupiter.api.Test; @@ -266,7 +266,7 @@ void testFlags() throws Exception { WritableResource output = new FileSystemResource(File.createTempFile("foo", "txt")); - String encoding = Charset.defaultCharset().name(); + String encoding = StandardCharsets.UTF_8.name(); FlatFileItemWriter writer = new FlatFileItemWriterBuilder ().name("foo") .resource(output) diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/mapping/DefaultLineMapperTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/mapping/DefaultLineMapperTests.java index 47ee5aecc9..17d2aef012 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/mapping/DefaultLineMapperTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/mapping/DefaultLineMapperTests.java @@ -50,11 +50,11 @@ void testMapping() throws Exception { final FieldSet fs = new DefaultFieldSet(new String[] { "token1", "token2" }); final String item = "ITEM"; - LineTokenizer tokenizer = mock(LineTokenizer.class); + LineTokenizer tokenizer = mock(); when(tokenizer.tokenize(line)).thenReturn(fs); @SuppressWarnings("unchecked") - FieldSetMapper fsMapper = mock(FieldSetMapper.class); + FieldSetMapper fsMapper = mock(); when(fsMapper.mapFieldSet(fs)).thenReturn(item); tested.setLineTokenizer(tokenizer); diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/jms/JmsItemReaderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/jms/JmsItemReaderTests.java index 1613bd9c90..260a2c87f7 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/jms/JmsItemReaderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/jms/JmsItemReaderTests.java @@ -37,7 +37,7 @@ class JmsItemReaderTests { @Test void testNoItemTypeSunnyDay() { - JmsOperations jmsTemplate = mock(JmsOperations.class); + JmsOperations jmsTemplate = mock(); when(jmsTemplate.receiveAndConvert()).thenReturn("foo"); itemReader.setJmsTemplate(jmsTemplate); @@ -46,7 +46,7 @@ void testNoItemTypeSunnyDay() { @Test void testSetItemTypeSunnyDay() { - JmsOperations jmsTemplate = mock(JmsOperations.class); + JmsOperations jmsTemplate = mock(); when(jmsTemplate.receiveAndConvert()).thenReturn("foo"); itemReader.setJmsTemplate(jmsTemplate); @@ -56,7 +56,7 @@ void testSetItemTypeSunnyDay() { @Test void testSetItemSubclassTypeSunnyDay() { - JmsOperations jmsTemplate = mock(JmsOperations.class); + JmsOperations jmsTemplate = mock(); Date date = new java.sql.Date(0L); when(jmsTemplate.receiveAndConvert()).thenReturn(date); @@ -70,7 +70,7 @@ void testSetItemSubclassTypeSunnyDay() { @Test void testSetItemTypeMismatch() { - JmsOperations jmsTemplate = mock(JmsOperations.class); + JmsOperations jmsTemplate = mock(); when(jmsTemplate.receiveAndConvert()).thenReturn("foo"); JmsItemReader itemReader = new JmsItemReader<>(); @@ -82,8 +82,8 @@ void testSetItemTypeMismatch() { @Test void testNextMessageSunnyDay() { - JmsOperations jmsTemplate = mock(JmsOperations.class); - Message message = mock(Message.class); + JmsOperations jmsTemplate = mock(); + Message message = mock(); when(jmsTemplate.receive()).thenReturn(message); JmsItemReader itemReader = new JmsItemReader<>(); diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/jms/JmsItemWriterTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/jms/JmsItemWriterTests.java index cc5c2aa0fb..7a36cdb782 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/jms/JmsItemWriterTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/jms/JmsItemWriterTests.java @@ -31,7 +31,7 @@ class JmsItemWriterTests { @Test void testNoItemTypeSunnyDay() throws Exception { - JmsOperations jmsTemplate = mock(JmsOperations.class); + JmsOperations jmsTemplate = mock(); jmsTemplate.convertAndSend("foo"); jmsTemplate.convertAndSend("bar"); diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/jms/JmsMethodArgumentsKeyGeneratorTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/jms/JmsMethodArgumentsKeyGeneratorTests.java index 7dc639a655..050f7d393b 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/jms/JmsMethodArgumentsKeyGeneratorTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/jms/JmsMethodArgumentsKeyGeneratorTests.java @@ -35,7 +35,7 @@ class JmsMethodArgumentsKeyGeneratorTests { @Test void testGetKeyFromMessage() throws Exception { - Message message = mock(Message.class); + Message message = mock(); when(message.getJMSMessageID()).thenReturn("foo"); JmsItemReader itemReader = new JmsItemReader<>(); diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/jms/JmsMethodInvocationRecovererTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/jms/JmsMethodInvocationRecovererTests.java index 57aa7d5638..aaf41439ec 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/jms/JmsMethodInvocationRecovererTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/jms/JmsMethodInvocationRecovererTests.java @@ -31,7 +31,7 @@ class JmsMethodInvocationRecovererTests { @Test void testRecoverWithNoDestination() { - JmsOperations jmsTemplate = mock(JmsOperations.class); + JmsOperations jmsTemplate = mock(); jmsTemplate.convertAndSend("foo"); itemReader.setJmsTemplate(jmsTemplate); diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/jms/JmsNewMethodArgumentsIdentifierTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/jms/JmsNewMethodArgumentsIdentifierTests.java index 8851c92d5e..d3f7da272a 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/jms/JmsNewMethodArgumentsIdentifierTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/jms/JmsNewMethodArgumentsIdentifierTests.java @@ -35,7 +35,7 @@ class JmsNewMethodArgumentsIdentifierTests { @Test void testIsNewForMessage() throws Exception { - Message message = mock(Message.class); + Message message = mock(); when(message.getJMSRedelivered()).thenReturn(true); assertFalse(newMethodArgumentsIdentifier.isNew(new Object[] { message })); diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/jms/builder/JmsItemReaderBuilderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/jms/builder/JmsItemReaderBuilderTests.java index 45d9692ecc..fbb48ac41b 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/jms/builder/JmsItemReaderBuilderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/jms/builder/JmsItemReaderBuilderTests.java @@ -42,7 +42,7 @@ class JmsItemReaderBuilderTests { @BeforeEach void setupJmsTemplate() { - this.defaultJmsTemplate = mock(JmsOperations.class); + this.defaultJmsTemplate = mock(); when(this.defaultJmsTemplate.receiveAndConvert()).thenReturn("foo"); } @@ -55,7 +55,7 @@ void testBasicRead() { @Test void testSetItemSubclassType() { - JmsOperations jmsTemplate = mock(JmsOperations.class); + JmsOperations jmsTemplate = mock(); Date date = new java.sql.Date(0L); when(jmsTemplate.receiveAndConvert()).thenReturn(date); @@ -77,8 +77,8 @@ void testSetItemTypeMismatch() { @Test void testMessageType() { - JmsOperations jmsTemplate = mock(JmsOperations.class); - Message message = mock(Message.class); + JmsOperations jmsTemplate = mock(); + Message message = mock(); when(jmsTemplate.receive()).thenReturn(message); JmsItemReader itemReader = new JmsItemReaderBuilder ().jmsTemplate(jmsTemplate) diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/jms/builder/JmsItemWriterBuilderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/jms/builder/JmsItemWriterBuilderTests.java index ad256ae325..6b88fea37d 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/jms/builder/JmsItemWriterBuilderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/jms/builder/JmsItemWriterBuilderTests.java @@ -37,7 +37,7 @@ class JmsItemWriterBuilderTests { @Test void testNoItem() throws Exception { - JmsOperations jmsTemplate = mock(JmsOperations.class); + JmsOperations jmsTemplate = mock(); JmsItemWriter itemWriter = new JmsItemWriterBuilder ().jmsTemplate(jmsTemplate).build(); ArgumentCaptor argCaptor = ArgumentCaptor.forClass(String.class); itemWriter.write(Chunk.of("foo", "bar")); diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/json/JsonFileItemWriterFunctionalTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/json/JsonFileItemWriterFunctionalTests.java index 3612ba984d..a8d24a2534 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/json/JsonFileItemWriterFunctionalTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/json/JsonFileItemWriterFunctionalTests.java @@ -19,7 +19,6 @@ import java.io.File; import java.io.IOException; import java.math.BigDecimal; -import java.nio.charset.Charset; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; @@ -334,7 +333,7 @@ private void assertFileEquals(File expected, File actual) throws Exception { } private String getContent(File file) throws IOException { - return Files.readString(file.toPath(), Charset.defaultCharset()); + return Files.readString(file.toPath()); } } diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/json/builder/JsonFileItemWriterBuilderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/json/builder/JsonFileItemWriterBuilderTests.java index 1fa37b7aa0..da3e032beb 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/json/builder/JsonFileItemWriterBuilderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/json/builder/JsonFileItemWriterBuilderTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2022 the original author or authors. + * Copyright 2018-2023 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,7 +17,7 @@ package org.springframework.batch.item.json.builder; import java.io.File; -import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; import java.nio.file.Files; import org.junit.jupiter.api.BeforeEach; @@ -82,8 +82,8 @@ void testJsonFileItemWriterCreation() { boolean shouldDeleteIfExists = true; String encoding = "UTF-8"; String lineSeparator = "#"; - FlatFileHeaderCallback headerCallback = Mockito.mock(FlatFileHeaderCallback.class); - FlatFileFooterCallback footerCallback = Mockito.mock(FlatFileFooterCallback.class); + FlatFileHeaderCallback headerCallback = Mockito.mock(); + FlatFileFooterCallback footerCallback = Mockito.mock(); // when JsonFileItemWriter writer = new JsonFileItemWriterBuilder ().name("jsonFileItemWriter") @@ -112,10 +112,10 @@ void testJsonFileItemWriterCreationDefaultEncoding() { boolean transactional = true; boolean shouldDeleteIfEmpty = true; boolean shouldDeleteIfExists = true; - String encoding = Charset.defaultCharset().name(); + String encoding = StandardCharsets.UTF_8.name(); String lineSeparator = "#"; - FlatFileHeaderCallback headerCallback = Mockito.mock(FlatFileHeaderCallback.class); - FlatFileFooterCallback footerCallback = Mockito.mock(FlatFileFooterCallback.class); + FlatFileHeaderCallback headerCallback = Mockito.mock(); + FlatFileFooterCallback footerCallback = Mockito.mock(); // when JsonFileItemWriter writer = new JsonFileItemWriterBuilder ().name("jsonFileItemWriter") diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/mail/SimpleMailMessageItemWriterTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/mail/SimpleMailMessageItemWriterTests.java index 7d69fc64ce..43cbc5c59a 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/mail/SimpleMailMessageItemWriterTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/mail/SimpleMailMessageItemWriterTests.java @@ -47,7 +47,7 @@ class SimpleMailMessageItemWriterTests { private final SimpleMailMessageItemWriter writer = new SimpleMailMessageItemWriter(); - private final MailSender mailSender = mock(MailSender.class); + private final MailSender mailSender = mock(); @BeforeEach void setUp() { diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/mail/builder/SimpleMailMessageItemWriterBuilderTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/mail/builder/SimpleMailMessageItemWriterBuilderTests.java index cc30179ab0..60bc88647c 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/mail/builder/SimpleMailMessageItemWriterBuilderTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/mail/builder/SimpleMailMessageItemWriterBuilderTests.java @@ -52,7 +52,7 @@ class SimpleMailMessageItemWriterBuilderTests { @BeforeEach void setup() { - mailSender = mock(MailSender.class); + mailSender = mock(); this.foo = new SimpleMailMessage(); this.bar = new SimpleMailMessage(); this.items = new SimpleMailMessage[] { this.foo, this.bar }; diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/mail/javamail/MimeMessageItemWriterTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/mail/javamail/MimeMessageItemWriterTests.java index 573c531776..658fb71d0b 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/mail/javamail/MimeMessageItemWriterTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/mail/javamail/MimeMessageItemWriterTests.java @@ -49,7 +49,7 @@ class MimeMessageItemWriterTests { private final MimeMessageItemWriter writer = new MimeMessageItemWriter(); - private final JavaMailSender mailSender = mock(JavaMailSender.class); + private final JavaMailSender mailSender = mock(); private final Session session = Session.getDefaultInstance(new Properties()); diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/support/CompositeItemProcessorTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/support/CompositeItemProcessorTests.java index f8d15de35b..b4e7e84875 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/support/CompositeItemProcessorTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/support/CompositeItemProcessorTests.java @@ -46,8 +46,8 @@ class CompositeItemProcessorTests { @SuppressWarnings("unchecked") @BeforeEach void setUp() throws Exception { - processor1 = mock(ItemProcessor.class); - processor2 = mock(ItemProcessor.class); + processor1 = mock(); + processor2 = mock(); composite.setDelegates(Arrays.asList(processor1, processor2)); @@ -80,8 +80,8 @@ void testTransform() throws Exception { @SuppressWarnings("unchecked") void testItemProcessorGenerics() throws Exception { CompositeItemProcessor composite = new CompositeItemProcessor<>(); - final ItemProcessor processor1 = mock(ItemProcessor.class); - final ItemProcessor processor2 = mock(ItemProcessor.class); + final ItemProcessor processor1 = mock(); + final ItemProcessor processor2 = mock(); composite.setDelegates(Arrays.asList(processor1, processor2)); composite.afterPropertiesSet(); diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/support/CompositeItemWriterTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/support/CompositeItemWriterTests.java index 43ba76c879..8d5d3f7b62 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/support/CompositeItemWriterTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/support/CompositeItemWriterTests.java @@ -52,7 +52,7 @@ void testProcess() throws Exception { for (int i = 0; i < NUMBER_OF_WRITERS; i++) { @SuppressWarnings("unchecked") - ItemWriter super Object> writer = mock(ItemWriter.class); + ItemWriter super Object> writer = mock(); writer.write(data); @@ -76,7 +76,7 @@ void testItemStreamNotCalled() throws Exception { private void doTestItemStream(boolean expectOpen) throws Exception { @SuppressWarnings("unchecked") - ItemStreamWriter super Object> writer = mock(ItemStreamWriter.class); + ItemStreamWriter super Object> writer = mock(); Chunk