diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index facf8fdc..90c82df3 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -10,6 +10,6 @@ repositories { dependencies { // see also (compatibility matrix) : https://docs.gradle.org/current/userguide/compatibility.html - implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.20") - implementation("org.jlleitschuh.gradle.ktlint:org.jlleitschuh.gradle.ktlint.gradle.plugin:11.6.1") + implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:2.2.21") + implementation("org.jlleitschuh.gradle.ktlint:org.jlleitschuh.gradle.ktlint.gradle.plugin:14.2.0") } diff --git a/buildSrc/src/main/kotlin/spring.batch.plus.kotlin-conventions.gradle.kts b/buildSrc/src/main/kotlin/spring.batch.plus.kotlin-conventions.gradle.kts index aebc0eff..9fe8fe14 100644 --- a/buildSrc/src/main/kotlin/spring.batch.plus.kotlin-conventions.gradle.kts +++ b/buildSrc/src/main/kotlin/spring.batch.plus.kotlin-conventions.gradle.kts @@ -11,7 +11,6 @@ plugins { id("org.jlleitschuh.gradle.ktlint") } - /* kotlin */ kotlin { @@ -21,7 +20,7 @@ kotlin { "-Xjsr305=strict", // enable jsr305 null-safety in kotlin ) jvmTarget = JvmTarget.JVM_17 // make class files for this version - languageVersion = KotlinVersion.KOTLIN_1_6 // language feature level - apiVersion = KotlinVersion.KOTLIN_1_6 // std api level + languageVersion = KotlinVersion.KOTLIN_2_2 // language feature level + apiVersion = KotlinVersion.KOTLIN_2_2 // std api level } } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 487983a8..fd7d5b0a 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,31 +1,41 @@ [versions] -spring-boot = "3.4.0" -spring-batch = "5.2.0" +spring-boot = "4.0.7" +spring-batch = "6.0.4" # spring-jdbc version should follow minor version described in 'spring-framework.version' # https://github.com/spring-projects/spring-batch/blob/main/pom.xml -spring-jdbc = "6.2.0" +spring-jdbc = "7.0.6" +# spring-data-mongodb / mongodb-driver versions should follow what 'spring-batch.version' pins +# https://github.com/spring-projects/spring-batch/blob/main/pom.xml +spring-data-mongodb = "5.0.6" +mongodb-driver = "5.6.5" slf4j = "2.0.17" -reactor-core = "3.5.0" +reactor-core = "3.8.4" findbugs-jsr305 = "3.0.2" +jspecify = "1.0.0" # test-only -junit = "5.11.+" +junit = "6.0.+" assertj = "3.27.+" -mockito = "5.15.+" -mockk = "1.13.+" -h2 = "2.3.+" -log4j = "2.24.+" +mockito = "5.20.+" +mockk = "1.14.+" +h2 = "2.4.+" +log4j = "2.25.+" [libraries] spring-boot-autoconfigure = { module = "org.springframework.boot:spring-boot-autoconfigure", version.ref = "spring-boot" } +spring-boot-batch-jdbc = { module = "org.springframework.boot:spring-boot-batch-jdbc", version.ref = "spring-boot" } +spring-data-mongodb = { module = "org.springframework.data:spring-data-mongodb", version.ref = "spring-data-mongodb" } +mongodb-driver-sync = { module = "org.mongodb:mongodb-driver-sync", version.ref = "mongodb-driver" } spring-batch-core = { module = "org.springframework.batch:spring-batch-core", version.ref = "spring-batch" } spring-jdbc = { module = "org.springframework:spring-jdbc", version.ref = "spring-jdbc" } slf4j = { module = "org.slf4j:slf4j-api", version.ref = "slf4j" } reactor-core = { module = "io.projectreactor:reactor-core", version.ref = "reactor-core" } findbugs-jsr305 = { module = "com.google.code.findbugs:jsr305", version.ref = "findbugs-jsr305" } +jspecify = { module = "org.jspecify:jspecify", version.ref = "jspecify" } # test-only junit = { module = "org.junit.jupiter:junit-jupiter", version.ref = "junit" } +junit-platform-launcher = { module = "org.junit.platform:junit-platform-launcher", version.ref = "junit" } assertj = { module = "org.assertj:assertj-core", version.ref = "assertj" } mockito = { module = "org.mockito:mockito-core", version.ref = "mockito" } mockk = { module = "io.mockk:mockk", version.ref = "mockk" } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 37f853b1..5dd3c012 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.5.1-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/spring-batch-plus-kotlin/build.gradle.kts b/spring-batch-plus-kotlin/build.gradle.kts index 93eecbd6..e8f0614e 100644 --- a/spring-batch-plus-kotlin/build.gradle.kts +++ b/spring-batch-plus-kotlin/build.gradle.kts @@ -4,6 +4,11 @@ plugins { id("spring.batch.plus.maven-publish-conventions") } +tasks.javadoc { + // Java sources only bridge Kotlin compiler limitations and expose no public API to document. + exclude("**/*.java") +} + dependencies { api(project(":spring-batch-plus")) @@ -14,6 +19,7 @@ dependencies { testImplementation(libs.spring.batch.core) testImplementation(libs.spring.jdbc) testImplementation(libs.reactor.core) + testRuntimeOnly(libs.junit.platform.launcher) testRuntimeOnly(libs.h2) testRuntimeOnly(libs.log4j) } diff --git a/spring-batch-plus-kotlin/src/integrationTest/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/ConcreteFlowBuilderDslIntegrationTest.kt b/spring-batch-plus-kotlin/src/integrationTest/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/ConcreteFlowBuilderDslIntegrationTest.kt deleted file mode 100644 index 88c0b69c..00000000 --- a/spring-batch-plus-kotlin/src/integrationTest/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/ConcreteFlowBuilderDslIntegrationTest.kt +++ /dev/null @@ -1,1163 +0,0 @@ -/* - * Spring Batch Plus - * - * Copyright 2022-present NAVER Corp. - * - * 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 - * - * http://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 com.navercorp.spring.batch.plus.kotlin.configuration - -import org.assertj.core.api.Assertions.assertThat -import org.junit.jupiter.api.Test -import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.ExitStatus -import org.springframework.batch.core.JobParameters -import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing -import org.springframework.batch.core.job.flow.FlowExecutionStatus -import org.springframework.batch.core.job.flow.JobExecutionDecider -import org.springframework.batch.core.launch.JobLauncher -import org.springframework.batch.core.repository.JobRepository -import org.springframework.batch.repeat.RepeatStatus -import org.springframework.batch.support.transaction.ResourcelessTransactionManager -import org.springframework.beans.factory.BeanFactory -import org.springframework.beans.factory.getBean -import org.springframework.context.annotation.AnnotationConfigApplicationContext -import org.springframework.context.annotation.Bean -import org.springframework.context.annotation.Configuration -import org.springframework.context.support.registerBean -import org.springframework.jdbc.datasource.DataSourceTransactionManager -import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder -import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType -import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor -import org.springframework.transaction.TransactionManager -import javax.sql.DataSource - -internal class ConcreteFlowBuilderDslIntegrationTest { - - @Test - fun testStepBean() { - // given - val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) - val jobLauncher = context.getBean() - val batch = context.getBean() - var testStep1CallCount = 0 - var testStep2CallCount = 0 - val testStep1 = batch { - step("testStep1") { - tasklet( - { _, _ -> - ++testStep1CallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - val testStep2 = batch { - step("testStep2") { - tasklet( - { _, _ -> - ++testStep2CallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - context.apply { - registerBean("testStep1") { - testStep1 - } - registerBean("testStep2") { - testStep2 - } - } - - // when - val testFlow = batch { - flow("testFlow") { - stepBean("testStep1") - stepBean("testStep2") - } - } - val job = batch { - job("testJob") { - flow(testFlow) - } - } - val jobExecution = jobLauncher.run(job, JobParameters()) - - // then - assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) - assertThat(jobExecution.exitStatus.exitCode).isEqualTo(ExitStatus.COMPLETED.exitCode) - assertThat(testStep1CallCount).isEqualTo(1) - assertThat(testStep2CallCount).isEqualTo(1) - } - - @Test - fun testStepWithInit() { - // given - val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) - val jobLauncher = context.getBean() - val batch = context.getBean() - var testStep1CallCount = 0 - var testStep2CallCount = 0 - - // when - val testFlow = batch { - flow("testFlow") { - step("testStep1") { - tasklet( - { _, _ -> - ++testStep1CallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - step("testStep2") { - tasklet( - { _, _ -> - ++testStep2CallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - } - val job = batch { - job("testJob") { - flow(testFlow) - } - } - val jobExecution = jobLauncher.run(job, JobParameters()) - - // then - assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) - assertThat(jobExecution.exitStatus.exitCode).isEqualTo(ExitStatus.COMPLETED.exitCode) - assertThat(testStep1CallCount).isEqualTo(1) - assertThat(testStep2CallCount).isEqualTo(1) - } - - @Test - fun testStepWithVariable() { - // given - val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) - val jobLauncher = context.getBean() - val batch = context.getBean() - var testStep1CallCount = 0 - var testStep2CallCount = 0 - val testStep1 = batch { - step("testStep1") { - tasklet( - { _, _ -> - ++testStep1CallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - val testStep2 = batch { - step("testStep2") { - tasklet( - { _, _ -> - ++testStep2CallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - - // when - val testFlow = batch { - flow("testFlow") { - step(testStep1) - step(testStep2) - } - } - val job = batch { - job("testJob") { - flow(testFlow) - } - } - val jobExecution = jobLauncher.run(job, JobParameters()) - - // then - assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) - assertThat(jobExecution.exitStatus.exitCode).isEqualTo(ExitStatus.COMPLETED.exitCode) - assertThat(testStep1CallCount).isEqualTo(1) - assertThat(testStep2CallCount).isEqualTo(1) - } - - @Test - fun testStepBeanWithTransition() { - // given - val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) - val jobLauncher = context.getBean() - val batch = context.getBean() - var testStep1CallCount = 0 - var transitionStep1CallCount = 0 - var transitionStep2CallCount = 0 - var testStep2CallCount = 0 - val testStep1 = batch { - step("testStep1") { - tasklet( - { _, _ -> - ++testStep1CallCount - throw RuntimeException("Error") - }, - ResourcelessTransactionManager(), - ) - } - } - val testStep2 = batch { - step("testStep2") { - tasklet( - { _, _ -> - ++testStep2CallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - context.apply { - registerBean("testStep1") { - testStep1 - } - registerBean("testStep2") { - testStep2 - } - } - - // when - val testFlow = batch { - flow("testFlow") { - stepBean("testStep1") { - on("COMPLETED") { - step("transitionStep1") { - tasklet( - { _, _ -> - ++transitionStep1CallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - on("FAILED") { - step("transitionStep2") { - tasklet( - { _, _ -> - ++transitionStep2CallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - } - stepBean("testStep2") { - on("COMPLETED") { - end("TEST") - } - } - } - } - val job = batch { - job("testJob") { - flow(testFlow) - } - } - val jobExecution = jobLauncher.run(job, JobParameters()) - - // then - assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) - assertThat(jobExecution.exitStatus.exitCode).isEqualTo(ExitStatus("TEST").exitCode) - assertThat(testStep1CallCount).isEqualTo(1) - assertThat(transitionStep1CallCount).isEqualTo(0) - assertThat(transitionStep2CallCount).isEqualTo(1) - assertThat(testStep2CallCount).isEqualTo(1) - } - - @Test - fun testStepWithInitAndTransition() { - // given - val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) - val jobLauncher = context.getBean() - val batch = context.getBean() - var testStep1CallCount = 0 - var transitionStep1CallCount = 0 - var transitionStep2CallCount = 0 - var testStep2CallCount = 0 - - // when - val testFlow = batch { - flow("testFlow") { - step( - "testStep1", - { - tasklet( - { _, _ -> - ++testStep1CallCount - throw RuntimeException("Error") - }, - ResourcelessTransactionManager(), - ) - }, - ) { - on("COMPLETED") { - step("transitionStep1") { - tasklet( - { _, _ -> - ++transitionStep1CallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - on("FAILED") { - step("transitionStep2") { - tasklet( - { _, _ -> - ++transitionStep2CallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - } - step( - "testStep2", - { - tasklet( - { _, _ -> - ++testStep2CallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - }, - ) { - on("COMPLETED") { - end("TEST") - } - } - } - } - val job = batch { - job("testJob") { - flow(testFlow) - } - } - val jobExecution = jobLauncher.run(job, JobParameters()) - - // then - assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) - assertThat(jobExecution.exitStatus.exitCode).isEqualTo(ExitStatus("TEST").exitCode) - assertThat(testStep1CallCount).isEqualTo(1) - assertThat(transitionStep1CallCount).isEqualTo(0) - assertThat(transitionStep2CallCount).isEqualTo(1) - assertThat(testStep2CallCount).isEqualTo(1) - } - - @Test - fun testStepWithVariableAndTransition() { - // given - val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) - val jobLauncher = context.getBean() - val batch = context.getBean() - var testStep1CallCount = 0 - var transitionStep1CallCount = 0 - var transitionStep2CallCount = 0 - var testStep2CallCount = 0 - val testStep1 = batch { - step("testStep1") { - tasklet( - { _, _ -> - ++testStep1CallCount - throw RuntimeException("Error") - }, - ResourcelessTransactionManager(), - ) - } - } - val testStep2 = batch { - step("testStep2") { - tasklet( - { _, _ -> - ++testStep2CallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - - // when - val testFlow = batch { - flow("testFlow") { - step(testStep1) { - on("COMPLETED") { - step("transitionStep1") { - tasklet( - { _, _ -> - ++transitionStep1CallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - on("FAILED") { - step("transitionStep2") { - tasklet( - { _, _ -> - ++transitionStep2CallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - } - step(testStep2) { - on("COMPLETED") { - end("TEST") - } - } - } - } - val job = batch { - job("testJob") { - flow(testFlow) - } - } - val jobExecution = jobLauncher.run(job, JobParameters()) - - // then - assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) - assertThat(jobExecution.exitStatus.exitCode).isEqualTo(ExitStatus("TEST").exitCode) - assertThat(testStep1CallCount).isEqualTo(1) - assertThat(transitionStep1CallCount).isEqualTo(0) - assertThat(transitionStep2CallCount).isEqualTo(1) - assertThat(testStep2CallCount).isEqualTo(1) - } - - @Test - fun testFlowBean() { - // given - val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) - val jobLauncher = context.getBean() - val batch = context.getBean() - var testStep1CallCount = 0 - var testStep2CallCount = 0 - val testFlow1 = batch { - flow("testFlow1") { - step("testStep1") { - tasklet( - { _, _ -> - ++testStep1CallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - } - val testFlow2 = batch { - flow("testFlow2") { - step("testStep2") { - tasklet( - { _, _ -> - ++testStep2CallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - } - context.apply { - registerBean("testFlow1") { - testFlow1 - } - registerBean("testFlow2") { - testFlow2 - } - } - - // when - val testFlow = batch { - flow("testFlow") { - flowBean("testFlow1") - flowBean("testFlow2") - } - } - val job = batch { - job("testJob") { - flow(testFlow) - } - } - val jobExecution = jobLauncher.run(job, JobParameters()) - - // then - assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) - assertThat(jobExecution.exitStatus.exitCode).isEqualTo(ExitStatus.COMPLETED.exitCode) - assertThat(testStep1CallCount).isEqualTo(1) - assertThat(testStep2CallCount).isEqualTo(1) - } - - @Test - fun testFlowWithInit() { - // given - val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) - val jobLauncher = context.getBean() - val batch = context.getBean() - var testStep1CallCount = 0 - var testStep2CallCount = 0 - - // when - val testFlow = batch { - flow("testFlow") { - flow("testFlow1") { - step("testStep1") { - tasklet( - { _, _ -> - ++testStep1CallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - flow("testFlow2") { - step("testStep2") { - tasklet( - { _, _ -> - ++testStep2CallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - } - } - val job = batch { - job("testJob") { - flow(testFlow) - } - } - val jobExecution = jobLauncher.run(job, JobParameters()) - - // then - assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) - assertThat(jobExecution.exitStatus.exitCode).isEqualTo(ExitStatus.COMPLETED.exitCode) - assertThat(testStep1CallCount).isEqualTo(1) - assertThat(testStep2CallCount).isEqualTo(1) - } - - @Test - fun testFlowWithVariable() { - // given - val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) - val jobLauncher = context.getBean() - val batch = context.getBean() - var testStep1CallCount = 0 - var testStep2CallCount = 0 - val testFlow1 = batch { - flow("testFlow1") { - step("testStep1") { - tasklet( - { _, _ -> - ++testStep1CallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - } - val testFlow2 = batch { - flow("testFlow2") { - step("testStep2") { - tasklet( - { _, _ -> - ++testStep2CallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - } - - // when - val testFlow = batch { - flow("testFlow") { - flow(testFlow1) - flow(testFlow2) - } - } - val job = batch { - job("testJob") { - flow(testFlow) - } - } - val jobExecution = jobLauncher.run(job, JobParameters()) - - // then - assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) - assertThat(jobExecution.exitStatus.exitCode).isEqualTo(ExitStatus.COMPLETED.exitCode) - assertThat(testStep1CallCount).isEqualTo(1) - assertThat(testStep2CallCount).isEqualTo(1) - } - - @Test - fun testFlowBeanWithTransition() { - // given - val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) - val jobLauncher = context.getBean() - val batch = context.getBean() - var testStep1CallCount = 0 - var transitionStep1CallCount = 0 - var transitionStep2CallCount = 0 - var testStep2CallCount = 0 - val testFlow1 = batch { - flow("testFlow1") { - step("testStep1") { - tasklet( - { _, _ -> - ++testStep1CallCount - throw RuntimeException("Error") - }, - ResourcelessTransactionManager(), - ) - } - } - } - val testFlow2 = batch { - flow("testFlow2") { - step("testStep2") { - tasklet( - { _, _ -> - ++testStep2CallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - } - context.apply { - registerBean("testFlow1") { - testFlow1 - } - registerBean("testFlow2") { - testFlow2 - } - } - - // when - val testFlow = batch { - flow("testFlow") { - flowBean("testFlow1") { - on("COMPLETED") { - step("transitionStep1") { - tasklet( - { _, _ -> - ++transitionStep1CallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - on("FAILED") { - step("transitionStep2") { - tasklet( - { _, _ -> - ++transitionStep2CallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - } - flowBean("testFlow2") { - on("COMPLETED") { - end("TEST") - } - } - } - } - val job = batch { - job("testJob") { - flow(testFlow) - } - } - val jobExecution = jobLauncher.run(job, JobParameters()) - - // then - assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) - assertThat(jobExecution.exitStatus.exitCode).isEqualTo(ExitStatus("TEST").exitCode) - assertThat(testStep1CallCount).isEqualTo(1) - assertThat(transitionStep1CallCount).isEqualTo(0) - assertThat(transitionStep2CallCount).isEqualTo(1) - assertThat(testStep2CallCount).isEqualTo(1) - } - - @Test - fun testFlowWithInitAndTransition() { - // given - val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) - val jobLauncher = context.getBean() - val batch = context.getBean() - var testStep1CallCount = 0 - var transitionStep1CallCount = 0 - var transitionStep2CallCount = 0 - var testStep2CallCount = 0 - - // when - val testFlow = batch { - flow("testFlow") { - flow( - "testFlow1", - { - step("testStep1") { - tasklet( - { _, _ -> - ++testStep1CallCount - throw RuntimeException("Error") - }, - ResourcelessTransactionManager(), - ) - } - }, - ) { - on("COMPLETED") { - step("transitionStep1") { - tasklet( - { _, _ -> - ++transitionStep1CallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - on("FAILED") { - step("transitionStep2") { - tasklet( - { _, _ -> - ++transitionStep2CallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - } - flow( - "testFlow2", - { - step("testStep2") { - tasklet( - { _, _ -> - ++testStep2CallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - }, - ) { - on("COMPLETED") { - end("TEST") - } - } - } - } - val job = batch { - job("testJob") { - flow(testFlow) - } - } - val jobExecution = jobLauncher.run(job, JobParameters()) - - // then - assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) - assertThat(jobExecution.exitStatus.exitCode).isEqualTo(ExitStatus("TEST").exitCode) - assertThat(testStep1CallCount).isEqualTo(1) - assertThat(transitionStep1CallCount).isEqualTo(0) - assertThat(transitionStep2CallCount).isEqualTo(1) - assertThat(testStep2CallCount).isEqualTo(1) - } - - @Test - fun testFlowWithVariableAndTransition() { - // given - val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) - val jobLauncher = context.getBean() - val batch = context.getBean() - var testStep1CallCount = 0 - var transitionStep1CallCount = 0 - var transitionStep2CallCount = 0 - var testStep2CallCount = 0 - val testFlow1 = batch { - flow("testFlow1") { - step("testStep1") { - tasklet( - { _, _ -> - ++testStep1CallCount - throw RuntimeException("Error") - }, - ResourcelessTransactionManager(), - ) - } - } - } - val testFlow2 = batch { - flow("testFlow2") { - step("testStep2") { - tasklet( - { _, _ -> - ++testStep2CallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - } - - // when - val testFlow = batch { - flow("testFlow") { - flow(testFlow1) { - on("COMPLETED") { - step("transitionStep1") { - tasklet( - { _, _ -> - ++transitionStep1CallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - on("FAILED") { - step("transitionStep2") { - tasklet( - { _, _ -> - ++transitionStep2CallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - } - flow(testFlow2) { - on("COMPLETED") { - end("TEST") - } - } - } - } - val job = batch { - job("testJob") { - flow(testFlow) - } - } - val jobExecution = jobLauncher.run(job, JobParameters()) - - // then - assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) - assertThat(jobExecution.exitStatus.exitCode).isEqualTo(ExitStatus("TEST").exitCode) - assertThat(testStep1CallCount).isEqualTo(1) - assertThat(transitionStep1CallCount).isEqualTo(0) - assertThat(transitionStep2CallCount).isEqualTo(1) - assertThat(testStep2CallCount).isEqualTo(1) - } - - @Test - fun testDeciderBean() { - // given - val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) - val jobLauncher = context.getBean() - val batch = context.getBean() - var testDeciderCallCount = 0 - val testDecider = JobExecutionDecider { _, _ -> - ++testDeciderCallCount - FlowExecutionStatus.COMPLETED - } - context.registerBean("testDecider") { - testDecider - } - - // when - val testFlow = batch { - flow("testFlow") { - deciderBean("testDecider") { - on("COMPLETED") { - end("TEST") - } - } - } - } - val job = batch { - job("testJob") { - flow(testFlow) - } - } - val jobExecution = jobLauncher.run(job, JobParameters()) - - // then - assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) - assertThat(jobExecution.exitStatus.exitCode).isEqualTo(ExitStatus("TEST").exitCode) - assertThat(testDeciderCallCount).isEqualTo(1) - } - - @Test - fun testDeciderBeanNotFirst() { - // given - val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) - val jobLauncher = context.getBean() - val batch = context.getBean() - var testStep1CallCount = 0 - var testDeciderCallCount = 0 - val testDecider = JobExecutionDecider { _, _ -> - ++testDeciderCallCount - FlowExecutionStatus.COMPLETED - } - context.registerBean("testDecider") { - testDecider - } - - // when - val testFlow = batch { - flow("testFlow") { - step("testStep1") { - tasklet( - { _, _ -> - ++testStep1CallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - deciderBean("testDecider") { - on("COMPLETED") { - end("TEST") - } - } - } - } - val job = batch { - job("testJob") { - flow(testFlow) - } - } - val jobExecution = jobLauncher.run(job, JobParameters()) - - // then - assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) - assertThat(jobExecution.exitStatus.exitCode).isEqualTo(ExitStatus("TEST").exitCode) - assertThat(testStep1CallCount).isEqualTo(1) - assertThat(testDeciderCallCount).isEqualTo(1) - } - - @Test - fun testDeciderWithVariable() { - // given - val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) - val jobLauncher = context.getBean() - val batch = context.getBean() - var testDeciderCallCount = 0 - val decider = JobExecutionDecider { _, _ -> - ++testDeciderCallCount - FlowExecutionStatus.COMPLETED - } - - // when - val testFlow = batch { - flow("testFlow") { - decider(decider) { - on("COMPLETED") { - end("TEST") - } - } - } - } - val job = batch { - job("testJob") { - flow(testFlow) - } - } - val jobExecution = jobLauncher.run(job, JobParameters()) - - // then - assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) - assertThat(jobExecution.exitStatus.exitCode).isEqualTo(ExitStatus("TEST").exitCode) - assertThat(testDeciderCallCount).isEqualTo(1) - } - - @Test - fun testDeciderWithVariableNotFirst() { - // given - val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) - val jobLauncher = context.getBean() - val batch = context.getBean() - var testStep1CallCount = 0 - var testDeciderCallCount = 0 - val decider = JobExecutionDecider { _, _ -> - ++testDeciderCallCount - FlowExecutionStatus.COMPLETED - } - - // when - val testFlow = batch { - flow("testFlow") { - step("testStep1") { - tasklet( - { _, _ -> - ++testStep1CallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - decider(decider) { - on("COMPLETED") { - end("TEST") - } - } - } - } - val job = batch { - job("testJob") { - flow(testFlow) - } - } - val jobExecution = jobLauncher.run(job, JobParameters()) - - // then - assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) - assertThat(jobExecution.exitStatus.exitCode).isEqualTo(ExitStatus("TEST").exitCode) - assertThat(testStep1CallCount).isEqualTo(1) - assertThat(testDeciderCallCount).isEqualTo(1) - } - - @Test - fun testSplit() { - // given - val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) - val jobLauncher = context.getBean() - val batch = context.getBean() - var taskExecutorCallCount = 0 - var testStep1CallCount = 0 - var testStep2CallCount = 0 - val callerThread = Thread.currentThread().name - val taskExecutor = object : ThreadPoolTaskExecutor() { - override fun execute(task: Runnable) { - ++taskExecutorCallCount - super.execute(task) - } - }.apply { initialize() } - - // when - val testFlow = batch { - flow("testFlow") { - split(taskExecutor) { - flow("testFlow1") { - step("testStep1") { - tasklet( - { _, _ -> - ++testStep1CallCount - assertThat(Thread.currentThread().name).isNotEqualTo(callerThread) - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - flow("testFlow2") { - step("testStep2") { - tasklet( - { _, _ -> - ++testStep2CallCount - assertThat(Thread.currentThread().name).isNotEqualTo(callerThread) - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - } - } - } - val job = batch { - job("testJob") { - flow(testFlow) - } - } - val jobExecution = jobLauncher.run(job, JobParameters()) - - // then - assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) - assertThat(jobExecution.exitStatus.exitCode).isEqualTo(ExitStatus.COMPLETED.exitCode) - assertThat(taskExecutorCallCount).isEqualTo(2) - assertThat(testStep1CallCount).isEqualTo(1) - assertThat(testStep2CallCount).isEqualTo(1) - } - - @Configuration - @EnableBatchProcessing( - dataSourceRef = "metadataDataSource", - transactionManagerRef = "metadataTransactionManager", - ) - private open class TestConfiguration { - - @Bean - open fun batchDsl( - beanFactory: BeanFactory, - jobRepository: JobRepository, - ): BatchDsl = BatchDsl( - beanFactory, - jobRepository, - ) - - @Bean - open fun metadataTransactionManager(): TransactionManager { - return DataSourceTransactionManager(metadataDataSource()) - } - - @Bean - open fun metadataDataSource(): DataSource { - return EmbeddedDatabaseBuilder() - .setType(EmbeddedDatabaseType.H2) - .addScript("/org/springframework/batch/core/schema-h2.sql") - .generateUniqueName(true) - .build() - } - } -} diff --git a/spring-batch-plus-kotlin/src/integrationTest/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/FlowJobBuilderDslIntegrationTest.kt b/spring-batch-plus-kotlin/src/integrationTest/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/FlowJobBuilderDslIntegrationTest.kt deleted file mode 100644 index 785c6d7e..00000000 --- a/spring-batch-plus-kotlin/src/integrationTest/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/FlowJobBuilderDslIntegrationTest.kt +++ /dev/null @@ -1,936 +0,0 @@ -/* - * Spring Batch Plus - * - * Copyright 2022-present NAVER Corp. - * - * 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 - * - * http://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 com.navercorp.spring.batch.plus.kotlin.configuration - -import org.assertj.core.api.Assertions.assertThat -import org.junit.jupiter.api.Test -import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.ExitStatus -import org.springframework.batch.core.JobParameters -import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing -import org.springframework.batch.core.job.flow.FlowExecutionStatus -import org.springframework.batch.core.job.flow.JobExecutionDecider -import org.springframework.batch.core.launch.JobLauncher -import org.springframework.batch.core.repository.JobRepository -import org.springframework.batch.repeat.RepeatStatus -import org.springframework.batch.support.transaction.ResourcelessTransactionManager -import org.springframework.beans.factory.BeanFactory -import org.springframework.beans.factory.getBean -import org.springframework.context.annotation.AnnotationConfigApplicationContext -import org.springframework.context.annotation.Bean -import org.springframework.context.annotation.Configuration -import org.springframework.context.support.registerBean -import org.springframework.jdbc.datasource.DataSourceTransactionManager -import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder -import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType -import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor -import org.springframework.transaction.TransactionManager -import javax.sql.DataSource - -internal class FlowJobBuilderDslIntegrationTest { - - @Test - fun testStepBeanWithTransition() { - // given - val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) - val jobLauncher = context.getBean() - val batch = context.getBean() - var testStep1CallCount = 0 - var transitionStep1CallCount = 0 - var transitionStep2CallCount = 0 - var testStep2CallCount = 0 - val testStep1 = batch { - step("testStep1") { - tasklet( - { _, _ -> - ++testStep1CallCount - throw RuntimeException("Error") - }, - ResourcelessTransactionManager(), - ) - } - } - val testStep2 = batch { - step("testStep2") { - tasklet( - { _, _ -> - ++testStep2CallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - context.apply { - registerBean("testStep1") { - testStep1 - } - registerBean("testStep2") { - testStep2 - } - } - - // when - val job = batch { - job("testJob") { - stepBean("testStep1") { - on("COMPLETED") { - step("transitionStep1") { - tasklet( - { _, _ -> - ++transitionStep1CallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - on("FAILED") { - step("transitionStep2") { - tasklet( - { _, _ -> - ++transitionStep2CallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - } - stepBean("testStep2") { - on("COMPLETED") { - end("TEST") - } - } - } - } - val jobExecution = jobLauncher.run(job, JobParameters()) - - // then - assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) - assertThat(jobExecution.exitStatus.exitCode).isEqualTo(ExitStatus("TEST").exitCode) - assertThat(testStep1CallCount).isEqualTo(1) - assertThat(transitionStep1CallCount).isEqualTo(0) - assertThat(transitionStep2CallCount).isEqualTo(1) - assertThat(testStep2CallCount).isEqualTo(1) - } - - @Test - fun testStepWithInitAndTransition() { - // given - val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) - val jobLauncher = context.getBean() - val batch = context.getBean() - var testStep1CallCount = 0 - var transitionStep1CallCount = 0 - var transitionStep2CallCount = 0 - var testStep2CallCount = 0 - - // when - val job = batch { - job("testJob") { - step( - "testStep1", - { - tasklet( - { _, _ -> - ++testStep1CallCount - throw RuntimeException("Error") - }, - ResourcelessTransactionManager(), - ) - }, - ) { - on("COMPLETED") { - step("transitionStep1") { - tasklet( - { _, _ -> - ++transitionStep1CallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - on("FAILED") { - step("transitionStep2") { - tasklet( - { _, _ -> - ++transitionStep2CallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - } - step( - "testStep2", - { - tasklet( - { _, _ -> - ++testStep2CallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - }, - ) { - on("COMPLETED") { - end("TEST") - } - } - } - } - val jobExecution = jobLauncher.run(job, JobParameters()) - - // then - assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) - assertThat(jobExecution.exitStatus.exitCode).isEqualTo(ExitStatus("TEST").exitCode) - assertThat(testStep1CallCount).isEqualTo(1) - assertThat(transitionStep1CallCount).isEqualTo(0) - assertThat(transitionStep2CallCount).isEqualTo(1) - assertThat(testStep2CallCount).isEqualTo(1) - } - - @Test - fun testStepWithVariableAndTransition() { - // given - val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) - val jobLauncher = context.getBean() - val batch = context.getBean() - var testStep1CallCount = 0 - var transitionStep1CallCount = 0 - var transitionStep2CallCount = 0 - var testStep2CallCount = 0 - val testStep1 = batch { - step("testStep1") { - tasklet( - { _, _ -> - ++testStep1CallCount - throw RuntimeException("Error") - }, - ResourcelessTransactionManager(), - ) - } - } - val testStep2 = batch { - step("testStep2") { - tasklet( - { _, _ -> - ++testStep2CallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - - // when - val job = batch { - job("testJob") { - step(testStep1) { - on("COMPLETED") { - step("transitionStep1") { - tasklet( - { _, _ -> - ++transitionStep1CallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - on("FAILED") { - step("transitionStep2") { - tasklet( - { _, _ -> - ++transitionStep2CallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - } - step(testStep2) { - on("COMPLETED") { - end("TEST") - } - } - } - } - val jobExecution = jobLauncher.run(job, JobParameters()) - - // then - assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) - assertThat(jobExecution.exitStatus.exitCode).isEqualTo(ExitStatus("TEST").exitCode) - assertThat(testStep1CallCount).isEqualTo(1) - assertThat(transitionStep1CallCount).isEqualTo(0) - assertThat(transitionStep2CallCount).isEqualTo(1) - assertThat(testStep2CallCount).isEqualTo(1) - } - - @Test - fun testFlowBean() { - // given - val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) - val jobLauncher = context.getBean() - val batch = context.getBean() - var testStep1CallCount = 0 - var testStep2CallCount = 0 - val testFlow1 = batch { - flow("testFlow1") { - step("testStep1") { - tasklet( - { _, _ -> - ++testStep1CallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - } - val testFlow2 = batch { - flow("testFlow2") { - step("testStep2") { - tasklet( - { _, _ -> - ++testStep2CallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - } - context.apply { - registerBean("testFlow1") { - testFlow1 - } - registerBean("testFlow2") { - testFlow2 - } - } - - // when - val job = batch { - job("testJob") { - flowBean("testFlow1") - flowBean("testFlow2") - } - } - val jobExecution = jobLauncher.run(job, JobParameters()) - - // then - assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) - assertThat(jobExecution.exitStatus.exitCode).isEqualTo(ExitStatus.COMPLETED.exitCode) - assertThat(testStep1CallCount).isEqualTo(1) - assertThat(testStep2CallCount).isEqualTo(1) - } - - @Test - fun testFlowWithInit() { - // given - val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) - val jobLauncher = context.getBean() - val batch = context.getBean() - var testStep1CallCount = 0 - var testStep2CallCount = 0 - - // when - val job = batch { - job("testJob") { - flow("testFlow1") { - step("testStep1") { - tasklet( - { _, _ -> - ++testStep1CallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - flow("testFlow2") { - step("testStep2") { - tasklet( - { _, _ -> - ++testStep2CallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - } - } - val jobExecution = jobLauncher.run(job, JobParameters()) - - // then - assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) - assertThat(jobExecution.exitStatus.exitCode).isEqualTo(ExitStatus.COMPLETED.exitCode) - assertThat(testStep1CallCount).isEqualTo(1) - assertThat(testStep2CallCount).isEqualTo(1) - } - - @Test - fun testFlowWithVariable() { - // given - val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) - val jobLauncher = context.getBean() - val batch = context.getBean() - var testStep1CallCount = 0 - var testStep2CallCount = 0 - val testFlow1 = batch { - flow("testFlow1") { - step("testStep1") { - tasklet( - { _, _ -> - ++testStep1CallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - } - val testFlow2 = batch { - flow("testFlow2") { - step("testStep2") { - tasklet( - { _, _ -> - ++testStep2CallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - } - - // when - val job = batch { - job("testJob") { - flow(testFlow1) - flow(testFlow2) - } - } - val jobExecution = jobLauncher.run(job, JobParameters()) - - // then - assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) - assertThat(jobExecution.exitStatus.exitCode).isEqualTo(ExitStatus.COMPLETED.exitCode) - assertThat(testStep1CallCount).isEqualTo(1) - assertThat(testStep2CallCount).isEqualTo(1) - } - - @Test - fun testFlowBeanWithTransition() { - // given - val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) - val jobLauncher = context.getBean() - val batch = context.getBean() - var testStep1CallCount = 0 - var transitionStep1CallCount = 0 - var transitionStep2CallCount = 0 - var testStep2CallCount = 0 - val testFlow1 = batch { - flow("testFlow1") { - step("testStep1") { - tasklet( - { _, _ -> - ++testStep1CallCount - throw RuntimeException("Error") - }, - ResourcelessTransactionManager(), - ) - } - } - } - - val testFlow2 = batch { - flow("testFlow2") { - step("testStep2") { - tasklet( - { _, _ -> - ++testStep2CallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - } - context.apply { - registerBean("testFlow1") { - testFlow1 - } - registerBean("testFlow2") { - testFlow2 - } - } - - // when - val job = batch { - job("testJob") { - flowBean("testFlow1") { - on("COMPLETED") { - step("transitionStep1") { - tasklet( - { _, _ -> - ++transitionStep1CallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - on("FAILED") { - step("transitionStep2") { - tasklet( - { _, _ -> - ++transitionStep2CallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - } - flowBean("testFlow2") { - on("COMPLETED") { - end("TEST") - } - } - } - } - val jobExecution = jobLauncher.run(job, JobParameters()) - - // then - assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) - assertThat(jobExecution.exitStatus.exitCode).isEqualTo(ExitStatus("TEST").exitCode) - assertThat(testStep1CallCount).isEqualTo(1) - assertThat(transitionStep1CallCount).isEqualTo(0) - assertThat(transitionStep2CallCount).isEqualTo(1) - assertThat(testStep2CallCount).isEqualTo(1) - } - - @Test - fun testFlowWithInitAndTransition() { - // given - val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) - val jobLauncher = context.getBean() - val batch = context.getBean() - var testStep1CallCount = 0 - var transitionStep1CallCount = 0 - var transitionStep2CallCount = 0 - var testStep2CallCount = 0 - - // when - val job = batch { - job("testJob") { - flow( - "testFlow1", - { - step("testStep1") { - tasklet( - { _, _ -> - ++testStep1CallCount - throw RuntimeException("Error") - }, - ResourcelessTransactionManager(), - ) - } - }, - ) { - on("COMPLETED") { - step("transitionStep1") { - tasklet( - { _, _ -> - ++transitionStep1CallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - on("FAILED") { - step("transitionStep2") { - tasklet( - { _, _ -> - ++transitionStep2CallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - } - flow( - "testFlow2", - { - step("testStep2") { - tasklet( - { _, _ -> - ++testStep2CallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - }, - ) { - on("COMPLETED") { - end("TEST") - } - } - } - } - val jobExecution = jobLauncher.run(job, JobParameters()) - - // then - assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) - assertThat(jobExecution.exitStatus.exitCode).isEqualTo(ExitStatus("TEST").exitCode) - assertThat(testStep1CallCount).isEqualTo(1) - assertThat(transitionStep1CallCount).isEqualTo(0) - assertThat(transitionStep2CallCount).isEqualTo(1) - assertThat(testStep2CallCount).isEqualTo(1) - } - - @Test - fun testFlowWithVariableAndTransition() { - // given - val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) - val jobLauncher = context.getBean() - val batch = context.getBean() - var testStep1CallCount = 0 - var transitionStep1CallCount = 0 - var transitionStep2CallCount = 0 - var testStep2CallCount = 0 - val testFlow1 = batch { - flow("testFlow1") { - step("testStep1") { - tasklet( - { _, _ -> - ++testStep1CallCount - throw RuntimeException("Error") - }, - ResourcelessTransactionManager(), - ) - } - } - } - val testFlow2 = batch { - flow("testFlow2") { - step("testStep2") { - tasklet( - { _, _ -> - ++testStep2CallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - } - - // when - val job = batch { - job("testJob") { - flow(testFlow1) { - on("COMPLETED") { - step("transitionStep1") { - tasklet( - { _, _ -> - ++transitionStep1CallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - on("FAILED") { - step("transitionStep2") { - tasklet( - { _, _ -> - ++transitionStep2CallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - } - flow(testFlow2) { - on("COMPLETED") { - end("TEST") - } - } - } - } - val jobExecution = jobLauncher.run(job, JobParameters()) - - // then - assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) - assertThat(jobExecution.exitStatus.exitCode).isEqualTo(ExitStatus("TEST").exitCode) - assertThat(testStep1CallCount).isEqualTo(1) - assertThat(transitionStep1CallCount).isEqualTo(0) - assertThat(transitionStep2CallCount).isEqualTo(1) - assertThat(testStep2CallCount).isEqualTo(1) - } - - @Test - fun testDeciderBean() { - // given - val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) - val jobLauncher = context.getBean() - val batch = context.getBean() - var testDeciderCallCount = 0 - val testDecider = JobExecutionDecider { _, _ -> - ++testDeciderCallCount - FlowExecutionStatus.COMPLETED - } - context.registerBean("testDecider") { - testDecider - } - - // when - val job = batch { - job("testJob") { - deciderBean("testDecider") { - on("COMPLETED") { - end("TEST") - } - } - } - } - val jobExecution = jobLauncher.run(job, JobParameters()) - - // then - assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) - assertThat(jobExecution.exitStatus.exitCode).isEqualTo(ExitStatus("TEST").exitCode) - assertThat(testDeciderCallCount).isEqualTo(1) - } - - @Test - fun testDeciderBeanNotFirst() { - // given - val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) - val jobLauncher = context.getBean() - val batch = context.getBean() - var testStep1CallCount = 0 - var testDeciderCallCount = 0 - val testDecider = JobExecutionDecider { _, _ -> - ++testDeciderCallCount - FlowExecutionStatus.COMPLETED - } - context.registerBean("testDecider") { - testDecider - } - - // when - val job = batch { - job("testJob") { - step("testStep1") { - tasklet( - { _, _ -> - ++testStep1CallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - deciderBean("testDecider") { - on("COMPLETED") { - end("TEST") - } - } - } - } - val jobExecution = jobLauncher.run(job, JobParameters()) - - // then - assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) - assertThat(jobExecution.exitStatus.exitCode).isEqualTo(ExitStatus("TEST").exitCode) - assertThat(testStep1CallCount).isEqualTo(1) - assertThat(testDeciderCallCount).isEqualTo(1) - } - - @Test - fun testDeciderWithVariable() { - // given - val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) - val jobLauncher = context.getBean() - val batch = context.getBean() - var testDeciderCallCount = 0 - val decider = JobExecutionDecider { _, _ -> - ++testDeciderCallCount - FlowExecutionStatus.COMPLETED - } - - // when - val job = batch { - job("testJob") { - decider(decider) { - on("COMPLETED") { - end("TEST") - } - } - } - } - val jobExecution = jobLauncher.run(job, JobParameters()) - - // then - assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) - assertThat(jobExecution.exitStatus.exitCode).isEqualTo(ExitStatus("TEST").exitCode) - assertThat(testDeciderCallCount).isEqualTo(1) - } - - @Test - fun testDeciderWithVariableNotFirst() { - // given - val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) - val jobLauncher = context.getBean() - val batch = context.getBean() - var testStep1CallCount = 0 - var testDeciderCallCount = 0 - val decider = JobExecutionDecider { _, _ -> - ++testDeciderCallCount - FlowExecutionStatus.COMPLETED - } - - // when - val job = batch { - job("testJob") { - step("testStep1") { - tasklet( - { _, _ -> - ++testStep1CallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - decider(decider) { - on("COMPLETED") { - end("TEST") - } - } - } - } - val jobExecution = jobLauncher.run(job, JobParameters()) - - // then - assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) - assertThat(jobExecution.exitStatus.exitCode).isEqualTo(ExitStatus("TEST").exitCode) - assertThat(testStep1CallCount).isEqualTo(1) - assertThat(testDeciderCallCount).isEqualTo(1) - } - - @Test - fun testSplit() { - // given - val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) - val jobLauncher = context.getBean() - val batch = context.getBean() - var taskExecutorCallCount = 0 - var testStep1CallCount = 0 - var testStep2CallCount = 0 - val callerThread = Thread.currentThread().name - val taskExecutor = object : ThreadPoolTaskExecutor() { - override fun execute(task: Runnable) { - ++taskExecutorCallCount - super.execute(task) - } - }.apply { initialize() } - - // when - val job = batch { - job("testJob") { - split(taskExecutor) { - flow("testFlow1") { - step("testStep1") { - tasklet( - { _, _ -> - ++testStep1CallCount - assertThat(Thread.currentThread().name).isNotEqualTo(callerThread) - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - flow("testFlow2") { - step("testStep2") { - tasklet( - { _, _ -> - ++testStep2CallCount - assertThat(Thread.currentThread().name).isNotEqualTo(callerThread) - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - } - } - } - val jobExecution = jobLauncher.run(job, JobParameters()) - - // then - assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) - assertThat(jobExecution.exitStatus.exitCode).isEqualTo(ExitStatus.COMPLETED.exitCode) - assertThat(taskExecutorCallCount).isEqualTo(2) - assertThat(testStep1CallCount).isEqualTo(1) - assertThat(testStep2CallCount).isEqualTo(1) - } - - @Configuration - @EnableBatchProcessing( - dataSourceRef = "metadataDataSource", - transactionManagerRef = "metadataTransactionManager", - ) - private open class TestConfiguration { - - @Bean - open fun batchDsl( - beanFactory: BeanFactory, - jobRepository: JobRepository, - ): BatchDsl = BatchDsl( - beanFactory, - jobRepository, - ) - - @Bean - open fun metadataTransactionManager(): TransactionManager { - return DataSourceTransactionManager(metadataDataSource()) - } - - @Bean - open fun metadataDataSource(): DataSource { - return EmbeddedDatabaseBuilder() - .setType(EmbeddedDatabaseType.H2) - .addScript("/org/springframework/batch/core/schema-h2.sql") - .generateUniqueName(true) - .build() - } - } -} diff --git a/spring-batch-plus-kotlin/src/integrationTest/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/SimpleJobBuilderDslIntegrationTest.kt b/spring-batch-plus-kotlin/src/integrationTest/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/SimpleJobBuilderDslIntegrationTest.kt deleted file mode 100644 index 90c77177..00000000 --- a/spring-batch-plus-kotlin/src/integrationTest/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/SimpleJobBuilderDslIntegrationTest.kt +++ /dev/null @@ -1,216 +0,0 @@ -/* - * Spring Batch Plus - * - * Copyright 2022-present NAVER Corp. - * - * 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 - * - * http://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 com.navercorp.spring.batch.plus.kotlin.configuration - -import org.assertj.core.api.Assertions.assertThat -import org.junit.jupiter.api.Test -import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.JobParameters -import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing -import org.springframework.batch.core.launch.JobLauncher -import org.springframework.batch.core.repository.JobRepository -import org.springframework.batch.repeat.RepeatStatus -import org.springframework.batch.support.transaction.ResourcelessTransactionManager -import org.springframework.beans.factory.BeanFactory -import org.springframework.beans.factory.getBean -import org.springframework.context.annotation.AnnotationConfigApplicationContext -import org.springframework.context.annotation.Bean -import org.springframework.context.annotation.Configuration -import org.springframework.context.support.registerBean -import org.springframework.jdbc.datasource.DataSourceTransactionManager -import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder -import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType -import org.springframework.transaction.TransactionManager -import javax.sql.DataSource - -internal class SimpleJobBuilderDslIntegrationTest { - - @Test - fun testStepBean() { - // given - AnnotationConfigApplicationContext() - val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) - val jobLauncher = context.getBean() - val batch = context.getBean() - var testStep1CallCount = 0 - var testStep2CallCount = 0 - - val testStep1 = batch { - step("testStep1") { - tasklet( - { _, _ -> - ++testStep1CallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - val testStep2 = batch { - step("testStep2") { - tasklet( - { _, _ -> - ++testStep2CallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - context.apply { - registerBean("testStep1") { - testStep1 - } - registerBean("testStep2") { - testStep2 - } - } - - // when - val job = batch { - job("testJob") { - stepBean("testStep1") - stepBean("testStep2") - } - } - val jobExecution = jobLauncher.run(job, JobParameters()) - - // then - assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) - assertThat(testStep1CallCount).isEqualTo(1) - assertThat(testStep2CallCount).isEqualTo(1) - } - - @Test - fun testStepWithInit() { - // given - val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) - val jobLauncher = context.getBean() - val batch = context.getBean() - var testStep1CallCount = 0 - var testStep2CallCount = 0 - - // when - val job = batch { - job("testJob") { - step("testStep1") { - tasklet( - { _, _ -> - ++testStep1CallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - step("testStep2") { - tasklet( - { _, _ -> - ++testStep2CallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - } - val jobExecution = jobLauncher.run(job, JobParameters()) - - // then - assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) - assertThat(testStep1CallCount).isEqualTo(1) - assertThat(testStep2CallCount).isEqualTo(1) - } - - @Test - fun testStepWithVariable() { - // given - val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) - val jobLauncher = context.getBean() - val batch = context.getBean() - var testStep1CallCount = 0 - var testStep2CallCount = 0 - val testStep1 = batch { - step("testStep1") { - tasklet( - { _, _ -> - ++testStep1CallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - val testStep2 = batch { - step("testStep2") { - tasklet( - { _, _ -> - ++testStep2CallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - - // when - val job = batch { - job("testJob") { - step(testStep1) - step(testStep2) - } - } - val jobExecution = jobLauncher.run(job, JobParameters()) - - // then - assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) - assertThat(testStep1CallCount).isEqualTo(1) - assertThat(testStep2CallCount).isEqualTo(1) - } - - @Configuration - @EnableBatchProcessing( - dataSourceRef = "metadataDataSource", - transactionManagerRef = "metadataTransactionManager", - ) - private open class TestConfiguration { - - @Bean - open fun batchDsl( - beanFactory: BeanFactory, - jobRepository: JobRepository, - ): BatchDsl = BatchDsl( - beanFactory, - jobRepository, - ) - - @Bean - open fun metadataTransactionManager(): TransactionManager { - return DataSourceTransactionManager(metadataDataSource()) - } - - @Bean - open fun metadataDataSource(): DataSource { - return EmbeddedDatabaseBuilder() - .setType(EmbeddedDatabaseType.H2) - .addScript("/org/springframework/batch/core/schema-h2.sql") - .generateUniqueName(true) - .build() - } - } -} diff --git a/spring-batch-plus-kotlin/src/integrationTest/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/SplitBuilderDslIntegrationTest.kt b/spring-batch-plus-kotlin/src/integrationTest/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/SplitBuilderDslIntegrationTest.kt deleted file mode 100644 index e2ec4313..00000000 --- a/spring-batch-plus-kotlin/src/integrationTest/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/SplitBuilderDslIntegrationTest.kt +++ /dev/null @@ -1,291 +0,0 @@ -/* - * Spring Batch Plus - * - * Copyright 2022-present NAVER Corp. - * - * 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 - * - * http://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 com.navercorp.spring.batch.plus.kotlin.configuration - -import org.assertj.core.api.Assertions.assertThat -import org.assertj.core.api.Assertions.assertThatThrownBy -import org.junit.jupiter.api.Test -import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.ExitStatus -import org.springframework.batch.core.JobParameters -import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing -import org.springframework.batch.core.launch.JobLauncher -import org.springframework.batch.core.repository.JobRepository -import org.springframework.batch.repeat.RepeatStatus -import org.springframework.batch.support.transaction.ResourcelessTransactionManager -import org.springframework.beans.factory.BeanFactory -import org.springframework.beans.factory.getBean -import org.springframework.context.annotation.AnnotationConfigApplicationContext -import org.springframework.context.annotation.Bean -import org.springframework.context.annotation.Configuration -import org.springframework.context.support.registerBean -import org.springframework.jdbc.datasource.DataSourceTransactionManager -import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder -import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType -import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor -import org.springframework.transaction.TransactionManager -import javax.sql.DataSource - -internal class SplitBuilderDslIntegrationTest { - - @Test - fun testFlowBean() { - // given - val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) - val jobLauncher = context.getBean() - val batch = context.getBean() - val callerThread = Thread.currentThread().name - var taskExecutorCallCount = 0 - val taskExecutor = object : ThreadPoolTaskExecutor() { - override fun execute(task: Runnable) { - ++taskExecutorCallCount - super.execute(task) - } - }.apply { initialize() } - var testStep1CallCount = 0 - var testStep2CallCount = 0 - val testFlow1 = batch { - flow("testFlow1") { - step("testStep1") { - tasklet( - { _, _ -> - ++testStep1CallCount - assertThat(Thread.currentThread().name).isNotEqualTo(callerThread) - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - } - val testFlow2 = batch { - flow("testFlow2") { - step("testStep2") { - tasklet( - { _, _ -> - ++testStep2CallCount - assertThat(Thread.currentThread().name).isNotEqualTo(callerThread) - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - } - context.apply { - registerBean("testFlow1") { - testFlow1 - } - registerBean("testFlow2") { - testFlow2 - } - } - - // when - val job = batch { - job("testJob") { - split(taskExecutor) { - flowBean("testFlow1") - flowBean("testFlow2") - } - } - } - val jobExecution = jobLauncher.run(job, JobParameters()) - - // then - assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) - assertThat(jobExecution.exitStatus.exitCode).isEqualTo(ExitStatus.COMPLETED.exitCode) - assertThat(taskExecutorCallCount).isEqualTo(2) - assertThat(testStep1CallCount).isEqualTo(1) - assertThat(testStep2CallCount).isEqualTo(1) - } - - @Test - fun testFlowWithInit() { - // given - val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) - val jobLauncher = context.getBean() - val batch = context.getBean() - var taskExecutorCallCount = 0 - var testStep1CallCount = 0 - var testStep2CallCount = 0 - val callerThread = Thread.currentThread().name - val taskExecutor = object : ThreadPoolTaskExecutor() { - override fun execute(task: Runnable) { - ++taskExecutorCallCount - super.execute(task) - } - }.apply { initialize() } - - // when - val job = batch { - job("testJob") { - split(taskExecutor) { - flow("testFlow1") { - step("testStep1") { - tasklet( - { _, _ -> - ++testStep1CallCount - assertThat(Thread.currentThread().name).isNotEqualTo(callerThread) - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - flow("testFlow2") { - step("testStep2") { - tasklet( - { _, _ -> - ++testStep2CallCount - assertThat(Thread.currentThread().name).isNotEqualTo(callerThread) - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - } - } - } - val jobExecution = jobLauncher.run(job, JobParameters()) - - // then - assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) - assertThat(jobExecution.exitStatus.exitCode).isEqualTo(ExitStatus.COMPLETED.exitCode) - assertThat(taskExecutorCallCount).isEqualTo(2) - assertThat(testStep1CallCount).isEqualTo(1) - assertThat(testStep2CallCount).isEqualTo(1) - } - - @Test - fun testFlowWithVariable() { - // given - val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) - val jobLauncher = context.getBean() - val batch = context.getBean() - val callerThread = Thread.currentThread().name - var taskExecutorCallCount = 0 - val taskExecutor = object : ThreadPoolTaskExecutor() { - override fun execute(task: Runnable) { - ++taskExecutorCallCount - super.execute(task) - } - }.apply { initialize() } - var testStep1CallCount = 0 - var testStep2CallCount = 0 - val testFlow1 = batch { - flow("testFlow1") { - step("testStep1") { - tasklet( - { _, _ -> - ++testStep1CallCount - assertThat(Thread.currentThread().name).isNotEqualTo(callerThread) - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - } - val testFlow2 = batch { - flow("testFlow2") { - step("testStep2") { - tasklet( - { _, _ -> - ++testStep2CallCount - assertThat(Thread.currentThread().name).isNotEqualTo(callerThread) - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - } - - // when - val job = batch { - job("testJob") { - split(taskExecutor) { - flow(testFlow1) - flow(testFlow2) - } - } - } - val jobExecution = jobLauncher.run(job, JobParameters()) - - // then - assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) - assertThat(jobExecution.exitStatus.exitCode).isEqualTo(ExitStatus.COMPLETED.exitCode) - assertThat(taskExecutorCallCount).isEqualTo(2) - assertThat(testStep1CallCount).isEqualTo(1) - assertThat(testStep2CallCount).isEqualTo(1) - } - - @Test - fun testNoFlow() { - // given - val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) - val batch = context.getBean() - val taskExecutor = ThreadPoolTaskExecutor().apply { - initialize() - } - - // when, then - assertThatThrownBy { - batch { - job("testJob") { - split(taskExecutor) { - } - } - } - }.hasMessageContaining("should set at least one flow to split") - } - - @Configuration - @EnableBatchProcessing( - dataSourceRef = "metadataDataSource", - transactionManagerRef = "metadataTransactionManager", - ) - private open class TestConfiguration { - - @Bean - open fun batchDsl( - beanFactory: BeanFactory, - jobRepository: JobRepository, - ): BatchDsl = BatchDsl( - beanFactory, - jobRepository, - ) - - @Bean - open fun metadataTransactionManager(): TransactionManager { - return DataSourceTransactionManager(metadataDataSource()) - } - - @Bean - open fun metadataDataSource(): DataSource { - return EmbeddedDatabaseBuilder() - .setType(EmbeddedDatabaseType.H2) - .addScript("/org/springframework/batch/core/schema-h2.sql") - .generateUniqueName(true) - .build() - } - } -} diff --git a/spring-batch-plus-kotlin/src/integrationTest/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/StepBuilderDslIntegrationTest.kt b/spring-batch-plus-kotlin/src/integrationTest/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/StepBuilderDslIntegrationTest.kt deleted file mode 100644 index 99636808..00000000 --- a/spring-batch-plus-kotlin/src/integrationTest/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/StepBuilderDslIntegrationTest.kt +++ /dev/null @@ -1,875 +0,0 @@ -/* - * Spring Batch Plus - * - * Copyright 2022-present NAVER Corp. - * - * 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 - * - * http://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 com.navercorp.spring.batch.plus.kotlin.configuration - -import org.assertj.core.api.Assertions.assertThat -import org.assertj.core.api.Assertions.assertThatThrownBy -import org.junit.jupiter.api.Test -import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.JobParameters -import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing -import org.springframework.batch.core.launch.JobLauncher -import org.springframework.batch.core.repository.JobRepository -import org.springframework.batch.core.step.tasklet.Tasklet -import org.springframework.batch.repeat.RepeatStatus -import org.springframework.batch.repeat.policy.SimpleCompletionPolicy -import org.springframework.batch.repeat.support.RepeatTemplate -import org.springframework.batch.support.transaction.ResourcelessTransactionManager -import org.springframework.beans.factory.BeanFactory -import org.springframework.beans.factory.getBean -import org.springframework.context.annotation.AnnotationConfigApplicationContext -import org.springframework.context.annotation.Bean -import org.springframework.context.annotation.Configuration -import org.springframework.context.support.registerBean -import org.springframework.jdbc.datasource.DataSourceTransactionManager -import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder -import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType -import org.springframework.transaction.TransactionManager -import javax.sql.DataSource - -@Suppress("DEPRECATION") -internal class StepBuilderDslIntegrationTest { - - @Test - fun testDeprecatedTaskletBean() { - // given - val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) - val batch = context.getBean() - var taskletCallCount = 0 - val tasklet = Tasklet { _, _ -> - ++taskletCallCount - RepeatStatus.FINISHED - } - context.registerBean("testTasklet") { - tasklet - } - - // when, then - assertThatThrownBy { - batch { - job("testJob") { - step("testStep") { - taskletBean("testTasklet") - } - } - } - } - } - - @Test - fun testDeprecatedTaskletBeanWithInit() { - // given - val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) - val batch = context.getBean() - var taskletCallCount = 0 - var taskExecutorCallCount = 0 - val tasklet = Tasklet { _, _ -> - ++taskletCallCount - RepeatStatus.FINISHED - } - context.registerBean("testTasklet") { - tasklet - } - - // when, then - assertThatThrownBy { - batch { - job("testJob") { - step("testStep") { - taskletBean("testTasklet") { - taskExecutor { - ++taskExecutorCallCount - it.run() - } - } - } - } - } - } - } - - @Test - fun testDeprecatedTaskletWithLambda() { - // given - val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) - val batch = context.getBean() - var taskletCallCount = 0 - - // when, then - assertThatThrownBy { - batch { - job("testJob") { - step("testStep") { - tasklet { _, _ -> - ++taskletCallCount - RepeatStatus.FINISHED - } - } - } - } - } - } - - @Test - fun testDeprecatedTaskletWithLambdaAndInit() { - // given - val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) - val batch = context.getBean() - var taskletCallCount = 0 - var taskExecutorCallCount = 0 - - // when, then - assertThatThrownBy { - batch { - job("testJob") { - step("testStep") { - tasklet( - { _, _ -> - ++taskletCallCount - RepeatStatus.FINISHED - }, - ) { - taskExecutor { - ++taskExecutorCallCount - it.run() - } - } - } - } - } - } - } - - @Test - fun testDeprecatedChunkWithCount() { - // given - val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) - val batch = context.getBean() - val readLimit = 20 - val chunkSize = 3 - var readCallCount = 0 - var writeCallCount = 0 - - // when, then - assertThatThrownBy { - batch { - job("testJob") { - step("testStep") { - chunk(chunkSize) { - reader { - if (readCallCount < readLimit) { - ++readCallCount - 1 - } else { - null - } - } - writer { - ++writeCallCount - } - } - } - } - } - } - } - - @Test - fun testDeprecatedChunkWithCompletionPolicy() { - // given - val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) - val batch = context.getBean() - val readLimit = 20 - val chunkSize = 3 - var readCallCount = 0 - var writeCallCount = 0 - - // when, then - assertThatThrownBy { - batch { - job("testJob") { - step("testStep") { - chunk(SimpleCompletionPolicy(chunkSize)) { - reader { - if (readCallCount < readLimit) { - ++readCallCount - 1 - } else { - null - } - } - writer { - ++writeCallCount - } - } - } - } - } - } - } - - @Test - fun testDeprecatedChunkWithRepeatOperations() { - // given - val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) - val batch = context.getBean() - val readLimit = 20 - val chunkSize = 3 - var readCallCount = 0 - var writeCallCount = 0 - - // when, then - assertThatThrownBy { - batch { - job("testJob") { - step("testStep") { - chunk( - RepeatTemplate().apply { - setCompletionPolicy(SimpleCompletionPolicy(chunkSize)) - }, - ) { - reader { - if (readCallCount < readLimit) { - ++readCallCount - 1 - } else { - null - } - } - writer { - ++writeCallCount - } - } - } - } - } - } - } - - @Test - fun testTaskletBean() { - // given - val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) - val jobLauncher = context.getBean() - val batch = context.getBean() - var taskletCallCount = 0 - val tasklet = Tasklet { _, _ -> - ++taskletCallCount - RepeatStatus.FINISHED - } - context.registerBean("testTasklet") { - tasklet - } - - // when - val job = batch { - job("testJob") { - step("testStep") { - taskletBean("testTasklet", ResourcelessTransactionManager()) - } - } - } - val jobExecution = jobLauncher.run(job, JobParameters()) - - // then - assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) - assertThat(taskletCallCount).isEqualTo(1) - } - - @Test - fun testTaskletBeanWithInit() { - // given - val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) - val jobLauncher = context.getBean() - val batch = context.getBean() - var taskletCallCount = 0 - var taskExecutorCallCount = 0 - val tasklet = Tasklet { _, _ -> - ++taskletCallCount - RepeatStatus.FINISHED - } - context.registerBean("testTasklet") { - tasklet - } - - // when - val job = batch { - job("testJob") { - step("testStep") { - taskletBean("testTasklet", ResourcelessTransactionManager()) { - taskExecutor { - ++taskExecutorCallCount - it.run() - } - } - } - } - } - val jobExecution = jobLauncher.run(job, JobParameters()) - - // then - assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) - assertThat(taskletCallCount).isEqualTo(1) - assertThat(taskExecutorCallCount).isEqualTo(1) - } - - @Test - fun testTaskletWithLambda() { - // given - val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) - val jobLauncher = context.getBean() - val batch = context.getBean() - var taskletCallCount = 0 - - // when - val job = batch { - job("testJob") { - step("testStep") { - tasklet( - { _, _ -> - ++taskletCallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - } - val jobExecution = jobLauncher.run(job, JobParameters()) - - // then - assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) - assertThat(taskletCallCount).isEqualTo(1) - } - - @Test - fun testTaskletWithLambdaAndInit() { - // given - val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) - val jobLauncher = context.getBean() - val batch = context.getBean() - var taskletCallCount = 0 - var taskExecutorCallCount = 0 - - // when - val job = batch { - job("testJob") { - step("testStep") { - tasklet( - { _, _ -> - ++taskletCallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) { - taskExecutor { - ++taskExecutorCallCount - it.run() - } - } - } - } - } - val jobExecution = jobLauncher.run(job, JobParameters()) - - // then - assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) - assertThat(taskletCallCount).isEqualTo(1) - assertThat(taskExecutorCallCount).isEqualTo(1) - } - - @Test - fun testChunkWithCount() { - // given - val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) - val jobLauncher = context.getBean() - val batch = context.getBean() - val readLimit = 20 - val chunkSize = 3 - var readCallCount = 0 - var writeCallCount = 0 - - // when - val job = batch { - job("testJob") { - step("testStep") { - chunk(chunkSize, ResourcelessTransactionManager()) { - reader { - if (readCallCount < readLimit) { - ++readCallCount - 1 - } else { - null - } - } - writer { - ++writeCallCount - } - } - } - } - } - val jobExecution = jobLauncher.run(job, JobParameters()) - - // then - assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) - assertThat(readCallCount).isEqualTo(readLimit) - assertThat(writeCallCount).isEqualTo(7) // Ceil(20/3) - } - - @Test - fun testChunkWithCompletionPolicy() { - // given - val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) - val jobLauncher = context.getBean() - val batch = context.getBean() - val readLimit = 20 - val chunkSize = 3 - var readCallCount = 0 - var writeCallCount = 0 - - // when - val job = batch { - job("testJob") { - step("testStep") { - chunk(SimpleCompletionPolicy(chunkSize), ResourcelessTransactionManager()) { - reader { - if (readCallCount < readLimit) { - ++readCallCount - 1 - } else { - null - } - } - writer { - ++writeCallCount - } - } - } - } - } - val jobExecution = jobLauncher.run(job, JobParameters()) - - // then - assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) - assertThat(readCallCount).isEqualTo(readLimit) - assertThat(writeCallCount).isEqualTo(7) // Ceil(20/3) - } - - @Test - fun testChunkWithRepeatOperations() { - // given - val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) - val jobLauncher = context.getBean() - val batch = context.getBean() - val readLimit = 20 - val chunkSize = 3 - var readCallCount = 0 - var writeCallCount = 0 - - // when - val job = batch { - job("testJob") { - step("testStep") { - chunk( - RepeatTemplate().apply { - setCompletionPolicy(SimpleCompletionPolicy(chunkSize)) - }, - ResourcelessTransactionManager(), - ) { - reader { - if (readCallCount < readLimit) { - ++readCallCount - 1 - } else { - null - } - } - writer { - ++writeCallCount - } - } - } - } - } - val jobExecution = jobLauncher.run(job, JobParameters()) - - // then - assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) - assertThat(readCallCount).isEqualTo(readLimit) - assertThat(writeCallCount).isEqualTo(7) // Ceil(20/3) - } - - @Test - fun testPartitioner() { - // given - val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) - val jobLauncher = context.getBean() - val batch = context.getBean() - var partitionHandlerCallCount = 0 - - // when - val job = batch { - job("testJob") { - step("testStep") { - partitioner { - partitionHandler { _, _ -> - ++partitionHandlerCallCount - listOf() - } - splitter("splitStep") { mapOf() } - } - } - } - } - val jobExecution = jobLauncher.run(job, JobParameters()) - - // then - assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) - assertThat(partitionHandlerCallCount).isEqualTo(1) - } - - @Test - fun testJobBean() { - // given - val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) - val jobLauncher = context.getBean() - val batch = context.getBean() - var stepCallCount = 0 - val testJob2 = batch { - job("testJob2") { - step("testStep2") { - ++stepCallCount - tasklet( - { _, _ -> RepeatStatus.FINISHED }, - ResourcelessTransactionManager(), - ) - } - } - } - context.registerBean("testJob2") { - testJob2 - } - - // when - val job = batch { - job("testJob") { - step("testStep") { - jobBean("testJob2") - } - } - } - val jobExecution = jobLauncher.run(job, JobParameters()) - - // then - assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) - assertThat(stepCallCount).isEqualTo(1) - } - - @Test - fun testJobBeanWithInit() { - // given - val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) - val jobLauncher = context.getBean() - val batch = context.getBean() - var stepCallCount = 0 - var jobParametersExtractorCallCount = 0 - val testJob2 = batch { - job("testJob2") { - step("testStep2") { - ++stepCallCount - tasklet( - { _, _ -> RepeatStatus.FINISHED }, - ResourcelessTransactionManager(), - ) - } - } - } - context.registerBean("testJob2") { - testJob2 - } - - // when - val job = batch { - job("testJob") { - step("testStep") { - jobBean("testJob2") { - parametersExtractor { _, _ -> - ++jobParametersExtractorCallCount - JobParameters() - } - } - } - } - } - val jobExecution = jobLauncher.run(job, JobParameters()) - - // then - assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) - assertThat(stepCallCount).isEqualTo(1) - assertThat(jobParametersExtractorCallCount).isEqualTo(1) - } - - @Test - fun testJobWithJobVariable() { - // given - val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) - val jobLauncher = context.getBean() - val batch = context.getBean() - var stepCallCount = 0 - val testJob2 = batch { - job("testJob2") { - step("testStep2") { - ++stepCallCount - tasklet( - { _, _ -> RepeatStatus.FINISHED }, - ResourcelessTransactionManager(), - ) - } - } - } - - // when - val job = batch { - job("testJob") { - step("testStep") { - job(testJob2) - } - } - } - val jobExecution = jobLauncher.run(job, JobParameters()) - - // then - assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) - assertThat(stepCallCount).isEqualTo(1) - } - - @Test - fun testJobWithJobVariableAndInit() { - // given - val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) - val jobLauncher = context.getBean() - val batch = context.getBean() - var jobCallcount = 0 - var jobParametersExtractorCallCount = 0 - val testJob2 = batch { - job("testJob2") { - step("testStep2") { - ++jobCallcount - tasklet( - { _, _ -> RepeatStatus.FINISHED }, - ResourcelessTransactionManager(), - ) - } - } - } - - // when - val job = batch { - job("testJob") { - step("testStep") { - job(testJob2) { - parametersExtractor { _, _ -> - ++jobParametersExtractorCallCount - JobParameters() - } - } - } - } - } - val jobExecution = jobLauncher.run(job, JobParameters()) - - // then - assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) - assertThat(jobCallcount).isEqualTo(1) - assertThat(jobParametersExtractorCallCount).isEqualTo(1) - } - - @Test - fun testFlowBean() { - // given - val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) - val jobLauncher = context.getBean() - val batch = context.getBean() - var testStep1CallCount = 0 - var testStep2CallCount = 0 - val testFlow = batch { - flow("testFlow") { - step("testStep1") { - tasklet( - { _, _ -> - ++testStep1CallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - step("testStep2") { - tasklet( - { _, _ -> - ++testStep2CallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - } - context.registerBean("testFlow") { - testFlow - } - - // when - val job = batch { - job("testJob") { - step("testStep") { - flowBean("testFlow") - } - } - } - val jobExecution = jobLauncher.run(job, JobParameters()) - - // then - assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) - assertThat(testStep1CallCount).isEqualTo(1) - assertThat(testStep2CallCount).isEqualTo(1) - } - - @Test - fun testFlowWithLambda() { - // given - val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) - val jobLauncher = context.getBean() - val batch = context.getBean() - var testStep1CallCount = 0 - var testStep2CallCount = 0 - - // when - val job = batch { - job("testJob") { - step("testStep") { - flow("testFlow") { - step("testStep1") { - tasklet( - { _, _ -> - ++testStep1CallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - step("testStep2") { - tasklet( - { _, _ -> - ++testStep2CallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - } - } - } - val jobExecution = jobLauncher.run(job, JobParameters()) - - // then - assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) - assertThat(testStep1CallCount).isEqualTo(1) - assertThat(testStep2CallCount).isEqualTo(1) - } - - @Test - fun testFlowWithVariable() { - // given - val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) - val jobLauncher = context.getBean() - val batch = context.getBean() - var testStep1CallCount = 0 - var testStep2CallCount = 0 - val testFlow = batch { - flow("testFlow") { - step("testStep1") { - tasklet( - { _, _ -> - ++testStep1CallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - step("testStep2") { - tasklet( - { _, _ -> - ++testStep2CallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - } - - // when - val job = batch { - job("testJob") { - step("testStep") { - flow(testFlow) - } - } - } - val jobExecution = jobLauncher.run(job, JobParameters()) - - // then - assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) - assertThat(testStep1CallCount).isEqualTo(1) - assertThat(testStep2CallCount).isEqualTo(1) - } - - @Configuration - @EnableBatchProcessing( - dataSourceRef = "metadataDataSource", - transactionManagerRef = "metadataTransactionManager", - ) - private open class TestConfiguration { - - @Bean - open fun batchDsl( - beanFactory: BeanFactory, - jobRepository: JobRepository, - ): BatchDsl = BatchDsl( - beanFactory, - jobRepository, - ) - - @Bean - open fun metadataTransactionManager(): TransactionManager { - return DataSourceTransactionManager(metadataDataSource()) - } - - @Bean - open fun metadataDataSource(): DataSource { - return EmbeddedDatabaseBuilder() - .setType(EmbeddedDatabaseType.H2) - .addScript("/org/springframework/batch/core/schema-h2.sql") - .generateUniqueName(true) - .build() - } - } -} diff --git a/spring-batch-plus-kotlin/src/integrationTest/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/TransitionBuilderDslIntegrationTest.kt b/spring-batch-plus-kotlin/src/integrationTest/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/TransitionBuilderDslIntegrationTest.kt deleted file mode 100644 index 885013ba..00000000 --- a/spring-batch-plus-kotlin/src/integrationTest/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/TransitionBuilderDslIntegrationTest.kt +++ /dev/null @@ -1,1903 +0,0 @@ -/* - * Spring Batch Plus - * - * Copyright 2022-present NAVER Corp. - * - * 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 - * - * http://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 com.navercorp.spring.batch.plus.kotlin.configuration - -import org.assertj.core.api.Assertions.assertThat -import org.assertj.core.api.Assertions.assertThatThrownBy -import org.junit.jupiter.api.Test -import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.ExitStatus -import org.springframework.batch.core.JobParameters -import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing -import org.springframework.batch.core.job.flow.FlowExecutionStatus -import org.springframework.batch.core.job.flow.JobExecutionDecider -import org.springframework.batch.core.launch.JobLauncher -import org.springframework.batch.core.repository.JobRepository -import org.springframework.batch.repeat.RepeatStatus -import org.springframework.batch.support.transaction.ResourcelessTransactionManager -import org.springframework.beans.factory.BeanFactory -import org.springframework.beans.factory.getBean -import org.springframework.context.annotation.AnnotationConfigApplicationContext -import org.springframework.context.annotation.Bean -import org.springframework.context.annotation.Configuration -import org.springframework.context.support.registerBean -import org.springframework.jdbc.datasource.DataSourceTransactionManager -import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder -import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType -import org.springframework.transaction.TransactionManager -import javax.sql.DataSource - -/** - * Separated from FlowJobBuilderDslIntegrationTest since it's too big. - */ -internal class TransitionBuilderDslIntegrationTest { - - @Test - fun testTransitionToStepBean() { - // given - val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) - val jobLauncher = context.getBean() - val batch = context.getBean() - var testStep1CallCount = 0 - var transitionStepCallCount = 0 - val testStep1 = batch { - step("testStep1") { - tasklet( - { _, _ -> - ++testStep1CallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - val transitionStep = batch { - step("transitionStep") { - tasklet( - { _, _ -> - ++transitionStepCallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - context.registerBean("transitionStep") { - transitionStep - } - - // when - val job = batch { - job("testJob") { - step(testStep1) { - on("COMPLETED") { - stepBean("transitionStep") - } - } - } - } - val jobExecution = jobLauncher.run(job, JobParameters()) - - // then - assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) - assertThat(jobExecution.exitStatus.exitCode).isEqualTo(ExitStatus.COMPLETED.exitCode) - assertThat(testStep1CallCount).isEqualTo(1) - assertThat(transitionStepCallCount).isEqualTo(1) - } - - @Test - fun testTransitionToStepWithInit() { - // given - val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) - val jobLauncher = context.getBean() - val batch = context.getBean() - var testStep1CallCount = 0 - var transitionStepCallCount = 0 - val testStep1 = batch { - step("testStep1") { - tasklet( - { _, _ -> - ++testStep1CallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - - // when - val job = batch { - job("testJob") { - step(testStep1) { - on("COMPLETED") { - step("transitionStep") { - tasklet( - { _, _ -> - ++transitionStepCallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - } - } - } - val jobExecution = jobLauncher.run(job, JobParameters()) - - // then - assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) - assertThat(jobExecution.exitStatus.exitCode).isEqualTo(ExitStatus.COMPLETED.exitCode) - assertThat(testStep1CallCount).isEqualTo(1) - assertThat(transitionStepCallCount).isEqualTo(1) - } - - @Test - fun testTransitionToStepVariable() { - // given - val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) - val jobLauncher = context.getBean() - val batch = context.getBean() - var testStep1CallCount = 0 - var transitionStepCallCount = 0 - val testStep1 = batch { - step("testStep1") { - tasklet( - { _, _ -> - ++testStep1CallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - val transitionStep = batch { - step("transitionStep") { - tasklet( - { _, _ -> - ++transitionStepCallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - - // when - val job = batch { - job("testJob") { - step(testStep1) { - on("COMPLETED") { - step(transitionStep) - } - } - } - } - val jobExecution = jobLauncher.run(job, JobParameters()) - - // then - assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) - assertThat(jobExecution.exitStatus.exitCode).isEqualTo(ExitStatus.COMPLETED.exitCode) - assertThat(testStep1CallCount).isEqualTo(1) - assertThat(transitionStepCallCount).isEqualTo(1) - } - - @Test - fun testTransitionToStepBeanWithTransition() { - // given - val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) - val jobLauncher = context.getBean() - val batch = context.getBean() - var testStep1CallCount = 0 - var transitionStepCallCount = 0 - val testStep1 = batch { - step("testStep1") { - tasklet( - { _, _ -> - ++testStep1CallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - val transitionStep = batch { - step("transitionStep") { - tasklet( - { _, _ -> - ++transitionStepCallCount - throw RuntimeException("Error") - }, - ResourcelessTransactionManager(), - ) - } - } - context.registerBean("transitionStep") { - transitionStep - } - - // when - val job = batch { - job("testJob") { - step(testStep1) { - on("COMPLETED") { - stepBean("transitionStep") { - on("COMPLETED") { - fail() - } - on("FAILED") { - end("TEST") - } - on("*") { - end() - } - } - } - } - } - } - val jobExecution = jobLauncher.run(job, JobParameters()) - - // then - assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) - assertThat(jobExecution.exitStatus.exitCode).isEqualTo(ExitStatus("TEST").exitCode) - assertThat(testStep1CallCount).isEqualTo(1) - assertThat(transitionStepCallCount).isEqualTo(1) - } - - @Test - fun testTransitionToStepWithInitAndTransition() { - // given - val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) - val jobLauncher = context.getBean() - val batch = context.getBean() - var testStep1CallCount = 0 - var transitionStepCallCount = 0 - val testStep1 = batch { - step("testStep1") { - tasklet( - { _, _ -> - ++testStep1CallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - - // when - val job = batch { - job("testJob") { - step(testStep1) { - on("COMPLETED") { - step( - "transitionStep", - { - tasklet( - { _, _ -> - ++transitionStepCallCount - throw RuntimeException("Error") - }, - ResourcelessTransactionManager(), - ) - }, - ) { - on("COMPLETED") { - fail() - } - on("FAILED") { - end("TEST") - } - on("*") { - end() - } - } - } - } - } - } - val jobExecution = jobLauncher.run(job, JobParameters()) - - // then - assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) - assertThat(jobExecution.exitStatus.exitCode).isEqualTo(ExitStatus("TEST").exitCode) - assertThat(testStep1CallCount).isEqualTo(1) - assertThat(transitionStepCallCount).isEqualTo(1) - } - - @Test - fun testTransitionToStepVariableWithTransition() { - // given - val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) - val jobLauncher = context.getBean() - val batch = context.getBean() - var testStep1CallCount = 0 - var transitionStepCallCount = 0 - val testStep1 = batch { - step("testStep1") { - tasklet( - { _, _ -> - ++testStep1CallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - val transitionStep = batch { - step("transitionStep") { - tasklet( - { _, _ -> - ++transitionStepCallCount - throw RuntimeException("Error") - }, - ResourcelessTransactionManager(), - ) - } - } - - // when - val job = batch { - job("testJob") { - step(testStep1) { - on("COMPLETED") { - step(transitionStep) { - on("COMPLETED") { - fail() - } - on("FAILED") { - end("TEST") - } - on("*") { - end() - } - } - } - } - } - } - val jobExecution = jobLauncher.run(job, JobParameters()) - - // then - assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) - assertThat(jobExecution.exitStatus.exitCode).isEqualTo(ExitStatus("TEST").exitCode) - assertThat(testStep1CallCount).isEqualTo(1) - assertThat(transitionStepCallCount).isEqualTo(1) - } - - @Test - fun testTransitionToFlowBean() { - // given - val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) - val jobLauncher = context.getBean() - val batch = context.getBean() - var testStep1CallCount = 0 - var transitionStepCallCount = 0 - val testStep1 = batch { - step("testStep1") { - tasklet( - { _, _ -> - ++testStep1CallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - val transitionFlow = batch { - flow("transitionFlow") { - step("transitionStep") { - tasklet( - { _, _ -> - ++transitionStepCallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - } - context.registerBean("transitionFlow") { - transitionFlow - } - - // when - val job = batch { - job("testJob") { - step(testStep1) { - on("COMPLETED") { - flowBean("transitionFlow") - } - } - } - } - val jobExecution = jobLauncher.run(job, JobParameters()) - - // then - assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) - assertThat(jobExecution.exitStatus.exitCode).isEqualTo(ExitStatus.COMPLETED.exitCode) - assertThat(testStep1CallCount).isEqualTo(1) - assertThat(transitionStepCallCount).isEqualTo(1) - } - - @Test - fun testTransitionToFlowWithInit() { - // given - val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) - val jobLauncher = context.getBean() - val batch = context.getBean() - var testStep1CallCount = 0 - var transitionStepCallCount = 0 - val testStep1 = batch { - step("testStep1") { - tasklet( - { _, _ -> - ++testStep1CallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - - // when - val job = batch { - job("testJob") { - step(testStep1) { - on("COMPLETED") { - flow("transitionFlow") { - step("transitionStep") { - tasklet( - { _, _ -> - ++transitionStepCallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - } - } - } - } - val jobExecution = jobLauncher.run(job, JobParameters()) - - // then - assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) - assertThat(jobExecution.exitStatus.exitCode).isEqualTo(ExitStatus.COMPLETED.exitCode) - assertThat(testStep1CallCount).isEqualTo(1) - assertThat(transitionStepCallCount).isEqualTo(1) - } - - @Test - fun testTransitionToFlowVariable() { - // given - val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) - val jobLauncher = context.getBean() - val batch = context.getBean() - var testStep1CallCount = 0 - var transitionStepCallCount = 0 - val testStep1 = batch { - step("testStep1") { - tasklet( - { _, _ -> - ++testStep1CallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - val transitionFlow = batch { - flow("transitionFlow") { - step("transitionStep") { - tasklet( - { _, _ -> - ++transitionStepCallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - } - - // when - val job = batch { - job("testJob") { - step(testStep1) { - on("COMPLETED") { - flow(transitionFlow) - } - } - } - } - val jobExecution = jobLauncher.run(job, JobParameters()) - - // then - assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) - assertThat(jobExecution.exitStatus.exitCode).isEqualTo(ExitStatus.COMPLETED.exitCode) - assertThat(testStep1CallCount).isEqualTo(1) - assertThat(transitionStepCallCount).isEqualTo(1) - } - - @Test - fun testTransitionToFlowBeanWithTransition() { - // given - val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) - val jobLauncher = context.getBean() - val batch = context.getBean() - var testStep1CallCount = 0 - var transitionStepCallCount = 0 - val testStep1 = batch { - step("testStep1") { - tasklet( - { _, _ -> - ++testStep1CallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - val transitionFlow = batch { - flow("transitionFlow") { - step("transitionStep") { - tasklet( - { _, _ -> - ++transitionStepCallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - } - context.registerBean("transitionFlow") { - transitionFlow - } - - // when - val job = batch { - job("testJob") { - step(testStep1) { - on("COMPLETED") { - flowBean("transitionFlow") { - on("COMPLETED") { - end("TEST") - } - on("*") { - stop() - } - } - } - } - } - } - val jobExecution = jobLauncher.run(job, JobParameters()) - - // then - assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) - assertThat(jobExecution.exitStatus.exitCode).isEqualTo(ExitStatus("TEST").exitCode) - assertThat(testStep1CallCount).isEqualTo(1) - assertThat(transitionStepCallCount).isEqualTo(1) - } - - @Test - fun testTransitionToFlowWithInitAndTransition() { - // given - val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) - val jobLauncher = context.getBean() - val batch = context.getBean() - var testStep1CallCount = 0 - var transitionStepCallCount = 0 - val testStep1 = batch { - step("testStep1") { - tasklet( - { _, _ -> - ++testStep1CallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - - // when - val job = batch { - job("testJob") { - step(testStep1) { - on("COMPLETED") { - flow( - "transitionFlow", - { - step("transitionStep") { - tasklet( - { _, _ -> - ++transitionStepCallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - }, - ) { - on("COMPLETED") { - end("TEST") - } - on("*") { - stop() - } - } - } - } - } - } - val jobExecution = jobLauncher.run(job, JobParameters()) - - // then - assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) - assertThat(jobExecution.exitStatus.exitCode).isEqualTo(ExitStatus("TEST").exitCode) - assertThat(testStep1CallCount).isEqualTo(1) - assertThat(transitionStepCallCount).isEqualTo(1) - } - - @Test - fun testTransitionToFlowWithVariableAndTransition() { - // given - val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) - val jobLauncher = context.getBean() - val batch = context.getBean() - var testStep1CallCount = 0 - var transitionStepCallCount = 0 - val testStep1 = batch { - step("testStep1") { - tasklet( - { _, _ -> - ++testStep1CallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - val transitionFlow = batch { - flow("transitionFlow") { - step("transitionStep") { - tasklet( - { _, _ -> - ++transitionStepCallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - } - - // when - val job = batch { - job("testJob") { - step(testStep1) { - on("COMPLETED") { - flow(transitionFlow) { - on("COMPLETED") { - end("TEST") - } - on("*") { - stop() - } - } - } - } - } - } - val jobExecution = jobLauncher.run(job, JobParameters()) - - // then - assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) - assertThat(jobExecution.exitStatus.exitCode).isEqualTo(ExitStatus("TEST").exitCode) - assertThat(testStep1CallCount).isEqualTo(1) - assertThat(transitionStepCallCount).isEqualTo(1) - } - - @Test - fun testTransitionToDeciderBean() { - // given - val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) - val jobLauncher = context.getBean() - val batch = context.getBean() - var testStep1CallCount = 0 - var testDeciderCallCount = 0 - val testStep1 = batch { - step("testStep1") { - tasklet( - { _, _ -> - ++testStep1CallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - val testDecider = JobExecutionDecider { _, _ -> - ++testDeciderCallCount - FlowExecutionStatus("SKIPPED") - } - context.registerBean("testDecider") { - testDecider - } - - // when - val job = batch { - job("testJob") { - step(testStep1) { - on("COMPLETED") { - deciderBean("testDecider") { - on("COMPLETED") { - fail() - } - on("SKIPPED") { - end("TEST") - } - on("*") { - end() - } - } - } - } - } - } - val jobExecution = jobLauncher.run(job, JobParameters()) - - // then - assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) - assertThat(jobExecution.exitStatus.exitCode).isEqualTo(ExitStatus("TEST").exitCode) - assertThat(testStep1CallCount).isEqualTo(1) - assertThat(testDeciderCallCount).isEqualTo(1) - } - - @Test - fun testTransitionToDeciderVariable() { - // given - val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) - val jobLauncher = context.getBean() - val batch = context.getBean() - var testStep1CallCount = 0 - var testDeciderCallCount = 0 - val testStep1 = batch { - step("testStep1") { - tasklet( - { _, _ -> - ++testStep1CallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - val testDecider = JobExecutionDecider { _, _ -> - ++testDeciderCallCount - FlowExecutionStatus("SKIPPED") - } - - // when - val job = batch { - job("testJob") { - step(testStep1) { - on("COMPLETED") { - decider(testDecider) { - on("COMPLETED") { - fail() - } - on("SKIPPED") { - end("TEST") - } - on("*") { - end() - } - } - } - } - } - } - val jobExecution = jobLauncher.run(job, JobParameters()) - - // then - assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) - assertThat(jobExecution.exitStatus.exitCode).isEqualTo(ExitStatus("TEST").exitCode) - assertThat(testStep1CallCount).isEqualTo(1) - assertThat(testDeciderCallCount).isEqualTo(1) - } - - @Test - fun testTransitionToStop() { - // given - val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) - val jobLauncher = context.getBean() - val batch = context.getBean() - var testStep1CallCount = 0 - val testStep1 = batch { - step("testStep1") { - tasklet( - { _, _ -> - ++testStep1CallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - - // when - val job = batch { - job("testJob") { - step(testStep1) { - on("COMPLETED") { - stop() - } - } - } - } - val jobExecution = jobLauncher.run(job, JobParameters()) - - // then - assertThat(jobExecution.status).isEqualTo(BatchStatus.STOPPED) - assertThat(jobExecution.exitStatus.exitCode).isEqualTo(ExitStatus.STOPPED.exitCode) - assertThat(testStep1CallCount).isEqualTo(1) - } - - @Test - fun testTransitionToStopAndRestartToFlowBean() { - // given - val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) - val jobLauncher = context.getBean() - val batch = context.getBean() - var testStep1CallCount = 0 - var transitionStepCallCount = 0 - val testStep1 = batch { - step("testStep1") { - tasklet( - { _, _ -> - ++testStep1CallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - val transitionFlow = batch { - flow("transitionFlow") { - step("transitionStep") { - tasklet( - { _, _ -> - ++transitionStepCallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - } - context.registerBean("transitionFlow") { - transitionFlow - } - - // when - val job = batch { - job("testJob") { - step(testStep1) { - on("COMPLETED") { - stopAndRestartToFlowBean("transitionFlow") - } - } - } - } - val firstJobExecution = jobLauncher.run(job, JobParameters()) - val secondJobExecution = jobLauncher.run(job, JobParameters()) - val thirdJobExecution = jobLauncher.run(job, JobParameters()) - - // then - assertThat(firstJobExecution.status).isEqualTo(BatchStatus.STOPPED) - assertThat(firstJobExecution.exitStatus.exitCode).isEqualTo(ExitStatus.STOPPED.exitCode) - assertThat(secondJobExecution.status).isEqualTo(BatchStatus.COMPLETED) - assertThat(secondJobExecution.exitStatus.exitCode).isEqualTo(ExitStatus.COMPLETED.exitCode) - assertThat(thirdJobExecution.status).isEqualTo(BatchStatus.COMPLETED) - assertThat(thirdJobExecution.exitStatus.exitCode).isEqualTo(ExitStatus.NOOP.exitCode) - assertThat(testStep1CallCount).isEqualTo(1) - assertThat(transitionStepCallCount).isEqualTo(1) - } - - @Test - fun testTransitionToStopAndRestartToFlowWithInit() { - // given - val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) - val jobLauncher = context.getBean() - val batch = context.getBean() - var testStep1CallCount = 0 - var transitionStepCallCount = 0 - val testStep1 = batch { - step("testStep1") { - tasklet( - { _, _ -> - ++testStep1CallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - - // when - val job = batch { - job("testJob") { - step(testStep1) { - on("COMPLETED") { - stopAndRestartToFlow("transitionFlow") { - step("transitionStep") { - tasklet( - { _, _ -> - ++transitionStepCallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - } - } - } - } - val firstJobExecution = jobLauncher.run(job, JobParameters()) - val secondJobExecution = jobLauncher.run(job, JobParameters()) - val thirdJobExecution = jobLauncher.run(job, JobParameters()) - - // then - assertThat(firstJobExecution.status).isEqualTo(BatchStatus.STOPPED) - assertThat(firstJobExecution.exitStatus.exitCode).isEqualTo(ExitStatus.STOPPED.exitCode) - assertThat(secondJobExecution.status).isEqualTo(BatchStatus.COMPLETED) - assertThat(secondJobExecution.exitStatus.exitCode).isEqualTo(ExitStatus.COMPLETED.exitCode) - assertThat(thirdJobExecution.status).isEqualTo(BatchStatus.COMPLETED) - assertThat(thirdJobExecution.exitStatus.exitCode).isEqualTo(ExitStatus.NOOP.exitCode) - assertThat(testStep1CallCount).isEqualTo(1) - assertThat(transitionStepCallCount).isEqualTo(1) - } - - @Test - fun testTransitionToStopAndRestartToFlowVariable() { - // given - val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) - val jobLauncher = context.getBean() - val batch = context.getBean() - var testStep1CallCount = 0 - var transitionStepCallCount = 0 - val testStep1 = batch { - step("testStep1") { - tasklet( - { _, _ -> - ++testStep1CallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - val transitionFlow = batch { - flow("transitionFlow") { - step("transitionStep") { - tasklet( - { _, _ -> - ++transitionStepCallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - } - - // when - val job = batch { - job("testJob") { - step(testStep1) { - on("COMPLETED") { - stopAndRestartToFlow(transitionFlow) - } - } - } - } - val firstJobExecution = jobLauncher.run(job, JobParameters()) - val secondJobExecution = jobLauncher.run(job, JobParameters()) - val thirdJobExecution = jobLauncher.run(job, JobParameters()) - - // then - assertThat(firstJobExecution.status).isEqualTo(BatchStatus.STOPPED) - assertThat(firstJobExecution.exitStatus.exitCode).isEqualTo(ExitStatus.STOPPED.exitCode) - assertThat(secondJobExecution.status).isEqualTo(BatchStatus.COMPLETED) - assertThat(secondJobExecution.exitStatus.exitCode).isEqualTo(ExitStatus.COMPLETED.exitCode) - assertThat(thirdJobExecution.status).isEqualTo(BatchStatus.COMPLETED) - assertThat(thirdJobExecution.exitStatus.exitCode).isEqualTo(ExitStatus.NOOP.exitCode) - assertThat(testStep1CallCount).isEqualTo(1) - assertThat(transitionStepCallCount).isEqualTo(1) - } - - @Test - fun testTransitionToStopAndRestartToFlowBeanWithTransition() { - // given - val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) - val jobLauncher = context.getBean() - val batch = context.getBean() - var testStep1CallCount = 0 - var transitionStepCallCount = 0 - val testStep1 = batch { - step("testStep1") { - tasklet( - { _, _ -> - ++testStep1CallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - val transitionFlow = batch { - flow("transitionFlow") { - step("transitionStep") { - tasklet( - { _, _ -> - ++transitionStepCallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - } - context.registerBean("transitionFlow") { - transitionFlow - } - - // when - val job = batch { - job("testJob") { - step(testStep1) { - on("COMPLETED") { - stopAndRestartToFlowBean("transitionFlow") { - on("COMPLETED") { - end("TEST") - } - on("*") { - stop() - } - } - } - } - } - } - val firstJobExecution = jobLauncher.run(job, JobParameters()) - val secondJobExecution = jobLauncher.run(job, JobParameters()) - val thirdJobExecution = jobLauncher.run(job, JobParameters()) - - // then - assertThat(firstJobExecution.status).isEqualTo(BatchStatus.STOPPED) - assertThat(firstJobExecution.exitStatus.exitCode).isEqualTo(ExitStatus.STOPPED.exitCode) - assertThat(secondJobExecution.status).isEqualTo(BatchStatus.COMPLETED) - assertThat(secondJobExecution.exitStatus.exitCode).isEqualTo(ExitStatus("TEST").exitCode) - assertThat(thirdJobExecution.status).isEqualTo(BatchStatus.COMPLETED) - assertThat(thirdJobExecution.exitStatus.exitCode).isEqualTo(ExitStatus("TEST").exitCode) - assertThat(testStep1CallCount).isEqualTo(1) - assertThat(transitionStepCallCount).isEqualTo(1) - } - - @Test - fun testTransitionToStopAndRestartToFlowWithInitAndTransition() { - // given - val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) - val jobLauncher = context.getBean() - val batch = context.getBean() - var testStep1CallCount = 0 - var transitionStepCallCount = 0 - val testStep1 = batch { - step("testStep1") { - tasklet( - { _, _ -> - ++testStep1CallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - - // when - val job = batch { - job("testJob") { - step(testStep1) { - on("COMPLETED") { - stopAndRestartToFlow("transitionFlow", { - step("transitionStep") { - tasklet( - { _, _ -> - ++transitionStepCallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - },) { - on("COMPLETED") { - end("TEST") - } - on("*") { - stop() - } - } - } - } - } - } - val firstJobExecution = jobLauncher.run(job, JobParameters()) - val secondJobExecution = jobLauncher.run(job, JobParameters()) - val thirdJobExecution = jobLauncher.run(job, JobParameters()) - - // then - assertThat(firstJobExecution.status).isEqualTo(BatchStatus.STOPPED) - assertThat(firstJobExecution.exitStatus.exitCode).isEqualTo(ExitStatus.STOPPED.exitCode) - assertThat(secondJobExecution.status).isEqualTo(BatchStatus.COMPLETED) - assertThat(secondJobExecution.exitStatus.exitCode).isEqualTo(ExitStatus("TEST").exitCode) - assertThat(thirdJobExecution.status).isEqualTo(BatchStatus.COMPLETED) - assertThat(thirdJobExecution.exitStatus.exitCode).isEqualTo(ExitStatus("TEST").exitCode) - assertThat(testStep1CallCount).isEqualTo(1) - assertThat(transitionStepCallCount).isEqualTo(1) - } - - @Test - fun testTransitionToStopAndRestartToFlowVariableWithTransition() { - // given - val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) - val jobLauncher = context.getBean() - val batch = context.getBean() - var testStep1CallCount = 0 - var transitionStepCallCount = 0 - val testStep1 = batch { - step("testStep1") { - tasklet( - { _, _ -> - ++testStep1CallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - val transitionFlow = batch { - flow("transitionFlow") { - step("transitionStep") { - tasklet( - { _, _ -> - ++transitionStepCallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - } - - // when - val job = batch { - job("testJob") { - step(testStep1) { - on("COMPLETED") { - stopAndRestartToFlow(transitionFlow) { - on("COMPLETED") { - end("TEST") - } - on("*") { - stop() - } - } - } - } - } - } - val firstJobExecution = jobLauncher.run(job, JobParameters()) - val secondJobExecution = jobLauncher.run(job, JobParameters()) - val thirdJobExecution = jobLauncher.run(job, JobParameters()) - - // then - assertThat(firstJobExecution.status).isEqualTo(BatchStatus.STOPPED) - assertThat(firstJobExecution.exitStatus.exitCode).isEqualTo(ExitStatus.STOPPED.exitCode) - assertThat(secondJobExecution.status).isEqualTo(BatchStatus.COMPLETED) - assertThat(secondJobExecution.exitStatus.exitCode).isEqualTo(ExitStatus("TEST").exitCode) - assertThat(thirdJobExecution.status).isEqualTo(BatchStatus.COMPLETED) - assertThat(thirdJobExecution.exitStatus.exitCode).isEqualTo(ExitStatus("TEST").exitCode) - assertThat(testStep1CallCount).isEqualTo(1) - assertThat(transitionStepCallCount).isEqualTo(1) - } - - @Test - fun testTransitionToStopAndRestartToDeciderBean() { - // given - val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) - val jobLauncher = context.getBean() - val batch = context.getBean() - var testStep1CallCount = 0 - var testDeciderCallCount = 0 - var transitionStepCallCount = 0 - val testStep1 = batch { - step("testStep1") { - tasklet( - { _, _ -> - ++testStep1CallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - val testDecider = JobExecutionDecider { _, _ -> - ++testDeciderCallCount - FlowExecutionStatus.UNKNOWN - } - context.registerBean("testDecider") { - testDecider - } - - // when - val job = batch { - job("testJob") { - step(testStep1) { - on("COMPLETED") { - stopAndRestartToDeciderBean("testDecider") { - on("UNKNOWN") { - step("transitionStep") { - tasklet( - { _, _ -> - ++transitionStepCallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - on("*") { - fail() - } - } - } - } - } - } - val firstJobExecution = jobLauncher.run(job, JobParameters()) - val secondJobExecution = jobLauncher.run(job, JobParameters()) - val thirdJobExecution = jobLauncher.run(job, JobParameters()) - - // then - assertThat(firstJobExecution.status).isEqualTo(BatchStatus.STOPPED) - assertThat(firstJobExecution.exitStatus.exitCode).isEqualTo(ExitStatus.STOPPED.exitCode) - assertThat(secondJobExecution.status).isEqualTo(BatchStatus.COMPLETED) - assertThat(secondJobExecution.exitStatus.exitCode).isEqualTo(ExitStatus.COMPLETED.exitCode) - assertThat(thirdJobExecution.status).isEqualTo(BatchStatus.COMPLETED) - assertThat(thirdJobExecution.exitStatus.exitCode).isEqualTo(ExitStatus.NOOP.exitCode) - assertThat(testStep1CallCount).isEqualTo(1) - assertThat(testDeciderCallCount).isEqualTo(2) // always run on restart - assertThat(transitionStepCallCount).isEqualTo(1) - } - - @Test - fun testTransitionToStopAndRestartToDeciderVariable() { - // given - val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) - val jobLauncher = context.getBean() - val batch = context.getBean() - var testStep1CallCount = 0 - var testDeciderCallCount = 0 - var transitionStepCallCount = 0 - val testStep1 = batch { - step("testStep1") { - tasklet( - { _, _ -> - ++testStep1CallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - - // when - val job = batch { - job("testJob") { - step(testStep1) { - on("COMPLETED") { - stopAndRestartToDecider( - { _, _ -> - ++testDeciderCallCount - FlowExecutionStatus.UNKNOWN - }, - ) { - on("UNKNOWN") { - step("transitionStep") { - tasklet( - { _, _ -> - ++transitionStepCallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - on("*") { - fail() - } - } - } - } - } - } - val firstJobExecution = jobLauncher.run(job, JobParameters()) - val secondJobExecution = jobLauncher.run(job, JobParameters()) - val thirdJobExecution = jobLauncher.run(job, JobParameters()) - - // then - assertThat(firstJobExecution.status).isEqualTo(BatchStatus.STOPPED) - assertThat(firstJobExecution.exitStatus.exitCode).isEqualTo(ExitStatus.STOPPED.exitCode) - assertThat(secondJobExecution.status).isEqualTo(BatchStatus.COMPLETED) - assertThat(secondJobExecution.exitStatus.exitCode).isEqualTo(ExitStatus.COMPLETED.exitCode) - assertThat(thirdJobExecution.status).isEqualTo(BatchStatus.COMPLETED) - assertThat(thirdJobExecution.exitStatus.exitCode).isEqualTo(ExitStatus.NOOP.exitCode) - assertThat(testStep1CallCount).isEqualTo(1) - assertThat(testDeciderCallCount).isEqualTo(2) // always run on restart - assertThat(transitionStepCallCount).isEqualTo(1) - } - - @Test - fun testTransitionToStopAndRestartToStepBean() { - // given - val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) - val jobLauncher = context.getBean() - val batch = context.getBean() - var testStep1CallCount = 0 - var transitionStepCallCount = 0 - val testStep1 = batch { - step("testStep1") { - tasklet( - { _, _ -> - ++testStep1CallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - val transitionStep = batch { - step("transitionStep") { - tasklet( - { _, _ -> - ++transitionStepCallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - context.registerBean("transitionStep") { - transitionStep - } - - // when - val job = batch { - job("testJob") { - step(testStep1) { - on("COMPLETED") { - stopAndRestartToStepBean("transitionStep") - } - } - } - } - val firstJobExecution = jobLauncher.run(job, JobParameters()) - val secondJobExecution = jobLauncher.run(job, JobParameters()) - val thirdJobExecution = jobLauncher.run(job, JobParameters()) - - // then - assertThat(firstJobExecution.status).isEqualTo(BatchStatus.STOPPED) - assertThat(firstJobExecution.exitStatus.exitCode).isEqualTo(ExitStatus.STOPPED.exitCode) - assertThat(secondJobExecution.status).isEqualTo(BatchStatus.COMPLETED) - assertThat(secondJobExecution.exitStatus.exitCode).isEqualTo(ExitStatus.COMPLETED.exitCode) - assertThat(thirdJobExecution.status).isEqualTo(BatchStatus.COMPLETED) - assertThat(thirdJobExecution.exitStatus.exitCode).isEqualTo(ExitStatus.NOOP.exitCode) - assertThat(testStep1CallCount).isEqualTo(1) - assertThat(transitionStepCallCount).isEqualTo(1) - } - - @Test - fun testTransitionToStopAndRestartToStepWithInit() { - // given - val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) - val jobLauncher = context.getBean() - val batch = context.getBean() - var testStep1CallCount = 0 - var transitionStepCallCount = 0 - val testStep1 = batch { - step("testStep1") { - tasklet( - { _, _ -> - ++testStep1CallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - - // when - val job = batch { - job("testJob") { - step(testStep1) { - on("COMPLETED") { - stopAndRestartToStep("transitionStep") { - tasklet( - { _, _ -> - ++transitionStepCallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - } - } - } - val firstJobExecution = jobLauncher.run(job, JobParameters()) - val secondJobExecution = jobLauncher.run(job, JobParameters()) - val thirdJobExecution = jobLauncher.run(job, JobParameters()) - - // then - assertThat(firstJobExecution.status).isEqualTo(BatchStatus.STOPPED) - assertThat(firstJobExecution.exitStatus.exitCode).isEqualTo(ExitStatus.STOPPED.exitCode) - assertThat(secondJobExecution.status).isEqualTo(BatchStatus.COMPLETED) - assertThat(secondJobExecution.exitStatus.exitCode).isEqualTo(ExitStatus.COMPLETED.exitCode) - assertThat(thirdJobExecution.status).isEqualTo(BatchStatus.COMPLETED) - assertThat(thirdJobExecution.exitStatus.exitCode).isEqualTo(ExitStatus.NOOP.exitCode) - assertThat(testStep1CallCount).isEqualTo(1) - assertThat(transitionStepCallCount).isEqualTo(1) - } - - @Test - fun testTransitionToStopAndRestartToStepVariable() { - // given - val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) - val jobLauncher = context.getBean() - val batch = context.getBean() - var testStep1CallCount = 0 - var transitionStepCallCount = 0 - val testStep1 = batch { - step("testStep1") { - tasklet( - { _, _ -> - ++testStep1CallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - val transitionStep = batch { - step("transitionStep") { - tasklet( - { _, _ -> - ++transitionStepCallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - - // when - val job = batch { - job("testJob") { - step(testStep1) { - on("COMPLETED") { - stopAndRestartToStep(transitionStep) - } - } - } - } - val firstJobExecution = jobLauncher.run(job, JobParameters()) - val secondJobExecution = jobLauncher.run(job, JobParameters()) - val thirdJobExecution = jobLauncher.run(job, JobParameters()) - - // then - assertThat(firstJobExecution.status).isEqualTo(BatchStatus.STOPPED) - assertThat(firstJobExecution.exitStatus.exitCode).isEqualTo(ExitStatus.STOPPED.exitCode) - assertThat(secondJobExecution.status).isEqualTo(BatchStatus.COMPLETED) - assertThat(secondJobExecution.exitStatus.exitCode).isEqualTo(ExitStatus.COMPLETED.exitCode) - assertThat(thirdJobExecution.status).isEqualTo(BatchStatus.COMPLETED) - assertThat(thirdJobExecution.exitStatus.exitCode).isEqualTo(ExitStatus.NOOP.exitCode) - assertThat(testStep1CallCount).isEqualTo(1) - assertThat(transitionStepCallCount).isEqualTo(1) - } - - @Test - fun testTransitionToStopAndRestartToStepBeanWithTransition() { - // given - val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) - val jobLauncher = context.getBean() - val batch = context.getBean() - var testStep1CallCount = 0 - var transitionStepCallCount = 0 - val testStep1 = batch { - step("testStep1") { - tasklet( - { _, _ -> - ++testStep1CallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - val transitionStep = batch { - step("transitionStep") { - tasklet( - { _, _ -> - ++transitionStepCallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - context.registerBean("transitionStep") { - transitionStep - } - - // when - val job = batch { - job("testJob") { - step(testStep1) { - on("COMPLETED") { - stopAndRestartToStepBean("transitionStep") { - on("COMPLETED") { - end("TEST") - } - on("*") { - stop() - } - } - } - } - } - } - val firstJobExecution = jobLauncher.run(job, JobParameters()) - val secondJobExecution = jobLauncher.run(job, JobParameters()) - val thirdJobExecution = jobLauncher.run(job, JobParameters()) - - // then - assertThat(firstJobExecution.status).isEqualTo(BatchStatus.STOPPED) - assertThat(firstJobExecution.exitStatus.exitCode).isEqualTo(ExitStatus.STOPPED.exitCode) - assertThat(secondJobExecution.status).isEqualTo(BatchStatus.COMPLETED) - assertThat(secondJobExecution.exitStatus.exitCode).isEqualTo(ExitStatus("TEST").exitCode) - assertThat(thirdJobExecution.status).isEqualTo(BatchStatus.COMPLETED) - assertThat(thirdJobExecution.exitStatus.exitCode).isEqualTo(ExitStatus("TEST").exitCode) - assertThat(testStep1CallCount).isEqualTo(1) - assertThat(transitionStepCallCount).isEqualTo(1) - } - - @Test - fun testTransitionToStopAndRestartToStepWithInitAndTransition() { - // given - val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) - val jobLauncher = context.getBean() - val batch = context.getBean() - var testStep1CallCount = 0 - var transitionStepCallCount = 0 - val testStep1 = batch { - step("testStep1") { - tasklet( - { _, _ -> - ++testStep1CallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - - // when - val job = batch { - job("testJob") { - step(testStep1) { - on("COMPLETED") { - stopAndRestartToStep("transitionStep", { - tasklet( - { _, _ -> - ++transitionStepCallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - },) { - on("COMPLETED") { - end("TEST") - } - on("*") { - stop() - } - } - } - } - } - } - val firstJobExecution = jobLauncher.run(job, JobParameters()) - val secondJobExecution = jobLauncher.run(job, JobParameters()) - val thirdJobExecution = jobLauncher.run(job, JobParameters()) - - // then - assertThat(firstJobExecution.status).isEqualTo(BatchStatus.STOPPED) - assertThat(firstJobExecution.exitStatus.exitCode).isEqualTo(ExitStatus.STOPPED.exitCode) - assertThat(secondJobExecution.status).isEqualTo(BatchStatus.COMPLETED) - assertThat(secondJobExecution.exitStatus.exitCode).isEqualTo(ExitStatus("TEST").exitCode) - assertThat(thirdJobExecution.status).isEqualTo(BatchStatus.COMPLETED) - assertThat(thirdJobExecution.exitStatus.exitCode).isEqualTo(ExitStatus("TEST").exitCode) - assertThat(testStep1CallCount).isEqualTo(1) - assertThat(transitionStepCallCount).isEqualTo(1) - } - - @Test - fun testTransitionToStopAndRestartToStepVariableWithTransition() { - // given - val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) - val jobLauncher = context.getBean() - val batch = context.getBean() - var testStep1CallCount = 0 - var transitionStepCallCount = 0 - val testStep1 = batch { - step("testStep1") { - tasklet( - { _, _ -> - ++testStep1CallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - val transitionStep = batch { - step("transitionStep") { - tasklet( - { _, _ -> - ++transitionStepCallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - - // when - val job = batch { - job("testJob") { - step(testStep1) { - on("COMPLETED") { - stopAndRestartToStep(transitionStep) { - on("COMPLETED") { - end("TEST") - } - on("*") { - stop() - } - } - } - } - } - } - val firstJobExecution = jobLauncher.run(job, JobParameters()) - val secondJobExecution = jobLauncher.run(job, JobParameters()) - val thirdJobExecution = jobLauncher.run(job, JobParameters()) - - // then - assertThat(firstJobExecution.status).isEqualTo(BatchStatus.STOPPED) - assertThat(firstJobExecution.exitStatus.exitCode).isEqualTo(ExitStatus.STOPPED.exitCode) - assertThat(secondJobExecution.status).isEqualTo(BatchStatus.COMPLETED) - assertThat(secondJobExecution.exitStatus.exitCode).isEqualTo(ExitStatus("TEST").exitCode) - assertThat(thirdJobExecution.status).isEqualTo(BatchStatus.COMPLETED) - assertThat(thirdJobExecution.exitStatus.exitCode).isEqualTo(ExitStatus("TEST").exitCode) - assertThat(testStep1CallCount).isEqualTo(1) - assertThat(transitionStepCallCount).isEqualTo(1) - } - - @Test - fun testTransitionToEnd() { - // given - val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) - val jobLauncher = context.getBean() - val batch = context.getBean() - var testStep1CallCount = 0 - val testStep1 = batch { - step("testStep1") { - tasklet( - { contribution, _ -> - ++testStep1CallCount - contribution.exitStatus = ExitStatus.UNKNOWN - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - - // when - val job = batch { - job("testJob") { - step(testStep1) { - on("UNKNOWN") { - end() - } - } - } - } - val jobExecution = jobLauncher.run(job, JobParameters()) - - // then - assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) - assertThat(jobExecution.exitStatus.exitCode).isEqualTo(ExitStatus.COMPLETED.exitCode) - assertThat(testStep1CallCount).isEqualTo(1) - } - - @Test - fun testTransitionToEndWithStatus() { - // given - val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) - val jobLauncher = context.getBean() - val batch = context.getBean() - var testStep1CallCount = 0 - val testStep1 = batch { - step("testStep1") { - tasklet( - { contribution, _ -> - ++testStep1CallCount - contribution.exitStatus = ExitStatus.UNKNOWN - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - - // when - val job = batch { - job("testJob") { - step(testStep1) { - on("UNKNOWN") { - end("TEST") - } - on("*") { - end() - } - } - } - } - val jobExecution = jobLauncher.run(job, JobParameters()) - - // then - assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) - assertThat(jobExecution.exitStatus.exitCode).isEqualTo(ExitStatus("TEST").exitCode) - assertThat(testStep1CallCount).isEqualTo(1) - } - - @Test - fun testTransitionToFail() { - // given - val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) - val jobLauncher = context.getBean() - val batch = context.getBean() - var testStep1CallCount = 0 - val testStep1 = batch { - step("testStep1") { - tasklet( - { _, _ -> - ++testStep1CallCount - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - - // when - val job = batch { - job("testJob") { - step(testStep1) { - on("COMPLETED") { - fail() - } - } - } - } - val jobExecution = jobLauncher.run(job, JobParameters()) - - // then - assertThat(jobExecution.status).isEqualTo(BatchStatus.FAILED) - assertThat(jobExecution.exitStatus.exitCode).isEqualTo(ExitStatus.FAILED.exitCode) - assertThat(testStep1CallCount).isEqualTo(1) - } - - @Test - fun testNoTransition() { - // given - val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) - val batch = context.getBean() - val testStep1 = batch { - step("testStep1") { - tasklet( - { _, _ -> - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) - } - } - - // when, then - assertThatThrownBy { - batch { - job("testJob") { - step(testStep1) { - on("COMPLETED") { - } - } - } - } - }.hasMessageContaining("should set transition") - } - - @Configuration - @EnableBatchProcessing( - dataSourceRef = "metadataDataSource", - transactionManagerRef = "metadataTransactionManager", - ) - private open class TestConfiguration { - - @Bean - open fun batchDsl( - beanFactory: BeanFactory, - jobRepository: JobRepository, - ): BatchDsl = BatchDsl( - beanFactory, - jobRepository, - ) - - @Bean - open fun metadataTransactionManager(): TransactionManager { - return DataSourceTransactionManager(metadataDataSource()) - } - - @Bean - open fun metadataDataSource(): DataSource { - return EmbeddedDatabaseBuilder() - .setType(EmbeddedDatabaseType.H2) - .addScript("/org/springframework/batch/core/schema-h2.sql") - .generateUniqueName(true) - .build() - } - } -} diff --git a/spring-batch-plus-kotlin/src/integrationTest/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/job/decider/JobBuilderDslDeciderCreationIntegrationTest.kt b/spring-batch-plus-kotlin/src/integrationTest/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/job/decider/JobBuilderDslDeciderCreationIntegrationTest.kt new file mode 100644 index 00000000..26fa027c --- /dev/null +++ b/spring-batch-plus-kotlin/src/integrationTest/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/job/decider/JobBuilderDslDeciderCreationIntegrationTest.kt @@ -0,0 +1,235 @@ +/* + * Spring Batch Plus + * + * Copyright 2022-present NAVER Corp. + * + * 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 + * + * http://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 com.navercorp.spring.batch.plus.kotlin.configuration.job.decider + +import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test +import org.springframework.batch.core.BatchStatus +import org.springframework.batch.core.ExitStatus +import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing +import org.springframework.batch.core.configuration.annotation.EnableJdbcJobRepository +import org.springframework.batch.core.job.flow.FlowExecutionStatus +import org.springframework.batch.core.job.flow.JobExecutionDecider +import org.springframework.batch.core.job.parameters.JobParameters +import org.springframework.batch.core.launch.JobOperator +import org.springframework.batch.core.repository.JobRepository +import org.springframework.batch.infrastructure.repeat.RepeatStatus +import org.springframework.batch.infrastructure.support.transaction.ResourcelessTransactionManager +import org.springframework.beans.factory.BeanFactory +import org.springframework.beans.factory.getBean +import org.springframework.context.annotation.AnnotationConfigApplicationContext +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import org.springframework.context.support.registerBean +import org.springframework.jdbc.datasource.DataSourceTransactionManager +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType +import org.springframework.transaction.TransactionManager +import javax.sql.DataSource + +/** + * Covers the boundary where introducing a decider selects flow-job construction at any state position. + */ +internal class JobBuilderDslDeciderCreationIntegrationTest { + @Test + fun deciderBeanShouldExecuteAsFirstStateWhenBeanNameIsProvided() { + // given + val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) + val jobOperator = context.getBean() + val batch = context.getBean() + var testDeciderCallCount = 0 + val testDecider = + JobExecutionDecider { _, _ -> + ++testDeciderCallCount + FlowExecutionStatus.COMPLETED + } + context.registerBean("testDecider") { + testDecider + } + + // when + val job = + batch { + job("testJob") { + deciderBean("testDecider") { + on("COMPLETED") { + end("TEST") + } + } + } + } + val jobExecution = jobOperator.start(job, JobParameters()) + + // then + assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) + assertThat(jobExecution.exitStatus.exitCode).isEqualTo(ExitStatus("TEST").exitCode) + assertThat(testDeciderCallCount).isEqualTo(1) + } + + @Test + fun deciderBeanShouldExecuteAfterStepWhenBeanNameIsProvided() { + // given + val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) + val jobOperator = context.getBean() + val batch = context.getBean() + var testStep1CallCount = 0 + var testDeciderCallCount = 0 + val testDecider = + JobExecutionDecider { _, _ -> + ++testDeciderCallCount + FlowExecutionStatus.COMPLETED + } + context.registerBean("testDecider") { + testDecider + } + + // when + val job = + batch { + job("testJob") { + step("testStep1") { + tasklet( + { _, _ -> + ++testStep1CallCount + RepeatStatus.FINISHED + }, + ResourcelessTransactionManager(), + ) + } + deciderBean("testDecider") { + on("COMPLETED") { + end("TEST") + } + } + } + } + val jobExecution = jobOperator.start(job, JobParameters()) + + // then + assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) + assertThat(jobExecution.exitStatus.exitCode).isEqualTo(ExitStatus("TEST").exitCode) + assertThat(testStep1CallCount).isEqualTo(1) + assertThat(testDeciderCallCount).isEqualTo(1) + } + + @Test + fun deciderShouldExecuteAsFirstStateWhenInstanceIsProvided() { + // given + val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) + val jobOperator = context.getBean() + val batch = context.getBean() + var testDeciderCallCount = 0 + val decider = + JobExecutionDecider { _, _ -> + ++testDeciderCallCount + FlowExecutionStatus.COMPLETED + } + + // when + val job = + batch { + job("testJob") { + decider(decider) { + on("COMPLETED") { + end("TEST") + } + } + } + } + val jobExecution = jobOperator.start(job, JobParameters()) + + // then + assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) + assertThat(jobExecution.exitStatus.exitCode).isEqualTo(ExitStatus("TEST").exitCode) + assertThat(testDeciderCallCount).isEqualTo(1) + } + + @Test + fun deciderShouldExecuteAfterStepWhenInstanceIsProvided() { + // given + val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) + val jobOperator = context.getBean() + val batch = context.getBean() + var testStep1CallCount = 0 + var testDeciderCallCount = 0 + val decider = + JobExecutionDecider { _, _ -> + ++testDeciderCallCount + FlowExecutionStatus.COMPLETED + } + + // when + val job = + batch { + job("testJob") { + step("testStep1") { + tasklet( + { _, _ -> + ++testStep1CallCount + RepeatStatus.FINISHED + }, + ResourcelessTransactionManager(), + ) + } + decider(decider) { + on("COMPLETED") { + end("TEST") + } + } + } + } + val jobExecution = jobOperator.start(job, JobParameters()) + + // then + assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) + assertThat(jobExecution.exitStatus.exitCode).isEqualTo(ExitStatus("TEST").exitCode) + assertThat(testStep1CallCount).isEqualTo(1) + assertThat(testDeciderCallCount).isEqualTo(1) + } + + @Configuration + @EnableBatchProcessing + @EnableJdbcJobRepository( + dataSourceRef = "metadataDataSource", + transactionManagerRef = "metadataTransactionManager", + ) + private open class TestConfiguration { + @Bean + open fun batchDsl( + beanFactory: BeanFactory, + jobRepository: JobRepository, + ): BatchDsl = + BatchDsl( + beanFactory, + jobRepository, + ) + + @Bean + open fun metadataTransactionManager(): TransactionManager = DataSourceTransactionManager(metadataDataSource()) + + @Bean + open fun metadataDataSource(): DataSource = + EmbeddedDatabaseBuilder() + .setType(EmbeddedDatabaseType.H2) + .addScript("/org/springframework/batch/core/schema-h2.sql") + .generateUniqueName(true) + .build() + } +} diff --git a/spring-batch-plus-kotlin/src/integrationTest/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/DeciderTransitionBuilderDslIntegrationTest.kt b/spring-batch-plus-kotlin/src/integrationTest/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/job/decider/transition/DeciderTransitionBuilderDslIntegrationTest.kt similarity index 72% rename from spring-batch-plus-kotlin/src/integrationTest/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/DeciderTransitionBuilderDslIntegrationTest.kt rename to spring-batch-plus-kotlin/src/integrationTest/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/job/decider/transition/DeciderTransitionBuilderDslIntegrationTest.kt index 0dfbc5b1..2504a310 100644 --- a/spring-batch-plus-kotlin/src/integrationTest/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/DeciderTransitionBuilderDslIntegrationTest.kt +++ b/spring-batch-plus-kotlin/src/integrationTest/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/job/decider/transition/DeciderTransitionBuilderDslIntegrationTest.kt @@ -16,19 +16,21 @@ * limitations under the License. */ -package com.navercorp.spring.batch.plus.kotlin.configuration +package com.navercorp.spring.batch.plus.kotlin.configuration.job.decider.transition +import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl import org.assertj.core.api.Assertions.assertThat import org.assertj.core.api.Assertions.assertThatThrownBy import org.junit.jupiter.api.RepeatedTest import org.junit.jupiter.api.Test import org.springframework.batch.core.BatchStatus import org.springframework.batch.core.ExitStatus -import org.springframework.batch.core.JobParameters import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing +import org.springframework.batch.core.configuration.annotation.EnableJdbcJobRepository import org.springframework.batch.core.job.flow.FlowExecutionStatus import org.springframework.batch.core.job.flow.JobExecutionDecider -import org.springframework.batch.core.launch.JobLauncher +import org.springframework.batch.core.job.parameters.JobParameters +import org.springframework.batch.core.launch.JobOperator import org.springframework.batch.core.repository.JobRepository import org.springframework.beans.factory.BeanFactory import org.springframework.beans.factory.getBean @@ -41,35 +43,39 @@ import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType import org.springframework.transaction.TransactionManager import javax.sql.DataSource +/** + * Covers source reselection after the first `on` clause. + */ internal class DeciderTransitionBuilderDslIntegrationTest { - @RepeatedTest(10) - fun testDeciderWithMultipleTransition() { + fun deciderShouldFollowMatchingTransitionWhenMultipleTransitionsAreConfigured() { // given val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) - val jobLauncher = context.getBean() + val jobOperator = context.getBean() val batch = context.getBean() val expectedFlowExecutionStatus = randomFlowExecutionStatus() var testDeciderCallCount = 0 - val testDecider = JobExecutionDecider { _, _ -> - ++testDeciderCallCount - expectedFlowExecutionStatus - } + val testDecider = + JobExecutionDecider { _, _ -> + ++testDeciderCallCount + expectedFlowExecutionStatus + } // when - val job = batch { - job("testJob") { - decider(testDecider) { - on("UNKNOWN") { - end() - } - on("*") { - fail() + val job = + batch { + job("testJob") { + decider(testDecider) { + on("UNKNOWN") { + end() + } + on("*") { + fail() + } } } } - } - val jobExecution = jobLauncher.run(job, JobParameters()) + val jobExecution = jobOperator.start(job, JobParameters()) // then assertThat(testDeciderCallCount).isEqualTo(1) @@ -93,63 +99,60 @@ internal class DeciderTransitionBuilderDslIntegrationTest { } @Test - fun testStepWithNoTransition() { + fun deciderShouldThrowExceptionWhenTransitionBlockIsEmpty() { // given val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) val batch = context.getBean() - val testDecider = JobExecutionDecider { _, _ -> - FlowExecutionStatus.COMPLETED - } + val testDecider = + JobExecutionDecider { _, _ -> + FlowExecutionStatus.COMPLETED + } // when, then assertThatThrownBy { batch { job("testJob") { decider(testDecider) { - // no transition } } } }.hasMessageContaining("should set transition for decider") } - private fun randomFlowExecutionStatus(): FlowExecutionStatus { - return listOf( + private fun randomFlowExecutionStatus(): FlowExecutionStatus = + listOf( FlowExecutionStatus.COMPLETED, FlowExecutionStatus.FAILED, FlowExecutionStatus.UNKNOWN, FlowExecutionStatus.STOPPED, // when stopped, just stop the job ).random() - } @Configuration - @EnableBatchProcessing( + @EnableBatchProcessing + @EnableJdbcJobRepository( dataSourceRef = "metadataDataSource", transactionManagerRef = "metadataTransactionManager", ) private open class TestConfiguration { - @Bean open fun batchDsl( beanFactory: BeanFactory, jobRepository: JobRepository, - ): BatchDsl = BatchDsl( - beanFactory, - jobRepository, - ) + ): BatchDsl = + BatchDsl( + beanFactory, + jobRepository, + ) @Bean - open fun metadataTransactionManager(): TransactionManager { - return DataSourceTransactionManager(metadataDataSource()) - } + open fun metadataTransactionManager(): TransactionManager = DataSourceTransactionManager(metadataDataSource()) @Bean - open fun metadataDataSource(): DataSource { - return EmbeddedDatabaseBuilder() + open fun metadataDataSource(): DataSource = + EmbeddedDatabaseBuilder() .setType(EmbeddedDatabaseType.H2) .addScript("/org/springframework/batch/core/schema-h2.sql") .generateUniqueName(true) .build() - } } } diff --git a/spring-batch-plus-kotlin/src/integrationTest/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/job/flow/JobBuilderDslFlowCreationIntegrationTest.kt b/spring-batch-plus-kotlin/src/integrationTest/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/job/flow/JobBuilderDslFlowCreationIntegrationTest.kt new file mode 100644 index 00000000..b1eef206 --- /dev/null +++ b/spring-batch-plus-kotlin/src/integrationTest/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/job/flow/JobBuilderDslFlowCreationIntegrationTest.kt @@ -0,0 +1,548 @@ +/* + * Spring Batch Plus + * + * Copyright 2022-present NAVER Corp. + * + * 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 + * + * http://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 com.navercorp.spring.batch.plus.kotlin.configuration.job.flow + +import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test +import org.springframework.batch.core.BatchStatus +import org.springframework.batch.core.ExitStatus +import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing +import org.springframework.batch.core.configuration.annotation.EnableJdbcJobRepository +import org.springframework.batch.core.job.flow.FlowJob +import org.springframework.batch.core.job.parameters.JobParameters +import org.springframework.batch.core.launch.JobOperator +import org.springframework.batch.core.repository.JobRepository +import org.springframework.batch.infrastructure.repeat.RepeatStatus +import org.springframework.batch.infrastructure.support.transaction.ResourcelessTransactionManager +import org.springframework.beans.factory.BeanFactory +import org.springframework.beans.factory.getBean +import org.springframework.context.annotation.AnnotationConfigApplicationContext +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import org.springframework.context.support.registerBean +import org.springframework.jdbc.datasource.DataSourceTransactionManager +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType +import org.springframework.transaction.TransactionManager +import javax.sql.DataSource + +/** + * Covers the boundary where introducing a flow selects flow-job construction. + */ +internal class JobBuilderDslFlowCreationIntegrationTest { + @Test + fun flowBeanShouldCreateFlowJobWhenFlowBeanNamesAreProvided() { + // given + val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) + val jobOperator = context.getBean() + val batch = context.getBean() + var testStep1CallCount = 0 + var testStep2CallCount = 0 + val testFlow1 = + batch { + flow("testFlow1") { + step("testStep1") { + tasklet( + { _, _ -> + ++testStep1CallCount + RepeatStatus.FINISHED + }, + ResourcelessTransactionManager(), + ) + } + } + } + val testFlow2 = + batch { + flow("testFlow2") { + step("testStep2") { + tasklet( + { _, _ -> + ++testStep2CallCount + RepeatStatus.FINISHED + }, + ResourcelessTransactionManager(), + ) + } + } + } + context.apply { + registerBean("testFlow1") { + testFlow1 + } + registerBean("testFlow2") { + testFlow2 + } + } + + // when + val job = + batch { + job("testJob") { + flowBean("testFlow1") + flowBean("testFlow2") + } + } + val jobExecution = jobOperator.start(job, JobParameters()) + + // then + assertThat(job).isInstanceOf(FlowJob::class.java) + assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) + assertThat(jobExecution.exitStatus.exitCode).isEqualTo(ExitStatus.COMPLETED.exitCode) + assertThat(testStep1CallCount).isEqualTo(1) + assertThat(testStep2CallCount).isEqualTo(1) + } + + @Test + fun flowShouldCreateFlowJobWhenFlowsAreDeclaredWithInit() { + // given + val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) + val jobOperator = context.getBean() + val batch = context.getBean() + var testStep1CallCount = 0 + var testStep2CallCount = 0 + + // when + val job = + batch { + job("testJob") { + flow("testFlow1") { + step("testStep1") { + tasklet( + { _, _ -> + ++testStep1CallCount + RepeatStatus.FINISHED + }, + ResourcelessTransactionManager(), + ) + } + } + flow("testFlow2") { + step("testStep2") { + tasklet( + { _, _ -> + ++testStep2CallCount + RepeatStatus.FINISHED + }, + ResourcelessTransactionManager(), + ) + } + } + } + } + val jobExecution = jobOperator.start(job, JobParameters()) + + // then + assertThat(job).isInstanceOf(FlowJob::class.java) + assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) + assertThat(jobExecution.exitStatus.exitCode).isEqualTo(ExitStatus.COMPLETED.exitCode) + assertThat(testStep1CallCount).isEqualTo(1) + assertThat(testStep2CallCount).isEqualTo(1) + } + + @Test + fun flowShouldCreateFlowJobWhenInitialStepBeanNameIsProvided() { + // given + val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) + val jobOperator = context.getBean() + val batch = context.getBean() + var testStepCallCount = 0 + val testStep = + batch { + step("testStep") { + tasklet( + { _, _ -> + ++testStepCallCount + RepeatStatus.FINISHED + }, + ResourcelessTransactionManager(), + ) + } + } + context.registerBean("testStep") { + testStep + } + + // when + val job = + batch { + job("testJob") { + flow("testFlow") { + stepBean("testStep") + } + } + } + val jobExecution = jobOperator.start(job, JobParameters()) + + // then + assertThat(job).isInstanceOf(FlowJob::class.java) + assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) + assertThat(jobExecution.exitStatus.exitCode).isEqualTo(ExitStatus.COMPLETED.exitCode) + assertThat(testStepCallCount).isEqualTo(1) + } + + @Test + fun flowShouldCreateFlowJobWhenFlowInstancesAreProvided() { + // given + val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) + val jobOperator = context.getBean() + val batch = context.getBean() + var testStep1CallCount = 0 + var testStep2CallCount = 0 + val testFlow1 = + batch { + flow("testFlow1") { + step("testStep1") { + tasklet( + { _, _ -> + ++testStep1CallCount + RepeatStatus.FINISHED + }, + ResourcelessTransactionManager(), + ) + } + } + } + val testFlow2 = + batch { + flow("testFlow2") { + step("testStep2") { + tasklet( + { _, _ -> + ++testStep2CallCount + RepeatStatus.FINISHED + }, + ResourcelessTransactionManager(), + ) + } + } + } + + // when + val job = + batch { + job("testJob") { + flow(testFlow1) + flow(testFlow2) + } + } + val jobExecution = jobOperator.start(job, JobParameters()) + + // then + assertThat(job).isInstanceOf(FlowJob::class.java) + assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) + assertThat(jobExecution.exitStatus.exitCode).isEqualTo(ExitStatus.COMPLETED.exitCode) + assertThat(testStep1CallCount).isEqualTo(1) + assertThat(testStep2CallCount).isEqualTo(1) + } + + @Test + fun flowBeanShouldCreateFlowJobWhenBeanNameAndTransitionAreProvided() { + // given + val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) + val jobOperator = context.getBean() + val batch = context.getBean() + var testStep1CallCount = 0 + var transitionStep1CallCount = 0 + var transitionStep2CallCount = 0 + var testStep2CallCount = 0 + val testFlow1 = + batch { + flow("testFlow1") { + step("testStep1") { + tasklet( + { _, _ -> + ++testStep1CallCount + throw RuntimeException("Error") + }, + ResourcelessTransactionManager(), + ) + } + } + } + val testFlow2 = + batch { + flow("testFlow2") { + step("testStep2") { + tasklet( + { _, _ -> + ++testStep2CallCount + RepeatStatus.FINISHED + }, + ResourcelessTransactionManager(), + ) + } + } + } + context.apply { + registerBean("testFlow1") { + testFlow1 + } + registerBean("testFlow2") { + testFlow2 + } + } + + // when + val job = + batch { + job("testJob") { + flowBean("testFlow1") { + on("COMPLETED") { + step("transitionStep1") { + tasklet( + { _, _ -> + ++transitionStep1CallCount + RepeatStatus.FINISHED + }, + ResourcelessTransactionManager(), + ) + } + } + on("FAILED") { + step("transitionStep2") { + tasklet( + { _, _ -> + ++transitionStep2CallCount + RepeatStatus.FINISHED + }, + ResourcelessTransactionManager(), + ) + } + } + } + flowBean("testFlow2") { + on("COMPLETED") { + end("TEST") + } + } + } + } + val jobExecution = jobOperator.start(job, JobParameters()) + + // then + assertThat(job).isInstanceOf(FlowJob::class.java) + assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) + assertThat(jobExecution.exitStatus.exitCode).isEqualTo(ExitStatus("TEST").exitCode) + assertThat(testStep1CallCount).isEqualTo(1) + assertThat(transitionStep1CallCount).isEqualTo(0) + assertThat(transitionStep2CallCount).isEqualTo(1) + assertThat(testStep2CallCount).isEqualTo(1) + } + + @Test + fun flowShouldCreateFlowJobWhenInitAndTransitionAreProvided() { + // given + val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) + val jobOperator = context.getBean() + val batch = context.getBean() + var testStep1CallCount = 0 + var transitionStep1CallCount = 0 + var transitionStep2CallCount = 0 + var testStep2CallCount = 0 + + // when + val job = + batch { + job("testJob") { + flow( + "testFlow1", + { + step("testStep1") { + tasklet( + { _, _ -> + ++testStep1CallCount + throw RuntimeException("Error") + }, + ResourcelessTransactionManager(), + ) + } + }, + ) { + on("COMPLETED") { + step("transitionStep1") { + tasklet( + { _, _ -> + ++transitionStep1CallCount + RepeatStatus.FINISHED + }, + ResourcelessTransactionManager(), + ) + } + } + on("FAILED") { + step("transitionStep2") { + tasklet( + { _, _ -> + ++transitionStep2CallCount + RepeatStatus.FINISHED + }, + ResourcelessTransactionManager(), + ) + } + } + } + flow( + "testFlow2", + { + step("testStep2") { + tasklet( + { _, _ -> + ++testStep2CallCount + RepeatStatus.FINISHED + }, + ResourcelessTransactionManager(), + ) + } + }, + ) { + on("COMPLETED") { + end("TEST") + } + } + } + } + val jobExecution = jobOperator.start(job, JobParameters()) + + // then + assertThat(job).isInstanceOf(FlowJob::class.java) + assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) + assertThat(jobExecution.exitStatus.exitCode).isEqualTo(ExitStatus("TEST").exitCode) + assertThat(testStep1CallCount).isEqualTo(1) + assertThat(transitionStep1CallCount).isEqualTo(0) + assertThat(transitionStep2CallCount).isEqualTo(1) + assertThat(testStep2CallCount).isEqualTo(1) + } + + @Test + fun flowShouldCreateFlowJobWhenInstanceAndTransitionAreProvided() { + // given + val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) + val jobOperator = context.getBean() + val batch = context.getBean() + var testStep1CallCount = 0 + var transitionStep1CallCount = 0 + var transitionStep2CallCount = 0 + var testStep2CallCount = 0 + val testFlow1 = + batch { + flow("testFlow1") { + step("testStep1") { + tasklet( + { _, _ -> + ++testStep1CallCount + throw RuntimeException("Error") + }, + ResourcelessTransactionManager(), + ) + } + } + } + val testFlow2 = + batch { + flow("testFlow2") { + step("testStep2") { + tasklet( + { _, _ -> + ++testStep2CallCount + RepeatStatus.FINISHED + }, + ResourcelessTransactionManager(), + ) + } + } + } + + // when + val job = + batch { + job("testJob") { + flow(testFlow1) { + on("COMPLETED") { + step("transitionStep1") { + tasklet( + { _, _ -> + ++transitionStep1CallCount + RepeatStatus.FINISHED + }, + ResourcelessTransactionManager(), + ) + } + } + on("FAILED") { + step("transitionStep2") { + tasklet( + { _, _ -> + ++transitionStep2CallCount + RepeatStatus.FINISHED + }, + ResourcelessTransactionManager(), + ) + } + } + } + flow(testFlow2) { + on("COMPLETED") { + end("TEST") + } + } + } + } + val jobExecution = jobOperator.start(job, JobParameters()) + + // then + assertThat(job).isInstanceOf(FlowJob::class.java) + assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) + assertThat(jobExecution.exitStatus.exitCode).isEqualTo(ExitStatus("TEST").exitCode) + assertThat(testStep1CallCount).isEqualTo(1) + assertThat(transitionStep1CallCount).isEqualTo(0) + assertThat(transitionStep2CallCount).isEqualTo(1) + assertThat(testStep2CallCount).isEqualTo(1) + } + + @Configuration + @EnableBatchProcessing + @EnableJdbcJobRepository( + dataSourceRef = "metadataDataSource", + transactionManagerRef = "metadataTransactionManager", + ) + private open class TestConfiguration { + @Bean + open fun batchDsl( + beanFactory: BeanFactory, + jobRepository: JobRepository, + ): BatchDsl = + BatchDsl( + beanFactory, + jobRepository, + ) + + @Bean + open fun metadataTransactionManager(): TransactionManager = DataSourceTransactionManager(metadataDataSource()) + + @Bean + open fun metadataDataSource(): DataSource = + EmbeddedDatabaseBuilder() + .setType(EmbeddedDatabaseType.H2) + .addScript("/org/springframework/batch/core/schema-h2.sql") + .generateUniqueName(true) + .build() + } +} diff --git a/spring-batch-plus-kotlin/src/integrationTest/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/StepTransitionBuilderDslIntegrationTest.kt b/spring-batch-plus-kotlin/src/integrationTest/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/job/flow/transition/FlowTransitionBuilderDslIntegrationTest.kt similarity index 58% rename from spring-batch-plus-kotlin/src/integrationTest/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/StepTransitionBuilderDslIntegrationTest.kt rename to spring-batch-plus-kotlin/src/integrationTest/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/job/flow/transition/FlowTransitionBuilderDslIntegrationTest.kt index 1ee4c5bb..b1a5be6b 100644 --- a/spring-batch-plus-kotlin/src/integrationTest/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/StepTransitionBuilderDslIntegrationTest.kt +++ b/spring-batch-plus-kotlin/src/integrationTest/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/job/flow/transition/FlowTransitionBuilderDslIntegrationTest.kt @@ -16,20 +16,22 @@ * limitations under the License. */ -package com.navercorp.spring.batch.plus.kotlin.configuration +package com.navercorp.spring.batch.plus.kotlin.configuration.job.flow.transition +import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl import org.assertj.core.api.Assertions.assertThat import org.assertj.core.api.Assertions.assertThatThrownBy import org.junit.jupiter.api.RepeatedTest import org.junit.jupiter.api.Test import org.springframework.batch.core.BatchStatus import org.springframework.batch.core.ExitStatus -import org.springframework.batch.core.JobParameters import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing -import org.springframework.batch.core.launch.JobLauncher +import org.springframework.batch.core.configuration.annotation.EnableJdbcJobRepository +import org.springframework.batch.core.job.parameters.JobParameters +import org.springframework.batch.core.launch.JobOperator import org.springframework.batch.core.repository.JobRepository -import org.springframework.batch.repeat.RepeatStatus -import org.springframework.batch.support.transaction.ResourcelessTransactionManager +import org.springframework.batch.infrastructure.repeat.RepeatStatus +import org.springframework.batch.infrastructure.support.transaction.ResourcelessTransactionManager import org.springframework.beans.factory.BeanFactory import org.springframework.beans.factory.getBean import org.springframework.context.annotation.AnnotationConfigApplicationContext @@ -41,43 +43,49 @@ import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType import org.springframework.transaction.TransactionManager import javax.sql.DataSource -internal class StepTransitionBuilderDslIntegrationTest { - +/** + * Covers source reselection after the first `on` clause. + */ +internal class FlowTransitionBuilderDslIntegrationTest { @RepeatedTest(10) - fun testStepWithMultipleTransition() { + fun flowShouldFollowMatchingTransitionWhenMultipleTransitionsAreConfigured() { // given val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) - val jobLauncher = context.getBean() + val jobOperator = context.getBean() val batch = context.getBean() val expectedExitStatus = randomExitStatus() var testStep1CallCount = 0 - val testStep1 = batch { - step("testStep1") { - tasklet( - { contribution, _ -> - ++testStep1CallCount - contribution.exitStatus = expectedExitStatus - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) + val testFlow1 = + batch { + flow("testFlow1") { + step("testStep1") { + tasklet( + { contribution, _ -> + ++testStep1CallCount + contribution.exitStatus = expectedExitStatus + RepeatStatus.FINISHED + }, + ResourcelessTransactionManager(), + ) + } + } } - } // when - val job = batch { - job("testJob") { - step(testStep1) { - on("COMPLETED") { - end() - } - on("*") { - fail() + val job = + batch { + job("testJob") { + flow(testFlow1) { + on("COMPLETED") { + end() + } + on("*") { + fail() + } } } } - } - val jobExecution = jobLauncher.run(job, JobParameters()) + val jobExecution = jobOperator.start(job, JobParameters()) // then assertThat(testStep1CallCount).isEqualTo(1) @@ -95,35 +103,37 @@ internal class StepTransitionBuilderDslIntegrationTest { } @Test - fun testStepWithNoTransition() { + fun flowShouldThrowExceptionWhenTransitionBlockIsEmpty() { // given val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) val batch = context.getBean() - val testStep1 = batch { - step("testStep1") { - tasklet( - { _, _ -> - RepeatStatus.FINISHED - }, - ResourcelessTransactionManager(), - ) + val testFlow1 = + batch { + flow("testFlow1") { + step("testStep1") { + tasklet( + { _, _ -> + RepeatStatus.FINISHED + }, + ResourcelessTransactionManager(), + ) + } + } } - } // when, then assertThatThrownBy { batch { job("testJob") { - step(testStep1) { - // no transition + flow(testFlow1) { } } } - }.hasMessageContaining("should set transition for step") + }.hasMessageContaining("should set transition for flow") } - private fun randomExitStatus(): ExitStatus { - return listOf( + private fun randomExitStatus(): ExitStatus = + listOf( ExitStatus.UNKNOWN, ExitStatus.NOOP, ExitStatus.FAILED, @@ -131,36 +141,33 @@ internal class StepTransitionBuilderDslIntegrationTest { ExitStatus.COMPLETED, // ExitStatus.EXECUTING, // why considered ExitStatus.COMPLETE? ).random() - } @Configuration - @EnableBatchProcessing( + @EnableBatchProcessing + @EnableJdbcJobRepository( dataSourceRef = "metadataDataSource", transactionManagerRef = "metadataTransactionManager", ) private open class TestConfiguration { - @Bean open fun batchDsl( beanFactory: BeanFactory, jobRepository: JobRepository, - ): BatchDsl = BatchDsl( - beanFactory, - jobRepository, - ) + ): BatchDsl = + BatchDsl( + beanFactory, + jobRepository, + ) @Bean - open fun metadataTransactionManager(): TransactionManager { - return DataSourceTransactionManager(metadataDataSource()) - } + open fun metadataTransactionManager(): TransactionManager = DataSourceTransactionManager(metadataDataSource()) @Bean - open fun metadataDataSource(): DataSource { - return EmbeddedDatabaseBuilder() + open fun metadataDataSource(): DataSource = + EmbeddedDatabaseBuilder() .setType(EmbeddedDatabaseType.H2) .addScript("/org/springframework/batch/core/schema-h2.sql") .generateUniqueName(true) .build() - } } } diff --git a/spring-batch-plus-kotlin/src/integrationTest/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/job/split/JobBuilderDslSplitCreationIntegrationTest.kt b/spring-batch-plus-kotlin/src/integrationTest/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/job/split/JobBuilderDslSplitCreationIntegrationTest.kt new file mode 100644 index 00000000..35ae258c --- /dev/null +++ b/spring-batch-plus-kotlin/src/integrationTest/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/job/split/JobBuilderDslSplitCreationIntegrationTest.kt @@ -0,0 +1,101 @@ +/* + * Spring Batch Plus + * + * Copyright 2022-present NAVER Corp. + * + * 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 + * + * http://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 com.navercorp.spring.batch.plus.kotlin.configuration.job.split + +import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test +import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing +import org.springframework.batch.core.configuration.annotation.EnableJdbcJobRepository +import org.springframework.batch.core.job.flow.FlowJob +import org.springframework.batch.core.repository.JobRepository +import org.springframework.batch.infrastructure.repeat.RepeatStatus +import org.springframework.batch.infrastructure.support.transaction.ResourcelessTransactionManager +import org.springframework.beans.factory.BeanFactory +import org.springframework.beans.factory.getBean +import org.springframework.context.annotation.AnnotationConfigApplicationContext +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import org.springframework.core.task.SyncTaskExecutor +import org.springframework.jdbc.datasource.DataSourceTransactionManager +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType +import org.springframework.transaction.TransactionManager +import javax.sql.DataSource + +/** + * Covers the boundary where introducing a split selects flow-job construction. + */ +internal class JobBuilderDslSplitCreationIntegrationTest { + @Test + fun splitShouldCreateFlowJobWhenTaskExecutorAndFlowAreProvided() { + // given + val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) + val batch = context.getBean() + + // when + val job = + batch { + job("testJob") { + split(SyncTaskExecutor()) { + flow("testFlow") { + step("testStep") { + tasklet( + { _, _ -> RepeatStatus.FINISHED }, + ResourcelessTransactionManager(), + ) + } + } + } + } + } + + // then + assertThat(job).isInstanceOf(FlowJob::class.java) + } + + @Configuration + @EnableBatchProcessing + @EnableJdbcJobRepository( + dataSourceRef = "metadataDataSource", + transactionManagerRef = "metadataTransactionManager", + ) + private open class TestConfiguration { + @Bean + open fun batchDsl( + beanFactory: BeanFactory, + jobRepository: JobRepository, + ): BatchDsl = + BatchDsl( + beanFactory, + jobRepository, + ) + + @Bean + open fun metadataTransactionManager(): TransactionManager = DataSourceTransactionManager(metadataDataSource()) + + @Bean + open fun metadataDataSource(): DataSource = + EmbeddedDatabaseBuilder() + .setType(EmbeddedDatabaseType.H2) + .addScript("/org/springframework/batch/core/schema-h2.sql") + .generateUniqueName(true) + .build() + } +} diff --git a/spring-batch-plus-kotlin/src/integrationTest/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/job/split/builder/SplitBuilderDslIntegrationTest.kt b/spring-batch-plus-kotlin/src/integrationTest/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/job/split/builder/SplitBuilderDslIntegrationTest.kt new file mode 100644 index 00000000..452ba87e --- /dev/null +++ b/spring-batch-plus-kotlin/src/integrationTest/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/job/split/builder/SplitBuilderDslIntegrationTest.kt @@ -0,0 +1,304 @@ +/* + * Spring Batch Plus + * + * Copyright 2022-present NAVER Corp. + * + * 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 + * + * http://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 com.navercorp.spring.batch.plus.kotlin.configuration.job.split.builder + +import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl +import org.assertj.core.api.Assertions.assertThat +import org.assertj.core.api.Assertions.assertThatThrownBy +import org.junit.jupiter.api.Test +import org.springframework.batch.core.BatchStatus +import org.springframework.batch.core.ExitStatus +import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing +import org.springframework.batch.core.configuration.annotation.EnableJdbcJobRepository +import org.springframework.batch.core.job.parameters.JobParameters +import org.springframework.batch.core.launch.JobOperator +import org.springframework.batch.core.repository.JobRepository +import org.springframework.batch.infrastructure.repeat.RepeatStatus +import org.springframework.batch.infrastructure.support.transaction.ResourcelessTransactionManager +import org.springframework.beans.factory.BeanFactory +import org.springframework.beans.factory.getBean +import org.springframework.context.annotation.AnnotationConfigApplicationContext +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import org.springframework.context.support.registerBean +import org.springframework.jdbc.datasource.DataSourceTransactionManager +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor +import org.springframework.transaction.TransactionManager +import javax.sql.DataSource + +/** + * Covers flow membership and validation inside an already-created split, rather than entry into split construction. + */ +internal class SplitBuilderDslIntegrationTest { + @Test + fun flowBeanShouldCreateSplitWhenFlowBeanNamesAreProvided() { + // given + val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) + val jobOperator = context.getBean() + val batch = context.getBean() + val callerThread = Thread.currentThread().name + var taskExecutorCallCount = 0 + val taskExecutor = + object : ThreadPoolTaskExecutor() { + override fun execute(task: Runnable) { + ++taskExecutorCallCount + super.execute(task) + } + }.apply { initialize() } + var testStep1CallCount = 0 + var testStep2CallCount = 0 + val testFlow1 = + batch { + flow("testFlow1") { + step("testStep1") { + tasklet( + { _, _ -> + ++testStep1CallCount + assertThat(Thread.currentThread().name).isNotEqualTo(callerThread) + RepeatStatus.FINISHED + }, + ResourcelessTransactionManager(), + ) + } + } + } + val testFlow2 = + batch { + flow("testFlow2") { + step("testStep2") { + tasklet( + { _, _ -> + ++testStep2CallCount + assertThat(Thread.currentThread().name).isNotEqualTo(callerThread) + RepeatStatus.FINISHED + }, + ResourcelessTransactionManager(), + ) + } + } + } + context.apply { + registerBean("testFlow1") { + testFlow1 + } + registerBean("testFlow2") { + testFlow2 + } + } + + // when + val job = + batch { + job("testJob") { + split(taskExecutor) { + flowBean("testFlow1") + flowBean("testFlow2") + } + } + } + val jobExecution = jobOperator.start(job, JobParameters()) + + // then + assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) + assertThat(jobExecution.exitStatus.exitCode).isEqualTo(ExitStatus.COMPLETED.exitCode) + assertThat(taskExecutorCallCount).isEqualTo(2) + assertThat(testStep1CallCount).isEqualTo(1) + assertThat(testStep2CallCount).isEqualTo(1) + } + + @Test + fun flowShouldCreateSplitWhenFlowsAreDeclaredWithInit() { + // given + val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) + val jobOperator = context.getBean() + val batch = context.getBean() + var taskExecutorCallCount = 0 + var testStep1CallCount = 0 + var testStep2CallCount = 0 + val callerThread = Thread.currentThread().name + val taskExecutor = + object : ThreadPoolTaskExecutor() { + override fun execute(task: Runnable) { + ++taskExecutorCallCount + super.execute(task) + } + }.apply { initialize() } + + // when + val job = + batch { + job("testJob") { + split(taskExecutor) { + flow("testFlow1") { + step("testStep1") { + tasklet( + { _, _ -> + ++testStep1CallCount + assertThat(Thread.currentThread().name).isNotEqualTo(callerThread) + RepeatStatus.FINISHED + }, + ResourcelessTransactionManager(), + ) + } + } + flow("testFlow2") { + step("testStep2") { + tasklet( + { _, _ -> + ++testStep2CallCount + assertThat(Thread.currentThread().name).isNotEqualTo(callerThread) + RepeatStatus.FINISHED + }, + ResourcelessTransactionManager(), + ) + } + } + } + } + } + val jobExecution = jobOperator.start(job, JobParameters()) + + // then + assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) + assertThat(jobExecution.exitStatus.exitCode).isEqualTo(ExitStatus.COMPLETED.exitCode) + assertThat(taskExecutorCallCount).isEqualTo(2) + assertThat(testStep1CallCount).isEqualTo(1) + assertThat(testStep2CallCount).isEqualTo(1) + } + + @Test + fun flowShouldCreateSplitWhenFlowInstancesAreProvided() { + // given + val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) + val jobOperator = context.getBean() + val batch = context.getBean() + val callerThread = Thread.currentThread().name + var taskExecutorCallCount = 0 + val taskExecutor = + object : ThreadPoolTaskExecutor() { + override fun execute(task: Runnable) { + ++taskExecutorCallCount + super.execute(task) + } + }.apply { initialize() } + var testStep1CallCount = 0 + var testStep2CallCount = 0 + val testFlow1 = + batch { + flow("testFlow1") { + step("testStep1") { + tasklet( + { _, _ -> + ++testStep1CallCount + assertThat(Thread.currentThread().name).isNotEqualTo(callerThread) + RepeatStatus.FINISHED + }, + ResourcelessTransactionManager(), + ) + } + } + } + val testFlow2 = + batch { + flow("testFlow2") { + step("testStep2") { + tasklet( + { _, _ -> + ++testStep2CallCount + assertThat(Thread.currentThread().name).isNotEqualTo(callerThread) + RepeatStatus.FINISHED + }, + ResourcelessTransactionManager(), + ) + } + } + } + + // when + val job = + batch { + job("testJob") { + split(taskExecutor) { + flow(testFlow1) + flow(testFlow2) + } + } + } + val jobExecution = jobOperator.start(job, JobParameters()) + + // then + assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) + assertThat(jobExecution.exitStatus.exitCode).isEqualTo(ExitStatus.COMPLETED.exitCode) + assertThat(taskExecutorCallCount).isEqualTo(2) + assertThat(testStep1CallCount).isEqualTo(1) + assertThat(testStep2CallCount).isEqualTo(1) + } + + @Test + fun splitShouldThrowExceptionWhenNoFlowIsProvided() { + // given + val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) + val batch = context.getBean() + val taskExecutor = + ThreadPoolTaskExecutor().apply { + initialize() + } + + // when, then + assertThatThrownBy { + batch { + job("testJob") { + split(taskExecutor) { + } + } + } + }.hasMessageContaining("should set at least one flow to split") + } + + @Configuration + @EnableBatchProcessing + @EnableJdbcJobRepository( + dataSourceRef = "metadataDataSource", + transactionManagerRef = "metadataTransactionManager", + ) + private open class TestConfiguration { + @Bean + open fun batchDsl( + beanFactory: BeanFactory, + jobRepository: JobRepository, + ): BatchDsl = + BatchDsl( + beanFactory, + jobRepository, + ) + + @Bean + open fun metadataTransactionManager(): TransactionManager = DataSourceTransactionManager(metadataDataSource()) + + @Bean + open fun metadataDataSource(): DataSource = + EmbeddedDatabaseBuilder() + .setType(EmbeddedDatabaseType.H2) + .addScript("/org/springframework/batch/core/schema-h2.sql") + .generateUniqueName(true) + .build() + } +} diff --git a/spring-batch-plus-kotlin/src/integrationTest/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/job/step/JobBuilderDslSequentialStepCreationIntegrationTest.kt b/spring-batch-plus-kotlin/src/integrationTest/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/job/step/JobBuilderDslSequentialStepCreationIntegrationTest.kt new file mode 100644 index 00000000..95d915b3 --- /dev/null +++ b/spring-batch-plus-kotlin/src/integrationTest/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/job/step/JobBuilderDslSequentialStepCreationIntegrationTest.kt @@ -0,0 +1,190 @@ +/* + * Spring Batch Plus + * + * Copyright 2022-present NAVER Corp. + * + * 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 + * + * http://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 com.navercorp.spring.batch.plus.kotlin.configuration.job.step + +import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test +import org.springframework.batch.core.BatchStatus +import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing +import org.springframework.batch.core.configuration.annotation.EnableJdbcJobRepository +import org.springframework.batch.core.job.SimpleJob +import org.springframework.batch.core.job.parameters.JobParameters +import org.springframework.batch.core.launch.JobOperator +import org.springframework.batch.core.repository.JobRepository +import org.springframework.batch.core.step.Step +import org.springframework.batch.infrastructure.repeat.RepeatStatus +import org.springframework.batch.infrastructure.support.transaction.ResourcelessTransactionManager +import org.springframework.beans.factory.BeanFactory +import org.springframework.beans.factory.getBean +import org.springframework.context.annotation.AnnotationConfigApplicationContext +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import org.springframework.context.support.registerBean +import org.springframework.jdbc.datasource.DataSourceTransactionManager +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType +import org.springframework.transaction.TransactionManager +import javax.sql.DataSource + +/** + * Covers step declarations that keep job construction on the sequential simple-job path. + */ +internal class JobBuilderDslSequentialStepCreationIntegrationTest { + @Test + fun stepBeanShouldCreateSimpleJobWhenBeanNameIsProvided() { + // given + val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) + val batch = context.getBean() + val step = batch.createTaskletStep("testStep") + context.registerBean("testStep") { + step + } + + // when + val job = + batch { + job("testJob") { + stepBean("testStep") + } + } + + // then + assertThat(job).isInstanceOf(SimpleJob::class.java) + } + + @Test + fun stepShouldCreateSimpleJobWhenInitIsProvided() { + // given + val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) + val batch = context.getBean() + + // when + val job = + batch { + job("testJob") { + step("testStep") { + tasklet( + { _, _ -> RepeatStatus.FINISHED }, + ResourcelessTransactionManager(), + ) + } + } + } + + // then + assertThat(job).isInstanceOf(SimpleJob::class.java) + } + + @Test + fun stepShouldCreateSimpleJobWhenInstanceIsProvided() { + // given + val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) + val batch = context.getBean() + val step = batch.createTaskletStep("testStep") + + // when + val job = + batch { + job("testJob") { + step(step) + } + } + + // then + assertThat(job).isInstanceOf(SimpleJob::class.java) + } + + @Test + fun stepsShouldExecuteSequentiallyWhenTransitionsAreNotProvided() { + // given + val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) + val jobOperator = context.getBean() + val batch = context.getBean() + val executionOrder = mutableListOf() + + val job = + batch { + job("testJob") { + step("testStep1") { + tasklet( + { _, _ -> + executionOrder += "testStep1" + RepeatStatus.FINISHED + }, + ResourcelessTransactionManager(), + ) + } + step("testStep2") { + tasklet( + { _, _ -> + executionOrder += "testStep2" + RepeatStatus.FINISHED + }, + ResourcelessTransactionManager(), + ) + } + } + } + + // when + val jobExecution = jobOperator.start(job, JobParameters()) + + // then + assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) + assertThat(executionOrder).containsExactly("testStep1", "testStep2") + } + + private fun BatchDsl.createTaskletStep(name: String): Step = + step(name) { + tasklet( + { _, _ -> RepeatStatus.FINISHED }, + ResourcelessTransactionManager(), + ) + } + + @Configuration + @EnableBatchProcessing + @EnableJdbcJobRepository( + dataSourceRef = "metadataDataSource", + transactionManagerRef = "metadataTransactionManager", + ) + private open class TestConfiguration { + @Bean + open fun batchDsl( + beanFactory: BeanFactory, + jobRepository: JobRepository, + ): BatchDsl = + BatchDsl( + beanFactory, + jobRepository, + ) + + @Bean + open fun metadataTransactionManager(): TransactionManager = DataSourceTransactionManager(metadataDataSource()) + + @Bean + open fun metadataDataSource(): DataSource = + EmbeddedDatabaseBuilder() + .setType(EmbeddedDatabaseType.H2) + .addScript("/org/springframework/batch/core/schema-h2.sql") + .generateUniqueName(true) + .build() + } +} diff --git a/spring-batch-plus-kotlin/src/integrationTest/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/job/step/JobBuilderDslTransitionStepCreationIntegrationTest.kt b/spring-batch-plus-kotlin/src/integrationTest/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/job/step/JobBuilderDslTransitionStepCreationIntegrationTest.kt new file mode 100644 index 00000000..74d775f7 --- /dev/null +++ b/spring-batch-plus-kotlin/src/integrationTest/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/job/step/JobBuilderDslTransitionStepCreationIntegrationTest.kt @@ -0,0 +1,330 @@ +/* + * Spring Batch Plus + * + * Copyright 2022-present NAVER Corp. + * + * 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 + * + * http://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 com.navercorp.spring.batch.plus.kotlin.configuration.job.step + +import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test +import org.springframework.batch.core.BatchStatus +import org.springframework.batch.core.ExitStatus +import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing +import org.springframework.batch.core.configuration.annotation.EnableJdbcJobRepository +import org.springframework.batch.core.job.flow.FlowJob +import org.springframework.batch.core.job.parameters.JobParameters +import org.springframework.batch.core.launch.JobOperator +import org.springframework.batch.core.repository.JobRepository +import org.springframework.batch.infrastructure.repeat.RepeatStatus +import org.springframework.batch.infrastructure.support.transaction.ResourcelessTransactionManager +import org.springframework.beans.factory.BeanFactory +import org.springframework.beans.factory.getBean +import org.springframework.context.annotation.AnnotationConfigApplicationContext +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import org.springframework.context.support.registerBean +import org.springframework.jdbc.datasource.DataSourceTransactionManager +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType +import org.springframework.transaction.TransactionManager +import javax.sql.DataSource + +/** + * Covers step declarations whose explicit transitions require flow-job construction. + */ +internal class JobBuilderDslTransitionStepCreationIntegrationTest { + @Test + fun stepBeanShouldCreateFlowJobWhenBeanNameAndTransitionAreProvided() { + // given + val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) + val jobOperator = context.getBean() + val batch = context.getBean() + var testStep1CallCount = 0 + var transitionStep1CallCount = 0 + var transitionStep2CallCount = 0 + var testStep2CallCount = 0 + val testStep1 = + batch { + step("testStep1") { + tasklet( + { _, _ -> + ++testStep1CallCount + throw RuntimeException("Error") + }, + ResourcelessTransactionManager(), + ) + } + } + val testStep2 = + batch { + step("testStep2") { + tasklet( + { _, _ -> + ++testStep2CallCount + RepeatStatus.FINISHED + }, + ResourcelessTransactionManager(), + ) + } + } + context.apply { + registerBean("testStep1") { + testStep1 + } + registerBean("testStep2") { + testStep2 + } + } + + // when + val job = + batch { + job("testJob") { + stepBean("testStep1") { + on("COMPLETED") { + step("transitionStep1") { + tasklet( + { _, _ -> + ++transitionStep1CallCount + RepeatStatus.FINISHED + }, + ResourcelessTransactionManager(), + ) + } + } + on("FAILED") { + step("transitionStep2") { + tasklet( + { _, _ -> + ++transitionStep2CallCount + RepeatStatus.FINISHED + }, + ResourcelessTransactionManager(), + ) + } + } + } + stepBean("testStep2") { + on("COMPLETED") { + end("TEST") + } + } + } + } + val jobExecution = jobOperator.start(job, JobParameters()) + + // then + assertThat(job).isInstanceOf(FlowJob::class.java) + assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) + assertThat(jobExecution.exitStatus.exitCode).isEqualTo(ExitStatus("TEST").exitCode) + assertThat(testStep1CallCount).isEqualTo(1) + assertThat(transitionStep1CallCount).isEqualTo(0) + assertThat(transitionStep2CallCount).isEqualTo(1) + assertThat(testStep2CallCount).isEqualTo(1) + } + + @Test + fun stepShouldCreateFlowJobWhenInitAndTransitionAreProvided() { + // given + val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) + val jobOperator = context.getBean() + val batch = context.getBean() + var testStep1CallCount = 0 + var transitionStep1CallCount = 0 + var transitionStep2CallCount = 0 + var testStep2CallCount = 0 + + // when + val job = + batch { + job("testJob") { + step( + "testStep1", + { + tasklet( + { _, _ -> + ++testStep1CallCount + throw RuntimeException("Error") + }, + ResourcelessTransactionManager(), + ) + }, + ) { + on("COMPLETED") { + step("transitionStep1") { + tasklet( + { _, _ -> + ++transitionStep1CallCount + RepeatStatus.FINISHED + }, + ResourcelessTransactionManager(), + ) + } + } + on("FAILED") { + step("transitionStep2") { + tasklet( + { _, _ -> + ++transitionStep2CallCount + RepeatStatus.FINISHED + }, + ResourcelessTransactionManager(), + ) + } + } + } + step( + "testStep2", + { + tasklet( + { _, _ -> + ++testStep2CallCount + RepeatStatus.FINISHED + }, + ResourcelessTransactionManager(), + ) + }, + ) { + on("COMPLETED") { + end("TEST") + } + } + } + } + val jobExecution = jobOperator.start(job, JobParameters()) + + // then + assertThat(job).isInstanceOf(FlowJob::class.java) + assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) + assertThat(jobExecution.exitStatus.exitCode).isEqualTo(ExitStatus("TEST").exitCode) + assertThat(testStep1CallCount).isEqualTo(1) + assertThat(transitionStep1CallCount).isEqualTo(0) + assertThat(transitionStep2CallCount).isEqualTo(1) + assertThat(testStep2CallCount).isEqualTo(1) + } + + @Test + fun stepShouldCreateFlowJobWhenInstanceAndTransitionAreProvided() { + // given + val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) + val jobOperator = context.getBean() + val batch = context.getBean() + var testStep1CallCount = 0 + var transitionStep1CallCount = 0 + var transitionStep2CallCount = 0 + var testStep2CallCount = 0 + val testStep1 = + batch { + step("testStep1") { + tasklet( + { _, _ -> + ++testStep1CallCount + throw RuntimeException("Error") + }, + ResourcelessTransactionManager(), + ) + } + } + val testStep2 = + batch { + step("testStep2") { + tasklet( + { _, _ -> + ++testStep2CallCount + RepeatStatus.FINISHED + }, + ResourcelessTransactionManager(), + ) + } + } + + // when + val job = + batch { + job("testJob") { + step(testStep1) { + on("COMPLETED") { + step("transitionStep1") { + tasklet( + { _, _ -> + ++transitionStep1CallCount + RepeatStatus.FINISHED + }, + ResourcelessTransactionManager(), + ) + } + } + on("FAILED") { + step("transitionStep2") { + tasklet( + { _, _ -> + ++transitionStep2CallCount + RepeatStatus.FINISHED + }, + ResourcelessTransactionManager(), + ) + } + } + } + step(testStep2) { + on("COMPLETED") { + end("TEST") + } + } + } + } + val jobExecution = jobOperator.start(job, JobParameters()) + + // then + assertThat(job).isInstanceOf(FlowJob::class.java) + assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) + assertThat(jobExecution.exitStatus.exitCode).isEqualTo(ExitStatus("TEST").exitCode) + assertThat(testStep1CallCount).isEqualTo(1) + assertThat(transitionStep1CallCount).isEqualTo(0) + assertThat(transitionStep2CallCount).isEqualTo(1) + assertThat(testStep2CallCount).isEqualTo(1) + } + + @Configuration + @EnableBatchProcessing + @EnableJdbcJobRepository( + dataSourceRef = "metadataDataSource", + transactionManagerRef = "metadataTransactionManager", + ) + private open class TestConfiguration { + @Bean + open fun batchDsl( + beanFactory: BeanFactory, + jobRepository: JobRepository, + ): BatchDsl = + BatchDsl( + beanFactory, + jobRepository, + ) + + @Bean + open fun metadataTransactionManager(): TransactionManager = DataSourceTransactionManager(metadataDataSource()) + + @Bean + open fun metadataDataSource(): DataSource = + EmbeddedDatabaseBuilder() + .setType(EmbeddedDatabaseType.H2) + .addScript("/org/springframework/batch/core/schema-h2.sql") + .generateUniqueName(true) + .build() + } +} diff --git a/spring-batch-plus-kotlin/src/integrationTest/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/job/step/builder/ChunkOrientedStepBuilderDslIntegrationTest.kt b/spring-batch-plus-kotlin/src/integrationTest/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/job/step/builder/ChunkOrientedStepBuilderDslIntegrationTest.kt new file mode 100644 index 00000000..47ea1b24 --- /dev/null +++ b/spring-batch-plus-kotlin/src/integrationTest/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/job/step/builder/ChunkOrientedStepBuilderDslIntegrationTest.kt @@ -0,0 +1,266 @@ +/* + * Spring Batch Plus + * + * Copyright 2022-present NAVER Corp. + * + * 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 + * + * http://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 com.navercorp.spring.batch.plus.kotlin.configuration.job.step.builder + +import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test +import org.springframework.batch.core.BatchStatus +import org.springframework.batch.core.annotation.AfterChunk +import org.springframework.batch.core.annotation.AfterStep +import org.springframework.batch.core.annotation.BeforeChunk +import org.springframework.batch.core.annotation.BeforeStep +import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing +import org.springframework.batch.core.configuration.annotation.EnableJdbcJobRepository +import org.springframework.batch.core.job.parameters.JobParameters +import org.springframework.batch.core.launch.JobOperator +import org.springframework.batch.core.listener.SkipListener +import org.springframework.batch.core.repository.JobRepository +import org.springframework.batch.infrastructure.item.ItemProcessor +import org.springframework.batch.infrastructure.item.ItemReader +import org.springframework.batch.infrastructure.item.ItemWriter +import org.springframework.batch.infrastructure.support.transaction.ResourcelessTransactionManager +import org.springframework.beans.factory.BeanFactory +import org.springframework.beans.factory.getBean +import org.springframework.context.annotation.AnnotationConfigApplicationContext +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import org.springframework.jdbc.datasource.DataSourceTransactionManager +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType +import org.springframework.transaction.TransactionManager +import java.util.UUID +import javax.sql.DataSource + +/** + * Covers the integration boundary from chunk declarations to actual chunk-oriented step execution. + */ +internal class ChunkOrientedStepBuilderDslIntegrationTest { + @Test + fun chunkShouldCreateChunkOrientedStepWhenItemComponentsAreProvided() { + // given + val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) + val jobOperator = context.getBean() + val batch = context.getBean() + val jobName = UUID.randomUUID().toString() + val stepName = UUID.randomUUID().toString() + val readLimit = 6 + var readCallCount = 0 + val writtenItems = mutableListOf() + val reader: ItemReader = + ItemReader { + if (readCallCount < readLimit) { + readCallCount++ + } else { + null + } + } + val writer: ItemWriter = + ItemWriter { chunk -> + writtenItems.addAll(chunk.items) + } + + // when + val job = + batch { + job(jobName) { + step(stepName) { + chunk(3) { + transactionManager(ResourcelessTransactionManager()) + reader(reader) + writer(writer) + } + } + } + } + val jobExecution = jobOperator.start(job, JobParameters()) + + // then + assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) + assertThat(readCallCount).isEqualTo(readLimit) + assertThat(writtenItems).containsExactly(0, 1, 2, 3, 4, 5) + } + + @Test + fun listenerShouldInvokeAnnotatedCallbacksWhenChunkOrientedStepRuns() { + // given + val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) + val jobOperator = context.getBean() + val batch = context.getBean() + val jobName = UUID.randomUUID().toString() + val stepName = UUID.randomUUID().toString() + var readCallCount = 0 + var beforeStepCallCount = 0 + var afterStepCallCount = 0 + var beforeChunkCallCount = 0 + var afterChunkCallCount = 0 + val reader: ItemReader = + ItemReader { + if (readCallCount < 1) { + readCallCount++ + } else { + null + } + } + val writer: ItemWriter = ItemWriter { } + + // when + val job = + batch { + job(jobName) { + step(stepName) { + chunk(3) { + transactionManager(ResourcelessTransactionManager()) + reader(reader) + writer(writer) + listener( + object { + @BeforeStep + fun beforeStep() { + ++beforeStepCallCount + } + + @AfterStep + fun afterStep() { + ++afterStepCallCount + } + + @BeforeChunk + fun beforeChunk() { + ++beforeChunkCallCount + } + + @AfterChunk + fun afterChunk() { + ++afterChunkCallCount + } + }, + ) + } + } + } + } + val jobExecution = jobOperator.start(job, JobParameters()) + + // then + assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) + assertThat(readCallCount).isEqualTo(1) + assertThat(beforeStepCallCount).isEqualTo(1) + assertThat(afterStepCallCount).isEqualTo(1) + assertThat(beforeChunkCallCount).isEqualTo(1) + assertThat(afterChunkCallCount).isEqualTo(1) + } + + @Test + fun chunkShouldCreateFaultTolerantStepWhenItemComponentsUseVariantTypes() { + // given + val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) + val jobOperator = context.getBean() + val batch = context.getBean() + val jobName = UUID.randomUUID().toString() + val stepName = UUID.randomUUID().toString() + var readCallCount = 0 + var skipInProcessCallCount = 0 + val writtenItems = mutableListOf() + val reader: ItemReader = + ItemReader { + if (readCallCount < 6) { + readCallCount++ + } else { + null + } + } + val processor: ItemProcessor = + ItemProcessor { item -> + val value = item.toInt() + if (value == 2) { + throw IllegalArgumentException("skipped") + } + value * 10 + } + val writer: ItemWriter = + ItemWriter { chunk -> + writtenItems.addAll(chunk.items) + } + val skipListener = + object : SkipListener { + override fun onSkipInProcess( + item: Any, + t: Throwable, + ) { + ++skipInProcessCallCount + } + } + + // when + val job = + batch { + job(jobName) { + step(stepName) { + chunk(3) { + transactionManager(ResourcelessTransactionManager()) + reader(reader) + processor(processor) + writer(writer) + faultTolerant() + skip() + skipLimit(1L) + skipListener(skipListener) + } + } + } + } + val jobExecution = jobOperator.start(job, JobParameters()) + + // then + assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) + assertThat(readCallCount).isEqualTo(6) + assertThat(skipInProcessCallCount).isEqualTo(1) + assertThat(writtenItems).containsExactly(0, 10, 30, 40, 50) + } + + @Configuration + @EnableBatchProcessing + @EnableJdbcJobRepository( + dataSourceRef = "metadataDataSource", + transactionManagerRef = "metadataTransactionManager", + ) + private open class TestConfiguration { + @Bean + open fun batchDsl( + beanFactory: BeanFactory, + jobRepository: JobRepository, + ): BatchDsl = + BatchDsl( + beanFactory, + jobRepository, + ) + + @Bean + open fun metadataTransactionManager(): TransactionManager = DataSourceTransactionManager(metadataDataSource()) + + @Bean + open fun metadataDataSource(): DataSource = + EmbeddedDatabaseBuilder() + .setType(EmbeddedDatabaseType.H2) + .addScript("/org/springframework/batch/core/schema-h2.sql") + .generateUniqueName(true) + .build() + } +} diff --git a/spring-batch-plus-kotlin/src/integrationTest/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/job/step/builder/FlowStepBuilderDslIntegrationTest.kt b/spring-batch-plus-kotlin/src/integrationTest/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/job/step/builder/FlowStepBuilderDslIntegrationTest.kt new file mode 100644 index 00000000..7a1221b1 --- /dev/null +++ b/spring-batch-plus-kotlin/src/integrationTest/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/job/step/builder/FlowStepBuilderDslIntegrationTest.kt @@ -0,0 +1,222 @@ +/* + * Spring Batch Plus + * + * Copyright 2022-present NAVER Corp. + * + * 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 + * + * http://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 com.navercorp.spring.batch.plus.kotlin.configuration.job.step.builder + +import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test +import org.springframework.batch.core.BatchStatus +import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing +import org.springframework.batch.core.configuration.annotation.EnableJdbcJobRepository +import org.springframework.batch.core.job.parameters.JobParameters +import org.springframework.batch.core.launch.JobOperator +import org.springframework.batch.core.repository.JobRepository +import org.springframework.batch.infrastructure.repeat.RepeatStatus +import org.springframework.batch.infrastructure.support.transaction.ResourcelessTransactionManager +import org.springframework.beans.factory.BeanFactory +import org.springframework.beans.factory.getBean +import org.springframework.context.annotation.AnnotationConfigApplicationContext +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import org.springframework.context.support.registerBean +import org.springframework.jdbc.datasource.DataSourceTransactionManager +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType +import org.springframework.transaction.TransactionManager +import javax.sql.DataSource + +/** + * Covers the integration boundary from flow declarations to actual flow-step execution. + */ +internal class FlowStepBuilderDslIntegrationTest { + @Test + fun flowBeanShouldCreateFlowStepWhenBeanNameIsProvided() { + // given + val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) + val jobOperator = context.getBean() + val batch = context.getBean() + var testStep1CallCount = 0 + var testStep2CallCount = 0 + val testFlow = + batch { + flow("testFlow") { + step("testStep1") { + tasklet( + { _, _ -> + ++testStep1CallCount + RepeatStatus.FINISHED + }, + ResourcelessTransactionManager(), + ) + } + step("testStep2") { + tasklet( + { _, _ -> + ++testStep2CallCount + RepeatStatus.FINISHED + }, + ResourcelessTransactionManager(), + ) + } + } + } + context.registerBean("testFlow") { + testFlow + } + + // when + val job = + batch { + job("testJob") { + step("testStep") { + flowBean("testFlow") + } + } + } + val jobExecution = jobOperator.start(job, JobParameters()) + + // then + assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) + assertThat(testStep1CallCount).isEqualTo(1) + assertThat(testStep2CallCount).isEqualTo(1) + } + + @Test + fun flowShouldCreateFlowStepWhenFlowIsDeclaredWithInit() { + // given + val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) + val jobOperator = context.getBean() + val batch = context.getBean() + var testStep1CallCount = 0 + var testStep2CallCount = 0 + + // when + val job = + batch { + job("testJob") { + step("testStep") { + flow("testFlow") { + step("testStep1") { + tasklet( + { _, _ -> + ++testStep1CallCount + RepeatStatus.FINISHED + }, + ResourcelessTransactionManager(), + ) + } + step("testStep2") { + tasklet( + { _, _ -> + ++testStep2CallCount + RepeatStatus.FINISHED + }, + ResourcelessTransactionManager(), + ) + } + } + } + } + } + val jobExecution = jobOperator.start(job, JobParameters()) + + // then + assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) + assertThat(testStep1CallCount).isEqualTo(1) + assertThat(testStep2CallCount).isEqualTo(1) + } + + @Test + fun flowShouldCreateFlowStepWhenFlowIsProvided() { + // given + val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) + val jobOperator = context.getBean() + val batch = context.getBean() + var testStep1CallCount = 0 + var testStep2CallCount = 0 + val testFlow = + batch { + flow("testFlow") { + step("testStep1") { + tasklet( + { _, _ -> + ++testStep1CallCount + RepeatStatus.FINISHED + }, + ResourcelessTransactionManager(), + ) + } + step("testStep2") { + tasklet( + { _, _ -> + ++testStep2CallCount + RepeatStatus.FINISHED + }, + ResourcelessTransactionManager(), + ) + } + } + } + + // when + val job = + batch { + job("testJob") { + step("testStep") { + flow(testFlow) + } + } + } + val jobExecution = jobOperator.start(job, JobParameters()) + + // then + assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) + assertThat(testStep1CallCount).isEqualTo(1) + assertThat(testStep2CallCount).isEqualTo(1) + } + + @Configuration + @EnableBatchProcessing + @EnableJdbcJobRepository( + dataSourceRef = "metadataDataSource", + transactionManagerRef = "metadataTransactionManager", + ) + private open class TestConfiguration { + @Bean + open fun batchDsl( + beanFactory: BeanFactory, + jobRepository: JobRepository, + ): BatchDsl = + BatchDsl( + beanFactory, + jobRepository, + ) + + @Bean + open fun metadataTransactionManager(): TransactionManager = DataSourceTransactionManager(metadataDataSource()) + + @Bean + open fun metadataDataSource(): DataSource = + EmbeddedDatabaseBuilder() + .setType(EmbeddedDatabaseType.H2) + .addScript("/org/springframework/batch/core/schema-h2.sql") + .generateUniqueName(true) + .build() + } +} diff --git a/spring-batch-plus-kotlin/src/integrationTest/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/job/step/builder/JobStepBuilderDslIntegrationTest.kt b/spring-batch-plus-kotlin/src/integrationTest/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/job/step/builder/JobStepBuilderDslIntegrationTest.kt new file mode 100644 index 00000000..85d07e59 --- /dev/null +++ b/spring-batch-plus-kotlin/src/integrationTest/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/job/step/builder/JobStepBuilderDslIntegrationTest.kt @@ -0,0 +1,240 @@ +/* + * Spring Batch Plus + * + * Copyright 2022-present NAVER Corp. + * + * 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 + * + * http://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 com.navercorp.spring.batch.plus.kotlin.configuration.job.step.builder + +import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test +import org.springframework.batch.core.BatchStatus +import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing +import org.springframework.batch.core.configuration.annotation.EnableJdbcJobRepository +import org.springframework.batch.core.job.parameters.JobParameters +import org.springframework.batch.core.launch.JobOperator +import org.springframework.batch.core.repository.JobRepository +import org.springframework.batch.infrastructure.repeat.RepeatStatus +import org.springframework.batch.infrastructure.support.transaction.ResourcelessTransactionManager +import org.springframework.beans.factory.BeanFactory +import org.springframework.beans.factory.getBean +import org.springframework.context.annotation.AnnotationConfigApplicationContext +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import org.springframework.context.support.registerBean +import org.springframework.jdbc.datasource.DataSourceTransactionManager +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType +import org.springframework.transaction.TransactionManager +import javax.sql.DataSource + +/** + * Covers the integration boundary from nested job declarations to actual job-step execution. + */ +internal class JobStepBuilderDslIntegrationTest { + @Test + fun jobBeanShouldCreateJobStepWhenBeanNameIsProvided() { + // given + val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) + val jobOperator = context.getBean() + val batch = context.getBean() + var stepCallCount = 0 + val testJob2 = + batch { + job("testJob2") { + step("testStep2") { + ++stepCallCount + tasklet( + { _, _ -> RepeatStatus.FINISHED }, + ResourcelessTransactionManager(), + ) + } + } + } + context.registerBean("testJob2") { + testJob2 + } + + // when + val job = + batch { + job("testJob") { + step("testStep") { + jobBean("testJob2") + } + } + } + val jobExecution = jobOperator.start(job, JobParameters()) + + // then + assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) + assertThat(stepCallCount).isEqualTo(1) + } + + @Test + fun jobBeanShouldCreateJobStepWhenBeanNameAndInitAreProvided() { + // given + val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) + val jobOperator = context.getBean() + val batch = context.getBean() + var stepCallCount = 0 + var jobParametersExtractorCallCount = 0 + val testJob2 = + batch { + job("testJob2") { + step("testStep2") { + ++stepCallCount + tasklet( + { _, _ -> RepeatStatus.FINISHED }, + ResourcelessTransactionManager(), + ) + } + } + } + context.registerBean("testJob2") { + testJob2 + } + + // when + val job = + batch { + job("testJob") { + step("testStep") { + jobBean("testJob2") { + parametersExtractor { _, _ -> + ++jobParametersExtractorCallCount + JobParameters() + } + } + } + } + } + val jobExecution = jobOperator.start(job, JobParameters()) + + // then + assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) + assertThat(stepCallCount).isEqualTo(1) + assertThat(jobParametersExtractorCallCount).isEqualTo(1) + } + + @Test + fun jobShouldCreateJobStepWhenJobIsProvided() { + // given + val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) + val jobOperator = context.getBean() + val batch = context.getBean() + var stepCallCount = 0 + val testJob2 = + batch { + job("testJob2") { + step("testStep2") { + ++stepCallCount + tasklet( + { _, _ -> RepeatStatus.FINISHED }, + ResourcelessTransactionManager(), + ) + } + } + } + + // when + val job = + batch { + job("testJob") { + step("testStep") { + job(testJob2) + } + } + } + val jobExecution = jobOperator.start(job, JobParameters()) + + // then + assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) + assertThat(stepCallCount).isEqualTo(1) + } + + @Test + fun jobShouldCreateJobStepWhenJobAndInitAreProvided() { + // given + val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) + val jobOperator = context.getBean() + val batch = context.getBean() + var jobCallCount = 0 + var jobParametersExtractorCallCount = 0 + val testJob2 = + batch { + job("testJob2") { + step("testStep2") { + ++jobCallCount + tasklet( + { _, _ -> RepeatStatus.FINISHED }, + ResourcelessTransactionManager(), + ) + } + } + } + + // when + val job = + batch { + job("testJob") { + step("testStep") { + job(testJob2) { + parametersExtractor { _, _ -> + ++jobParametersExtractorCallCount + JobParameters() + } + } + } + } + } + val jobExecution = jobOperator.start(job, JobParameters()) + + // then + assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) + assertThat(jobCallCount).isEqualTo(1) + assertThat(jobParametersExtractorCallCount).isEqualTo(1) + } + + @Configuration + @EnableBatchProcessing + @EnableJdbcJobRepository( + dataSourceRef = "metadataDataSource", + transactionManagerRef = "metadataTransactionManager", + ) + private open class TestConfiguration { + @Bean + open fun batchDsl( + beanFactory: BeanFactory, + jobRepository: JobRepository, + ): BatchDsl = + BatchDsl( + beanFactory, + jobRepository, + ) + + @Bean + open fun metadataTransactionManager(): TransactionManager = DataSourceTransactionManager(metadataDataSource()) + + @Bean + open fun metadataDataSource(): DataSource = + EmbeddedDatabaseBuilder() + .setType(EmbeddedDatabaseType.H2) + .addScript("/org/springframework/batch/core/schema-h2.sql") + .generateUniqueName(true) + .build() + } +} diff --git a/spring-batch-plus-kotlin/src/integrationTest/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/job/step/builder/PartitionStepBuilderDslIntegrationTest.kt b/spring-batch-plus-kotlin/src/integrationTest/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/job/step/builder/PartitionStepBuilderDslIntegrationTest.kt new file mode 100644 index 00000000..85824733 --- /dev/null +++ b/spring-batch-plus-kotlin/src/integrationTest/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/job/step/builder/PartitionStepBuilderDslIntegrationTest.kt @@ -0,0 +1,312 @@ +/* + * Spring Batch Plus + * + * Copyright 2022-present NAVER Corp. + * + * 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 + * + * http://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 com.navercorp.spring.batch.plus.kotlin.configuration.job.step.builder + +import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Nested +import org.junit.jupiter.api.Test +import org.springframework.batch.core.BatchStatus +import org.springframework.batch.core.ExitStatus +import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing +import org.springframework.batch.core.configuration.annotation.EnableJdbcJobRepository +import org.springframework.batch.core.job.parameters.JobParameters +import org.springframework.batch.core.launch.JobOperator +import org.springframework.batch.core.partition.PartitionHandler +import org.springframework.batch.core.partition.StepExecutionSplitter +import org.springframework.batch.core.repository.JobRepository +import org.springframework.batch.core.step.StepExecution +import org.springframework.batch.infrastructure.item.ExecutionContext +import org.springframework.batch.infrastructure.repeat.RepeatStatus +import org.springframework.batch.infrastructure.support.transaction.ResourcelessTransactionManager +import org.springframework.beans.factory.BeanFactory +import org.springframework.beans.factory.getBean +import org.springframework.context.annotation.AnnotationConfigApplicationContext +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import org.springframework.jdbc.datasource.DataSourceTransactionManager +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType +import org.springframework.transaction.TransactionManager +import java.util.UUID +import javax.sql.DataSource + +/** + * Covers the integration boundary from partition declarations to actual partition-step execution. + */ +internal class PartitionStepBuilderDslIntegrationTest { + @Test + fun partitionerShouldCreatePartitionStepWhenPartitionHandlerIsProvided() { + // given + val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) + val jobOperator = context.getBean() + val batch = context.getBean() + val jobName = UUID.randomUUID().toString() + val stepName = UUID.randomUUID().toString() + val splitStepName = UUID.randomUUID().toString() + val gridSize = 4 + var partitionHandlerCallCount = 0 + var partitionerCallCount = 0 + + // when + val job = + batch { + job(jobName) { + step(stepName) { + partitioner { + partitionHandler { stepSplitter, stepExecution -> + ++partitionHandlerCallCount + stepSplitter + .split(stepExecution, gridSize) + .map { it.complete() } + } + splitter(splitStepName) { partitionCount -> + ++partitionerCallCount + (0 until partitionCount) + .associate { "$it" to ExecutionContext() } + } + } + } + } + } + val jobExecution = jobOperator.start(job, JobParameters()) + + // then + assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) + assertThat(partitionHandlerCallCount).isEqualTo(1) + assertThat(partitionerCallCount).isEqualTo(1) + } + + @Test + fun partitionerShouldCreatePartitionStepWhenTaskExecutorPartitionHandlerIsConfigured() { + // given + val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) + val jobOperator = context.getBean() + val batch = context.getBean() + val jobName = UUID.randomUUID().toString() + val stepName = UUID.randomUUID().toString() + val splitStepName = UUID.randomUUID().toString() + val gridSize = 4 + var workerStepCallCount = 0 + var taskExecutorCallCount = 0 + var partitionerCallCount = 0 + val workerStep = + batch { + step(splitStepName) { + tasklet( + { _, _ -> + ++workerStepCallCount + RepeatStatus.FINISHED + }, + ResourcelessTransactionManager(), + ) + } + } + + // when + val job = + batch { + job(jobName) { + step(stepName) { + partitioner { + partitionHandler { + step(workerStep) + taskExecutor { task -> + ++taskExecutorCallCount + task.run() + } + gridSize(gridSize) + } + splitter(splitStepName) { partitionCount -> + ++partitionerCallCount + (0 until partitionCount) + .associate { "$it" to ExecutionContext() } + } + } + } + } + } + val jobExecution = jobOperator.start(job, JobParameters()) + + // then + assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) + assertThat(workerStepCallCount).isEqualTo(gridSize) + assertThat(taskExecutorCallCount).isEqualTo(gridSize) + assertThat(partitionerCallCount).isEqualTo(1) + } + + @Nested + inner class RedundancyCheck { + @Test + fun partitionHandlerShouldIgnoreTaskExecutorPartitionHandlerSettingsWhenBothAreConfigured() { + // given + val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) + val jobOperator = context.getBean() + val batch = context.getBean() + val jobName = UUID.randomUUID().toString() + val stepName = UUID.randomUUID().toString() + val splitStepName = UUID.randomUUID().toString() + val gridSize = 4 + var partitionHandlerCallCount = 0 + var taskExecutorCallCount = 0 + var workerStepCallCount = 0 + val workerStep = + batch { + step(splitStepName) { + tasklet( + { _, _ -> + ++workerStepCallCount + RepeatStatus.FINISHED + }, + ResourcelessTransactionManager(), + ) + } + } + + // when + val job = + batch { + job(jobName) { + step(stepName) { + partitioner { + partitionHandler { _, _ -> + ++partitionHandlerCallCount + listOf() + } + partitionHandler { + step(workerStep) + taskExecutor { task -> + ++taskExecutorCallCount + task.run() + } + gridSize(gridSize) + } + splitter(splitStepName) { partitionCount -> + (0 until partitionCount) + .associate { "$it" to ExecutionContext() } + } + } + } + } + } + val jobExecution = jobOperator.start(job, JobParameters()) + + // then + assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) + assertThat(partitionHandlerCallCount).isEqualTo(1) + assertThat(taskExecutorCallCount).isEqualTo(0) + assertThat(workerStepCallCount).isEqualTo(0) + } + + @Test + fun splitterShouldIgnorePartitionerWhenBothAreConfigured() { + // given + val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) + val jobOperator = context.getBean() + val batch = context.getBean() + val jobName = UUID.randomUUID().toString() + val stepName = UUID.randomUUID().toString() + val splitStepName = UUID.randomUUID().toString() + val gridSize = 4 + var splitterCallCount = 0 + var partitionerCallCount = 0 + val partitionHandler = + PartitionHandler { stepSplitter, stepExecution -> + stepSplitter + .split(stepExecution, gridSize) + .map { it.complete() } + } + val splitter = + object : StepExecutionSplitter { + override fun getStepName(): String = splitStepName + + override fun split( + stepExecution: StepExecution, + gridSize: Int, + ): Set { + ++splitterCallCount + val jobExecution = stepExecution.jobExecution + return (0 until gridSize) + .map { + StepExecution(0L, "${stepName}$it", jobExecution) + .also { jobExecution.addStepExecution(it) } + }.toSet() + } + } + + // when + val job = + batch { + job(jobName) { + step(stepName) { + partitioner { + partitionHandler(partitionHandler) + splitter(splitter) + splitter(splitStepName) { + ++partitionerCallCount + mapOf() + } + } + } + } + } + val jobExecution = jobOperator.start(job, JobParameters()) + + // then + assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) + assertThat(splitterCallCount).isEqualTo(1) + assertThat(partitionerCallCount).isEqualTo(0) + } + } + + private fun StepExecution.complete(): StepExecution = + apply { + exitStatus = ExitStatus.COMPLETED + status = BatchStatus.COMPLETED + } + + @Configuration + @EnableBatchProcessing + @EnableJdbcJobRepository( + dataSourceRef = "metadataDataSource", + transactionManagerRef = "metadataTransactionManager", + ) + private open class TestConfiguration { + @Bean + open fun batchDsl( + beanFactory: BeanFactory, + jobRepository: JobRepository, + ): BatchDsl = + BatchDsl( + beanFactory, + jobRepository, + ) + + @Bean + open fun metadataTransactionManager(): TransactionManager = DataSourceTransactionManager(metadataDataSource()) + + @Bean + open fun metadataDataSource(): DataSource = + EmbeddedDatabaseBuilder() + .setType(EmbeddedDatabaseType.H2) + .addScript("/org/springframework/batch/core/schema-h2.sql") + .generateUniqueName(true) + .build() + } +} diff --git a/spring-batch-plus-kotlin/src/integrationTest/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/job/step/builder/SimpleStepBuilderDslIntegrationTest.kt b/spring-batch-plus-kotlin/src/integrationTest/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/job/step/builder/SimpleStepBuilderDslIntegrationTest.kt new file mode 100644 index 00000000..47461ad7 --- /dev/null +++ b/spring-batch-plus-kotlin/src/integrationTest/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/job/step/builder/SimpleStepBuilderDslIntegrationTest.kt @@ -0,0 +1,161 @@ +/* + * Spring Batch Plus + * + * Copyright 2022-present NAVER Corp. + * + * 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 + * + * http://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 com.navercorp.spring.batch.plus.kotlin.configuration.job.step.builder + +import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test +import org.springframework.batch.core.BatchStatus +import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing +import org.springframework.batch.core.configuration.annotation.EnableJdbcJobRepository +import org.springframework.batch.core.job.parameters.JobParameters +import org.springframework.batch.core.launch.JobOperator +import org.springframework.batch.core.repository.JobRepository +import org.springframework.batch.infrastructure.repeat.policy.SimpleCompletionPolicy +import org.springframework.batch.infrastructure.support.transaction.ResourcelessTransactionManager +import org.springframework.beans.factory.BeanFactory +import org.springframework.beans.factory.getBean +import org.springframework.context.annotation.AnnotationConfigApplicationContext +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import org.springframework.jdbc.datasource.DataSourceTransactionManager +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType +import org.springframework.transaction.TransactionManager +import java.util.UUID +import javax.sql.DataSource + +/** + * Covers the integration boundary from deprecated chunk declarations to actual simple-step execution. + */ +@Suppress("DEPRECATION") +internal class SimpleStepBuilderDslIntegrationTest { + @Test + fun chunkShouldCreateSimpleStepWhenChunkSizeIsProvided() { + // given + val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) + val jobOperator = context.getBean() + val batch = context.getBean() + val jobName = UUID.randomUUID().toString() + val stepName = UUID.randomUUID().toString() + val readLimit = 20 + val chunkSize = 3 + var readCallCount = 0 + var writeCallCount = 0 + + // when + val job = + batch { + job(jobName) { + step(stepName) { + chunk(chunkSize, ResourcelessTransactionManager()) { + reader { + if (readCallCount < readLimit) { + ++readCallCount + 1 + } else { + null + } + } + writer { + ++writeCallCount + } + } + } + } + } + val jobExecution = jobOperator.start(job, JobParameters()) + + // then + assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) + assertThat(readCallCount).isEqualTo(readLimit) + assertThat(writeCallCount).isEqualTo(7) // Ceil(20/3) + } + + @Test + fun chunkShouldCreateSimpleStepWhenCompletionPolicyIsProvided() { + // given + val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) + val jobOperator = context.getBean() + val batch = context.getBean() + val jobName = UUID.randomUUID().toString() + val stepName = UUID.randomUUID().toString() + val readLimit = 20 + val chunkSize = 3 + var readCallCount = 0 + var writeCallCount = 0 + + // when + val job = + batch { + job(jobName) { + step(stepName) { + chunk(SimpleCompletionPolicy(chunkSize), ResourcelessTransactionManager()) { + reader { + if (readCallCount < readLimit) { + ++readCallCount + 1 + } else { + null + } + } + writer { + ++writeCallCount + } + } + } + } + } + val jobExecution = jobOperator.start(job, JobParameters()) + + // then + assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) + assertThat(readCallCount).isEqualTo(readLimit) + assertThat(writeCallCount).isEqualTo(7) // Ceil(20/3) + } + + @Configuration + @EnableBatchProcessing + @EnableJdbcJobRepository( + dataSourceRef = "metadataDataSource", + transactionManagerRef = "metadataTransactionManager", + ) + private open class TestConfiguration { + @Bean + open fun batchDsl( + beanFactory: BeanFactory, + jobRepository: JobRepository, + ): BatchDsl = + BatchDsl( + beanFactory, + jobRepository, + ) + + @Bean + open fun metadataTransactionManager(): TransactionManager = DataSourceTransactionManager(metadataDataSource()) + + @Bean + open fun metadataDataSource(): DataSource = + EmbeddedDatabaseBuilder() + .setType(EmbeddedDatabaseType.H2) + .addScript("/org/springframework/batch/core/schema-h2.sql") + .generateUniqueName(true) + .build() + } +} diff --git a/spring-batch-plus-kotlin/src/integrationTest/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/job/step/builder/TaskletStepBuilderDslIntegrationTest.kt b/spring-batch-plus-kotlin/src/integrationTest/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/job/step/builder/TaskletStepBuilderDslIntegrationTest.kt new file mode 100644 index 00000000..4bd8c8c6 --- /dev/null +++ b/spring-batch-plus-kotlin/src/integrationTest/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/job/step/builder/TaskletStepBuilderDslIntegrationTest.kt @@ -0,0 +1,428 @@ +/* + * Spring Batch Plus + * + * Copyright 2022-present NAVER Corp. + * + * 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 + * + * http://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 com.navercorp.spring.batch.plus.kotlin.configuration.job.step.builder + +import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl +import io.mockk.mockk +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Nested +import org.junit.jupiter.api.Test +import org.springframework.batch.core.BatchStatus +import org.springframework.batch.core.annotation.AfterChunk +import org.springframework.batch.core.annotation.AfterStep +import org.springframework.batch.core.annotation.BeforeChunk +import org.springframework.batch.core.annotation.BeforeStep +import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing +import org.springframework.batch.core.configuration.annotation.EnableJdbcJobRepository +import org.springframework.batch.core.job.JobExecution +import org.springframework.batch.core.job.JobInstance +import org.springframework.batch.core.job.parameters.JobParameters +import org.springframework.batch.core.launch.JobOperator +import org.springframework.batch.core.repository.JobRepository +import org.springframework.batch.core.step.StepExecution +import org.springframework.batch.core.step.builder.StepBuilder +import org.springframework.batch.core.step.tasklet.Tasklet +import org.springframework.batch.infrastructure.item.ExecutionContext +import org.springframework.batch.infrastructure.item.ItemStream +import org.springframework.batch.infrastructure.repeat.RepeatCallback +import org.springframework.batch.infrastructure.repeat.RepeatStatus +import org.springframework.batch.infrastructure.repeat.support.RepeatTemplate +import org.springframework.batch.infrastructure.support.transaction.ResourcelessTransactionManager +import org.springframework.beans.factory.BeanFactory +import org.springframework.beans.factory.getBean +import org.springframework.context.annotation.AnnotationConfigApplicationContext +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import org.springframework.context.support.registerBean +import org.springframework.jdbc.datasource.DataSourceTransactionManager +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType +import org.springframework.transaction.TransactionManager +import java.util.UUID +import java.util.concurrent.ThreadLocalRandom +import javax.sql.DataSource + +/** + * Covers the integration boundary from tasklet declarations to actual tasklet-step execution. + */ +internal class TaskletStepBuilderDslIntegrationTest { + @Test + fun taskletBeanShouldCreateTaskletStepWhenBeanNameIsProvided() { + // given + val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) + val jobOperator = context.getBean() + val batch = context.getBean() + var taskletCallCount = 0 + val tasklet = + Tasklet { _, _ -> + ++taskletCallCount + RepeatStatus.FINISHED + } + context.registerBean("testTasklet") { + tasklet + } + + // when + val job = + batch { + job("testJob") { + step("testStep") { + taskletBean("testTasklet") + } + } + } + val jobExecution = jobOperator.start(job, JobParameters()) + + // then + assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) + assertThat(taskletCallCount).isEqualTo(1) + } + + @Test + fun taskletBeanShouldCreateTaskletStepWhenBeanNameAndInitAreProvided() { + // given + val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) + val jobOperator = context.getBean() + val batch = context.getBean() + var taskletCallCount = 0 + var streamOpenCallCount = 0 + var streamCloseCallCount = 0 + val tasklet = + Tasklet { _, _ -> + ++taskletCallCount + RepeatStatus.FINISHED + } + context.registerBean("testTasklet") { + tasklet + } + + // when + val job = + batch { + job("testJob") { + step("testStep") { + taskletBean("testTasklet") { + stream( + object : ItemStream { + override fun open(executionContext: ExecutionContext) { + ++streamOpenCallCount + } + + override fun close() { + ++streamCloseCallCount + } + }, + ) + } + } + } + } + val jobExecution = jobOperator.start(job, JobParameters()) + + // then + assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) + assertThat(taskletCallCount).isEqualTo(1) + assertThat(streamOpenCallCount).isEqualTo(1) + assertThat(streamCloseCallCount).isEqualTo(1) + } + + @Test + fun taskletBeanShouldCreateTaskletStepWhenBeanNameAndTransactionManagerAreProvided() { + // given + val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) + val jobOperator = context.getBean() + val batch = context.getBean() + var taskletCallCount = 0 + val tasklet = + Tasklet { _, _ -> + ++taskletCallCount + RepeatStatus.FINISHED + } + context.registerBean("testTasklet") { + tasklet + } + + // when + val job = + batch { + job("testJob") { + step("testStep") { + taskletBean("testTasklet", ResourcelessTransactionManager()) + } + } + } + val jobExecution = jobOperator.start(job, JobParameters()) + + // then + assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) + assertThat(taskletCallCount).isEqualTo(1) + } + + @Test + fun taskletBeanShouldCreateTaskletStepWhenBeanNameTransactionManagerAndInitAreProvided() { + // given + val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) + val jobOperator = context.getBean() + val batch = context.getBean() + var taskletCallCount = 0 + var streamOpenCallCount = 0 + var streamCloseCallCount = 0 + val tasklet = + Tasklet { _, _ -> + ++taskletCallCount + RepeatStatus.FINISHED + } + context.registerBean("testTasklet") { + tasklet + } + + // when + val job = + batch { + job("testJob") { + step("testStep") { + taskletBean("testTasklet", ResourcelessTransactionManager()) { + stream( + object : ItemStream { + override fun open(executionContext: ExecutionContext) { + ++streamOpenCallCount + } + + override fun close() { + ++streamCloseCallCount + } + }, + ) + } + } + } + } + val jobExecution = jobOperator.start(job, JobParameters()) + + // then + assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) + assertThat(taskletCallCount).isEqualTo(1) + assertThat(streamOpenCallCount).isEqualTo(1) + assertThat(streamCloseCallCount).isEqualTo(1) + } + + @Test + fun taskletShouldCreateTaskletStepWhenLambdaIsProvided() { + // given + val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) + val jobOperator = context.getBean() + val batch = context.getBean() + var taskletCallCount = 0 + + // when + val job = + batch { + job("testJob") { + step("testStep") { + tasklet { _, _ -> + ++taskletCallCount + RepeatStatus.FINISHED + } + } + } + } + val jobExecution = jobOperator.start(job, JobParameters()) + + // then + assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) + assertThat(taskletCallCount).isEqualTo(1) + } + + @Test + fun taskletShouldCreateTaskletStepWhenLambdaAndInitAreProvided() { + // given + val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) + val jobOperator = context.getBean() + val batch = context.getBean() + var taskletCallCount = 0 + var streamOpenCallCount = 0 + var streamCloseCallCount = 0 + + // when + val job = + batch { + job("testJob") { + step("testStep") { + tasklet( + { _, _ -> + ++taskletCallCount + RepeatStatus.FINISHED + }, + ) { + stream( + object : ItemStream { + override fun open(executionContext: ExecutionContext) { + ++streamOpenCallCount + } + + override fun close() { + ++streamCloseCallCount + } + }, + ) + } + } + } + } + val jobExecution = jobOperator.start(job, JobParameters()) + + // then + assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) + assertThat(taskletCallCount).isEqualTo(1) + assertThat(streamOpenCallCount).isEqualTo(1) + assertThat(streamCloseCallCount).isEqualTo(1) + } + + @Test + fun listenerShouldInvokeAnnotatedCallbacksWhenTaskletStepRuns() { + // given + val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) + val jobOperator = context.getBean() + val batch = context.getBean() + var taskletCallCount = 0 + var beforeStepCallCount = 0 + var afterStepCallCount = 0 + var beforeChunkCallCount = 0 + var afterChunkCallCount = 0 + + // when + val job = + batch { + job("testJob") { + step("testStep") { + tasklet( + { _, _ -> + ++taskletCallCount + RepeatStatus.FINISHED + }, + ) { + listener( + object { + @BeforeStep + fun beforeStep() { + ++beforeStepCallCount + } + + @AfterStep + fun afterStep() { + ++afterStepCallCount + } + + @BeforeChunk + fun beforeChunk() { + ++beforeChunkCallCount + } + + @AfterChunk + fun afterChunk() { + ++afterChunkCallCount + } + }, + ) + } + } + } + } + val jobExecution = jobOperator.start(job, JobParameters()) + + // then + assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) + assertThat(taskletCallCount).isEqualTo(1) + assertThat(beforeStepCallCount).isEqualTo(1) + assertThat(afterStepCallCount).isEqualTo(1) + assertThat(beforeChunkCallCount).isEqualTo(1) + assertThat(afterChunkCallCount).isEqualTo(1) + } + + @Nested + inner class RedundancyCheck { + @Suppress("DEPRECATION") + @Test + fun stepOperationsShouldIgnoreTaskExecutorAndExceptionHandlerWhenBothAreConfigured() { + // given + var iterateCount = 0 + var taskExecutorCallCount = 0 + var exceptionHandlerCallCount = 0 + val stepBuilder = StepBuilder(UUID.randomUUID().toString(), mockk(relaxed = true)) + + // when + val step = + stepBuilder + .tasklet({ _, _ -> RepeatStatus.FINISHED }, ResourcelessTransactionManager()) + .stepOperations( + object : RepeatTemplate() { + override fun iterate(callback: RepeatCallback): RepeatStatus { + ++iterateCount + return super.iterate(callback) + } + }, + ).taskExecutor { task -> + ++taskExecutorCallCount + task.run() + }.exceptionHandler { _, e -> + ++exceptionHandlerCallCount + throw e + }.build() + val jobInstance = JobInstance(ThreadLocalRandom.current().nextLong(), UUID.randomUUID().toString()) + val jobExecution = JobExecution(0L, jobInstance, JobParameters()) + val stepExecution = StepExecution(0L, step.name, jobExecution) + step.execute(stepExecution) + + // then + assertThat(stepExecution.status).isEqualTo(BatchStatus.COMPLETED) + assertThat(iterateCount).isEqualTo(1) + assertThat(taskExecutorCallCount).isEqualTo(0) + assertThat(exceptionHandlerCallCount).isEqualTo(0) + } + } + + @Configuration + @EnableBatchProcessing + @EnableJdbcJobRepository( + dataSourceRef = "metadataDataSource", + transactionManagerRef = "metadataTransactionManager", + ) + private open class TestConfiguration { + @Bean + open fun batchDsl( + beanFactory: BeanFactory, + jobRepository: JobRepository, + ): BatchDsl = + BatchDsl( + beanFactory, + jobRepository, + ) + + @Bean + open fun metadataTransactionManager(): TransactionManager = DataSourceTransactionManager(metadataDataSource()) + + @Bean + open fun metadataDataSource(): DataSource = + EmbeddedDatabaseBuilder() + .setType(EmbeddedDatabaseType.H2) + .addScript("/org/springframework/batch/core/schema-h2.sql") + .generateUniqueName(true) + .build() + } +} diff --git a/spring-batch-plus-kotlin/src/integrationTest/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/FlowTransitionBuilderDslIntegrationTest.kt b/spring-batch-plus-kotlin/src/integrationTest/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/job/step/transition/StepTransitionBuilderDslIntegrationTest.kt similarity index 71% rename from spring-batch-plus-kotlin/src/integrationTest/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/FlowTransitionBuilderDslIntegrationTest.kt rename to spring-batch-plus-kotlin/src/integrationTest/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/job/step/transition/StepTransitionBuilderDslIntegrationTest.kt index a362b240..7d780bef 100644 --- a/spring-batch-plus-kotlin/src/integrationTest/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/FlowTransitionBuilderDslIntegrationTest.kt +++ b/spring-batch-plus-kotlin/src/integrationTest/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/job/step/transition/StepTransitionBuilderDslIntegrationTest.kt @@ -16,20 +16,22 @@ * limitations under the License. */ -package com.navercorp.spring.batch.plus.kotlin.configuration +package com.navercorp.spring.batch.plus.kotlin.configuration.job.step.transition +import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl import org.assertj.core.api.Assertions.assertThat import org.assertj.core.api.Assertions.assertThatThrownBy import org.junit.jupiter.api.RepeatedTest import org.junit.jupiter.api.Test import org.springframework.batch.core.BatchStatus import org.springframework.batch.core.ExitStatus -import org.springframework.batch.core.JobParameters import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing -import org.springframework.batch.core.launch.JobLauncher +import org.springframework.batch.core.configuration.annotation.EnableJdbcJobRepository +import org.springframework.batch.core.job.parameters.JobParameters +import org.springframework.batch.core.launch.JobOperator import org.springframework.batch.core.repository.JobRepository -import org.springframework.batch.repeat.RepeatStatus -import org.springframework.batch.support.transaction.ResourcelessTransactionManager +import org.springframework.batch.infrastructure.repeat.RepeatStatus +import org.springframework.batch.infrastructure.support.transaction.ResourcelessTransactionManager import org.springframework.beans.factory.BeanFactory import org.springframework.beans.factory.getBean import org.springframework.context.annotation.AnnotationConfigApplicationContext @@ -41,18 +43,20 @@ import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType import org.springframework.transaction.TransactionManager import javax.sql.DataSource -internal class FlowTransitionBuilderDslIntegrationTest { - +/** + * Covers source reselection after the first `on` clause. + */ +internal class StepTransitionBuilderDslIntegrationTest { @RepeatedTest(10) - fun testFlowWithMultipleTransition() { + fun stepShouldFollowMatchingTransitionWhenMultipleTransitionsAreConfigured() { // given val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) - val jobLauncher = context.getBean() + val jobOperator = context.getBean() val batch = context.getBean() val expectedExitStatus = randomExitStatus() var testStep1CallCount = 0 - val testFlow1 = batch { - flow("testFlow1") { + val testStep1 = + batch { step("testStep1") { tasklet( { contribution, _ -> @@ -64,22 +68,22 @@ internal class FlowTransitionBuilderDslIntegrationTest { ) } } - } // when - val job = batch { - job("testJob") { - flow(testFlow1) { - on("COMPLETED") { - end() - } - on("*") { - fail() + val job = + batch { + job("testJob") { + step(testStep1) { + on("COMPLETED") { + end() + } + on("*") { + fail() + } } } } - } - val jobExecution = jobLauncher.run(job, JobParameters()) + val jobExecution = jobOperator.start(job, JobParameters()) // then assertThat(testStep1CallCount).isEqualTo(1) @@ -97,12 +101,12 @@ internal class FlowTransitionBuilderDslIntegrationTest { } @Test - fun testStepWithNoTransition() { + fun stepShouldThrowExceptionWhenTransitionBlockIsEmpty() { // given val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) val batch = context.getBean() - val testFlow1 = batch { - flow("testFlow1") { + val testStep1 = + batch { step("testStep1") { tasklet( { _, _ -> @@ -112,22 +116,20 @@ internal class FlowTransitionBuilderDslIntegrationTest { ) } } - } // when, then assertThatThrownBy { batch { job("testJob") { - flow(testFlow1) { - // no transition + step(testStep1) { } } } - }.hasMessageContaining("should set transition for flow") + }.hasMessageContaining("should set transition for step") } - private fun randomExitStatus(): ExitStatus { - return listOf( + private fun randomExitStatus(): ExitStatus = + listOf( ExitStatus.UNKNOWN, ExitStatus.NOOP, ExitStatus.FAILED, @@ -135,36 +137,33 @@ internal class FlowTransitionBuilderDslIntegrationTest { ExitStatus.COMPLETED, // ExitStatus.EXECUTING, // why considered ExitStatus.COMPLETE? ).random() - } @Configuration - @EnableBatchProcessing( + @EnableBatchProcessing + @EnableJdbcJobRepository( dataSourceRef = "metadataDataSource", transactionManagerRef = "metadataTransactionManager", ) private open class TestConfiguration { - @Bean open fun batchDsl( beanFactory: BeanFactory, jobRepository: JobRepository, - ): BatchDsl = BatchDsl( - beanFactory, - jobRepository, - ) + ): BatchDsl = + BatchDsl( + beanFactory, + jobRepository, + ) @Bean - open fun metadataTransactionManager(): TransactionManager { - return DataSourceTransactionManager(metadataDataSource()) - } + open fun metadataTransactionManager(): TransactionManager = DataSourceTransactionManager(metadataDataSource()) @Bean - open fun metadataDataSource(): DataSource { - return EmbeddedDatabaseBuilder() + open fun metadataDataSource(): DataSource = + EmbeddedDatabaseBuilder() .setType(EmbeddedDatabaseType.H2) .addScript("/org/springframework/batch/core/schema-h2.sql") .generateUniqueName(true) .build() - } } } diff --git a/spring-batch-plus-kotlin/src/integrationTest/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/job/transition/OnDeciderTargetIntegrationTest.kt b/spring-batch-plus-kotlin/src/integrationTest/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/job/transition/OnDeciderTargetIntegrationTest.kt new file mode 100644 index 00000000..6141017c --- /dev/null +++ b/spring-batch-plus-kotlin/src/integrationTest/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/job/transition/OnDeciderTargetIntegrationTest.kt @@ -0,0 +1,194 @@ +/* + * Spring Batch Plus + * + * Copyright 2022-present NAVER Corp. + * + * 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 + * + * http://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 com.navercorp.spring.batch.plus.kotlin.configuration.job.transition + +import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test +import org.springframework.batch.core.BatchStatus +import org.springframework.batch.core.ExitStatus +import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing +import org.springframework.batch.core.configuration.annotation.EnableJdbcJobRepository +import org.springframework.batch.core.job.flow.FlowExecutionStatus +import org.springframework.batch.core.job.flow.JobExecutionDecider +import org.springframework.batch.core.job.parameters.JobParameters +import org.springframework.batch.core.launch.JobOperator +import org.springframework.batch.core.repository.JobRepository +import org.springframework.batch.infrastructure.repeat.RepeatStatus +import org.springframework.batch.infrastructure.support.transaction.ResourcelessTransactionManager +import org.springframework.beans.factory.BeanFactory +import org.springframework.beans.factory.getBean +import org.springframework.context.annotation.AnnotationConfigApplicationContext +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import org.springframework.context.support.registerBean +import org.springframework.jdbc.datasource.DataSourceTransactionManager +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType +import org.springframework.transaction.TransactionManager +import javax.sql.DataSource + +/** + * Covers a decider as an immediate transition destination, distinct from branching from a decider source. + */ +internal class OnDeciderTargetIntegrationTest { + @Test + fun deciderBeanShouldExecuteAsTransitionTargetWhenBeanNameIsProvided() { + // given + val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) + val jobOperator = context.getBean() + val batch = context.getBean() + var testStep1CallCount = 0 + var testDeciderCallCount = 0 + val testStep1 = + batch { + step("testStep1") { + tasklet( + { _, _ -> + ++testStep1CallCount + RepeatStatus.FINISHED + }, + ResourcelessTransactionManager(), + ) + } + } + val testDecider = + JobExecutionDecider { _, _ -> + ++testDeciderCallCount + FlowExecutionStatus("SKIPPED") + } + context.registerBean("testDecider") { + testDecider + } + + // when + val job = + batch { + job("testJob") { + step(testStep1) { + on("COMPLETED") { + deciderBean("testDecider") { + on("COMPLETED") { + fail() + } + on("SKIPPED") { + end("TEST") + } + on("*") { + end() + } + } + } + } + } + } + val jobExecution = jobOperator.start(job, JobParameters()) + + // then + assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) + assertThat(jobExecution.exitStatus.exitCode).isEqualTo(ExitStatus("TEST").exitCode) + assertThat(testStep1CallCount).isEqualTo(1) + assertThat(testDeciderCallCount).isEqualTo(1) + } + + @Test + fun deciderShouldExecuteAsTransitionTargetWhenInstanceIsProvided() { + // given + val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) + val jobOperator = context.getBean() + val batch = context.getBean() + var testStep1CallCount = 0 + var testDeciderCallCount = 0 + val testStep1 = + batch { + step("testStep1") { + tasklet( + { _, _ -> + ++testStep1CallCount + RepeatStatus.FINISHED + }, + ResourcelessTransactionManager(), + ) + } + } + val testDecider = + JobExecutionDecider { _, _ -> + ++testDeciderCallCount + FlowExecutionStatus("SKIPPED") + } + + // when + val job = + batch { + job("testJob") { + step(testStep1) { + on("COMPLETED") { + decider(testDecider) { + on("COMPLETED") { + fail() + } + on("SKIPPED") { + end("TEST") + } + on("*") { + end() + } + } + } + } + } + } + val jobExecution = jobOperator.start(job, JobParameters()) + + // then + assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) + assertThat(jobExecution.exitStatus.exitCode).isEqualTo(ExitStatus("TEST").exitCode) + assertThat(testStep1CallCount).isEqualTo(1) + assertThat(testDeciderCallCount).isEqualTo(1) + } + + @Configuration + @EnableBatchProcessing + @EnableJdbcJobRepository( + dataSourceRef = "metadataDataSource", + transactionManagerRef = "metadataTransactionManager", + ) + private open class TestConfiguration { + @Bean + open fun batchDsl( + beanFactory: BeanFactory, + jobRepository: JobRepository, + ): BatchDsl = + BatchDsl( + beanFactory, + jobRepository, + ) + + @Bean + open fun metadataTransactionManager(): TransactionManager = DataSourceTransactionManager(metadataDataSource()) + + @Bean + open fun metadataDataSource(): DataSource = + EmbeddedDatabaseBuilder() + .setType(EmbeddedDatabaseType.H2) + .addScript("/org/springframework/batch/core/schema-h2.sql") + .generateUniqueName(true) + .build() + } +} diff --git a/spring-batch-plus-kotlin/src/integrationTest/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/job/transition/OnFlowTargetIntegrationTest.kt b/spring-batch-plus-kotlin/src/integrationTest/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/job/transition/OnFlowTargetIntegrationTest.kt new file mode 100644 index 00000000..cfd0bd47 --- /dev/null +++ b/spring-batch-plus-kotlin/src/integrationTest/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/job/transition/OnFlowTargetIntegrationTest.kt @@ -0,0 +1,429 @@ +/* + * Spring Batch Plus + * + * Copyright 2022-present NAVER Corp. + * + * 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 + * + * http://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 com.navercorp.spring.batch.plus.kotlin.configuration.job.transition + +import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test +import org.springframework.batch.core.BatchStatus +import org.springframework.batch.core.ExitStatus +import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing +import org.springframework.batch.core.configuration.annotation.EnableJdbcJobRepository +import org.springframework.batch.core.job.parameters.JobParameters +import org.springframework.batch.core.launch.JobOperator +import org.springframework.batch.core.repository.JobRepository +import org.springframework.batch.infrastructure.repeat.RepeatStatus +import org.springframework.batch.infrastructure.support.transaction.ResourcelessTransactionManager +import org.springframework.beans.factory.BeanFactory +import org.springframework.beans.factory.getBean +import org.springframework.context.annotation.AnnotationConfigApplicationContext +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import org.springframework.context.support.registerBean +import org.springframework.jdbc.datasource.DataSourceTransactionManager +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType +import org.springframework.transaction.TransactionManager +import javax.sql.DataSource + +/** + * Covers a flow as an immediate transition destination, distinct from branching from a flow source. + */ +internal class OnFlowTargetIntegrationTest { + @Test + fun flowBeanShouldExecuteAsTransitionTargetWhenBeanNameIsProvided() { + // given + val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) + val jobOperator = context.getBean() + val batch = context.getBean() + var testStep1CallCount = 0 + var transitionStepCallCount = 0 + val testStep1 = + batch { + step("testStep1") { + tasklet( + { _, _ -> + ++testStep1CallCount + RepeatStatus.FINISHED + }, + ResourcelessTransactionManager(), + ) + } + } + val transitionFlow = + batch { + flow("transitionFlow") { + step("transitionStep") { + tasklet( + { _, _ -> + ++transitionStepCallCount + RepeatStatus.FINISHED + }, + ResourcelessTransactionManager(), + ) + } + } + } + context.registerBean("transitionFlow") { + transitionFlow + } + + // when + val job = + batch { + job("testJob") { + step(testStep1) { + on("COMPLETED") { + flowBean("transitionFlow") + } + } + } + } + val jobExecution = jobOperator.start(job, JobParameters()) + + // then + assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) + assertThat(jobExecution.exitStatus.exitCode).isEqualTo(ExitStatus.COMPLETED.exitCode) + assertThat(testStep1CallCount).isEqualTo(1) + assertThat(transitionStepCallCount).isEqualTo(1) + } + + @Test + fun flowShouldExecuteAsTransitionTargetWhenInitIsProvided() { + // given + val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) + val jobOperator = context.getBean() + val batch = context.getBean() + var testStep1CallCount = 0 + var transitionStepCallCount = 0 + val testStep1 = + batch { + step("testStep1") { + tasklet( + { _, _ -> + ++testStep1CallCount + RepeatStatus.FINISHED + }, + ResourcelessTransactionManager(), + ) + } + } + + // when + val job = + batch { + job("testJob") { + step(testStep1) { + on("COMPLETED") { + flow("transitionFlow") { + step("transitionStep") { + tasklet( + { _, _ -> + ++transitionStepCallCount + RepeatStatus.FINISHED + }, + ResourcelessTransactionManager(), + ) + } + } + } + } + } + } + val jobExecution = jobOperator.start(job, JobParameters()) + + // then + assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) + assertThat(jobExecution.exitStatus.exitCode).isEqualTo(ExitStatus.COMPLETED.exitCode) + assertThat(testStep1CallCount).isEqualTo(1) + assertThat(transitionStepCallCount).isEqualTo(1) + } + + @Test + fun flowShouldExecuteAsTransitionTargetWhenInstanceIsProvided() { + // given + val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) + val jobOperator = context.getBean() + val batch = context.getBean() + var testStep1CallCount = 0 + var transitionStepCallCount = 0 + val testStep1 = + batch { + step("testStep1") { + tasklet( + { _, _ -> + ++testStep1CallCount + RepeatStatus.FINISHED + }, + ResourcelessTransactionManager(), + ) + } + } + val transitionFlow = + batch { + flow("transitionFlow") { + step("transitionStep") { + tasklet( + { _, _ -> + ++transitionStepCallCount + RepeatStatus.FINISHED + }, + ResourcelessTransactionManager(), + ) + } + } + } + + // when + val job = + batch { + job("testJob") { + step(testStep1) { + on("COMPLETED") { + flow(transitionFlow) + } + } + } + } + val jobExecution = jobOperator.start(job, JobParameters()) + + // then + assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) + assertThat(jobExecution.exitStatus.exitCode).isEqualTo(ExitStatus.COMPLETED.exitCode) + assertThat(testStep1CallCount).isEqualTo(1) + assertThat(transitionStepCallCount).isEqualTo(1) + } + + @Test + fun flowBeanShouldApplySubsequentTransitionWhenBeanNameAndTransitionAreProvided() { + // given + val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) + val jobOperator = context.getBean() + val batch = context.getBean() + var testStep1CallCount = 0 + var transitionStepCallCount = 0 + val testStep1 = + batch { + step("testStep1") { + tasklet( + { _, _ -> + ++testStep1CallCount + RepeatStatus.FINISHED + }, + ResourcelessTransactionManager(), + ) + } + } + val transitionFlow = + batch { + flow("transitionFlow") { + step("transitionStep") { + tasklet( + { _, _ -> + ++transitionStepCallCount + RepeatStatus.FINISHED + }, + ResourcelessTransactionManager(), + ) + } + } + } + context.registerBean("transitionFlow") { + transitionFlow + } + + // when + val job = + batch { + job("testJob") { + step(testStep1) { + on("COMPLETED") { + flowBean("transitionFlow") { + on("COMPLETED") { + end("TEST") + } + on("*") { + stop() + } + } + } + } + } + } + val jobExecution = jobOperator.start(job, JobParameters()) + + // then + assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) + assertThat(jobExecution.exitStatus.exitCode).isEqualTo(ExitStatus("TEST").exitCode) + assertThat(testStep1CallCount).isEqualTo(1) + assertThat(transitionStepCallCount).isEqualTo(1) + } + + @Test + fun flowShouldApplySubsequentTransitionWhenInitAndTransitionAreProvided() { + // given + val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) + val jobOperator = context.getBean() + val batch = context.getBean() + var testStep1CallCount = 0 + var transitionStepCallCount = 0 + val testStep1 = + batch { + step("testStep1") { + tasklet( + { _, _ -> + ++testStep1CallCount + RepeatStatus.FINISHED + }, + ResourcelessTransactionManager(), + ) + } + } + + // when + val job = + batch { + job("testJob") { + step(testStep1) { + on("COMPLETED") { + flow( + "transitionFlow", + { + step("transitionStep") { + tasklet( + { _, _ -> + ++transitionStepCallCount + RepeatStatus.FINISHED + }, + ResourcelessTransactionManager(), + ) + } + }, + ) { + on("COMPLETED") { + end("TEST") + } + on("*") { + stop() + } + } + } + } + } + } + val jobExecution = jobOperator.start(job, JobParameters()) + + // then + assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) + assertThat(jobExecution.exitStatus.exitCode).isEqualTo(ExitStatus("TEST").exitCode) + assertThat(testStep1CallCount).isEqualTo(1) + assertThat(transitionStepCallCount).isEqualTo(1) + } + + @Test + fun flowShouldApplySubsequentTransitionWhenInstanceAndTransitionAreProvided() { + // given + val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) + val jobOperator = context.getBean() + val batch = context.getBean() + var testStep1CallCount = 0 + var transitionStepCallCount = 0 + val testStep1 = + batch { + step("testStep1") { + tasklet( + { _, _ -> + ++testStep1CallCount + RepeatStatus.FINISHED + }, + ResourcelessTransactionManager(), + ) + } + } + val transitionFlow = + batch { + flow("transitionFlow") { + step("transitionStep") { + tasklet( + { _, _ -> + ++transitionStepCallCount + RepeatStatus.FINISHED + }, + ResourcelessTransactionManager(), + ) + } + } + } + + // when + val job = + batch { + job("testJob") { + step(testStep1) { + on("COMPLETED") { + flow(transitionFlow) { + on("COMPLETED") { + end("TEST") + } + on("*") { + stop() + } + } + } + } + } + } + val jobExecution = jobOperator.start(job, JobParameters()) + + // then + assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) + assertThat(jobExecution.exitStatus.exitCode).isEqualTo(ExitStatus("TEST").exitCode) + assertThat(testStep1CallCount).isEqualTo(1) + assertThat(transitionStepCallCount).isEqualTo(1) + } + + @Configuration + @EnableBatchProcessing + @EnableJdbcJobRepository( + dataSourceRef = "metadataDataSource", + transactionManagerRef = "metadataTransactionManager", + ) + private open class TestConfiguration { + @Bean + open fun batchDsl( + beanFactory: BeanFactory, + jobRepository: JobRepository, + ): BatchDsl = + BatchDsl( + beanFactory, + jobRepository, + ) + + @Bean + open fun metadataTransactionManager(): TransactionManager = DataSourceTransactionManager(metadataDataSource()) + + @Bean + open fun metadataDataSource(): DataSource = + EmbeddedDatabaseBuilder() + .setType(EmbeddedDatabaseType.H2) + .addScript("/org/springframework/batch/core/schema-h2.sql") + .generateUniqueName(true) + .build() + } +} diff --git a/spring-batch-plus-kotlin/src/integrationTest/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/job/transition/OnStepTargetIntegrationTest.kt b/spring-batch-plus-kotlin/src/integrationTest/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/job/transition/OnStepTargetIntegrationTest.kt new file mode 100644 index 00000000..4007e44e --- /dev/null +++ b/spring-batch-plus-kotlin/src/integrationTest/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/job/transition/OnStepTargetIntegrationTest.kt @@ -0,0 +1,426 @@ +/* + * Spring Batch Plus + * + * Copyright 2022-present NAVER Corp. + * + * 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 + * + * http://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 com.navercorp.spring.batch.plus.kotlin.configuration.job.transition + +import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test +import org.springframework.batch.core.BatchStatus +import org.springframework.batch.core.ExitStatus +import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing +import org.springframework.batch.core.configuration.annotation.EnableJdbcJobRepository +import org.springframework.batch.core.job.parameters.JobParameters +import org.springframework.batch.core.launch.JobOperator +import org.springframework.batch.core.repository.JobRepository +import org.springframework.batch.infrastructure.repeat.RepeatStatus +import org.springframework.batch.infrastructure.support.transaction.ResourcelessTransactionManager +import org.springframework.beans.factory.BeanFactory +import org.springframework.beans.factory.getBean +import org.springframework.context.annotation.AnnotationConfigApplicationContext +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import org.springframework.context.support.registerBean +import org.springframework.jdbc.datasource.DataSourceTransactionManager +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType +import org.springframework.transaction.TransactionManager +import javax.sql.DataSource + +/** + * Covers a step as an immediate transition destination, distinct from branching from a step source. + */ +internal class OnStepTargetIntegrationTest { + @Test + fun stepBeanShouldExecuteAsTransitionTargetWhenBeanNameIsProvided() { + // given + val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) + val jobOperator = context.getBean() + val batch = context.getBean() + var testStep1CallCount = 0 + var transitionStepCallCount = 0 + val testStep1 = + batch { + step("testStep1") { + tasklet( + { _, _ -> + ++testStep1CallCount + RepeatStatus.FINISHED + }, + ResourcelessTransactionManager(), + ) + } + } + val transitionStep = + batch { + step("transitionStep") { + tasklet( + { _, _ -> + ++transitionStepCallCount + RepeatStatus.FINISHED + }, + ResourcelessTransactionManager(), + ) + } + } + context.registerBean("transitionStep") { + transitionStep + } + + // when + val job = + batch { + job("testJob") { + step(testStep1) { + on("COMPLETED") { + stepBean("transitionStep") + } + } + } + } + val jobExecution = jobOperator.start(job, JobParameters()) + + // then + assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) + assertThat(jobExecution.exitStatus.exitCode).isEqualTo(ExitStatus.COMPLETED.exitCode) + assertThat(testStep1CallCount).isEqualTo(1) + assertThat(transitionStepCallCount).isEqualTo(1) + } + + @Test + fun stepShouldExecuteAsTransitionTargetWhenInitIsProvided() { + // given + val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) + val jobOperator = context.getBean() + val batch = context.getBean() + var testStep1CallCount = 0 + var transitionStepCallCount = 0 + val testStep1 = + batch { + step("testStep1") { + tasklet( + { _, _ -> + ++testStep1CallCount + RepeatStatus.FINISHED + }, + ResourcelessTransactionManager(), + ) + } + } + + // when + val job = + batch { + job("testJob") { + step(testStep1) { + on("COMPLETED") { + step("transitionStep") { + tasklet( + { _, _ -> + ++transitionStepCallCount + RepeatStatus.FINISHED + }, + ResourcelessTransactionManager(), + ) + } + } + } + } + } + val jobExecution = jobOperator.start(job, JobParameters()) + + // then + assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) + assertThat(jobExecution.exitStatus.exitCode).isEqualTo(ExitStatus.COMPLETED.exitCode) + assertThat(testStep1CallCount).isEqualTo(1) + assertThat(transitionStepCallCount).isEqualTo(1) + } + + @Test + fun stepShouldExecuteAsTransitionTargetWhenInstanceIsProvided() { + // given + val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) + val jobOperator = context.getBean() + val batch = context.getBean() + var testStep1CallCount = 0 + var transitionStepCallCount = 0 + val testStep1 = + batch { + step("testStep1") { + tasklet( + { _, _ -> + ++testStep1CallCount + RepeatStatus.FINISHED + }, + ResourcelessTransactionManager(), + ) + } + } + val transitionStep = + batch { + step("transitionStep") { + tasklet( + { _, _ -> + ++transitionStepCallCount + RepeatStatus.FINISHED + }, + ResourcelessTransactionManager(), + ) + } + } + + // when + val job = + batch { + job("testJob") { + step(testStep1) { + on("COMPLETED") { + step(transitionStep) + } + } + } + } + val jobExecution = jobOperator.start(job, JobParameters()) + + // then + assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) + assertThat(jobExecution.exitStatus.exitCode).isEqualTo(ExitStatus.COMPLETED.exitCode) + assertThat(testStep1CallCount).isEqualTo(1) + assertThat(transitionStepCallCount).isEqualTo(1) + } + + @Test + fun stepBeanShouldApplySubsequentTransitionWhenBeanNameAndTransitionAreProvided() { + // given + val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) + val jobOperator = context.getBean() + val batch = context.getBean() + var testStep1CallCount = 0 + var transitionStepCallCount = 0 + val testStep1 = + batch { + step("testStep1") { + tasklet( + { _, _ -> + ++testStep1CallCount + RepeatStatus.FINISHED + }, + ResourcelessTransactionManager(), + ) + } + } + val transitionStep = + batch { + step("transitionStep") { + tasklet( + { _, _ -> + ++transitionStepCallCount + throw RuntimeException("Error") + }, + ResourcelessTransactionManager(), + ) + } + } + context.registerBean("transitionStep") { + transitionStep + } + + // when + val job = + batch { + job("testJob") { + step(testStep1) { + on("COMPLETED") { + stepBean("transitionStep") { + on("COMPLETED") { + fail() + } + on("FAILED") { + end("TEST") + } + on("*") { + end() + } + } + } + } + } + } + val jobExecution = jobOperator.start(job, JobParameters()) + + // then + assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) + assertThat(jobExecution.exitStatus.exitCode).isEqualTo(ExitStatus("TEST").exitCode) + assertThat(testStep1CallCount).isEqualTo(1) + assertThat(transitionStepCallCount).isEqualTo(1) + } + + @Test + fun stepShouldApplySubsequentTransitionWhenInitAndTransitionAreProvided() { + // given + val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) + val jobOperator = context.getBean() + val batch = context.getBean() + var testStep1CallCount = 0 + var transitionStepCallCount = 0 + val testStep1 = + batch { + step("testStep1") { + tasklet( + { _, _ -> + ++testStep1CallCount + RepeatStatus.FINISHED + }, + ResourcelessTransactionManager(), + ) + } + } + + // when + val job = + batch { + job("testJob") { + step(testStep1) { + on("COMPLETED") { + step( + "transitionStep", + { + tasklet( + { _, _ -> + ++transitionStepCallCount + throw RuntimeException("Error") + }, + ResourcelessTransactionManager(), + ) + }, + ) { + on("COMPLETED") { + fail() + } + on("FAILED") { + end("TEST") + } + on("*") { + end() + } + } + } + } + } + } + val jobExecution = jobOperator.start(job, JobParameters()) + + // then + assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) + assertThat(jobExecution.exitStatus.exitCode).isEqualTo(ExitStatus("TEST").exitCode) + assertThat(testStep1CallCount).isEqualTo(1) + assertThat(transitionStepCallCount).isEqualTo(1) + } + + @Test + fun stepShouldApplySubsequentTransitionWhenInstanceAndTransitionAreProvided() { + // given + val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) + val jobOperator = context.getBean() + val batch = context.getBean() + var testStep1CallCount = 0 + var transitionStepCallCount = 0 + val testStep1 = + batch { + step("testStep1") { + tasklet( + { _, _ -> + ++testStep1CallCount + RepeatStatus.FINISHED + }, + ResourcelessTransactionManager(), + ) + } + } + val transitionStep = + batch { + step("transitionStep") { + tasklet( + { _, _ -> + ++transitionStepCallCount + throw RuntimeException("Error") + }, + ResourcelessTransactionManager(), + ) + } + } + + // when + val job = + batch { + job("testJob") { + step(testStep1) { + on("COMPLETED") { + step(transitionStep) { + on("COMPLETED") { + fail() + } + on("FAILED") { + end("TEST") + } + on("*") { + end() + } + } + } + } + } + } + val jobExecution = jobOperator.start(job, JobParameters()) + + // then + assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) + assertThat(jobExecution.exitStatus.exitCode).isEqualTo(ExitStatus("TEST").exitCode) + assertThat(testStep1CallCount).isEqualTo(1) + assertThat(transitionStepCallCount).isEqualTo(1) + } + + @Configuration + @EnableBatchProcessing + @EnableJdbcJobRepository( + dataSourceRef = "metadataDataSource", + transactionManagerRef = "metadataTransactionManager", + ) + private open class TestConfiguration { + @Bean + open fun batchDsl( + beanFactory: BeanFactory, + jobRepository: JobRepository, + ): BatchDsl = + BatchDsl( + beanFactory, + jobRepository, + ) + + @Bean + open fun metadataTransactionManager(): TransactionManager = DataSourceTransactionManager(metadataDataSource()) + + @Bean + open fun metadataDataSource(): DataSource = + EmbeddedDatabaseBuilder() + .setType(EmbeddedDatabaseType.H2) + .addScript("/org/springframework/batch/core/schema-h2.sql") + .generateUniqueName(true) + .build() + } +} diff --git a/spring-batch-plus-kotlin/src/integrationTest/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/job/transition/OnTargetSelectionIntegrationTest.kt b/spring-batch-plus-kotlin/src/integrationTest/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/job/transition/OnTargetSelectionIntegrationTest.kt new file mode 100644 index 00000000..097295c4 --- /dev/null +++ b/spring-batch-plus-kotlin/src/integrationTest/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/job/transition/OnTargetSelectionIntegrationTest.kt @@ -0,0 +1,100 @@ +/* + * Spring Batch Plus + * + * Copyright 2022-present NAVER Corp. + * + * 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 + * + * http://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 com.navercorp.spring.batch.plus.kotlin.configuration.job.transition + +import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl +import org.assertj.core.api.Assertions.assertThatThrownBy +import org.junit.jupiter.api.Test +import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing +import org.springframework.batch.core.configuration.annotation.EnableJdbcJobRepository +import org.springframework.batch.core.repository.JobRepository +import org.springframework.batch.infrastructure.repeat.RepeatStatus +import org.springframework.batch.infrastructure.support.transaction.ResourcelessTransactionManager +import org.springframework.beans.factory.BeanFactory +import org.springframework.beans.factory.getBean +import org.springframework.context.annotation.AnnotationConfigApplicationContext +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import org.springframework.jdbc.datasource.DataSourceTransactionManager +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType +import org.springframework.transaction.TransactionManager +import javax.sql.DataSource + +/** + * Covers the requirement that every `on` clause select a transition target. + */ +internal class OnTargetSelectionIntegrationTest { + @Test + fun onShouldThrowExceptionWhenTransitionTargetIsNotConfigured() { + // given + val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) + val batch = context.getBean() + val testStep = + batch { + step("testStep") { + tasklet( + { _, _ -> RepeatStatus.FINISHED }, + ResourcelessTransactionManager(), + ) + } + } + + // when, then + assertThatThrownBy { + batch { + job("testJob") { + step(testStep) { + on("COMPLETED") { + } + } + } + } + }.hasMessageContaining("should set transition") + } + + @Configuration + @EnableBatchProcessing + @EnableJdbcJobRepository( + dataSourceRef = "metadataDataSource", + transactionManagerRef = "metadataTransactionManager", + ) + private open class TestConfiguration { + @Bean + open fun batchDsl( + beanFactory: BeanFactory, + jobRepository: JobRepository, + ): BatchDsl = + BatchDsl( + beanFactory, + jobRepository, + ) + + @Bean + open fun metadataTransactionManager(): TransactionManager = DataSourceTransactionManager(metadataDataSource()) + + @Bean + open fun metadataDataSource(): DataSource = + EmbeddedDatabaseBuilder() + .setType(EmbeddedDatabaseType.H2) + .addScript("/org/springframework/batch/core/schema-h2.sql") + .generateUniqueName(true) + .build() + } +} diff --git a/spring-batch-plus-kotlin/src/integrationTest/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/job/transition/OnTerminalActionIntegrationTest.kt b/spring-batch-plus-kotlin/src/integrationTest/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/job/transition/OnTerminalActionIntegrationTest.kt new file mode 100644 index 00000000..f80fe2bb --- /dev/null +++ b/spring-batch-plus-kotlin/src/integrationTest/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/job/transition/OnTerminalActionIntegrationTest.kt @@ -0,0 +1,237 @@ +/* + * Spring Batch Plus + * + * Copyright 2022-present NAVER Corp. + * + * 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 + * + * http://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 com.navercorp.spring.batch.plus.kotlin.configuration.job.transition + +import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test +import org.springframework.batch.core.BatchStatus +import org.springframework.batch.core.ExitStatus +import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing +import org.springframework.batch.core.configuration.annotation.EnableJdbcJobRepository +import org.springframework.batch.core.job.parameters.JobParameters +import org.springframework.batch.core.launch.JobOperator +import org.springframework.batch.core.repository.JobRepository +import org.springframework.batch.infrastructure.repeat.RepeatStatus +import org.springframework.batch.infrastructure.support.transaction.ResourcelessTransactionManager +import org.springframework.beans.factory.BeanFactory +import org.springframework.beans.factory.getBean +import org.springframework.context.annotation.AnnotationConfigApplicationContext +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import org.springframework.jdbc.datasource.DataSourceTransactionManager +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType +import org.springframework.transaction.TransactionManager +import javax.sql.DataSource + +/** + * Covers terminal actions as valid transition targets. + */ +internal class OnTerminalActionIntegrationTest { + @Test + fun stopShouldStopJobWhenTransitionMatches() { + // given + val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) + val jobOperator = context.getBean() + val batch = context.getBean() + var testStep1CallCount = 0 + val testStep1 = + batch { + step("testStep1") { + tasklet( + { _, _ -> + ++testStep1CallCount + RepeatStatus.FINISHED + }, + ResourcelessTransactionManager(), + ) + } + } + + // when + val job = + batch { + job("testJob") { + step(testStep1) { + on("COMPLETED") { + stop() + } + } + } + } + val jobExecution = jobOperator.start(job, JobParameters()) + + // then + assertThat(jobExecution.status).isEqualTo(BatchStatus.STOPPED) + assertThat(jobExecution.exitStatus.exitCode).isEqualTo(ExitStatus.STOPPED.exitCode) + assertThat(testStep1CallCount).isEqualTo(1) + } + + @Test + fun endShouldCompleteJobWhenTransitionMatches() { + // given + val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) + val jobOperator = context.getBean() + val batch = context.getBean() + var testStep1CallCount = 0 + val testStep1 = + batch { + step("testStep1") { + tasklet( + { contribution, _ -> + ++testStep1CallCount + contribution.exitStatus = ExitStatus.UNKNOWN + RepeatStatus.FINISHED + }, + ResourcelessTransactionManager(), + ) + } + } + + // when + val job = + batch { + job("testJob") { + step(testStep1) { + on("UNKNOWN") { + end() + } + } + } + } + val jobExecution = jobOperator.start(job, JobParameters()) + + // then + assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) + assertThat(jobExecution.exitStatus.exitCode).isEqualTo(ExitStatus.COMPLETED.exitCode) + assertThat(testStep1CallCount).isEqualTo(1) + } + + @Test + fun endShouldCompleteJobWithCustomExitStatusWhenStatusIsProvided() { + // given + val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) + val jobOperator = context.getBean() + val batch = context.getBean() + var testStep1CallCount = 0 + val testStep1 = + batch { + step("testStep1") { + tasklet( + { contribution, _ -> + ++testStep1CallCount + contribution.exitStatus = ExitStatus.UNKNOWN + RepeatStatus.FINISHED + }, + ResourcelessTransactionManager(), + ) + } + } + + // when + val job = + batch { + job("testJob") { + step(testStep1) { + on("UNKNOWN") { + end("TEST") + } + on("*") { + end() + } + } + } + } + val jobExecution = jobOperator.start(job, JobParameters()) + + // then + assertThat(jobExecution.status).isEqualTo(BatchStatus.COMPLETED) + assertThat(jobExecution.exitStatus.exitCode).isEqualTo(ExitStatus("TEST").exitCode) + assertThat(testStep1CallCount).isEqualTo(1) + } + + @Test + fun failShouldFailJobWhenTransitionMatches() { + // given + val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) + val jobOperator = context.getBean() + val batch = context.getBean() + var testStep1CallCount = 0 + val testStep1 = + batch { + step("testStep1") { + tasklet( + { _, _ -> + ++testStep1CallCount + RepeatStatus.FINISHED + }, + ResourcelessTransactionManager(), + ) + } + } + + // when + val job = + batch { + job("testJob") { + step(testStep1) { + on("COMPLETED") { + fail() + } + } + } + } + val jobExecution = jobOperator.start(job, JobParameters()) + + // then + assertThat(jobExecution.status).isEqualTo(BatchStatus.FAILED) + assertThat(jobExecution.exitStatus.exitCode).isEqualTo(ExitStatus.FAILED.exitCode) + assertThat(testStep1CallCount).isEqualTo(1) + } + + @Configuration + @EnableBatchProcessing + @EnableJdbcJobRepository( + dataSourceRef = "metadataDataSource", + transactionManagerRef = "metadataTransactionManager", + ) + private open class TestConfiguration { + @Bean + open fun batchDsl( + beanFactory: BeanFactory, + jobRepository: JobRepository, + ): BatchDsl = + BatchDsl( + beanFactory, + jobRepository, + ) + + @Bean + open fun metadataTransactionManager(): TransactionManager = DataSourceTransactionManager(metadataDataSource()) + + @Bean + open fun metadataDataSource(): DataSource = + EmbeddedDatabaseBuilder() + .setType(EmbeddedDatabaseType.H2) + .addScript("/org/springframework/batch/core/schema-h2.sql") + .generateUniqueName(true) + .build() + } +} diff --git a/spring-batch-plus-kotlin/src/integrationTest/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/job/transition/StopAndRestartToDeciderIntegrationTest.kt b/spring-batch-plus-kotlin/src/integrationTest/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/job/transition/StopAndRestartToDeciderIntegrationTest.kt new file mode 100644 index 00000000..15777843 --- /dev/null +++ b/spring-batch-plus-kotlin/src/integrationTest/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/job/transition/StopAndRestartToDeciderIntegrationTest.kt @@ -0,0 +1,214 @@ +/* + * Spring Batch Plus + * + * Copyright 2022-present NAVER Corp. + * + * 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 + * + * http://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 com.navercorp.spring.batch.plus.kotlin.configuration.job.transition + +import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test +import org.springframework.batch.core.BatchStatus +import org.springframework.batch.core.ExitStatus +import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing +import org.springframework.batch.core.configuration.annotation.EnableJdbcJobRepository +import org.springframework.batch.core.job.flow.FlowExecutionStatus +import org.springframework.batch.core.job.flow.JobExecutionDecider +import org.springframework.batch.core.job.parameters.JobParameters +import org.springframework.batch.core.launch.JobOperator +import org.springframework.batch.core.repository.JobRepository +import org.springframework.batch.infrastructure.repeat.RepeatStatus +import org.springframework.batch.infrastructure.support.transaction.ResourcelessTransactionManager +import org.springframework.beans.factory.BeanFactory +import org.springframework.beans.factory.getBean +import org.springframework.context.annotation.AnnotationConfigApplicationContext +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import org.springframework.context.support.registerBean +import org.springframework.jdbc.datasource.DataSourceTransactionManager +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType +import org.springframework.transaction.TransactionManager +import javax.sql.DataSource + +/** + * Covers a decider as the restart target after a stopped execution. + */ +internal class StopAndRestartToDeciderIntegrationTest { + @Test + fun stopAndRestartToDeciderBeanShouldRestartAtDeciderWhenBeanNameIsProvided() { + // given + val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) + val jobOperator = context.getBean() + val batch = context.getBean() + var testStep1CallCount = 0 + var testDeciderCallCount = 0 + var transitionStepCallCount = 0 + val testStep1 = + batch { + step("testStep1") { + tasklet( + { _, _ -> + ++testStep1CallCount + RepeatStatus.FINISHED + }, + ResourcelessTransactionManager(), + ) + } + } + val testDecider = + JobExecutionDecider { _, _ -> + ++testDeciderCallCount + FlowExecutionStatus.UNKNOWN + } + context.registerBean("testDecider") { + testDecider + } + + // when + val job = + batch { + job("testJob") { + step(testStep1) { + on("COMPLETED") { + stopAndRestartToDeciderBean("testDecider") { + on("UNKNOWN") { + step("transitionStep") { + tasklet( + { _, _ -> + ++transitionStepCallCount + RepeatStatus.FINISHED + }, + ResourcelessTransactionManager(), + ) + } + } + on("*") { + fail() + } + } + } + } + } + } + val firstJobExecution = jobOperator.start(job, JobParameters()) + val secondJobExecution = jobOperator.start(job, JobParameters()) + + // then + assertThat(firstJobExecution.status).isEqualTo(BatchStatus.STOPPED) + assertThat(firstJobExecution.exitStatus.exitCode).isEqualTo(ExitStatus.STOPPED.exitCode) + assertThat(secondJobExecution.status).isEqualTo(BatchStatus.COMPLETED) + assertThat(secondJobExecution.exitStatus.exitCode).isEqualTo(ExitStatus.COMPLETED.exitCode) + assertThat(testStep1CallCount).isEqualTo(1) + assertThat(testDeciderCallCount).isEqualTo(1) + assertThat(transitionStepCallCount).isEqualTo(1) + } + + @Test + fun stopAndRestartToDeciderShouldRestartAtDeciderWhenInstanceIsProvided() { + // given + val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) + val jobOperator = context.getBean() + val batch = context.getBean() + var testStep1CallCount = 0 + var testDeciderCallCount = 0 + var transitionStepCallCount = 0 + val testStep1 = + batch { + step("testStep1") { + tasklet( + { _, _ -> + ++testStep1CallCount + RepeatStatus.FINISHED + }, + ResourcelessTransactionManager(), + ) + } + } + + // when + val job = + batch { + job("testJob") { + step(testStep1) { + on("COMPLETED") { + stopAndRestartToDecider( + { _, _ -> + ++testDeciderCallCount + FlowExecutionStatus.UNKNOWN + }, + ) { + on("UNKNOWN") { + step("transitionStep") { + tasklet( + { _, _ -> + ++transitionStepCallCount + RepeatStatus.FINISHED + }, + ResourcelessTransactionManager(), + ) + } + } + on("*") { + fail() + } + } + } + } + } + } + val firstJobExecution = jobOperator.start(job, JobParameters()) + val secondJobExecution = jobOperator.start(job, JobParameters()) + + // then + assertThat(firstJobExecution.status).isEqualTo(BatchStatus.STOPPED) + assertThat(firstJobExecution.exitStatus.exitCode).isEqualTo(ExitStatus.STOPPED.exitCode) + assertThat(secondJobExecution.status).isEqualTo(BatchStatus.COMPLETED) + assertThat(secondJobExecution.exitStatus.exitCode).isEqualTo(ExitStatus.COMPLETED.exitCode) + assertThat(testStep1CallCount).isEqualTo(1) + assertThat(testDeciderCallCount).isEqualTo(1) + assertThat(transitionStepCallCount).isEqualTo(1) + } + + @Configuration + @EnableBatchProcessing + @EnableJdbcJobRepository( + dataSourceRef = "metadataDataSource", + transactionManagerRef = "metadataTransactionManager", + ) + private open class TestConfiguration { + @Bean + open fun batchDsl( + beanFactory: BeanFactory, + jobRepository: JobRepository, + ): BatchDsl = + BatchDsl( + beanFactory, + jobRepository, + ) + + @Bean + open fun metadataTransactionManager(): TransactionManager = DataSourceTransactionManager(metadataDataSource()) + + @Bean + open fun metadataDataSource(): DataSource = + EmbeddedDatabaseBuilder() + .setType(EmbeddedDatabaseType.H2) + .addScript("/org/springframework/batch/core/schema-h2.sql") + .generateUniqueName(true) + .build() + } +} diff --git a/spring-batch-plus-kotlin/src/integrationTest/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/job/transition/StopAndRestartToFlowIntegrationTest.kt b/spring-batch-plus-kotlin/src/integrationTest/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/job/transition/StopAndRestartToFlowIntegrationTest.kt new file mode 100644 index 00000000..e337b681 --- /dev/null +++ b/spring-batch-plus-kotlin/src/integrationTest/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/job/transition/StopAndRestartToFlowIntegrationTest.kt @@ -0,0 +1,444 @@ +/* + * Spring Batch Plus + * + * Copyright 2022-present NAVER Corp. + * + * 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 + * + * http://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 com.navercorp.spring.batch.plus.kotlin.configuration.job.transition + +import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test +import org.springframework.batch.core.BatchStatus +import org.springframework.batch.core.ExitStatus +import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing +import org.springframework.batch.core.configuration.annotation.EnableJdbcJobRepository +import org.springframework.batch.core.job.parameters.JobParameters +import org.springframework.batch.core.launch.JobOperator +import org.springframework.batch.core.repository.JobRepository +import org.springframework.batch.infrastructure.repeat.RepeatStatus +import org.springframework.batch.infrastructure.support.transaction.ResourcelessTransactionManager +import org.springframework.beans.factory.BeanFactory +import org.springframework.beans.factory.getBean +import org.springframework.context.annotation.AnnotationConfigApplicationContext +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import org.springframework.context.support.registerBean +import org.springframework.jdbc.datasource.DataSourceTransactionManager +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType +import org.springframework.transaction.TransactionManager +import javax.sql.DataSource + +/** + * Covers a flow as the restart target after a stopped execution. + */ +internal class StopAndRestartToFlowIntegrationTest { + @Test + fun stopAndRestartToFlowBeanShouldRestartAtFlowWhenBeanNameIsProvided() { + // given + val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) + val jobOperator = context.getBean() + val batch = context.getBean() + var testStep1CallCount = 0 + var transitionStepCallCount = 0 + val testStep1 = + batch { + step("testStep1") { + tasklet( + { _, _ -> + ++testStep1CallCount + RepeatStatus.FINISHED + }, + ResourcelessTransactionManager(), + ) + } + } + val transitionFlow = + batch { + flow("transitionFlow") { + step("transitionStep") { + tasklet( + { _, _ -> + ++transitionStepCallCount + RepeatStatus.FINISHED + }, + ResourcelessTransactionManager(), + ) + } + } + } + context.registerBean("transitionFlow") { + transitionFlow + } + + // when + val job = + batch { + job("testJob") { + step(testStep1) { + on("COMPLETED") { + stopAndRestartToFlowBean("transitionFlow") + } + } + } + } + val firstJobExecution = jobOperator.start(job, JobParameters()) + val secondJobExecution = jobOperator.start(job, JobParameters()) + + // then + assertThat(firstJobExecution.status).isEqualTo(BatchStatus.STOPPED) + assertThat(firstJobExecution.exitStatus.exitCode).isEqualTo(ExitStatus.STOPPED.exitCode) + assertThat(secondJobExecution.status).isEqualTo(BatchStatus.COMPLETED) + assertThat(secondJobExecution.exitStatus.exitCode).isEqualTo(ExitStatus.COMPLETED.exitCode) + assertThat(testStep1CallCount).isEqualTo(1) + assertThat(transitionStepCallCount).isEqualTo(1) + } + + @Test + fun stopAndRestartToFlowShouldRestartAtFlowWhenInitIsProvided() { + // given + val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) + val jobOperator = context.getBean() + val batch = context.getBean() + var testStep1CallCount = 0 + var transitionStepCallCount = 0 + val testStep1 = + batch { + step("testStep1") { + tasklet( + { _, _ -> + ++testStep1CallCount + RepeatStatus.FINISHED + }, + ResourcelessTransactionManager(), + ) + } + } + + // when + val job = + batch { + job("testJob") { + step(testStep1) { + on("COMPLETED") { + stopAndRestartToFlow("transitionFlow") { + step("transitionStep") { + tasklet( + { _, _ -> + ++transitionStepCallCount + RepeatStatus.FINISHED + }, + ResourcelessTransactionManager(), + ) + } + } + } + } + } + } + val firstJobExecution = jobOperator.start(job, JobParameters()) + val secondJobExecution = jobOperator.start(job, JobParameters()) + + // then + assertThat(firstJobExecution.status).isEqualTo(BatchStatus.STOPPED) + assertThat(firstJobExecution.exitStatus.exitCode).isEqualTo(ExitStatus.STOPPED.exitCode) + assertThat(secondJobExecution.status).isEqualTo(BatchStatus.COMPLETED) + assertThat(secondJobExecution.exitStatus.exitCode).isEqualTo(ExitStatus.COMPLETED.exitCode) + assertThat(testStep1CallCount).isEqualTo(1) + assertThat(transitionStepCallCount).isEqualTo(1) + } + + @Test + fun stopAndRestartToFlowShouldRestartAtFlowWhenInstanceIsProvided() { + // given + val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) + val jobOperator = context.getBean() + val batch = context.getBean() + var testStep1CallCount = 0 + var transitionStepCallCount = 0 + val testStep1 = + batch { + step("testStep1") { + tasklet( + { _, _ -> + ++testStep1CallCount + RepeatStatus.FINISHED + }, + ResourcelessTransactionManager(), + ) + } + } + val transitionFlow = + batch { + flow("transitionFlow") { + step("transitionStep") { + tasklet( + { _, _ -> + ++transitionStepCallCount + RepeatStatus.FINISHED + }, + ResourcelessTransactionManager(), + ) + } + } + } + + // when + val job = + batch { + job("testJob") { + step(testStep1) { + on("COMPLETED") { + stopAndRestartToFlow(transitionFlow) + } + } + } + } + val firstJobExecution = jobOperator.start(job, JobParameters()) + val secondJobExecution = jobOperator.start(job, JobParameters()) + + // then + assertThat(firstJobExecution.status).isEqualTo(BatchStatus.STOPPED) + assertThat(firstJobExecution.exitStatus.exitCode).isEqualTo(ExitStatus.STOPPED.exitCode) + assertThat(secondJobExecution.status).isEqualTo(BatchStatus.COMPLETED) + assertThat(secondJobExecution.exitStatus.exitCode).isEqualTo(ExitStatus.COMPLETED.exitCode) + assertThat(testStep1CallCount).isEqualTo(1) + assertThat(transitionStepCallCount).isEqualTo(1) + } + + @Test + fun stopAndRestartToFlowBeanShouldApplySubsequentTransitionAfterRestartWhenBeanNameAndTransitionAreProvided() { + // given + val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) + val jobOperator = context.getBean() + val batch = context.getBean() + var testStep1CallCount = 0 + var transitionStepCallCount = 0 + val testStep1 = + batch { + step("testStep1") { + tasklet( + { _, _ -> + ++testStep1CallCount + RepeatStatus.FINISHED + }, + ResourcelessTransactionManager(), + ) + } + } + val transitionFlow = + batch { + flow("transitionFlow") { + step("transitionStep") { + tasklet( + { _, _ -> + ++transitionStepCallCount + RepeatStatus.FINISHED + }, + ResourcelessTransactionManager(), + ) + } + } + } + context.registerBean("transitionFlow") { + transitionFlow + } + + // when + val job = + batch { + job("testJob") { + step(testStep1) { + on("COMPLETED") { + stopAndRestartToFlowBean("transitionFlow") { + on("COMPLETED") { + end("TEST") + } + on("*") { + stop() + } + } + } + } + } + } + val firstJobExecution = jobOperator.start(job, JobParameters()) + val secondJobExecution = jobOperator.start(job, JobParameters()) + + // then + assertThat(firstJobExecution.status).isEqualTo(BatchStatus.STOPPED) + assertThat(firstJobExecution.exitStatus.exitCode).isEqualTo(ExitStatus.STOPPED.exitCode) + assertThat(secondJobExecution.status).isEqualTo(BatchStatus.COMPLETED) + assertThat(secondJobExecution.exitStatus.exitCode).isEqualTo(ExitStatus("TEST").exitCode) + assertThat(testStep1CallCount).isEqualTo(1) + assertThat(transitionStepCallCount).isEqualTo(1) + } + + @Test + fun stopAndRestartToFlowShouldApplySubsequentTransitionAfterRestartWhenInitAndTransitionAreProvided() { + // given + val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) + val jobOperator = context.getBean() + val batch = context.getBean() + var testStep1CallCount = 0 + var transitionStepCallCount = 0 + val testStep1 = + batch { + step("testStep1") { + tasklet( + { _, _ -> + ++testStep1CallCount + RepeatStatus.FINISHED + }, + ResourcelessTransactionManager(), + ) + } + } + + // when + val job = + batch { + job("testJob") { + step(testStep1) { + on("COMPLETED") { + stopAndRestartToFlow("transitionFlow", { + step("transitionStep") { + tasklet( + { _, _ -> + ++transitionStepCallCount + RepeatStatus.FINISHED + }, + ResourcelessTransactionManager(), + ) + } + }) { + on("COMPLETED") { + end("TEST") + } + on("*") { + stop() + } + } + } + } + } + } + val firstJobExecution = jobOperator.start(job, JobParameters()) + val secondJobExecution = jobOperator.start(job, JobParameters()) + + // then + assertThat(firstJobExecution.status).isEqualTo(BatchStatus.STOPPED) + assertThat(firstJobExecution.exitStatus.exitCode).isEqualTo(ExitStatus.STOPPED.exitCode) + assertThat(secondJobExecution.status).isEqualTo(BatchStatus.COMPLETED) + assertThat(secondJobExecution.exitStatus.exitCode).isEqualTo(ExitStatus("TEST").exitCode) + assertThat(testStep1CallCount).isEqualTo(1) + assertThat(transitionStepCallCount).isEqualTo(1) + } + + @Test + fun stopAndRestartToFlowShouldApplySubsequentTransitionAfterRestartWhenInstanceAndTransitionAreProvided() { + // given + val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) + val jobOperator = context.getBean() + val batch = context.getBean() + var testStep1CallCount = 0 + var transitionStepCallCount = 0 + val testStep1 = + batch { + step("testStep1") { + tasklet( + { _, _ -> + ++testStep1CallCount + RepeatStatus.FINISHED + }, + ResourcelessTransactionManager(), + ) + } + } + val transitionFlow = + batch { + flow("transitionFlow") { + step("transitionStep") { + tasklet( + { _, _ -> + ++transitionStepCallCount + RepeatStatus.FINISHED + }, + ResourcelessTransactionManager(), + ) + } + } + } + + // when + val job = + batch { + job("testJob") { + step(testStep1) { + on("COMPLETED") { + stopAndRestartToFlow(transitionFlow) { + on("COMPLETED") { + end("TEST") + } + on("*") { + stop() + } + } + } + } + } + } + val firstJobExecution = jobOperator.start(job, JobParameters()) + val secondJobExecution = jobOperator.start(job, JobParameters()) + + // then + assertThat(firstJobExecution.status).isEqualTo(BatchStatus.STOPPED) + assertThat(firstJobExecution.exitStatus.exitCode).isEqualTo(ExitStatus.STOPPED.exitCode) + assertThat(secondJobExecution.status).isEqualTo(BatchStatus.COMPLETED) + assertThat(secondJobExecution.exitStatus.exitCode).isEqualTo(ExitStatus("TEST").exitCode) + assertThat(testStep1CallCount).isEqualTo(1) + assertThat(transitionStepCallCount).isEqualTo(1) + } + + @Configuration + @EnableBatchProcessing + @EnableJdbcJobRepository( + dataSourceRef = "metadataDataSource", + transactionManagerRef = "metadataTransactionManager", + ) + private open class TestConfiguration { + @Bean + open fun batchDsl( + beanFactory: BeanFactory, + jobRepository: JobRepository, + ): BatchDsl = + BatchDsl( + beanFactory, + jobRepository, + ) + + @Bean + open fun metadataTransactionManager(): TransactionManager = DataSourceTransactionManager(metadataDataSource()) + + @Bean + open fun metadataDataSource(): DataSource = + EmbeddedDatabaseBuilder() + .setType(EmbeddedDatabaseType.H2) + .addScript("/org/springframework/batch/core/schema-h2.sql") + .generateUniqueName(true) + .build() + } +} diff --git a/spring-batch-plus-kotlin/src/integrationTest/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/job/transition/StopAndRestartToStepIntegrationTest.kt b/spring-batch-plus-kotlin/src/integrationTest/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/job/transition/StopAndRestartToStepIntegrationTest.kt new file mode 100644 index 00000000..4c684ae5 --- /dev/null +++ b/spring-batch-plus-kotlin/src/integrationTest/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/job/transition/StopAndRestartToStepIntegrationTest.kt @@ -0,0 +1,432 @@ +/* + * Spring Batch Plus + * + * Copyright 2022-present NAVER Corp. + * + * 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 + * + * http://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 com.navercorp.spring.batch.plus.kotlin.configuration.job.transition + +import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test +import org.springframework.batch.core.BatchStatus +import org.springframework.batch.core.ExitStatus +import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing +import org.springframework.batch.core.configuration.annotation.EnableJdbcJobRepository +import org.springframework.batch.core.job.parameters.JobParameters +import org.springframework.batch.core.launch.JobOperator +import org.springframework.batch.core.repository.JobRepository +import org.springframework.batch.infrastructure.repeat.RepeatStatus +import org.springframework.batch.infrastructure.support.transaction.ResourcelessTransactionManager +import org.springframework.beans.factory.BeanFactory +import org.springframework.beans.factory.getBean +import org.springframework.context.annotation.AnnotationConfigApplicationContext +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import org.springframework.context.support.registerBean +import org.springframework.jdbc.datasource.DataSourceTransactionManager +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType +import org.springframework.transaction.TransactionManager +import javax.sql.DataSource + +/** + * Covers a step as the restart target after a stopped execution. + */ +internal class StopAndRestartToStepIntegrationTest { + @Test + fun stopAndRestartToStepBeanShouldRestartAtStepWhenBeanNameIsProvided() { + // given + val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) + val jobOperator = context.getBean() + val batch = context.getBean() + var testStep1CallCount = 0 + var transitionStepCallCount = 0 + val testStep1 = + batch { + step("testStep1") { + tasklet( + { _, _ -> + ++testStep1CallCount + RepeatStatus.FINISHED + }, + ResourcelessTransactionManager(), + ) + } + } + val transitionStep = + batch { + step("transitionStep") { + tasklet( + { _, _ -> + ++transitionStepCallCount + RepeatStatus.FINISHED + }, + ResourcelessTransactionManager(), + ) + } + } + context.registerBean("transitionStep") { + transitionStep + } + + // when + val job = + batch { + job("testJob") { + step(testStep1) { + on("COMPLETED") { + stopAndRestartToStepBean("transitionStep") + } + } + } + } + val firstJobExecution = jobOperator.start(job, JobParameters()) + val secondJobExecution = jobOperator.start(job, JobParameters()) + + // then + assertThat(firstJobExecution.status).isEqualTo(BatchStatus.STOPPED) + assertThat(firstJobExecution.exitStatus.exitCode).isEqualTo(ExitStatus.STOPPED.exitCode) + assertThat(secondJobExecution.status).isEqualTo(BatchStatus.COMPLETED) + assertThat(secondJobExecution.exitStatus.exitCode).isEqualTo(ExitStatus.COMPLETED.exitCode) + assertThat(testStep1CallCount).isEqualTo(1) + assertThat(transitionStepCallCount).isEqualTo(1) + } + + @Test + fun stopAndRestartToStepShouldRestartAtStepWhenInitIsProvided() { + // given + val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) + val jobOperator = context.getBean() + val batch = context.getBean() + var testStep1CallCount = 0 + var transitionStepCallCount = 0 + val testStep1 = + batch { + step("testStep1") { + tasklet( + { _, _ -> + ++testStep1CallCount + RepeatStatus.FINISHED + }, + ResourcelessTransactionManager(), + ) + } + } + + // when + val job = + batch { + job("testJob") { + step(testStep1) { + on("COMPLETED") { + stopAndRestartToStep("transitionStep") { + tasklet( + { _, _ -> + ++transitionStepCallCount + RepeatStatus.FINISHED + }, + ResourcelessTransactionManager(), + ) + } + } + } + } + } + val firstJobExecution = jobOperator.start(job, JobParameters()) + val secondJobExecution = jobOperator.start(job, JobParameters()) + + // then + assertThat(firstJobExecution.status).isEqualTo(BatchStatus.STOPPED) + assertThat(firstJobExecution.exitStatus.exitCode).isEqualTo(ExitStatus.STOPPED.exitCode) + assertThat(secondJobExecution.status).isEqualTo(BatchStatus.COMPLETED) + assertThat(secondJobExecution.exitStatus.exitCode).isEqualTo(ExitStatus.COMPLETED.exitCode) + assertThat(testStep1CallCount).isEqualTo(1) + assertThat(transitionStepCallCount).isEqualTo(1) + } + + @Test + fun stopAndRestartToStepShouldRestartAtStepWhenInstanceIsProvided() { + // given + val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) + val jobOperator = context.getBean() + val batch = context.getBean() + var testStep1CallCount = 0 + var transitionStepCallCount = 0 + val testStep1 = + batch { + step("testStep1") { + tasklet( + { _, _ -> + ++testStep1CallCount + RepeatStatus.FINISHED + }, + ResourcelessTransactionManager(), + ) + } + } + val transitionStep = + batch { + step("transitionStep") { + tasklet( + { _, _ -> + ++transitionStepCallCount + RepeatStatus.FINISHED + }, + ResourcelessTransactionManager(), + ) + } + } + + // when + val job = + batch { + job("testJob") { + step(testStep1) { + on("COMPLETED") { + stopAndRestartToStep(transitionStep) + } + } + } + } + val firstJobExecution = jobOperator.start(job, JobParameters()) + val secondJobExecution = jobOperator.start(job, JobParameters()) + + // then + assertThat(firstJobExecution.status).isEqualTo(BatchStatus.STOPPED) + assertThat(firstJobExecution.exitStatus.exitCode).isEqualTo(ExitStatus.STOPPED.exitCode) + assertThat(secondJobExecution.status).isEqualTo(BatchStatus.COMPLETED) + assertThat(secondJobExecution.exitStatus.exitCode).isEqualTo(ExitStatus.COMPLETED.exitCode) + assertThat(testStep1CallCount).isEqualTo(1) + assertThat(transitionStepCallCount).isEqualTo(1) + } + + @Test + fun stopAndRestartToStepBeanShouldApplySubsequentTransitionAfterRestartWhenBeanNameAndTransitionAreProvided() { + // given + val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) + val jobOperator = context.getBean() + val batch = context.getBean() + var testStep1CallCount = 0 + var transitionStepCallCount = 0 + val testStep1 = + batch { + step("testStep1") { + tasklet( + { _, _ -> + ++testStep1CallCount + RepeatStatus.FINISHED + }, + ResourcelessTransactionManager(), + ) + } + } + val transitionStep = + batch { + step("transitionStep") { + tasklet( + { _, _ -> + ++transitionStepCallCount + RepeatStatus.FINISHED + }, + ResourcelessTransactionManager(), + ) + } + } + context.registerBean("transitionStep") { + transitionStep + } + + // when + val job = + batch { + job("testJob") { + step(testStep1) { + on("COMPLETED") { + stopAndRestartToStepBean("transitionStep") { + on("COMPLETED") { + end("TEST") + } + on("*") { + stop() + } + } + } + } + } + } + val firstJobExecution = jobOperator.start(job, JobParameters()) + val secondJobExecution = jobOperator.start(job, JobParameters()) + + // then + assertThat(firstJobExecution.status).isEqualTo(BatchStatus.STOPPED) + assertThat(firstJobExecution.exitStatus.exitCode).isEqualTo(ExitStatus.STOPPED.exitCode) + assertThat(secondJobExecution.status).isEqualTo(BatchStatus.COMPLETED) + assertThat(secondJobExecution.exitStatus.exitCode).isEqualTo(ExitStatus("TEST").exitCode) + assertThat(testStep1CallCount).isEqualTo(1) + assertThat(transitionStepCallCount).isEqualTo(1) + } + + @Test + fun stopAndRestartToStepShouldApplySubsequentTransitionAfterRestartWhenInitAndTransitionAreProvided() { + // given + val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) + val jobOperator = context.getBean() + val batch = context.getBean() + var testStep1CallCount = 0 + var transitionStepCallCount = 0 + val testStep1 = + batch { + step("testStep1") { + tasklet( + { _, _ -> + ++testStep1CallCount + RepeatStatus.FINISHED + }, + ResourcelessTransactionManager(), + ) + } + } + + // when + val job = + batch { + job("testJob") { + step(testStep1) { + on("COMPLETED") { + stopAndRestartToStep("transitionStep", { + tasklet( + { _, _ -> + ++transitionStepCallCount + RepeatStatus.FINISHED + }, + ResourcelessTransactionManager(), + ) + }) { + on("COMPLETED") { + end("TEST") + } + on("*") { + stop() + } + } + } + } + } + } + val firstJobExecution = jobOperator.start(job, JobParameters()) + val secondJobExecution = jobOperator.start(job, JobParameters()) + + // then + assertThat(firstJobExecution.status).isEqualTo(BatchStatus.STOPPED) + assertThat(firstJobExecution.exitStatus.exitCode).isEqualTo(ExitStatus.STOPPED.exitCode) + assertThat(secondJobExecution.status).isEqualTo(BatchStatus.COMPLETED) + assertThat(secondJobExecution.exitStatus.exitCode).isEqualTo(ExitStatus("TEST").exitCode) + assertThat(testStep1CallCount).isEqualTo(1) + assertThat(transitionStepCallCount).isEqualTo(1) + } + + @Test + fun stopAndRestartToStepShouldApplySubsequentTransitionAfterRestartWhenInstanceAndTransitionAreProvided() { + // given + val context = AnnotationConfigApplicationContext(TestConfiguration::class.java) + val jobOperator = context.getBean() + val batch = context.getBean() + var testStep1CallCount = 0 + var transitionStepCallCount = 0 + val testStep1 = + batch { + step("testStep1") { + tasklet( + { _, _ -> + ++testStep1CallCount + RepeatStatus.FINISHED + }, + ResourcelessTransactionManager(), + ) + } + } + val transitionStep = + batch { + step("transitionStep") { + tasklet( + { _, _ -> + ++transitionStepCallCount + RepeatStatus.FINISHED + }, + ResourcelessTransactionManager(), + ) + } + } + + // when + val job = + batch { + job("testJob") { + step(testStep1) { + on("COMPLETED") { + stopAndRestartToStep(transitionStep) { + on("COMPLETED") { + end("TEST") + } + on("*") { + stop() + } + } + } + } + } + } + val firstJobExecution = jobOperator.start(job, JobParameters()) + val secondJobExecution = jobOperator.start(job, JobParameters()) + + // then + assertThat(firstJobExecution.status).isEqualTo(BatchStatus.STOPPED) + assertThat(firstJobExecution.exitStatus.exitCode).isEqualTo(ExitStatus.STOPPED.exitCode) + assertThat(secondJobExecution.status).isEqualTo(BatchStatus.COMPLETED) + assertThat(secondJobExecution.exitStatus.exitCode).isEqualTo(ExitStatus("TEST").exitCode) + assertThat(testStep1CallCount).isEqualTo(1) + assertThat(transitionStepCallCount).isEqualTo(1) + } + + @Configuration + @EnableBatchProcessing + @EnableJdbcJobRepository( + dataSourceRef = "metadataDataSource", + transactionManagerRef = "metadataTransactionManager", + ) + private open class TestConfiguration { + @Bean + open fun batchDsl( + beanFactory: BeanFactory, + jobRepository: JobRepository, + ): BatchDsl = + BatchDsl( + beanFactory, + jobRepository, + ) + + @Bean + open fun metadataTransactionManager(): TransactionManager = DataSourceTransactionManager(metadataDataSource()) + + @Bean + open fun metadataDataSource(): DataSource = + EmbeddedDatabaseBuilder() + .setType(EmbeddedDatabaseType.H2) + .addScript("/org/springframework/batch/core/schema-h2.sql") + .generateUniqueName(true) + .build() + } +} diff --git a/spring-batch-plus-kotlin/src/main/java/com/navercorp/spring/batch/plus/kotlin/configuration/BatchBuilderBridge.java b/spring-batch-plus-kotlin/src/main/java/com/navercorp/spring/batch/plus/kotlin/configuration/BatchBuilderBridge.java new file mode 100644 index 00000000..d3c6ccd8 --- /dev/null +++ b/spring-batch-plus-kotlin/src/main/java/com/navercorp/spring/batch/plus/kotlin/configuration/BatchBuilderBridge.java @@ -0,0 +1,46 @@ +/* + * Spring Batch Plus + * + * Copyright 2022-present NAVER Corp. + * + * 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 + * + * http://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 com.navercorp.spring.batch.plus.kotlin.configuration; + +import org.springframework.batch.core.job.builder.FlowJobBuilder; +import org.springframework.batch.core.job.builder.JobBuilder; +import org.springframework.batch.core.job.builder.SimpleJobBuilder; +import org.springframework.batch.core.step.builder.PartitionStepBuilder; +import org.springframework.batch.core.step.builder.StepBuilder; + +// Java bridge for Spring Batch builder constructors whose F-bounded wildcard +// signatures cannot be matched by the Kotlin K2 compiler. See KT-66570. +@SuppressWarnings("deprecation") +final class BatchBuilderBridge { + + static SimpleJobBuilder toSimpleJobBuilder(JobBuilder jobBuilder) { + return new SimpleJobBuilder(jobBuilder); + } + + static FlowJobBuilder toFlowJobBuilder(JobBuilder jobBuilder) { + return new FlowJobBuilder(jobBuilder); + } + + static PartitionStepBuilder toPartitionStepBuilder(StepBuilder stepBuilder) { + return new PartitionStepBuilder(stepBuilder); + } + + private BatchBuilderBridge() { + } +} diff --git a/spring-batch-plus-kotlin/src/main/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/BatchDsl.kt b/spring-batch-plus-kotlin/src/main/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/BatchDsl.kt index 403a389d..2ed5f6c1 100644 --- a/spring-batch-plus-kotlin/src/main/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/BatchDsl.kt +++ b/spring-batch-plus-kotlin/src/main/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/BatchDsl.kt @@ -20,12 +20,12 @@ package com.navercorp.spring.batch.plus.kotlin.configuration import com.navercorp.spring.batch.plus.kotlin.configuration.support.BatchDslMarker import com.navercorp.spring.batch.plus.kotlin.configuration.support.DslContext -import org.springframework.batch.core.Job -import org.springframework.batch.core.Step +import org.springframework.batch.core.job.Job import org.springframework.batch.core.job.builder.FlowBuilder import org.springframework.batch.core.job.builder.JobBuilder import org.springframework.batch.core.job.flow.Flow import org.springframework.batch.core.repository.JobRepository +import org.springframework.batch.core.step.Step import org.springframework.batch.core.step.builder.StepBuilder import org.springframework.beans.factory.BeanFactory @@ -53,7 +53,10 @@ class BatchDsl internal constructor( /** * Make a new job. */ - fun job(name: String, init: JobBuilderDsl.() -> Unit): Job { + fun job( + name: String, + init: JobBuilderDsl.() -> Unit, + ): Job { val jobRepository = this.dslContext.jobRepository val jobBuilder = JobBuilder(name, jobRepository) return JobBuilderDsl(this.dslContext, jobBuilder).apply(init).build() @@ -62,7 +65,10 @@ class BatchDsl internal constructor( /** * Make a new step. */ - fun step(name: String, init: StepBuilderDsl.() -> Step): Step { + fun step( + name: String, + init: StepBuilderDsl.() -> Step, + ): Step { val jobRepository = this.dslContext.jobRepository val stepBuilder = StepBuilder(name, jobRepository) return StepBuilderDsl(this.dslContext, stepBuilder).let(init) @@ -71,7 +77,10 @@ class BatchDsl internal constructor( /** * Make a new flow. */ - fun flow(name: String, init: FlowBuilderDsl.() -> Unit): Flow { + fun flow( + name: String, + init: FlowBuilderDsl.() -> Unit, + ): Flow { val flowBuilder = FlowBuilder(name) return ConcreteFlowBuilderDsl(this.dslContext, flowBuilder).apply(init).build() } diff --git a/spring-batch-plus-kotlin/src/main/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/ConcreteFlowBuilderDsl.kt b/spring-batch-plus-kotlin/src/main/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/ConcreteFlowBuilderDsl.kt index e58329ce..cd454acb 100644 --- a/spring-batch-plus-kotlin/src/main/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/ConcreteFlowBuilderDsl.kt +++ b/spring-batch-plus-kotlin/src/main/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/ConcreteFlowBuilderDsl.kt @@ -20,16 +20,17 @@ package com.navercorp.spring.batch.plus.kotlin.configuration import com.navercorp.spring.batch.plus.kotlin.configuration.support.BatchDslMarker import com.navercorp.spring.batch.plus.kotlin.configuration.support.DslContext -import org.springframework.batch.core.Step import org.springframework.batch.core.job.builder.FlowBuilder import org.springframework.batch.core.job.flow.Flow import org.springframework.batch.core.job.flow.JobExecutionDecider +import org.springframework.batch.core.step.Step import org.springframework.batch.core.step.builder.StepBuilder import org.springframework.beans.factory.getBean import org.springframework.core.task.TaskExecutor /** - * A concrete implementation for [FlowBuilder][org.springframework.batch.core.job.builder.FlowBuilder]. + * Shared entry implementation for top-level, nested, split, and job flow declarations. + * Source-specific transition blocks are delegated so repeated `on` clauses branch from the same source. */ @BatchDslMarker internal class ConcreteFlowBuilderDsl internal constructor( @@ -49,7 +50,10 @@ internal class ConcreteFlowBuilderDsl internal constructor( /** * Add step. */ - override fun step(name: String, stepInit: StepBuilderDsl.() -> Step) { + override fun step( + name: String, + stepInit: StepBuilderDsl.() -> Step, + ) { val stepBuilder = StepBuilder(name, this.dslContext.jobRepository) val step = StepBuilderDsl(this.dslContext, stepBuilder).let(stepInit) step(step) @@ -59,12 +63,13 @@ internal class ConcreteFlowBuilderDsl internal constructor( * Add step. */ override fun step(step: Step) { - val baseFlowBuilder = if (!this.started) { - this.started = true - this.flowBuilder.start(step) - } else { - this.flowBuilder.next(step) - } + val baseFlowBuilder = + if (!this.started) { + this.started = true + this.flowBuilder.start(step) + } else { + this.flowBuilder.next(step) + } this.flowBuilder = baseFlowBuilder } @@ -72,7 +77,10 @@ internal class ConcreteFlowBuilderDsl internal constructor( /** * Add step by bean name with transition. */ - override fun stepBean(name: String, stepTransitionInit: StepTransitionBuilderDsl.() -> Unit) { + override fun stepBean( + name: String, + stepTransitionInit: StepTransitionBuilderDsl.() -> Unit, + ) { val step = this.dslContext.beanFactory.getBean(name) step(step, stepTransitionInit) } @@ -93,17 +101,22 @@ internal class ConcreteFlowBuilderDsl internal constructor( /** * Add step with transition. */ - override fun step(step: Step, stepTransitionInit: StepTransitionBuilderDsl.() -> Unit) { - val baseFlowBuilder = if (!this.started) { - this.started = true - this.flowBuilder.start(step) - } else { - this.flowBuilder.next(step) - } - - this.flowBuilder = StepTransitionBuilderDsl(this.dslContext, step, baseFlowBuilder) - .apply(stepTransitionInit) - .build() + override fun step( + step: Step, + stepTransitionInit: StepTransitionBuilderDsl.() -> Unit, + ) { + val baseFlowBuilder = + if (!this.started) { + this.started = true + this.flowBuilder.start(step) + } else { + this.flowBuilder.next(step) + } + + this.flowBuilder = + StepTransitionBuilderDsl(this.dslContext, step, baseFlowBuilder) + .apply(stepTransitionInit) + .build() } /** @@ -117,10 +130,15 @@ internal class ConcreteFlowBuilderDsl internal constructor( /** * Add flow. */ - override fun flow(name: String, flowInit: FlowBuilderDsl.() -> Unit) { + override fun flow( + name: String, + flowInit: FlowBuilderDsl.() -> Unit, + ) { val flowBuilder = FlowBuilder(name) - val flow = ConcreteFlowBuilderDsl(this.dslContext, flowBuilder).apply(flowInit) - .build() + val flow = + ConcreteFlowBuilderDsl(this.dslContext, flowBuilder) + .apply(flowInit) + .build() flow(flow) } @@ -128,12 +146,13 @@ internal class ConcreteFlowBuilderDsl internal constructor( * Add flow. */ override fun flow(flow: Flow) { - val baseFlowBuilder = if (!this.started) { - this.started = true - this.flowBuilder.start(flow) - } else { - this.flowBuilder.next(flow) - } + val baseFlowBuilder = + if (!this.started) { + this.started = true + this.flowBuilder.start(flow) + } else { + this.flowBuilder.next(flow) + } this.flowBuilder = baseFlowBuilder } @@ -141,7 +160,10 @@ internal class ConcreteFlowBuilderDsl internal constructor( /** * Add flow by bean name with transition. */ - override fun flowBean(name: String, flowTransitionInit: FlowTransitionBuilderDsl.() -> Unit) { + override fun flowBean( + name: String, + flowTransitionInit: FlowTransitionBuilderDsl.() -> Unit, + ) { val flow = this.dslContext.beanFactory.getBean(name) flow(flow, flowTransitionInit) } @@ -155,25 +177,32 @@ internal class ConcreteFlowBuilderDsl internal constructor( flowTransitionInit: FlowTransitionBuilderDsl.() -> Unit, ) { val flowBuilder = FlowBuilder(name) - val flow = ConcreteFlowBuilderDsl(this.dslContext, flowBuilder).apply(flowInit) - .build() + val flow = + ConcreteFlowBuilderDsl(this.dslContext, flowBuilder) + .apply(flowInit) + .build() flow(flow, flowTransitionInit) } /** * Add flow with transition. */ - override fun flow(flow: Flow, flowTransitionInit: FlowTransitionBuilderDsl.() -> Unit) { - val baseFlowBuilder = if (!this.started) { - this.started = true - this.flowBuilder.start(flow) - } else { - this.flowBuilder.next(flow) - } - - this.flowBuilder = FlowTransitionBuilderDsl(this.dslContext, flow, baseFlowBuilder) - .apply(flowTransitionInit) - .build() + override fun flow( + flow: Flow, + flowTransitionInit: FlowTransitionBuilderDsl.() -> Unit, + ) { + val baseFlowBuilder = + if (!this.started) { + this.started = true + this.flowBuilder.start(flow) + } else { + this.flowBuilder.next(flow) + } + + this.flowBuilder = + FlowTransitionBuilderDsl(this.dslContext, flow, baseFlowBuilder) + .apply(flowTransitionInit) + .build() } /** @@ -194,16 +223,18 @@ internal class ConcreteFlowBuilderDsl internal constructor( decider: JobExecutionDecider, deciderTransitionInit: DeciderTransitionBuilderDsl.() -> Unit, ) { - val baseUnterminatedFlowBuilder = if (!started) { - this.started = true - this.flowBuilder.start(decider) - } else { - this.flowBuilder.next(decider) - } - - this.flowBuilder = DeciderTransitionBuilderDsl(this.dslContext, decider, baseUnterminatedFlowBuilder) - .apply(deciderTransitionInit) - .build() + val baseUnterminatedFlowBuilder = + if (!started) { + this.started = true + this.flowBuilder.start(decider) + } else { + this.flowBuilder.next(decider) + } + + this.flowBuilder = + DeciderTransitionBuilderDsl(this.dslContext, decider, baseUnterminatedFlowBuilder) + .apply(deciderTransitionInit) + .build() } /** @@ -211,10 +242,15 @@ internal class ConcreteFlowBuilderDsl internal constructor( * * @see [FlowBuilder.split][org.springframework.batch.core.job.builder.FlowBuilder.split] */ - override fun split(taskExecutor: TaskExecutor, splitInit: SplitBuilderDsl.() -> Unit) { + override fun split( + taskExecutor: TaskExecutor, + splitInit: SplitBuilderDsl.() -> Unit, + ) { val splitBuilder = this.flowBuilder.split(taskExecutor) - this.flowBuilder = SplitBuilderDsl(this.dslContext, splitBuilder).apply(splitInit) - .build() + this.flowBuilder = + SplitBuilderDsl(this.dslContext, splitBuilder) + .apply(splitInit) + .build() } internal fun build(): T = this.flowBuilder.build() diff --git a/spring-batch-plus-kotlin/src/main/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/DeciderTransitionBuilderDsl.kt b/spring-batch-plus-kotlin/src/main/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/DeciderTransitionBuilderDsl.kt index 3c74f73e..08ee61bd 100644 --- a/spring-batch-plus-kotlin/src/main/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/DeciderTransitionBuilderDsl.kt +++ b/spring-batch-plus-kotlin/src/main/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/DeciderTransitionBuilderDsl.kt @@ -24,7 +24,8 @@ import org.springframework.batch.core.job.builder.FlowBuilder import org.springframework.batch.core.job.flow.JobExecutionDecider /** - * A dsl for decider transition. + * Collects transition clauses that start from a single decider state. + * The first clause continues from the incoming builder; additional clauses branch from the same decider. * * @since 0.1.0 */ @@ -41,23 +42,29 @@ class DeciderTransitionBuilderDsl internal constructor( * * @see [org.springframework.batch.core.job.builder.FlowBuilder.on] */ - fun on(pattern: String, init: TransitionBuilderDsl.() -> Unit) { + fun on( + pattern: String, + init: TransitionBuilderDsl.() -> Unit, + ) { val flowBuilder = this.flowBuilder - val transitionBuilder = if (flowBuilder == null) { - this.baseUnterminatedFlowBuilder.on(pattern) - } else { - flowBuilder.from(this.decider) - .on(pattern) - } + val transitionBuilder = + if (flowBuilder == null) { + this.baseUnterminatedFlowBuilder.on(pattern) + } else { + flowBuilder + .from(this.decider) + .on(pattern) + } - this.flowBuilder = TransitionBuilderDsl(this.dslContext, transitionBuilder).apply(init) - .build() + this.flowBuilder = + TransitionBuilderDsl(this.dslContext, transitionBuilder) + .apply(init) + .build() } - internal fun build(): FlowBuilder { - return checkNotNull(this.flowBuilder) { + internal fun build(): FlowBuilder = + checkNotNull(this.flowBuilder) { "should set transition for decider $decider." } - } } diff --git a/spring-batch-plus-kotlin/src/main/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/FlowBuilderDsl.kt b/spring-batch-plus-kotlin/src/main/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/FlowBuilderDsl.kt index 7fb4b95a..53d217da 100644 --- a/spring-batch-plus-kotlin/src/main/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/FlowBuilderDsl.kt +++ b/spring-batch-plus-kotlin/src/main/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/FlowBuilderDsl.kt @@ -19,20 +19,20 @@ package com.navercorp.spring.batch.plus.kotlin.configuration import com.navercorp.spring.batch.plus.kotlin.configuration.support.BatchDslMarker -import org.springframework.batch.core.Step -import org.springframework.batch.core.job.builder.FlowBuilder +import org.springframework.batch.core.job.builder.FlowJobBuilder import org.springframework.batch.core.job.flow.Flow import org.springframework.batch.core.job.flow.JobExecutionDecider +import org.springframework.batch.core.step.Step import org.springframework.core.task.TaskExecutor /** - * A dsl for [FlowBuilder][org.springframework.batch.core.job.builder.FlowBuilder]. + * Shared DSL for declaring either a standalone [Flow] or the flow of a job. * + * @param T [Flow] for standalone flow declarations, or [FlowJobBuilder] for flow-job declarations * @since 0.1.0 */ @BatchDslMarker interface FlowBuilderDsl { - /** * Add step by bean name. */ @@ -41,7 +41,10 @@ interface FlowBuilderDsl { /** * Add step. */ - fun step(name: String, stepInit: StepBuilderDsl.() -> Step) + fun step( + name: String, + stepInit: StepBuilderDsl.() -> Step, + ) /** * Add step. @@ -51,7 +54,10 @@ interface FlowBuilderDsl { /** * Add step by bean name with transition. */ - fun stepBean(name: String, stepTransitionInit: StepTransitionBuilderDsl.() -> Unit) + fun stepBean( + name: String, + stepTransitionInit: StepTransitionBuilderDsl.() -> Unit, + ) /** * Add step with transition. @@ -65,7 +71,10 @@ interface FlowBuilderDsl { /** * Add step with transition. */ - fun step(step: Step, stepTransitionInit: StepTransitionBuilderDsl.() -> Unit) + fun step( + step: Step, + stepTransitionInit: StepTransitionBuilderDsl.() -> Unit, + ) /** * Add flow by bean name. @@ -75,7 +84,10 @@ interface FlowBuilderDsl { /** * Add flow. */ - fun flow(name: String, flowInit: FlowBuilderDsl.() -> Unit) + fun flow( + name: String, + flowInit: FlowBuilderDsl.() -> Unit, + ) /** * Add flow. @@ -85,7 +97,10 @@ interface FlowBuilderDsl { /** * Add flow by bean name with transition. */ - fun flowBean(name: String, flowTransitionInit: FlowTransitionBuilderDsl.() -> Unit) + fun flowBean( + name: String, + flowTransitionInit: FlowTransitionBuilderDsl.() -> Unit, + ) /** * Add flow with transition. @@ -99,7 +114,10 @@ interface FlowBuilderDsl { /** * Add flow with transition. */ - fun flow(flow: Flow, flowTransitionInit: FlowTransitionBuilderDsl.() -> Unit) + fun flow( + flow: Flow, + flowTransitionInit: FlowTransitionBuilderDsl.() -> Unit, + ) /** * Add decider by bean name with transition. @@ -122,5 +140,8 @@ interface FlowBuilderDsl { * * @see [FlowBuilder.split][org.springframework.batch.core.job.builder.FlowBuilder.split] */ - fun split(taskExecutor: TaskExecutor, splitInit: SplitBuilderDsl.() -> Unit) + fun split( + taskExecutor: TaskExecutor, + splitInit: SplitBuilderDsl.() -> Unit, + ) } diff --git a/spring-batch-plus-kotlin/src/main/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/FlowJobBuilderDsl.kt b/spring-batch-plus-kotlin/src/main/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/FlowJobBuilderDsl.kt index 680ed0f4..b1f65236 100644 --- a/spring-batch-plus-kotlin/src/main/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/FlowJobBuilderDsl.kt +++ b/spring-batch-plus-kotlin/src/main/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/FlowJobBuilderDsl.kt @@ -20,11 +20,12 @@ package com.navercorp.spring.batch.plus.kotlin.configuration import com.navercorp.spring.batch.plus.kotlin.configuration.support.BatchDslMarker import com.navercorp.spring.batch.plus.kotlin.configuration.support.DslContext -import org.springframework.batch.core.Job +import org.springframework.batch.core.job.Job import org.springframework.batch.core.job.builder.FlowJobBuilder /** - * A dsl for [FlowJobBuilder][org.springframework.batch.core.job.builder.FlowJobBuilder]. + * Builds jobs that require Spring Batch's flow-job path. + * The actual flow declaration operations are delegated to [ConcreteFlowBuilderDsl]. */ @BatchDslMarker internal class FlowJobBuilderDsl internal constructor( @@ -32,7 +33,8 @@ internal class FlowJobBuilderDsl internal constructor( private val dslContext: DslContext, private val delegate: ConcreteFlowBuilderDsl, ) : FlowBuilderDsl by delegate { - - internal fun build(): Job = this.delegate.build() - .build() + internal fun build(): Job { + val flowJobBuilder = this.delegate.build() + return flowJobBuilder.build() + } } diff --git a/spring-batch-plus-kotlin/src/main/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/FlowTransitionBuilderDsl.kt b/spring-batch-plus-kotlin/src/main/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/FlowTransitionBuilderDsl.kt index dcb7259f..4480ef5d 100644 --- a/spring-batch-plus-kotlin/src/main/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/FlowTransitionBuilderDsl.kt +++ b/spring-batch-plus-kotlin/src/main/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/FlowTransitionBuilderDsl.kt @@ -24,7 +24,8 @@ import org.springframework.batch.core.job.builder.FlowBuilder import org.springframework.batch.core.job.flow.Flow /** - * A dsl for flow transition. + * Collects transition clauses that start from a single flow. + * The first clause continues from the incoming builder; additional clauses branch from the same flow. * * @since 0.1.0 */ @@ -41,23 +42,29 @@ class FlowTransitionBuilderDsl internal constructor( * * @see [org.springframework.batch.core.job.builder.FlowBuilder.on] */ - fun on(pattern: String, init: TransitionBuilderDsl.() -> Unit) { + fun on( + pattern: String, + init: TransitionBuilderDsl.() -> Unit, + ) { val flowBuilder = this.flowBuilder - val transitionBuilder = if (flowBuilder == null) { - this.baseFlowBuilder.on(pattern) - } else { - flowBuilder.from(this.flow) - .on(pattern) - } + val transitionBuilder = + if (flowBuilder == null) { + this.baseFlowBuilder.on(pattern) + } else { + flowBuilder + .from(this.flow) + .on(pattern) + } - this.flowBuilder = TransitionBuilderDsl(this.dslContext, transitionBuilder).apply(init) - .build() + this.flowBuilder = + TransitionBuilderDsl(this.dslContext, transitionBuilder) + .apply(init) + .build() } - internal fun build(): FlowBuilder { - return checkNotNull(this.flowBuilder) { + internal fun build(): FlowBuilder = + checkNotNull(this.flowBuilder) { "should set transition for flow ${flow.name}" } - } } diff --git a/spring-batch-plus-kotlin/src/main/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/JobBuilderDsl.kt b/spring-batch-plus-kotlin/src/main/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/JobBuilderDsl.kt index bae7930b..d7e505b7 100644 --- a/spring-batch-plus-kotlin/src/main/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/JobBuilderDsl.kt +++ b/spring-batch-plus-kotlin/src/main/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/JobBuilderDsl.kt @@ -21,26 +21,24 @@ package com.navercorp.spring.batch.plus.kotlin.configuration import com.navercorp.spring.batch.plus.kotlin.configuration.support.BatchDslMarker import com.navercorp.spring.batch.plus.kotlin.configuration.support.DslContext import com.navercorp.spring.batch.plus.kotlin.configuration.support.LazyConfigurer -import io.micrometer.core.instrument.MeterRegistry import io.micrometer.observation.ObservationRegistry -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobExecutionListener -import org.springframework.batch.core.JobParametersIncrementer -import org.springframework.batch.core.JobParametersValidator -import org.springframework.batch.core.Step +import org.springframework.batch.core.job.Job import org.springframework.batch.core.job.builder.FlowJobBuilder import org.springframework.batch.core.job.builder.JobBuilder import org.springframework.batch.core.job.builder.JobBuilderHelper import org.springframework.batch.core.job.builder.JobFlowBuilder -import org.springframework.batch.core.job.builder.SimpleJobBuilder import org.springframework.batch.core.job.flow.Flow import org.springframework.batch.core.job.flow.JobExecutionDecider -import org.springframework.batch.core.observability.BatchJobObservationConvention -import org.springframework.batch.core.repository.JobRepository +import org.springframework.batch.core.job.parameters.JobParametersIncrementer +import org.springframework.batch.core.job.parameters.JobParametersValidator +import org.springframework.batch.core.listener.JobExecutionListener +import org.springframework.batch.core.step.Step import org.springframework.core.task.TaskExecutor /** - * A dsl for [JobBuilder][org.springframework.batch.core.job.builder.JobBuilder]. + * Entry DSL for a job block. + * Common job settings are applied to the base [JobBuilder] before the block is + * replayed into either the simple-job or flow-job builder path. * * @since 0.1.0 */ @@ -49,12 +47,11 @@ class JobBuilderDsl internal constructor( private val dslContext: DslContext, private val jobBuilder: JobBuilder, ) : FlowBuilderDsl { + private val lazyConfigurer = LazyConfigurer>() - private var lazyConfigurer = LazyConfigurer>() + private val lazyFlowConfigurer = LazyConfigurer>() - private var lazyFlowConfigurer = LazyConfigurer>() - - private var isFlowJob = false + private var requiresFlowJob = false /** * Set for [JobBuilder.validator][org.springframework.batch.core.job.builder.JobBuilderHelper.validator]. @@ -74,15 +71,6 @@ class JobBuilderDsl internal constructor( } } - /** - * Set for [JobBuilder.observationConvention][org.springframework.batch.core.job.builder.JobBuilderHelper.observationConvention]. - */ - fun observationConvention(observationConvention: BatchJobObservationConvention) { - lazyConfigurer.add { - it.observationConvention(observationConvention) - } - } - /** * Set for [JobBuilder.observationRegistry][org.springframework.batch.core.job.builder.JobBuilderHelper.observationRegistry]. */ @@ -92,28 +80,6 @@ class JobBuilderDsl internal constructor( } } - /** - * Set for [JobBuilder.meterRegistry][org.springframework.batch.core.job.builder.JobBuilderHelper.meterRegistry]. - */ - fun meterRegistry(meterRegistry: MeterRegistry) { - lazyConfigurer.add { - it.meterRegistry(meterRegistry) - } - } - - /** - * Set for [JobBuilder.repository][org.springframework.batch.core.job.builder.JobBuilderHelper.repository]. - */ - @Suppress("DEPRECATION") - @Deprecated( - message = "spring batch 5.1.0 deprecates this", - ) - fun repository(jobRepository: JobRepository) { - lazyConfigurer.add { - it.repository(jobRepository) - } - } - /** * Set listener processing followings. * @@ -150,7 +116,10 @@ class JobBuilderDsl internal constructor( } } - override fun step(name: String, stepInit: StepBuilderDsl.() -> Step) { + override fun step( + name: String, + stepInit: StepBuilderDsl.() -> Step, + ) { this.lazyFlowConfigurer.add { it.step(name, stepInit) } @@ -162,11 +131,14 @@ class JobBuilderDsl internal constructor( } } - override fun stepBean(name: String, stepTransitionInit: StepTransitionBuilderDsl.() -> Unit) { + override fun stepBean( + name: String, + stepTransitionInit: StepTransitionBuilderDsl.() -> Unit, + ) { this.lazyFlowConfigurer.add { it.stepBean(name, stepTransitionInit) } - this.isFlowJob = true + this.requiresFlowJob = true } override fun step( @@ -177,42 +149,51 @@ class JobBuilderDsl internal constructor( this.lazyFlowConfigurer.add { it.step(name, stepInit, stepTransitionInit) } - this.isFlowJob = true + this.requiresFlowJob = true } - override fun step(step: Step, stepTransitionInit: StepTransitionBuilderDsl.() -> Unit) { + override fun step( + step: Step, + stepTransitionInit: StepTransitionBuilderDsl.() -> Unit, + ) { this.lazyFlowConfigurer.add { it.step(step, stepTransitionInit) } - this.isFlowJob = true + this.requiresFlowJob = true } override fun flowBean(name: String) { this.lazyFlowConfigurer.add { it.flowBean(name) } - this.isFlowJob = true + this.requiresFlowJob = true } - override fun flow(name: String, flowInit: FlowBuilderDsl.() -> Unit) { + override fun flow( + name: String, + flowInit: FlowBuilderDsl.() -> Unit, + ) { this.lazyFlowConfigurer.add { it.flow(name, flowInit) } - this.isFlowJob = true + this.requiresFlowJob = true } override fun flow(flow: Flow) { this.lazyFlowConfigurer.add { it.flow(flow) } - this.isFlowJob = true + this.requiresFlowJob = true } - override fun flowBean(name: String, flowTransitionInit: FlowTransitionBuilderDsl.() -> Unit) { + override fun flowBean( + name: String, + flowTransitionInit: FlowTransitionBuilderDsl.() -> Unit, + ) { this.lazyFlowConfigurer.add { it.flowBean(name, flowTransitionInit) } - this.isFlowJob = true + this.requiresFlowJob = true } override fun flow( @@ -223,14 +204,17 @@ class JobBuilderDsl internal constructor( this.lazyFlowConfigurer.add { it.flow(name, flowInit, flowTransitionInit) } - this.isFlowJob = true + this.requiresFlowJob = true } - override fun flow(flow: Flow, flowTransitionInit: FlowTransitionBuilderDsl.() -> Unit) { + override fun flow( + flow: Flow, + flowTransitionInit: FlowTransitionBuilderDsl.() -> Unit, + ) { this.lazyFlowConfigurer.add { it.flow(flow, flowTransitionInit) } - this.isFlowJob = true + this.requiresFlowJob = true } override fun deciderBean( @@ -240,7 +224,7 @@ class JobBuilderDsl internal constructor( this.lazyFlowConfigurer.add { it.deciderBean(name, deciderTransitionInit) } - this.isFlowJob = true + this.requiresFlowJob = true } override fun decider( @@ -250,29 +234,48 @@ class JobBuilderDsl internal constructor( this.lazyFlowConfigurer.add { it.decider(decider, deciderTransitionInit) } - this.isFlowJob = true + this.requiresFlowJob = true } - override fun split(taskExecutor: TaskExecutor, splitInit: SplitBuilderDsl.() -> Unit) { + override fun split( + taskExecutor: TaskExecutor, + splitInit: SplitBuilderDsl.() -> Unit, + ) { this.lazyFlowConfigurer.add { it.split(taskExecutor, splitInit) } - this.isFlowJob = true + this.requiresFlowJob = true } internal fun build(): Job { this.jobBuilder.apply(this.lazyConfigurer) - return if (!isFlowJob) { - val simpleJobBuilder = SimpleJobBuilder(this.jobBuilder) + /** + * A plain sequence of steps can use a simple job. A flow, decider, split, or explicit + * transition requires a flow job because it introduces a flow graph. + */ + return if (!requiresFlowJob) { + /** + * The first step is unknown until deferred declarations are replayed, so + * [JobBuilder.start] cannot be called yet. `SimpleJobBuilder(JobBuilderHelper)` leaves + * the step list open for replay. + */ + val simpleJobBuilder = BatchBuilderBridge.toSimpleJobBuilder(this.jobBuilder) val simpleJobBuilderDsl = SimpleJobBuilderDsl(this.dslContext, simpleJobBuilder) - SimpleJobBuilderDslAdapter(simpleJobBuilderDsl).apply(this.lazyFlowConfigurer) + SimpleJobBuilderDslAdapter(simpleJobBuilderDsl) + .apply(this.lazyFlowConfigurer) .build() } else { - val flowJobBuilder = FlowJobBuilder(this.jobBuilder) + /** + * The first state is unknown until deferred declarations are replayed, so + * [JobBuilder.start] or [JobBuilder.flow] cannot be called yet. + * `JobFlowBuilder(FlowJobBuilder)` leaves the initial state open for replay. + */ + val flowJobBuilder = BatchBuilderBridge.toFlowJobBuilder(this.jobBuilder) val jobFlowBuilder = JobFlowBuilder(flowJobBuilder) val delegate = ConcreteFlowBuilderDsl(this.dslContext, jobFlowBuilder) - FlowJobBuilderDsl(this.dslContext, delegate).apply(this.lazyFlowConfigurer) + FlowJobBuilderDsl(this.dslContext, delegate) + .apply(this.lazyFlowConfigurer) .build() } } diff --git a/spring-batch-plus-kotlin/src/main/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/SimpleJobBuilderDsl.kt b/spring-batch-plus-kotlin/src/main/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/SimpleJobBuilderDsl.kt index 92447f17..adb55a71 100644 --- a/spring-batch-plus-kotlin/src/main/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/SimpleJobBuilderDsl.kt +++ b/spring-batch-plus-kotlin/src/main/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/SimpleJobBuilderDsl.kt @@ -20,27 +20,31 @@ package com.navercorp.spring.batch.plus.kotlin.configuration import com.navercorp.spring.batch.plus.kotlin.configuration.support.BatchDslMarker import com.navercorp.spring.batch.plus.kotlin.configuration.support.DslContext -import org.springframework.batch.core.Job -import org.springframework.batch.core.Step +import org.springframework.batch.core.job.Job import org.springframework.batch.core.job.builder.SimpleJobBuilder +import org.springframework.batch.core.step.Step import org.springframework.batch.core.step.builder.StepBuilder import org.springframework.beans.factory.getBean /** - * A dsl for [SimpleJobBuilder][org.springframework.batch.core.job.builder.SimpleJobBuilder]. + * Builds sequential jobs whose declarations are limited to plain step entries. + * Flow and transition declarations are selected by [JobBuilderDsl] before this + * builder is used. */ @BatchDslMarker internal class SimpleJobBuilderDsl internal constructor( private val dslContext: DslContext, private val simpleJobBuilder: SimpleJobBuilder, ) { - fun stepBean(name: String) { val step = this.dslContext.beanFactory.getBean(name) step(step) } - fun step(name: String, stepInit: StepBuilderDsl.() -> Step) { + fun step( + name: String, + stepInit: StepBuilderDsl.() -> Step, + ) { val stepBuilder = StepBuilder(name, this.dslContext.jobRepository) val step = StepBuilderDsl(this.dslContext, stepBuilder).let(stepInit) step(step) diff --git a/spring-batch-plus-kotlin/src/main/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/SimpleJobBuilderDslAdapter.kt b/spring-batch-plus-kotlin/src/main/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/SimpleJobBuilderDslAdapter.kt index c3d4f7b9..fd985abe 100644 --- a/spring-batch-plus-kotlin/src/main/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/SimpleJobBuilderDslAdapter.kt +++ b/spring-batch-plus-kotlin/src/main/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/SimpleJobBuilderDslAdapter.kt @@ -19,26 +19,30 @@ package com.navercorp.spring.batch.plus.kotlin.configuration import com.navercorp.spring.batch.plus.kotlin.configuration.support.BatchDslMarker -import org.springframework.batch.core.Job -import org.springframework.batch.core.Step +import org.springframework.batch.core.job.Job import org.springframework.batch.core.job.builder.FlowJobBuilder import org.springframework.batch.core.job.flow.Flow import org.springframework.batch.core.job.flow.JobExecutionDecider +import org.springframework.batch.core.step.Step import org.springframework.core.task.TaskExecutor /** - * A dsl for [SimpleJobBuilder][org.springframework.batch.core.job.builder.SimpleJobBuilder]. + * Adapts the simple-job builder to the shared flow declaration replay path. + * Calls that require a flow job fail fast because a simple job can only replay + * plain step declarations. */ @BatchDslMarker internal class SimpleJobBuilderDslAdapter internal constructor( private val simpleJobBuilderDsl: SimpleJobBuilderDsl, ) : FlowBuilderDsl { - override fun stepBean(name: String) { this.simpleJobBuilderDsl.stepBean(name) } - override fun step(name: String, stepInit: StepBuilderDsl.() -> Step) { + override fun step( + name: String, + stepInit: StepBuilderDsl.() -> Step, + ) { this.simpleJobBuilderDsl.step(name, stepInit) } @@ -46,67 +50,61 @@ internal class SimpleJobBuilderDslAdapter internal constructor( this.simpleJobBuilderDsl.step(step) } - override fun stepBean(name: String, stepTransitionInit: StepTransitionBuilderDsl.() -> Unit) { - throw UnsupportedOperationException("SimpleJob can't process flow.") - } + override fun stepBean( + name: String, + stepTransitionInit: StepTransitionBuilderDsl.() -> Unit, + ): Unit = throw UnsupportedOperationException("SimpleJob can't process flow.") override fun step( name: String, stepInit: StepBuilderDsl.() -> Step, stepTransitionInit: StepTransitionBuilderDsl.() -> Unit, - ) { - throw UnsupportedOperationException("SimpleJob can't process flow.") - } + ): Unit = throw UnsupportedOperationException("SimpleJob can't process flow.") - override fun step(step: Step, stepTransitionInit: StepTransitionBuilderDsl.() -> Unit) { - throw UnsupportedOperationException("SimpleJob can't process flow.") - } + override fun step( + step: Step, + stepTransitionInit: StepTransitionBuilderDsl.() -> Unit, + ): Unit = throw UnsupportedOperationException("SimpleJob can't process flow.") - override fun flowBean(name: String) { - throw UnsupportedOperationException("SimpleJob can't process flow.") - } + override fun flowBean(name: String): Unit = throw UnsupportedOperationException("SimpleJob can't process flow.") - override fun flow(name: String, flowInit: FlowBuilderDsl.() -> Unit) { - throw UnsupportedOperationException("SimpleJob can't process flow.") - } + override fun flow( + name: String, + flowInit: FlowBuilderDsl.() -> Unit, + ): Unit = throw UnsupportedOperationException("SimpleJob can't process flow.") - override fun flow(flow: Flow) { - throw UnsupportedOperationException("SimpleJob can't process flow.") - } + override fun flow(flow: Flow): Unit = throw UnsupportedOperationException("SimpleJob can't process flow.") - override fun flowBean(name: String, flowTransitionInit: FlowTransitionBuilderDsl.() -> Unit) { - throw UnsupportedOperationException("SimpleJob can't process flow.") - } + override fun flowBean( + name: String, + flowTransitionInit: FlowTransitionBuilderDsl.() -> Unit, + ): Unit = throw UnsupportedOperationException("SimpleJob can't process flow.") override fun flow( name: String, flowInit: FlowBuilderDsl.() -> Unit, flowTransitionInit: FlowTransitionBuilderDsl.() -> Unit, - ) { - throw UnsupportedOperationException("SimpleJob can't process flow.") - } + ): Unit = throw UnsupportedOperationException("SimpleJob can't process flow.") - override fun flow(flow: Flow, flowTransitionInit: FlowTransitionBuilderDsl.() -> Unit) { - throw UnsupportedOperationException("SimpleJob can't process flow.") - } + override fun flow( + flow: Flow, + flowTransitionInit: FlowTransitionBuilderDsl.() -> Unit, + ): Unit = throw UnsupportedOperationException("SimpleJob can't process flow.") override fun deciderBean( name: String, deciderTransitionInit: DeciderTransitionBuilderDsl.() -> Unit, - ) { - throw UnsupportedOperationException("SimpleJob can't process flow.") - } + ): Unit = throw UnsupportedOperationException("SimpleJob can't process flow.") override fun decider( decider: JobExecutionDecider, deciderTransitionInit: DeciderTransitionBuilderDsl.() -> Unit, - ) { - throw UnsupportedOperationException("SimpleJob can't process flow.") - } + ): Unit = throw UnsupportedOperationException("SimpleJob can't process flow.") - override fun split(taskExecutor: TaskExecutor, splitInit: SplitBuilderDsl.() -> Unit) { - throw UnsupportedOperationException("SimpleJob can't process flow.") - } + override fun split( + taskExecutor: TaskExecutor, + splitInit: SplitBuilderDsl.() -> Unit, + ): Unit = throw UnsupportedOperationException("SimpleJob can't process flow.") internal fun build(): Job = this.simpleJobBuilderDsl.build() } diff --git a/spring-batch-plus-kotlin/src/main/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/SplitBuilderDsl.kt b/spring-batch-plus-kotlin/src/main/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/SplitBuilderDsl.kt index a721b14e..a2758996 100644 --- a/spring-batch-plus-kotlin/src/main/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/SplitBuilderDsl.kt +++ b/spring-batch-plus-kotlin/src/main/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/SplitBuilderDsl.kt @@ -25,7 +25,7 @@ import org.springframework.batch.core.job.flow.Flow import org.springframework.beans.factory.getBean /** - * A dsl for [FlowBuilder.SplitBuilder][org.springframework.batch.core.job.builder.FlowBuilder.SplitBuilder]. + * Collects flows for a split state before adding them to the underlying [FlowBuilder.SplitBuilder]. * * @since 0.1.0 */ @@ -47,10 +47,15 @@ class SplitBuilderDsl internal constructor( /** * Add flow to split. */ - fun flow(name: String, flowInit: FlowBuilderDsl.() -> Unit) { + fun flow( + name: String, + flowInit: FlowBuilderDsl.() -> Unit, + ) { val flowBuilder = FlowBuilder(name) - val flow = ConcreteFlowBuilderDsl(this.dslContext, flowBuilder).apply(flowInit) - .build() + val flow = + ConcreteFlowBuilderDsl(this.dslContext, flowBuilder) + .apply(flowInit) + .build() flow(flow) } diff --git a/spring-batch-plus-kotlin/src/main/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/StepBuilderDsl.kt b/spring-batch-plus-kotlin/src/main/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/StepBuilderDsl.kt index 864c9025..216d4a70 100644 --- a/spring-batch-plus-kotlin/src/main/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/StepBuilderDsl.kt +++ b/spring-batch-plus-kotlin/src/main/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/StepBuilderDsl.kt @@ -18,6 +18,7 @@ package com.navercorp.spring.batch.plus.kotlin.configuration +import com.navercorp.spring.batch.plus.kotlin.configuration.step.ChunkOrientedStepBuilderDsl import com.navercorp.spring.batch.plus.kotlin.configuration.step.FlowStepBuilderDsl import com.navercorp.spring.batch.plus.kotlin.configuration.step.JobStepBuilderDsl import com.navercorp.spring.batch.plus.kotlin.configuration.step.PartitionStepBuilderDsl @@ -25,21 +26,15 @@ import com.navercorp.spring.batch.plus.kotlin.configuration.step.SimpleStepBuild import com.navercorp.spring.batch.plus.kotlin.configuration.step.TaskletStepBuilderDsl import com.navercorp.spring.batch.plus.kotlin.configuration.support.BatchDslMarker import com.navercorp.spring.batch.plus.kotlin.configuration.support.DslContext -import io.micrometer.core.instrument.MeterRegistry import io.micrometer.observation.ObservationRegistry -import org.springframework.batch.core.Job -import org.springframework.batch.core.Step -import org.springframework.batch.core.StepExecutionListener +import org.springframework.batch.core.job.Job import org.springframework.batch.core.job.builder.FlowBuilder import org.springframework.batch.core.job.flow.Flow -import org.springframework.batch.core.observability.BatchStepObservationConvention -import org.springframework.batch.core.repository.JobRepository -import org.springframework.batch.core.step.builder.PartitionStepBuilder -import org.springframework.batch.core.step.builder.SimpleStepBuilder +import org.springframework.batch.core.listener.StepExecutionListener +import org.springframework.batch.core.step.Step import org.springframework.batch.core.step.builder.StepBuilder import org.springframework.batch.core.step.tasklet.Tasklet -import org.springframework.batch.repeat.CompletionPolicy -import org.springframework.batch.repeat.RepeatOperations +import org.springframework.batch.infrastructure.repeat.CompletionPolicy import org.springframework.beans.factory.getBean import org.springframework.transaction.PlatformTransactionManager @@ -53,25 +48,6 @@ class StepBuilderDsl internal constructor( private val dslContext: DslContext, private val stepBuilder: StepBuilder, ) { - - /** - * Set for [StepBuilder.repository][org.springframework.batch.core.step.builder.StepBuilderHelper.repository]. - */ - @Suppress("DEPRECATION") - @Deprecated( - message = "spring batch 5.1.0 deprecates this", - ) - fun repository(jobRepository: JobRepository) { - this.stepBuilder.repository(jobRepository) - } - - /** - * Set for [StepBuilder.observationConvention][org.springframework.batch.core.step.builder.StepBuilderHelper.observationConvention]. - */ - fun observationConvention(observationConvention: BatchStepObservationConvention) { - this.stepBuilder.observationConvention(observationConvention) - } - /** * Set for [StepBuilder.observationRegistry][org.springframework.batch.core.step.builder.StepBuilderHelper.observationRegistry]. */ @@ -79,13 +55,6 @@ class StepBuilderDsl internal constructor( this.stepBuilder.observationRegistry(observationRegistry) } - /** - * Set for [StepBuilder.meterRegistry][org.springframework.batch.core.step.builder.StepBuilderHelper.meterRegistry]. - */ - fun meterRegistry(meterRegistry: MeterRegistry) { - this.stepBuilder.meterRegistry(meterRegistry) - } - /** * Set for [StepBuilder.startLimit][org.springframework.batch.core.step.builder.StepBuilderHelper.startLimit]. */ @@ -120,24 +89,15 @@ class StepBuilderDsl internal constructor( /** * Set tasklet step by bean name. */ - @Suppress("DEPRECATION") - @Deprecated( - message = "spring batch 5.0.0 deprecates this", - replaceWith = ReplaceWith("taskletBean(name, transactionManager)"), - ) - fun taskletBean(name: String): Step { - return taskletBean(name) {} - } + fun taskletBean(name: String): Step = taskletBean(name) {} /** * Set tasklet step by bean name. */ - @Suppress("DEPRECATION") - @Deprecated( - message = "spring batch 5.0.0 deprecates this", - replaceWith = ReplaceWith("taskletBean(name, transactionManager, taskletStepInit)"), - ) - fun taskletBean(name: String, taskletStepInit: TaskletStepBuilderDsl.() -> Unit): Step { + fun taskletBean( + name: String, + taskletStepInit: TaskletStepBuilderDsl.() -> Unit, + ): Step { val tasklet = this.dslContext.beanFactory.getBean(name) return tasklet(tasklet, taskletStepInit) } @@ -145,73 +105,18 @@ class StepBuilderDsl internal constructor( /** * Set tasklet step. */ - @Suppress("DEPRECATION") - @Deprecated( - message = "spring batch 5.0.0 deprecates this", - replaceWith = ReplaceWith("tasklet(tasklet, transactionManager)"), - ) - fun tasklet(tasklet: Tasklet): Step { - return tasklet(tasklet) {} - } + fun tasklet(tasklet: Tasklet): Step = tasklet(tasklet) {} /** * Set tasklet step. */ - @Suppress("DEPRECATION") - @Deprecated( - message = "spring batch 5.0.0 deprecates this", - replaceWith = ReplaceWith("tasklet(tasklet, transactionManager, taskletStepInit)"), - ) - fun tasklet(tasklet: Tasklet, taskletStepInit: TaskletStepBuilderDsl.() -> Unit): Step { - val taskletStepBuilder = this.stepBuilder.tasklet(tasklet) - return TaskletStepBuilderDsl(this.dslContext, taskletStepBuilder).apply(taskletStepInit) - .build() - } - - /** - * Set chunk-based step with a chunk size. - */ - @Suppress("DEPRECATION") - @Deprecated( - message = "spring batch 5.0.0 deprecates this", - replaceWith = ReplaceWith("chunk(chunkSize, transactionManager, simpleStepInit)"), - ) - fun chunk(chunkSize: Int, simpleStepInit: SimpleStepBuilderDsl.() -> Unit): Step { - val simpleStepBuilder = this.stepBuilder.chunk(chunkSize) - return SimpleStepBuilderDsl(this.dslContext, simpleStepBuilder).apply(simpleStepInit) - .build() - } - - /** - * Set chunk-based step with a completion policy. - */ - @Suppress("DEPRECATION") - @Deprecated( - message = "spring batch 5.0.0 deprecates this", - replaceWith = ReplaceWith("chunk(completionPolicy, transactionManager, simpleStepInit)"), - ) - fun chunk( - completionPolicy: CompletionPolicy, - simpleStepInit: SimpleStepBuilderDsl.() -> Unit, - ): Step { - val simpleStepBuilder = this.stepBuilder.chunk(completionPolicy) - return SimpleStepBuilderDsl(this.dslContext, simpleStepBuilder).apply(simpleStepInit) - .build() - } - - /** - * Set chunk-based step with a repeat operations. - */ - @Deprecated( - message = "spring batch 5.0.0 deprecates this", - replaceWith = ReplaceWith("chunk(repeatOperations, transactionManager, simpleStepInit)"), - ) - fun chunk( - repeatOperations: RepeatOperations, - simpleStepInit: SimpleStepBuilderDsl.() -> Unit, + fun tasklet( + tasklet: Tasklet, + taskletStepInit: TaskletStepBuilderDsl.() -> Unit, ): Step { - val simpleStepBuilder = SimpleStepBuilder(this.stepBuilder).chunkOperations(repeatOperations) - return SimpleStepBuilderDsl(this.dslContext, simpleStepBuilder).apply(simpleStepInit) + val taskletStepBuilder = this.stepBuilder.tasklet(tasklet) + return TaskletStepBuilderDsl(this.dslContext, taskletStepBuilder) + .apply(taskletStepInit) .build() } @@ -221,9 +126,7 @@ class StepBuilderDsl internal constructor( fun taskletBean( name: String, transactionManager: PlatformTransactionManager, - ): Step { - return taskletBean(name, transactionManager) {} - } + ): Step = taskletBean(name, transactionManager) {} /** * Set tasklet step by bean name. @@ -243,9 +146,7 @@ class StepBuilderDsl internal constructor( fun tasklet( tasklet: Tasklet, transactionManager: PlatformTransactionManager, - ): Step { - return tasklet(tasklet, transactionManager) {} - } + ): Step = tasklet(tasklet, transactionManager) {} /** * Set tasklet step. @@ -256,49 +157,59 @@ class StepBuilderDsl internal constructor( taskletStepInit: TaskletStepBuilderDsl.() -> Unit, ): Step { val taskletStepBuilder = this.stepBuilder.tasklet(tasklet, transactionManager) - return TaskletStepBuilderDsl(this.dslContext, taskletStepBuilder).apply(taskletStepInit) + return TaskletStepBuilderDsl(this.dslContext, taskletStepBuilder) + .apply(taskletStepInit) .build() } /** * Set chunk-based step with a chunk size. */ + @Suppress("DEPRECATION") + @Deprecated( + message = "Spring Batch 6.0 deprecates this.", + ) fun chunk( chunkSize: Int, transactionManager: PlatformTransactionManager, simpleStepInit: SimpleStepBuilderDsl.() -> Unit, ): Step { val simpleStepBuilder = this.stepBuilder.chunk(chunkSize, transactionManager) - return SimpleStepBuilderDsl(this.dslContext, simpleStepBuilder).apply(simpleStepInit) + return SimpleStepBuilderDsl(this.dslContext, simpleStepBuilder) + .apply(simpleStepInit) .build() } /** - * Set chunk-based step with a completion policy. + * Set chunk-oriented step with a chunk size. + * + * @since 2.0.0 */ fun chunk( - completionPolicy: CompletionPolicy, - transactionManager: PlatformTransactionManager, - simpleStepInit: SimpleStepBuilderDsl.() -> Unit, + chunkSize: Int, + chunkOrientedStepInit: ChunkOrientedStepBuilderDsl.() -> Unit, ): Step { - val simpleStepBuilder = this.stepBuilder.chunk(completionPolicy, transactionManager) - return SimpleStepBuilderDsl(this.dslContext, simpleStepBuilder).apply(simpleStepInit) + val chunkOrientedStepBuilder = this.stepBuilder.chunk(chunkSize) + return ChunkOrientedStepBuilderDsl(this.dslContext, chunkOrientedStepBuilder) + .apply(chunkOrientedStepInit) .build() } /** - * Set chunk-based step with a repeat operations. + * Set chunk-based step with a completion policy. */ + @Suppress("DEPRECATION") + @Deprecated( + message = "Spring Batch 6.0 deprecates this.", + ) fun chunk( - repeatOperations: RepeatOperations, + completionPolicy: CompletionPolicy, transactionManager: PlatformTransactionManager, simpleStepInit: SimpleStepBuilderDsl.() -> Unit, ): Step { - val simpleStepBuilder = SimpleStepBuilder(this.stepBuilder).apply { - transactionManager(transactionManager) - chunkOperations(repeatOperations) - } - return SimpleStepBuilderDsl(this.dslContext, simpleStepBuilder).apply(simpleStepInit) + val simpleStepBuilder = this.stepBuilder.chunk(completionPolicy, transactionManager) + return SimpleStepBuilderDsl(this.dslContext, simpleStepBuilder) + .apply(simpleStepInit) .build() } @@ -306,22 +217,24 @@ class StepBuilderDsl internal constructor( * Set partition step. */ fun partitioner(partitionStepInit: PartitionStepBuilderDsl.() -> Unit): Step { - val partitionStepBuilder = PartitionStepBuilder(this.stepBuilder) - return PartitionStepBuilderDsl(this.dslContext, partitionStepBuilder).apply(partitionStepInit) + val partitionStepBuilder = BatchBuilderBridge.toPartitionStepBuilder(this.stepBuilder) + return PartitionStepBuilderDsl(this.dslContext, partitionStepBuilder) + .apply(partitionStepInit) .build() } /** * Set job step by bean name. */ - fun jobBean(name: String): Step { - return jobBean(name) {} - } + fun jobBean(name: String): Step = jobBean(name) {} /** * Set job step by bean name. */ - fun jobBean(name: String, jobStepInit: JobStepBuilderDsl.() -> Unit): Step { + fun jobBean( + name: String, + jobStepInit: JobStepBuilderDsl.() -> Unit, + ): Step { val job = this.dslContext.beanFactory.getBean(name) return job(job, jobStepInit) } @@ -329,16 +242,18 @@ class StepBuilderDsl internal constructor( /** * Set job step. */ - fun job(job: Job): Step { - return job(job) {} - } + fun job(job: Job): Step = job(job) {} /** * Set job step. */ - fun job(job: Job, jobStepInit: JobStepBuilderDsl.() -> Unit): Step { + fun job( + job: Job, + jobStepInit: JobStepBuilderDsl.() -> Unit, + ): Step { val jobStepBuilder = this.stepBuilder.job(job) - return JobStepBuilderDsl(this.dslContext, jobStepBuilder).apply(jobStepInit) + return JobStepBuilderDsl(this.dslContext, jobStepBuilder) + .apply(jobStepInit) .build() } @@ -353,10 +268,15 @@ class StepBuilderDsl internal constructor( /** * Set flow step. */ - fun flow(name: String, flowInit: FlowBuilderDsl.() -> Unit): Step { + fun flow( + name: String, + flowInit: FlowBuilderDsl.() -> Unit, + ): Step { val flowBuilder = FlowBuilder(name) - val flow = ConcreteFlowBuilderDsl(this.dslContext, flowBuilder).apply(flowInit) - .build() + val flow = + ConcreteFlowBuilderDsl(this.dslContext, flowBuilder) + .apply(flowInit) + .build() return flow(flow) } diff --git a/spring-batch-plus-kotlin/src/main/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/StepTransitionBuilderDsl.kt b/spring-batch-plus-kotlin/src/main/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/StepTransitionBuilderDsl.kt index 24d9f8c4..187a857d 100644 --- a/spring-batch-plus-kotlin/src/main/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/StepTransitionBuilderDsl.kt +++ b/spring-batch-plus-kotlin/src/main/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/StepTransitionBuilderDsl.kt @@ -20,11 +20,12 @@ package com.navercorp.spring.batch.plus.kotlin.configuration import com.navercorp.spring.batch.plus.kotlin.configuration.support.BatchDslMarker import com.navercorp.spring.batch.plus.kotlin.configuration.support.DslContext -import org.springframework.batch.core.Step import org.springframework.batch.core.job.builder.FlowBuilder +import org.springframework.batch.core.step.Step /** - * A dsl for step transition. + * Collects transition clauses that start from a single step. + * The first clause continues from the incoming builder; additional clauses branch from the same step. * * @since 0.1.0 */ @@ -42,23 +43,29 @@ class StepTransitionBuilderDsl internal constructor( * * @see [org.springframework.batch.core.job.builder.FlowBuilder.on] */ - fun on(pattern: String, init: TransitionBuilderDsl.() -> Unit) { + fun on( + pattern: String, + init: TransitionBuilderDsl.() -> Unit, + ) { val flowBuilder = this.flowBuilder - val transitionBuilder = if (flowBuilder == null) { - this.baseFlowBuilder.on(pattern) - } else { - flowBuilder.from(this.step) - .on(pattern) - } + val transitionBuilder = + if (flowBuilder == null) { + this.baseFlowBuilder.on(pattern) + } else { + flowBuilder + .from(this.step) + .on(pattern) + } - this.flowBuilder = TransitionBuilderDsl(this.dslContext, transitionBuilder).apply(init) - .build() + this.flowBuilder = + TransitionBuilderDsl(this.dslContext, transitionBuilder) + .apply(init) + .build() } - internal fun build(): FlowBuilder { - return checkNotNull(this.flowBuilder) { + internal fun build(): FlowBuilder = + checkNotNull(this.flowBuilder) { "should set transition for step ${step.name}." } - } } diff --git a/spring-batch-plus-kotlin/src/main/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/TransitionBuilderDsl.kt b/spring-batch-plus-kotlin/src/main/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/TransitionBuilderDsl.kt index 1ae5286a..417abbb8 100644 --- a/spring-batch-plus-kotlin/src/main/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/TransitionBuilderDsl.kt +++ b/spring-batch-plus-kotlin/src/main/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/TransitionBuilderDsl.kt @@ -20,15 +20,16 @@ package com.navercorp.spring.batch.plus.kotlin.configuration import com.navercorp.spring.batch.plus.kotlin.configuration.support.BatchDslMarker import com.navercorp.spring.batch.plus.kotlin.configuration.support.DslContext -import org.springframework.batch.core.Step import org.springframework.batch.core.job.builder.FlowBuilder import org.springframework.batch.core.job.flow.Flow import org.springframework.batch.core.job.flow.JobExecutionDecider +import org.springframework.batch.core.step.Step import org.springframework.batch.core.step.builder.StepBuilder import org.springframework.beans.factory.getBean /** - * A dsl for [FlowBuilder.TransitionBuilder][org.springframework.batch.core.job.builder.FlowBuilder.TransitionBuilder]. + * Target DSL for a single transition pattern. + * A target step, flow, decider, or terminal action must be selected before build. * * @since 0.1.0 */ @@ -50,7 +51,10 @@ class TransitionBuilderDsl internal constructor( /** * Transition to step. */ - fun step(name: String, stepInit: StepBuilderDsl.() -> Step) { + fun step( + name: String, + stepInit: StepBuilderDsl.() -> Step, + ) { val stepBuilder = StepBuilder(name, this.dslContext.jobRepository) val step = StepBuilderDsl(this.dslContext, stepBuilder).let(stepInit) step(step) @@ -60,14 +64,19 @@ class TransitionBuilderDsl internal constructor( * Transition to step. */ fun step(step: Step) { - this.flowBuilder = this.baseTransitionBuilder.to(step) - .from(step) + this.flowBuilder = + this.baseTransitionBuilder + .to(step) + .from(step) } /** * Transition to step by bean name and set another transition. */ - fun stepBean(name: String, stepTransitionInit: StepTransitionBuilderDsl.() -> Unit) { + fun stepBean( + name: String, + stepTransitionInit: StepTransitionBuilderDsl.() -> Unit, + ) { val step = this.dslContext.beanFactory.getBean(name) step(step, stepTransitionInit) } @@ -88,11 +97,15 @@ class TransitionBuilderDsl internal constructor( /** * Transition to step and set another transition. */ - fun step(step: Step, stepTransitionInit: StepTransitionBuilderDsl.() -> Unit) { + fun step( + step: Step, + stepTransitionInit: StepTransitionBuilderDsl.() -> Unit, + ) { val baseFlowBuilder = this.baseTransitionBuilder.to(step).from(step) - this.flowBuilder = StepTransitionBuilderDsl(this.dslContext, step, baseFlowBuilder) - .apply(stepTransitionInit) - .build() + this.flowBuilder = + StepTransitionBuilderDsl(this.dslContext, step, baseFlowBuilder) + .apply(stepTransitionInit) + .build() } /** @@ -106,10 +119,15 @@ class TransitionBuilderDsl internal constructor( /** * Transition to flow. */ - fun flow(name: String, flowInit: FlowBuilderDsl.() -> Unit) { + fun flow( + name: String, + flowInit: FlowBuilderDsl.() -> Unit, + ) { val flowBuilder = FlowBuilder(name) - val flow = ConcreteFlowBuilderDsl(this.dslContext, flowBuilder).apply(flowInit) - .build() + val flow = + ConcreteFlowBuilderDsl(this.dslContext, flowBuilder) + .apply(flowInit) + .build() flow(flow) } @@ -117,14 +135,19 @@ class TransitionBuilderDsl internal constructor( * Transition to flow. */ fun flow(flow: Flow) { - this.flowBuilder = this.baseTransitionBuilder.to(flow) - .from(flow) + this.flowBuilder = + this.baseTransitionBuilder + .to(flow) + .from(flow) } /** * Transition to flow by bean name and set another transition. */ - fun flowBean(name: String, flowTransitionInit: FlowTransitionBuilderDsl.() -> Unit) { + fun flowBean( + name: String, + flowTransitionInit: FlowTransitionBuilderDsl.() -> Unit, + ) { val flow = this.dslContext.beanFactory.getBean(name) flow(flow, flowTransitionInit) } @@ -138,20 +161,28 @@ class TransitionBuilderDsl internal constructor( flowTransitionInit: FlowTransitionBuilderDsl.() -> Unit, ) { val flowBuilder = FlowBuilder(name) - val flow = ConcreteFlowBuilderDsl(this.dslContext, flowBuilder).apply(flowInit) - .build() + val flow = + ConcreteFlowBuilderDsl(this.dslContext, flowBuilder) + .apply(flowInit) + .build() flow(flow, flowTransitionInit) } /** * Transition to flow and set another transition. */ - fun flow(flow: Flow, flowTransitionInit: FlowTransitionBuilderDsl.() -> Unit) { - val baseFlowBuilder = this.baseTransitionBuilder.to(flow) - .from(flow) - this.flowBuilder = FlowTransitionBuilderDsl(this.dslContext, flow, baseFlowBuilder) - .apply(flowTransitionInit) - .build() + fun flow( + flow: Flow, + flowTransitionInit: FlowTransitionBuilderDsl.() -> Unit, + ) { + val baseFlowBuilder = + this.baseTransitionBuilder + .to(flow) + .from(flow) + this.flowBuilder = + FlowTransitionBuilderDsl(this.dslContext, flow, baseFlowBuilder) + .apply(flowTransitionInit) + .build() } /** @@ -172,15 +203,17 @@ class TransitionBuilderDsl internal constructor( decider: JobExecutionDecider, deciderTransitionInit: DeciderTransitionBuilderDsl.() -> Unit, ) { - val baseUnterminatedFlowBuilder = this.baseTransitionBuilder.to(decider) - .from(decider) - this.flowBuilder = DeciderTransitionBuilderDsl( - this.dslContext, - decider, - baseUnterminatedFlowBuilder, - ) - .apply(deciderTransitionInit) - .build() + val baseUnterminatedFlowBuilder = + this.baseTransitionBuilder + .to(decider) + .from(decider) + this.flowBuilder = + DeciderTransitionBuilderDsl( + this.dslContext, + decider, + baseUnterminatedFlowBuilder, + ).apply(deciderTransitionInit) + .build() } /** @@ -201,10 +234,15 @@ class TransitionBuilderDsl internal constructor( /** * Transition to stop and restart with flow if the flow is restarted. */ - fun stopAndRestartToFlow(name: String, flowInit: FlowBuilderDsl.() -> Unit) { + fun stopAndRestartToFlow( + name: String, + flowInit: FlowBuilderDsl.() -> Unit, + ) { val flowBuilder = FlowBuilder(name) - val flow = ConcreteFlowBuilderDsl(this.dslContext, flowBuilder).apply(flowInit) - .build() + val flow = + ConcreteFlowBuilderDsl(this.dslContext, flowBuilder) + .apply(flowInit) + .build() stopAndRestartToFlow(flow) } @@ -235,21 +273,29 @@ class TransitionBuilderDsl internal constructor( flowTransitionInit: FlowTransitionBuilderDsl.() -> Unit, ) { val flowBuilder = FlowBuilder(name) - val flow = ConcreteFlowBuilderDsl(this.dslContext, flowBuilder).apply(flowInit) - .build() + val flow = + ConcreteFlowBuilderDsl(this.dslContext, flowBuilder) + .apply(flowInit) + .build() stopAndRestartToFlow(flow, flowTransitionInit) } /** * Transition to stop and restart with flow if the flow is restarted. */ - fun stopAndRestartToFlow(flow: Flow, flowTransitionInit: FlowTransitionBuilderDsl.() -> Unit) { - val baseFlowBuilder = this.baseTransitionBuilder.stopAndRestart(flow) - .from(flow) + fun stopAndRestartToFlow( + flow: Flow, + flowTransitionInit: FlowTransitionBuilderDsl.() -> Unit, + ) { + val baseFlowBuilder = + this.baseTransitionBuilder + .stopAndRestart(flow) + .from(flow) - this.flowBuilder = FlowTransitionBuilderDsl(this.dslContext, flow, baseFlowBuilder) - .apply(flowTransitionInit) - .build() + this.flowBuilder = + FlowTransitionBuilderDsl(this.dslContext, flow, baseFlowBuilder) + .apply(flowTransitionInit) + .build() } /** @@ -271,9 +317,10 @@ class TransitionBuilderDsl internal constructor( deciderTransitionInit: DeciderTransitionBuilderDsl.() -> Unit, ) { val baseFlowBuilder = this.baseTransitionBuilder.stopAndRestart(decider).from(decider) - this.flowBuilder = DeciderTransitionBuilderDsl(this.dslContext, decider, baseFlowBuilder) - .apply(deciderTransitionInit) - .build() + this.flowBuilder = + DeciderTransitionBuilderDsl(this.dslContext, decider, baseFlowBuilder) + .apply(deciderTransitionInit) + .build() } /** @@ -287,7 +334,10 @@ class TransitionBuilderDsl internal constructor( /** * Transition to stop and restart with step if the flow is restarted. */ - fun stopAndRestartToStep(name: String, stepInit: StepBuilderDsl.() -> Step) { + fun stopAndRestartToStep( + name: String, + stepInit: StepBuilderDsl.() -> Step, + ) { val stepBuilder = StepBuilder(name, this.dslContext.jobRepository) val step = StepBuilderDsl(this.dslContext, stepBuilder).let(stepInit) stopAndRestartToStep(step) @@ -327,13 +377,19 @@ class TransitionBuilderDsl internal constructor( /** * Transition to stop and restart with step if the flow is restarted. */ - fun stopAndRestartToStep(step: Step, stepTransitionInit: StepTransitionBuilderDsl.() -> Unit) { - val baseFlowBuilder = this.baseTransitionBuilder.stopAndRestart(step) - .from(step) + fun stopAndRestartToStep( + step: Step, + stepTransitionInit: StepTransitionBuilderDsl.() -> Unit, + ) { + val baseFlowBuilder = + this.baseTransitionBuilder + .stopAndRestart(step) + .from(step) - this.flowBuilder = StepTransitionBuilderDsl(this.dslContext, step, baseFlowBuilder) - .apply(stepTransitionInit) - .build() + this.flowBuilder = + StepTransitionBuilderDsl(this.dslContext, step, baseFlowBuilder) + .apply(stepTransitionInit) + .build() } /** @@ -357,9 +413,8 @@ class TransitionBuilderDsl internal constructor( this.flowBuilder = this.baseTransitionBuilder.fail() } - internal fun build(): FlowBuilder { - return checkNotNull(this.flowBuilder) { + internal fun build(): FlowBuilder = + checkNotNull(this.flowBuilder) { "should set transition." } - } } diff --git a/spring-batch-plus-kotlin/src/main/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/step/ChunkOrientedStepBuilderDsl.kt b/spring-batch-plus-kotlin/src/main/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/step/ChunkOrientedStepBuilderDsl.kt new file mode 100644 index 00000000..ff3791a9 --- /dev/null +++ b/spring-batch-plus-kotlin/src/main/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/step/ChunkOrientedStepBuilderDsl.kt @@ -0,0 +1,274 @@ +/* + * Spring Batch Plus + * + * Copyright 2022-present NAVER Corp. + * + * 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 + * + * http://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 com.navercorp.spring.batch.plus.kotlin.configuration.step + +import com.navercorp.spring.batch.plus.kotlin.configuration.support.BatchDslMarker +import com.navercorp.spring.batch.plus.kotlin.configuration.support.DslContext +import com.navercorp.spring.batch.plus.kotlin.configuration.support.LazyConfigurer +import io.micrometer.observation.ObservationRegistry +import org.springframework.batch.core.listener.SkipListener +import org.springframework.batch.core.listener.StepListener +import org.springframework.batch.core.step.Step +import org.springframework.batch.core.step.StepInterruptionPolicy +import org.springframework.batch.core.step.builder.ChunkOrientedStepBuilder +import org.springframework.batch.core.step.skip.SkipPolicy +import org.springframework.batch.infrastructure.item.ItemProcessor +import org.springframework.batch.infrastructure.item.ItemReader +import org.springframework.batch.infrastructure.item.ItemStream +import org.springframework.batch.infrastructure.item.ItemWriter +import org.springframework.core.retry.RetryListener +import org.springframework.core.retry.RetryPolicy +import org.springframework.core.task.AsyncTaskExecutor +import org.springframework.transaction.PlatformTransactionManager +import org.springframework.transaction.interceptor.TransactionAttribute +import kotlin.reflect.KClass + +/** + * A dsl for [ChunkOrientedStepBuilder][org.springframework.batch.core.step.builder.ChunkOrientedStepBuilder]. + * + * Common step settings stay on + * [StepBuilderDsl][com.navercorp.spring.batch.plus.kotlin.configuration.StepBuilderDsl]. + * [observationRegistry] stays here because `ChunkOrientedStepBuilder` redefines it. + * + * @since 2.0.0 + */ +@BatchDslMarker +class ChunkOrientedStepBuilderDsl internal constructor( + @Suppress("unused") + private val dslContext: DslContext, + private val chunkOrientedStepBuilder: ChunkOrientedStepBuilder, +) { + private val lazyConfigurer = LazyConfigurer>() + + /** + * Set for [ChunkOrientedStepBuilder.reader][org.springframework.batch.core.step.builder.ChunkOrientedStepBuilder.reader]. + */ + fun reader(reader: ItemReader) { + this.lazyConfigurer.add { + it.reader(reader) + } + } + + /** + * Set for [ChunkOrientedStepBuilder.processor][org.springframework.batch.core.step.builder.ChunkOrientedStepBuilder.processor]. + */ + fun processor(processor: ItemProcessor) { + this.lazyConfigurer.add { + it.processor(processor) + } + } + + /** + * Set for [ChunkOrientedStepBuilder.writer][org.springframework.batch.core.step.builder.ChunkOrientedStepBuilder.writer]. + */ + fun writer(writer: ItemWriter) { + this.lazyConfigurer.add { + it.writer(writer) + } + } + + /** + * Set for [ChunkOrientedStepBuilder.transactionManager][org.springframework.batch.core.step.builder.ChunkOrientedStepBuilder.transactionManager]. + */ + fun transactionManager(transactionManager: PlatformTransactionManager) { + this.lazyConfigurer.add { + it.transactionManager(transactionManager) + } + } + + /** + * Set for [ChunkOrientedStepBuilder.transactionAttribute][org.springframework.batch.core.step.builder.ChunkOrientedStepBuilder.transactionAttribute]. + */ + fun transactionAttribute(transactionAttribute: TransactionAttribute) { + this.lazyConfigurer.add { + it.transactionAttribute(transactionAttribute) + } + } + + /** + * Set for [ChunkOrientedStepBuilder.stream][org.springframework.batch.core.step.builder.ChunkOrientedStepBuilder.stream]. + */ + fun stream(stream: ItemStream) { + this.lazyConfigurer.add { + it.stream(stream) + } + } + + /** + * Set for [ChunkOrientedStepBuilder.listener][org.springframework.batch.core.step.builder.ChunkOrientedStepBuilder.listener]. + */ + fun listener(listener: StepListener) { + this.lazyConfigurer.add { + it.listener(listener) + } + } + + /** + * Set listener processing followings. + * + * - [org.springframework.batch.core.annotation.BeforeStep] + * - [org.springframework.batch.core.annotation.AfterStep] + * - [org.springframework.batch.core.annotation.BeforeChunk] + * - [org.springframework.batch.core.annotation.AfterChunk] + * - [org.springframework.batch.core.annotation.OnChunkError] + * - [org.springframework.batch.core.annotation.BeforeRead] + * - [org.springframework.batch.core.annotation.AfterRead] + * - [org.springframework.batch.core.annotation.OnReadError] + * - [org.springframework.batch.core.annotation.BeforeProcess] + * - [org.springframework.batch.core.annotation.AfterProcess] + * - [org.springframework.batch.core.annotation.OnProcessError] + * - [org.springframework.batch.core.annotation.BeforeWrite] + * - [org.springframework.batch.core.annotation.AfterWrite] + * - [org.springframework.batch.core.annotation.OnWriteError] + */ + fun listener(listener: Any) { + this.lazyConfigurer.add { + it.listener(listener) + } + } + + /** + * Set for [ChunkOrientedStepBuilder.interruptionPolicy][org.springframework.batch.core.step.builder.ChunkOrientedStepBuilder.interruptionPolicy]. + */ + fun interruptionPolicy(interruptionPolicy: StepInterruptionPolicy) { + this.lazyConfigurer.add { + it.interruptionPolicy(interruptionPolicy) + } + } + + /** + * Set for [ChunkOrientedStepBuilder.faultTolerant][org.springframework.batch.core.step.builder.ChunkOrientedStepBuilder.faultTolerant]. + * + * Must be called before any retry/skip configuration takes effect. + */ + fun faultTolerant() { + this.lazyConfigurer.add { + it.faultTolerant() + } + } + + /** + * Set for [ChunkOrientedStepBuilder.retryPolicy][org.springframework.batch.core.step.builder.ChunkOrientedStepBuilder.retryPolicy]. + */ + fun retryPolicy(policy: RetryPolicy) { + this.lazyConfigurer.add { + it.retryPolicy(policy) + } + } + + /** + * Set for [ChunkOrientedStepBuilder.retryListener][org.springframework.batch.core.step.builder.ChunkOrientedStepBuilder.retryListener]. + */ + fun retryListener(listener: RetryListener) { + this.lazyConfigurer.add { + it.retryListener(listener) + } + } + + /** + * Set for [ChunkOrientedStepBuilder.retry][org.springframework.batch.core.step.builder.ChunkOrientedStepBuilder.retry]. + */ + inline fun retry() { + retry(T::class) + } + + /** + * Set for [ChunkOrientedStepBuilder.retry][org.springframework.batch.core.step.builder.ChunkOrientedStepBuilder.retry]. + */ + fun retry(exceptionClass: KClass) { + this.lazyConfigurer.add { + it.retry(exceptionClass.java) + } + } + + /** + * Set for [ChunkOrientedStepBuilder.retryLimit][org.springframework.batch.core.step.builder.ChunkOrientedStepBuilder.retryLimit]. + */ + fun retryLimit(retryLimit: Long) { + this.lazyConfigurer.add { + it.retryLimit(retryLimit) + } + } + + /** + * Set for [ChunkOrientedStepBuilder.skipPolicy][org.springframework.batch.core.step.builder.ChunkOrientedStepBuilder.skipPolicy]. + */ + fun skipPolicy(skipPolicy: SkipPolicy) { + this.lazyConfigurer.add { + it.skipPolicy(skipPolicy) + } + } + + /** + * Set for [ChunkOrientedStepBuilder.skipListener][org.springframework.batch.core.step.builder.ChunkOrientedStepBuilder.skipListener]. + */ + fun skipListener(skipListener: SkipListener) { + this.lazyConfigurer.add { + it.skipListener(skipListener) + } + } + + /** + * Set for [ChunkOrientedStepBuilder.skip][org.springframework.batch.core.step.builder.ChunkOrientedStepBuilder.skip]. + */ + inline fun skip() { + skip(T::class) + } + + /** + * Set for [ChunkOrientedStepBuilder.skip][org.springframework.batch.core.step.builder.ChunkOrientedStepBuilder.skip]. + */ + fun skip(exceptionClass: KClass) { + this.lazyConfigurer.add { + it.skip(exceptionClass.java) + } + } + + /** + * Set for [ChunkOrientedStepBuilder.skipLimit][org.springframework.batch.core.step.builder.ChunkOrientedStepBuilder.skipLimit]. + */ + fun skipLimit(skipLimit: Long) { + this.lazyConfigurer.add { + it.skipLimit(skipLimit) + } + } + + /** + * Set for [ChunkOrientedStepBuilder.taskExecutor][org.springframework.batch.core.step.builder.ChunkOrientedStepBuilder.taskExecutor]. + */ + fun taskExecutor(asyncTaskExecutor: AsyncTaskExecutor) { + this.lazyConfigurer.add { + it.taskExecutor(asyncTaskExecutor) + } + } + + /** + * Set for [ChunkOrientedStepBuilder.observationRegistry][org.springframework.batch.core.step.builder.ChunkOrientedStepBuilder.observationRegistry]. + */ + fun observationRegistry(observationRegistry: ObservationRegistry) { + this.lazyConfigurer.add { + it.observationRegistry(observationRegistry) + } + } + + internal fun build(): Step = + this.chunkOrientedStepBuilder + .apply(this.lazyConfigurer) + .build() +} diff --git a/spring-batch-plus-kotlin/src/main/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/step/FlowStepBuilderDsl.kt b/spring-batch-plus-kotlin/src/main/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/step/FlowStepBuilderDsl.kt index 73e23c9a..ab673793 100644 --- a/spring-batch-plus-kotlin/src/main/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/step/FlowStepBuilderDsl.kt +++ b/spring-batch-plus-kotlin/src/main/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/step/FlowStepBuilderDsl.kt @@ -21,12 +21,15 @@ package com.navercorp.spring.batch.plus.kotlin.configuration.step import com.navercorp.spring.batch.plus.kotlin.configuration.support.BatchDslMarker import com.navercorp.spring.batch.plus.kotlin.configuration.support.DslContext import com.navercorp.spring.batch.plus.kotlin.configuration.support.LazyConfigurer -import org.springframework.batch.core.Step +import org.springframework.batch.core.step.Step import org.springframework.batch.core.step.builder.FlowStepBuilder /** * A dsl for [FlowStepBuilder][org.springframework.batch.core.step.builder.FlowStepBuilder]. * + * Common step settings stay on + * [StepBuilderDsl][com.navercorp.spring.batch.plus.kotlin.configuration.StepBuilderDsl]. + * * @since 0.1.0 */ @BatchDslMarker @@ -37,8 +40,8 @@ class FlowStepBuilderDsl internal constructor( ) { private val lazyConfigurer = LazyConfigurer() - internal fun build(): Step { - return this.flowStepBuilder.apply(this.lazyConfigurer) + internal fun build(): Step = + this.flowStepBuilder + .apply(this.lazyConfigurer) .build() - } } diff --git a/spring-batch-plus-kotlin/src/main/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/step/JobStepBuilderDsl.kt b/spring-batch-plus-kotlin/src/main/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/step/JobStepBuilderDsl.kt index c89bddbc..11e531b5 100644 --- a/spring-batch-plus-kotlin/src/main/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/step/JobStepBuilderDsl.kt +++ b/spring-batch-plus-kotlin/src/main/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/step/JobStepBuilderDsl.kt @@ -21,14 +21,17 @@ package com.navercorp.spring.batch.plus.kotlin.configuration.step import com.navercorp.spring.batch.plus.kotlin.configuration.support.BatchDslMarker import com.navercorp.spring.batch.plus.kotlin.configuration.support.DslContext import com.navercorp.spring.batch.plus.kotlin.configuration.support.LazyConfigurer -import org.springframework.batch.core.Step -import org.springframework.batch.core.launch.JobLauncher +import org.springframework.batch.core.launch.JobOperator +import org.springframework.batch.core.step.Step import org.springframework.batch.core.step.builder.JobStepBuilder import org.springframework.batch.core.step.job.JobParametersExtractor /** * A dsl for [JobStepBuilder][org.springframework.batch.core.step.builder.JobStepBuilder]. * + * Common step settings stay on + * [StepBuilderDsl][com.navercorp.spring.batch.plus.kotlin.configuration.StepBuilderDsl]. + * * @since 0.1.0 */ @BatchDslMarker @@ -40,11 +43,11 @@ class JobStepBuilderDsl internal constructor( private val lazyConfigurer = LazyConfigurer() /** - * Set for [JobStepBuilder.jobLauncher][org.springframework.batch.core.step.builder.JobStepBuilder.jobLauncher]. + * Set for [JobStepBuilder.operator][org.springframework.batch.core.step.builder.JobStepBuilder.operator]. */ - fun launcher(jobLauncher: JobLauncher) { + fun operator(jobOperator: JobOperator) { this.lazyConfigurer.add { - it.launcher(jobLauncher) + it.operator(jobOperator) } } @@ -57,8 +60,8 @@ class JobStepBuilderDsl internal constructor( } } - internal fun build(): Step { - return this.jobStepBuilder.apply(this.lazyConfigurer) + internal fun build(): Step = + this.jobStepBuilder + .apply(this.lazyConfigurer) .build() - } } diff --git a/spring-batch-plus-kotlin/src/main/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/step/PartitionStepBuilderDsl.kt b/spring-batch-plus-kotlin/src/main/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/step/PartitionStepBuilderDsl.kt index 310fee80..53927b12 100644 --- a/spring-batch-plus-kotlin/src/main/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/step/PartitionStepBuilderDsl.kt +++ b/spring-batch-plus-kotlin/src/main/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/step/PartitionStepBuilderDsl.kt @@ -22,17 +22,20 @@ import com.navercorp.spring.batch.plus.kotlin.configuration.support.BatchDslMark import com.navercorp.spring.batch.plus.kotlin.configuration.support.Configurer import com.navercorp.spring.batch.plus.kotlin.configuration.support.DslContext import com.navercorp.spring.batch.plus.kotlin.configuration.support.LazyConfigurer -import org.springframework.batch.core.Step import org.springframework.batch.core.partition.PartitionHandler +import org.springframework.batch.core.partition.Partitioner +import org.springframework.batch.core.partition.StepExecutionAggregator import org.springframework.batch.core.partition.StepExecutionSplitter -import org.springframework.batch.core.partition.support.Partitioner -import org.springframework.batch.core.partition.support.StepExecutionAggregator +import org.springframework.batch.core.step.Step import org.springframework.batch.core.step.builder.PartitionStepBuilder import org.springframework.core.task.TaskExecutor /** * A dsl for [PartitionStepBuilder][org.springframework.batch.core.step.builder.PartitionStepBuilder]. * + * Common step settings stay on + * [StepBuilderDsl][com.navercorp.spring.batch.plus.kotlin.configuration.StepBuilderDsl]. + * * @since 0.1.0 */ @BatchDslMarker @@ -56,13 +59,14 @@ class PartitionStepBuilderDsl internal constructor( } /** - * Build [TaskExecutorPartitionHandler][org.springframework.batch.core.partition.support.TaskExecutorPartitionHandler] - * for [PartitionHandler][org.springframework.batch.core.partition.PartitionHandler]. + * Build the default [TaskExecutorPartitionHandler][org.springframework.batch.core.partition.support.TaskExecutorPartitionHandler] + * via [TaskExecutorPartitionHandlerBuilderDsl]. See class KDoc for the scoping rationale. */ fun partitionHandler(init: TaskExecutorPartitionHandlerBuilderDsl.() -> Unit) { - val taskExecutorPartitionHandlerConfigurers = TaskExecutorPartitionHandlerBuilderDsl(this.dslContext) - .apply(init) - .build() + val taskExecutorPartitionHandlerConfigurers = + TaskExecutorPartitionHandlerBuilderDsl(this.dslContext) + .apply(init) + .build() this.lazyConfigurer.add(taskExecutorPartitionHandlerConfigurers) this.partitionHandlerSet = true } @@ -78,12 +82,15 @@ class PartitionStepBuilderDsl internal constructor( } /** - * Build [SimpleStepExecutionSplitter][org.springframework.batch.core.partition.support.SimpleStepExecutionSplitter] - * for [StepExecutionSplitter][org.springframework.batch.core.partition.StepExecutionSplitter]. - * - * @see [PartitionStepBuilder.partitioner][org.springframework.batch.core.step.builder.PartitionStepBuilder.partitioner] + * Build a [SimpleStepExecutionSplitter][org.springframework.batch.core.partition.support.SimpleStepExecutionSplitter] + * from a worker step name and [Partitioner]. Maps to + * [PartitionStepBuilder.partitioner][org.springframework.batch.core.step.builder.PartitionStepBuilder.partitioner], + * which internally constructs the splitter and sets it. */ - fun splitter(stepName: String, partitioner: Partitioner) { + fun splitter( + stepName: String, + partitioner: Partitioner, + ) { this.lazyConfigurer.add { it.partitioner(stepName, partitioner) } @@ -108,12 +115,14 @@ class PartitionStepBuilderDsl internal constructor( "splitter is not set." } - return this.partitionStepBuilder.apply(this.lazyConfigurer) + return this.partitionStepBuilder + .apply(this.lazyConfigurer) .build() } /** - * A dsl for building [TaskExecutorPartitionHandler][org.springframework.batch.core.partition.support.TaskExecutorPartitionHandler]. + * A dsl for building the default [TaskExecutorPartitionHandler][org.springframework.batch.core.partition.support.TaskExecutorPartitionHandler]. + * See [PartitionStepBuilderDsl] KDoc for the scoping rationale. * * @since 0.1.0 */ diff --git a/spring-batch-plus-kotlin/src/main/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/step/SimpleStepBuilderDsl.kt b/spring-batch-plus-kotlin/src/main/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/step/SimpleStepBuilderDsl.kt index 1d14fc70..707a1880 100644 --- a/spring-batch-plus-kotlin/src/main/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/step/SimpleStepBuilderDsl.kt +++ b/spring-batch-plus-kotlin/src/main/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/step/SimpleStepBuilderDsl.kt @@ -16,28 +16,30 @@ * limitations under the License. */ +@file:Suppress("DEPRECATION") + package com.navercorp.spring.batch.plus.kotlin.configuration.step import com.navercorp.spring.batch.plus.kotlin.configuration.support.BatchDslMarker import com.navercorp.spring.batch.plus.kotlin.configuration.support.Configurer import com.navercorp.spring.batch.plus.kotlin.configuration.support.DslContext import com.navercorp.spring.batch.plus.kotlin.configuration.support.LazyConfigurer -import org.springframework.batch.core.ChunkListener -import org.springframework.batch.core.ItemProcessListener -import org.springframework.batch.core.ItemReadListener -import org.springframework.batch.core.ItemWriteListener -import org.springframework.batch.core.SkipListener -import org.springframework.batch.core.Step +import org.springframework.batch.core.listener.ChunkListener +import org.springframework.batch.core.listener.ItemProcessListener +import org.springframework.batch.core.listener.ItemReadListener +import org.springframework.batch.core.listener.ItemWriteListener +import org.springframework.batch.core.listener.SkipListener +import org.springframework.batch.core.step.Step import org.springframework.batch.core.step.builder.FaultTolerantStepBuilder import org.springframework.batch.core.step.builder.SimpleStepBuilder import org.springframework.batch.core.step.item.KeyGenerator import org.springframework.batch.core.step.skip.SkipPolicy -import org.springframework.batch.item.ItemProcessor -import org.springframework.batch.item.ItemReader -import org.springframework.batch.item.ItemStream -import org.springframework.batch.item.ItemWriter -import org.springframework.batch.repeat.RepeatOperations -import org.springframework.batch.repeat.exception.ExceptionHandler +import org.springframework.batch.infrastructure.item.ItemProcessor +import org.springframework.batch.infrastructure.item.ItemReader +import org.springframework.batch.infrastructure.item.ItemStream +import org.springframework.batch.infrastructure.item.ItemWriter +import org.springframework.batch.infrastructure.repeat.RepeatOperations +import org.springframework.batch.infrastructure.repeat.exception.ExceptionHandler import org.springframework.core.task.TaskExecutor import org.springframework.retry.RetryListener import org.springframework.retry.RetryPolicy @@ -49,9 +51,15 @@ import kotlin.reflect.KClass /** * A dsl for [SimpleStepBuilder][org.springframework.batch.core.step.builder.SimpleStepBuilder]. * + * Common step settings stay on + * [StepBuilderDsl][com.navercorp.spring.batch.plus.kotlin.configuration.StepBuilderDsl]. + * * @since 0.1.0 */ @BatchDslMarker +@Deprecated( + message = "Spring Batch 6.0 deprecates SimpleStepBuilder, FaultTolerantStepBuilder.", +) class SimpleStepBuilderDsl internal constructor( private val dslContext: DslContext, private val simpleStepBuilder: SimpleStepBuilder, @@ -60,7 +68,6 @@ class SimpleStepBuilderDsl internal constructor( private var faultTolerantStepConfigurer: Configurer>? = null private var taskExecutorSet = false - private var throttleLimitSet = false private var exceptionHandlerSet = false private var stepOperationsSet = false @@ -70,9 +77,10 @@ class SimpleStepBuilderDsl internal constructor( * @see [FaultTolerantStepBuilder][org.springframework.batch.core.step.builder.FaultTolerantStepBuilder]. */ fun faultTolerant(init: FaultTolerantStepBuilderDsl.() -> Unit) { - this.faultTolerantStepConfigurer = FaultTolerantStepBuilderDsl(this.dslContext) - .apply(init) - .build() + this.faultTolerantStepConfigurer = + FaultTolerantStepBuilderDsl(this.dslContext) + .apply(init) + .build() } /** @@ -171,7 +179,7 @@ class SimpleStepBuilderDsl internal constructor( /** * Set for [SimpleStepBuilder.listener][org.springframework.batch.core.step.builder.AbstractTaskletStepBuilder.listener]. */ - fun listener(chunkListener: ChunkListener) { + fun listener(chunkListener: ChunkListener) { this.simpleStepConfigurer.add { it.listener(chunkListener) } @@ -197,22 +205,6 @@ class SimpleStepBuilderDsl internal constructor( this.taskExecutorSet = true } - /** - * Set for [SimpleStepBuilder.throttleLimit][org.springframework.batch.core.step.builder.AbstractTaskletStepBuilder.throttleLimit]. - * If not present, set as default value of [AbstractTaskletStepBuilder][org.springframework.batch.core.step.builder.AbstractTaskletStepBuilder]. - * It can't be used when no [taskExecutor] is set. - */ - @Suppress("DEPRECATION") - @Deprecated( - message = "spring batch 5.0.0 deprecates this", - ) - fun throttleLimit(throttleLimit: Int) { - this.simpleStepConfigurer.add { - it.throttleLimit(throttleLimit) - } - this.throttleLimitSet = true - } - /** * Set for [SimpleStepBuilder.exceptionHandler][org.springframework.batch.core.step.builder.AbstractTaskletStepBuilder.exceptionHandler]. * It can't be used when [stepOperations] is set. @@ -254,21 +246,17 @@ class SimpleStepBuilderDsl internal constructor( } } - if (!this.taskExecutorSet) { - check(!this.throttleLimitSet) { - "throttleLimit is redundant when no taskExecutor is set." - } - } - val faultTolerantStepConfigurer = this.faultTolerantStepConfigurer val simpleStepConfigurer = this.simpleStepConfigurer return if (faultTolerantStepConfigurer != null) { - this.simpleStepBuilder.faultTolerant() + this.simpleStepBuilder + .faultTolerant() .apply(faultTolerantStepConfigurer) .apply(simpleStepConfigurer) .build() } else { - this.simpleStepBuilder.apply(simpleStepConfigurer) + this.simpleStepBuilder + .apply(simpleStepConfigurer) .build() } } @@ -279,6 +267,9 @@ class SimpleStepBuilderDsl internal constructor( * @since 0.1.0 */ @BatchDslMarker + @Deprecated( + message = "Spring Batch 6.0 deprecates FaultTolerantStepBuilder.", + ) class FaultTolerantStepBuilderDsl internal constructor( @Suppress("unused") private val dslContext: DslContext, @@ -457,8 +448,6 @@ class SimpleStepBuilderDsl internal constructor( } } - internal fun build(): Configurer> { - return this.lazyConfigurer - } + internal fun build(): Configurer> = this.lazyConfigurer } } diff --git a/spring-batch-plus-kotlin/src/main/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/step/TaskletStepBuilderDsl.kt b/spring-batch-plus-kotlin/src/main/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/step/TaskletStepBuilderDsl.kt index 3c6d3f8d..bd51aa6f 100644 --- a/spring-batch-plus-kotlin/src/main/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/step/TaskletStepBuilderDsl.kt +++ b/spring-batch-plus-kotlin/src/main/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/step/TaskletStepBuilderDsl.kt @@ -21,18 +21,22 @@ package com.navercorp.spring.batch.plus.kotlin.configuration.step import com.navercorp.spring.batch.plus.kotlin.configuration.support.BatchDslMarker import com.navercorp.spring.batch.plus.kotlin.configuration.support.DslContext import com.navercorp.spring.batch.plus.kotlin.configuration.support.LazyConfigurer -import org.springframework.batch.core.ChunkListener -import org.springframework.batch.core.Step +import org.springframework.batch.core.listener.ChunkListener +import org.springframework.batch.core.step.Step import org.springframework.batch.core.step.builder.TaskletStepBuilder -import org.springframework.batch.item.ItemStream -import org.springframework.batch.repeat.RepeatOperations -import org.springframework.batch.repeat.exception.ExceptionHandler +import org.springframework.batch.infrastructure.item.ItemStream +import org.springframework.batch.infrastructure.repeat.RepeatOperations +import org.springframework.batch.infrastructure.repeat.exception.ExceptionHandler import org.springframework.core.task.TaskExecutor +import org.springframework.transaction.PlatformTransactionManager import org.springframework.transaction.interceptor.TransactionAttribute /** * A dsl for [TaskletStepBuilder][org.springframework.batch.core.step.builder.TaskletStepBuilder]. * + * Common step settings stay on + * [StepBuilderDsl][com.navercorp.spring.batch.plus.kotlin.configuration.StepBuilderDsl]. + * * @since 0.1.0 */ @BatchDslMarker @@ -50,7 +54,7 @@ class TaskletStepBuilderDsl internal constructor( /** * Set for [TaskletStepBuilder.listener][org.springframework.batch.core.step.builder.AbstractTaskletStepBuilder.listener]. */ - fun listener(chunkListener: ChunkListener) { + fun listener(chunkListener: ChunkListener<*, *>) { this.lazyConfigurer.add { it.listener(chunkListener) } @@ -59,6 +63,8 @@ class TaskletStepBuilderDsl internal constructor( /** * Set listener processing followings. * + * - [org.springframework.batch.core.annotation.BeforeStep] + * - [org.springframework.batch.core.annotation.AfterStep] * - [org.springframework.batch.core.annotation.BeforeChunk] * - [org.springframework.batch.core.annotation.AfterChunk] * - [org.springframework.batch.core.annotation.AfterChunkError] @@ -82,6 +88,10 @@ class TaskletStepBuilderDsl internal constructor( * Set for [TaskletStepBuilder.taskExecutor][org.springframework.batch.core.step.builder.AbstractTaskletStepBuilder.taskExecutor]. * It can't be used when [stepOperations] is set. */ + @Suppress("DEPRECATION") + @Deprecated( + message = "Spring Batch 6.0 deprecates this.", + ) fun taskExecutor(taskExecutor: TaskExecutor) { this.lazyConfigurer.add { it.taskExecutor(taskExecutor) @@ -89,8 +99,6 @@ class TaskletStepBuilderDsl internal constructor( this.taskExecutorSet = true } - // Maybe throttleLimit can be here. But throttleLimit is redundant in a tasklet step. - /** * Set for [TaskletStepBuilder.exceptionHandler][org.springframework.batch.core.step.builder.AbstractTaskletStepBuilder.exceptionHandler]. * It can't be used when [stepOperations] is set. @@ -112,6 +120,15 @@ class TaskletStepBuilderDsl internal constructor( this.stepOperationsSet = true } + /** + * Set for [TaskletStepBuilder.transactionManager][org.springframework.batch.core.step.builder.AbstractTaskletStepBuilder.transactionManager]. + */ + fun transactionManager(transactionManager: PlatformTransactionManager) { + this.lazyConfigurer.add { + it.transactionManager(transactionManager) + } + } + /** * Set for [TaskletStepBuilder.transactionAttribute][org.springframework.batch.core.step.builder.AbstractTaskletStepBuilder.transactionAttribute]. */ @@ -132,7 +149,8 @@ class TaskletStepBuilderDsl internal constructor( } } - return this.taskletStepBuilder.apply(this.lazyConfigurer) + return this.taskletStepBuilder + .apply(this.lazyConfigurer) .build() } } diff --git a/spring-batch-plus-kotlin/src/main/kotlin/com/navercorp/spring/batch/plus/kotlin/item/adapter/ItemDelegates.kt b/spring-batch-plus-kotlin/src/main/kotlin/com/navercorp/spring/batch/plus/kotlin/item/adapter/ItemDelegates.kt index aefda05a..024d5087 100644 --- a/spring-batch-plus-kotlin/src/main/kotlin/com/navercorp/spring/batch/plus/kotlin/item/adapter/ItemDelegates.kt +++ b/spring-batch-plus-kotlin/src/main/kotlin/com/navercorp/spring/batch/plus/kotlin/item/adapter/ItemDelegates.kt @@ -24,9 +24,9 @@ import com.navercorp.spring.batch.plus.item.adapter.AdapterFactory import com.navercorp.spring.batch.plus.item.adapter.ItemProcessorDelegate import com.navercorp.spring.batch.plus.item.adapter.ItemStreamReaderDelegate import com.navercorp.spring.batch.plus.item.adapter.ItemStreamWriterDelegate -import org.springframework.batch.item.ItemProcessor -import org.springframework.batch.item.ItemStreamReader -import org.springframework.batch.item.ItemStreamWriter +import org.springframework.batch.infrastructure.item.ItemProcessor +import org.springframework.batch.infrastructure.item.ItemStreamReader +import org.springframework.batch.infrastructure.item.ItemStreamWriter /** * An extensions to invoke [AdapterFactory.itemStreamReader]. @@ -35,8 +35,7 @@ import org.springframework.batch.item.ItemStreamWriter message = "Uses ItemStreamFluxReaderDelegate instead", replaceWith = ReplaceWith(""), ) -fun ItemStreamReaderDelegate.asItemStreamReader(): ItemStreamReader = - AdapterFactory.itemStreamReader(this) +fun ItemStreamReaderDelegate.asItemStreamReader(): ItemStreamReader = AdapterFactory.itemStreamReader(this) /** * An extensions to invoke [AdapterFactory.itemProcessor]. @@ -45,18 +44,17 @@ fun ItemStreamReaderDelegate.asItemStreamReader(): ItemStreamReader message = "Uses com.navercorp.spring.batch.plus.step.adapter.ItemProcessorDelegate instead", replaceWith = ReplaceWith(""), ) -fun ItemProcessorDelegate.asItemProcessor(): ItemProcessor = - AdapterFactory.itemProcessor(this) +fun ItemProcessorDelegate.asItemProcessor(): ItemProcessor = AdapterFactory.itemProcessor(this) /** * An extensions to invoke [AdapterFactory.itemStreamWriter]. */ @Deprecated( message = "Uses com.navercorp.spring.batch.plus.step.adapter.ItemStreamWriterDelegate instead", - replaceWith = ReplaceWith( - "AdapterFactory.itemStreamWriter(this)", - "com.navercorp.spring.batch.plus.step.adapter.AdapterFactory", - ), + replaceWith = + ReplaceWith( + "AdapterFactory.itemStreamWriter(this)", + "com.navercorp.spring.batch.plus.step.adapter.AdapterFactory", + ), ) -fun ItemStreamWriterDelegate.asItemStreamWriter(): ItemStreamWriter = - AdapterFactory.itemStreamWriter(this) +fun ItemStreamWriterDelegate.asItemStreamWriter(): ItemStreamWriter = AdapterFactory.itemStreamWriter(this) diff --git a/spring-batch-plus-kotlin/src/main/kotlin/com/navercorp/spring/batch/plus/kotlin/step/adapter/ItemDelegates.kt b/spring-batch-plus-kotlin/src/main/kotlin/com/navercorp/spring/batch/plus/kotlin/step/adapter/ItemDelegates.kt index d4b4a999..9f6da80c 100644 --- a/spring-batch-plus-kotlin/src/main/kotlin/com/navercorp/spring/batch/plus/kotlin/step/adapter/ItemDelegates.kt +++ b/spring-batch-plus-kotlin/src/main/kotlin/com/navercorp/spring/batch/plus/kotlin/step/adapter/ItemDelegates.kt @@ -25,42 +25,36 @@ import com.navercorp.spring.batch.plus.step.adapter.ItemStreamIterableReaderDele import com.navercorp.spring.batch.plus.step.adapter.ItemStreamIteratorReaderDelegate import com.navercorp.spring.batch.plus.step.adapter.ItemStreamSimpleReaderDelegate import com.navercorp.spring.batch.plus.step.adapter.ItemStreamWriterDelegate -import org.springframework.batch.item.ItemProcessor -import org.springframework.batch.item.ItemStreamReader -import org.springframework.batch.item.ItemStreamWriter +import org.springframework.batch.infrastructure.item.ItemProcessor +import org.springframework.batch.infrastructure.item.ItemStreamReader +import org.springframework.batch.infrastructure.item.ItemStreamWriter /** * An extensions to invoke [AdapterFactory.itemStreamReader]. */ -fun ItemStreamFluxReaderDelegate.asItemStreamReader(): ItemStreamReader = - AdapterFactory.itemStreamReader(this) +fun ItemStreamFluxReaderDelegate.asItemStreamReader(): ItemStreamReader = AdapterFactory.itemStreamReader(this) /** * An extensions to invoke [AdapterFactory.itemStreamReader]. */ -fun ItemStreamIterableReaderDelegate.asItemStreamReader(): ItemStreamReader = - AdapterFactory.itemStreamReader(this) +fun ItemStreamIterableReaderDelegate.asItemStreamReader(): ItemStreamReader = AdapterFactory.itemStreamReader(this) /** * An extensions to invoke [AdapterFactory.itemStreamReader]. */ -fun ItemStreamIteratorReaderDelegate.asItemStreamReader(): ItemStreamReader = - AdapterFactory.itemStreamReader(this) +fun ItemStreamIteratorReaderDelegate.asItemStreamReader(): ItemStreamReader = AdapterFactory.itemStreamReader(this) /** * An extensions to invoke [AdapterFactory.itemStreamReader]. */ -fun ItemStreamSimpleReaderDelegate.asItemStreamReader(): ItemStreamReader = - AdapterFactory.itemStreamReader(this) +fun ItemStreamSimpleReaderDelegate.asItemStreamReader(): ItemStreamReader = AdapterFactory.itemStreamReader(this) /** * An extensions to invoke [AdapterFactory.itemProcessor]. */ -fun ItemProcessorDelegate.asItemProcessor(): ItemProcessor = - AdapterFactory.itemProcessor(this) +fun ItemProcessorDelegate.asItemProcessor(): ItemProcessor = AdapterFactory.itemProcessor(this) /** * An extensions to invoke [AdapterFactory.itemStreamWriter]. */ -fun ItemStreamWriterDelegate.asItemStreamWriter(): ItemStreamWriter = - AdapterFactory.itemStreamWriter(this) +fun ItemStreamWriterDelegate.asItemStreamWriter(): ItemStreamWriter = AdapterFactory.itemStreamWriter(this) diff --git a/spring-batch-plus-kotlin/src/test/java/com/navercorp/spring/batch/plus/kotlin/configuration/step/TestBuilderBridge.java b/spring-batch-plus-kotlin/src/test/java/com/navercorp/spring/batch/plus/kotlin/configuration/step/TestBuilderBridge.java new file mode 100644 index 00000000..aefb4fb2 --- /dev/null +++ b/spring-batch-plus-kotlin/src/test/java/com/navercorp/spring/batch/plus/kotlin/configuration/step/TestBuilderBridge.java @@ -0,0 +1,40 @@ +/* + * Spring Batch Plus + * + * Copyright 2022-present NAVER Corp. + * + * 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 + * + * http://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 com.navercorp.spring.batch.plus.kotlin.configuration.step; + +import org.springframework.batch.core.step.builder.PartitionStepBuilder; +import org.springframework.batch.core.step.builder.SimpleStepBuilder; +import org.springframework.batch.core.step.builder.StepBuilder; + +// Test-only Java bridge for Spring Batch builder constructors whose F-bounded wildcard +// signatures cannot be matched by the Kotlin K2 compiler. See KT-66570. +@SuppressWarnings("deprecation") +final class TestBuilderBridge { + + static SimpleStepBuilder simpleStepBuilder(StepBuilder stepBuilder) { + return new SimpleStepBuilder<>(stepBuilder); + } + + static PartitionStepBuilder partitionStepBuilder(StepBuilder stepBuilder) { + return new PartitionStepBuilder(stepBuilder); + } + + private TestBuilderBridge() { + } +} diff --git a/spring-batch-plus-kotlin/src/test/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/JobBuilderDslHelperTest.kt b/spring-batch-plus-kotlin/src/test/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/JobBuilderDslHelperTest.kt deleted file mode 100644 index df330a14..00000000 --- a/spring-batch-plus-kotlin/src/test/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/JobBuilderDslHelperTest.kt +++ /dev/null @@ -1,212 +0,0 @@ -/* - * Spring Batch Plus - * - * Copyright 2022-present NAVER Corp. - * - * 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 - * - * http://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 com.navercorp.spring.batch.plus.kotlin.configuration - -import com.navercorp.spring.batch.plus.kotlin.configuration.support.DslContext -import io.micrometer.core.instrument.MeterRegistry -import io.micrometer.observation.ObservationRegistry -import io.mockk.mockk -import io.mockk.spyk -import io.mockk.verify -import org.junit.jupiter.api.Test -import org.springframework.batch.core.JobExecutionListener -import org.springframework.batch.core.JobParametersIncrementer -import org.springframework.batch.core.JobParametersValidator -import org.springframework.batch.core.job.builder.JobBuilder -import org.springframework.batch.core.observability.BatchJobObservationConvention -import org.springframework.batch.core.repository.JobRepository -import java.util.UUID - -/** - * org.springframework.batch.core.job.builder.JobBuilderHelper related tests - */ -internal class JobBuilderDslHelperTest { - - @Test - fun testValidator() { - // given - val jobBuilder = spyk(JobBuilder(UUID.randomUUID().toString(), mockk(relaxed = true))) - val jobBuilderDsl = jobBuilderDsl(jobBuilder) - - // when - val jobParametersValidator = mockk() - jobBuilderDsl.apply { - validator(jobParametersValidator) - }.build() - - // then - verify(exactly = 1) { jobBuilder.validator(jobParametersValidator) } - } - - @Test - fun testIncrementer() { - // given - val jobBuilder = spyk(JobBuilder(UUID.randomUUID().toString(), mockk(relaxed = true))) - val jobBuilderDsl = jobBuilderDsl(jobBuilder) - - // when - val jobParametersIncrementer = mockk() - jobBuilderDsl.apply { - incrementer(jobParametersIncrementer) - }.build() - - // then - verify(exactly = 1) { jobBuilder.incrementer(jobParametersIncrementer) } - } - - @Test - fun testObservationConvention() { - // given - val jobBuilder = spyk(JobBuilder(UUID.randomUUID().toString(), mockk(relaxed = true))) - val jobBuilderDsl = jobBuilderDsl(jobBuilder) - - // when - val observationConvention = mockk() - jobBuilderDsl.apply { - observationConvention(observationConvention) - }.build() - - // then - verify(exactly = 1) { jobBuilder.observationConvention(observationConvention) } - } - - @Test - fun testObservationRegistry() { - // given - val jobBuilder = spyk(JobBuilder(UUID.randomUUID().toString(), mockk(relaxed = true))) - val jobBuilderDsl = jobBuilderDsl(jobBuilder) - - // when - val observationRegistry = mockk() - jobBuilderDsl.apply { - observationRegistry(observationRegistry) - }.build() - - // then - verify(exactly = 1) { jobBuilder.observationRegistry(observationRegistry) } - } - - @Test - fun testMeterRegistry() { - // given - val jobBuilder = spyk(JobBuilder(UUID.randomUUID().toString(), mockk(relaxed = true))) - val jobBuilderDsl = jobBuilderDsl(jobBuilder) - - // when - val meterRegistry = mockk() - jobBuilderDsl.apply { - meterRegistry(meterRegistry) - }.build() - - // then - verify(exactly = 1) { jobBuilder.meterRegistry(meterRegistry) } - } - - @Suppress("DEPRECATION") - @Test - fun testRepository() { - // given - val jobBuilder = spyk(JobBuilder(UUID.randomUUID().toString(), mockk(relaxed = true))) - val jobBuilderDsl = jobBuilderDsl(jobBuilder) - - // when - val jobRepository = mockk() - jobBuilderDsl.apply { - repository(jobRepository) - }.build() - - // then - verify(exactly = 1) { jobBuilder.repository(jobRepository) } - } - - @Test - fun testObjectListener() { - // given - val jobBuilder = spyk(JobBuilder(UUID.randomUUID().toString(), mockk(relaxed = true))) - val jobBuilderDsl = jobBuilderDsl(jobBuilder) - - class TestListener - - // when - val testListener = TestListener() - jobBuilderDsl.apply { - listener(testListener) - }.build() - - // then - verify(exactly = 1) { jobBuilder.listener(testListener) } - } - - @Test - fun testJobExecutionListener() { - // given - val jobBuilder = spyk(JobBuilder(UUID.randomUUID().toString(), mockk(relaxed = true))) - val jobBuilderDsl = jobBuilderDsl(jobBuilder) - - // when - val jobExecutionListener = mockk() - jobBuilderDsl.apply { - listener(jobExecutionListener) - }.build() - - // then - verify(exactly = 1) { jobBuilder.listener(jobExecutionListener) } - } - - @Test - fun testPreventRestart() { - // given - val jobBuilder = spyk(JobBuilder(UUID.randomUUID().toString(), mockk(relaxed = true))) - val jobBuilderDsl = jobBuilderDsl(jobBuilder) - - // when - jobBuilderDsl.apply { - preventRestart() - }.build() - - // then - verify(exactly = 1) { jobBuilder.preventRestart() } - } - - @Test - fun testConfigurationAfterStep() { - // given - val jobBuilder = spyk(JobBuilder(UUID.randomUUID().toString(), mockk(relaxed = true))) - val jobBuilderDsl = jobBuilderDsl(jobBuilder) - - // when - val jobParametersValidator = mockk() - jobBuilderDsl.apply { - step(mockk()) - validator(jobParametersValidator) - }.build() - - // then - verify(exactly = 1) { jobBuilder.validator(jobParametersValidator) } - } - - private fun jobBuilderDsl(jobBuilder: JobBuilder): JobBuilderDsl { - val dslContext = DslContext( - beanFactory = mockk(), - jobRepository = mockk(), - ) - - return JobBuilderDsl(dslContext, jobBuilder) - } -} diff --git a/spring-batch-plus-kotlin/src/test/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/JobBuilderDslTest.kt b/spring-batch-plus-kotlin/src/test/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/JobBuilderDslTest.kt new file mode 100644 index 00000000..ab4878d5 --- /dev/null +++ b/spring-batch-plus-kotlin/src/test/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/JobBuilderDslTest.kt @@ -0,0 +1,149 @@ +/* + * Spring Batch Plus + * + * Copyright 2022-present NAVER Corp. + * + * 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 + * + * http://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 com.navercorp.spring.batch.plus.kotlin.configuration + +import com.navercorp.spring.batch.plus.kotlin.configuration.support.DslContext +import io.micrometer.observation.ObservationRegistry +import io.mockk.mockk +import io.mockk.spyk +import io.mockk.verify +import org.junit.jupiter.api.Test +import org.springframework.batch.core.job.builder.JobBuilder +import org.springframework.batch.core.job.parameters.JobParametersIncrementer +import org.springframework.batch.core.job.parameters.JobParametersValidator +import org.springframework.batch.core.listener.JobExecutionListener +import java.util.UUID + +/** + * Covers deferred application of common job settings when a job is built. + */ +internal class JobBuilderDslTest { + @Test + fun validatorShouldConfigureJobBuilderWhenValidatorIsProvided() { + // given + val jobBuilder = spyk(JobBuilder(UUID.randomUUID().toString(), mockk(relaxed = true))) + val jobBuilderDsl = jobBuilderDsl(jobBuilder) + + // when + val jobParametersValidator = mockk() + jobBuilderDsl + .apply { + validator(jobParametersValidator) + }.build() + + // then + verify(exactly = 1) { jobBuilder.validator(jobParametersValidator) } + } + + @Test + fun incrementerShouldConfigureJobBuilderWhenIncrementerIsProvided() { + // given + val jobBuilder = spyk(JobBuilder(UUID.randomUUID().toString(), mockk(relaxed = true))) + val jobBuilderDsl = jobBuilderDsl(jobBuilder) + + // when + val jobParametersIncrementer = mockk() + jobBuilderDsl + .apply { + incrementer(jobParametersIncrementer) + }.build() + + // then + verify(exactly = 1) { jobBuilder.incrementer(jobParametersIncrementer) } + } + + @Test + fun observationRegistryShouldConfigureJobBuilderWhenRegistryIsProvided() { + // given + val jobBuilder = spyk(JobBuilder(UUID.randomUUID().toString(), mockk(relaxed = true))) + val jobBuilderDsl = jobBuilderDsl(jobBuilder) + + // when + val observationRegistry = mockk() + jobBuilderDsl + .apply { + observationRegistry(observationRegistry) + }.build() + + // then + verify(exactly = 1) { jobBuilder.observationRegistry(observationRegistry) } + } + + @Test + fun listenerShouldConfigureJobBuilderWhenObjectListenerIsProvided() { + // given + val jobBuilder = spyk(JobBuilder(UUID.randomUUID().toString(), mockk(relaxed = true))) + val jobBuilderDsl = jobBuilderDsl(jobBuilder) + + class TestListener + + // when + val testListener = TestListener() + jobBuilderDsl + .apply { + listener(testListener) + }.build() + + // then + verify(exactly = 1) { jobBuilder.listener(testListener) } + } + + @Test + fun listenerShouldConfigureJobBuilderWhenJobExecutionListenerIsProvided() { + // given + val jobBuilder = spyk(JobBuilder(UUID.randomUUID().toString(), mockk(relaxed = true))) + val jobBuilderDsl = jobBuilderDsl(jobBuilder) + + // when + val jobExecutionListener = mockk() + jobBuilderDsl + .apply { + listener(jobExecutionListener) + }.build() + + // then + verify(exactly = 1) { jobBuilder.listener(jobExecutionListener) } + } + + @Test + fun preventRestartShouldConfigureJobBuilderWhenInvoked() { + // given + val jobBuilder = spyk(JobBuilder(UUID.randomUUID().toString(), mockk(relaxed = true))) + val jobBuilderDsl = jobBuilderDsl(jobBuilder) + + // when + jobBuilderDsl + .apply { + preventRestart() + }.build() + + // then + verify(exactly = 1) { jobBuilder.preventRestart() } + } + + private fun jobBuilderDsl(jobBuilder: JobBuilder): JobBuilderDsl { + val dslContext = + DslContext( + beanFactory = mockk(), + jobRepository = mockk(), + ) + + return JobBuilderDsl(dslContext, jobBuilder) + } +} diff --git a/spring-batch-plus-kotlin/src/test/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/SimpleJobBuilderDslAdapterTest.kt b/spring-batch-plus-kotlin/src/test/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/SimpleJobBuilderDslAdapterTest.kt index e9f3b50f..922509bf 100644 --- a/spring-batch-plus-kotlin/src/test/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/SimpleJobBuilderDslAdapterTest.kt +++ b/spring-batch-plus-kotlin/src/test/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/SimpleJobBuilderDslAdapterTest.kt @@ -19,18 +19,86 @@ package com.navercorp.spring.batch.plus.kotlin.configuration import com.navercorp.spring.batch.plus.kotlin.configuration.support.DslContext +import io.mockk.every import io.mockk.mockk +import io.mockk.verify +import org.assertj.core.api.Assertions.assertThat import org.assertj.core.api.Assertions.assertThatThrownBy import org.junit.jupiter.api.Test -import org.springframework.batch.core.Step +import org.springframework.batch.core.job.Job import org.springframework.batch.core.job.flow.Flow -import org.springframework.batch.repeat.RepeatStatus -import org.springframework.batch.support.transaction.ResourcelessTransactionManager +import org.springframework.batch.core.step.Step +import org.springframework.batch.infrastructure.repeat.RepeatStatus +import org.springframework.batch.infrastructure.support.transaction.ResourcelessTransactionManager +import java.util.UUID +/** + * Covers the adapter boundary between supported plain-step replay and rejected flow-job operations. + */ internal class SimpleJobBuilderDslAdapterTest { + @Test + fun stepBeanShouldDelegateToSimpleJobBuilderDslWhenBeanNameIsProvided() { + // given + val stepName = UUID.randomUUID().toString() + val simpleJobBuilderDsl = mockk(relaxed = true) + val simpleJobBuilderDslAdapter = SimpleJobBuilderDslAdapter(simpleJobBuilderDsl) + + // when + simpleJobBuilderDslAdapter.stepBean(stepName) + + // then + verify(exactly = 1) { simpleJobBuilderDsl.stepBean(stepName) } + } + + @Test + fun stepShouldDelegateToSimpleJobBuilderDslWhenNameAndInitAreProvided() { + // given + val stepName = UUID.randomUUID().toString() + val step = mockk() + val stepInit: StepBuilderDsl.() -> Step = { step } + val simpleJobBuilderDsl = mockk(relaxed = true) + val simpleJobBuilderDslAdapter = SimpleJobBuilderDslAdapter(simpleJobBuilderDsl) + + // when + simpleJobBuilderDslAdapter.step(stepName, stepInit) + + // then + verify(exactly = 1) { simpleJobBuilderDsl.step(stepName, stepInit) } + } + + @Test + fun stepShouldDelegateToSimpleJobBuilderDslWhenStepIsProvided() { + // given + val step = mockk() + val simpleJobBuilderDsl = mockk(relaxed = true) + val simpleJobBuilderDslAdapter = SimpleJobBuilderDslAdapter(simpleJobBuilderDsl) + + // when + simpleJobBuilderDslAdapter.step(step) + + // then + verify(exactly = 1) { simpleJobBuilderDsl.step(step) } + } + + @Test + fun buildShouldReturnJobWhenSimpleJobBuilderDslBuildsJob() { + // given + val job = mockk() + val simpleJobBuilderDsl = + mockk { + every { build() } returns job + } + val simpleJobBuilderDslAdapter = SimpleJobBuilderDslAdapter(simpleJobBuilderDsl) + + // when + val actual = simpleJobBuilderDslAdapter.build() + + // then + assertThat(actual).isSameAs(job) + } @Test - fun testUnsupportedCall() { + fun flowJobOperationShouldThrowUnsupportedOperationExceptionWhenSimpleJobAdapterIsUsed() { // given val simpleJobBuilderDsl = SimpleJobBuilderDsl(DslContext(mockk(), mockk()), mockk()) val simpleJobBuilderDslAdapter = SimpleJobBuilderDslAdapter(simpleJobBuilderDsl) diff --git a/spring-batch-plus-kotlin/src/test/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/StepBuilderDslHelperTest.kt b/spring-batch-plus-kotlin/src/test/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/StepBuilderDslTest.kt similarity index 50% rename from spring-batch-plus-kotlin/src/test/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/StepBuilderDslHelperTest.kt rename to spring-batch-plus-kotlin/src/test/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/StepBuilderDslTest.kt index 9af85ad2..1852d6b6 100644 --- a/spring-batch-plus-kotlin/src/test/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/StepBuilderDslHelperTest.kt +++ b/spring-batch-plus-kotlin/src/test/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/StepBuilderDslTest.kt @@ -19,106 +19,55 @@ package com.navercorp.spring.batch.plus.kotlin.configuration import com.navercorp.spring.batch.plus.kotlin.configuration.support.DslContext -import io.micrometer.core.instrument.MeterRegistry import io.micrometer.observation.ObservationRegistry import io.mockk.mockk import io.mockk.verify import org.junit.jupiter.api.Test -import org.springframework.batch.core.StepExecutionListener -import org.springframework.batch.core.observability.BatchStepObservationConvention -import org.springframework.batch.core.repository.JobRepository +import org.springframework.batch.core.listener.StepExecutionListener import org.springframework.batch.core.step.builder.StepBuilder import org.springframework.transaction.PlatformTransactionManager import java.util.concurrent.ThreadLocalRandom /** - * org.springframework.batch.core.step.builder.StepBuilderHelper related tests + * Covers deferred application of common step settings before specialized step creation. */ -internal class StepBuilderDslHelperTest { - - @Suppress("DEPRECATION") - @Test - fun testRepository() { - // given - val stepBuilder = mockk(relaxed = true) - val stepBuilderDsl = stepBuilderDsl(stepBuilder) - - // when - val jobRepository = mockk() - stepBuilderDsl.apply { - repository(jobRepository) - }.tasklet(mockk(), mockk()) - - // then - verify(exactly = 1) { stepBuilderDsl.repository(jobRepository) } - } - +internal class StepBuilderDslTest { @Test - fun testObservationConvention() { - // given - val stepBuilder = mockk(relaxed = true) - val stepBuilderDsl = stepBuilderDsl(stepBuilder) - - // when - val observationConvention = mockk() - stepBuilderDsl.apply { - observationConvention(observationConvention) - }.tasklet(mockk(), mockk()) - - // then - verify(exactly = 1) { stepBuilderDsl.observationConvention(observationConvention) } - } - - @Test - fun testObservationRegistry() { + fun observationRegistryShouldConfigureStepBuilderWhenRegistryIsProvided() { // given val stepBuilder = mockk(relaxed = true) val stepBuilderDsl = stepBuilderDsl(stepBuilder) // when val observationRegistry = mockk() - stepBuilderDsl.apply { - observationRegistry(observationRegistry) - }.tasklet(mockk(), mockk()) + stepBuilderDsl + .apply { + observationRegistry(observationRegistry) + }.tasklet(mockk(), mockk()) // then verify(exactly = 1) { stepBuilderDsl.observationRegistry(observationRegistry) } } @Test - fun testMeterRegistry() { - // given - val stepBuilder = mockk(relaxed = true) - val stepBuilderDsl = stepBuilderDsl(stepBuilder) - - // when - val meterRegistry = mockk() - stepBuilderDsl.apply { - meterRegistry(meterRegistry) - }.tasklet(mockk(), mockk()) - - // then - verify(exactly = 1) { stepBuilderDsl.meterRegistry(meterRegistry) } - } - - @Test - fun testStartLimit() { + fun startLimitShouldConfigureStepBuilderWhenLimitIsProvided() { // given val stepBuilder = mockk(relaxed = true) val stepBuilderDsl = stepBuilderDsl(stepBuilder) // when val startLimit = ThreadLocalRandom.current().nextInt() - stepBuilderDsl.apply { - startLimit(startLimit) - }.tasklet(mockk(), mockk()) + stepBuilderDsl + .apply { + startLimit(startLimit) + }.tasklet(mockk(), mockk()) // then verify(exactly = 1) { stepBuilderDsl.startLimit(startLimit) } } @Test - fun testObjectListener() { + fun listenerShouldConfigureStepBuilderWhenObjectListenerIsProvided() { // given val stepBuilder = mockk(relaxed = true) val stepBuilderDsl = stepBuilderDsl(stepBuilder) @@ -127,51 +76,55 @@ internal class StepBuilderDslHelperTest { // when val testListener = TestListener() - stepBuilderDsl.apply { - listener(testListener) - }.tasklet(mockk(), mockk()) + stepBuilderDsl + .apply { + listener(testListener) + }.tasklet(mockk(), mockk()) // then verify(exactly = 1) { stepBuilderDsl.listener(testListener) } } @Test - fun testStepExecutionListener() { + fun listenerShouldConfigureStepBuilderWhenStepExecutionListenerIsProvided() { // given val stepBuilder = mockk(relaxed = true) val stepBuilderDsl = stepBuilderDsl(stepBuilder) // when val stepExecutionListener = mockk() - stepBuilderDsl.apply { - listener(stepExecutionListener) - }.tasklet(mockk(), mockk()) + stepBuilderDsl + .apply { + listener(stepExecutionListener) + }.tasklet(mockk(), mockk()) // then verify(exactly = 1) { stepBuilderDsl.listener(stepExecutionListener) } } @Test - fun testAllowStartIfComplete() { + fun allowStartIfCompleteShouldConfigureStepBuilderWhenFlagIsProvided() { // given val stepBuilder = mockk(relaxed = true) val stepBuilderDsl = stepBuilderDsl(stepBuilder) // when val allowStartIfComplete = ThreadLocalRandom.current().nextBoolean() - stepBuilderDsl.apply { - allowStartIfComplete(allowStartIfComplete) - }.tasklet(mockk(), mockk()) + stepBuilderDsl + .apply { + allowStartIfComplete(allowStartIfComplete) + }.tasklet(mockk(), mockk()) // then verify(exactly = 1) { stepBuilderDsl.allowStartIfComplete(allowStartIfComplete) } } private fun stepBuilderDsl(stepBuilder: StepBuilder): StepBuilderDsl { - val dslContext = DslContext( - beanFactory = mockk(), - jobRepository = mockk(), - ) + val dslContext = + DslContext( + beanFactory = mockk(), + jobRepository = mockk(), + ) return StepBuilderDsl(dslContext, stepBuilder) } diff --git a/spring-batch-plus-kotlin/src/test/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/step/ChunkOrientedStepBuilderDslTest.kt b/spring-batch-plus-kotlin/src/test/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/step/ChunkOrientedStepBuilderDslTest.kt new file mode 100644 index 00000000..b4a8bf7d --- /dev/null +++ b/spring-batch-plus-kotlin/src/test/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/step/ChunkOrientedStepBuilderDslTest.kt @@ -0,0 +1,412 @@ +/* + * Spring Batch Plus + * + * Copyright 2022-present NAVER Corp. + * + * 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 + * + * http://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 com.navercorp.spring.batch.plus.kotlin.configuration.step + +import io.micrometer.observation.ObservationRegistry +import io.mockk.every +import io.mockk.mockk +import io.mockk.verify +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test +import org.springframework.batch.core.listener.SkipListener +import org.springframework.batch.core.listener.StepListener +import org.springframework.batch.core.step.StepInterruptionPolicy +import org.springframework.batch.core.step.builder.ChunkOrientedStepBuilder +import org.springframework.batch.core.step.item.ChunkOrientedStep +import org.springframework.batch.core.step.skip.SkipPolicy +import org.springframework.batch.infrastructure.item.ItemProcessor +import org.springframework.batch.infrastructure.item.ItemReader +import org.springframework.batch.infrastructure.item.ItemStream +import org.springframework.batch.infrastructure.item.ItemWriter +import org.springframework.core.retry.RetryListener +import org.springframework.core.retry.RetryPolicy +import org.springframework.core.task.AsyncTaskExecutor +import org.springframework.transaction.PlatformTransactionManager +import org.springframework.transaction.interceptor.TransactionAttribute +import java.util.concurrent.ThreadLocalRandom + +/** + * Covers the unit boundary between chunk-oriented step declarations and their underlying builder configuration. + */ +internal class ChunkOrientedStepBuilderDslTest { + @Test + fun readerShouldConfigureChunkOrientedStepBuilderWhenReaderIsProvided() { + // given + val chunkOrientedStepBuilder = mockk>(relaxed = true) + + // when + val itemReader = mockk>() + ChunkOrientedStepBuilderDsl(mockk(), chunkOrientedStepBuilder) + .apply { + reader(itemReader) + }.build() + + // then + verify(exactly = 1) { chunkOrientedStepBuilder.reader(itemReader) } + } + + @Test + fun processorShouldConfigureChunkOrientedStepBuilderWhenProcessorIsProvided() { + // given + val chunkOrientedStepBuilder = mockk>(relaxed = true) + + // when + val itemProcessor = mockk>() + ChunkOrientedStepBuilderDsl(mockk(), chunkOrientedStepBuilder) + .apply { + processor(itemProcessor) + }.build() + + // then + verify(exactly = 1) { chunkOrientedStepBuilder.processor(itemProcessor) } + } + + @Test + fun writerShouldConfigureChunkOrientedStepBuilderWhenWriterIsProvided() { + // given + val chunkOrientedStepBuilder = mockk>(relaxed = true) + + // when + val itemWriter = mockk>() + ChunkOrientedStepBuilderDsl(mockk(), chunkOrientedStepBuilder) + .apply { + writer(itemWriter) + }.build() + + // then + verify(exactly = 1) { chunkOrientedStepBuilder.writer(itemWriter) } + } + + @Test + fun transactionManagerShouldConfigureChunkOrientedStepBuilderWhenTransactionManagerIsProvided() { + // given + val chunkOrientedStepBuilder = mockk>(relaxed = true) + + // when + val transactionManager = mockk() + ChunkOrientedStepBuilderDsl(mockk(), chunkOrientedStepBuilder) + .apply { + transactionManager(transactionManager) + }.build() + + // then + verify(exactly = 1) { chunkOrientedStepBuilder.transactionManager(transactionManager) } + } + + @Test + fun transactionAttributeShouldConfigureChunkOrientedStepBuilderWhenTransactionAttributeIsProvided() { + // given + val chunkOrientedStepBuilder = mockk>(relaxed = true) + + // when + val transactionAttribute = mockk() + ChunkOrientedStepBuilderDsl(mockk(), chunkOrientedStepBuilder) + .apply { + transactionAttribute(transactionAttribute) + }.build() + + // then + verify(exactly = 1) { chunkOrientedStepBuilder.transactionAttribute(transactionAttribute) } + } + + @Test + fun streamShouldConfigureChunkOrientedStepBuilderWhenItemStreamIsProvided() { + // given + val chunkOrientedStepBuilder = mockk>(relaxed = true) + + // when + val itemStream = mockk() + ChunkOrientedStepBuilderDsl(mockk(), chunkOrientedStepBuilder) + .apply { + stream(itemStream) + }.build() + + // then + verify(exactly = 1) { chunkOrientedStepBuilder.stream(itemStream) } + } + + @Test + fun listenerShouldConfigureChunkOrientedStepBuilderWhenStepListenerIsProvided() { + // given + val chunkOrientedStepBuilder = mockk>(relaxed = true) + + // when + val stepListener = mockk() + ChunkOrientedStepBuilderDsl(mockk(), chunkOrientedStepBuilder) + .apply { + listener(stepListener) + }.build() + + // then + verify(exactly = 1) { chunkOrientedStepBuilder.listener(stepListener) } + } + + @Test + fun listenerShouldConfigureChunkOrientedStepBuilderWhenObjectListenerIsProvided() { + // given + val chunkOrientedStepBuilder = mockk>(relaxed = true) + + class TestListener + + // when + val testListener = TestListener() + ChunkOrientedStepBuilderDsl(mockk(), chunkOrientedStepBuilder) + .apply { + listener(testListener) + }.build() + + // then + verify(exactly = 1) { chunkOrientedStepBuilder.listener(testListener) } + } + + @Test + fun interruptionPolicyShouldConfigureChunkOrientedStepBuilderWhenPolicyIsProvided() { + // given + val chunkOrientedStepBuilder = mockk>(relaxed = true) + + // when + val interruptionPolicy = mockk() + ChunkOrientedStepBuilderDsl(mockk(), chunkOrientedStepBuilder) + .apply { + interruptionPolicy(interruptionPolicy) + }.build() + + // then + verify(exactly = 1) { chunkOrientedStepBuilder.interruptionPolicy(interruptionPolicy) } + } + + @Test + fun faultTolerantShouldEnableFaultToleranceWhenInvoked() { + // given + val chunkOrientedStepBuilder = mockk>(relaxed = true) + + // when + ChunkOrientedStepBuilderDsl(mockk(), chunkOrientedStepBuilder) + .apply { + faultTolerant() + }.build() + + // then + verify(exactly = 1) { chunkOrientedStepBuilder.faultTolerant() } + } + + @Test + fun retryPolicyShouldConfigureChunkOrientedStepBuilderWhenPolicyIsProvided() { + // given + val chunkOrientedStepBuilder = mockk>(relaxed = true) + + // when + val retryPolicy = mockk() + ChunkOrientedStepBuilderDsl(mockk(), chunkOrientedStepBuilder) + .apply { + retryPolicy(retryPolicy) + }.build() + + // then + verify(exactly = 1) { chunkOrientedStepBuilder.retryPolicy(retryPolicy) } + } + + @Test + fun retryListenerShouldConfigureChunkOrientedStepBuilderWhenListenerIsProvided() { + // given + val chunkOrientedStepBuilder = mockk>(relaxed = true) + + // when + val retryListener = mockk() + ChunkOrientedStepBuilderDsl(mockk(), chunkOrientedStepBuilder) + .apply { + retryListener(retryListener) + }.build() + + // then + verify(exactly = 1) { chunkOrientedStepBuilder.retryListener(retryListener) } + } + + @Test + fun retryShouldConfigureChunkOrientedStepBuilderWhenReifiedExceptionTypeIsProvided() { + // given + val chunkOrientedStepBuilder = mockk>(relaxed = true) + + // when + ChunkOrientedStepBuilderDsl(mockk(), chunkOrientedStepBuilder) + .apply { + retry() + }.build() + + // then + verify(exactly = 1) { chunkOrientedStepBuilder.retry(RuntimeException::class.java) } + } + + @Test + fun retryShouldConfigureChunkOrientedStepBuilderWhenKClassIsProvided() { + // given + val chunkOrientedStepBuilder = mockk>(relaxed = true) + + // when + ChunkOrientedStepBuilderDsl(mockk(), chunkOrientedStepBuilder) + .apply { + retry(RuntimeException::class) + }.build() + + // then + verify(exactly = 1) { chunkOrientedStepBuilder.retry(RuntimeException::class.java) } + } + + @Test + fun retryLimitShouldConfigureChunkOrientedStepBuilderWhenLimitIsProvided() { + // given + val chunkOrientedStepBuilder = mockk>(relaxed = true) + + // when + val retryLimit = ThreadLocalRandom.current().nextLong() + ChunkOrientedStepBuilderDsl(mockk(), chunkOrientedStepBuilder) + .apply { + retryLimit(retryLimit) + }.build() + + // then + verify(exactly = 1) { chunkOrientedStepBuilder.retryLimit(retryLimit) } + } + + @Test + fun skipPolicyShouldConfigureChunkOrientedStepBuilderWhenPolicyIsProvided() { + // given + val chunkOrientedStepBuilder = mockk>(relaxed = true) + + // when + val skipPolicy = mockk() + ChunkOrientedStepBuilderDsl(mockk(), chunkOrientedStepBuilder) + .apply { + skipPolicy(skipPolicy) + }.build() + + // then + verify(exactly = 1) { chunkOrientedStepBuilder.skipPolicy(skipPolicy) } + } + + @Test + fun skipListenerShouldConfigureChunkOrientedStepBuilderWhenListenerIsProvided() { + // given + val chunkOrientedStepBuilder = mockk>(relaxed = true) + + // when + val skipListener = mockk>() + ChunkOrientedStepBuilderDsl(mockk(), chunkOrientedStepBuilder) + .apply { + skipListener(skipListener) + }.build() + + // then + verify(exactly = 1) { chunkOrientedStepBuilder.skipListener(skipListener) } + } + + @Test + fun skipShouldConfigureChunkOrientedStepBuilderWhenReifiedExceptionTypeIsProvided() { + // given + val chunkOrientedStepBuilder = mockk>(relaxed = true) + + // when + ChunkOrientedStepBuilderDsl(mockk(), chunkOrientedStepBuilder) + .apply { + skip() + }.build() + + // then + verify(exactly = 1) { chunkOrientedStepBuilder.skip(RuntimeException::class.java) } + } + + @Test + fun skipShouldConfigureChunkOrientedStepBuilderWhenKClassIsProvided() { + // given + val chunkOrientedStepBuilder = mockk>(relaxed = true) + + // when + ChunkOrientedStepBuilderDsl(mockk(), chunkOrientedStepBuilder) + .apply { + skip(RuntimeException::class) + }.build() + + // then + verify(exactly = 1) { chunkOrientedStepBuilder.skip(RuntimeException::class.java) } + } + + @Test + fun skipLimitShouldConfigureChunkOrientedStepBuilderWhenLimitIsProvided() { + // given + val chunkOrientedStepBuilder = mockk>(relaxed = true) + + // when + val skipLimit = ThreadLocalRandom.current().nextLong() + ChunkOrientedStepBuilderDsl(mockk(), chunkOrientedStepBuilder) + .apply { + skipLimit(skipLimit) + }.build() + + // then + verify(exactly = 1) { chunkOrientedStepBuilder.skipLimit(skipLimit) } + } + + @Test + fun taskExecutorShouldConfigureChunkOrientedStepBuilderWhenExecutorIsProvided() { + // given + val chunkOrientedStepBuilder = mockk>(relaxed = true) + + // when + val taskExecutor = mockk() + ChunkOrientedStepBuilderDsl(mockk(), chunkOrientedStepBuilder) + .apply { + taskExecutor(taskExecutor) + }.build() + + // then + verify(exactly = 1) { chunkOrientedStepBuilder.taskExecutor(taskExecutor) } + } + + @Test + fun observationRegistryShouldConfigureChunkOrientedStepBuilderWhenRegistryIsProvided() { + // given + val chunkOrientedStepBuilder = mockk>(relaxed = true) + + // when + val observationRegistry = mockk() + ChunkOrientedStepBuilderDsl(mockk(), chunkOrientedStepBuilder) + .apply { + observationRegistry(observationRegistry) + }.build() + + // then + verify(exactly = 1) { chunkOrientedStepBuilder.observationRegistry(observationRegistry) } + } + + @Test + fun buildShouldReturnBuiltStepWhenInvoked() { + // given + val mockStep = mockk>() + val chunkOrientedStepBuilder = + mockk>(relaxed = true) { + every { build() } returns mockStep + } + + // when + val actual = ChunkOrientedStepBuilderDsl(mockk(), chunkOrientedStepBuilder).build() + + // then + assertThat(actual).isEqualTo(mockStep) + } +} diff --git a/spring-batch-plus-kotlin/src/test/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/step/FaultTolerantStepBuilderDslTest.kt b/spring-batch-plus-kotlin/src/test/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/step/FaultTolerantStepBuilderDslTest.kt index 187a6879..fd3abab7 100644 --- a/spring-batch-plus-kotlin/src/test/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/step/FaultTolerantStepBuilderDslTest.kt +++ b/spring-batch-plus-kotlin/src/test/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/step/FaultTolerantStepBuilderDslTest.kt @@ -16,6 +16,8 @@ * limitations under the License. */ +@file:Suppress("DEPRECATION", "OVERRIDE_DEPRECATION") + package com.navercorp.spring.batch.plus.kotlin.configuration.step import com.navercorp.spring.batch.plus.kotlin.configuration.support.DslContext @@ -24,22 +26,22 @@ import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.ChunkListener -import org.springframework.batch.core.JobExecution -import org.springframework.batch.core.JobInstance -import org.springframework.batch.core.JobParameters -import org.springframework.batch.core.SkipListener -import org.springframework.batch.core.Step import org.springframework.batch.core.annotation.OnSkipInRead +import org.springframework.batch.core.job.JobExecution +import org.springframework.batch.core.job.JobInstance +import org.springframework.batch.core.job.parameters.JobParameters +import org.springframework.batch.core.listener.ChunkListener +import org.springframework.batch.core.listener.SkipListener import org.springframework.batch.core.scope.context.ChunkContext import org.springframework.batch.core.step.FatalStepExecutionException -import org.springframework.batch.core.step.builder.SimpleStepBuilder +import org.springframework.batch.core.step.Step +import org.springframework.batch.core.step.StepExecution import org.springframework.batch.core.step.builder.StepBuilder import org.springframework.batch.core.step.skip.LimitCheckingItemSkipPolicy -import org.springframework.batch.item.ExecutionContext -import org.springframework.batch.item.ItemReader -import org.springframework.batch.item.ItemStream -import org.springframework.batch.support.transaction.ResourcelessTransactionManager +import org.springframework.batch.infrastructure.item.ExecutionContext +import org.springframework.batch.infrastructure.item.ItemReader +import org.springframework.batch.infrastructure.item.ItemStream +import org.springframework.batch.infrastructure.support.transaction.ResourcelessTransactionManager import org.springframework.retry.RetryCallback import org.springframework.retry.RetryContext import org.springframework.retry.RetryListener @@ -49,16 +51,15 @@ import org.springframework.retry.policy.SimpleRetryPolicy import org.springframework.transaction.interceptor.DefaultTransactionAttribute /** - * Separated from SimpleStepBuilderDslTest since it's too big. + * Covers fault-tolerant behavior retained by the deprecated simple-step DSL and ordering-sensitive builder overrides. */ internal class FaultTolerantStepBuilderDslTest { - private val jobInstance = JobInstance(0L, "testJob") private val jobParameters = JobParameters() @Test - fun testSkipListener() { + fun skipListenerShouldReceiveCallbackWhenSkippableReadFailureOccurs() { // given val chunkSize = 3 val readLimit = 20 @@ -68,43 +69,50 @@ internal class FaultTolerantStepBuilderDslTest { var onSkipInReadCallCount = 0 // when - val step = simpleStepBuilderDsl(chunkSize) { - reader { - if (tryCount < skipLimit) { - ++tryCount - throw IllegalStateException("Error") - } + val step = + simpleStepBuilderDsl(chunkSize) { + reader { + if (tryCount < skipLimit) { + ++tryCount + throw IllegalStateException("Error") + } - if (readCallCount < readLimit) { - ++readCallCount - 1 - } else { - null + if (readCallCount < readLimit) { + ++readCallCount + 1 + } else { + null + } + } + writer {} + faultTolerant { + skipLimit(skipLimit) + skip() + listener( + object : SkipListener { + override fun onSkipInRead(t: Throwable) { + ++onSkipInReadCallCount + } + + override fun onSkipInProcess( + item: Number, + t: Throwable, + ) { + // no need to test. we are just testing if listener is invoked + } + + override fun onSkipInWrite( + item: Number, + t: Throwable, + ) { + // no need to test. we are just testing if listener is invoked + } + }, + ) } } - writer {} - faultTolerant { - skipLimit(skipLimit) - skip() - listener( - object : SkipListener { - override fun onSkipInRead(t: Throwable) { - ++onSkipInReadCallCount - } - - override fun onSkipInProcess(item: Number, t: Throwable) { - // no need to test. we are just testing if listener is invoked - } - - override fun onSkipInWrite(item: Number, t: Throwable) { - // no need to test. we are just testing if listener is invoked - } - }, - ) - } - } - val jobExecution = JobExecution(jobInstance, jobParameters) - val stepExecution = jobExecution.createStepExecution(step.name) + val jobExecution = JobExecution(0L, jobInstance, jobParameters) + val stepExecution = StepExecution(step.name, jobExecution) step.execute(stepExecution) // then @@ -115,7 +123,7 @@ internal class FaultTolerantStepBuilderDslTest { } @Test - fun testRetryListener() { + fun retryListenerShouldBeInvokedWhenWriterRetryOccurs() { // given val chunkSize = 3 val readLimit = 20 @@ -124,52 +132,53 @@ internal class FaultTolerantStepBuilderDslTest { var retryOpenCallCount = 0 // when - val step = simpleStepBuilderDsl(chunkSize) { - reader { - if (readCallCount < readLimit) { - ++readCallCount - 1 - } else { - null + val step = + simpleStepBuilderDsl(chunkSize) { + reader { + if (readCallCount < readLimit) { + ++readCallCount + 1 + } else { + null + } + } + writer { + throw IllegalStateException("Error") + } + faultTolerant { + retryLimit(retryLimit) + retry() + listener( + object : RetryListener { + override fun open( + context: RetryContext?, + callback: RetryCallback?, + ): Boolean { + ++retryOpenCallCount + return true + } + + override fun close( + context: RetryContext?, + callback: RetryCallback?, + throwable: Throwable?, + ) { + // no need to test. we are just testing if listener is invoked + } + + override fun onError( + context: RetryContext?, + callback: RetryCallback?, + throwable: Throwable?, + ) { + // no need to test. we are just testing if listener is invoked + } + }, + ) } } - writer { - throw IllegalStateException("Error") - } - faultTolerant { - retryLimit(retryLimit) - retry() - listener( - object : RetryListener { - override fun open( - context: RetryContext?, - callback: RetryCallback?, - ): Boolean { - ++retryOpenCallCount - return true - } - - override fun close( - context: RetryContext?, - callback: RetryCallback?, - throwable: Throwable?, - ) { - // no need to test. we are just testing if listener is invoked - } - - override fun onError( - context: RetryContext?, - callback: RetryCallback?, - throwable: Throwable?, - ) { - // no need to test. we are just testing if listener is invoked - } - }, - ) - } - } - val jobExecution = JobExecution(jobInstance, jobParameters) - val stepExecution = jobExecution.createStepExecution(step.name) + val jobExecution = JobExecution(0L, jobInstance, jobParameters) + val stepExecution = StepExecution(step.name, jobExecution) step.execute(stepExecution) // then @@ -179,7 +188,7 @@ internal class FaultTolerantStepBuilderDslTest { } @Test - fun testKeyGenerator() { + fun keyGeneratorShouldBeInvokedWhenWriterRetryOccurs() { // given val chunkSize = 3 val readLimit = 20 @@ -188,29 +197,30 @@ internal class FaultTolerantStepBuilderDslTest { var keyGeneratorCallCount = 0 // when - val step = simpleStepBuilderDsl(chunkSize) { - reader { - if (readCallCount < readLimit) { - ++readCallCount - 1 - } else { - null + val step = + simpleStepBuilderDsl(chunkSize) { + reader { + if (readCallCount < readLimit) { + ++readCallCount + 1 + } else { + null + } } - } - writer { - throw IllegalStateException("Error") - } - faultTolerant { - retryLimit(retryLimit) - retry() - keyGenerator { - ++keyGeneratorCallCount - "testkey" + writer { + throw IllegalStateException("Error") + } + faultTolerant { + retryLimit(retryLimit) + retry() + keyGenerator { + ++keyGeneratorCallCount + "testkey" + } } } - } - val jobExecution = JobExecution(jobInstance, jobParameters) - val stepExecution = jobExecution.createStepExecution(step.name) + val jobExecution = JobExecution(0L, jobInstance, jobParameters) + val stepExecution = StepExecution(step.name, jobExecution) step.execute(stepExecution) // then @@ -220,7 +230,7 @@ internal class FaultTolerantStepBuilderDslTest { } @Test - fun testRetryLimit() { + fun retryLimitShouldBoundAttemptsWhenWriterKeepsFailing() { // given val chunkSize = 3 val readLimit = 20 @@ -229,26 +239,27 @@ internal class FaultTolerantStepBuilderDslTest { var tryCount = 0 // when - val step = simpleStepBuilderDsl(chunkSize) { - reader { - if (readCallCount < readLimit) { - ++readCallCount - 1 - } else { - null + val step = + simpleStepBuilderDsl(chunkSize) { + reader { + if (readCallCount < readLimit) { + ++readCallCount + 1 + } else { + null + } + } + writer { + ++tryCount + throw IllegalStateException("Error") + } + faultTolerant { + retryLimit(retryLimit) + retry() } } - writer { - ++tryCount - throw IllegalStateException("Error") - } - faultTolerant { - retryLimit(retryLimit) - retry() - } - } - val jobExecution = JobExecution(jobInstance, jobParameters) - val stepExecution = jobExecution.createStepExecution(step.name) + val jobExecution = JobExecution(0L, jobInstance, jobParameters) + val stepExecution = StepExecution(step.name, jobExecution) step.execute(stepExecution) // then @@ -258,7 +269,7 @@ internal class FaultTolerantStepBuilderDslTest { } @Test - fun testRetry() { + fun retryShouldRetryMatchingExceptionWhenWriterFails() { // given val chunkSize = 3 val readLimit = 20 @@ -267,26 +278,27 @@ internal class FaultTolerantStepBuilderDslTest { var tryCount = 0 // when - val step = simpleStepBuilderDsl(chunkSize) { - reader { - if (readCallCount < readLimit) { - ++readCallCount - 1 - } else { - null + val step = + simpleStepBuilderDsl(chunkSize) { + reader { + if (readCallCount < readLimit) { + ++readCallCount + 1 + } else { + null + } + } + writer { + ++tryCount + throw IllegalStateException("Error") + } + faultTolerant { + retryLimit(retryLimit) + retry() } } - writer { - ++tryCount - throw IllegalStateException("Error") - } - faultTolerant { - retryLimit(retryLimit) - retry() - } - } - val jobExecution = JobExecution(jobInstance, jobParameters) - val stepExecution = jobExecution.createStepExecution(step.name) + val jobExecution = JobExecution(0L, jobInstance, jobParameters) + val stepExecution = StepExecution(step.name, jobExecution) step.execute(stepExecution) // then @@ -296,7 +308,7 @@ internal class FaultTolerantStepBuilderDslTest { } @Test - fun testNoRetry() { + fun noRetryShouldPreventRetryWhenExceptionIsExcluded() { // given val chunkSize = 3 val readLimit = 20 @@ -305,27 +317,28 @@ internal class FaultTolerantStepBuilderDslTest { var tryCount = 0 // when - val step = simpleStepBuilderDsl(chunkSize) { - reader { - if (readCallCount < readLimit) { - ++readCallCount - 1 - } else { - null + val step = + simpleStepBuilderDsl(chunkSize) { + reader { + if (readCallCount < readLimit) { + ++readCallCount + 1 + } else { + null + } + } + writer { + ++tryCount + throw IllegalStateException("Error") + } + faultTolerant { + retryLimit(retryLimit) + retry() + noRetry() } } - writer { - ++tryCount - throw IllegalStateException("Error") - } - faultTolerant { - retryLimit(retryLimit) - retry() - noRetry() - } - } - val jobExecution = JobExecution(jobInstance, jobParameters) - val stepExecution = jobExecution.createStepExecution(step.name) + val jobExecution = JobExecution(0L, jobInstance, jobParameters) + val stepExecution = StepExecution(step.name, jobExecution) step.execute(stepExecution) // then @@ -335,7 +348,7 @@ internal class FaultTolerantStepBuilderDslTest { } @Test - fun testRetryPolicy() { + fun retryPolicyShouldControlAttemptsWhenWriterKeepsFailing() { // given val chunkSize = 3 val readLimit = 20 @@ -344,26 +357,27 @@ internal class FaultTolerantStepBuilderDslTest { var tryCount = 0 // when - val step = simpleStepBuilderDsl(chunkSize) { - reader { - if (readCallCount < readLimit) { - ++readCallCount - 1 - } else { - null + val step = + simpleStepBuilderDsl(chunkSize) { + reader { + if (readCallCount < readLimit) { + ++readCallCount + 1 + } else { + null + } + } + writer { + ++tryCount + throw IllegalStateException("Error") + } + faultTolerant { + retryPolicy(SimpleRetryPolicy(retryLimit)) + retry() } } - writer { - ++tryCount - throw IllegalStateException("Error") - } - faultTolerant { - retryPolicy(SimpleRetryPolicy(retryLimit)) - retry() - } - } - val jobExecution = JobExecution(jobInstance, jobParameters) - val stepExecution = jobExecution.createStepExecution(step.name) + val jobExecution = JobExecution(0L, jobInstance, jobParameters) + val stepExecution = StepExecution(step.name, jobExecution) step.execute(stepExecution) // then @@ -373,7 +387,7 @@ internal class FaultTolerantStepBuilderDslTest { } @Test - fun testBackoffPolicy() { + fun backOffPolicyShouldBeInvokedWhenWriterRetryOccurs() { // given val chunkSize = 3 val readLimit = 20 @@ -383,34 +397,35 @@ internal class FaultTolerantStepBuilderDslTest { var backoffPolicyCallCount = 0 // when - val step = simpleStepBuilderDsl(chunkSize) { - reader { - if (readCallCount < readLimit) { - ++readCallCount - 1 - } else { - null + val step = + simpleStepBuilderDsl(chunkSize) { + reader { + if (readCallCount < readLimit) { + ++readCallCount + 1 + } else { + null + } + } + writer { + ++tryCount + throw IllegalStateException("Error") + } + faultTolerant { + retryLimit(retryLimit) + backOffPolicy( + object : FixedBackOffPolicy() { + override fun doBackOff() { + ++backoffPolicyCallCount + super.doBackOff() + } + }, + ) + retry() } } - writer { - ++tryCount - throw IllegalStateException("Error") - } - faultTolerant { - retryLimit(retryLimit) - backOffPolicy( - object : FixedBackOffPolicy() { - override fun doBackOff() { - ++backoffPolicyCallCount - super.doBackOff() - } - }, - ) - retry() - } - } - val jobExecution = JobExecution(jobInstance, jobParameters) - val stepExecution = jobExecution.createStepExecution(step.name) + val jobExecution = JobExecution(0L, jobInstance, jobParameters) + val stepExecution = StepExecution(step.name, jobExecution) step.execute(stepExecution) // then @@ -421,7 +436,7 @@ internal class FaultTolerantStepBuilderDslTest { } @Test - fun testRetryContextCache() { + fun retryContextCacheShouldBeUsedWhenWriterRetryOccurs() { // given val chunkSize = 3 val readLimit = 20 @@ -431,34 +446,35 @@ internal class FaultTolerantStepBuilderDslTest { var retryContextCacheCallCount = 0 // when - val step = simpleStepBuilderDsl(chunkSize) { - reader { - if (readCallCount < readLimit) { - ++readCallCount - 1 - } else { - null + val step = + simpleStepBuilderDsl(chunkSize) { + reader { + if (readCallCount < readLimit) { + ++readCallCount + 1 + } else { + null + } + } + writer { + ++tryCount + throw IllegalStateException("Error") + } + faultTolerant { + retryLimit(retryLimit) + retryContextCache( + object : MapRetryContextCache() { + override fun containsKey(key: Any?): Boolean { + ++retryContextCacheCallCount + return super.containsKey(key) + } + }, + ) + retry() } } - writer { - ++tryCount - throw IllegalStateException("Error") - } - faultTolerant { - retryLimit(retryLimit) - retryContextCache( - object : MapRetryContextCache() { - override fun containsKey(key: Any?): Boolean { - ++retryContextCacheCallCount - return super.containsKey(key) - } - }, - ) - retry() - } - } - val jobExecution = JobExecution(jobInstance, jobParameters) - val stepExecution = jobExecution.createStepExecution(step.name) + val jobExecution = JobExecution(0L, jobInstance, jobParameters) + val stepExecution = StepExecution(step.name, jobExecution) step.execute(stepExecution) // then @@ -469,7 +485,7 @@ internal class FaultTolerantStepBuilderDslTest { } @Test - fun testSkipLimit() { + fun skipLimitShouldAllowConfiguredNumberOfReadFailuresWhenExceptionIsSkippable() { // given val chunkSize = 3 val readLimit = 20 @@ -478,28 +494,29 @@ internal class FaultTolerantStepBuilderDslTest { var tryCount = 0 // when - val step = simpleStepBuilderDsl(chunkSize) { - reader { - if (tryCount < skipLimit) { - ++tryCount - throw IllegalStateException("Error") - } + val step = + simpleStepBuilderDsl(chunkSize) { + reader { + if (tryCount < skipLimit) { + ++tryCount + throw IllegalStateException("Error") + } - if (readCallCount < readLimit) { - ++readCallCount - 1 - } else { - null + if (readCallCount < readLimit) { + ++readCallCount + 1 + } else { + null + } + } + writer { } + faultTolerant { + skipLimit(skipLimit) + skip() } } - writer { } - faultTolerant { - skipLimit(skipLimit) - skip() - } - } - val jobExecution = JobExecution(jobInstance, jobParameters) - val stepExecution = jobExecution.createStepExecution(step.name) + val jobExecution = JobExecution(0L, jobInstance, jobParameters) + val stepExecution = StepExecution(step.name, jobExecution) step.execute(stepExecution) // then @@ -509,7 +526,7 @@ internal class FaultTolerantStepBuilderDslTest { } @Test - fun testSkip() { + fun skipShouldSkipMatchingExceptionWhenReadFails() { // given val chunkSize = 3 val readLimit = 20 @@ -518,28 +535,29 @@ internal class FaultTolerantStepBuilderDslTest { var tryCount = 0 // when - val step = simpleStepBuilderDsl(chunkSize) { - reader { - if (tryCount < skipLimit) { - ++tryCount - throw IllegalStateException("Error") - } + val step = + simpleStepBuilderDsl(chunkSize) { + reader { + if (tryCount < skipLimit) { + ++tryCount + throw IllegalStateException("Error") + } - if (readCallCount < readLimit) { - ++readCallCount - 1 - } else { - null + if (readCallCount < readLimit) { + ++readCallCount + 1 + } else { + null + } + } + writer { } + faultTolerant { + skipLimit(skipLimit) + skip() } } - writer { } - faultTolerant { - skipLimit(skipLimit) - skip() - } - } - val jobExecution = JobExecution(jobInstance, jobParameters) - val stepExecution = jobExecution.createStepExecution(step.name) + val jobExecution = JobExecution(0L, jobInstance, jobParameters) + val stepExecution = StepExecution(step.name, jobExecution) step.execute(stepExecution) // then @@ -549,7 +567,7 @@ internal class FaultTolerantStepBuilderDslTest { } @Test - fun testNoSkip() { + fun noSkipShouldFailStepWithoutSkippingWhenExceptionIsExcluded() { // given val chunkSize = 3 val readLimit = 20 @@ -558,29 +576,30 @@ internal class FaultTolerantStepBuilderDslTest { var tryCount = 0 // when - val step = simpleStepBuilderDsl(chunkSize) { - reader { - if (tryCount < skipLimit) { - ++tryCount - throw IllegalStateException("Error") - } + val step = + simpleStepBuilderDsl(chunkSize) { + reader { + if (tryCount < skipLimit) { + ++tryCount + throw IllegalStateException("Error") + } - if (readCallCount < readLimit) { - ++readCallCount - 1 - } else { - null + if (readCallCount < readLimit) { + ++readCallCount + 1 + } else { + null + } + } + writer { } + faultTolerant { + skipLimit(skipLimit) + skip() + noSkip() } } - writer { } - faultTolerant { - skipLimit(skipLimit) - skip() - noSkip() - } - } - val jobExecution = JobExecution(jobInstance, jobParameters) - val stepExecution = jobExecution.createStepExecution(step.name) + val jobExecution = JobExecution(0L, jobInstance, jobParameters) + val stepExecution = StepExecution(step.name, jobExecution) step.execute(stepExecution) // then @@ -590,7 +609,7 @@ internal class FaultTolerantStepBuilderDslTest { } @Test - fun testSkipPolicy() { + fun skipPolicyShouldAllowReadFailuresWhenPolicyAcceptsException() { // given val chunkSize = 3 val readLimit = 20 @@ -599,32 +618,33 @@ internal class FaultTolerantStepBuilderDslTest { var tryCount = 0 // when - val step = simpleStepBuilderDsl(chunkSize) { - reader { - if (tryCount < skipLimit) { - ++tryCount - throw IllegalStateException("Error") - } + val step = + simpleStepBuilderDsl(chunkSize) { + reader { + if (tryCount < skipLimit) { + ++tryCount + throw IllegalStateException("Error") + } - if (readCallCount < readLimit) { - ++readCallCount - 1 - } else { - null + if (readCallCount < readLimit) { + ++readCallCount + 1 + } else { + null + } + } + writer { } + faultTolerant { + skipPolicy( + LimitCheckingItemSkipPolicy( + skipLimit, + mapOf(IllegalStateException::class.java to true), + ), + ) } } - writer { } - faultTolerant { - skipPolicy( - LimitCheckingItemSkipPolicy( - skipLimit, - mapOf(IllegalStateException::class.java to true), - ), - ) - } - } - val jobExecution = JobExecution(jobInstance, jobParameters) - val stepExecution = jobExecution.createStepExecution(step.name) + val jobExecution = JobExecution(0L, jobInstance, jobParameters) + val stepExecution = StepExecution(step.name, jobExecution) step.execute(stepExecution) // then @@ -634,32 +654,33 @@ internal class FaultTolerantStepBuilderDslTest { } @Test - fun testNoRollback() { + fun noRollbackShouldCompleteStepWhenWriterThrowsExcludedException() { // given val chunkSize = 3 val readLimit = 20 var readCallCount = 0 // when - val step = simpleStepBuilderDsl(chunkSize) { - reader { - if (readCallCount < readLimit) { - ++readCallCount - 1 - } else { - null + val step = + simpleStepBuilderDsl(chunkSize) { + reader { + if (readCallCount < readLimit) { + ++readCallCount + 1 + } else { + null + } + } + writer { + // ignored when noRollback is set + throw IllegalStateException("Error") + } + faultTolerant { + noRollback() } } - writer { - // ignored when noRollback is set - throw IllegalStateException("Error") - } - faultTolerant { - noRollback() - } - } - val jobExecution = JobExecution(jobInstance, jobParameters) - val stepExecution = jobExecution.createStepExecution(step.name) + val jobExecution = JobExecution(0L, jobInstance, jobParameters) + val stepExecution = StepExecution(step.name, jobExecution) step.execute(stepExecution) // then @@ -668,7 +689,7 @@ internal class FaultTolerantStepBuilderDslTest { } @Test - fun testProcessorNonTransactional() { + fun processorNonTransactionalShouldAvoidReprocessingItemsWhenWriterRetries() { // given val chunkSize = 3 val readLimit = 20 @@ -678,33 +699,34 @@ internal class FaultTolerantStepBuilderDslTest { var tryCount = 0 // when - val step = simpleStepBuilderDsl(chunkSize) { - reader { - if (readCallCount < readLimit) { - ++readCallCount - 1 - } else { - null + val step = + simpleStepBuilderDsl(chunkSize) { + reader { + if (readCallCount < readLimit) { + ++readCallCount + 1 + } else { + null + } } - } - processor { - ++processCallCount - it - } - writer { - if (tryCount < (retryLimit - 1)) { - ++tryCount - throw IllegalStateException("Error") + processor { + ++processCallCount + it + } + writer { + if (tryCount < (retryLimit - 1)) { + ++tryCount + throw IllegalStateException("Error") + } + } + faultTolerant { + retryLimit(retryLimit) + retry() + processorNonTransactional() } } - faultTolerant { - retryLimit(retryLimit) - retry() - processorNonTransactional() - } - } - val jobExecution = JobExecution(jobInstance, jobParameters) - val stepExecution = jobExecution.createStepExecution(step.name) + val jobExecution = JobExecution(0L, jobInstance, jobParameters) + val stepExecution = StepExecution(step.name, jobExecution) step.execute(stepExecution) // then @@ -714,11 +736,13 @@ internal class FaultTolerantStepBuilderDslTest { assertThat(processCallCount).isEqualTo(readLimit) } + /** + * Covers ordering compatibility for options whose delegate changes after fault tolerance is enabled. + */ @Nested inner class OverriddenMethodTest { - @Test - fun testObjectSkipListenerNotInvokedWhenCalledBeforeFaultTolerant() { + fun objectListenerShouldNotReceiveSkipCallbackWhenRegisteredBeforeFaultTolerantOnDelegate() { // given val chunkSize = 1 val readLimit = 3 @@ -728,7 +752,7 @@ internal class FaultTolerantStepBuilderDslTest { var onSkipInReadCallCount = 0 val stepBuilder = StepBuilder("testStep", mockk(relaxed = true)) - val simpleStepBuilder = SimpleStepBuilder(stepBuilder) + val simpleStepBuilder = TestBuilderBridge.simpleStepBuilder(stepBuilder) class TestListener { @Suppress("unused") @@ -739,30 +763,30 @@ internal class FaultTolerantStepBuilderDslTest { } // when - val step = simpleStepBuilder - .chunk(chunkSize) - .transactionManager(ResourcelessTransactionManager()) - .listener(TestListener()) // called before faultTolerant() - .reader { - if (tryCount < skipLimit) { - ++tryCount - throw IllegalStateException("Error") - } + val step = + simpleStepBuilder + .chunk(chunkSize) + .transactionManager(ResourcelessTransactionManager()) + .listener(TestListener()) // called before faultTolerant() + .reader { + if (tryCount < skipLimit) { + ++tryCount + throw IllegalStateException("Error") + } - if (readCallCount < readLimit) { - ++readCallCount - 1 - } else { - null - } - } - .writer {} - .faultTolerant() - .skipLimit(skipLimit) - .skip(IllegalStateException::class.java) - .build() - val jobExecution = JobExecution(jobInstance, jobParameters) - val stepExecution = jobExecution.createStepExecution(step.name) + if (readCallCount < readLimit) { + ++readCallCount + 1 + } else { + null + } + }.writer {} + .faultTolerant() + .skipLimit(skipLimit) + .skip(IllegalStateException::class.java) + .build() + val jobExecution = JobExecution(0L, jobInstance, jobParameters) + val stepExecution = StepExecution(step.name, jobExecution) step.execute(stepExecution) // then @@ -773,7 +797,7 @@ internal class FaultTolerantStepBuilderDslTest { } @Test - fun testObjectSkipListenerInvokedWhenCalledAfterFaultTolerant() { + fun objectListenerShouldReceiveSkipCallbackWhenRegisteredAfterFaultTolerantOnDelegate() { // given val chunkSize = 1 val readLimit = 3 @@ -783,7 +807,7 @@ internal class FaultTolerantStepBuilderDslTest { var onSkipInReadCallCount = 0 val stepBuilder = StepBuilder("testStep", mockk(relaxed = true)) - val simpleStepBuilder = SimpleStepBuilder(stepBuilder) + val simpleStepBuilder = TestBuilderBridge.simpleStepBuilder(stepBuilder) class TestListener { @Suppress("unused") @@ -794,30 +818,30 @@ internal class FaultTolerantStepBuilderDslTest { } // when - val step = simpleStepBuilder - .chunk(chunkSize) - .transactionManager(ResourcelessTransactionManager()) - .reader { - if (tryCount < skipLimit) { - ++tryCount - throw IllegalStateException("Error") - } + val step = + simpleStepBuilder + .chunk(chunkSize) + .transactionManager(ResourcelessTransactionManager()) + .reader { + if (tryCount < skipLimit) { + ++tryCount + throw IllegalStateException("Error") + } - if (readCallCount < readLimit) { - ++readCallCount - 1 - } else { - null - } - } - .writer {} - .faultTolerant() - .skipLimit(skipLimit) - .skip(IllegalStateException::class.java) - .listener(TestListener()) // called after faultTolerant() - .build() - val jobExecution = JobExecution(jobInstance, jobParameters) - val stepExecution = jobExecution.createStepExecution(step.name) + if (readCallCount < readLimit) { + ++readCallCount + 1 + } else { + null + } + }.writer {} + .faultTolerant() + .skipLimit(skipLimit) + .skip(IllegalStateException::class.java) + .listener(TestListener()) // called after faultTolerant() + .build() + val jobExecution = JobExecution(0L, jobInstance, jobParameters) + val stepExecution = StepExecution(step.name, jobExecution) step.execute(stepExecution) // then @@ -828,7 +852,7 @@ internal class FaultTolerantStepBuilderDslTest { } @Test - fun testObjectSkipListenerInvokedOnDslWhenCalledBeforeFaultTolerant() { + fun objectListenerShouldReceiveSkipCallbackWhenRegisteredBeforeFaultTolerantOnDsl() { // given val chunkSize = 1 val readLimit = 3 @@ -846,29 +870,30 @@ internal class FaultTolerantStepBuilderDslTest { } // when - val step = simpleStepBuilderDsl(chunkSize) { - listener(TestListener()) // called before faultTolerant - reader { - if (tryCount < skipLimit) { - ++tryCount - throw IllegalStateException("Error") - } + val step = + simpleStepBuilderDsl(chunkSize) { + listener(TestListener()) // called before faultTolerant + reader { + if (tryCount < skipLimit) { + ++tryCount + throw IllegalStateException("Error") + } - if (readCallCount < readLimit) { - ++readCallCount - 1 - } else { - null + if (readCallCount < readLimit) { + ++readCallCount + 1 + } else { + null + } + } + writer {} + faultTolerant { + skipLimit(skipLimit) + skip(IllegalStateException::class) } } - writer {} - faultTolerant { - skipLimit(skipLimit) - skip(IllegalStateException::class) - } - } - val jobExecution = JobExecution(jobInstance, jobParameters) - val stepExecution = jobExecution.createStepExecution(step.name) + val jobExecution = JobExecution(0L, jobInstance, jobParameters) + val stepExecution = StepExecution(step.name, jobExecution) step.execute(stepExecution) // then @@ -879,7 +904,7 @@ internal class FaultTolerantStepBuilderDslTest { } @Test - fun testObjectSkipListenerInvokedOnDslWhenCalledAfterFaultTolerant() { + fun objectListenerShouldReceiveSkipCallbackWhenRegisteredAfterFaultTolerantOnDsl() { // given val chunkSize = 1 val readLimit = 3 @@ -897,29 +922,30 @@ internal class FaultTolerantStepBuilderDslTest { } // when - val step = simpleStepBuilderDsl(chunkSize) { - reader { - if (tryCount < skipLimit) { - ++tryCount - throw IllegalStateException("Error") - } + val step = + simpleStepBuilderDsl(chunkSize) { + reader { + if (tryCount < skipLimit) { + ++tryCount + throw IllegalStateException("Error") + } - if (readCallCount < readLimit) { - ++readCallCount - 1 - } else { - null + if (readCallCount < readLimit) { + ++readCallCount + 1 + } else { + null + } } + writer {} + faultTolerant { + skipLimit(skipLimit) + skip(IllegalStateException::class) + } + listener(TestListener()) // called before faultTolerant } - writer {} - faultTolerant { - skipLimit(skipLimit) - skip(IllegalStateException::class) - } - listener(TestListener()) // called before faultTolerant - } - val jobExecution = JobExecution(jobInstance, jobParameters) - val stepExecution = jobExecution.createStepExecution(step.name) + val jobExecution = JobExecution(0L, jobInstance, jobParameters) + val stepExecution = StepExecution(step.name, jobExecution) step.execute(stepExecution) // then @@ -930,36 +956,34 @@ internal class FaultTolerantStepBuilderDslTest { } @Test - fun testDelegateListenerIsInvokedWhenCalledWithFaultTolerant() { + fun chunkListenerShouldBeInvokedWhenRegisteredAfterFaultTolerantOnDelegate() { // given val stepBuilder = StepBuilder("testStep", mockk(relaxed = true)) - val simpleStepBuilder = SimpleStepBuilder(stepBuilder) + val simpleStepBuilder = TestBuilderBridge.simpleStepBuilder(stepBuilder) // when - val step = simpleStepBuilder - .chunk(3) - .transactionManager(ResourcelessTransactionManager()) - .reader { null } - .faultTolerant() - .retryLimit(3) - .retry(RuntimeException::class.java) - .writer {} - .listener( - object : ChunkListener { - override fun beforeChunk(context: ChunkContext) { - throw IllegalStateException("Error") - } - - override fun afterChunk(context: ChunkContext) { - } - - override fun afterChunkError(context: ChunkContext) { - } - }, - ) - .build() - val jobExecution = JobExecution(jobInstance, jobParameters) - val stepExecution = jobExecution.createStepExecution(step.name) + val step = + simpleStepBuilder + .chunk(3) + .transactionManager(ResourcelessTransactionManager()) + .reader { null } + .faultTolerant() + .retryLimit(3) + .retry(RuntimeException::class.java) + .writer {} + .listener( + object : ChunkListener { + override fun beforeChunk(context: ChunkContext): Unit = throw IllegalStateException("Error") + + override fun afterChunk(context: ChunkContext) { + } + + override fun afterChunkError(context: ChunkContext) { + } + }, + ).build() + val jobExecution = JobExecution(0L, jobInstance, jobParameters) + val stepExecution = StepExecution(step.name, jobExecution) step.execute(stepExecution) // then @@ -970,31 +994,30 @@ internal class FaultTolerantStepBuilderDslTest { } @Test - fun testDelegateListenerIsInvokedOnDslWhenCalledBeforeFaultTolerant() { + fun chunkListenerShouldBeInvokedWhenRegisteredBeforeFaultTolerantOnDsl() { // when - val step = simpleStepBuilderDsl(3) { - reader { null } - writer {} - listener( - object : ChunkListener { - override fun beforeChunk(context: ChunkContext) { - throw IllegalStateException("Error") - } - - override fun afterChunk(context: ChunkContext) { - } - - override fun afterChunkError(context: ChunkContext) { - } - }, - ) - faultTolerant { - retryLimit(3) - retry() + val step = + simpleStepBuilderDsl(3) { + reader { null } + writer {} + listener( + object : ChunkListener { + override fun beforeChunk(context: ChunkContext): Unit = throw IllegalStateException("Error") + + override fun afterChunk(context: ChunkContext) { + } + + override fun afterChunkError(context: ChunkContext) { + } + }, + ) + faultTolerant { + retryLimit(3) + retry() + } } - } - val jobExecution = JobExecution(jobInstance, jobParameters) - val stepExecution = jobExecution.createStepExecution(step.name) + val jobExecution = JobExecution(0L, jobInstance, jobParameters) + val stepExecution = StepExecution(step.name, jobExecution) step.execute(stepExecution) // then @@ -1005,31 +1028,30 @@ internal class FaultTolerantStepBuilderDslTest { } @Test - fun testDelegateListenerIsInvokedOnDslWhenCalledAfterFaultTolerant() { + fun chunkListenerShouldBeInvokedWhenRegisteredAfterFaultTolerantOnDsl() { // when - val step = simpleStepBuilderDsl(3) { - reader { null } - writer {} - faultTolerant { - retryLimit(3) - retry() - } - listener( - object : ChunkListener { - override fun beforeChunk(context: ChunkContext) { - throw IllegalStateException("Error") - } + val step = + simpleStepBuilderDsl(3) { + reader { null } + writer {} + faultTolerant { + retryLimit(3) + retry() + } + listener( + object : ChunkListener { + override fun beforeChunk(context: ChunkContext): Unit = throw IllegalStateException("Error") - override fun afterChunk(context: ChunkContext) { - } + override fun afterChunk(context: ChunkContext) { + } - override fun afterChunkError(context: ChunkContext) { - } - }, - ) - } - val jobExecution = JobExecution(jobInstance, jobParameters) - val stepExecution = jobExecution.createStepExecution(step.name) + override fun afterChunkError(context: ChunkContext) { + } + }, + ) + } + val jobExecution = JobExecution(0L, jobInstance, jobParameters) + val stepExecution = StepExecution(step.name, jobExecution) step.execute(stepExecution) // then @@ -1040,7 +1062,7 @@ internal class FaultTolerantStepBuilderDslTest { } @Test - fun testTransactionAttributeIsWrappedWhenCalledWithFaultTolerant() { + fun transactionAttributeShouldHonorNoRollbackWhenConfiguredAfterFaultTolerantOnDelegate() { // given val chunkSize = 3 val readLimit = 20 @@ -1048,39 +1070,37 @@ internal class FaultTolerantStepBuilderDslTest { var noRollbackCallCount = 0 val stepBuilder = StepBuilder("testStep", mockk(relaxed = true)) - val simpleStepBuilder = SimpleStepBuilder(stepBuilder) + val simpleStepBuilder = TestBuilderBridge.simpleStepBuilder(stepBuilder) // when - val step = simpleStepBuilder - .chunk(chunkSize) - .transactionManager(ResourcelessTransactionManager()) - .reader { - if (readCallCount < readLimit) { - ++readCallCount - 1 - } else { - null - } - } - .writer { - throw IllegalStateException("Error") - } - .faultTolerant() // use faultTolerant - .noRollback(IllegalStateException::class.java) // wrapped by making it as noRollback - .transactionAttribute( - object : DefaultTransactionAttribute() { - override fun rollbackOn(ex: Throwable): Boolean { - // make it always rollback (batch exit with failed) - // but with faultTolerant, class defined in noRollback is considered - // noRollback in transaction by wrapping transactionAttribute - ++noRollbackCallCount - return ex is IllegalStateException + val step = + simpleStepBuilder + .chunk(chunkSize) + .transactionManager(ResourcelessTransactionManager()) + .reader { + if (readCallCount < readLimit) { + ++readCallCount + 1 + } else { + null } - }, - ) - .build() - val jobExecution = JobExecution(jobInstance, jobParameters) - val stepExecution = jobExecution.createStepExecution(step.name) + }.writer { + throw IllegalStateException("Error") + }.faultTolerant() // use faultTolerant + .noRollback(IllegalStateException::class.java) // wrapped by making it as noRollback + .transactionAttribute( + object : DefaultTransactionAttribute() { + override fun rollbackOn(ex: Throwable): Boolean { + // make it always rollback (batch exit with failed) + // but with faultTolerant, class defined in noRollback is considered + // noRollback in transaction by wrapping transactionAttribute + ++noRollbackCallCount + return ex is IllegalStateException + } + }, + ).build() + val jobExecution = JobExecution(0L, jobInstance, jobParameters) + val stepExecution = StepExecution(step.name, jobExecution) step.execute(stepExecution) // then @@ -1090,7 +1110,7 @@ internal class FaultTolerantStepBuilderDslTest { } @Test - fun testTransactionAttributeIsWrappedOnDslWhenCalledBeforeFaultTolerantIsCalled() { + fun transactionAttributeShouldHonorNoRollbackWhenConfiguredBeforeFaultTolerantOnDsl() { // given val chunkSize = 3 val readLimit = 20 @@ -1098,32 +1118,33 @@ internal class FaultTolerantStepBuilderDslTest { var noRollbackCallCount = 0 // when - val step = simpleStepBuilderDsl(chunkSize) { - transactionAttribute( - object : DefaultTransactionAttribute() { - override fun rollbackOn(ex: Throwable): Boolean { - ++noRollbackCallCount - return ex is IllegalStateException + val step = + simpleStepBuilderDsl(chunkSize) { + transactionAttribute( + object : DefaultTransactionAttribute() { + override fun rollbackOn(ex: Throwable): Boolean { + ++noRollbackCallCount + return ex is IllegalStateException + } + }, + ) + reader { + if (readCallCount < readLimit) { + ++readCallCount + 1 + } else { + null } - }, - ) - reader { - if (readCallCount < readLimit) { - ++readCallCount - 1 - } else { - null + } + writer { + throw IllegalStateException("Error") + } + faultTolerant { + noRollback() } } - writer { - throw IllegalStateException("Error") - } - faultTolerant { - noRollback() - } - } - val jobExecution = JobExecution(jobInstance, jobParameters) - val stepExecution = jobExecution.createStepExecution(step.name) + val jobExecution = JobExecution(0L, jobInstance, jobParameters) + val stepExecution = StepExecution(step.name, jobExecution) step.execute(stepExecution) // then @@ -1133,7 +1154,7 @@ internal class FaultTolerantStepBuilderDslTest { } @Test - fun testTransactionAttributeIsWrappedOnDslWhenCalledAfterFaultTolerantIsCalled() { + fun transactionAttributeShouldHonorNoRollbackWhenConfiguredAfterFaultTolerantOnDsl() { // given val chunkSize = 3 val readLimit = 20 @@ -1141,32 +1162,33 @@ internal class FaultTolerantStepBuilderDslTest { var noRollbackCallCount = 0 // when - val step = simpleStepBuilderDsl(chunkSize) { - reader { - if (readCallCount < readLimit) { - ++readCallCount - 1 - } else { - null + val step = + simpleStepBuilderDsl(chunkSize) { + reader { + if (readCallCount < readLimit) { + ++readCallCount + 1 + } else { + null + } } + writer { + throw IllegalStateException("Error") + } + faultTolerant { + noRollback() + } + transactionAttribute( + object : DefaultTransactionAttribute() { + override fun rollbackOn(ex: Throwable): Boolean { + ++noRollbackCallCount + return ex is IllegalStateException + } + }, + ) } - writer { - throw IllegalStateException("Error") - } - faultTolerant { - noRollback() - } - transactionAttribute( - object : DefaultTransactionAttribute() { - override fun rollbackOn(ex: Throwable): Boolean { - ++noRollbackCallCount - return ex is IllegalStateException - } - }, - ) - } - val jobExecution = JobExecution(jobInstance, jobParameters) - val stepExecution = jobExecution.createStepExecution(step.name) + val jobExecution = JobExecution(0L, jobInstance, jobParameters) + val stepExecution = StepExecution(step.name, jobExecution) step.execute(stepExecution) // then @@ -1176,7 +1198,7 @@ internal class FaultTolerantStepBuilderDslTest { } @Test - fun testStreamIsDelegatedToChunkMonitorWhenCalledWithFaultTolerant() { + fun streamShouldRegisterWithChunkMonitorWhenConfiguredAfterFaultTolerantOnDelegate() { // given val chunkSize = 3 val readLimit = 20 @@ -1184,12 +1206,15 @@ internal class FaultTolerantStepBuilderDslTest { var readCallCount = 0 val stepBuilder = StepBuilder("testStep", mockk(relaxed = true)) - val simpleStepBuilder = SimpleStepBuilder(stepBuilder) + val simpleStepBuilder = TestBuilderBridge.simpleStepBuilder(stepBuilder) - class TestStream : ItemStream, ItemReader { + class TestStream : + ItemStream, + ItemReader { override fun open(executionContext: ExecutionContext) { ++streamOpenCallCount - Throwable().stackTrace + Throwable() + .stackTrace .filter { it.className.endsWith("ChunkMonitor") } .also { assertThat(it).isNotEmpty @@ -1202,29 +1227,27 @@ internal class FaultTolerantStepBuilderDslTest { override fun close() { } - override fun read(): Int? { - return null - } + override fun read(): Int? = null } // when - val step = simpleStepBuilder - .chunk(chunkSize) - .transactionManager(ResourcelessTransactionManager()) - .reader { - if (readCallCount < readLimit) { - ++readCallCount - 1 - } else { - null - } - } - .writer {} - .faultTolerant() - .stream(TestStream()) - .build() - val jobExecution = JobExecution(jobInstance, jobParameters) - val stepExecution = jobExecution.createStepExecution(step.name) + val step = + simpleStepBuilder + .chunk(chunkSize) + .transactionManager(ResourcelessTransactionManager()) + .reader { + if (readCallCount < readLimit) { + ++readCallCount + 1 + } else { + null + } + }.writer {} + .faultTolerant() + .stream(TestStream()) + .build() + val jobExecution = JobExecution(0L, jobInstance, jobParameters) + val stepExecution = StepExecution(step.name, jobExecution) step.execute(stepExecution) // then @@ -1234,18 +1257,21 @@ internal class FaultTolerantStepBuilderDslTest { } @Test - fun testStreamIsDelegatedToChunkMonitorOnDslWhenCalledBeforeFaultTolerant() { + fun streamShouldRegisterWithChunkMonitorWhenConfiguredBeforeFaultTolerantOnDsl() { // given val chunkSize = 3 val readLimit = 20 var streamOpenCallCount = 0 var readCallCount = 0 - class TestStream : ItemStream, ItemReader { + class TestStream : + ItemStream, + ItemReader { override fun open(executionContext: ExecutionContext) { ++streamOpenCallCount Throwable().printStackTrace() - Throwable().stackTrace + Throwable() + .stackTrace .filter { it.className.endsWith("ChunkMonitor") } .also { assertThat(it).isNotEmpty @@ -1258,27 +1284,26 @@ internal class FaultTolerantStepBuilderDslTest { override fun close() { } - override fun read(): Int? { - return null - } + override fun read(): Int? = null } // when - val step = simpleStepBuilderDsl(chunkSize) { - stream(TestStream()) - reader { - if (readCallCount < readLimit) { - ++readCallCount - 1 - } else { - null + val step = + simpleStepBuilderDsl(chunkSize) { + stream(TestStream()) + reader { + if (readCallCount < readLimit) { + ++readCallCount + 1 + } else { + null + } } + writer {} + faultTolerant {} } - writer {} - faultTolerant {} - } - val jobExecution = JobExecution(jobInstance, jobParameters) - val stepExecution = jobExecution.createStepExecution(step.name) + val jobExecution = JobExecution(0L, jobInstance, jobParameters) + val stepExecution = StepExecution(step.name, jobExecution) step.execute(stepExecution) // then @@ -1288,17 +1313,20 @@ internal class FaultTolerantStepBuilderDslTest { } @Test - fun testStreamIsDelegatedToChunkMonitorOnDslWhenCalledAfterFaultTolerant() { + fun streamShouldRegisterWithChunkMonitorWhenConfiguredAfterFaultTolerantOnDsl() { // given val chunkSize = 3 val readLimit = 20 var streamOpenCallCount = 0 var readCallCount = 0 - class TestStream : ItemStream, ItemReader { + class TestStream : + ItemStream, + ItemReader { override fun open(executionContext: ExecutionContext) { ++streamOpenCallCount - Throwable().stackTrace + Throwable() + .stackTrace .filter { it.className.endsWith("ChunkMonitor") } .also { assertThat(it).isNotEmpty @@ -1311,28 +1339,27 @@ internal class FaultTolerantStepBuilderDslTest { override fun close() { } - override fun read(): Int? { - return null - } + override fun read(): Int? = null } // when - val step = simpleStepBuilderDsl(chunkSize) { - reader { - if (readCallCount < readLimit) { - ++readCallCount - 1 - } else { - null + val step = + simpleStepBuilderDsl(chunkSize) { + reader { + if (readCallCount < readLimit) { + ++readCallCount + 1 + } else { + null + } } + writer {} + faultTolerant { + } + stream(TestStream()) } - writer {} - faultTolerant { - } - stream(TestStream()) - } - val jobExecution = JobExecution(jobInstance, jobParameters) - val stepExecution = jobExecution.createStepExecution(step.name) + val jobExecution = JobExecution(0L, jobInstance, jobParameters) + val stepExecution = StepExecution(step.name, jobExecution) step.execute(stepExecution) // then @@ -1346,10 +1373,11 @@ internal class FaultTolerantStepBuilderDslTest { chunkSize: Int, init: SimpleStepBuilderDsl.() -> Unit, ): Step { - val dslContext = DslContext( - beanFactory = mockk(), - jobRepository = mockk(), - ) + val dslContext = + DslContext( + beanFactory = mockk(), + jobRepository = mockk(), + ) val stepBuilder = StepBuilder("testStep", mockk(relaxed = true)) val simpleStepBuilder = stepBuilder.chunk(chunkSize, ResourcelessTransactionManager()) diff --git a/spring-batch-plus-kotlin/src/test/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/step/FlowStepBuilderDslTest.kt b/spring-batch-plus-kotlin/src/test/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/step/FlowStepBuilderDslTest.kt index ddf234d5..89954cd0 100644 --- a/spring-batch-plus-kotlin/src/test/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/step/FlowStepBuilderDslTest.kt +++ b/spring-batch-plus-kotlin/src/test/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/step/FlowStepBuilderDslTest.kt @@ -22,18 +22,21 @@ import io.mockk.every import io.mockk.mockk import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.Test -import org.springframework.batch.core.Step +import org.springframework.batch.core.step.Step import org.springframework.batch.core.step.builder.FlowStepBuilder +/** + * Covers the delegation boundary between the flow-step DSL and its underlying builder. + */ internal class FlowStepBuilderDslTest { - @Test - fun testBuild() { + fun buildShouldReturnBuiltStepWhenInvoked() { // given val mockStep = mockk() - val flowStepBuilder = mockk(relaxed = true) { - every { build() } returns mockStep - } + val flowStepBuilder = + mockk(relaxed = true) { + every { build() } returns mockStep + } // when val actual = FlowStepBuilderDsl(mockk(), flowStepBuilder).build() diff --git a/spring-batch-plus-kotlin/src/test/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/step/JobStepBuilderDslTest.kt b/spring-batch-plus-kotlin/src/test/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/step/JobStepBuilderDslTest.kt index 812c790e..f8c5a1f5 100644 --- a/spring-batch-plus-kotlin/src/test/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/step/JobStepBuilderDslTest.kt +++ b/spring-batch-plus-kotlin/src/test/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/step/JobStepBuilderDslTest.kt @@ -23,50 +23,55 @@ import io.mockk.mockk import io.mockk.verify import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.Test -import org.springframework.batch.core.Step -import org.springframework.batch.core.launch.JobLauncher +import org.springframework.batch.core.launch.JobOperator +import org.springframework.batch.core.step.Step import org.springframework.batch.core.step.builder.JobStepBuilder import org.springframework.batch.core.step.job.JobParametersExtractor +/** + * Covers the delegation boundary between the job-step DSL and its underlying builder. + */ internal class JobStepBuilderDslTest { - @Test - fun testLauncher() { + fun operatorShouldConfigureJobStepBuilderWhenJobOperatorIsProvided() { // given val jobStepBuilder = mockk(relaxed = true) // when - val jobLauncher = mockk() - JobStepBuilderDsl(mockk(), jobStepBuilder).apply { - launcher(jobLauncher) - }.build() + val jobOperator = mockk() + JobStepBuilderDsl(mockk(), jobStepBuilder) + .apply { + operator(jobOperator) + }.build() // then - verify(exactly = 1) { jobStepBuilder.launcher(jobLauncher) } + verify(exactly = 1) { jobStepBuilder.operator(jobOperator) } } @Test - fun testParametersExtractor() { + fun parametersExtractorShouldConfigureJobStepBuilderWhenExtractorIsProvided() { // given val jobStepBuilder = mockk(relaxed = true) // when val jobParametersExtractor = mockk() - JobStepBuilderDsl(mockk(), jobStepBuilder).apply { - parametersExtractor(jobParametersExtractor) - }.build() + JobStepBuilderDsl(mockk(), jobStepBuilder) + .apply { + parametersExtractor(jobParametersExtractor) + }.build() // then verify(exactly = 1) { jobStepBuilder.parametersExtractor(jobParametersExtractor) } } @Test - fun testBuild() { + fun buildShouldReturnBuiltStepWhenInvoked() { // given val mockStep = mockk() - val jobStepBuilder = mockk(relaxed = true) { - every { build() } returns mockStep - } + val jobStepBuilder = + mockk(relaxed = true) { + every { build() } returns mockStep + } // when val actual = JobStepBuilderDsl(mockk(), jobStepBuilder).build() diff --git a/spring-batch-plus-kotlin/src/test/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/step/PartitionStepBuilderDslTest.kt b/spring-batch-plus-kotlin/src/test/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/step/PartitionStepBuilderDslTest.kt index 97d3525d..5c8bd847 100644 --- a/spring-batch-plus-kotlin/src/test/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/step/PartitionStepBuilderDslTest.kt +++ b/spring-batch-plus-kotlin/src/test/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/step/PartitionStepBuilderDslTest.kt @@ -21,582 +21,214 @@ package com.navercorp.spring.batch.plus.kotlin.configuration.step import com.navercorp.spring.batch.plus.kotlin.configuration.support.DslContext import io.mockk.every import io.mockk.mockk +import io.mockk.verify import org.assertj.core.api.Assertions.assertThat import org.assertj.core.api.Assertions.assertThatThrownBy -import org.junit.jupiter.api.Nested 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.JobInstance -import org.springframework.batch.core.JobParameters -import org.springframework.batch.core.Step -import org.springframework.batch.core.StepExecution import org.springframework.batch.core.partition.PartitionHandler +import org.springframework.batch.core.partition.Partitioner +import org.springframework.batch.core.partition.StepExecutionAggregator import org.springframework.batch.core.partition.StepExecutionSplitter -import org.springframework.batch.core.repository.JobRepository +import org.springframework.batch.core.step.Step import org.springframework.batch.core.step.builder.PartitionStepBuilder -import org.springframework.batch.core.step.builder.StepBuilder -import org.springframework.batch.item.ExecutionContext +import org.springframework.core.task.TaskExecutor +import java.util.UUID +import java.util.concurrent.ThreadLocalRandom +/** + * Covers partition builder delegation and the configuration required to build a partition step. + */ internal class PartitionStepBuilderDslTest { - - private val jobInstance = JobInstance(0L, "testJob") - - private val jobParameters = JobParameters() - - @Nested - inner class PartitionHandlerTest { - - @Test - fun testPartitionHandlerAndDummySettings() { - // given - var partitionHandlerCallCount = 0 - var taskExecutorCallCount = 0 - val stepBuilder = StepBuilder("testStep", mockk(relaxed = true)) - val partitionStepBuilder = PartitionStepBuilder(stepBuilder) - - // when - val step = partitionStepBuilder - .partitionHandler { _, _ -> - ++partitionHandlerCallCount - listOf() - } - // dummy - .step( - object : Step { - override fun getName(): String { - throw RuntimeException("Should not be called") - } - - override fun isAllowStartIfComplete(): Boolean { - throw RuntimeException("Should not be called") - } - - override fun getStartLimit(): Int { - throw RuntimeException("Should not be called") - } - - override fun execute(stepExecution: StepExecution) { - throw RuntimeException("Should not be called") - } - }, - ) - .taskExecutor { task -> - ++taskExecutorCallCount - task.run() - } - .gridSize(3) - .build() - val jobExecution = JobExecution(jobInstance, jobParameters) - val stepExecution = jobExecution.createStepExecution(step.name) - step.execute(stepExecution) - - // then - assertThat(stepExecution.status).isEqualTo(BatchStatus.COMPLETED) - assertThat(partitionHandlerCallCount).isEqualTo(1) - assertThat(taskExecutorCallCount).isEqualTo(0) - } - - @Test - fun testPartitionHandlerWithDirectOne() { - // given - val gridSize = 4 - var partitionHandlerCallCount = 0 - val splitter = object : StepExecutionSplitter { - override fun getStepName(): String = "splitStep" - - override fun split(stepExecution: StepExecution, gridSize: Int): Set { - val jobExecution = stepExecution.jobExecution - return (0 until gridSize) - .map { - jobExecution.createStepExecution("${stepName}$it") - } - .toSet() - } - } - - // when - val step = partitionStepBuilderDsl { - partitionHandler { splitter, stepExecution -> - ++partitionHandlerCallCount - splitter.split(stepExecution, gridSize) - .map { - it.apply { - exitStatus = ExitStatus.COMPLETED - status = BatchStatus.COMPLETED - } - } - } - splitter(splitter) + @Test + fun partitionHandlerShouldConfigurePartitionStepBuilderWhenHandlerIsProvided() { + // given + val partitionHandler = mockk() + val splitter = mockk() + val mockStep = mockk() + val partitionStepBuilder = + mockk(relaxed = true) { + every { build() } returns mockStep } - val jobExecution = JobExecution(jobInstance, jobParameters) - val stepExecution = jobExecution.createStepExecution(step.name) - step.execute(stepExecution) - // then - assertThat(partitionHandlerCallCount).isEqualTo(1) - assertThat(jobExecution.stepExecutions).hasSize(gridSize + 1) - assertThat(jobExecution.stepExecutions).allMatch { - it.status == BatchStatus.COMPLETED - } - assertThat(jobExecution.stepExecutions.find { it.stepName == "testStep" }).isNotNull - (0 until gridSize).forEach { gridNumber -> - assertThat(jobExecution.stepExecutions.find { it.stepName == "splitStep$gridNumber" }).isNotNull - } + // when + partitionStepBuilderDsl(partitionStepBuilder) { + partitionHandler(partitionHandler) + splitter(splitter) } - @Test - fun testPartitionHandlerWithTaskExecutorPartitionHandler() { - // given - var stepExecuteCallCount = 0 - var taskExecutorCallCount = 0 - val gridSize = 4 - val splitter = object : StepExecutionSplitter { - override fun getStepName(): String = "splitStep" - - override fun split(stepExecution: StepExecution, gridSize: Int): Set { - val jobExecution = stepExecution.jobExecution - return (0 until gridSize) - .map { - jobExecution.createStepExecution("${stepName}$it") - } - .toSet() - } - } - - // when - val step = partitionStepBuilderDsl { - partitionHandler { - step( - object : Step { - override fun getName(): String { - throw RuntimeException("Should not be called") - } - - override fun isAllowStartIfComplete(): Boolean { - throw RuntimeException("Should not be called") - } - - override fun getStartLimit(): Int { - throw RuntimeException("Should not be called") - } + // then + verify(exactly = 1) { partitionStepBuilder.partitionHandler(partitionHandler) } + } - override fun execute(stepExecution: StepExecution) { - ++stepExecuteCallCount - stepExecution.apply { - status = BatchStatus.COMPLETED - exitStatus = ExitStatus.COMPLETED - } - } - }, - ) - taskExecutor { task -> - ++taskExecutorCallCount - task.run() - } - gridSize(gridSize) - } - splitter(splitter) + @Test + fun partitionHandlerShouldConfigurePartitionStepBuilderWhenInitIsProvided() { + // given + val step = mockk() + val taskExecutor = mockk() + val gridSize = ThreadLocalRandom.current().nextInt(1, 10) + val splitter = mockk() + val mockStep = mockk() + val partitionStepBuilder = + mockk(relaxed = true) { + every { build() } returns mockStep } - val jobExecution = JobExecution(jobInstance, jobParameters) - val stepExecution = jobExecution.createStepExecution(step.name) - step.execute(stepExecution) - // then - assertThat(stepExecuteCallCount).isEqualTo(gridSize) - assertThat(taskExecutorCallCount).isEqualTo(gridSize) - assertThat(jobExecution.stepExecutions).hasSize(gridSize + 1) - assertThat(jobExecution.stepExecutions).allMatch { - it.status == BatchStatus.COMPLETED - } - assertThat(jobExecution.stepExecutions.find { it.stepName == "testStep" }).isNotNull - (0 until gridSize).forEach { gridNumber -> - assertThat(jobExecution.stepExecutions.find { it.stepName == "splitStep$gridNumber" }).isNotNull + // when + partitionStepBuilderDsl(partitionStepBuilder) { + partitionHandler { + step(step) + taskExecutor(taskExecutor) + gridSize(gridSize) } + splitter(splitter) } - @Test - fun testPartitionHandlerWithTaskExecutorPartitionHandlerWithoutTaskExecutor() { - // given - var stepExecuteCallCount = 0 - val gridSize = 4 - val splitter = object : StepExecutionSplitter { - override fun getStepName(): String = "splitStep" - - override fun split(stepExecution: StepExecution, gridSize: Int): Set { - val jobExecution = stepExecution.jobExecution - return (0 until gridSize) - .map { - jobExecution.createStepExecution("${stepName}$it") - } - .toSet() - } - } - - // when - val step = partitionStepBuilderDsl { - partitionHandler { - step( - object : Step { - override fun getName(): String { - throw RuntimeException("Should not be called") - } - - override fun isAllowStartIfComplete(): Boolean { - throw RuntimeException("Should not be called") - } - - override fun getStartLimit(): Int { - throw RuntimeException("Should not be called") - } + // then + verify(exactly = 1) { partitionStepBuilder.step(step) } + verify(exactly = 1) { partitionStepBuilder.taskExecutor(taskExecutor) } + verify(exactly = 1) { partitionStepBuilder.gridSize(gridSize) } + } - override fun execute(stepExecution: StepExecution) { - ++stepExecuteCallCount - stepExecution.apply { - status = BatchStatus.COMPLETED - exitStatus = ExitStatus.COMPLETED - } - } - }, - ) - gridSize(gridSize) - } - splitter(splitter) + @Test + fun splitterShouldConfigurePartitionStepBuilderWhenSplitterIsProvided() { + // given + val partitionHandler = mockk() + val splitter = mockk() + val mockStep = mockk() + val partitionStepBuilder = + mockk(relaxed = true) { + every { build() } returns mockStep } - val jobExecution = JobExecution(jobInstance, jobParameters) - val stepExecution = jobExecution.createStepExecution(step.name) - step.execute(stepExecution) - // then - assertThat(stepExecuteCallCount).isEqualTo(gridSize) - assertThat(jobExecution.stepExecutions).hasSize(gridSize + 1) - assertThat(jobExecution.stepExecutions).allMatch { - it.status == BatchStatus.COMPLETED - } - assertThat(jobExecution.stepExecutions.find { it.stepName == "testStep" }).isNotNull - (0 until gridSize).forEach { gridNumber -> - assertThat(jobExecution.stepExecutions.find { it.stepName == "splitStep$gridNumber" }).isNotNull - } + // when + partitionStepBuilderDsl(partitionStepBuilder) { + partitionHandler(partitionHandler) + splitter(splitter) } - @Test - fun testPartitionHandlerWithTaskExecutorPartitionHandlerWithoutGridSize() { - // given - var stepExecuteCallCount = 0 - var taskExecutorCallCount = 0 - val splitter = object : StepExecutionSplitter { - override fun getStepName(): String = "splitStep" - - override fun split(stepExecution: StepExecution, gridSize: Int): Set { - val jobExecution = stepExecution.jobExecution - return (0 until gridSize) - .map { - jobExecution.createStepExecution("${stepName}$it") - } - .toSet() - } - } - // org.springframework.batch.core.step.builder.PartitionStepBuilder.DEFAULT_GRID_SIZE - val defaultGridSize = 6 - - // when - val step = partitionStepBuilderDsl { - partitionHandler { - step( - object : Step { - override fun getName(): String { - throw RuntimeException("Should not be called") - } - - override fun isAllowStartIfComplete(): Boolean { - throw RuntimeException("Should not be called") - } - - override fun getStartLimit(): Int { - throw RuntimeException("Should not be called") - } + // then + verify(exactly = 1) { partitionStepBuilder.splitter(splitter) } + } - override fun execute(stepExecution: StepExecution) { - ++stepExecuteCallCount - stepExecution.apply { - status = BatchStatus.COMPLETED - exitStatus = ExitStatus.COMPLETED - } - } - }, - ) - taskExecutor { task -> - ++taskExecutorCallCount - task.run() - } - } - splitter(splitter) + @Test + fun splitterShouldConfigurePartitionStepBuilderWhenStepNameAndPartitionerAreProvided() { + // given + val stepName = UUID.randomUUID().toString() + val partitionHandler = mockk() + val partitioner = mockk() + val mockStep = mockk() + val partitionStepBuilder = + mockk(relaxed = true) { + every { build() } returns mockStep } - val jobExecution = JobExecution(jobInstance, jobParameters) - val stepExecution = jobExecution.createStepExecution(step.name) - step.execute(stepExecution) - // then - assertThat(stepExecuteCallCount).isEqualTo(defaultGridSize) - assertThat(taskExecutorCallCount).isEqualTo(defaultGridSize) - assertThat(jobExecution.stepExecutions).hasSize(defaultGridSize + 1) - assertThat(jobExecution.stepExecutions).allMatch { - it.status == BatchStatus.COMPLETED - } - assertThat(jobExecution.stepExecutions.find { it.stepName == "testStep" }).isNotNull - (0 until defaultGridSize).forEach { gridNumber -> - assertThat(jobExecution.stepExecutions.find { it.stepName == "splitStep$gridNumber" }).isNotNull - } + // when + partitionStepBuilderDsl(partitionStepBuilder) { + partitionHandler(partitionHandler) + splitter(stepName, partitioner) } - @Test - fun testPartitionHandlerWithTaskExecutorPartitionHandlerWithoutStep() { - // given - val splitter = object : StepExecutionSplitter { - override fun getStepName(): String = "splitStep" + // then + verify(exactly = 1) { partitionStepBuilder.partitioner(stepName, partitioner) } + } - override fun split(stepExecution: StepExecution, gridSize: Int): Set { - val jobExecution = stepExecution.jobExecution - return (0 until gridSize) - .map { - jobExecution.createStepExecution("${stepName}$it") - } - .toSet() - } + @Test + fun aggregatorShouldConfigurePartitionStepBuilderWhenAggregatorIsProvided() { + // given + val aggregator = mockk() + val partitionHandler = mockk() + val splitter = mockk() + val mockStep = mockk() + val partitionStepBuilder = + mockk(relaxed = true) { + every { build() } returns mockStep } - // when, then - assertThatThrownBy { - partitionStepBuilderDsl { - partitionHandler { - taskExecutor { task -> - task.run() - } - gridSize(3) - } - splitter(splitter) - } - }.hasMessageContaining("step is not set") + // when + partitionStepBuilderDsl(partitionStepBuilder) { + aggregator(aggregator) + partitionHandler(partitionHandler) + splitter(splitter) } - @Test - fun testWithoutPartitionHandler() { - // given - val splitter = object : StepExecutionSplitter { - override fun getStepName(): String = "splitStep" - - override fun split(stepExecution: StepExecution, gridSize: Int): Set { - val jobExecution = stepExecution.jobExecution - return (0 until gridSize) - .map { - jobExecution.createStepExecution("${stepName}$it") - } - .toSet() - } - } - - // when, then - assertThatThrownBy { - partitionStepBuilderDsl { - splitter(splitter) - } - }.hasMessageContaining("partitionHandler is not set") - } + // then + verify(exactly = 1) { partitionStepBuilder.aggregator(aggregator) } } - @Nested - inner class SplitterTest { - - @Test - fun testSplitterAndDummySettings() { - // given - var splitterCallCount = 0 - val dummyStepName = "dummyStepName" - var partitionerCallCount = 0 - val stepBuilder = StepBuilder("testStep", mockk(relaxed = true)) - val partitionStepBuilder = PartitionStepBuilder(stepBuilder) - - // when - val step = partitionStepBuilder - .partitionHandler { stepSplitter, stepExecution -> - stepSplitter.split(stepExecution, 1) - } - .splitter( - object : StepExecutionSplitter { - override fun getStepName(): String { - return "testStep" - } - - override fun split(stepExecution: StepExecution, gridSize: Int): Set { - ++splitterCallCount - return setOf() - } - }, - ) - // dummy - .partitioner(dummyStepName) { - ++partitionerCallCount - mapOf() - } - .build() - val jobExecution = JobExecution(jobInstance, jobParameters) - val stepExecution = jobExecution.createStepExecution(step.name) - step.execute(stepExecution) - - // then - assertThat(stepExecution.status).isEqualTo(BatchStatus.COMPLETED) - assertThat(splitterCallCount).isEqualTo(1) - assertThat(stepExecution.stepName).isEqualTo("testStep") - assertThat(partitionerCallCount).isEqualTo(0) - } - - @Test - fun testSplitterWithDirectOne() { - // given - var splitterCallCount = 0 - val gridSize = 4 - val partitionHandler = PartitionHandler { stepSplitter, stepExecution -> - stepSplitter.split(stepExecution, gridSize) - .map { - it.apply { - exitStatus = ExitStatus.COMPLETED - status = BatchStatus.COMPLETED - } - } - } - - // when - val step = partitionStepBuilderDsl { - partitionHandler(partitionHandler) - splitter( - - object : StepExecutionSplitter { - override fun getStepName(): String = "splitStep" - - override fun split(stepExecution: StepExecution, gridSize: Int): Set { - ++splitterCallCount - val jobExecution = stepExecution.jobExecution - return (0 until gridSize) - .map { - jobExecution.createStepExecution("${stepName}$it") - } - .toSet() - } - }, - ) - } - val jobExecution = JobExecution(jobInstance, jobParameters) - val stepExecution = jobExecution.createStepExecution(step.name) - step.execute(stepExecution) - - // then - assertThat(splitterCallCount).isEqualTo(1) - assertThat(jobExecution.stepExecutions).hasSize(gridSize + 1) - assertThat(jobExecution.stepExecutions).allMatch { - it.status == BatchStatus.COMPLETED - } - assertThat(jobExecution.stepExecutions.find { it.stepName == "testStep" }).isNotNull - (0 until gridSize).forEach { gridNumber -> - assertThat(jobExecution.stepExecutions.find { it.stepName == "splitStep$gridNumber" }).isNotNull - } - } - - @Test - fun testSplitterWithSimpleStepExecutionSplitter() { - // given - var partitionerCallCount = 0 - val gridSize = 4 - val partitionHandler = PartitionHandler { stepSplitter, stepExecution -> - stepSplitter.split(stepExecution, gridSize) - .map { - it.apply { - exitStatus = ExitStatus.COMPLETED - status = BatchStatus.COMPLETED - } - } + @Test + fun buildShouldReturnBuiltStepWhenRequiredConfigurationIsProvided() { + // given + val partitionHandler = mockk() + val splitter = mockk() + val mockStep = mockk() + val partitionStepBuilder = + mockk(relaxed = true) { + every { build() } returns mockStep } - // when - val step = partitionStepBuilderDsl { + // when + val actual = + partitionStepBuilderDsl(partitionStepBuilder) { partitionHandler(partitionHandler) - splitter("splitStep") { gridSize -> - ++partitionerCallCount - (0 until gridSize).map { - "$it" to ExecutionContext() - }.toMap() - } - } - val jobExecution = JobExecution(jobInstance, jobParameters) - val stepExecution = jobExecution.createStepExecution(step.name) - step.execute(stepExecution) - - // then - assertThat(partitionerCallCount).isEqualTo(1) - assertThat(jobExecution.stepExecutions).hasSize(gridSize + 1) - assertThat(jobExecution.stepExecutions).allMatch { - it.status == BatchStatus.COMPLETED - } - assertThat(jobExecution.stepExecutions.find { it.stepName == "testStep" }).isNotNull - (0 until gridSize).forEach { gridNumber -> - assertThat(jobExecution.stepExecutions.find { it.stepName == "splitStep:$gridNumber" }).isNotNull + splitter(splitter) } - } - @Test - fun testWithoutSplitter() { - // given - val partitionHandler = PartitionHandler { stepSplitter, stepExecution -> - stepSplitter.split(stepExecution, 2_000_000_000) - .map { - it.apply { - exitStatus = ExitStatus.COMPLETED - status = BatchStatus.COMPLETED - } - } - } + // then + assertThat(actual).isEqualTo(mockStep) + } - // when, then - assertThatThrownBy { - partitionStepBuilderDsl { - partitionHandler(partitionHandler) + @Test + fun partitionHandlerShouldThrowIllegalStateExceptionWhenStepIsNotConfigured() { + // given + val taskExecutor = mockk() + val gridSize = ThreadLocalRandom.current().nextInt(1, 10) + val partitionStepBuilder = mockk(relaxed = true) + + // when, then + assertThatThrownBy { + PartitionStepBuilderDsl(mockk(), partitionStepBuilder) + .partitionHandler { + taskExecutor(taskExecutor) + gridSize(gridSize) } - }.hasMessageContaining("splitter is not set") - } + }.isInstanceOf(IllegalStateException::class.java) } @Test - fun testAggregator() { + fun buildShouldThrowIllegalStateExceptionWhenPartitionHandlerIsNotConfigured() { // given - var aggregatorCallCount = 0 - - // when - val step = partitionStepBuilderDsl { - aggregator { _, _ -> - ++aggregatorCallCount - } - partitionHandler(mockk(relaxed = true)) - splitter(mockk()) - } - val jobExecution = JobExecution(jobInstance, jobParameters) - val stepExecution = jobExecution.createStepExecution(step.name) - step.execute(stepExecution) + val splitter = mockk() + val partitionStepBuilder = mockk(relaxed = true) - // then - assertThat(stepExecution.status).isEqualTo(BatchStatus.COMPLETED) - assertThat(aggregatorCallCount).isEqualTo(1) + // when, then + assertThatThrownBy { + PartitionStepBuilderDsl(mockk(), partitionStepBuilder) + .apply { + splitter(splitter) + }.build() + }.isInstanceOf(IllegalStateException::class.java) } - private fun partitionStepBuilderDsl(init: PartitionStepBuilderDsl.() -> Unit): Step { - val dslContext = DslContext( - beanFactory = mockk(), - jobRepository = mockk(), - ) - val mockk = mockk(relaxed = true) { - every { getLastStepExecution(any(), any()) } returns null - } - val stepBuilder = StepBuilder("testStep", mockk) + @Test + fun buildShouldThrowIllegalStateExceptionWhenSplitterIsNotConfigured() { + // given + val partitionHandler = mockk() + val partitionStepBuilder = mockk(relaxed = true) - return PartitionStepBuilderDsl(dslContext, PartitionStepBuilder(stepBuilder)).apply(init).build() + // when, then + assertThatThrownBy { + PartitionStepBuilderDsl(mockk(), partitionStepBuilder) + .apply { + partitionHandler(partitionHandler) + }.build() + }.isInstanceOf(IllegalStateException::class.java) } + + private fun partitionStepBuilderDsl( + partitionStepBuilder: PartitionStepBuilder, + init: PartitionStepBuilderDsl.() -> Unit, + ): Step = + PartitionStepBuilderDsl(mockk(), partitionStepBuilder) + .apply(init) + .build() } diff --git a/spring-batch-plus-kotlin/src/test/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/step/SimpleStepBuilderDslTest.kt b/spring-batch-plus-kotlin/src/test/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/step/SimpleStepBuilderDslTest.kt index c459c7e7..76534ff3 100644 --- a/spring-batch-plus-kotlin/src/test/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/step/SimpleStepBuilderDslTest.kt +++ b/spring-batch-plus-kotlin/src/test/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/step/SimpleStepBuilderDslTest.kt @@ -16,6 +16,8 @@ * limitations under the License. */ +@file:Suppress("DEPRECATION") + package com.navercorp.spring.batch.plus.kotlin.configuration.step import io.mockk.every @@ -26,95 +28,102 @@ import org.assertj.core.api.Assertions.assertThatThrownBy import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.ChunkListener -import org.springframework.batch.core.ItemProcessListener -import org.springframework.batch.core.ItemReadListener -import org.springframework.batch.core.ItemWriteListener -import org.springframework.batch.core.JobExecution -import org.springframework.batch.core.JobInstance -import org.springframework.batch.core.JobParameters +import org.springframework.batch.core.job.JobExecution +import org.springframework.batch.core.job.JobInstance +import org.springframework.batch.core.job.parameters.JobParameters +import org.springframework.batch.core.listener.ChunkListener +import org.springframework.batch.core.listener.ItemProcessListener +import org.springframework.batch.core.listener.ItemReadListener +import org.springframework.batch.core.listener.ItemWriteListener +import org.springframework.batch.core.step.StepExecution import org.springframework.batch.core.step.builder.SimpleStepBuilder import org.springframework.batch.core.step.builder.StepBuilder 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.ItemStream -import org.springframework.batch.item.ItemWriter -import org.springframework.batch.repeat.RepeatCallback -import org.springframework.batch.repeat.RepeatOperations -import org.springframework.batch.repeat.RepeatStatus -import org.springframework.batch.repeat.exception.ExceptionHandler -import org.springframework.batch.repeat.support.RepeatTemplate -import org.springframework.batch.support.transaction.ResourcelessTransactionManager +import org.springframework.batch.infrastructure.item.ItemProcessor +import org.springframework.batch.infrastructure.item.ItemReader +import org.springframework.batch.infrastructure.item.ItemStream +import org.springframework.batch.infrastructure.item.ItemWriter +import org.springframework.batch.infrastructure.repeat.RepeatCallback +import org.springframework.batch.infrastructure.repeat.RepeatOperations +import org.springframework.batch.infrastructure.repeat.RepeatStatus +import org.springframework.batch.infrastructure.repeat.exception.ExceptionHandler +import org.springframework.batch.infrastructure.repeat.support.RepeatTemplate +import org.springframework.batch.infrastructure.support.transaction.ResourcelessTransactionManager import org.springframework.core.task.SyncTaskExecutor import org.springframework.core.task.TaskExecutor import org.springframework.transaction.interceptor.TransactionAttribute import java.util.UUID import java.util.concurrent.ThreadLocalRandom +/** + * Covers the deprecated simple-step delegation boundary and its legacy repeat-operation precedence. + */ internal class SimpleStepBuilderDslTest { - @Test - fun testReader() { + fun readerShouldConfigureSimpleStepBuilderWhenReaderIsProvided() { // given val simpleStepBuilder = mockk>(relaxed = true) // when val itemReader = mockk>() - SimpleStepBuilderDsl(mockk(), simpleStepBuilder).apply { - reader(itemReader) - }.build() + SimpleStepBuilderDsl(mockk(), simpleStepBuilder) + .apply { + reader(itemReader) + }.build() // then verify(exactly = 1) { simpleStepBuilder.reader(itemReader) } } @Test - fun testProcessor() { + fun processorShouldConfigureSimpleStepBuilderWhenProcessorIsProvided() { // given val simpleStepBuilder = mockk>(relaxed = true) // when val itemProcessor = mockk>() - SimpleStepBuilderDsl(mockk(), simpleStepBuilder).apply { - processor(itemProcessor) - }.build() + SimpleStepBuilderDsl(mockk(), simpleStepBuilder) + .apply { + processor(itemProcessor) + }.build() // then verify(exactly = 1) { simpleStepBuilder.processor(itemProcessor) } } @Test - fun testWriter() { + fun writerShouldConfigureSimpleStepBuilderWhenWriterIsProvided() { // given val simpleStepBuilder = mockk>(relaxed = true) // when val itemWriter = mockk>() - SimpleStepBuilderDsl(mockk(), simpleStepBuilder).apply { - writer(itemWriter) - }.build() + SimpleStepBuilderDsl(mockk(), simpleStepBuilder) + .apply { + writer(itemWriter) + }.build() // then verify(exactly = 1) { simpleStepBuilder.writer(itemWriter) } } @Test - fun testReaderIsTransactionalQueue() { + fun readerIsTransactionalQueueShouldConfigureSimpleStepBuilderWhenInvoked() { // given val simpleStepBuilder = mockk>(relaxed = true) // when - SimpleStepBuilderDsl(mockk(), simpleStepBuilder).apply { - readerIsTransactionalQueue() - }.build() + SimpleStepBuilderDsl(mockk(), simpleStepBuilder) + .apply { + readerIsTransactionalQueue() + }.build() // then verify(exactly = 1) { simpleStepBuilder.readerIsTransactionalQueue() } } @Test - fun testObjectListener() { + fun listenerShouldConfigureSimpleStepBuilderWhenObjectListenerIsProvided() { // given val simpleStepBuilder = mockk>(relaxed = true) @@ -122,99 +131,106 @@ internal class SimpleStepBuilderDslTest { // when val testListener = TestListener() - SimpleStepBuilderDsl(mockk(), simpleStepBuilder).apply { - listener(testListener) - }.build() + SimpleStepBuilderDsl(mockk(), simpleStepBuilder) + .apply { + listener(testListener) + }.build() // then verify(exactly = 1) { simpleStepBuilder.listener(testListener) } } @Test - fun testReadListener() { + fun listenerShouldConfigureSimpleStepBuilderWhenItemReadListenerIsProvided() { // given val simpleStepBuilder = mockk>(relaxed = true) // when val itemReadListener = mockk>() - SimpleStepBuilderDsl(mockk(), simpleStepBuilder).apply { - listener(itemReadListener) - }.build() + SimpleStepBuilderDsl(mockk(), simpleStepBuilder) + .apply { + listener(itemReadListener) + }.build() // then verify(exactly = 1) { simpleStepBuilder.listener(itemReadListener) } } @Test - fun testWriteListener() { + fun listenerShouldConfigureSimpleStepBuilderWhenItemWriteListenerIsProvided() { // given val simpleStepBuilder = mockk>(relaxed = true) // when val itemWriteListener = mockk>() - SimpleStepBuilderDsl(mockk(), simpleStepBuilder).apply { - listener(itemWriteListener) - }.build() + SimpleStepBuilderDsl(mockk(), simpleStepBuilder) + .apply { + listener(itemWriteListener) + }.build() // then verify(exactly = 1) { simpleStepBuilder.listener(itemWriteListener) } } @Test - fun testProcessListener() { + fun listenerShouldConfigureSimpleStepBuilderWhenItemProcessListenerIsProvided() { // given val simpleStepBuilder = mockk>(relaxed = true) // when val itemProcessListener = mockk>() - SimpleStepBuilderDsl(mockk(), simpleStepBuilder).apply { - listener(itemProcessListener) - }.build() + SimpleStepBuilderDsl(mockk(), simpleStepBuilder) + .apply { + listener(itemProcessListener) + }.build() // then verify(exactly = 1) { simpleStepBuilder.listener(itemProcessListener) } } @Test - fun testChunkListener() { + fun listenerShouldConfigureSimpleStepBuilderWhenChunkListenerIsProvided() { // given val simpleStepBuilder = mockk>(relaxed = true) // when - val chunkListener = mockk() - SimpleStepBuilderDsl(mockk(), simpleStepBuilder).apply { - listener(chunkListener) - }.build() + val chunkListener = mockk>() + SimpleStepBuilderDsl(mockk(), simpleStepBuilder) + .apply { + listener(chunkListener) + }.build() // then verify(exactly = 1) { simpleStepBuilder.listener(chunkListener) } } @Test - fun testStream() { + fun streamShouldConfigureSimpleStepBuilderWhenItemStreamIsProvided() { // given val simpleStepBuilder = mockk>(relaxed = true) // when val itemStream = mockk() - SimpleStepBuilderDsl(mockk(), simpleStepBuilder).apply { - stream(itemStream) - }.build() + SimpleStepBuilderDsl(mockk(), simpleStepBuilder) + .apply { + stream(itemStream) + }.build() // then verify(exactly = 1) { simpleStepBuilder.stream(itemStream) } } @Test - fun testTaskExecutor() { + fun taskExecutorShouldConfigureSimpleStepBuilderWhenExecutorIsProvided() { // given val simpleStepBuilder = mockk>(relaxed = true) // when val taskExecutor = mockk() - SimpleStepBuilderDsl(mockk(), simpleStepBuilder).apply { - taskExecutor(taskExecutor) - }.build() + SimpleStepBuilderDsl(mockk(), simpleStepBuilder) + .apply { + taskExecutor(taskExecutor) + }.build() // then verify(exactly = 1) { simpleStepBuilder.taskExecutor(taskExecutor) } @@ -222,74 +238,61 @@ internal class SimpleStepBuilderDslTest { @Suppress("DEPRECATION") @Test - fun testThrottleLimit() { - // given - val simpleStepBuilder = mockk>(relaxed = true) - - // when - val taskExecutor = mockk() - val limit = ThreadLocalRandom.current().nextInt() - SimpleStepBuilderDsl(mockk(), simpleStepBuilder).apply { - taskExecutor(taskExecutor) - throttleLimit(limit) - }.build() - - // then - verify(exactly = 1) { simpleStepBuilder.throttleLimit(limit) } - } - - @Test - fun testExceptionHandler() { + fun exceptionHandlerShouldConfigureSimpleStepBuilderWhenHandlerIsProvided() { // given val simpleStepBuilder = mockk>(relaxed = true) // when val exceptionHandler = mockk() - SimpleStepBuilderDsl(mockk(), simpleStepBuilder).apply { - exceptionHandler(exceptionHandler) - }.build() + SimpleStepBuilderDsl(mockk(), simpleStepBuilder) + .apply { + exceptionHandler(exceptionHandler) + }.build() // then verify(exactly = 1) { simpleStepBuilder.exceptionHandler(exceptionHandler) } } @Test - fun testStepOperations() { + fun stepOperationsShouldConfigureSimpleStepBuilderWhenRepeatOperationsAreProvided() { // given val simpleStepBuilder = mockk>(relaxed = true) // when val repeatOperations = mockk() - SimpleStepBuilderDsl(mockk(), simpleStepBuilder).apply { - stepOperations(repeatOperations) - }.build() + SimpleStepBuilderDsl(mockk(), simpleStepBuilder) + .apply { + stepOperations(repeatOperations) + }.build() // then verify(exactly = 1) { simpleStepBuilder.stepOperations(repeatOperations) } } @Test - fun testTransactionAttribute() { + fun transactionAttributeShouldConfigureSimpleStepBuilderWhenTransactionAttributeIsProvided() { // given val simpleStepBuilder = mockk>(relaxed = true) // when val transactionAttribute = mockk() - SimpleStepBuilderDsl(mockk(), simpleStepBuilder).apply { - transactionAttribute(transactionAttribute) - }.build() + SimpleStepBuilderDsl(mockk(), simpleStepBuilder) + .apply { + transactionAttribute(transactionAttribute) + }.build() // then verify(exactly = 1) { simpleStepBuilder.transactionAttribute(transactionAttribute) } } @Test - fun testBuild() { + fun buildShouldReturnBuiltStepWhenInvoked() { // given val mockStep = mockk() - val taskletStepBuilder = mockk>(relaxed = true) { - every { build() } returns mockStep - } + val taskletStepBuilder = + mockk>(relaxed = true) { + every { build() } returns mockStep + } // when val actual = SimpleStepBuilderDsl(mockk(), taskletStepBuilder).build() @@ -299,54 +302,41 @@ internal class SimpleStepBuilderDslTest { } @Test - fun testBuildWithSettingStepOperationsAndTaskExecutor() { + fun buildShouldRejectTaskExecutorWhenStepOperationsAreConfigured() { // given val simpleStepBuilder = mockk>(relaxed = true) // when, then assertThatThrownBy { - SimpleStepBuilderDsl(mockk(), simpleStepBuilder).apply { - stepOperations(RepeatTemplate()) - taskExecutor(SyncTaskExecutor()) - }.build() + SimpleStepBuilderDsl(mockk(), simpleStepBuilder) + .apply { + stepOperations(RepeatTemplate()) + taskExecutor(SyncTaskExecutor()) + }.build() }.hasMessageContaining("taskExecutor is redundant") } @Test - fun testBuildWithSettingStepOperationsAndExceptionHandler() { + fun buildShouldRejectExceptionHandlerWhenStepOperationsAreConfigured() { // given val simpleStepBuilder = mockk>(relaxed = true) // when, then assertThatThrownBy { - SimpleStepBuilderDsl(mockk(), simpleStepBuilder).apply { - stepOperations(RepeatTemplate()) - exceptionHandler { _, e -> - throw e - } - }.build() + SimpleStepBuilderDsl(mockk(), simpleStepBuilder) + .apply { + stepOperations(RepeatTemplate()) + exceptionHandler { _, e -> + throw e + } + }.build() }.hasMessageContaining("exceptionHandler is redundant") } - @Suppress("DEPRECATION") - @Test - fun testBuildWithSettingThrottleLimitWhenNoTaskExecutor() { - // given - val simpleStepBuilder = mockk>(relaxed = true) - - // when, then - assertThatThrownBy { - SimpleStepBuilderDsl(mockk(), simpleStepBuilder).apply { - throttleLimit(3) - }.build() - }.hasMessageContaining("throttleLimit is redundant") - } - @Nested inner class RedundancyCheck { - @Test - fun testStepOperationsAndRedundantSettings() { + fun stepOperationsShouldTakePrecedenceWhenTaskExecutorAndExceptionHandlerAreConfigured() { // given val chunkSize = 3 val readLimit = 20 @@ -357,38 +347,34 @@ internal class SimpleStepBuilderDslTest { val stepBuilder = StepBuilder(UUID.randomUUID().toString(), mockk(relaxed = true)) // when - val step = stepBuilder - .chunk(chunkSize, ResourcelessTransactionManager()) - .reader { - if (readCallCount < readLimit) { - ++readCallCount - 1 - } else { - null - } - } - .writer { } - .stepOperations( - object : RepeatTemplate() { - override fun iterate(callback: RepeatCallback): RepeatStatus { - ++stepOperationCallCount - return super.iterate(callback) + val step = + stepBuilder + .chunk(chunkSize, ResourcelessTransactionManager()) + .reader { + if (readCallCount < readLimit) { + ++readCallCount + 1 + } else { + null } - }, - ) - // redundant - .taskExecutor { task -> - ++taskExecutorCallCount - task.run() - } - .exceptionHandler { _, e -> - ++exceptionHandlerCallCount - throw e - } - .build() + }.writer { } + .stepOperations( + object : RepeatTemplate() { + override fun iterate(callback: RepeatCallback): RepeatStatus { + ++stepOperationCallCount + return super.iterate(callback) + } + }, + ).taskExecutor { task -> + ++taskExecutorCallCount + task.run() + }.exceptionHandler { _, e -> + ++exceptionHandlerCallCount + throw e + }.build() val jobInstance = JobInstance(ThreadLocalRandom.current().nextLong(), UUID.randomUUID().toString()) - val jobExecution = JobExecution(jobInstance, JobParameters()) - val stepExecution = jobExecution.createStepExecution(step.name) + val jobExecution = JobExecution(0L, jobInstance, JobParameters()) + val stepExecution = StepExecution(step.name, jobExecution) step.execute(stepExecution) // then @@ -398,49 +384,5 @@ internal class SimpleStepBuilderDslTest { assertThat(taskExecutorCallCount).isEqualTo(0) assertThat(exceptionHandlerCallCount).isEqualTo(0) } - - @Suppress("DEPRECATION") - @Test - fun testThrottleLimitAndRedundantSettings() { - // given - val readLimit = 10000 - val chunkSize = 1 - var readCallCount = 0 - var processCallCount = 0 - var writeCallCount = 0 - val stepBuilder = StepBuilder(UUID.randomUUID().toString(), mockk(relaxed = true)) - - // when - val step = stepBuilder - .chunk(chunkSize, ResourcelessTransactionManager()) - .reader { - if (readCallCount < readLimit) { - ++readCallCount - 1 - } else { - null - } - } - .processor { - ++processCallCount - it - } - .writer { - ++writeCallCount - } - .throttleLimit(100) - .build() - val jobInstance = JobInstance(ThreadLocalRandom.current().nextLong(), UUID.randomUUID().toString()) - val jobExecution = JobExecution(jobInstance, JobParameters()) - val stepExecution = jobExecution.createStepExecution(step.name) - step.execute(stepExecution) - - // then - assertThat(stepExecution.status).isEqualTo(BatchStatus.COMPLETED) - // if throttleLimit is applied to executor, it should be different by race condition - assertThat(readCallCount).isEqualTo(readLimit) - assertThat(processCallCount).isEqualTo(readLimit) - assertThat(writeCallCount).isEqualTo(10000) - } } } diff --git a/spring-batch-plus-kotlin/src/test/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/step/TaskletStepBuilderDslTest.kt b/spring-batch-plus-kotlin/src/test/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/step/TaskletStepBuilderDslTest.kt index 646da3ea..2e413ef0 100644 --- a/spring-batch-plus-kotlin/src/test/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/step/TaskletStepBuilderDslTest.kt +++ b/spring-batch-plus-kotlin/src/test/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/step/TaskletStepBuilderDslTest.kt @@ -23,47 +23,39 @@ import io.mockk.mockk import io.mockk.verify import org.assertj.core.api.Assertions.assertThat import org.assertj.core.api.Assertions.assertThatThrownBy -import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test -import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.ChunkListener -import org.springframework.batch.core.JobExecution -import org.springframework.batch.core.JobInstance -import org.springframework.batch.core.JobParameters -import org.springframework.batch.core.step.builder.StepBuilder +import org.springframework.batch.core.listener.ChunkListener import org.springframework.batch.core.step.builder.TaskletStepBuilder import org.springframework.batch.core.step.tasklet.TaskletStep -import org.springframework.batch.item.ItemStream -import org.springframework.batch.repeat.RepeatCallback -import org.springframework.batch.repeat.RepeatOperations -import org.springframework.batch.repeat.RepeatStatus -import org.springframework.batch.repeat.exception.ExceptionHandler -import org.springframework.batch.repeat.support.RepeatTemplate -import org.springframework.batch.support.transaction.ResourcelessTransactionManager +import org.springframework.batch.infrastructure.item.ItemStream +import org.springframework.batch.infrastructure.repeat.RepeatOperations +import org.springframework.batch.infrastructure.repeat.exception.ExceptionHandler import org.springframework.core.task.TaskExecutor +import org.springframework.transaction.PlatformTransactionManager import org.springframework.transaction.interceptor.TransactionAttribute -import java.util.UUID -import java.util.concurrent.ThreadLocalRandom +/** + * Covers tasklet-step option delegation and mutually exclusive repeat-operation settings. + */ internal class TaskletStepBuilderDslTest { - @Test - fun testChunkListener() { + fun listenerShouldConfigureTaskletStepBuilderWhenChunkListenerIsProvided() { // given val taskletStepBuilder = mockk(relaxed = true) // when - val chunkListener = mockk() - TaskletStepBuilderDsl(mockk(), taskletStepBuilder).apply { - listener(chunkListener) - }.build() + val chunkListener = mockk>() + TaskletStepBuilderDsl(mockk(), taskletStepBuilder) + .apply { + listener(chunkListener) + }.build() // then verify(exactly = 1) { taskletStepBuilder.listener(chunkListener) } } @Test - fun testObjectListener() { + fun listenerShouldConfigureTaskletStepBuilderWhenObjectListenerIsProvided() { // given val taskletStepBuilder = mockk(relaxed = true) @@ -71,96 +63,120 @@ internal class TaskletStepBuilderDslTest { // when val testListener = TestListener() - TaskletStepBuilderDsl(mockk(), taskletStepBuilder).apply { - listener(testListener) - }.build() + TaskletStepBuilderDsl(mockk(), taskletStepBuilder) + .apply { + listener(testListener) + }.build() // then verify(exactly = 1) { taskletStepBuilder.listener(testListener) } } @Test - fun testStream() { + fun streamShouldConfigureTaskletStepBuilderWhenItemStreamIsProvided() { // given val taskletStepBuilder = mockk(relaxed = true) // when val itemStream = mockk() - TaskletStepBuilderDsl(mockk(), taskletStepBuilder).apply { - stream(itemStream) - }.build() + TaskletStepBuilderDsl(mockk(), taskletStepBuilder) + .apply { + stream(itemStream) + }.build() // then verify(exactly = 1) { taskletStepBuilder.stream(itemStream) } } + @Suppress("DEPRECATION") @Test - fun testTaskExecutor() { + fun taskExecutorShouldConfigureTaskletStepBuilderWhenExecutorIsProvided() { // given val taskletStepBuilder = mockk(relaxed = true) // when val taskExecutor = mockk() - TaskletStepBuilderDsl(mockk(), taskletStepBuilder).apply { - taskExecutor(taskExecutor) - }.build() + TaskletStepBuilderDsl(mockk(), taskletStepBuilder) + .apply { + taskExecutor(taskExecutor) + }.build() // then verify(exactly = 1) { taskletStepBuilder.taskExecutor(taskExecutor) } } @Test - fun testExceptionHandler() { + fun exceptionHandlerShouldConfigureTaskletStepBuilderWhenHandlerIsProvided() { // given val taskletStepBuilder = mockk(relaxed = true) // when val exceptionHandler = mockk() - TaskletStepBuilderDsl(mockk(), taskletStepBuilder).apply { - exceptionHandler(exceptionHandler) - }.build() + TaskletStepBuilderDsl(mockk(), taskletStepBuilder) + .apply { + exceptionHandler(exceptionHandler) + }.build() // then verify(exactly = 1) { taskletStepBuilder.exceptionHandler(exceptionHandler) } } @Test - fun testStepOperations() { + fun stepOperationsShouldConfigureTaskletStepBuilderWhenRepeatOperationsAreProvided() { // given val taskletStepBuilder = mockk(relaxed = true) // when val repeatOperations = mockk() - TaskletStepBuilderDsl(mockk(), taskletStepBuilder).apply { - stepOperations(repeatOperations) - }.build() + TaskletStepBuilderDsl(mockk(), taskletStepBuilder) + .apply { + stepOperations(repeatOperations) + }.build() // then verify(exactly = 1) { taskletStepBuilder.stepOperations(repeatOperations) } } @Test - fun testTransactionalAttribute() { + fun transactionManagerShouldConfigureTaskletStepBuilderWhenTransactionManagerIsProvided() { + // given + val taskletStepBuilder = mockk(relaxed = true) + + // when + val transactionManager = mockk() + TaskletStepBuilderDsl(mockk(), taskletStepBuilder) + .apply { + transactionManager(transactionManager) + }.build() + + // then + verify(exactly = 1) { taskletStepBuilder.transactionManager(transactionManager) } + } + + @Test + fun transactionAttributeShouldConfigureTaskletStepBuilderWhenTransactionAttributeIsProvided() { // given val taskletStepBuilder = mockk(relaxed = true) // when val transactionAttribute = mockk() - TaskletStepBuilderDsl(mockk(), taskletStepBuilder).apply { - transactionAttribute(transactionAttribute) - }.build() + TaskletStepBuilderDsl(mockk(), taskletStepBuilder) + .apply { + transactionAttribute(transactionAttribute) + }.build() // then verify(exactly = 1) { taskletStepBuilder.transactionAttribute(transactionAttribute) } } @Test - fun testBuild() { + fun buildShouldReturnBuiltStepWhenInvoked() { // given val mockStep = mockk() - val taskletStepBuilder = mockk(relaxed = true) { - every { build() } returns mockStep - } + val taskletStepBuilder = + mockk(relaxed = true) { + every { build() } returns mockStep + } // when val actual = TaskletStepBuilderDsl(mockk(), taskletStepBuilder).build() @@ -169,8 +185,9 @@ internal class TaskletStepBuilderDslTest { assertThat(actual).isEqualTo(mockStep) } + @Suppress("DEPRECATION") @Test - fun testBuildWithSettingStepOperationsAndTaskExecutor() { + fun buildShouldRejectTaskExecutorWhenStepOperationsAreConfigured() { // given val taskletStepBuilder = mockk(relaxed = true) @@ -178,15 +195,16 @@ internal class TaskletStepBuilderDslTest { val repeatOperations = mockk() val taskExecutor = mockk() assertThatThrownBy { - TaskletStepBuilderDsl(mockk(), taskletStepBuilder).apply { - stepOperations(repeatOperations) - taskExecutor(taskExecutor) - }.build() + TaskletStepBuilderDsl(mockk(), taskletStepBuilder) + .apply { + stepOperations(repeatOperations) + taskExecutor(taskExecutor) + }.build() }.hasMessageContaining("taskExecutor is redundant") } @Test - fun testBuildWithSettingStepOperationsAndExceptionHandler() { + fun buildShouldRejectExceptionHandlerWhenStepOperationsAreConfigured() { // given val taskletStepBuilder = mockk(relaxed = true) @@ -194,55 +212,11 @@ internal class TaskletStepBuilderDslTest { val repeatOperations = mockk() val exceptionHandler = mockk() assertThatThrownBy { - TaskletStepBuilderDsl(mockk(), taskletStepBuilder).apply { - stepOperations(repeatOperations) - exceptionHandler(exceptionHandler) - }.build() + TaskletStepBuilderDsl(mockk(), taskletStepBuilder) + .apply { + stepOperations(repeatOperations) + exceptionHandler(exceptionHandler) + }.build() }.hasMessageContaining("exceptionHandler is redundant") } - - @Nested - inner class RedundancyCheck { - - @Test - fun testStepOperationsAndRedundantSettings() { - // given - var iterateCount = 0 - var taskExecutorCallCount = 0 - var exceptionHandlerCallCount = 0 - val stepBuilder = StepBuilder(UUID.randomUUID().toString(), mockk(relaxed = true)) - - // when - val step = stepBuilder - .tasklet({ _, _ -> RepeatStatus.FINISHED }, ResourcelessTransactionManager()) - .stepOperations( - object : RepeatTemplate() { - override fun iterate(callback: RepeatCallback): RepeatStatus { - ++iterateCount - return super.iterate(callback) - } - }, - ) - // redundant - .taskExecutor { task -> - ++taskExecutorCallCount - task.run() - } - .exceptionHandler { _, e -> - ++exceptionHandlerCallCount - throw e - } - .build() - val jobInstance = JobInstance(ThreadLocalRandom.current().nextLong(), UUID.randomUUID().toString()) - val jobExecution = JobExecution(jobInstance, JobParameters()) - val stepExecution = jobExecution.createStepExecution(step.name) - step.execute(stepExecution) - - // then - assertThat(stepExecution.status).isEqualTo(BatchStatus.COMPLETED) - assertThat(iterateCount).isEqualTo(1) - assertThat(taskExecutorCallCount).isEqualTo(0) - assertThat(exceptionHandlerCallCount).isEqualTo(0) - } - } } diff --git a/spring-batch-plus-kotlin/src/test/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/support/LazyConfigurerTest.kt b/spring-batch-plus-kotlin/src/test/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/support/LazyConfigurerTest.kt index 82ad9e31..ab2c4456 100644 --- a/spring-batch-plus-kotlin/src/test/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/support/LazyConfigurerTest.kt +++ b/spring-batch-plus-kotlin/src/test/kotlin/com/navercorp/spring/batch/plus/kotlin/configuration/support/LazyConfigurerTest.kt @@ -20,11 +20,14 @@ package com.navercorp.spring.batch.plus.kotlin.configuration.support import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.Test +import java.util.UUID +/** + * Covers the invariant that composed deferred configurations execute each registered action exactly once. + */ internal class LazyConfigurerTest { - @Test - fun testAdd() { + fun configurerShouldExecuteOnceWhenAppliedToTarget() { // given var configurerCallCount = 0 @@ -33,14 +36,14 @@ internal class LazyConfigurerTest { lazyConfigurer.add { ++configurerCallCount } - "test".apply(lazyConfigurer) + lazyConfigurer(UUID.randomUUID().toString()) // then assertThat(configurerCallCount).isEqualTo(1) } @Test - fun testAddOther() { + fun configurersShouldExecuteOnceEachWhenNestedConfigurerIsAppliedToTarget() { // given var configurer1CallCount = 0 var configurer2CallCount = 0 @@ -57,7 +60,7 @@ internal class LazyConfigurerTest { } }, ) - "test".apply(lazyConfigurer) + lazyConfigurer(UUID.randomUUID().toString()) // then assertThat(configurer1CallCount).isEqualTo(1) diff --git a/spring-batch-plus-kotlin/src/test/kotlin/com/navercorp/spring/batch/plus/kotlin/item/adapter/ItemDelegatesTest.kt b/spring-batch-plus-kotlin/src/test/kotlin/com/navercorp/spring/batch/plus/kotlin/item/adapter/ItemDelegatesTest.kt index 645ed07d..94cdc052 100644 --- a/spring-batch-plus-kotlin/src/test/kotlin/com/navercorp/spring/batch/plus/kotlin/item/adapter/ItemDelegatesTest.kt +++ b/spring-batch-plus-kotlin/src/test/kotlin/com/navercorp/spring/batch/plus/kotlin/item/adapter/ItemDelegatesTest.kt @@ -26,12 +26,11 @@ import com.navercorp.spring.batch.plus.item.adapter.ItemStreamWriterAdapter import com.navercorp.spring.batch.plus.item.adapter.StepScopeItemStreamReader import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.Test -import org.springframework.batch.item.Chunk -import org.springframework.batch.item.ExecutionContext +import org.springframework.batch.infrastructure.item.Chunk +import org.springframework.batch.infrastructure.item.ExecutionContext import reactor.core.publisher.Flux internal class ItemDelegatesTest { - @Test fun testExtensions() { // when @@ -47,14 +46,9 @@ internal class ItemDelegatesTest { } internal open class TestClass : ItemStreamReaderProcessorWriter { + override fun readFlux(executionContext: ExecutionContext): Flux = Flux.empty() - override fun readFlux(executionContext: ExecutionContext): Flux { - return Flux.empty() - } - - override fun process(item: Int): String { - return item.toString() - } + override fun process(item: Int): String = item.toString() override fun write(chunk: Chunk) { } diff --git a/spring-batch-plus-kotlin/src/test/kotlin/com/navercorp/spring/batch/plus/kotlin/step/adapter/ItemDelegatesTest.kt b/spring-batch-plus-kotlin/src/test/kotlin/com/navercorp/spring/batch/plus/kotlin/step/adapter/ItemDelegatesTest.kt index 9ad59be8..eb0f10c4 100644 --- a/spring-batch-plus-kotlin/src/test/kotlin/com/navercorp/spring/batch/plus/kotlin/step/adapter/ItemDelegatesTest.kt +++ b/spring-batch-plus-kotlin/src/test/kotlin/com/navercorp/spring/batch/plus/kotlin/step/adapter/ItemDelegatesTest.kt @@ -31,65 +31,55 @@ import io.mockk.mockk import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.Test +/** + * Covers the Kotlin extension boundary that converts item delegates into Spring Batch adapters. + */ internal class ItemDelegatesTest { - @Test - fun testAsItemStreamReaderOnItemStreamFluxReaderDelegate() { - // when + fun asItemStreamReaderShouldReturnStepScopedReaderWhenFluxDelegateIsProvided() { val delegate = mockk>() val itemStreamReader = delegate.asItemStreamReader() - // then assertThat(itemStreamReader).isInstanceOf(StepScopeItemStreamReader::class.java) } @Test - fun testAsItemStreamReaderOnItemStreamIterableReaderDelegate() { - // when + fun asItemStreamReaderShouldReturnStepScopedReaderWhenIterableDelegateIsProvided() { val delegate = mockk>() val itemStreamReader = delegate.asItemStreamReader() - // then assertThat(itemStreamReader).isInstanceOf(StepScopeItemStreamReader::class.java) } @Test - fun testAsItemStreamReaderOnItemStreamIteratorReaderDelegate() { - // when + fun asItemStreamReaderShouldReturnStepScopedReaderWhenIteratorDelegateIsProvided() { val delegate = mockk>() val itemStreamReader = delegate.asItemStreamReader() - // then assertThat(itemStreamReader).isInstanceOf(StepScopeItemStreamReader::class.java) } @Test - fun testAsItemStreamReaderOnItemStreamSimpleReaderDelegate() { - // when + fun asItemStreamReaderShouldReturnStepScopedReaderWhenSimpleDelegateIsProvided() { val delegate = mockk>() val itemStreamReader = delegate.asItemStreamReader() - // then assertThat(itemStreamReader).isInstanceOf(StepScopeItemStreamReader::class.java) } @Test - fun testAsItemProcessor() { - // when + fun asItemProcessorShouldReturnItemProcessorAdapterWhenDelegateIsProvided() { val delegate = mockk>() val itemProcessor = delegate.asItemProcessor() - // then assertThat(itemProcessor).isInstanceOf(ItemProcessorAdapter::class.java) } @Test - fun testAsItemStreamWriter() { - // when + fun asItemStreamWriterShouldReturnItemStreamWriterAdapterWhenDelegateIsProvided() { val delegate = mockk>() val itemStreamWriter = delegate.asItemStreamWriter() - // then assertThat(itemStreamWriter).isInstanceOf(ItemStreamWriterAdapter::class.java) } } diff --git a/spring-batch-plus-sample/clear-run-id-incrementer-kotlin-sample/build.gradle.kts b/spring-batch-plus-sample/clear-run-id-incrementer-kotlin-sample/build.gradle.kts index db01bfaa..6a4c7cbd 100644 --- a/spring-batch-plus-sample/clear-run-id-incrementer-kotlin-sample/build.gradle.kts +++ b/spring-batch-plus-sample/clear-run-id-incrementer-kotlin-sample/build.gradle.kts @@ -1,3 +1,5 @@ +import org.jetbrains.kotlin.gradle.dsl.JvmTarget + buildscript { repositories { gradlePluginPortal() // give accees to gradle community plugins @@ -17,12 +19,9 @@ repositories { kotlin { jvmToolchain(17) -} - -tasks.withType { - kotlinOptions { + compilerOptions { freeCompilerArgs = listOf("-Xjsr305=strict") // enable jsr305 null-safety in kotlin - jvmTarget = "17" + jvmTarget = JvmTarget.JVM_17 } } @@ -33,14 +32,14 @@ tasks.named("test") { dependencyManagement { imports { - mavenBom("org.springframework.boot:spring-boot-dependencies:3.5.0") + mavenBom("org.springframework.boot:spring-boot-dependencies:4.0.7") } } dependencies { - implementation("org.springframework.boot:spring-boot-starter-batch") + implementation("org.springframework.boot:spring-boot-starter-batch-jdbc") implementation(project(":spring-boot-starter-batch-plus-kotlin")) - runtimeOnly("com.h2database:h2:2.1.214") + runtimeOnly("com.h2database:h2:2.4.240") testImplementation("org.springframework.boot:spring-boot-starter-test") testRuntimeOnly("org.junit.platform:junit-platform-launcher") diff --git a/spring-batch-plus-sample/clear-run-id-incrementer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/clear/README.md b/spring-batch-plus-sample/clear-run-id-incrementer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/clear/README.md new file mode 100644 index 00000000..8b54f435 --- /dev/null +++ b/spring-batch-plus-sample/clear-run-id-incrementer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/clear/README.md @@ -0,0 +1,8 @@ +# Default Run ID Samples + +## Invariants + +- Samples should configure `ClearRunIdIncrementer` with its default `run.id` + parameter name. +- Consecutive job instances should demonstrate initialization and incrementation + of that parameter. diff --git a/spring-batch-plus-sample/clear-run-id-incrementer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/clear/SampleApplicationTest.kt b/spring-batch-plus-sample/clear-run-id-incrementer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/clear/SampleApplicationTest.kt index a49002ca..3c30b57a 100644 --- a/spring-batch-plus-sample/clear-run-id-incrementer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/clear/SampleApplicationTest.kt +++ b/spring-batch-plus-sample/clear-run-id-incrementer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/clear/SampleApplicationTest.kt @@ -20,10 +20,8 @@ package com.navercorp.spring.batch.plus.sample.clear import org.junit.jupiter.api.Test import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.explore.JobExplorer -import org.springframework.batch.core.launch.JobLauncher +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.launch.JobOperator import org.springframework.beans.factory.getBean import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.runApplication @@ -33,20 +31,11 @@ open class SampleApplicationTest { @Test fun run() { val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() - - val jobExplorer = applicationContext.getBean() + val jobOperator = applicationContext.getBean() val job = applicationContext.getBean() - val firstJobParameters = JobParametersBuilder(jobExplorer) - .getNextJobParameters(job) - .toJobParameters() - val firstJobExecution = jobLauncher.run(job, firstJobParameters) - - val secondJobParameters = JobParametersBuilder(jobExplorer) - .getNextJobParameters(job) - .toJobParameters() - val secondJobExecution = jobLauncher.run(job, secondJobParameters) + val firstJobExecution = jobOperator.startNextInstance(job) + val secondJobExecution = jobOperator.startNextInstance(job) // first assert(BatchStatus.COMPLETED.equals(firstJobExecution.status)) diff --git a/spring-batch-plus-sample/clear-run-id-incrementer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/clear/TestJobConfig.kt b/spring-batch-plus-sample/clear-run-id-incrementer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/clear/TestJobConfig.kt index 23801c2d..b69c55e0 100644 --- a/spring-batch-plus-sample/clear-run-id-incrementer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/clear/TestJobConfig.kt +++ b/spring-batch-plus-sample/clear-run-id-incrementer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/clear/TestJobConfig.kt @@ -20,8 +20,8 @@ package com.navercorp.spring.batch.plus.sample.clear import com.navercorp.spring.batch.plus.job.ClearRunIdIncrementer import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.Job -import org.springframework.batch.repeat.RepeatStatus +import org.springframework.batch.core.job.Job +import org.springframework.batch.infrastructure.repeat.RepeatStatus import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.transaction.PlatformTransactionManager @@ -31,17 +31,17 @@ open class TestJobConfig( private val batch: BatchDsl, private val transactionManager: PlatformTransactionManager, ) { - @Bean - open fun testJob(): Job = batch { - job("testJob") { - incrementer(ClearRunIdIncrementer.create()) - step("testStep") { - tasklet( - { _, _ -> RepeatStatus.FINISHED }, - transactionManager, - ) + open fun testJob(): Job = + batch { + job("testJob") { + incrementer(ClearRunIdIncrementer.create()) + step("testStep") { + tasklet( + { _, _ -> RepeatStatus.FINISHED }, + transactionManager, + ) + } } } - } } diff --git a/spring-batch-plus-sample/clear-run-id-incrementer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/clearwithid/README.md b/spring-batch-plus-sample/clear-run-id-incrementer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/clearwithid/README.md new file mode 100644 index 00000000..a10c3c74 --- /dev/null +++ b/spring-batch-plus-sample/clear-run-id-incrementer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/clearwithid/README.md @@ -0,0 +1,8 @@ +# Custom Run ID Samples + +## Invariants + +- Samples should configure `ClearRunIdIncrementer` with an explicit run-id + parameter name. +- Consecutive job instances should demonstrate initialization and incrementation + of the configured parameter. diff --git a/spring-batch-plus-sample/clear-run-id-incrementer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/clearwithid/SampleApplicationTest.kt b/spring-batch-plus-sample/clear-run-id-incrementer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/clearwithid/SampleApplicationTest.kt index 95f52c3d..699191c0 100644 --- a/spring-batch-plus-sample/clear-run-id-incrementer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/clearwithid/SampleApplicationTest.kt +++ b/spring-batch-plus-sample/clear-run-id-incrementer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/clearwithid/SampleApplicationTest.kt @@ -20,10 +20,8 @@ package com.navercorp.spring.batch.plus.sample.clearwithid import org.junit.jupiter.api.Test import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.explore.JobExplorer -import org.springframework.batch.core.launch.JobLauncher +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.launch.JobOperator import org.springframework.beans.factory.getBean import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.runApplication @@ -33,20 +31,11 @@ open class SampleApplicationTest { @Test fun run() { val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() - - val jobExplorer = applicationContext.getBean() + val jobOperator = applicationContext.getBean() val job = applicationContext.getBean() - val firstJobParameters = JobParametersBuilder(jobExplorer) - .getNextJobParameters(job) - .toJobParameters() - val firstJobExecution = jobLauncher.run(job, firstJobParameters) - - val secondJobParameters = JobParametersBuilder(jobExplorer) - .getNextJobParameters(job) - .toJobParameters() - val secondJobExecution = jobLauncher.run(job, secondJobParameters) + val firstJobExecution = jobOperator.startNextInstance(job) + val secondJobExecution = jobOperator.startNextInstance(job) // first assert(BatchStatus.COMPLETED.equals(firstJobExecution.status)) diff --git a/spring-batch-plus-sample/clear-run-id-incrementer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/clearwithid/TestJobConfig.kt b/spring-batch-plus-sample/clear-run-id-incrementer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/clearwithid/TestJobConfig.kt index b82c442c..d5c3863c 100644 --- a/spring-batch-plus-sample/clear-run-id-incrementer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/clearwithid/TestJobConfig.kt +++ b/spring-batch-plus-sample/clear-run-id-incrementer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/clearwithid/TestJobConfig.kt @@ -20,8 +20,8 @@ package com.navercorp.spring.batch.plus.sample.clearwithid import com.navercorp.spring.batch.plus.job.ClearRunIdIncrementer import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.Job -import org.springframework.batch.repeat.RepeatStatus +import org.springframework.batch.core.job.Job +import org.springframework.batch.infrastructure.repeat.RepeatStatus import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.transaction.PlatformTransactionManager @@ -31,17 +31,17 @@ open class TestJobConfig( private val batch: BatchDsl, private val transactionManager: PlatformTransactionManager, ) { - @Bean - open fun testJob(): Job = batch { - job("testJob") { - incrementer(ClearRunIdIncrementer.create("testId")) - step("testStep") { - tasklet( - { _, _ -> RepeatStatus.FINISHED }, - transactionManager, - ) + open fun testJob(): Job = + batch { + job("testJob") { + incrementer(ClearRunIdIncrementer.create("testId")) + step("testStep") { + tasklet( + { _, _ -> RepeatStatus.FINISHED }, + transactionManager, + ) + } } } - } } diff --git a/spring-batch-plus-sample/clear-run-id-incrementer-sample/build.gradle.kts b/spring-batch-plus-sample/clear-run-id-incrementer-sample/build.gradle.kts index 495c7926..5f869286 100644 --- a/spring-batch-plus-sample/clear-run-id-incrementer-sample/build.gradle.kts +++ b/spring-batch-plus-sample/clear-run-id-incrementer-sample/build.gradle.kts @@ -27,14 +27,14 @@ tasks.named("test") { dependencyManagement { imports { - mavenBom("org.springframework.boot:spring-boot-dependencies:3.5.0") + mavenBom("org.springframework.boot:spring-boot-dependencies:4.0.7") } } dependencies { - implementation("org.springframework.boot:spring-boot-starter-batch") + implementation("org.springframework.boot:spring-boot-starter-batch-jdbc") implementation(project(":spring-boot-starter-batch-plus")) - runtimeOnly("com.h2database:h2:2.1.214") + runtimeOnly("com.h2database:h2:2.4.240") testImplementation("org.springframework.boot:spring-boot-starter-test") testRuntimeOnly("org.junit.platform:junit-platform-launcher") diff --git a/spring-batch-plus-sample/clear-run-id-incrementer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/clear/README.md b/spring-batch-plus-sample/clear-run-id-incrementer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/clear/README.md new file mode 100644 index 00000000..8b54f435 --- /dev/null +++ b/spring-batch-plus-sample/clear-run-id-incrementer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/clear/README.md @@ -0,0 +1,8 @@ +# Default Run ID Samples + +## Invariants + +- Samples should configure `ClearRunIdIncrementer` with its default `run.id` + parameter name. +- Consecutive job instances should demonstrate initialization and incrementation + of that parameter. diff --git a/spring-batch-plus-sample/clear-run-id-incrementer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/clear/SampleApplicationTest.java b/spring-batch-plus-sample/clear-run-id-incrementer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/clear/SampleApplicationTest.java index e0fcc874..4161006c 100644 --- a/spring-batch-plus-sample/clear-run-id-incrementer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/clear/SampleApplicationTest.java +++ b/spring-batch-plus-sample/clear-run-id-incrementer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/clear/SampleApplicationTest.java @@ -22,12 +22,9 @@ import org.junit.jupiter.api.Test; import org.springframework.batch.core.BatchStatus; -import org.springframework.batch.core.Job; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.JobParameters; -import org.springframework.batch.core.JobParametersBuilder; -import org.springframework.batch.core.explore.JobExplorer; -import org.springframework.batch.core.launch.JobLauncher; +import org.springframework.batch.core.job.Job; +import org.springframework.batch.core.job.JobExecution; +import org.springframework.batch.core.launch.JobOperator; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ApplicationContext; @@ -37,19 +34,11 @@ public class SampleApplicationTest { @Test void run() throws Exception { ApplicationContext applicationContext = SpringApplication.run(SampleApplicationTest.class); - JobLauncher jobLauncher = applicationContext.getBean(JobLauncher.class); - JobExplorer jobExplorer = applicationContext.getBean(JobExplorer.class); + JobOperator jobOperator = applicationContext.getBean(JobOperator.class); Job job = applicationContext.getBean(Job.class); - JobParameters firstJobParameters = new JobParametersBuilder(jobExplorer) - .getNextJobParameters(job) - .toJobParameters(); - JobExecution firstJobExecution = jobLauncher.run(job, firstJobParameters); - - JobParameters secondJobParameters = new JobParametersBuilder(jobExplorer) - .getNextJobParameters(job) - .toJobParameters(); - JobExecution secondJobExecution = jobLauncher.run(job, secondJobParameters); + JobExecution firstJobExecution = jobOperator.startNextInstance(job); + JobExecution secondJobExecution = jobOperator.startNextInstance(job); // first assert BatchStatus.COMPLETED.equals(firstJobExecution.getStatus()); @@ -57,7 +46,7 @@ void run() throws Exception { System.out.printf("first: %s, jobParameters: %s%n", firstJobExecution.getStatus(), firstJobExecution.getJobParameters()); - // second) + // second assert BatchStatus.COMPLETED.equals(secondJobExecution.getStatus()); assert 2L == Objects.requireNonNull(secondJobExecution.getJobParameters().getLong("run.id")); System.out.printf("second: %s, jobParameters: %s%n", secondJobExecution.getStatus(), diff --git a/spring-batch-plus-sample/clear-run-id-incrementer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/clear/TestJobConfig.java b/spring-batch-plus-sample/clear-run-id-incrementer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/clear/TestJobConfig.java index f008e2be..b77061d4 100644 --- a/spring-batch-plus-sample/clear-run-id-incrementer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/clear/TestJobConfig.java +++ b/spring-batch-plus-sample/clear-run-id-incrementer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/clear/TestJobConfig.java @@ -18,11 +18,11 @@ package com.navercorp.spring.batch.plus.sample.clear; -import org.springframework.batch.core.Job; +import org.springframework.batch.core.job.Job; import org.springframework.batch.core.job.builder.JobBuilder; import org.springframework.batch.core.repository.JobRepository; import org.springframework.batch.core.step.builder.StepBuilder; -import org.springframework.batch.repeat.RepeatStatus; +import org.springframework.batch.infrastructure.repeat.RepeatStatus; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.transaction.PlatformTransactionManager; diff --git a/spring-batch-plus-sample/clear-run-id-incrementer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/clearwithid/README.md b/spring-batch-plus-sample/clear-run-id-incrementer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/clearwithid/README.md new file mode 100644 index 00000000..a10c3c74 --- /dev/null +++ b/spring-batch-plus-sample/clear-run-id-incrementer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/clearwithid/README.md @@ -0,0 +1,8 @@ +# Custom Run ID Samples + +## Invariants + +- Samples should configure `ClearRunIdIncrementer` with an explicit run-id + parameter name. +- Consecutive job instances should demonstrate initialization and incrementation + of the configured parameter. diff --git a/spring-batch-plus-sample/clear-run-id-incrementer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/clearwithid/SampleApplicationTest.java b/spring-batch-plus-sample/clear-run-id-incrementer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/clearwithid/SampleApplicationTest.java index 5400eb98..65670ba9 100644 --- a/spring-batch-plus-sample/clear-run-id-incrementer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/clearwithid/SampleApplicationTest.java +++ b/spring-batch-plus-sample/clear-run-id-incrementer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/clearwithid/SampleApplicationTest.java @@ -22,12 +22,9 @@ import org.junit.jupiter.api.Test; import org.springframework.batch.core.BatchStatus; -import org.springframework.batch.core.Job; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.JobParameters; -import org.springframework.batch.core.JobParametersBuilder; -import org.springframework.batch.core.explore.JobExplorer; -import org.springframework.batch.core.launch.JobLauncher; +import org.springframework.batch.core.job.Job; +import org.springframework.batch.core.job.JobExecution; +import org.springframework.batch.core.launch.JobOperator; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ApplicationContext; @@ -37,19 +34,11 @@ public class SampleApplicationTest { @Test void run() throws Exception { ApplicationContext applicationContext = SpringApplication.run(SampleApplicationTest.class); - JobLauncher jobLauncher = applicationContext.getBean(JobLauncher.class); - JobExplorer jobExplorer = applicationContext.getBean(JobExplorer.class); + JobOperator jobOperator = applicationContext.getBean(JobOperator.class); Job job = applicationContext.getBean(Job.class); - JobParameters firstJobParameters = new JobParametersBuilder(jobExplorer) - .getNextJobParameters(job) - .toJobParameters(); - JobExecution firstJobExecution = jobLauncher.run(job, firstJobParameters); - - JobParameters secondJobParameters = new JobParametersBuilder(jobExplorer) - .getNextJobParameters(job) - .toJobParameters(); - JobExecution secondJobExecution = jobLauncher.run(job, secondJobParameters); + JobExecution firstJobExecution = jobOperator.startNextInstance(job); + JobExecution secondJobExecution = jobOperator.startNextInstance(job); // first assert BatchStatus.COMPLETED.equals(firstJobExecution.getStatus()); diff --git a/spring-batch-plus-sample/clear-run-id-incrementer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/clearwithid/TestJobConfig.java b/spring-batch-plus-sample/clear-run-id-incrementer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/clearwithid/TestJobConfig.java index 8f0c58e3..ef0d551b 100644 --- a/spring-batch-plus-sample/clear-run-id-incrementer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/clearwithid/TestJobConfig.java +++ b/spring-batch-plus-sample/clear-run-id-incrementer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/clearwithid/TestJobConfig.java @@ -18,11 +18,11 @@ package com.navercorp.spring.batch.plus.sample.clearwithid; -import org.springframework.batch.core.Job; +import org.springframework.batch.core.job.Job; import org.springframework.batch.core.job.builder.JobBuilder; import org.springframework.batch.core.repository.JobRepository; import org.springframework.batch.core.step.builder.StepBuilder; -import org.springframework.batch.repeat.RepeatStatus; +import org.springframework.batch.infrastructure.repeat.RepeatStatus; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.transaction.PlatformTransactionManager; diff --git a/spring-batch-plus-sample/clear-run-id-incrementer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/comparison/README.md b/spring-batch-plus-sample/clear-run-id-incrementer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/comparison/README.md new file mode 100644 index 00000000..0f4b0ae7 --- /dev/null +++ b/spring-batch-plus-sample/clear-run-id-incrementer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/comparison/README.md @@ -0,0 +1,12 @@ +# Run ID Incrementer Comparison Samples + +## Invariants + +- Comparison samples should start from equivalent completed job metadata + containing both run-id and non-run-id parameters. +- The [`bad`](bad) sample should show `RunIdIncrementer` carrying previous + non-run-id parameters forward. +- The [`good`](good) sample should show `ClearRunIdIncrementer` discarding those + parameters. +- This comparison represents legacy or externally populated metadata rather + than metadata produced by a clean Spring Batch 6 launch sequence. diff --git a/spring-batch-plus-sample/clear-run-id-incrementer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/comparison/bad/SampleApplicationTest.java b/spring-batch-plus-sample/clear-run-id-incrementer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/comparison/bad/SampleApplicationTest.java index ec808989..3925560b 100644 --- a/spring-batch-plus-sample/clear-run-id-incrementer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/comparison/bad/SampleApplicationTest.java +++ b/spring-batch-plus-sample/clear-run-id-incrementer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/comparison/bad/SampleApplicationTest.java @@ -22,58 +22,53 @@ import org.junit.jupiter.api.Test; import org.springframework.batch.core.BatchStatus; -import org.springframework.batch.core.Job; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.JobParameters; -import org.springframework.batch.core.JobParametersBuilder; -import org.springframework.batch.core.explore.JobExplorer; -import org.springframework.batch.core.launch.JobLauncher; +import org.springframework.batch.core.ExitStatus; +import org.springframework.batch.core.job.Job; +import org.springframework.batch.core.job.JobExecution; +import org.springframework.batch.core.job.JobInstance; +import org.springframework.batch.core.job.parameters.JobParameters; +import org.springframework.batch.core.job.parameters.JobParametersBuilder; +import org.springframework.batch.core.launch.JobOperator; +import org.springframework.batch.core.repository.JobRepository; +import org.springframework.batch.infrastructure.item.ExecutionContext; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ApplicationContext; +/** + * Demonstrates how {@link org.springframework.batch.core.job.parameters.RunIdIncrementer} + * carries legacy non-run-id parameters into the next job instance. + */ @SpringBootApplication public class SampleApplicationTest { @Test void run() throws Exception { ApplicationContext applicationContext = SpringApplication.run(SampleApplicationTest.class); - JobLauncher jobLauncher = applicationContext.getBean(JobLauncher.class); - JobExplorer jobExplorer = applicationContext.getBean(JobExplorer.class); + JobRepository jobRepository = applicationContext.getBean(JobRepository.class); + JobOperator jobOperator = applicationContext.getBean(JobOperator.class); Job job = applicationContext.getBean(Job.class); - JobParameters firstJobParameters = new JobParametersBuilder(jobExplorer) + // Direct repository setup reproduces metadata that the normal launch path cannot create. + JobParameters legacyParams = new JobParametersBuilder() .addString("stringValue", "1") .addString("longValue", "10") - .getNextJobParameters(job) + .addLong("run.id", 5L) .toJobParameters(); - JobExecution firstJobExecution = jobLauncher.run(job, firstJobParameters); + JobInstance legacyInstance = jobRepository.createJobInstance(job.getName(), legacyParams); + JobExecution legacyExecution = jobRepository.createJobExecution(legacyInstance, legacyParams, + new ExecutionContext()); + legacyExecution.setStatus(BatchStatus.COMPLETED); + legacyExecution.setExitStatus(ExitStatus.COMPLETED); + jobRepository.update(legacyExecution); - JobParameters secondJobParameters = new JobParametersBuilder(jobExplorer) - .addString("longValue", "20") - .getNextJobParameters(job) - .toJobParameters(); - JobExecution secondJobExecution = jobLauncher.run(job, secondJobParameters); + JobExecution nextExecution = jobOperator.startNextInstance(job); - // first - assert BatchStatus.COMPLETED.equals(firstJobExecution.getStatus()); - assert 1L == Objects.requireNonNull(firstJobExecution.getJobParameters().getLong("run.id")); - assert "1".equals(firstJobExecution.getJobParameters().getString("stringValue")); - assert "10".equals(firstJobExecution.getJobParameters().getString("longValue")); - assert 11L == firstJobExecution.getExecutionContext().getLong("result"); - System.out.printf("first: %s, jobParameters: %s, result: %d%n", - firstJobExecution.getStatus(), - firstJobExecution.getJobParameters(), - firstJobExecution.getExecutionContext().getLong("result")); + assert BatchStatus.COMPLETED.equals(nextExecution.getStatus()); + JobParameters nextParams = nextExecution.getJobParameters(); - // second - assert BatchStatus.COMPLETED.equals(secondJobExecution.getStatus()); - assert 2L == Objects.requireNonNull(secondJobExecution.getJobParameters().getLong("run.id")); - assert "1".equals(secondJobExecution.getJobParameters().getString("stringValue")); - assert "20".equals(secondJobExecution.getJobParameters().getString("longValue")); - assert 21L == secondJobExecution.getExecutionContext().getLong("result"); - System.out.printf("second: %s, jobParameters: %s, result: %d%n", - secondJobExecution.getStatus(), - secondJobExecution.getJobParameters(), - secondJobExecution.getExecutionContext().getLong("result")); + assert 6L == Objects.requireNonNull(nextParams.getLong("run.id")); + assert "1".equals(nextParams.getString("stringValue")); + assert "10".equals(nextParams.getString("longValue")); + System.out.printf("bad: params=%s%n", nextParams); } } diff --git a/spring-batch-plus-sample/clear-run-id-incrementer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/comparison/bad/TestJobConfig.java b/spring-batch-plus-sample/clear-run-id-incrementer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/comparison/bad/TestJobConfig.java index da4a5c58..df17fc3b 100644 --- a/spring-batch-plus-sample/clear-run-id-incrementer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/comparison/bad/TestJobConfig.java +++ b/spring-batch-plus-sample/clear-run-id-incrementer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/comparison/bad/TestJobConfig.java @@ -18,16 +18,12 @@ package com.navercorp.spring.batch.plus.sample.comparison.bad; -import org.springframework.batch.core.Job; -import org.springframework.batch.core.configuration.annotation.StepScope; +import org.springframework.batch.core.job.Job; import org.springframework.batch.core.job.builder.JobBuilder; -import org.springframework.batch.core.launch.support.RunIdIncrementer; +import org.springframework.batch.core.job.parameters.RunIdIncrementer; import org.springframework.batch.core.repository.JobRepository; import org.springframework.batch.core.step.builder.StepBuilder; -import org.springframework.batch.core.step.tasklet.Tasklet; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.batch.repeat.RepeatStatus; -import org.springframework.beans.factory.annotation.Value; +import org.springframework.batch.infrastructure.repeat.RepeatStatus; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.transaction.PlatformTransactionManager; @@ -45,33 +41,11 @@ public Job testJob( .start( new StepBuilder("testStep", jobRepository) .tasklet( - testTasklet(null, null), + (contribution, chunkContext) -> RepeatStatus.FINISHED, transactionManager ) .build() ) .build(); } - - @StepScope - @Bean - public Tasklet testTasklet( - @Value("#{jobParameters['longValue']}") Long longValue, - @Value("#{jobParameters['stringValue']}") String stringValue - ) { - return (contribution, chunkContext) -> { - Long result; - if (stringValue != null) { - result = longValue + Long.parseLong(stringValue); - } else { - result = 999L; - } - - ExecutionContext jobExecutionContext = contribution.getStepExecution() - .getJobExecution() - .getExecutionContext(); - jobExecutionContext.putLong("result", result); - return RepeatStatus.FINISHED; - }; - } } diff --git a/spring-batch-plus-sample/clear-run-id-incrementer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/comparison/good/SampleApplicationTest.java b/spring-batch-plus-sample/clear-run-id-incrementer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/comparison/good/SampleApplicationTest.java index b1ea2fd9..c52707fd 100644 --- a/spring-batch-plus-sample/clear-run-id-incrementer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/comparison/good/SampleApplicationTest.java +++ b/spring-batch-plus-sample/clear-run-id-incrementer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/comparison/good/SampleApplicationTest.java @@ -22,58 +22,53 @@ import org.junit.jupiter.api.Test; import org.springframework.batch.core.BatchStatus; -import org.springframework.batch.core.Job; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.JobParameters; -import org.springframework.batch.core.JobParametersBuilder; -import org.springframework.batch.core.explore.JobExplorer; -import org.springframework.batch.core.launch.JobLauncher; +import org.springframework.batch.core.ExitStatus; +import org.springframework.batch.core.job.Job; +import org.springframework.batch.core.job.JobExecution; +import org.springframework.batch.core.job.JobInstance; +import org.springframework.batch.core.job.parameters.JobParameters; +import org.springframework.batch.core.job.parameters.JobParametersBuilder; +import org.springframework.batch.core.launch.JobOperator; +import org.springframework.batch.core.repository.JobRepository; +import org.springframework.batch.infrastructure.item.ExecutionContext; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ApplicationContext; +/** + * Demonstrates how {@link com.navercorp.spring.batch.plus.job.ClearRunIdIncrementer} + * discards legacy non-run-id parameters from the next job instance. + */ @SpringBootApplication public class SampleApplicationTest { @Test void run() throws Exception { ApplicationContext applicationContext = SpringApplication.run(SampleApplicationTest.class); - JobLauncher jobLauncher = applicationContext.getBean(JobLauncher.class); - JobExplorer jobExplorer = applicationContext.getBean(JobExplorer.class); + JobRepository jobRepository = applicationContext.getBean(JobRepository.class); + JobOperator jobOperator = applicationContext.getBean(JobOperator.class); Job job = applicationContext.getBean(Job.class); - JobParameters firstJobParameters = new JobParametersBuilder(jobExplorer) + // Direct repository setup reproduces metadata that the normal launch path cannot create. + JobParameters legacyParams = new JobParametersBuilder() .addString("stringValue", "1") .addString("longValue", "10") - .getNextJobParameters(job) + .addLong("run.id", 5L) .toJobParameters(); - JobExecution firstJobExecution = jobLauncher.run(job, firstJobParameters); + JobInstance legacyInstance = jobRepository.createJobInstance(job.getName(), legacyParams); + JobExecution legacyExecution = jobRepository.createJobExecution(legacyInstance, legacyParams, + new ExecutionContext()); + legacyExecution.setStatus(BatchStatus.COMPLETED); + legacyExecution.setExitStatus(ExitStatus.COMPLETED); + jobRepository.update(legacyExecution); - JobParameters secondJobParameters = new JobParametersBuilder(jobExplorer) - .addString("longValue", "20") - .getNextJobParameters(job) - .toJobParameters(); - JobExecution secondJobExecution = jobLauncher.run(job, secondJobParameters); + JobExecution nextExecution = jobOperator.startNextInstance(job); - // first - assert BatchStatus.COMPLETED.equals(firstJobExecution.getStatus()); - assert 1L == Objects.requireNonNull(firstJobExecution.getJobParameters().getLong("run.id")); - assert "1".equals(firstJobExecution.getJobParameters().getString("stringValue")); - assert "10".equals(firstJobExecution.getJobParameters().getString("longValue")); - assert 11L == firstJobExecution.getExecutionContext().getLong("result"); - System.out.printf("first: %s, jobParameters: %s, result: %d%n", - firstJobExecution.getStatus(), - firstJobExecution.getJobParameters(), - firstJobExecution.getExecutionContext().getLong("result")); + assert BatchStatus.COMPLETED.equals(nextExecution.getStatus()); + JobParameters nextParams = nextExecution.getJobParameters(); - // second - assert BatchStatus.COMPLETED.equals(secondJobExecution.getStatus()); - assert 2L == Objects.requireNonNull(secondJobExecution.getJobParameters().getLong("run.id")); - assert null == secondJobExecution.getJobParameters().getString("stringValue"); - assert "20".equals(secondJobExecution.getJobParameters().getString("longValue")); - assert 999L == secondJobExecution.getExecutionContext().getLong("result"); - System.out.printf("second: %s, jobParameters: %s, result: %d%n", - secondJobExecution.getStatus(), - secondJobExecution.getJobParameters(), - secondJobExecution.getExecutionContext().getLong("result")); + assert 6L == Objects.requireNonNull(nextParams.getLong("run.id")); + assert nextParams.getString("stringValue") == null; + assert nextParams.getString("longValue") == null; + System.out.printf("good: params=%s%n", nextParams); } } diff --git a/spring-batch-plus-sample/clear-run-id-incrementer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/comparison/good/TestJobConfig.java b/spring-batch-plus-sample/clear-run-id-incrementer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/comparison/good/TestJobConfig.java index 97e5c2db..4d366292 100644 --- a/spring-batch-plus-sample/clear-run-id-incrementer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/comparison/good/TestJobConfig.java +++ b/spring-batch-plus-sample/clear-run-id-incrementer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/comparison/good/TestJobConfig.java @@ -18,15 +18,11 @@ package com.navercorp.spring.batch.plus.sample.comparison.good; -import org.springframework.batch.core.Job; -import org.springframework.batch.core.configuration.annotation.StepScope; +import org.springframework.batch.core.job.Job; import org.springframework.batch.core.job.builder.JobBuilder; import org.springframework.batch.core.repository.JobRepository; import org.springframework.batch.core.step.builder.StepBuilder; -import org.springframework.batch.core.step.tasklet.Tasklet; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.batch.repeat.RepeatStatus; -import org.springframework.beans.factory.annotation.Value; +import org.springframework.batch.infrastructure.repeat.RepeatStatus; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.transaction.PlatformTransactionManager; @@ -42,37 +38,15 @@ public Job testJob( PlatformTransactionManager transactionManager ) { return new JobBuilder("testJob", jobRepository) - .incrementer(ClearRunIdIncrementer.create()) // use ClearRunIdIncrementer + .incrementer(ClearRunIdIncrementer.create()) .start( new StepBuilder("testStep", jobRepository) .tasklet( - testTasklet(null, null), + (contribution, chunkContext) -> RepeatStatus.FINISHED, transactionManager ) .build() ) .build(); } - - @StepScope - @Bean - public Tasklet testTasklet( - @Value("#{jobParameters['longValue']}") Long longValue, - @Value("#{jobParameters['stringValue']}") String stringValue - ) { - return (contribution, chunkContext) -> { - Long result; - if (stringValue != null) { - result = longValue + Long.parseLong(stringValue); - } else { - result = 999L; - } - - ExecutionContext jobExecutionContext = contribution.getStepExecution() - .getJobExecution() - .getExecutionContext(); - jobExecutionContext.putLong("result", result); - return RepeatStatus.FINISHED; - }; - } } diff --git a/spring-batch-plus-sample/delete-meta-data-job-kotlin-sample/build.gradle.kts b/spring-batch-plus-sample/delete-meta-data-job-kotlin-sample/build.gradle.kts index db01bfaa..6a4c7cbd 100644 --- a/spring-batch-plus-sample/delete-meta-data-job-kotlin-sample/build.gradle.kts +++ b/spring-batch-plus-sample/delete-meta-data-job-kotlin-sample/build.gradle.kts @@ -1,3 +1,5 @@ +import org.jetbrains.kotlin.gradle.dsl.JvmTarget + buildscript { repositories { gradlePluginPortal() // give accees to gradle community plugins @@ -17,12 +19,9 @@ repositories { kotlin { jvmToolchain(17) -} - -tasks.withType { - kotlinOptions { + compilerOptions { freeCompilerArgs = listOf("-Xjsr305=strict") // enable jsr305 null-safety in kotlin - jvmTarget = "17" + jvmTarget = JvmTarget.JVM_17 } } @@ -33,14 +32,14 @@ tasks.named("test") { dependencyManagement { imports { - mavenBom("org.springframework.boot:spring-boot-dependencies:3.5.0") + mavenBom("org.springframework.boot:spring-boot-dependencies:4.0.7") } } dependencies { - implementation("org.springframework.boot:spring-boot-starter-batch") + implementation("org.springframework.boot:spring-boot-starter-batch-jdbc") implementation(project(":spring-boot-starter-batch-plus-kotlin")) - runtimeOnly("com.h2database:h2:2.1.214") + runtimeOnly("com.h2database:h2:2.4.240") testImplementation("org.springframework.boot:spring-boot-starter-test") testRuntimeOnly("org.junit.platform:junit-platform-launcher") diff --git a/spring-batch-plus-sample/delete-meta-data-job-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/deletemedadata/customdryrun/JdbcConfig.kt b/spring-batch-plus-sample/delete-meta-data-job-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/deletemedadata/customdryrun/JdbcConfig.kt index 50256cde..5792a674 100644 --- a/spring-batch-plus-sample/delete-meta-data-job-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/deletemedadata/customdryrun/JdbcConfig.kt +++ b/spring-batch-plus-sample/delete-meta-data-job-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/deletemedadata/customdryrun/JdbcConfig.kt @@ -18,7 +18,7 @@ package com.navercorp.spring.batch.plus.sample.deletemedadata.customdryrun -import org.springframework.boot.autoconfigure.batch.BatchDataSource +import org.springframework.boot.batch.jdbc.autoconfigure.BatchDataSource import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder @@ -27,14 +27,12 @@ import javax.sql.DataSource @Configuration open class JdbcConfig { - @BatchDataSource @Bean - open fun dataSource(): DataSource { - return EmbeddedDatabaseBuilder() + open fun dataSource(): DataSource = + EmbeddedDatabaseBuilder() .setType(EmbeddedDatabaseType.H2) .ignoreFailedDrops(true) .generateUniqueName(true) .build() - } } diff --git a/spring-batch-plus-sample/delete-meta-data-job-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/deletemedadata/customdryrun/SampleApplicationTest.kt b/spring-batch-plus-sample/delete-meta-data-job-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/deletemedadata/customdryrun/SampleApplicationTest.kt index 0e49f00e..46f766e9 100644 --- a/spring-batch-plus-sample/delete-meta-data-job-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/deletemedadata/customdryrun/SampleApplicationTest.kt +++ b/spring-batch-plus-sample/delete-meta-data-job-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/deletemedadata/customdryrun/SampleApplicationTest.kt @@ -19,9 +19,9 @@ package com.navercorp.spring.batch.plus.sample.deletemedadata.customdryrun import org.junit.jupiter.api.Test -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator import org.springframework.batch.core.repository.JobRepository import org.springframework.beans.factory.getBean import org.springframework.boot.autoconfigure.SpringBootApplication @@ -34,19 +34,20 @@ open class SampleApplicationTest { @Test fun run() { val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() + val jobOperator = applicationContext.getBean() val jobRepository = applicationContext.getBean() // prepare job instances val testJob = applicationContext.getBean("testJob") - val testJobParameterList = (0L..250L).map { - JobParametersBuilder() - .addLong("longValue", it) - .toJobParameters() - } + val testJobParameterList = + (0L..250L).map { + JobParametersBuilder() + .addLong("longValue", it) + .toJobParameters() + } for (testJobParameters in testJobParameterList) { // change create time date for test - val jobExecution = jobLauncher.run(testJob, testJobParameters) + val jobExecution = jobOperator.start(testJob, testJobParameters) jobExecution.createTime = jobExecution.createTime.minusDays(1) jobRepository.update(jobExecution) } @@ -55,11 +56,12 @@ open class SampleApplicationTest { val removeJob = applicationContext.getBean("removeJob") val now = LocalDate.now() val formatter = DateTimeFormatter.ofPattern("yyyy/MM/dd") - val jobParameters = JobParametersBuilder() - .addString("baseDate", now.format(formatter)) - .addString("customDryRunParam", "true") // set dryRun to 'true' - .toJobParameters() - jobLauncher.run(removeJob, jobParameters) + val jobParameters = + JobParametersBuilder() + .addString("baseDate", now.format(formatter)) + .addString("customDryRunParam", "true") // set dryRun to 'true' + .toJobParameters() + jobOperator.start(removeJob, jobParameters) // all instances should not be removed for (testJobParameters in testJobParameterList) { diff --git a/spring-batch-plus-sample/delete-meta-data-job-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/deletemedadata/customdryrun/TestJobConfig.kt b/spring-batch-plus-sample/delete-meta-data-job-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/deletemedadata/customdryrun/TestJobConfig.kt index 4017317f..58ff219f 100644 --- a/spring-batch-plus-sample/delete-meta-data-job-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/deletemedadata/customdryrun/TestJobConfig.kt +++ b/spring-batch-plus-sample/delete-meta-data-job-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/deletemedadata/customdryrun/TestJobConfig.kt @@ -20,10 +20,10 @@ package com.navercorp.spring.batch.plus.sample.deletemedadata.customdryrun import com.navercorp.spring.batch.plus.job.metadata.DeleteMetadataJobBuilder import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.Job +import org.springframework.batch.core.job.Job import org.springframework.batch.core.repository.JobRepository -import org.springframework.batch.repeat.RepeatStatus -import org.springframework.boot.autoconfigure.batch.BatchDataSource +import org.springframework.batch.infrastructure.repeat.RepeatStatus +import org.springframework.boot.batch.jdbc.autoconfigure.BatchDataSource import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.transaction.PlatformTransactionManager @@ -34,27 +34,26 @@ open class TestJobConfig( private val batch: BatchDsl, private val transactionManager: PlatformTransactionManager, ) { - @Bean open fun removeJob( @BatchDataSource dataSource: DataSource, jobRepository: JobRepository, - ): Job { - return DeleteMetadataJobBuilder(jobRepository, dataSource) + ): Job = + DeleteMetadataJobBuilder(jobRepository, dataSource) .name("removeJob") .dryRunParameterName("customDryRunParam") .build() - } @Bean - open fun testJob(): Job = batch { - job("testJob") { - step("testStep") { - tasklet( - { _, _ -> RepeatStatus.FINISHED }, - transactionManager, - ) + open fun testJob(): Job = + batch { + job("testJob") { + step("testStep") { + tasklet( + { _, _ -> RepeatStatus.FINISHED }, + transactionManager, + ) + } } } - } } diff --git a/spring-batch-plus-sample/delete-meta-data-job-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/deletemedadata/dryrun/JdbcConfig.kt b/spring-batch-plus-sample/delete-meta-data-job-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/deletemedadata/dryrun/JdbcConfig.kt index ee154016..46f857ba 100644 --- a/spring-batch-plus-sample/delete-meta-data-job-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/deletemedadata/dryrun/JdbcConfig.kt +++ b/spring-batch-plus-sample/delete-meta-data-job-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/deletemedadata/dryrun/JdbcConfig.kt @@ -18,7 +18,7 @@ package com.navercorp.spring.batch.plus.sample.deletemedadata.dryrun -import org.springframework.boot.autoconfigure.batch.BatchDataSource +import org.springframework.boot.batch.jdbc.autoconfigure.BatchDataSource import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder @@ -27,14 +27,12 @@ import javax.sql.DataSource @Configuration open class JdbcConfig { - @BatchDataSource @Bean - open fun dataSource(): DataSource { - return EmbeddedDatabaseBuilder() + open fun dataSource(): DataSource = + EmbeddedDatabaseBuilder() .setType(EmbeddedDatabaseType.H2) .ignoreFailedDrops(true) .generateUniqueName(true) .build() - } } diff --git a/spring-batch-plus-sample/delete-meta-data-job-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/deletemedadata/dryrun/SampleApplicationTest.kt b/spring-batch-plus-sample/delete-meta-data-job-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/deletemedadata/dryrun/SampleApplicationTest.kt index db499657..3fe97ddd 100644 --- a/spring-batch-plus-sample/delete-meta-data-job-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/deletemedadata/dryrun/SampleApplicationTest.kt +++ b/spring-batch-plus-sample/delete-meta-data-job-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/deletemedadata/dryrun/SampleApplicationTest.kt @@ -19,9 +19,9 @@ package com.navercorp.spring.batch.plus.sample.deletemedadata.dryrun import org.junit.jupiter.api.Test -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator import org.springframework.batch.core.repository.JobRepository import org.springframework.beans.factory.getBean import org.springframework.boot.autoconfigure.SpringBootApplication @@ -34,19 +34,20 @@ open class SampleApplicationTest { @Test fun run() { val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() + val jobOperator = applicationContext.getBean() val jobRepository = applicationContext.getBean() // prepare job instances val testJob = applicationContext.getBean("testJob") - val testJobParameterList = (0L..250L).map { - JobParametersBuilder() - .addLong("longValue", it) - .toJobParameters() - } + val testJobParameterList = + (0L..250L).map { + JobParametersBuilder() + .addLong("longValue", it) + .toJobParameters() + } for (testJobParameters in testJobParameterList) { // change create time date for test - val jobExecution = jobLauncher.run(testJob, testJobParameters) + val jobExecution = jobOperator.start(testJob, testJobParameters) jobExecution.createTime = jobExecution.createTime.minusDays(1) jobRepository.update(jobExecution) } @@ -55,11 +56,12 @@ open class SampleApplicationTest { val removeJob = applicationContext.getBean("removeJob") val now = LocalDate.now() val formatter = DateTimeFormatter.ofPattern("yyyy/MM/dd") - val jobParameters = JobParametersBuilder() - .addString("baseDate", now.format(formatter)) - .addString("dryRun", "true") // set dryRun to 'true' - .toJobParameters() - jobLauncher.run(removeJob, jobParameters) + val jobParameters = + JobParametersBuilder() + .addString("baseDate", now.format(formatter)) + .addString("dryRun", "true") // set dryRun to 'true' + .toJobParameters() + jobOperator.start(removeJob, jobParameters) // all instances should not be removed for (testJobParameters in testJobParameterList) { diff --git a/spring-batch-plus-sample/delete-meta-data-job-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/deletemedadata/dryrun/TestJobConfig.kt b/spring-batch-plus-sample/delete-meta-data-job-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/deletemedadata/dryrun/TestJobConfig.kt index dbb0cb27..9fa19eda 100644 --- a/spring-batch-plus-sample/delete-meta-data-job-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/deletemedadata/dryrun/TestJobConfig.kt +++ b/spring-batch-plus-sample/delete-meta-data-job-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/deletemedadata/dryrun/TestJobConfig.kt @@ -20,10 +20,10 @@ package com.navercorp.spring.batch.plus.sample.deletemedadata.dryrun import com.navercorp.spring.batch.plus.job.metadata.DeleteMetadataJobBuilder import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.Job +import org.springframework.batch.core.job.Job import org.springframework.batch.core.repository.JobRepository -import org.springframework.batch.repeat.RepeatStatus -import org.springframework.boot.autoconfigure.batch.BatchDataSource +import org.springframework.batch.infrastructure.repeat.RepeatStatus +import org.springframework.boot.batch.jdbc.autoconfigure.BatchDataSource import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.transaction.PlatformTransactionManager @@ -34,26 +34,25 @@ open class TestJobConfig( private val batch: BatchDsl, private val transactionManager: PlatformTransactionManager, ) { - @Bean open fun removeJob( @BatchDataSource dataSource: DataSource, jobRepository: JobRepository, - ): Job { - return DeleteMetadataJobBuilder(jobRepository, dataSource) + ): Job = + DeleteMetadataJobBuilder(jobRepository, dataSource) .name("removeJob") .build() - } @Bean - open fun testJob(): Job = batch { - job("testJob") { - step("testStep") { - tasklet( - { _, _ -> RepeatStatus.FINISHED }, - transactionManager, - ) + open fun testJob(): Job = + batch { + job("testJob") { + step("testStep") { + tasklet( + { _, _ -> RepeatStatus.FINISHED }, + transactionManager, + ) + } } } - } } diff --git a/spring-batch-plus-sample/delete-meta-data-job-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/deletemedadata/formatter/JdbcConfig.kt b/spring-batch-plus-sample/delete-meta-data-job-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/deletemedadata/formatter/JdbcConfig.kt index 1cdb3fc4..dce2c001 100644 --- a/spring-batch-plus-sample/delete-meta-data-job-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/deletemedadata/formatter/JdbcConfig.kt +++ b/spring-batch-plus-sample/delete-meta-data-job-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/deletemedadata/formatter/JdbcConfig.kt @@ -18,7 +18,7 @@ package com.navercorp.spring.batch.plus.sample.deletemedadata.formatter -import org.springframework.boot.autoconfigure.batch.BatchDataSource +import org.springframework.boot.batch.jdbc.autoconfigure.BatchDataSource import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder @@ -27,14 +27,12 @@ import javax.sql.DataSource @Configuration open class JdbcConfig { - @BatchDataSource @Bean - open fun dataSource(): DataSource { - return EmbeddedDatabaseBuilder() + open fun dataSource(): DataSource = + EmbeddedDatabaseBuilder() .setType(EmbeddedDatabaseType.H2) .ignoreFailedDrops(true) .generateUniqueName(true) .build() - } } diff --git a/spring-batch-plus-sample/delete-meta-data-job-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/deletemedadata/formatter/SampleApplicationTest.kt b/spring-batch-plus-sample/delete-meta-data-job-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/deletemedadata/formatter/SampleApplicationTest.kt index 777c205d..79bade07 100644 --- a/spring-batch-plus-sample/delete-meta-data-job-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/deletemedadata/formatter/SampleApplicationTest.kt +++ b/spring-batch-plus-sample/delete-meta-data-job-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/deletemedadata/formatter/SampleApplicationTest.kt @@ -19,9 +19,9 @@ package com.navercorp.spring.batch.plus.sample.deletemedadata.formatter import org.junit.jupiter.api.Test -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator import org.springframework.batch.core.repository.JobRepository import org.springframework.beans.factory.getBean import org.springframework.boot.autoconfigure.SpringBootApplication @@ -34,19 +34,20 @@ open class SampleApplicationTest { @Test fun run() { val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() + val jobOperator = applicationContext.getBean() val jobRepository = applicationContext.getBean() // prepare job instances val testJob = applicationContext.getBean("testJob") - val testJobParameterList = (0L..250L).map { - JobParametersBuilder() - .addLong("longValue", it) - .toJobParameters() - } + val testJobParameterList = + (0L..250L).map { + JobParametersBuilder() + .addLong("longValue", it) + .toJobParameters() + } for (testJobParameters in testJobParameterList) { // change create time date for test - val jobExecution = jobLauncher.run(testJob, testJobParameters) + val jobExecution = jobOperator.start(testJob, testJobParameters) jobExecution.createTime = jobExecution.createTime.minusDays(1) jobRepository.update(jobExecution) } @@ -55,10 +56,11 @@ open class SampleApplicationTest { val removeJob = applicationContext.getBean("removeJob") val now = LocalDate.now() val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd") - val jobParameters = JobParametersBuilder() - .addString("baseDate", now.format(formatter)) - .toJobParameters() - jobLauncher.run(removeJob, jobParameters) + val jobParameters = + JobParametersBuilder() + .addString("baseDate", now.format(formatter)) + .toJobParameters() + jobOperator.start(removeJob, jobParameters) // all instances are removed for (testJobParameters in testJobParameterList) { diff --git a/spring-batch-plus-sample/delete-meta-data-job-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/deletemedadata/formatter/TestJobConfig.kt b/spring-batch-plus-sample/delete-meta-data-job-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/deletemedadata/formatter/TestJobConfig.kt index 80071b57..adfc0e8a 100644 --- a/spring-batch-plus-sample/delete-meta-data-job-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/deletemedadata/formatter/TestJobConfig.kt +++ b/spring-batch-plus-sample/delete-meta-data-job-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/deletemedadata/formatter/TestJobConfig.kt @@ -20,10 +20,10 @@ package com.navercorp.spring.batch.plus.sample.deletemedadata.formatter import com.navercorp.spring.batch.plus.job.metadata.DeleteMetadataJobBuilder import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.Job +import org.springframework.batch.core.job.Job import org.springframework.batch.core.repository.JobRepository -import org.springframework.batch.repeat.RepeatStatus -import org.springframework.boot.autoconfigure.batch.BatchDataSource +import org.springframework.batch.infrastructure.repeat.RepeatStatus +import org.springframework.boot.batch.jdbc.autoconfigure.BatchDataSource import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.transaction.PlatformTransactionManager @@ -35,27 +35,26 @@ open class TestJobConfig( private val batch: BatchDsl, private val transactionManager: PlatformTransactionManager, ) { - @Bean open fun removeJob( @BatchDataSource dataSource: DataSource, jobRepository: JobRepository, - ): Job { - return DeleteMetadataJobBuilder(jobRepository, dataSource) + ): Job = + DeleteMetadataJobBuilder(jobRepository, dataSource) .name("removeJob") .baseDateFormatter(DateTimeFormatter.ofPattern("yyyy-MM-dd")) .build() - } @Bean - open fun testJob(): Job = batch { - job("testJob") { - step("testStep") { - tasklet( - { _, _ -> RepeatStatus.FINISHED }, - transactionManager, - ) + open fun testJob(): Job = + batch { + job("testJob") { + step("testStep") { + tasklet( + { _, _ -> RepeatStatus.FINISHED }, + transactionManager, + ) + } } } - } } diff --git a/spring-batch-plus-sample/delete-meta-data-job-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/deletemedadata/jobname/JdbcConfig.kt b/spring-batch-plus-sample/delete-meta-data-job-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/deletemedadata/jobname/JdbcConfig.kt index b7e582b5..b49491c8 100644 --- a/spring-batch-plus-sample/delete-meta-data-job-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/deletemedadata/jobname/JdbcConfig.kt +++ b/spring-batch-plus-sample/delete-meta-data-job-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/deletemedadata/jobname/JdbcConfig.kt @@ -18,7 +18,7 @@ package com.navercorp.spring.batch.plus.sample.deletemedadata.jobname -import org.springframework.boot.autoconfigure.batch.BatchDataSource +import org.springframework.boot.batch.jdbc.autoconfigure.BatchDataSource import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder @@ -27,14 +27,12 @@ import javax.sql.DataSource @Configuration open class JdbcConfig { - @BatchDataSource @Bean - open fun dataSource(): DataSource { - return EmbeddedDatabaseBuilder() + open fun dataSource(): DataSource = + EmbeddedDatabaseBuilder() .setType(EmbeddedDatabaseType.H2) .ignoreFailedDrops(true) .generateUniqueName(true) .build() - } } diff --git a/spring-batch-plus-sample/delete-meta-data-job-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/deletemedadata/jobname/SampleApplicationTest.kt b/spring-batch-plus-sample/delete-meta-data-job-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/deletemedadata/jobname/SampleApplicationTest.kt index 0a57c768..17405660 100644 --- a/spring-batch-plus-sample/delete-meta-data-job-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/deletemedadata/jobname/SampleApplicationTest.kt +++ b/spring-batch-plus-sample/delete-meta-data-job-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/deletemedadata/jobname/SampleApplicationTest.kt @@ -19,9 +19,9 @@ package com.navercorp.spring.batch.plus.sample.deletemedadata.jobname import org.junit.jupiter.api.Test -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator import org.springframework.batch.core.repository.JobRepository import org.springframework.beans.factory.getBean import org.springframework.boot.autoconfigure.SpringBootApplication @@ -34,19 +34,20 @@ open class SampleApplicationTest { @Test fun run() { val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() + val jobOperator = applicationContext.getBean() val jobRepository = applicationContext.getBean() // prepare job instances val testJob = applicationContext.getBean("testJob") - val testJobParameterList = (0L..250L).map { - JobParametersBuilder() - .addLong("longValue", it) - .toJobParameters() - } + val testJobParameterList = + (0L..250L).map { + JobParametersBuilder() + .addLong("longValue", it) + .toJobParameters() + } for (testJobParameters in testJobParameterList) { // change create time date for test - val jobExecution = jobLauncher.run(testJob, testJobParameters) + val jobExecution = jobOperator.start(testJob, testJobParameters) jobExecution.createTime = jobExecution.createTime.minusDays(1) jobRepository.update(jobExecution) } @@ -55,10 +56,11 @@ open class SampleApplicationTest { val removeJob = applicationContext.getBean("removeJob") val now = LocalDate.now() val formatter = DateTimeFormatter.ofPattern("yyyy/MM/dd") - val jobParameters = JobParametersBuilder() - .addString("baseDate", now.format(formatter)) - .toJobParameters() - jobLauncher.run(removeJob, jobParameters) + val jobParameters = + JobParametersBuilder() + .addString("baseDate", now.format(formatter)) + .toJobParameters() + jobOperator.start(removeJob, jobParameters) // all instances are removed for (testJobParameters in testJobParameterList) { diff --git a/spring-batch-plus-sample/delete-meta-data-job-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/deletemedadata/jobname/TestJobConfig.kt b/spring-batch-plus-sample/delete-meta-data-job-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/deletemedadata/jobname/TestJobConfig.kt index 6734b7fa..f1765489 100644 --- a/spring-batch-plus-sample/delete-meta-data-job-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/deletemedadata/jobname/TestJobConfig.kt +++ b/spring-batch-plus-sample/delete-meta-data-job-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/deletemedadata/jobname/TestJobConfig.kt @@ -20,10 +20,10 @@ package com.navercorp.spring.batch.plus.sample.deletemedadata.jobname import com.navercorp.spring.batch.plus.job.metadata.DeleteMetadataJobBuilder import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.Job +import org.springframework.batch.core.job.Job import org.springframework.batch.core.repository.JobRepository -import org.springframework.batch.repeat.RepeatStatus -import org.springframework.boot.autoconfigure.batch.BatchDataSource +import org.springframework.batch.infrastructure.repeat.RepeatStatus +import org.springframework.boot.batch.jdbc.autoconfigure.BatchDataSource import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.transaction.PlatformTransactionManager @@ -34,26 +34,25 @@ open class TestJobConfig( private val batch: BatchDsl, private val transactionManager: PlatformTransactionManager, ) { - @Bean open fun removeJob( @BatchDataSource dataSource: DataSource, jobRepository: JobRepository, - ): Job { - return DeleteMetadataJobBuilder(jobRepository, dataSource) + ): Job = + DeleteMetadataJobBuilder(jobRepository, dataSource) .name("removeJob") .build() - } @Bean - open fun testJob(): Job = batch { - job("testJob") { - step("testStep") { - tasklet( - { _, _ -> RepeatStatus.FINISHED }, - transactionManager, - ) + open fun testJob(): Job = + batch { + job("testJob") { + step("testStep") { + tasklet( + { _, _ -> RepeatStatus.FINISHED }, + transactionManager, + ) + } } } - } } diff --git a/spring-batch-plus-sample/delete-meta-data-job-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/deletemedadata/parametername/JdbcConfig.kt b/spring-batch-plus-sample/delete-meta-data-job-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/deletemedadata/parametername/JdbcConfig.kt index 159bd660..624cef2f 100644 --- a/spring-batch-plus-sample/delete-meta-data-job-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/deletemedadata/parametername/JdbcConfig.kt +++ b/spring-batch-plus-sample/delete-meta-data-job-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/deletemedadata/parametername/JdbcConfig.kt @@ -18,7 +18,7 @@ package com.navercorp.spring.batch.plus.sample.deletemedadata.parametername -import org.springframework.boot.autoconfigure.batch.BatchDataSource +import org.springframework.boot.batch.jdbc.autoconfigure.BatchDataSource import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder @@ -27,14 +27,12 @@ import javax.sql.DataSource @Configuration open class JdbcConfig { - @BatchDataSource @Bean - open fun dataSource(): DataSource { - return EmbeddedDatabaseBuilder() + open fun dataSource(): DataSource = + EmbeddedDatabaseBuilder() .setType(EmbeddedDatabaseType.H2) .ignoreFailedDrops(true) .generateUniqueName(true) .build() - } } diff --git a/spring-batch-plus-sample/delete-meta-data-job-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/deletemedadata/parametername/SampleApplicationTest.kt b/spring-batch-plus-sample/delete-meta-data-job-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/deletemedadata/parametername/SampleApplicationTest.kt index 235483b7..303dcf14 100644 --- a/spring-batch-plus-sample/delete-meta-data-job-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/deletemedadata/parametername/SampleApplicationTest.kt +++ b/spring-batch-plus-sample/delete-meta-data-job-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/deletemedadata/parametername/SampleApplicationTest.kt @@ -19,9 +19,9 @@ package com.navercorp.spring.batch.plus.sample.deletemedadata.parametername import org.junit.jupiter.api.Test -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator import org.springframework.batch.core.repository.JobRepository import org.springframework.beans.factory.getBean import org.springframework.boot.autoconfigure.SpringBootApplication @@ -34,19 +34,20 @@ open class SampleApplicationTest { @Test fun run() { val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() + val jobOperator = applicationContext.getBean() val jobRepository = applicationContext.getBean() // prepare job instances val testJob = applicationContext.getBean("testJob") - val testJobParameterList = (0L..250L).map { - JobParametersBuilder() - .addLong("longValue", it) - .toJobParameters() - } + val testJobParameterList = + (0L..250L).map { + JobParametersBuilder() + .addLong("longValue", it) + .toJobParameters() + } for (testJobParameters in testJobParameterList) { // change create time date for test - val jobExecution = jobLauncher.run(testJob, testJobParameters) + val jobExecution = jobOperator.start(testJob, testJobParameters) jobExecution.createTime = jobExecution.createTime.minusDays(1) jobRepository.update(jobExecution) } @@ -55,10 +56,11 @@ open class SampleApplicationTest { val removeJob = applicationContext.getBean("removeJob") val now = LocalDate.now() val formatter = DateTimeFormatter.ofPattern("yyyy/MM/dd") - val jobParameters = JobParametersBuilder() - .addString("base", now.format(formatter)) // custom naming - .toJobParameters() - jobLauncher.run(removeJob, jobParameters) + val jobParameters = + JobParametersBuilder() + .addString("base", now.format(formatter)) // custom naming + .toJobParameters() + jobOperator.start(removeJob, jobParameters) // all instances are removed for (testJobParameters in testJobParameterList) { diff --git a/spring-batch-plus-sample/delete-meta-data-job-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/deletemedadata/parametername/TestJobConfig.kt b/spring-batch-plus-sample/delete-meta-data-job-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/deletemedadata/parametername/TestJobConfig.kt index 2d5309f0..8f62c869 100644 --- a/spring-batch-plus-sample/delete-meta-data-job-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/deletemedadata/parametername/TestJobConfig.kt +++ b/spring-batch-plus-sample/delete-meta-data-job-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/deletemedadata/parametername/TestJobConfig.kt @@ -20,10 +20,10 @@ package com.navercorp.spring.batch.plus.sample.deletemedadata.parametername import com.navercorp.spring.batch.plus.job.metadata.DeleteMetadataJobBuilder import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.Job +import org.springframework.batch.core.job.Job import org.springframework.batch.core.repository.JobRepository -import org.springframework.batch.repeat.RepeatStatus -import org.springframework.boot.autoconfigure.batch.BatchDataSource +import org.springframework.batch.infrastructure.repeat.RepeatStatus +import org.springframework.boot.batch.jdbc.autoconfigure.BatchDataSource import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.transaction.PlatformTransactionManager @@ -34,27 +34,26 @@ open class TestJobConfig( private val batch: BatchDsl, private val transactionManager: PlatformTransactionManager, ) { - @Bean open fun removeJob( @BatchDataSource dataSource: DataSource, jobRepository: JobRepository, - ): Job { - return DeleteMetadataJobBuilder(jobRepository, dataSource) + ): Job = + DeleteMetadataJobBuilder(jobRepository, dataSource) .name("removeJob") .baseDateParameterName("base") .build() - } @Bean - open fun testJob(): Job = batch { - job("testJob") { - step("testStep") { - tasklet( - { _, _ -> RepeatStatus.FINISHED }, - transactionManager, - ) + open fun testJob(): Job = + batch { + job("testJob") { + step("testStep") { + tasklet( + { _, _ -> RepeatStatus.FINISHED }, + transactionManager, + ) + } } } - } } diff --git a/spring-batch-plus-sample/delete-meta-data-job-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/deletemedadata/plain/JdbcConfig.kt b/spring-batch-plus-sample/delete-meta-data-job-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/deletemedadata/plain/JdbcConfig.kt index dae66227..d5d92d59 100644 --- a/spring-batch-plus-sample/delete-meta-data-job-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/deletemedadata/plain/JdbcConfig.kt +++ b/spring-batch-plus-sample/delete-meta-data-job-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/deletemedadata/plain/JdbcConfig.kt @@ -18,7 +18,7 @@ package com.navercorp.spring.batch.plus.sample.deletemedadata.plain -import org.springframework.boot.autoconfigure.batch.BatchDataSource +import org.springframework.boot.batch.jdbc.autoconfigure.BatchDataSource import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder @@ -27,14 +27,12 @@ import javax.sql.DataSource @Configuration open class JdbcConfig { - @BatchDataSource @Bean - open fun dataSource(): DataSource { - return EmbeddedDatabaseBuilder() + open fun dataSource(): DataSource = + EmbeddedDatabaseBuilder() .setType(EmbeddedDatabaseType.H2) .ignoreFailedDrops(true) .generateUniqueName(true) .build() - } } diff --git a/spring-batch-plus-sample/delete-meta-data-job-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/deletemedadata/plain/SampleApplicationTest.kt b/spring-batch-plus-sample/delete-meta-data-job-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/deletemedadata/plain/SampleApplicationTest.kt index 6eeda43d..270151f6 100644 --- a/spring-batch-plus-sample/delete-meta-data-job-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/deletemedadata/plain/SampleApplicationTest.kt +++ b/spring-batch-plus-sample/delete-meta-data-job-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/deletemedadata/plain/SampleApplicationTest.kt @@ -19,9 +19,9 @@ package com.navercorp.spring.batch.plus.sample.deletemedadata.plain import org.junit.jupiter.api.Test -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator import org.springframework.batch.core.repository.JobRepository import org.springframework.beans.factory.getBean import org.springframework.boot.autoconfigure.SpringBootApplication @@ -34,19 +34,20 @@ open class SampleApplicationTest { @Test fun run() { val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() + val jobOperator = applicationContext.getBean() val jobRepository = applicationContext.getBean() // prepare job instances val testJob = applicationContext.getBean("testJob") - val testJobParameterList = (0L..250L).map { - JobParametersBuilder() - .addLong("longValue", it) - .toJobParameters() - } + val testJobParameterList = + (0L..250L).map { + JobParametersBuilder() + .addLong("longValue", it) + .toJobParameters() + } for (testJobParameters in testJobParameterList) { // change create time date for test - val jobExecution = jobLauncher.run(testJob, testJobParameters) + val jobExecution = jobOperator.start(testJob, testJobParameters) jobExecution.createTime = jobExecution.createTime.minusDays(1) jobRepository.update(jobExecution) } @@ -55,10 +56,11 @@ open class SampleApplicationTest { val removeJob = applicationContext.getBean("deleteMetadataJob") val now = LocalDate.now() val formatter = DateTimeFormatter.ofPattern("yyyy/MM/dd") - val jobParameters = JobParametersBuilder() - .addString("baseDate", now.format(formatter)) - .toJobParameters() - jobLauncher.run(removeJob, jobParameters) + val jobParameters = + JobParametersBuilder() + .addString("baseDate", now.format(formatter)) + .toJobParameters() + jobOperator.start(removeJob, jobParameters) // all instances are removed for (testJobParameters in testJobParameterList) { diff --git a/spring-batch-plus-sample/delete-meta-data-job-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/deletemedadata/plain/TestJobConfig.kt b/spring-batch-plus-sample/delete-meta-data-job-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/deletemedadata/plain/TestJobConfig.kt index a21c0f73..cf95dea7 100644 --- a/spring-batch-plus-sample/delete-meta-data-job-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/deletemedadata/plain/TestJobConfig.kt +++ b/spring-batch-plus-sample/delete-meta-data-job-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/deletemedadata/plain/TestJobConfig.kt @@ -20,10 +20,10 @@ package com.navercorp.spring.batch.plus.sample.deletemedadata.plain import com.navercorp.spring.batch.plus.job.metadata.DeleteMetadataJobBuilder import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.Job +import org.springframework.batch.core.job.Job import org.springframework.batch.core.repository.JobRepository -import org.springframework.batch.repeat.RepeatStatus -import org.springframework.boot.autoconfigure.batch.BatchDataSource +import org.springframework.batch.infrastructure.repeat.RepeatStatus +import org.springframework.boot.batch.jdbc.autoconfigure.BatchDataSource import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.transaction.PlatformTransactionManager @@ -34,25 +34,24 @@ open class TestJobConfig( private val batch: BatchDsl, private val transactionManager: PlatformTransactionManager, ) { - @Bean open fun deleteMetadataJob( @BatchDataSource dataSource: DataSource, jobRepository: JobRepository, - ): Job { - return DeleteMetadataJobBuilder(jobRepository, dataSource) + ): Job = + DeleteMetadataJobBuilder(jobRepository, dataSource) .build() - } @Bean - open fun testJob(): Job = batch { - job("testJob") { - step("testStep") { - tasklet( - { _, _ -> RepeatStatus.FINISHED }, - transactionManager, - ) + open fun testJob(): Job = + batch { + job("testJob") { + step("testStep") { + tasklet( + { _, _ -> RepeatStatus.FINISHED }, + transactionManager, + ) + } } } - } } diff --git a/spring-batch-plus-sample/delete-meta-data-job-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/deletemedadata/prefix/JdbcConfig.kt b/spring-batch-plus-sample/delete-meta-data-job-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/deletemedadata/prefix/JdbcConfig.kt index 84427780..0188302c 100644 --- a/spring-batch-plus-sample/delete-meta-data-job-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/deletemedadata/prefix/JdbcConfig.kt +++ b/spring-batch-plus-sample/delete-meta-data-job-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/deletemedadata/prefix/JdbcConfig.kt @@ -18,7 +18,7 @@ package com.navercorp.spring.batch.plus.sample.deletemedadata.prefix -import org.springframework.boot.autoconfigure.batch.BatchDataSource +import org.springframework.boot.batch.jdbc.autoconfigure.BatchDataSource import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder @@ -27,15 +27,13 @@ import javax.sql.DataSource @Configuration open class JdbcConfig { - @BatchDataSource @Bean - open fun dataSource(): DataSource { - return EmbeddedDatabaseBuilder() + open fun dataSource(): DataSource = + EmbeddedDatabaseBuilder() .setType(EmbeddedDatabaseType.H2) .addScript("classpath:sql/schema-h2-custom.sql") .ignoreFailedDrops(true) .generateUniqueName(true) .build() - } } diff --git a/spring-batch-plus-sample/delete-meta-data-job-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/deletemedadata/prefix/SampleApplicationTest.kt b/spring-batch-plus-sample/delete-meta-data-job-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/deletemedadata/prefix/SampleApplicationTest.kt index 9de7b78a..617dd676 100644 --- a/spring-batch-plus-sample/delete-meta-data-job-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/deletemedadata/prefix/SampleApplicationTest.kt +++ b/spring-batch-plus-sample/delete-meta-data-job-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/deletemedadata/prefix/SampleApplicationTest.kt @@ -19,9 +19,9 @@ package com.navercorp.spring.batch.plus.sample.deletemedadata.prefix import org.junit.jupiter.api.Test -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator import org.springframework.batch.core.repository.JobRepository import org.springframework.beans.factory.getBean import org.springframework.boot.SpringApplication @@ -35,26 +35,29 @@ open class SampleApplicationTest { @Test fun run() { // launch with custom prefix - val application = SpringApplication(SampleApplicationTest::class.java).apply { - val properties = Properties().apply { - this["spring.batch.jdbc.table-prefix"] = "CUSTOM_" + val application = + SpringApplication(SampleApplicationTest::class.java).apply { + val properties = + Properties().apply { + this["spring.batch.jdbc.table-prefix"] = "CUSTOM_" + } + setDefaultProperties(properties) } - setDefaultProperties(properties) - } val applicationContext = application.run() - val jobLauncher = applicationContext.getBean() + val jobOperator = applicationContext.getBean() val jobRepository = applicationContext.getBean() // prepare job instances val testJob = applicationContext.getBean("testJob") - val testJobParameterList = (0L..250L).map { - JobParametersBuilder() - .addLong("longValue", it) - .toJobParameters() - } + val testJobParameterList = + (0L..250L).map { + JobParametersBuilder() + .addLong("longValue", it) + .toJobParameters() + } for (testJobParameters in testJobParameterList) { // change create time date for test - val jobExecution = jobLauncher.run(testJob, testJobParameters) + val jobExecution = jobOperator.start(testJob, testJobParameters) jobExecution.createTime = jobExecution.createTime.minusDays(1) jobRepository.update(jobExecution) } @@ -63,10 +66,11 @@ open class SampleApplicationTest { val removeJob = applicationContext.getBean("removeJob") val now = LocalDate.now() val formatter = DateTimeFormatter.ofPattern("yyyy/MM/dd") - val jobParameters = JobParametersBuilder() - .addString("baseDate", now.format(formatter)) - .toJobParameters() - jobLauncher.run(removeJob, jobParameters) + val jobParameters = + JobParametersBuilder() + .addString("baseDate", now.format(formatter)) + .toJobParameters() + jobOperator.start(removeJob, jobParameters) // all instances are removed for (testJobParameters in testJobParameterList) { diff --git a/spring-batch-plus-sample/delete-meta-data-job-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/deletemedadata/prefix/TestJobConfig.kt b/spring-batch-plus-sample/delete-meta-data-job-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/deletemedadata/prefix/TestJobConfig.kt index 23a9530c..395fc31b 100644 --- a/spring-batch-plus-sample/delete-meta-data-job-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/deletemedadata/prefix/TestJobConfig.kt +++ b/spring-batch-plus-sample/delete-meta-data-job-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/deletemedadata/prefix/TestJobConfig.kt @@ -20,10 +20,10 @@ package com.navercorp.spring.batch.plus.sample.deletemedadata.prefix import com.navercorp.spring.batch.plus.job.metadata.DeleteMetadataJobBuilder import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.Job +import org.springframework.batch.core.job.Job import org.springframework.batch.core.repository.JobRepository -import org.springframework.batch.repeat.RepeatStatus -import org.springframework.boot.autoconfigure.batch.BatchDataSource +import org.springframework.batch.infrastructure.repeat.RepeatStatus +import org.springframework.boot.batch.jdbc.autoconfigure.BatchDataSource import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.transaction.PlatformTransactionManager @@ -34,27 +34,26 @@ open class TestJobConfig( private val batch: BatchDsl, private val transactionManager: PlatformTransactionManager, ) { - @Bean open fun removeJob( @BatchDataSource dataSource: DataSource, jobRepository: JobRepository, - ): Job { - return DeleteMetadataJobBuilder(jobRepository, dataSource) + ): Job = + DeleteMetadataJobBuilder(jobRepository, dataSource) .name("removeJob") .tablePrefix("CUSTOM_") .build() - } @Bean - open fun testJob(): Job = batch { - job("testJob") { - step("testStep") { - tasklet( - { _, _ -> RepeatStatus.FINISHED }, - transactionManager, - ) + open fun testJob(): Job = + batch { + job("testJob") { + step("testStep") { + tasklet( + { _, _ -> RepeatStatus.FINISHED }, + transactionManager, + ) + } } } - } } diff --git a/spring-batch-plus-sample/delete-meta-data-job-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/deletemedadata/prefixfromvariable/JdbcConfig.kt b/spring-batch-plus-sample/delete-meta-data-job-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/deletemedadata/prefixfromvariable/JdbcConfig.kt index b08910a4..f091ae08 100644 --- a/spring-batch-plus-sample/delete-meta-data-job-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/deletemedadata/prefixfromvariable/JdbcConfig.kt +++ b/spring-batch-plus-sample/delete-meta-data-job-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/deletemedadata/prefixfromvariable/JdbcConfig.kt @@ -18,7 +18,7 @@ package com.navercorp.spring.batch.plus.sample.deletemedadata.prefixfromvariable -import org.springframework.boot.autoconfigure.batch.BatchDataSource +import org.springframework.boot.batch.jdbc.autoconfigure.BatchDataSource import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder @@ -28,16 +28,14 @@ import javax.sql.DataSource @Configuration open class JdbcConfig { - @BatchDataSource @Bean - open fun dataSource(): DataSource { - return EmbeddedDatabaseBuilder() + open fun dataSource(): DataSource = + EmbeddedDatabaseBuilder() .setName(UUID.randomUUID().toString()) .setType(EmbeddedDatabaseType.H2) .addScript("classpath:sql/schema-h2-custom.sql") .ignoreFailedDrops(true) .generateUniqueName(true) .build() - } } diff --git a/spring-batch-plus-sample/delete-meta-data-job-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/deletemedadata/prefixfromvariable/SampleApplicationTest.kt b/spring-batch-plus-sample/delete-meta-data-job-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/deletemedadata/prefixfromvariable/SampleApplicationTest.kt index 3d65d626..545e67d0 100644 --- a/spring-batch-plus-sample/delete-meta-data-job-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/deletemedadata/prefixfromvariable/SampleApplicationTest.kt +++ b/spring-batch-plus-sample/delete-meta-data-job-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/deletemedadata/prefixfromvariable/SampleApplicationTest.kt @@ -19,9 +19,9 @@ package com.navercorp.spring.batch.plus.sample.deletemedadata.prefixfromvariable import org.junit.jupiter.api.Test -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator import org.springframework.batch.core.repository.JobRepository import org.springframework.beans.factory.getBean import org.springframework.boot.SpringApplication @@ -35,26 +35,29 @@ open class SampleApplicationTest { @Test fun run() { // launch with custom prefix - val application = SpringApplication(SampleApplicationTest::class.java).apply { - val properties = Properties().apply { - this["spring.batch.jdbc.table-prefix"] = "CUSTOM_" + val application = + SpringApplication(SampleApplicationTest::class.java).apply { + val properties = + Properties().apply { + this["spring.batch.jdbc.table-prefix"] = "CUSTOM_" + } + setDefaultProperties(properties) } - setDefaultProperties(properties) - } val applicationContext = application.run() - val jobLauncher = applicationContext.getBean() + val jobOperator = applicationContext.getBean() val jobRepository = applicationContext.getBean() // prepare job instances val testJob = applicationContext.getBean("testJob") - val testJobParameterList = (0L..250L).map { - JobParametersBuilder() - .addLong("longValue", it) - .toJobParameters() - } + val testJobParameterList = + (0L..250L).map { + JobParametersBuilder() + .addLong("longValue", it) + .toJobParameters() + } for (testJobParameters in testJobParameterList) { // change create time date for test - val jobExecution = jobLauncher.run(testJob, testJobParameters) + val jobExecution = jobOperator.start(testJob, testJobParameters) jobExecution.createTime = jobExecution.createTime.minusDays(1) jobRepository.update(jobExecution) } @@ -63,10 +66,11 @@ open class SampleApplicationTest { val removeJob = applicationContext.getBean("removeJob") val now = LocalDate.now() val formatter = DateTimeFormatter.ofPattern("yyyy/MM/dd") - val jobParameters = JobParametersBuilder() - .addString("baseDate", now.format(formatter)) - .toJobParameters() - jobLauncher.run(removeJob, jobParameters) + val jobParameters = + JobParametersBuilder() + .addString("baseDate", now.format(formatter)) + .toJobParameters() + jobOperator.start(removeJob, jobParameters) // all instances are removed for (testJobParameters in testJobParameterList) { diff --git a/spring-batch-plus-sample/delete-meta-data-job-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/deletemedadata/prefixfromvariable/TestJobConfig.kt b/spring-batch-plus-sample/delete-meta-data-job-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/deletemedadata/prefixfromvariable/TestJobConfig.kt index d2e40ac6..ccfe048e 100644 --- a/spring-batch-plus-sample/delete-meta-data-job-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/deletemedadata/prefixfromvariable/TestJobConfig.kt +++ b/spring-batch-plus-sample/delete-meta-data-job-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/deletemedadata/prefixfromvariable/TestJobConfig.kt @@ -20,11 +20,11 @@ package com.navercorp.spring.batch.plus.sample.deletemedadata.prefixfromvariable import com.navercorp.spring.batch.plus.job.metadata.DeleteMetadataJobBuilder import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.Job +import org.springframework.batch.core.job.Job import org.springframework.batch.core.repository.JobRepository -import org.springframework.batch.repeat.RepeatStatus -import org.springframework.boot.autoconfigure.batch.BatchDataSource -import org.springframework.boot.autoconfigure.batch.BatchProperties +import org.springframework.batch.infrastructure.repeat.RepeatStatus +import org.springframework.boot.batch.jdbc.autoconfigure.BatchDataSource +import org.springframework.boot.batch.jdbc.autoconfigure.BatchJdbcProperties import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.transaction.PlatformTransactionManager @@ -35,14 +35,13 @@ open class TestJobConfig( private val batch: BatchDsl, private val transactionManager: PlatformTransactionManager, ) { - @Bean open fun removeJob( @BatchDataSource dataSource: DataSource, jobRepository: JobRepository, - properties: BatchProperties, + properties: BatchJdbcProperties, ): Job { - val tablePrefix = properties.jdbc.tablePrefix + val tablePrefix = properties.tablePrefix!! return DeleteMetadataJobBuilder(jobRepository, dataSource) .name("removeJob") .tablePrefix(tablePrefix) @@ -50,14 +49,15 @@ open class TestJobConfig( } @Bean - open fun testJob(): Job = batch { - job("testJob") { - step("testStep") { - tasklet( - { _, _ -> RepeatStatus.FINISHED }, - transactionManager, - ) + open fun testJob(): Job = + batch { + job("testJob") { + step("testStep") { + tasklet( + { _, _ -> RepeatStatus.FINISHED }, + transactionManager, + ) + } } } - } } diff --git a/spring-batch-plus-sample/delete-meta-data-job-kotlin-sample/src/test/resources/sql/schema-h2-custom.sql b/spring-batch-plus-sample/delete-meta-data-job-kotlin-sample/src/test/resources/sql/schema-h2-custom.sql index 718302fb..a65cc0f5 100644 --- a/spring-batch-plus-sample/delete-meta-data-job-kotlin-sample/src/test/resources/sql/schema-h2-custom.sql +++ b/spring-batch-plus-sample/delete-meta-data-job-kotlin-sample/src/test/resources/sql/schema-h2-custom.sql @@ -73,4 +73,4 @@ CREATE TABLE CUSTOM_JOB_EXECUTION_CONTEXT ( CREATE SEQUENCE CUSTOM_STEP_EXECUTION_SEQ; CREATE SEQUENCE CUSTOM_JOB_EXECUTION_SEQ; -CREATE SEQUENCE CUSTOM_JOB_SEQ; +CREATE SEQUENCE CUSTOM_JOB_INSTANCE_SEQ; diff --git a/spring-batch-plus-sample/delete-meta-data-job-sample/build.gradle.kts b/spring-batch-plus-sample/delete-meta-data-job-sample/build.gradle.kts index 495c7926..5f869286 100644 --- a/spring-batch-plus-sample/delete-meta-data-job-sample/build.gradle.kts +++ b/spring-batch-plus-sample/delete-meta-data-job-sample/build.gradle.kts @@ -27,14 +27,14 @@ tasks.named("test") { dependencyManagement { imports { - mavenBom("org.springframework.boot:spring-boot-dependencies:3.5.0") + mavenBom("org.springframework.boot:spring-boot-dependencies:4.0.7") } } dependencies { - implementation("org.springframework.boot:spring-boot-starter-batch") + implementation("org.springframework.boot:spring-boot-starter-batch-jdbc") implementation(project(":spring-boot-starter-batch-plus")) - runtimeOnly("com.h2database:h2:2.1.214") + runtimeOnly("com.h2database:h2:2.4.240") testImplementation("org.springframework.boot:spring-boot-starter-test") testRuntimeOnly("org.junit.platform:junit-platform-launcher") diff --git a/spring-batch-plus-sample/delete-meta-data-job-sample/src/test/java/com/navercorp/spring/batch/plus/sample/deletemetadata/customdryrun/JdbcConfig.java b/spring-batch-plus-sample/delete-meta-data-job-sample/src/test/java/com/navercorp/spring/batch/plus/sample/deletemetadata/customdryrun/JdbcConfig.java index 2ce45232..a9d6526b 100644 --- a/spring-batch-plus-sample/delete-meta-data-job-sample/src/test/java/com/navercorp/spring/batch/plus/sample/deletemetadata/customdryrun/JdbcConfig.java +++ b/spring-batch-plus-sample/delete-meta-data-job-sample/src/test/java/com/navercorp/spring/batch/plus/sample/deletemetadata/customdryrun/JdbcConfig.java @@ -20,7 +20,7 @@ import javax.sql.DataSource; -import org.springframework.boot.autoconfigure.batch.BatchDataSource; +import org.springframework.boot.batch.jdbc.autoconfigure.BatchDataSource; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; diff --git a/spring-batch-plus-sample/delete-meta-data-job-sample/src/test/java/com/navercorp/spring/batch/plus/sample/deletemetadata/customdryrun/SampleApplicationTest.java b/spring-batch-plus-sample/delete-meta-data-job-sample/src/test/java/com/navercorp/spring/batch/plus/sample/deletemetadata/customdryrun/SampleApplicationTest.java index 7795e232..5789025c 100644 --- a/spring-batch-plus-sample/delete-meta-data-job-sample/src/test/java/com/navercorp/spring/batch/plus/sample/deletemetadata/customdryrun/SampleApplicationTest.java +++ b/spring-batch-plus-sample/delete-meta-data-job-sample/src/test/java/com/navercorp/spring/batch/plus/sample/deletemetadata/customdryrun/SampleApplicationTest.java @@ -24,11 +24,11 @@ import java.util.stream.LongStream; import org.junit.jupiter.api.Test; -import org.springframework.batch.core.Job; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.JobInstance; -import org.springframework.batch.core.JobParameters; -import org.springframework.batch.core.JobParametersBuilder; +import org.springframework.batch.core.job.Job; +import org.springframework.batch.core.job.JobExecution; +import org.springframework.batch.core.job.JobInstance; +import org.springframework.batch.core.job.parameters.JobParameters; +import org.springframework.batch.core.job.parameters.JobParametersBuilder; import org.springframework.batch.core.launch.JobLauncher; import org.springframework.batch.core.repository.JobRepository; import org.springframework.boot.SpringApplication; diff --git a/spring-batch-plus-sample/delete-meta-data-job-sample/src/test/java/com/navercorp/spring/batch/plus/sample/deletemetadata/customdryrun/TestJobConfig.java b/spring-batch-plus-sample/delete-meta-data-job-sample/src/test/java/com/navercorp/spring/batch/plus/sample/deletemetadata/customdryrun/TestJobConfig.java index 8e133b1c..276e2317 100644 --- a/spring-batch-plus-sample/delete-meta-data-job-sample/src/test/java/com/navercorp/spring/batch/plus/sample/deletemetadata/customdryrun/TestJobConfig.java +++ b/spring-batch-plus-sample/delete-meta-data-job-sample/src/test/java/com/navercorp/spring/batch/plus/sample/deletemetadata/customdryrun/TestJobConfig.java @@ -20,13 +20,13 @@ import javax.sql.DataSource; -import org.springframework.batch.core.Job; +import org.springframework.batch.core.job.Job; import org.springframework.batch.core.job.builder.JobBuilder; -import org.springframework.batch.core.launch.support.RunIdIncrementer; +import org.springframework.batch.core.job.parameters.RunIdIncrementer; import org.springframework.batch.core.repository.JobRepository; import org.springframework.batch.core.step.builder.StepBuilder; -import org.springframework.batch.repeat.RepeatStatus; -import org.springframework.boot.autoconfigure.batch.BatchDataSource; +import org.springframework.batch.infrastructure.repeat.RepeatStatus; +import org.springframework.boot.batch.jdbc.autoconfigure.BatchDataSource; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.transaction.PlatformTransactionManager; diff --git a/spring-batch-plus-sample/delete-meta-data-job-sample/src/test/java/com/navercorp/spring/batch/plus/sample/deletemetadata/dryrun/JdbcConfig.java b/spring-batch-plus-sample/delete-meta-data-job-sample/src/test/java/com/navercorp/spring/batch/plus/sample/deletemetadata/dryrun/JdbcConfig.java index d3d3ad7b..b11d43a6 100644 --- a/spring-batch-plus-sample/delete-meta-data-job-sample/src/test/java/com/navercorp/spring/batch/plus/sample/deletemetadata/dryrun/JdbcConfig.java +++ b/spring-batch-plus-sample/delete-meta-data-job-sample/src/test/java/com/navercorp/spring/batch/plus/sample/deletemetadata/dryrun/JdbcConfig.java @@ -20,7 +20,7 @@ import javax.sql.DataSource; -import org.springframework.boot.autoconfigure.batch.BatchDataSource; +import org.springframework.boot.batch.jdbc.autoconfigure.BatchDataSource; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; diff --git a/spring-batch-plus-sample/delete-meta-data-job-sample/src/test/java/com/navercorp/spring/batch/plus/sample/deletemetadata/dryrun/SampleApplicationTest.java b/spring-batch-plus-sample/delete-meta-data-job-sample/src/test/java/com/navercorp/spring/batch/plus/sample/deletemetadata/dryrun/SampleApplicationTest.java index 63bdc28f..0ad2423e 100644 --- a/spring-batch-plus-sample/delete-meta-data-job-sample/src/test/java/com/navercorp/spring/batch/plus/sample/deletemetadata/dryrun/SampleApplicationTest.java +++ b/spring-batch-plus-sample/delete-meta-data-job-sample/src/test/java/com/navercorp/spring/batch/plus/sample/deletemetadata/dryrun/SampleApplicationTest.java @@ -24,11 +24,11 @@ import java.util.stream.LongStream; import org.junit.jupiter.api.Test; -import org.springframework.batch.core.Job; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.JobInstance; -import org.springframework.batch.core.JobParameters; -import org.springframework.batch.core.JobParametersBuilder; +import org.springframework.batch.core.job.Job; +import org.springframework.batch.core.job.JobExecution; +import org.springframework.batch.core.job.JobInstance; +import org.springframework.batch.core.job.parameters.JobParameters; +import org.springframework.batch.core.job.parameters.JobParametersBuilder; import org.springframework.batch.core.launch.JobLauncher; import org.springframework.batch.core.repository.JobRepository; import org.springframework.boot.SpringApplication; diff --git a/spring-batch-plus-sample/delete-meta-data-job-sample/src/test/java/com/navercorp/spring/batch/plus/sample/deletemetadata/dryrun/TestJobConfig.java b/spring-batch-plus-sample/delete-meta-data-job-sample/src/test/java/com/navercorp/spring/batch/plus/sample/deletemetadata/dryrun/TestJobConfig.java index ca771e3d..5aeb9566 100644 --- a/spring-batch-plus-sample/delete-meta-data-job-sample/src/test/java/com/navercorp/spring/batch/plus/sample/deletemetadata/dryrun/TestJobConfig.java +++ b/spring-batch-plus-sample/delete-meta-data-job-sample/src/test/java/com/navercorp/spring/batch/plus/sample/deletemetadata/dryrun/TestJobConfig.java @@ -20,13 +20,13 @@ import javax.sql.DataSource; -import org.springframework.batch.core.Job; +import org.springframework.batch.core.job.Job; import org.springframework.batch.core.job.builder.JobBuilder; -import org.springframework.batch.core.launch.support.RunIdIncrementer; +import org.springframework.batch.core.job.parameters.RunIdIncrementer; import org.springframework.batch.core.repository.JobRepository; import org.springframework.batch.core.step.builder.StepBuilder; -import org.springframework.batch.repeat.RepeatStatus; -import org.springframework.boot.autoconfigure.batch.BatchDataSource; +import org.springframework.batch.infrastructure.repeat.RepeatStatus; +import org.springframework.boot.batch.jdbc.autoconfigure.BatchDataSource; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.transaction.PlatformTransactionManager; diff --git a/spring-batch-plus-sample/delete-meta-data-job-sample/src/test/java/com/navercorp/spring/batch/plus/sample/deletemetadata/formatter/JdbcConfig.java b/spring-batch-plus-sample/delete-meta-data-job-sample/src/test/java/com/navercorp/spring/batch/plus/sample/deletemetadata/formatter/JdbcConfig.java index 9bfe1ffd..54df5b62 100644 --- a/spring-batch-plus-sample/delete-meta-data-job-sample/src/test/java/com/navercorp/spring/batch/plus/sample/deletemetadata/formatter/JdbcConfig.java +++ b/spring-batch-plus-sample/delete-meta-data-job-sample/src/test/java/com/navercorp/spring/batch/plus/sample/deletemetadata/formatter/JdbcConfig.java @@ -20,7 +20,7 @@ import javax.sql.DataSource; -import org.springframework.boot.autoconfigure.batch.BatchDataSource; +import org.springframework.boot.batch.jdbc.autoconfigure.BatchDataSource; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; diff --git a/spring-batch-plus-sample/delete-meta-data-job-sample/src/test/java/com/navercorp/spring/batch/plus/sample/deletemetadata/formatter/SampleApplicationTest.java b/spring-batch-plus-sample/delete-meta-data-job-sample/src/test/java/com/navercorp/spring/batch/plus/sample/deletemetadata/formatter/SampleApplicationTest.java index 46ce3c4c..a6a985ab 100644 --- a/spring-batch-plus-sample/delete-meta-data-job-sample/src/test/java/com/navercorp/spring/batch/plus/sample/deletemetadata/formatter/SampleApplicationTest.java +++ b/spring-batch-plus-sample/delete-meta-data-job-sample/src/test/java/com/navercorp/spring/batch/plus/sample/deletemetadata/formatter/SampleApplicationTest.java @@ -24,11 +24,11 @@ import java.util.stream.LongStream; import org.junit.jupiter.api.Test; -import org.springframework.batch.core.Job; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.JobInstance; -import org.springframework.batch.core.JobParameters; -import org.springframework.batch.core.JobParametersBuilder; +import org.springframework.batch.core.job.Job; +import org.springframework.batch.core.job.JobExecution; +import org.springframework.batch.core.job.JobInstance; +import org.springframework.batch.core.job.parameters.JobParameters; +import org.springframework.batch.core.job.parameters.JobParametersBuilder; import org.springframework.batch.core.launch.JobLauncher; import org.springframework.batch.core.repository.JobRepository; import org.springframework.boot.SpringApplication; diff --git a/spring-batch-plus-sample/delete-meta-data-job-sample/src/test/java/com/navercorp/spring/batch/plus/sample/deletemetadata/formatter/TestJobConfig.java b/spring-batch-plus-sample/delete-meta-data-job-sample/src/test/java/com/navercorp/spring/batch/plus/sample/deletemetadata/formatter/TestJobConfig.java index f9ce2588..f7cd0e5a 100644 --- a/spring-batch-plus-sample/delete-meta-data-job-sample/src/test/java/com/navercorp/spring/batch/plus/sample/deletemetadata/formatter/TestJobConfig.java +++ b/spring-batch-plus-sample/delete-meta-data-job-sample/src/test/java/com/navercorp/spring/batch/plus/sample/deletemetadata/formatter/TestJobConfig.java @@ -22,13 +22,13 @@ import javax.sql.DataSource; -import org.springframework.batch.core.Job; +import org.springframework.batch.core.job.Job; import org.springframework.batch.core.job.builder.JobBuilder; -import org.springframework.batch.core.launch.support.RunIdIncrementer; +import org.springframework.batch.core.job.parameters.RunIdIncrementer; import org.springframework.batch.core.repository.JobRepository; import org.springframework.batch.core.step.builder.StepBuilder; -import org.springframework.batch.repeat.RepeatStatus; -import org.springframework.boot.autoconfigure.batch.BatchDataSource; +import org.springframework.batch.infrastructure.repeat.RepeatStatus; +import org.springframework.boot.batch.jdbc.autoconfigure.BatchDataSource; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.transaction.PlatformTransactionManager; diff --git a/spring-batch-plus-sample/delete-meta-data-job-sample/src/test/java/com/navercorp/spring/batch/plus/sample/deletemetadata/jobname/JdbcConfig.java b/spring-batch-plus-sample/delete-meta-data-job-sample/src/test/java/com/navercorp/spring/batch/plus/sample/deletemetadata/jobname/JdbcConfig.java index b153ef3d..b576f204 100644 --- a/spring-batch-plus-sample/delete-meta-data-job-sample/src/test/java/com/navercorp/spring/batch/plus/sample/deletemetadata/jobname/JdbcConfig.java +++ b/spring-batch-plus-sample/delete-meta-data-job-sample/src/test/java/com/navercorp/spring/batch/plus/sample/deletemetadata/jobname/JdbcConfig.java @@ -20,7 +20,7 @@ import javax.sql.DataSource; -import org.springframework.boot.autoconfigure.batch.BatchDataSource; +import org.springframework.boot.batch.jdbc.autoconfigure.BatchDataSource; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; diff --git a/spring-batch-plus-sample/delete-meta-data-job-sample/src/test/java/com/navercorp/spring/batch/plus/sample/deletemetadata/jobname/SampleApplicationTest.java b/spring-batch-plus-sample/delete-meta-data-job-sample/src/test/java/com/navercorp/spring/batch/plus/sample/deletemetadata/jobname/SampleApplicationTest.java index 269fff53..ad0dfab6 100644 --- a/spring-batch-plus-sample/delete-meta-data-job-sample/src/test/java/com/navercorp/spring/batch/plus/sample/deletemetadata/jobname/SampleApplicationTest.java +++ b/spring-batch-plus-sample/delete-meta-data-job-sample/src/test/java/com/navercorp/spring/batch/plus/sample/deletemetadata/jobname/SampleApplicationTest.java @@ -24,11 +24,11 @@ import java.util.stream.LongStream; import org.junit.jupiter.api.Test; -import org.springframework.batch.core.Job; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.JobInstance; -import org.springframework.batch.core.JobParameters; -import org.springframework.batch.core.JobParametersBuilder; +import org.springframework.batch.core.job.Job; +import org.springframework.batch.core.job.JobExecution; +import org.springframework.batch.core.job.JobInstance; +import org.springframework.batch.core.job.parameters.JobParameters; +import org.springframework.batch.core.job.parameters.JobParametersBuilder; import org.springframework.batch.core.launch.JobLauncher; import org.springframework.batch.core.repository.JobRepository; import org.springframework.boot.SpringApplication; diff --git a/spring-batch-plus-sample/delete-meta-data-job-sample/src/test/java/com/navercorp/spring/batch/plus/sample/deletemetadata/jobname/TestJobConfig.java b/spring-batch-plus-sample/delete-meta-data-job-sample/src/test/java/com/navercorp/spring/batch/plus/sample/deletemetadata/jobname/TestJobConfig.java index 4ef9d937..6e638b01 100644 --- a/spring-batch-plus-sample/delete-meta-data-job-sample/src/test/java/com/navercorp/spring/batch/plus/sample/deletemetadata/jobname/TestJobConfig.java +++ b/spring-batch-plus-sample/delete-meta-data-job-sample/src/test/java/com/navercorp/spring/batch/plus/sample/deletemetadata/jobname/TestJobConfig.java @@ -20,13 +20,13 @@ import javax.sql.DataSource; -import org.springframework.batch.core.Job; +import org.springframework.batch.core.job.Job; import org.springframework.batch.core.job.builder.JobBuilder; -import org.springframework.batch.core.launch.support.RunIdIncrementer; +import org.springframework.batch.core.job.parameters.RunIdIncrementer; import org.springframework.batch.core.repository.JobRepository; import org.springframework.batch.core.step.builder.StepBuilder; -import org.springframework.batch.repeat.RepeatStatus; -import org.springframework.boot.autoconfigure.batch.BatchDataSource; +import org.springframework.batch.infrastructure.repeat.RepeatStatus; +import org.springframework.boot.batch.jdbc.autoconfigure.BatchDataSource; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.transaction.PlatformTransactionManager; diff --git a/spring-batch-plus-sample/delete-meta-data-job-sample/src/test/java/com/navercorp/spring/batch/plus/sample/deletemetadata/parametername/JdbcConfig.java b/spring-batch-plus-sample/delete-meta-data-job-sample/src/test/java/com/navercorp/spring/batch/plus/sample/deletemetadata/parametername/JdbcConfig.java index 63e42eaa..7dd315bc 100644 --- a/spring-batch-plus-sample/delete-meta-data-job-sample/src/test/java/com/navercorp/spring/batch/plus/sample/deletemetadata/parametername/JdbcConfig.java +++ b/spring-batch-plus-sample/delete-meta-data-job-sample/src/test/java/com/navercorp/spring/batch/plus/sample/deletemetadata/parametername/JdbcConfig.java @@ -20,7 +20,7 @@ import javax.sql.DataSource; -import org.springframework.boot.autoconfigure.batch.BatchDataSource; +import org.springframework.boot.batch.jdbc.autoconfigure.BatchDataSource; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; diff --git a/spring-batch-plus-sample/delete-meta-data-job-sample/src/test/java/com/navercorp/spring/batch/plus/sample/deletemetadata/parametername/SampleApplicationTest.java b/spring-batch-plus-sample/delete-meta-data-job-sample/src/test/java/com/navercorp/spring/batch/plus/sample/deletemetadata/parametername/SampleApplicationTest.java index a3efe26b..fa75c67d 100644 --- a/spring-batch-plus-sample/delete-meta-data-job-sample/src/test/java/com/navercorp/spring/batch/plus/sample/deletemetadata/parametername/SampleApplicationTest.java +++ b/spring-batch-plus-sample/delete-meta-data-job-sample/src/test/java/com/navercorp/spring/batch/plus/sample/deletemetadata/parametername/SampleApplicationTest.java @@ -24,11 +24,11 @@ import java.util.stream.LongStream; import org.junit.jupiter.api.Test; -import org.springframework.batch.core.Job; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.JobInstance; -import org.springframework.batch.core.JobParameters; -import org.springframework.batch.core.JobParametersBuilder; +import org.springframework.batch.core.job.Job; +import org.springframework.batch.core.job.JobExecution; +import org.springframework.batch.core.job.JobInstance; +import org.springframework.batch.core.job.parameters.JobParameters; +import org.springframework.batch.core.job.parameters.JobParametersBuilder; import org.springframework.batch.core.launch.JobLauncher; import org.springframework.batch.core.repository.JobRepository; import org.springframework.boot.SpringApplication; diff --git a/spring-batch-plus-sample/delete-meta-data-job-sample/src/test/java/com/navercorp/spring/batch/plus/sample/deletemetadata/parametername/TestJobConfig.java b/spring-batch-plus-sample/delete-meta-data-job-sample/src/test/java/com/navercorp/spring/batch/plus/sample/deletemetadata/parametername/TestJobConfig.java index 1ee70876..465b6d1f 100644 --- a/spring-batch-plus-sample/delete-meta-data-job-sample/src/test/java/com/navercorp/spring/batch/plus/sample/deletemetadata/parametername/TestJobConfig.java +++ b/spring-batch-plus-sample/delete-meta-data-job-sample/src/test/java/com/navercorp/spring/batch/plus/sample/deletemetadata/parametername/TestJobConfig.java @@ -20,13 +20,13 @@ import javax.sql.DataSource; -import org.springframework.batch.core.Job; +import org.springframework.batch.core.job.Job; import org.springframework.batch.core.job.builder.JobBuilder; -import org.springframework.batch.core.launch.support.RunIdIncrementer; +import org.springframework.batch.core.job.parameters.RunIdIncrementer; import org.springframework.batch.core.repository.JobRepository; import org.springframework.batch.core.step.builder.StepBuilder; -import org.springframework.batch.repeat.RepeatStatus; -import org.springframework.boot.autoconfigure.batch.BatchDataSource; +import org.springframework.batch.infrastructure.repeat.RepeatStatus; +import org.springframework.boot.batch.jdbc.autoconfigure.BatchDataSource; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.transaction.PlatformTransactionManager; diff --git a/spring-batch-plus-sample/delete-meta-data-job-sample/src/test/java/com/navercorp/spring/batch/plus/sample/deletemetadata/plain/JdbcConfig.java b/spring-batch-plus-sample/delete-meta-data-job-sample/src/test/java/com/navercorp/spring/batch/plus/sample/deletemetadata/plain/JdbcConfig.java index 52aa8c78..15c47cf1 100644 --- a/spring-batch-plus-sample/delete-meta-data-job-sample/src/test/java/com/navercorp/spring/batch/plus/sample/deletemetadata/plain/JdbcConfig.java +++ b/spring-batch-plus-sample/delete-meta-data-job-sample/src/test/java/com/navercorp/spring/batch/plus/sample/deletemetadata/plain/JdbcConfig.java @@ -20,7 +20,7 @@ import javax.sql.DataSource; -import org.springframework.boot.autoconfigure.batch.BatchDataSource; +import org.springframework.boot.batch.jdbc.autoconfigure.BatchDataSource; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; diff --git a/spring-batch-plus-sample/delete-meta-data-job-sample/src/test/java/com/navercorp/spring/batch/plus/sample/deletemetadata/plain/SampleApplicationTest.java b/spring-batch-plus-sample/delete-meta-data-job-sample/src/test/java/com/navercorp/spring/batch/plus/sample/deletemetadata/plain/SampleApplicationTest.java index be64330f..ade72d24 100644 --- a/spring-batch-plus-sample/delete-meta-data-job-sample/src/test/java/com/navercorp/spring/batch/plus/sample/deletemetadata/plain/SampleApplicationTest.java +++ b/spring-batch-plus-sample/delete-meta-data-job-sample/src/test/java/com/navercorp/spring/batch/plus/sample/deletemetadata/plain/SampleApplicationTest.java @@ -24,11 +24,11 @@ import java.util.stream.LongStream; import org.junit.jupiter.api.Test; -import org.springframework.batch.core.Job; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.JobInstance; -import org.springframework.batch.core.JobParameters; -import org.springframework.batch.core.JobParametersBuilder; +import org.springframework.batch.core.job.Job; +import org.springframework.batch.core.job.JobExecution; +import org.springframework.batch.core.job.JobInstance; +import org.springframework.batch.core.job.parameters.JobParameters; +import org.springframework.batch.core.job.parameters.JobParametersBuilder; import org.springframework.batch.core.launch.JobLauncher; import org.springframework.batch.core.repository.JobRepository; import org.springframework.boot.SpringApplication; diff --git a/spring-batch-plus-sample/delete-meta-data-job-sample/src/test/java/com/navercorp/spring/batch/plus/sample/deletemetadata/plain/TestJobConfig.java b/spring-batch-plus-sample/delete-meta-data-job-sample/src/test/java/com/navercorp/spring/batch/plus/sample/deletemetadata/plain/TestJobConfig.java index c22e28c4..48cadd7c 100644 --- a/spring-batch-plus-sample/delete-meta-data-job-sample/src/test/java/com/navercorp/spring/batch/plus/sample/deletemetadata/plain/TestJobConfig.java +++ b/spring-batch-plus-sample/delete-meta-data-job-sample/src/test/java/com/navercorp/spring/batch/plus/sample/deletemetadata/plain/TestJobConfig.java @@ -20,13 +20,13 @@ import javax.sql.DataSource; -import org.springframework.batch.core.Job; +import org.springframework.batch.core.job.Job; import org.springframework.batch.core.job.builder.JobBuilder; -import org.springframework.batch.core.launch.support.RunIdIncrementer; +import org.springframework.batch.core.job.parameters.RunIdIncrementer; import org.springframework.batch.core.repository.JobRepository; import org.springframework.batch.core.step.builder.StepBuilder; -import org.springframework.batch.repeat.RepeatStatus; -import org.springframework.boot.autoconfigure.batch.BatchDataSource; +import org.springframework.batch.infrastructure.repeat.RepeatStatus; +import org.springframework.boot.batch.jdbc.autoconfigure.BatchDataSource; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.transaction.PlatformTransactionManager; diff --git a/spring-batch-plus-sample/delete-meta-data-job-sample/src/test/java/com/navercorp/spring/batch/plus/sample/deletemetadata/prefix/JdbcConfig.java b/spring-batch-plus-sample/delete-meta-data-job-sample/src/test/java/com/navercorp/spring/batch/plus/sample/deletemetadata/prefix/JdbcConfig.java index b2d2cab2..086c0013 100644 --- a/spring-batch-plus-sample/delete-meta-data-job-sample/src/test/java/com/navercorp/spring/batch/plus/sample/deletemetadata/prefix/JdbcConfig.java +++ b/spring-batch-plus-sample/delete-meta-data-job-sample/src/test/java/com/navercorp/spring/batch/plus/sample/deletemetadata/prefix/JdbcConfig.java @@ -20,7 +20,7 @@ import javax.sql.DataSource; -import org.springframework.boot.autoconfigure.batch.BatchDataSource; +import org.springframework.boot.batch.jdbc.autoconfigure.BatchDataSource; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; diff --git a/spring-batch-plus-sample/delete-meta-data-job-sample/src/test/java/com/navercorp/spring/batch/plus/sample/deletemetadata/prefix/SampleApplicationTest.java b/spring-batch-plus-sample/delete-meta-data-job-sample/src/test/java/com/navercorp/spring/batch/plus/sample/deletemetadata/prefix/SampleApplicationTest.java index fd1c8c7c..6c6e903d 100644 --- a/spring-batch-plus-sample/delete-meta-data-job-sample/src/test/java/com/navercorp/spring/batch/plus/sample/deletemetadata/prefix/SampleApplicationTest.java +++ b/spring-batch-plus-sample/delete-meta-data-job-sample/src/test/java/com/navercorp/spring/batch/plus/sample/deletemetadata/prefix/SampleApplicationTest.java @@ -25,11 +25,11 @@ import java.util.stream.LongStream; import org.junit.jupiter.api.Test; -import org.springframework.batch.core.Job; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.JobInstance; -import org.springframework.batch.core.JobParameters; -import org.springframework.batch.core.JobParametersBuilder; +import org.springframework.batch.core.job.Job; +import org.springframework.batch.core.job.JobExecution; +import org.springframework.batch.core.job.JobInstance; +import org.springframework.batch.core.job.parameters.JobParameters; +import org.springframework.batch.core.job.parameters.JobParametersBuilder; import org.springframework.batch.core.launch.JobLauncher; import org.springframework.batch.core.repository.JobRepository; import org.springframework.boot.SpringApplication; diff --git a/spring-batch-plus-sample/delete-meta-data-job-sample/src/test/java/com/navercorp/spring/batch/plus/sample/deletemetadata/prefix/TestJobConfig.java b/spring-batch-plus-sample/delete-meta-data-job-sample/src/test/java/com/navercorp/spring/batch/plus/sample/deletemetadata/prefix/TestJobConfig.java index 58695317..9e6c4152 100644 --- a/spring-batch-plus-sample/delete-meta-data-job-sample/src/test/java/com/navercorp/spring/batch/plus/sample/deletemetadata/prefix/TestJobConfig.java +++ b/spring-batch-plus-sample/delete-meta-data-job-sample/src/test/java/com/navercorp/spring/batch/plus/sample/deletemetadata/prefix/TestJobConfig.java @@ -20,13 +20,13 @@ import javax.sql.DataSource; -import org.springframework.batch.core.Job; +import org.springframework.batch.core.job.Job; import org.springframework.batch.core.job.builder.JobBuilder; -import org.springframework.batch.core.launch.support.RunIdIncrementer; +import org.springframework.batch.core.job.parameters.RunIdIncrementer; import org.springframework.batch.core.repository.JobRepository; import org.springframework.batch.core.step.builder.StepBuilder; -import org.springframework.batch.repeat.RepeatStatus; -import org.springframework.boot.autoconfigure.batch.BatchDataSource; +import org.springframework.batch.infrastructure.repeat.RepeatStatus; +import org.springframework.boot.batch.jdbc.autoconfigure.BatchDataSource; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.transaction.PlatformTransactionManager; diff --git a/spring-batch-plus-sample/delete-meta-data-job-sample/src/test/java/com/navercorp/spring/batch/plus/sample/deletemetadata/prefixfromvariable/JdbcConfig.java b/spring-batch-plus-sample/delete-meta-data-job-sample/src/test/java/com/navercorp/spring/batch/plus/sample/deletemetadata/prefixfromvariable/JdbcConfig.java index f2333599..453477a6 100644 --- a/spring-batch-plus-sample/delete-meta-data-job-sample/src/test/java/com/navercorp/spring/batch/plus/sample/deletemetadata/prefixfromvariable/JdbcConfig.java +++ b/spring-batch-plus-sample/delete-meta-data-job-sample/src/test/java/com/navercorp/spring/batch/plus/sample/deletemetadata/prefixfromvariable/JdbcConfig.java @@ -20,7 +20,7 @@ import javax.sql.DataSource; -import org.springframework.boot.autoconfigure.batch.BatchDataSource; +import org.springframework.boot.batch.jdbc.autoconfigure.BatchDataSource; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; diff --git a/spring-batch-plus-sample/delete-meta-data-job-sample/src/test/java/com/navercorp/spring/batch/plus/sample/deletemetadata/prefixfromvariable/SampleApplicationTest.java b/spring-batch-plus-sample/delete-meta-data-job-sample/src/test/java/com/navercorp/spring/batch/plus/sample/deletemetadata/prefixfromvariable/SampleApplicationTest.java index 1559dafe..8a33ed06 100644 --- a/spring-batch-plus-sample/delete-meta-data-job-sample/src/test/java/com/navercorp/spring/batch/plus/sample/deletemetadata/prefixfromvariable/SampleApplicationTest.java +++ b/spring-batch-plus-sample/delete-meta-data-job-sample/src/test/java/com/navercorp/spring/batch/plus/sample/deletemetadata/prefixfromvariable/SampleApplicationTest.java @@ -25,11 +25,11 @@ import java.util.stream.LongStream; import org.junit.jupiter.api.Test; -import org.springframework.batch.core.Job; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.JobInstance; -import org.springframework.batch.core.JobParameters; -import org.springframework.batch.core.JobParametersBuilder; +import org.springframework.batch.core.job.Job; +import org.springframework.batch.core.job.JobExecution; +import org.springframework.batch.core.job.JobInstance; +import org.springframework.batch.core.job.parameters.JobParameters; +import org.springframework.batch.core.job.parameters.JobParametersBuilder; import org.springframework.batch.core.launch.JobLauncher; import org.springframework.batch.core.repository.JobRepository; import org.springframework.boot.SpringApplication; diff --git a/spring-batch-plus-sample/delete-meta-data-job-sample/src/test/java/com/navercorp/spring/batch/plus/sample/deletemetadata/prefixfromvariable/TestJobConfig.java b/spring-batch-plus-sample/delete-meta-data-job-sample/src/test/java/com/navercorp/spring/batch/plus/sample/deletemetadata/prefixfromvariable/TestJobConfig.java index ba8a47d3..f25627fd 100644 --- a/spring-batch-plus-sample/delete-meta-data-job-sample/src/test/java/com/navercorp/spring/batch/plus/sample/deletemetadata/prefixfromvariable/TestJobConfig.java +++ b/spring-batch-plus-sample/delete-meta-data-job-sample/src/test/java/com/navercorp/spring/batch/plus/sample/deletemetadata/prefixfromvariable/TestJobConfig.java @@ -20,14 +20,14 @@ import javax.sql.DataSource; -import org.springframework.batch.core.Job; +import org.springframework.batch.core.job.Job; import org.springframework.batch.core.job.builder.JobBuilder; -import org.springframework.batch.core.launch.support.RunIdIncrementer; +import org.springframework.batch.core.job.parameters.RunIdIncrementer; import org.springframework.batch.core.repository.JobRepository; import org.springframework.batch.core.step.builder.StepBuilder; -import org.springframework.batch.repeat.RepeatStatus; -import org.springframework.boot.autoconfigure.batch.BatchDataSource; -import org.springframework.boot.autoconfigure.batch.BatchProperties; +import org.springframework.batch.infrastructure.repeat.RepeatStatus; +import org.springframework.boot.batch.jdbc.autoconfigure.BatchDataSource; +import org.springframework.boot.batch.jdbc.autoconfigure.BatchJdbcProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.transaction.PlatformTransactionManager; @@ -41,9 +41,9 @@ public class TestJobConfig { public Job removeJob( @BatchDataSource DataSource dataSource, JobRepository jobRepository, - BatchProperties properties + BatchJdbcProperties properties ) { - String tablePrefix = properties.getJdbc().getTablePrefix(); + String tablePrefix = properties.getTablePrefix(); return new DeleteMetadataJobBuilder(jobRepository, dataSource) .name("removeJob") .tablePrefix(tablePrefix) diff --git a/spring-batch-plus-sample/delete-meta-data-job-sample/src/test/resources/sql/schema-h2-custom.sql b/spring-batch-plus-sample/delete-meta-data-job-sample/src/test/resources/sql/schema-h2-custom.sql index 718302fb..a65cc0f5 100644 --- a/spring-batch-plus-sample/delete-meta-data-job-sample/src/test/resources/sql/schema-h2-custom.sql +++ b/spring-batch-plus-sample/delete-meta-data-job-sample/src/test/resources/sql/schema-h2-custom.sql @@ -73,4 +73,4 @@ CREATE TABLE CUSTOM_JOB_EXECUTION_CONTEXT ( CREATE SEQUENCE CUSTOM_STEP_EXECUTION_SEQ; CREATE SEQUENCE CUSTOM_JOB_EXECUTION_SEQ; -CREATE SEQUENCE CUSTOM_JOB_SEQ; +CREATE SEQUENCE CUSTOM_JOB_INSTANCE_SEQ; diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/build.gradle.kts b/spring-batch-plus-sample/kotlin-dsl-sample/build.gradle.kts index db01bfaa..6a4c7cbd 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/build.gradle.kts +++ b/spring-batch-plus-sample/kotlin-dsl-sample/build.gradle.kts @@ -1,3 +1,5 @@ +import org.jetbrains.kotlin.gradle.dsl.JvmTarget + buildscript { repositories { gradlePluginPortal() // give accees to gradle community plugins @@ -17,12 +19,9 @@ repositories { kotlin { jvmToolchain(17) -} - -tasks.withType { - kotlinOptions { + compilerOptions { freeCompilerArgs = listOf("-Xjsr305=strict") // enable jsr305 null-safety in kotlin - jvmTarget = "17" + jvmTarget = JvmTarget.JVM_17 } } @@ -33,14 +32,14 @@ tasks.named("test") { dependencyManagement { imports { - mavenBom("org.springframework.boot:spring-boot-dependencies:3.5.0") + mavenBom("org.springframework.boot:spring-boot-dependencies:4.0.7") } } dependencies { - implementation("org.springframework.boot:spring-boot-starter-batch") + implementation("org.springframework.boot:spring-boot-starter-batch-jdbc") implementation(project(":spring-boot-starter-batch-plus-kotlin")) - runtimeOnly("com.h2database:h2:2.1.214") + runtimeOnly("com.h2database:h2:2.4.240") testImplementation("org.springframework.boot:spring-boot-starter-test") testRuntimeOnly("org.junit.platform:junit-platform-launcher") diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/comparison/after/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/comparison/after/SampleApplicationTest.kt index 645cc00e..d14d7811 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/comparison/after/SampleApplicationTest.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/comparison/after/SampleApplicationTest.kt @@ -20,9 +20,9 @@ package com.navercorp.spring.batch.plus.sample.comparison.after import org.junit.jupiter.api.Test import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator import org.springframework.beans.factory.getBean import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.runApplication @@ -32,12 +32,13 @@ open class SampleApplicationTest { @Test fun run() { val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() + val jobOperator = applicationContext.getBean() val job = applicationContext.getBean() - val jobParameters = JobParametersBuilder() - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) + val jobParameters = + JobParametersBuilder() + .toJobParameters() + val jobExecution = jobOperator.start(job, jobParameters) assert(BatchStatus.COMPLETED == jobExecution.status) println(jobExecution) diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/comparison/after/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/comparison/after/TestJobConfig.kt index 947e21bb..bb8f9112 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/comparison/after/TestJobConfig.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/comparison/after/TestJobConfig.kt @@ -19,9 +19,9 @@ package com.navercorp.spring.batch.plus.sample.comparison.after import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.Job -import org.springframework.batch.core.Step -import org.springframework.batch.repeat.RepeatStatus +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.step.Step +import org.springframework.batch.infrastructure.repeat.RepeatStatus import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.transaction.PlatformTransactionManager @@ -31,42 +31,45 @@ open class TestJobConfig( private val batch: BatchDsl, private val transactionManager: PlatformTransactionManager, ) { - @Bean - open fun testJob(): Job = batch { - job("testJob") { - step("testStep1") { - tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) - } - step(testStep2()) { - on("COMPLETED") { - step(testStep3()) + open fun testJob(): Job = + batch { + job("testJob") { + step("testStep1") { + tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) } - on("FAILED") { - step(testStep4()) + step(testStep2()) { + on("COMPLETED") { + step(testStep3()) + } + on("FAILED") { + step(testStep4()) + } } } } - } @Bean - open fun testStep2(): Step = batch { - step("testStep2") { - tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + open fun testStep2(): Step = + batch { + step("testStep2") { + tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + } } - } @Bean - open fun testStep3(): Step = batch { - step("testStep3") { - tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + open fun testStep3(): Step = + batch { + step("testStep3") { + tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + } } - } @Bean - open fun testStep4(): Step = batch { - step("testStep4") { - tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + open fun testStep4(): Step = + batch { + step("testStep4") { + tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + } } - } } diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/comparison/before/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/comparison/before/SampleApplicationTest.kt index dc31d538..499d97bb 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/comparison/before/SampleApplicationTest.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/comparison/before/SampleApplicationTest.kt @@ -20,9 +20,9 @@ package com.navercorp.spring.batch.plus.sample.comparison.before import org.junit.jupiter.api.Test import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator import org.springframework.beans.factory.getBean import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.runApplication @@ -32,12 +32,13 @@ open class SampleApplicationTest { @Test fun run() { val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() + val jobOperator = applicationContext.getBean() val job = applicationContext.getBean() - val jobParameters = JobParametersBuilder() - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) + val jobParameters = + JobParametersBuilder() + .toJobParameters() + val jobExecution = jobOperator.start(job, jobParameters) assert(BatchStatus.COMPLETED == jobExecution.status) println(jobExecution) diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/comparison/before/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/comparison/before/TestJobConfig.kt index 23350029..a8a8fb21 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/comparison/before/TestJobConfig.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/comparison/before/TestJobConfig.kt @@ -18,12 +18,12 @@ package com.navercorp.spring.batch.plus.sample.comparison.before -import org.springframework.batch.core.Job -import org.springframework.batch.core.Step +import org.springframework.batch.core.job.Job import org.springframework.batch.core.job.builder.JobBuilder import org.springframework.batch.core.repository.JobRepository +import org.springframework.batch.core.step.Step import org.springframework.batch.core.step.builder.StepBuilder -import org.springframework.batch.repeat.RepeatStatus +import org.springframework.batch.infrastructure.repeat.RepeatStatus import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.transaction.PlatformTransactionManager @@ -33,41 +33,37 @@ open class TestJobConfig( private val jobRepository: JobRepository, private val transactionManager: PlatformTransactionManager, ) { - @Bean - open fun testJob(): Job { - return JobBuilder("testJob", jobRepository) + open fun testJob(): Job = + JobBuilder("testJob", jobRepository) .start( StepBuilder("testStep1", jobRepository) .tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) .build(), - ) - .next(testStep2()) - .on("COMPLETED").to(testStep3()) + ).next(testStep2()) + .on("COMPLETED") + .to(testStep3()) .from(testStep2()) - .on("FAILED").to(testStep4()) + .on("FAILED") + .to(testStep4()) .end() .build() - } @Bean - open fun testStep2(): Step { - return StepBuilder("testStep2", jobRepository) + open fun testStep2(): Step = + StepBuilder("testStep2", jobRepository) .tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) .build() - } @Bean - open fun testStep3(): Step { - return StepBuilder("testStep3", jobRepository) + open fun testStep3(): Step = + StepBuilder("testStep3", jobRepository) .tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) .build() - } @Bean - open fun testStep4(): Step { - return StepBuilder("testStep4", jobRepository) + open fun testStep4(): Step = + StepBuilder("testStep4", jobRepository) .tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) .build() - } } diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/flow/creation/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/flow/creation/SampleApplicationTest.kt index e6355d91..6eebbd69 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/flow/creation/SampleApplicationTest.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/flow/creation/SampleApplicationTest.kt @@ -20,9 +20,9 @@ package com.navercorp.spring.batch.plus.sample.flow.creation import org.junit.jupiter.api.Test import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator import org.springframework.beans.factory.getBean import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.runApplication @@ -32,12 +32,13 @@ open class SampleApplicationTest { @Test fun run() { val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() + val jobOperator = applicationContext.getBean() val job = applicationContext.getBean() - val jobParameters = JobParametersBuilder() - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) + val jobParameters = + JobParametersBuilder() + .toJobParameters() + val jobExecution = jobOperator.start(job, jobParameters) assert(BatchStatus.STOPPED == jobExecution.status) println(jobExecution) diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/flow/creation/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/flow/creation/TestJobConfig.kt index 17f8933e..3d3ae5af 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/flow/creation/TestJobConfig.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/flow/creation/TestJobConfig.kt @@ -19,10 +19,10 @@ package com.navercorp.spring.batch.plus.sample.flow.creation import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.Job -import org.springframework.batch.core.Step +import org.springframework.batch.core.job.Job import org.springframework.batch.core.job.flow.Flow -import org.springframework.batch.repeat.RepeatStatus +import org.springframework.batch.core.step.Step +import org.springframework.batch.infrastructure.repeat.RepeatStatus import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.transaction.PlatformTransactionManager @@ -32,32 +32,34 @@ open class TestJobConfig( private val batch: BatchDsl, private val transactionManager: PlatformTransactionManager, ) { - @Bean - open fun testJob(): Job = batch { - job("testJob") { - flow(testFlow()) + open fun testJob(): Job = + batch { + job("testJob") { + flow(testFlow()) + } } - } @Bean - open fun testFlow(): Flow = batch { - flow("testFlow") { - step(testStep()) { - on("COMPLETED") { - stop() - } - on("*") { - fail() + open fun testFlow(): Flow = + batch { + flow("testFlow") { + step(testStep()) { + on("COMPLETED") { + stop() + } + on("*") { + fail() + } } } } - } @Bean - open fun testStep(): Step = batch { - step("testStep") { - tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + open fun testStep(): Step = + batch { + step("testStep") { + tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + } } - } } diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/configuration/README.md b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/configuration/README.md new file mode 100644 index 00000000..1dff564c --- /dev/null +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/configuration/README.md @@ -0,0 +1,6 @@ +# Job Config Samples + +## Invariants + +- Every common job configuration option exposed by `JobBuilderDsl` should have + a runnable sample in this package. diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/configuration/incrementer/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/configuration/incrementer/SampleApplicationTest.kt index 33c6682b..3abb2716 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/configuration/incrementer/SampleApplicationTest.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/configuration/incrementer/SampleApplicationTest.kt @@ -20,10 +20,8 @@ package com.navercorp.spring.batch.plus.sample.job.configuration.incrementer import org.junit.jupiter.api.Test import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.explore.JobExplorer -import org.springframework.batch.core.launch.JobLauncher +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.launch.JobOperator import org.springframework.beans.factory.getBean import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.runApplication @@ -33,19 +31,11 @@ open class SampleApplicationTest { @Test fun run() { val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() - val jobExplorer = applicationContext.getBean() + val jobOperator = applicationContext.getBean() val job = applicationContext.getBean() - val firstJobParameters = JobParametersBuilder(jobExplorer) - .getNextJobParameters(job) - .toJobParameters() - val firstJobExecution = jobLauncher.run(job, firstJobParameters) - - val secondJobParameters = JobParametersBuilder(jobExplorer) - .getNextJobParameters(job) - .toJobParameters() - val secondJobExecution = jobLauncher.run(job, secondJobParameters) + val firstJobExecution = jobOperator.startNextInstance(job) + val secondJobExecution = jobOperator.startNextInstance(job) // first assert(BatchStatus.COMPLETED == firstJobExecution.status) diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/configuration/incrementer/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/configuration/incrementer/TestJobConfig.kt index 6d743ab6..9cb0bd01 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/configuration/incrementer/TestJobConfig.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/configuration/incrementer/TestJobConfig.kt @@ -19,10 +19,10 @@ package com.navercorp.spring.batch.plus.sample.job.configuration.incrementer import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParameters -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.repeat.RepeatStatus +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParameters +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.infrastructure.repeat.RepeatStatus import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.transaction.PlatformTransactionManager @@ -32,30 +32,30 @@ open class TestJobConfig( private val batch: BatchDsl, private val transactionManager: PlatformTransactionManager, ) { - @Bean - open fun testJob(): Job = batch { - job("testJob") { - incrementer { - val nextValue = it?.getLong("param")?.plus(1L) ?: 0L - JobParametersBuilder(it ?: JobParameters()) - .addLong("param", nextValue) - .toJobParameters() - } - // same as - // incrementer( - // object : JobParametersIncrementer { - // override fun getNext(parameters: JobParameters?): JobParameters { - // val nextValue = parameters?.getLong("param")?.plus(1L) ?: 0L - // return JobParametersBuilder(parameters ?: JobParameters()) - // .addLong("param", nextValue) - // .toJobParameters() - // } - // } - // ) - step("testStep") { - tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + open fun testJob(): Job = + batch { + job("testJob") { + incrementer { + val nextValue = it?.getLong("param")?.plus(1L) ?: 0L + JobParametersBuilder(it ?: JobParameters()) + .addLong("param", nextValue) + .toJobParameters() + } + // same as + // incrementer( + // object : JobParametersIncrementer { + // override fun getNext(parameters: JobParameters?): JobParameters { + // val nextValue = parameters?.getLong("param")?.plus(1L) ?: 0L + // return JobParametersBuilder(parameters ?: JobParameters()) + // .addLong("param", nextValue) + // .toJobParameters() + // } + // } + // ) + step("testStep") { + tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + } } } - } } diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/configuration/listenerannotation/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/configuration/listenerannotation/SampleApplicationTest.kt index b63fa7ee..fb73261c 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/configuration/listenerannotation/SampleApplicationTest.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/configuration/listenerannotation/SampleApplicationTest.kt @@ -20,9 +20,9 @@ package com.navercorp.spring.batch.plus.sample.job.configuration.listenerannotat import org.junit.jupiter.api.Test import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator import org.springframework.beans.factory.getBean import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.runApplication @@ -32,12 +32,13 @@ open class SampleApplicationTest { @Test fun run() { val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() + val jobOperator = applicationContext.getBean() val job = applicationContext.getBean() - val jobParameters = JobParametersBuilder() - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) + val jobParameters = + JobParametersBuilder() + .toJobParameters() + val jobExecution = jobOperator.start(job, jobParameters) assert(BatchStatus.COMPLETED == jobExecution.status) println(jobExecution) diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/configuration/listenerannotation/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/configuration/listenerannotation/TestJobConfig.kt index 08d8b47c..0a877978 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/configuration/listenerannotation/TestJobConfig.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/configuration/listenerannotation/TestJobConfig.kt @@ -19,10 +19,10 @@ package com.navercorp.spring.batch.plus.sample.job.configuration.listenerannotation import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.Job import org.springframework.batch.core.annotation.AfterJob import org.springframework.batch.core.annotation.BeforeJob -import org.springframework.batch.repeat.RepeatStatus +import org.springframework.batch.core.job.Job +import org.springframework.batch.infrastructure.repeat.RepeatStatus import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.transaction.PlatformTransactionManager @@ -32,7 +32,6 @@ open class TestJobConfig( private val batch: BatchDsl, private val transactionManager: PlatformTransactionManager, ) { - class TestListener { @BeforeJob fun beforeJob() { @@ -46,12 +45,13 @@ open class TestJobConfig( } @Bean - open fun testJob(): Job = batch { - job("testJob") { - listener(TestListener()) - step("testStep") { - tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + open fun testJob(): Job = + batch { + job("testJob") { + listener(TestListener()) + step("testStep") { + tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + } } } - } } diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/configuration/listenerobject/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/configuration/listenerobject/SampleApplicationTest.kt index 0e11df62..aff90f5e 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/configuration/listenerobject/SampleApplicationTest.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/configuration/listenerobject/SampleApplicationTest.kt @@ -20,9 +20,9 @@ package com.navercorp.spring.batch.plus.sample.job.configuration.listenerobject import org.junit.jupiter.api.Test import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator import org.springframework.beans.factory.getBean import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.runApplication @@ -32,12 +32,13 @@ open class SampleApplicationTest { @Test fun run() { val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() + val jobOperator = applicationContext.getBean() val job = applicationContext.getBean() - val jobParameters = JobParametersBuilder() - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) + val jobParameters = + JobParametersBuilder() + .toJobParameters() + val jobExecution = jobOperator.start(job, jobParameters) assert(BatchStatus.COMPLETED == jobExecution.status) println(jobExecution) diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/configuration/listenerobject/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/configuration/listenerobject/TestJobConfig.kt index 1fb15654..2099e31b 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/configuration/listenerobject/TestJobConfig.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/configuration/listenerobject/TestJobConfig.kt @@ -19,10 +19,10 @@ package com.navercorp.spring.batch.plus.sample.job.configuration.listenerobject import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobExecution -import org.springframework.batch.core.JobExecutionListener -import org.springframework.batch.repeat.RepeatStatus +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.JobExecution +import org.springframework.batch.core.listener.JobExecutionListener +import org.springframework.batch.infrastructure.repeat.RepeatStatus import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.transaction.PlatformTransactionManager @@ -32,24 +32,24 @@ open class TestJobConfig( private val batch: BatchDsl, private val transactionManager: PlatformTransactionManager, ) { - @Bean - open fun testJob(): Job = batch { - job("testJob") { - listener( - object : JobExecutionListener { - override fun beforeJob(jobExecution: JobExecution) { - println("before $jobExecution") - } + open fun testJob(): Job = + batch { + job("testJob") { + listener( + object : JobExecutionListener { + override fun beforeJob(jobExecution: JobExecution) { + println("before $jobExecution") + } - override fun afterJob(jobExecution: JobExecution) { - println("after $jobExecution") - } - }, - ) - step("testStep") { - tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + override fun afterJob(jobExecution: JobExecution) { + println("after $jobExecution") + } + }, + ) + step("testStep") { + tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + } } } - } } diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/configuration/meterregistry/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/configuration/meterregistry/TestJobConfig.kt deleted file mode 100644 index 1ba0a0af..00000000 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/configuration/meterregistry/TestJobConfig.kt +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Spring Batch Plus - * - * Copyright 2022-present NAVER Corp. - * - * 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 - * - * http://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 com.navercorp.spring.batch.plus.sample.job.configuration.meterregistry - -import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import io.micrometer.core.instrument.simple.SimpleMeterRegistry -import org.springframework.batch.core.Job -import org.springframework.batch.repeat.RepeatStatus -import org.springframework.context.annotation.Bean -import org.springframework.context.annotation.Configuration -import org.springframework.transaction.PlatformTransactionManager - -@Configuration -open class TestJobConfig( - private val batch: BatchDsl, - private val transactionManager: PlatformTransactionManager, -) { - - @Bean - open fun testJob(): Job = batch { - job("testJob") { - meterRegistry(SimpleMeterRegistry()) - step("testStep") { - tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) - } - } - } -} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/configuration/observationconvention/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/configuration/observationconvention/TestJobConfig.kt deleted file mode 100644 index 6696a3d6..00000000 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/configuration/observationconvention/TestJobConfig.kt +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Spring Batch Plus - * - * Copyright 2022-present NAVER Corp. - * - * 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 - * - * http://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 com.navercorp.spring.batch.plus.sample.job.configuration.observationconvention - -import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.Job -import org.springframework.batch.core.observability.DefaultBatchJobObservationConvention -import org.springframework.batch.repeat.RepeatStatus -import org.springframework.context.annotation.Bean -import org.springframework.context.annotation.Configuration -import org.springframework.transaction.PlatformTransactionManager - -@Configuration -open class TestJobConfig( - private val batch: BatchDsl, - private val transactionManager: PlatformTransactionManager, -) { - - @Bean - open fun testJob(): Job = batch { - job("testJob") { - observationConvention(DefaultBatchJobObservationConvention()) - step("testStep") { - tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) - } - } - } -} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/configuration/observationregistry/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/configuration/observationregistry/SampleApplicationTest.kt index 9c004531..3a3fd6eb 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/configuration/observationregistry/SampleApplicationTest.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/configuration/observationregistry/SampleApplicationTest.kt @@ -20,9 +20,9 @@ package com.navercorp.spring.batch.plus.sample.job.configuration.observationregi import org.junit.jupiter.api.Test import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator import org.springframework.beans.factory.getBean import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.runApplication @@ -32,12 +32,13 @@ open class SampleApplicationTest { @Test fun run() { val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() + val jobOperator = applicationContext.getBean() val job = applicationContext.getBean() - val jobParameters = JobParametersBuilder() - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) + val jobParameters = + JobParametersBuilder() + .toJobParameters() + val jobExecution = jobOperator.start(job, jobParameters) assert(BatchStatus.COMPLETED == jobExecution.status) println(jobExecution) diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/configuration/observationregistry/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/configuration/observationregistry/TestJobConfig.kt index 63f16461..585b1e9e 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/configuration/observationregistry/TestJobConfig.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/configuration/observationregistry/TestJobConfig.kt @@ -20,8 +20,8 @@ package com.navercorp.spring.batch.plus.sample.job.configuration.observationregi import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl import io.micrometer.observation.ObservationRegistry -import org.springframework.batch.core.Job -import org.springframework.batch.repeat.RepeatStatus +import org.springframework.batch.core.job.Job +import org.springframework.batch.infrastructure.repeat.RepeatStatus import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.transaction.PlatformTransactionManager @@ -31,14 +31,14 @@ open class TestJobConfig( private val batch: BatchDsl, private val transactionManager: PlatformTransactionManager, ) { - @Bean - open fun testJob(): Job = batch { - job("testJob") { - observationRegistry(ObservationRegistry.create()) - step("testStep") { - tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + open fun testJob(): Job = + batch { + job("testJob") { + observationRegistry(ObservationRegistry.create()) + step("testStep") { + tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + } } } - } } diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/configuration/preventrestart/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/configuration/preventrestart/SampleApplicationTest.kt index 3c17ec5b..1f501388 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/configuration/preventrestart/SampleApplicationTest.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/configuration/preventrestart/SampleApplicationTest.kt @@ -20,9 +20,9 @@ package com.navercorp.spring.batch.plus.sample.job.configuration.preventrestart import org.junit.jupiter.api.Test import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator import org.springframework.beans.factory.getBean import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.runApplication @@ -32,19 +32,20 @@ open class SampleApplicationTest { @Test fun run() { val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() + val jobOperator = applicationContext.getBean() val job = applicationContext.getBean() - val jobParameters = JobParametersBuilder() - .toJobParameters() + val jobParameters = + JobParametersBuilder() + .toJobParameters() - val firstJobExecution = jobLauncher.run(job, jobParameters) + val firstJobExecution = jobOperator.start(job, jobParameters) assert(BatchStatus.FAILED == firstJobExecution.status) println(firstJobExecution) try { - jobLauncher.run(job, jobParameters) + jobOperator.start(job, jobParameters) assert(false) { "It must throw exception" } } catch (e: Exception) { // JobInstance already exists and is not restartable diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/configuration/preventrestart/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/configuration/preventrestart/TestJobConfig.kt index b9d1231b..e23ddb49 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/configuration/preventrestart/TestJobConfig.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/configuration/preventrestart/TestJobConfig.kt @@ -19,8 +19,8 @@ package com.navercorp.spring.batch.plus.sample.job.configuration.preventrestart import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.Job -import org.springframework.batch.repeat.RepeatStatus +import org.springframework.batch.core.job.Job +import org.springframework.batch.infrastructure.repeat.RepeatStatus import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.transaction.PlatformTransactionManager @@ -30,25 +30,25 @@ open class TestJobConfig( private val batch: BatchDsl, private val transactionManager: PlatformTransactionManager, ) { - @Bean - open fun testJob(): Job = batch { - var isFirst = true + open fun testJob(): Job = + batch { + var isFirst = true - job("testJob") { - preventRestart() - step("testStep") { - tasklet( - { _, _ -> - if (isFirst) { - isFirst = false - throw RuntimeException("First try should be failed") - } - RepeatStatus.FINISHED - }, - transactionManager, - ) + job("testJob") { + preventRestart() + step("testStep") { + tasklet( + { _, _ -> + if (isFirst) { + isFirst = false + throw RuntimeException("First try should be failed") + } + RepeatStatus.FINISHED + }, + transactionManager, + ) + } } } - } } diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/configuration/validator/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/configuration/validator/SampleApplicationTest.kt index 2899a551..c6996641 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/configuration/validator/SampleApplicationTest.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/configuration/validator/SampleApplicationTest.kt @@ -19,9 +19,9 @@ package com.navercorp.spring.batch.plus.sample.job.configuration.validator import org.junit.jupiter.api.Test -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator import org.springframework.beans.factory.getBean import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.runApplication @@ -31,14 +31,15 @@ open class SampleApplicationTest { @Test fun run() { val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() + val jobOperator = applicationContext.getBean() val job = applicationContext.getBean() - val jobParameters = JobParametersBuilder() - .addLong("param", -1L) - .toJobParameters() + val jobParameters = + JobParametersBuilder() + .addLong("param", -1L) + .toJobParameters() try { - jobLauncher.run(job, jobParameters) + jobOperator.start(job, jobParameters) assert(false) { "It must throw exception" } } catch (e: Exception) { // param is null or less than 0 diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/configuration/validator/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/configuration/validator/TestJobConfig.kt index e66f545e..0e423f1d 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/configuration/validator/TestJobConfig.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/configuration/validator/TestJobConfig.kt @@ -19,9 +19,9 @@ package com.navercorp.spring.batch.plus.sample.job.configuration.validator import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersInvalidException -import org.springframework.batch.repeat.RepeatStatus +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.InvalidJobParametersException +import org.springframework.batch.infrastructure.repeat.RepeatStatus import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.transaction.PlatformTransactionManager @@ -31,30 +31,30 @@ open class TestJobConfig( private val batch: BatchDsl, private val transactionManager: PlatformTransactionManager, ) { - @Bean - open fun testJob(): Job = batch { - job("testJob") { - validator { - val value = it?.getLong("param") - if (value == null || value < 0L) { - throw JobParametersInvalidException("param is null or less than 0") + open fun testJob(): Job = + batch { + job("testJob") { + validator { + val value = it?.getLong("param") + if (value == null || value < 0L) { + throw InvalidJobParametersException("param is null or less than 0") + } + } + // same as + // validator( + // object : JobParametersValidator { + // override fun validate(parameters: JobParameters?) { + // val value = parameters?.getLong("param") + // if (value == null || value < 0L) { + // throw InvalidJobParametersException("param is < 0") + // } + // } + // } + // ) + step("testStep") { + tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) } - } - // same as - // validator( - // object : JobParametersValidator { - // override fun validate(parameters: JobParameters?) { - // val value = parameters?.getLong("param") - // if (value == null || value < 0L) { - // throw JobParametersInvalidException("param is < 0") - // } - // } - // } - // ) - step("testStep") { - tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) } } - } } diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/creation/README.md b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/creation/README.md new file mode 100644 index 00000000..28f53527 --- /dev/null +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/creation/README.md @@ -0,0 +1,6 @@ +# Job Creation Samples + +## Invariants + +- Plain simple-job creation examples from the Kotlin DSL job guide should have + a runnable sample in this package. diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/creation/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/creation/SampleApplicationTest.kt index 2864460a..31ee7e1d 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/creation/SampleApplicationTest.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/creation/SampleApplicationTest.kt @@ -20,9 +20,9 @@ package com.navercorp.spring.batch.plus.sample.job.creation import org.junit.jupiter.api.Test import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator import org.springframework.beans.factory.getBean import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.runApplication @@ -32,12 +32,13 @@ open class SampleApplicationTest { @Test fun run() { val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() + val jobOperator = applicationContext.getBean() val job = applicationContext.getBean() - val jobParameters = JobParametersBuilder() - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) + val jobParameters = + JobParametersBuilder() + .toJobParameters() + val jobExecution = jobOperator.start(job, jobParameters) assert(BatchStatus.COMPLETED == jobExecution.status) println(jobExecution) diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/creation/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/creation/TestJobConfig.kt index 035a22c3..f41bc3b0 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/creation/TestJobConfig.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/creation/TestJobConfig.kt @@ -19,8 +19,8 @@ package com.navercorp.spring.batch.plus.sample.job.creation import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.Job -import org.springframework.batch.repeat.RepeatStatus +import org.springframework.batch.core.job.Job +import org.springframework.batch.infrastructure.repeat.RepeatStatus import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.transaction.PlatformTransactionManager @@ -30,16 +30,16 @@ open class TestJobConfig( private val batch: BatchDsl, private val transactionManager: PlatformTransactionManager, ) { - @Bean - open fun testJob(): Job = batch { - job("testJob") { - step("testStep") { - tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) - } - step("testStep2") { - tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + open fun testJob(): Job = + batch { + job("testJob") { + step("testStep") { + tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + } + step("testStep2") { + tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + } } } - } } diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/decider/README.md b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/decider/README.md new file mode 100644 index 00000000..382c197c --- /dev/null +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/decider/README.md @@ -0,0 +1,8 @@ +# Job Decider Samples + +## Invariants + +- Job flow guide examples should cover deciders supplied by bean lookup and by + variable, including their required transitions. +- Transition DSL examples are covered in the sibling + [`transition`](../transition) package. diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/configuration/meterregistry/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/decider/bean/SampleApplicationTest.kt similarity index 71% rename from spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/configuration/meterregistry/SampleApplicationTest.kt rename to spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/decider/bean/SampleApplicationTest.kt index 14469892..afaf32a7 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/configuration/meterregistry/SampleApplicationTest.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/decider/bean/SampleApplicationTest.kt @@ -16,13 +16,13 @@ * limitations under the License. */ -package com.navercorp.spring.batch.plus.sample.job.configuration.meterregistry +package com.navercorp.spring.batch.plus.sample.job.decider.bean import org.junit.jupiter.api.Test import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator import org.springframework.beans.factory.getBean import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.runApplication @@ -32,12 +32,13 @@ open class SampleApplicationTest { @Test fun run() { val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() + val jobOperator = applicationContext.getBean() val job = applicationContext.getBean() - val jobParameters = JobParametersBuilder() - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) + val jobParameters = + JobParametersBuilder() + .toJobParameters() + val jobExecution = jobOperator.start(job, jobParameters) assert(BatchStatus.COMPLETED == jobExecution.status) println(jobExecution) diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/decider/bean/TestDecider.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/decider/bean/TestDecider.kt similarity index 72% rename from spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/decider/bean/TestDecider.kt rename to spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/decider/bean/TestDecider.kt index e9804313..5429da0a 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/decider/bean/TestDecider.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/decider/bean/TestDecider.kt @@ -16,17 +16,18 @@ * limitations under the License. */ -package com.navercorp.spring.batch.plus.sample.job.flow.decider.bean +package com.navercorp.spring.batch.plus.sample.job.decider.bean -import org.springframework.batch.core.JobExecution -import org.springframework.batch.core.StepExecution +import org.springframework.batch.core.job.JobExecution import org.springframework.batch.core.job.flow.FlowExecutionStatus import org.springframework.batch.core.job.flow.JobExecutionDecider +import org.springframework.batch.core.step.StepExecution import org.springframework.stereotype.Component @Component class TestDecider : JobExecutionDecider { - override fun decide(jobExecution: JobExecution, stepExecution: StepExecution?): FlowExecutionStatus { - return FlowExecutionStatus.FAILED - } + override fun decide( + jobExecution: JobExecution, + stepExecution: StepExecution?, + ): FlowExecutionStatus = FlowExecutionStatus.FAILED } diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/decider/bean/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/decider/bean/TestJobConfig.kt new file mode 100644 index 00000000..8827c9bb --- /dev/null +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/decider/bean/TestJobConfig.kt @@ -0,0 +1,52 @@ +/* + * Spring Batch Plus + * + * Copyright 2022-present NAVER Corp. + * + * 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 + * + * http://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 com.navercorp.spring.batch.plus.sample.job.decider.bean + +import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl +import org.springframework.batch.core.job.Job +import org.springframework.batch.infrastructure.repeat.RepeatStatus +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import org.springframework.transaction.PlatformTransactionManager + +@Configuration +open class TestJobConfig( + private val batch: BatchDsl, + private val transactionManager: PlatformTransactionManager, +) { + @Bean + open fun testJob(): Job = + batch { + job("testJob") { + deciderBean("testDecider") { + on("COMPLETED") { + end() + } + on("FAILED") { + step("transitionStep") { + tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + } + } + on("*") { + stop() + } + } + } + } +} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/decider/bean/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/decider/variable/SampleApplicationTest.kt similarity index 71% rename from spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/decider/bean/SampleApplicationTest.kt rename to spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/decider/variable/SampleApplicationTest.kt index 461bca27..965d6a0d 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/decider/bean/SampleApplicationTest.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/decider/variable/SampleApplicationTest.kt @@ -16,13 +16,13 @@ * limitations under the License. */ -package com.navercorp.spring.batch.plus.sample.job.flow.decider.bean +package com.navercorp.spring.batch.plus.sample.job.decider.variable import org.junit.jupiter.api.Test import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator import org.springframework.beans.factory.getBean import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.runApplication @@ -32,12 +32,13 @@ open class SampleApplicationTest { @Test fun run() { val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() + val jobOperator = applicationContext.getBean() val job = applicationContext.getBean() - val jobParameters = JobParametersBuilder() - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) + val jobParameters = + JobParametersBuilder() + .toJobParameters() + val jobExecution = jobOperator.start(job, jobParameters) assert(BatchStatus.COMPLETED == jobExecution.status) println(jobExecution) diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/decider/variable/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/decider/variable/TestJobConfig.kt similarity index 60% rename from spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/decider/variable/TestJobConfig.kt rename to spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/decider/variable/TestJobConfig.kt index 15ecf0af..975cf11b 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/decider/variable/TestJobConfig.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/decider/variable/TestJobConfig.kt @@ -16,13 +16,13 @@ * limitations under the License. */ -package com.navercorp.spring.batch.plus.sample.job.flow.decider.variable +package com.navercorp.spring.batch.plus.sample.job.decider.variable import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.Job +import org.springframework.batch.core.job.Job import org.springframework.batch.core.job.flow.FlowExecutionStatus import org.springframework.batch.core.job.flow.JobExecutionDecider -import org.springframework.batch.repeat.RepeatStatus +import org.springframework.batch.infrastructure.repeat.RepeatStatus import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.transaction.PlatformTransactionManager @@ -32,28 +32,29 @@ open class TestJobConfig( private val batch: BatchDsl, private val transactionManager: PlatformTransactionManager, ) { - @Bean - open fun testJob(): Job = batch { - job("testJob") { - decider(testDecider()) { - on("COMPLETED") { - end() - } - on("FAILED") { - step("transitionStep") { - tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + open fun testJob(): Job = + batch { + job("testJob") { + decider(testDecider()) { + on("COMPLETED") { + end() + } + on("FAILED") { + step("transitionStep") { + tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + } + } + on("*") { + stop() } - } - on("*") { - stop() } } } - } @Bean - open fun testDecider(): JobExecutionDecider = JobExecutionDecider { _, _ -> - FlowExecutionStatus.FAILED - } + open fun testDecider(): JobExecutionDecider = + JobExecutionDecider { _, _ -> + FlowExecutionStatus.FAILED + } } diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/README.md b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/README.md new file mode 100644 index 00000000..fcb41f3d --- /dev/null +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/README.md @@ -0,0 +1,10 @@ +# Job Flow Selection Samples + +## Invariants + +- The [`sequential`](sequential) package should cover flow selections by bean + lookup, inline creation, and variable input without explicit transitions. +- The [`transition`](transition) package should cover the same input forms with + explicit transitions. +- General transition DSL examples are covered in the sibling + [`transition`](../transition) package. diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/flow/plain/bean/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/flow/plain/bean/SampleApplicationTest.kt deleted file mode 100644 index 6e9c8a81..00000000 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/flow/plain/bean/SampleApplicationTest.kt +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Spring Batch Plus - * - * Copyright 2022-present NAVER Corp. - * - * 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 - * - * http://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 com.navercorp.spring.batch.plus.sample.job.flow.flow.plain.bean - -import org.junit.jupiter.api.Test -import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher -import org.springframework.beans.factory.getBean -import org.springframework.boot.autoconfigure.SpringBootApplication -import org.springframework.boot.runApplication - -@SpringBootApplication -open class SampleApplicationTest { - @Test - fun run() { - val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() - val job = applicationContext.getBean() - - val jobParameters = JobParametersBuilder() - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) - - assert(BatchStatus.COMPLETED == jobExecution.status) - println(jobExecution) - } -} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/flow/plain/init/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/flow/plain/init/SampleApplicationTest.kt deleted file mode 100644 index e3b91026..00000000 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/flow/plain/init/SampleApplicationTest.kt +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Spring Batch Plus - * - * Copyright 2022-present NAVER Corp. - * - * 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 - * - * http://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 com.navercorp.spring.batch.plus.sample.job.flow.flow.plain.init - -import org.junit.jupiter.api.Test -import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher -import org.springframework.beans.factory.getBean -import org.springframework.boot.autoconfigure.SpringBootApplication -import org.springframework.boot.runApplication - -@SpringBootApplication -open class SampleApplicationTest { - @Test - fun run() { - val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() - val job = applicationContext.getBean() - - val jobParameters = JobParametersBuilder() - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) - - assert(BatchStatus.COMPLETED == jobExecution.status) - println(jobExecution) - } -} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/flow/plain/variable/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/flow/plain/variable/SampleApplicationTest.kt deleted file mode 100644 index daaf1e98..00000000 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/flow/plain/variable/SampleApplicationTest.kt +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Spring Batch Plus - * - * Copyright 2022-present NAVER Corp. - * - * 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 - * - * http://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 com.navercorp.spring.batch.plus.sample.job.flow.flow.plain.variable - -import org.junit.jupiter.api.Test -import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher -import org.springframework.beans.factory.getBean -import org.springframework.boot.autoconfigure.SpringBootApplication -import org.springframework.boot.runApplication - -@SpringBootApplication -open class SampleApplicationTest { - @Test - fun run() { - val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() - val job = applicationContext.getBean() - - val jobParameters = JobParametersBuilder() - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) - - assert(BatchStatus.COMPLETED == jobExecution.status) - println(jobExecution) - } -} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/flow/transition/bean/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/flow/transition/bean/SampleApplicationTest.kt deleted file mode 100644 index a66d16bd..00000000 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/flow/transition/bean/SampleApplicationTest.kt +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Spring Batch Plus - * - * Copyright 2022-present NAVER Corp. - * - * 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 - * - * http://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 com.navercorp.spring.batch.plus.sample.job.flow.flow.transition.bean - -import org.junit.jupiter.api.Test -import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher -import org.springframework.beans.factory.getBean -import org.springframework.boot.autoconfigure.SpringBootApplication -import org.springframework.boot.runApplication - -@SpringBootApplication -open class SampleApplicationTest { - @Test - fun run() { - val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() - val job = applicationContext.getBean() - - val jobParameters = JobParametersBuilder() - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) - - assert(BatchStatus.COMPLETED == jobExecution.status) - println(jobExecution) - } -} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/flow/transition/init/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/flow/transition/init/SampleApplicationTest.kt deleted file mode 100644 index bf8c1857..00000000 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/flow/transition/init/SampleApplicationTest.kt +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Spring Batch Plus - * - * Copyright 2022-present NAVER Corp. - * - * 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 - * - * http://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 com.navercorp.spring.batch.plus.sample.job.flow.flow.transition.init - -import org.junit.jupiter.api.Test -import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher -import org.springframework.beans.factory.getBean -import org.springframework.boot.autoconfigure.SpringBootApplication -import org.springframework.boot.runApplication - -@SpringBootApplication -open class SampleApplicationTest { - @Test - fun run() { - val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() - val job = applicationContext.getBean() - - val jobParameters = JobParametersBuilder() - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) - - assert(BatchStatus.COMPLETED == jobExecution.status) - println(jobExecution) - } -} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/flow/transition/variable/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/flow/transition/variable/SampleApplicationTest.kt deleted file mode 100644 index 1a3ecdf7..00000000 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/flow/transition/variable/SampleApplicationTest.kt +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Spring Batch Plus - * - * Copyright 2022-present NAVER Corp. - * - * 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 - * - * http://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 com.navercorp.spring.batch.plus.sample.job.flow.flow.transition.variable - -import org.junit.jupiter.api.Test -import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher -import org.springframework.beans.factory.getBean -import org.springframework.boot.autoconfigure.SpringBootApplication -import org.springframework.boot.runApplication - -@SpringBootApplication -open class SampleApplicationTest { - @Test - fun run() { - val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() - val job = applicationContext.getBean() - - val jobParameters = JobParametersBuilder() - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) - - assert(BatchStatus.COMPLETED == jobExecution.status) - println(jobExecution) - } -} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/configuration/observationconvention/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/sequential/bean/SampleApplicationTest.kt similarity index 71% rename from spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/configuration/observationconvention/SampleApplicationTest.kt rename to spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/sequential/bean/SampleApplicationTest.kt index c0ea049a..7ce45ec7 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/configuration/observationconvention/SampleApplicationTest.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/sequential/bean/SampleApplicationTest.kt @@ -16,13 +16,13 @@ * limitations under the License. */ -package com.navercorp.spring.batch.plus.sample.job.configuration.observationconvention +package com.navercorp.spring.batch.plus.sample.job.flow.sequential.bean import org.junit.jupiter.api.Test import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator import org.springframework.beans.factory.getBean import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.runApplication @@ -32,12 +32,13 @@ open class SampleApplicationTest { @Test fun run() { val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() + val jobOperator = applicationContext.getBean() val job = applicationContext.getBean() - val jobParameters = JobParametersBuilder() - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) + val jobParameters = + JobParametersBuilder() + .toJobParameters() + val jobExecution = jobOperator.start(job, jobParameters) assert(BatchStatus.COMPLETED == jobExecution.status) println(jobExecution) diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/step/plain/variable/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/sequential/bean/TestJobConfig.kt similarity index 56% rename from spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/step/plain/variable/TestJobConfig.kt rename to spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/sequential/bean/TestJobConfig.kt index 14273e9b..2d52600a 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/step/plain/variable/TestJobConfig.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/sequential/bean/TestJobConfig.kt @@ -16,12 +16,12 @@ * limitations under the License. */ -package com.navercorp.spring.batch.plus.sample.job.flow.step.plain.variable +package com.navercorp.spring.batch.plus.sample.job.flow.sequential.bean import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.Job -import org.springframework.batch.core.Step -import org.springframework.batch.repeat.RepeatStatus +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.flow.Flow +import org.springframework.batch.infrastructure.repeat.RepeatStatus import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.transaction.PlatformTransactionManager @@ -31,33 +31,35 @@ open class TestJobConfig( private val batch: BatchDsl, private val transactionManager: PlatformTransactionManager, ) { - @Bean - open fun testJob(): Job = batch { - job("testJob") { - val testStep3 = batch { - step("testStep3") { - tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) - } + open fun testJob(): Job = + batch { + job("testJob") { + flowBean("testFlow1") + flowBean("testFlow2") } - - step(testStep1()) - step(testStep2()) - step(testStep3) } - } @Bean - open fun testStep1(): Step = batch { - step("testStep1") { - tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + open fun testFlow1(): Flow = + batch { + flow("testFlow1") { + step("testFlow1Step1") { + tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + } + step("testFlow1Step2") { + tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + } + } } - } @Bean - open fun testStep2(): Step = batch { - step("testStep2") { - tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + open fun testFlow2(): Flow = + batch { + flow("testFlow2") { + step("testFlow2Step1") { + tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + } + } } - } } diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/decider/variable/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/sequential/init/SampleApplicationTest.kt similarity index 71% rename from spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/decider/variable/SampleApplicationTest.kt rename to spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/sequential/init/SampleApplicationTest.kt index d6f7acc9..219772fc 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/decider/variable/SampleApplicationTest.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/sequential/init/SampleApplicationTest.kt @@ -16,13 +16,13 @@ * limitations under the License. */ -package com.navercorp.spring.batch.plus.sample.job.flow.decider.variable +package com.navercorp.spring.batch.plus.sample.job.flow.sequential.init import org.junit.jupiter.api.Test import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator import org.springframework.beans.factory.getBean import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.runApplication @@ -32,12 +32,13 @@ open class SampleApplicationTest { @Test fun run() { val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() + val jobOperator = applicationContext.getBean() val job = applicationContext.getBean() - val jobParameters = JobParametersBuilder() - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) + val jobParameters = + JobParametersBuilder() + .toJobParameters() + val jobExecution = jobOperator.start(job, jobParameters) assert(BatchStatus.COMPLETED == jobExecution.status) println(jobExecution) diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/decider/bean/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/sequential/init/TestJobConfig.kt similarity index 63% rename from spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/decider/bean/TestJobConfig.kt rename to spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/sequential/init/TestJobConfig.kt index eff902e3..1d423013 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/decider/bean/TestJobConfig.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/sequential/init/TestJobConfig.kt @@ -16,11 +16,11 @@ * limitations under the License. */ -package com.navercorp.spring.batch.plus.sample.job.flow.decider.bean +package com.navercorp.spring.batch.plus.sample.job.flow.sequential.init import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.Job -import org.springframework.batch.repeat.RepeatStatus +import org.springframework.batch.core.job.Job +import org.springframework.batch.infrastructure.repeat.RepeatStatus import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.transaction.PlatformTransactionManager @@ -30,23 +30,23 @@ open class TestJobConfig( private val batch: BatchDsl, private val transactionManager: PlatformTransactionManager, ) { - @Bean - open fun testJob(): Job = batch { - job("testJob") { - deciderBean("testDecider") { - on("COMPLETED") { - end() - } - on("FAILED") { - step("transitionStep") { + open fun testJob(): Job = + batch { + job("testJob") { + flow("testFlow1") { + step("testFlow1Step1") { + tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + } + step("testFlow1Step2") { tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) } } - on("*") { - stop() + flow("testFlow2") { + step("testFlow2Step1") { + tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + } } } } - } } diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/sequential/variable/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/sequential/variable/SampleApplicationTest.kt new file mode 100644 index 00000000..65a68c34 --- /dev/null +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/sequential/variable/SampleApplicationTest.kt @@ -0,0 +1,46 @@ +/* + * Spring Batch Plus + * + * Copyright 2022-present NAVER Corp. + * + * 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 + * + * http://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 com.navercorp.spring.batch.plus.sample.job.flow.sequential.variable + +import org.junit.jupiter.api.Test +import org.springframework.batch.core.BatchStatus +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator +import org.springframework.beans.factory.getBean +import org.springframework.boot.autoconfigure.SpringBootApplication +import org.springframework.boot.runApplication + +@SpringBootApplication +open class SampleApplicationTest { + @Test + fun run() { + val applicationContext = runApplication() + val jobOperator = applicationContext.getBean() + val job = applicationContext.getBean() + + val jobParameters = + JobParametersBuilder() + .toJobParameters() + val jobExecution = jobOperator.start(job, jobParameters) + + assert(BatchStatus.COMPLETED == jobExecution.status) + println(jobExecution) + } +} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/flow/nested/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/sequential/variable/TestJobConfig.kt similarity index 53% rename from spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/flow/nested/TestJobConfig.kt rename to spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/sequential/variable/TestJobConfig.kt index 72d240d2..6c0c6bb4 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/flow/nested/TestJobConfig.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/sequential/variable/TestJobConfig.kt @@ -16,13 +16,12 @@ * limitations under the License. */ -package com.navercorp.spring.batch.plus.sample.job.flow.transition.flow.nested +package com.navercorp.spring.batch.plus.sample.job.flow.sequential.variable import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.Job -import org.springframework.batch.core.Step +import org.springframework.batch.core.job.Job import org.springframework.batch.core.job.flow.Flow -import org.springframework.batch.repeat.RepeatStatus +import org.springframework.batch.infrastructure.repeat.RepeatStatus import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.transaction.PlatformTransactionManager @@ -32,52 +31,45 @@ open class TestJobConfig( private val batch: BatchDsl, private val transactionManager: PlatformTransactionManager, ) { - @Bean - open fun testJob(): Job = batch { - job("testJob") { - step(testStep()) { - on("COMPLETED") { - end() - } - on("FAILED") { - flow(transitionFlow()) { - on("COMPLETED") { - fail() - } - on("*") { - step("nestedStep") { + open fun testJob(): Job = + batch { + job("testJob") { + val testFlow3 = + batch { + flow("testFlow3") { + step("testFlow3Step1") { tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) } } } - } - on("*") { - stop() - } + + flow(testFlow1()) + flow(testFlow2()) + flow(testFlow3) } } - } @Bean - open fun testStep(): Step = batch { - step("testStep") { - tasklet( - { _, _ -> throw IllegalStateException("testStep failed") }, - transactionManager, - ) + open fun testFlow1(): Flow = + batch { + flow("testFlow1") { + step("testFlow1Step1") { + tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + } + step("testFlow1Step2") { + tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + } + } } - } @Bean - open fun transitionFlow(): Flow = batch { - flow("transitionFlow") { - step("transitionStep") { - tasklet( - { _, _ -> throw IllegalStateException("transitionStep failed") }, - transactionManager, - ) + open fun testFlow2(): Flow = + batch { + flow("testFlow2") { + step("testFlow2Step1") { + tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + } } } - } } diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/step/comparison/after/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/step/comparison/after/SampleApplicationTest.kt deleted file mode 100644 index afbcf54e..00000000 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/step/comparison/after/SampleApplicationTest.kt +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Spring Batch Plus - * - * Copyright 2022-present NAVER Corp. - * - * 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 - * - * http://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 com.navercorp.spring.batch.plus.sample.job.flow.step.comparison.after - -import org.junit.jupiter.api.Test -import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher -import org.springframework.beans.factory.getBean -import org.springframework.boot.autoconfigure.SpringBootApplication -import org.springframework.boot.runApplication - -@SpringBootApplication -open class SampleApplicationTest { - @Test - fun run() { - val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() - val job = applicationContext.getBean() - - val jobParameters = JobParametersBuilder() - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) - - assert(BatchStatus.COMPLETED == jobExecution.status) - println(jobExecution) - } -} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/step/comparison/after/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/step/comparison/after/TestJobConfig.kt deleted file mode 100644 index 98c3c5a6..00000000 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/step/comparison/after/TestJobConfig.kt +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Spring Batch Plus - * - * Copyright 2022-present NAVER Corp. - * - * 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 - * - * http://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 com.navercorp.spring.batch.plus.sample.job.flow.step.comparison.after - -import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.Job -import org.springframework.batch.core.Step -import org.springframework.batch.repeat.RepeatStatus -import org.springframework.context.annotation.Bean -import org.springframework.context.annotation.Configuration -import org.springframework.transaction.PlatformTransactionManager - -@Configuration -open class TestJobConfig( - private val batch: BatchDsl, - private val transactionManager: PlatformTransactionManager, -) { - - @Bean - open fun testJob(): Job = batch { - job("testJob") { - step(testStep1()) { - on("COMPLETED") { - step(successStep()) - } - on("FAILED") { - step("failureStep") { - tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) - } - } - on("*") { - stop() - } - } - } - } - - @Bean - open fun testStep1(): Step = batch { - step("testStep1") { - tasklet( - { _, _ -> - throw IllegalStateException("step failed") - }, - transactionManager, - ) - } - } - - @Bean - open fun successStep(): Step = batch { - step("successStep") { - tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) - } - } -} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/step/comparison/before/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/step/comparison/before/SampleApplicationTest.kt deleted file mode 100644 index 79e0b153..00000000 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/step/comparison/before/SampleApplicationTest.kt +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Spring Batch Plus - * - * Copyright 2022-present NAVER Corp. - * - * 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 - * - * http://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 com.navercorp.spring.batch.plus.sample.job.flow.step.comparison.before - -import org.junit.jupiter.api.Test -import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher -import org.springframework.beans.factory.getBean -import org.springframework.boot.autoconfigure.SpringBootApplication -import org.springframework.boot.runApplication - -@SpringBootApplication -open class SampleApplicationTest { - @Test - fun run() { - val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() - val job = applicationContext.getBean() - - val jobParameters = JobParametersBuilder() - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) - - assert(BatchStatus.COMPLETED == jobExecution.status) - println(jobExecution) - } -} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/step/comparison/before/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/step/comparison/before/TestJobConfig.kt deleted file mode 100644 index f3f45319..00000000 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/step/comparison/before/TestJobConfig.kt +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Spring Batch Plus - * - * Copyright 2022-present NAVER Corp. - * - * 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 - * - * http://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 com.navercorp.spring.batch.plus.sample.job.flow.step.comparison.before - -import org.springframework.batch.core.Job -import org.springframework.batch.core.Step -import org.springframework.batch.core.job.builder.JobBuilder -import org.springframework.batch.core.repository.JobRepository -import org.springframework.batch.core.step.builder.StepBuilder -import org.springframework.batch.repeat.RepeatStatus -import org.springframework.context.annotation.Bean -import org.springframework.context.annotation.Configuration -import org.springframework.transaction.PlatformTransactionManager - -@Configuration -open class TestJobConfig( - private val jobRepository: JobRepository, - private val transactionManager: PlatformTransactionManager, -) { - - @Bean - open fun testJob(): Job { - return JobBuilder("testJob", jobRepository) - .start(testStep1()).on("COMPLETED").to(successStep()) - .from(testStep1()).on("FAILED").to(failureStep()) - .from(testStep1()).on("*").stop() - .build() - .build() - } - - @Bean - open fun testStep1(): Step { - return StepBuilder("testStep1", jobRepository) - .tasklet( - { _, _ -> - throw IllegalStateException("step failed") - }, - transactionManager, - ) - .build() - } - - @Bean - open fun successStep(): Step { - return StepBuilder("successStep", jobRepository) - .tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) - .build() - } - - @Bean - open fun failureStep(): Step { - return StepBuilder("failureStep", jobRepository) - .tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) - .build() - } -} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/step/plain/bean/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/step/plain/bean/SampleApplicationTest.kt deleted file mode 100644 index 259dbe6f..00000000 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/step/plain/bean/SampleApplicationTest.kt +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Spring Batch Plus - * - * Copyright 2022-present NAVER Corp. - * - * 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 - * - * http://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 com.navercorp.spring.batch.plus.sample.job.flow.step.plain.bean - -import org.junit.jupiter.api.Test -import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher -import org.springframework.beans.factory.getBean -import org.springframework.boot.autoconfigure.SpringBootApplication -import org.springframework.boot.runApplication - -@SpringBootApplication -open class SampleApplicationTest { - @Test - fun run() { - val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() - val job = applicationContext.getBean() - - val jobParameters = JobParametersBuilder() - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) - - assert(BatchStatus.COMPLETED == jobExecution.status) - println(jobExecution) - } -} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/step/plain/bean/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/step/plain/bean/TestJobConfig.kt deleted file mode 100644 index 601b6559..00000000 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/step/plain/bean/TestJobConfig.kt +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Spring Batch Plus - * - * Copyright 2022-present NAVER Corp. - * - * 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 - * - * http://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 com.navercorp.spring.batch.plus.sample.job.flow.step.plain.bean - -import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.Job -import org.springframework.batch.core.Step -import org.springframework.batch.repeat.RepeatStatus -import org.springframework.context.annotation.Bean -import org.springframework.context.annotation.Configuration -import org.springframework.transaction.PlatformTransactionManager - -@Configuration -open class TestJobConfig( - private val batch: BatchDsl, - private val transactionManager: PlatformTransactionManager, -) { - - @Bean - open fun testJob(): Job = batch { - job("testJob") { - stepBean("testStep1") - stepBean("testStep2") - stepBean("testStep3") - } - } - - @Bean - open fun testStep1(): Step = batch { - step("testStep1") { - tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) - } - } - - @Bean - open fun testStep2(): Step = batch { - step("testStep2") { - tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) - } - } - - @Bean - open fun testStep3(): Step = batch { - step("testStep3") { - tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) - } - } -} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/step/plain/init/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/step/plain/init/SampleApplicationTest.kt deleted file mode 100644 index b91d81d4..00000000 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/step/plain/init/SampleApplicationTest.kt +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Spring Batch Plus - * - * Copyright 2022-present NAVER Corp. - * - * 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 - * - * http://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 com.navercorp.spring.batch.plus.sample.job.flow.step.plain.init - -import org.junit.jupiter.api.Test -import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher -import org.springframework.beans.factory.getBean -import org.springframework.boot.autoconfigure.SpringBootApplication -import org.springframework.boot.runApplication - -@SpringBootApplication -open class SampleApplicationTest { - @Test - fun run() { - val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() - val job = applicationContext.getBean() - - val jobParameters = JobParametersBuilder() - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) - - assert(BatchStatus.COMPLETED == jobExecution.status) - println(jobExecution) - } -} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/step/plain/variable/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/step/plain/variable/SampleApplicationTest.kt deleted file mode 100644 index 49bc22e7..00000000 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/step/plain/variable/SampleApplicationTest.kt +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Spring Batch Plus - * - * Copyright 2022-present NAVER Corp. - * - * 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 - * - * http://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 com.navercorp.spring.batch.plus.sample.job.flow.step.plain.variable - -import org.junit.jupiter.api.Test -import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher -import org.springframework.beans.factory.getBean -import org.springframework.boot.autoconfigure.SpringBootApplication -import org.springframework.boot.runApplication - -@SpringBootApplication -open class SampleApplicationTest { - @Test - fun run() { - val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() - val job = applicationContext.getBean() - - val jobParameters = JobParametersBuilder() - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) - - assert(BatchStatus.COMPLETED == jobExecution.status) - println(jobExecution) - } -} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/step/transition/bean/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/step/transition/bean/SampleApplicationTest.kt deleted file mode 100644 index 554bb285..00000000 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/step/transition/bean/SampleApplicationTest.kt +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Spring Batch Plus - * - * Copyright 2022-present NAVER Corp. - * - * 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 - * - * http://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 com.navercorp.spring.batch.plus.sample.job.flow.step.transition.bean - -import org.junit.jupiter.api.Test -import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher -import org.springframework.beans.factory.getBean -import org.springframework.boot.autoconfigure.SpringBootApplication -import org.springframework.boot.runApplication - -@SpringBootApplication -open class SampleApplicationTest { - @Test - fun run() { - val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() - val job = applicationContext.getBean() - - val jobParameters = JobParametersBuilder() - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) - - assert(BatchStatus.COMPLETED == jobExecution.status) - println(jobExecution) - } -} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/step/transition/bean/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/step/transition/bean/TestJobConfig.kt deleted file mode 100644 index 28ab5312..00000000 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/step/transition/bean/TestJobConfig.kt +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Spring Batch Plus - * - * Copyright 2022-present NAVER Corp. - * - * 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 - * - * http://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 com.navercorp.spring.batch.plus.sample.job.flow.step.transition.bean - -import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.Job -import org.springframework.batch.core.Step -import org.springframework.batch.repeat.RepeatStatus -import org.springframework.context.annotation.Bean -import org.springframework.context.annotation.Configuration -import org.springframework.transaction.PlatformTransactionManager - -@Configuration -open class TestJobConfig( - private val batch: BatchDsl, - private val transactionManager: PlatformTransactionManager, -) { - - @Bean - open fun testJob(): Job = batch { - job("testJob") { - stepBean("testStep") { - on("COMPLETED") { - end() - } - on("FAILED") { - step("transitionStep") { - tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) - } - } - on("*") { - stop() - } - } - } - } - - @Bean - open fun testStep(): Step = batch { - step("testStep") { - tasklet( - { _, _ -> throw IllegalStateException("testStep failed") }, - transactionManager, - ) - } - } -} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/step/transition/init/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/step/transition/init/SampleApplicationTest.kt deleted file mode 100644 index 8253c1f3..00000000 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/step/transition/init/SampleApplicationTest.kt +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Spring Batch Plus - * - * Copyright 2022-present NAVER Corp. - * - * 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 - * - * http://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 com.navercorp.spring.batch.plus.sample.job.flow.step.transition.init - -import org.junit.jupiter.api.Test -import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher -import org.springframework.beans.factory.getBean -import org.springframework.boot.autoconfigure.SpringBootApplication -import org.springframework.boot.runApplication - -@SpringBootApplication -open class SampleApplicationTest { - @Test - fun run() { - val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() - val job = applicationContext.getBean() - - val jobParameters = JobParametersBuilder() - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) - - assert(BatchStatus.COMPLETED == jobExecution.status) - println(jobExecution) - } -} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/step/transition/variable/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/step/transition/variable/SampleApplicationTest.kt deleted file mode 100644 index 65ccb827..00000000 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/step/transition/variable/SampleApplicationTest.kt +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Spring Batch Plus - * - * Copyright 2022-present NAVER Corp. - * - * 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 - * - * http://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 com.navercorp.spring.batch.plus.sample.job.flow.step.transition.variable - -import org.junit.jupiter.api.Test -import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher -import org.springframework.beans.factory.getBean -import org.springframework.boot.autoconfigure.SpringBootApplication -import org.springframework.boot.runApplication - -@SpringBootApplication -open class SampleApplicationTest { - @Test - fun run() { - val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() - val job = applicationContext.getBean() - - val jobParameters = JobParametersBuilder() - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) - - assert(BatchStatus.COMPLETED == jobExecution.status) - println(jobExecution) - } -} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/step/transition/variable/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/step/transition/variable/TestJobConfig.kt deleted file mode 100644 index 81dbaf91..00000000 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/step/transition/variable/TestJobConfig.kt +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Spring Batch Plus - * - * Copyright 2022-present NAVER Corp. - * - * 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 - * - * http://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 com.navercorp.spring.batch.plus.sample.job.flow.step.transition.variable - -import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.Job -import org.springframework.batch.core.Step -import org.springframework.batch.repeat.RepeatStatus -import org.springframework.context.annotation.Bean -import org.springframework.context.annotation.Configuration -import org.springframework.transaction.PlatformTransactionManager - -@Configuration -open class TestJobConfig( - private val batch: BatchDsl, - private val transactionManager: PlatformTransactionManager, -) { - - @Bean - open fun testJob(): Job = batch { - job("testJob") { - step(testStep()) { - on("COMPLETED") { - end() - } - on("FAILED") { - step("transitionStep") { - tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) - } - } - on("*") { - stop() - } - } - } - } - - @Bean - open fun testStep(): Step = batch { - step("testStep") { - tasklet( - { _, _ -> throw IllegalStateException("testStep failed") }, - transactionManager, - ) - } - } -} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/decider/bean/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/bean/SampleApplicationTest.kt similarity index 75% rename from spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/decider/bean/SampleApplicationTest.kt rename to spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/bean/SampleApplicationTest.kt index 2f0f9aad..00236b35 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/decider/bean/SampleApplicationTest.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/bean/SampleApplicationTest.kt @@ -16,13 +16,13 @@ * limitations under the License. */ -package com.navercorp.spring.batch.plus.sample.job.flow.transition.decider.bean +package com.navercorp.spring.batch.plus.sample.job.flow.transition.bean import org.junit.jupiter.api.Test import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator import org.springframework.beans.factory.getBean import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.runApplication @@ -32,12 +32,13 @@ open class SampleApplicationTest { @Test fun run() { val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() + val jobOperator = applicationContext.getBean() val job = applicationContext.getBean() - val jobParameters = JobParametersBuilder() - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) + val jobParameters = + JobParametersBuilder() + .toJobParameters() + val jobExecution = jobOperator.start(job, jobParameters) assert(BatchStatus.COMPLETED == jobExecution.status) println(jobExecution) diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/flow/init/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/bean/TestJobConfig.kt similarity index 62% rename from spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/flow/init/TestJobConfig.kt rename to spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/bean/TestJobConfig.kt index f313010e..d2dd5250 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/flow/init/TestJobConfig.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/bean/TestJobConfig.kt @@ -16,12 +16,12 @@ * limitations under the License. */ -package com.navercorp.spring.batch.plus.sample.job.flow.transition.flow.init +package com.navercorp.spring.batch.plus.sample.job.flow.transition.bean import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.Job -import org.springframework.batch.core.Step -import org.springframework.batch.repeat.RepeatStatus +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.flow.Flow +import org.springframework.batch.infrastructure.repeat.RepeatStatus import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.transaction.PlatformTransactionManager @@ -31,35 +31,36 @@ open class TestJobConfig( private val batch: BatchDsl, private val transactionManager: PlatformTransactionManager, ) { - @Bean - open fun testJob(): Job = batch { - job("testJob") { - step(testStep()) { - on("COMPLETED") { - end() - } - on("FAILED") { - flow("transitionFlow") { + open fun testJob(): Job = + batch { + job("testJob") { + flowBean("testFlow") { + on("COMPLETED") { + end() + } + on("FAILED") { step("transitionStep") { tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) } } - } - on("*") { - stop() + on("*") { + stop() + } } } } - } @Bean - open fun testStep(): Step = batch { - step("testStep") { - tasklet( - { _, _ -> throw IllegalStateException("testStep failed") }, - transactionManager, - ) + open fun testFlow(): Flow = + batch { + flow("testFlow") { + step("testStep") { + tasklet( + { _, _ -> throw IllegalStateException("testStep failed") }, + transactionManager, + ) + } + } } - } } diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/decider/bean/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/decider/bean/TestJobConfig.kt deleted file mode 100644 index 33161792..00000000 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/decider/bean/TestJobConfig.kt +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Spring Batch Plus - * - * Copyright 2022-present NAVER Corp. - * - * 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 - * - * http://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 com.navercorp.spring.batch.plus.sample.job.flow.transition.decider.bean - -import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.Job -import org.springframework.batch.core.Step -import org.springframework.batch.core.job.flow.FlowExecutionStatus -import org.springframework.batch.core.job.flow.JobExecutionDecider -import org.springframework.batch.repeat.RepeatStatus -import org.springframework.context.annotation.Bean -import org.springframework.context.annotation.Configuration -import org.springframework.transaction.PlatformTransactionManager - -@Configuration -open class TestJobConfig( - private val batch: BatchDsl, - private val transactionManager: PlatformTransactionManager, -) { - - @Bean - open fun testJob(): Job = batch { - job("testJob") { - step(testStep()) { - on("COMPLETED") { - end() - } - on("FAILED") { - deciderBean("testDecider") { - on("COMPLETED") { - stop() - } - on("BATCH TEST") { - step(transitionStep()) - } - on("*") { - fail() - } - } - } - on("*") { - stop() - } - } - } - } - - @Bean - open fun testStep(): Step = batch { - step("testStep") { - tasklet( - { _, _ -> throw IllegalStateException("testStep failed") }, - transactionManager, - ) - } - } - - @Bean - open fun testDecider(): JobExecutionDecider = JobExecutionDecider { _, _ -> - FlowExecutionStatus("BATCH TEST") - } - - @Bean - open fun transitionStep(): Step = batch { - step("transitionStep") { - tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) - } - } -} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/decider/variable/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/decider/variable/TestJobConfig.kt deleted file mode 100644 index d060e56b..00000000 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/decider/variable/TestJobConfig.kt +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Spring Batch Plus - * - * Copyright 2022-present NAVER Corp. - * - * 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 - * - * http://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 com.navercorp.spring.batch.plus.sample.job.flow.transition.decider.variable - -import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.Job -import org.springframework.batch.core.Step -import org.springframework.batch.core.job.flow.FlowExecutionStatus -import org.springframework.batch.core.job.flow.JobExecutionDecider -import org.springframework.batch.repeat.RepeatStatus -import org.springframework.context.annotation.Bean -import org.springframework.context.annotation.Configuration -import org.springframework.transaction.PlatformTransactionManager - -@Configuration -open class TestJobConfig( - private val batch: BatchDsl, - private val transactionManager: PlatformTransactionManager, -) { - - @Bean - open fun testJob(): Job = batch { - job("testJob") { - step(testStep()) { - on("COMPLETED") { - end() - } - on("FAILED") { - decider(testDecider()) { - on("COMPLETED") { - stop() - } - on("BATCH TEST") { - step(transitionStep()) - } - on("*") { - fail() - } - } - } - on("*") { - stop() - } - } - } - } - - @Bean - open fun testStep(): Step = batch { - step("testStep") { - tasklet( - { _, _ -> throw IllegalStateException("testStep failed") }, - transactionManager, - ) - } - } - - @Bean - open fun testDecider(): JobExecutionDecider = JobExecutionDecider { _, _ -> - FlowExecutionStatus("BATCH TEST") - } - - @Bean - open fun transitionStep(): Step = batch { - step("transitionStep") { - tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) - } - } -} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/finish/end/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/finish/end/TestJobConfig.kt deleted file mode 100644 index 02971cf7..00000000 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/finish/end/TestJobConfig.kt +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Spring Batch Plus - * - * Copyright 2022-present NAVER Corp. - * - * 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 - * - * http://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 com.navercorp.spring.batch.plus.sample.job.flow.transition.finish.end - -import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.Job -import org.springframework.batch.core.Step -import org.springframework.context.annotation.Bean -import org.springframework.context.annotation.Configuration -import org.springframework.transaction.PlatformTransactionManager - -@Configuration -open class TestJobConfig( - private val batch: BatchDsl, - private val transactionManager: PlatformTransactionManager, -) { - - @Bean - open fun testJob(): Job = batch { - job("testJob") { - step(testStep()) { - on("COMPLETED") { - stop() - } - on("FAILED") { - end("SKIPPED") - } - on("*") { - stop() - } - } - } - } - - @Bean - open fun testStep(): Step = batch { - step("testStep") { - tasklet( - { _, _ -> throw IllegalStateException("testStep failed") }, - transactionManager, - ) - } - } -} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/flow/bean/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/flow/bean/SampleApplicationTest.kt deleted file mode 100644 index a31b9831..00000000 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/flow/bean/SampleApplicationTest.kt +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Spring Batch Plus - * - * Copyright 2022-present NAVER Corp. - * - * 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 - * - * http://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 com.navercorp.spring.batch.plus.sample.job.flow.transition.flow.bean - -import org.junit.jupiter.api.Test -import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher -import org.springframework.beans.factory.getBean -import org.springframework.boot.autoconfigure.SpringBootApplication -import org.springframework.boot.runApplication - -@SpringBootApplication -open class SampleApplicationTest { - @Test - fun run() { - val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() - val job = applicationContext.getBean() - - val jobParameters = JobParametersBuilder() - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) - - assert(BatchStatus.COMPLETED == jobExecution.status) - println(jobExecution) - } -} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/flow/init/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/flow/init/SampleApplicationTest.kt deleted file mode 100644 index cdc91e17..00000000 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/flow/init/SampleApplicationTest.kt +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Spring Batch Plus - * - * Copyright 2022-present NAVER Corp. - * - * 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 - * - * http://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 com.navercorp.spring.batch.plus.sample.job.flow.transition.flow.init - -import org.junit.jupiter.api.Test -import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher -import org.springframework.beans.factory.getBean -import org.springframework.boot.autoconfigure.SpringBootApplication -import org.springframework.boot.runApplication - -@SpringBootApplication -open class SampleApplicationTest { - @Test - fun run() { - val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() - val job = applicationContext.getBean() - - val jobParameters = JobParametersBuilder() - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) - - assert(BatchStatus.COMPLETED == jobExecution.status) - println(jobExecution) - } -} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/flow/nested/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/flow/nested/SampleApplicationTest.kt deleted file mode 100644 index c88f62bc..00000000 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/flow/nested/SampleApplicationTest.kt +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Spring Batch Plus - * - * Copyright 2022-present NAVER Corp. - * - * 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 - * - * http://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 com.navercorp.spring.batch.plus.sample.job.flow.transition.flow.nested - -import org.junit.jupiter.api.Test -import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher -import org.springframework.beans.factory.getBean -import org.springframework.boot.autoconfigure.SpringBootApplication -import org.springframework.boot.runApplication - -@SpringBootApplication -open class SampleApplicationTest { - @Test - fun run() { - val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() - val job = applicationContext.getBean() - - val jobParameters = JobParametersBuilder() - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) - - assert(BatchStatus.COMPLETED == jobExecution.status) - println(jobExecution) - } -} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/flow/variable/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/flow/variable/SampleApplicationTest.kt deleted file mode 100644 index 6d4e1323..00000000 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/flow/variable/SampleApplicationTest.kt +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Spring Batch Plus - * - * Copyright 2022-present NAVER Corp. - * - * 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 - * - * http://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 com.navercorp.spring.batch.plus.sample.job.flow.transition.flow.variable - -import org.junit.jupiter.api.Test -import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher -import org.springframework.beans.factory.getBean -import org.springframework.boot.autoconfigure.SpringBootApplication -import org.springframework.boot.runApplication - -@SpringBootApplication -open class SampleApplicationTest { - @Test - fun run() { - val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() - val job = applicationContext.getBean() - - val jobParameters = JobParametersBuilder() - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) - - assert(BatchStatus.COMPLETED == jobExecution.status) - println(jobExecution) - } -} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/decider/variable/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/init/SampleApplicationTest.kt similarity index 75% rename from spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/decider/variable/SampleApplicationTest.kt rename to spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/init/SampleApplicationTest.kt index d639b16d..379452bb 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/decider/variable/SampleApplicationTest.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/init/SampleApplicationTest.kt @@ -16,13 +16,13 @@ * limitations under the License. */ -package com.navercorp.spring.batch.plus.sample.job.flow.transition.decider.variable +package com.navercorp.spring.batch.plus.sample.job.flow.transition.init import org.junit.jupiter.api.Test import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator import org.springframework.beans.factory.getBean import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.runApplication @@ -32,12 +32,13 @@ open class SampleApplicationTest { @Test fun run() { val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() + val jobOperator = applicationContext.getBean() val job = applicationContext.getBean() - val jobParameters = JobParametersBuilder() - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) + val jobParameters = + JobParametersBuilder() + .toJobParameters() + val jobExecution = jobOperator.start(job, jobParameters) assert(BatchStatus.COMPLETED == jobExecution.status) println(jobExecution) diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/step/init/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/init/TestJobConfig.kt similarity index 54% rename from spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/step/init/TestJobConfig.kt rename to spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/init/TestJobConfig.kt index 8fe82746..38ec98f9 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/step/init/TestJobConfig.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/init/TestJobConfig.kt @@ -16,12 +16,11 @@ * limitations under the License. */ -package com.navercorp.spring.batch.plus.sample.job.flow.transition.step.init +package com.navercorp.spring.batch.plus.sample.job.flow.transition.init import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.Job -import org.springframework.batch.core.Step -import org.springframework.batch.repeat.RepeatStatus +import org.springframework.batch.core.job.Job +import org.springframework.batch.infrastructure.repeat.RepeatStatus import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.transaction.PlatformTransactionManager @@ -31,33 +30,33 @@ open class TestJobConfig( private val batch: BatchDsl, private val transactionManager: PlatformTransactionManager, ) { - @Bean - open fun testJob(): Job = batch { - job("testJob") { - step(testStep()) { - on("COMPLETED") { - end() - } - on("FAILED") { - step("transitionStep") { - tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + open fun testJob(): Job = + batch { + job("testJob") { + flow( + "testFlow", + { + step("testStep") { + tasklet( + { _, _ -> throw IllegalStateException("testStep failed") }, + transactionManager, + ) + } + }, + ) { + on("COMPLETED") { + end() + } + on("FAILED") { + step("transitionStep") { + tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + } + } + on("*") { + stop() } - } - on("*") { - stop() } } } - } - - @Bean - open fun testStep(): Step = batch { - step("testStep") { - tasklet( - { _, _ -> throw IllegalStateException("testStep failed") }, - transactionManager, - ) - } - } } diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/step/bean/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/step/bean/SampleApplicationTest.kt deleted file mode 100644 index 5977d06f..00000000 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/step/bean/SampleApplicationTest.kt +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Spring Batch Plus - * - * Copyright 2022-present NAVER Corp. - * - * 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 - * - * http://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 com.navercorp.spring.batch.plus.sample.job.flow.transition.step.bean - -import org.junit.jupiter.api.Test -import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher -import org.springframework.beans.factory.getBean -import org.springframework.boot.autoconfigure.SpringBootApplication -import org.springframework.boot.runApplication - -@SpringBootApplication -open class SampleApplicationTest { - @Test - fun run() { - val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() - val job = applicationContext.getBean() - - val jobParameters = JobParametersBuilder() - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) - - assert(BatchStatus.COMPLETED == jobExecution.status) - println(jobExecution) - } -} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/step/bean/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/step/bean/TestJobConfig.kt deleted file mode 100644 index a7b70527..00000000 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/step/bean/TestJobConfig.kt +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Spring Batch Plus - * - * Copyright 2022-present NAVER Corp. - * - * 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 - * - * http://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 com.navercorp.spring.batch.plus.sample.job.flow.transition.step.bean - -import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.Job -import org.springframework.batch.core.Step -import org.springframework.batch.repeat.RepeatStatus -import org.springframework.context.annotation.Bean -import org.springframework.context.annotation.Configuration -import org.springframework.transaction.PlatformTransactionManager - -@Configuration -open class TestJobConfig( - private val batch: BatchDsl, - private val transactionManager: PlatformTransactionManager, -) { - - @Bean - open fun testJob(): Job = batch { - job("testJob") { - step(testStep()) { - on("COMPLETED") { - end() - } - on("FAILED") { - stepBean("transitionStep") - } - on("*") { - stop() - } - } - } - } - - @Bean - open fun testStep(): Step = batch { - step("testStep") { - tasklet( - { _, _ -> throw IllegalStateException("testStep failed") }, - transactionManager, - ) - } - } - - @Bean - open fun transitionStep(): Step = batch { - step("transitionStep") { - tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) - } - } -} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/step/init/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/step/init/SampleApplicationTest.kt deleted file mode 100644 index 0a8a4a4a..00000000 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/step/init/SampleApplicationTest.kt +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Spring Batch Plus - * - * Copyright 2022-present NAVER Corp. - * - * 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 - * - * http://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 com.navercorp.spring.batch.plus.sample.job.flow.transition.step.init - -import org.junit.jupiter.api.Test -import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher -import org.springframework.beans.factory.getBean -import org.springframework.boot.autoconfigure.SpringBootApplication -import org.springframework.boot.runApplication - -@SpringBootApplication -open class SampleApplicationTest { - @Test - fun run() { - val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() - val job = applicationContext.getBean() - - val jobParameters = JobParametersBuilder() - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) - - assert(BatchStatus.COMPLETED == jobExecution.status) - println(jobExecution) - } -} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/step/nested/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/step/nested/SampleApplicationTest.kt deleted file mode 100644 index 71b81d05..00000000 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/step/nested/SampleApplicationTest.kt +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Spring Batch Plus - * - * Copyright 2022-present NAVER Corp. - * - * 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 - * - * http://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 com.navercorp.spring.batch.plus.sample.job.flow.transition.step.nested - -import org.junit.jupiter.api.Test -import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher -import org.springframework.beans.factory.getBean -import org.springframework.boot.autoconfigure.SpringBootApplication -import org.springframework.boot.runApplication - -@SpringBootApplication -open class SampleApplicationTest { - @Test - fun run() { - val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() - val job = applicationContext.getBean() - - val jobParameters = JobParametersBuilder() - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) - - assert(BatchStatus.COMPLETED == jobExecution.status) - println(jobExecution) - } -} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/step/nested/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/step/nested/TestJobConfig.kt deleted file mode 100644 index 451b00e7..00000000 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/step/nested/TestJobConfig.kt +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Spring Batch Plus - * - * Copyright 2022-present NAVER Corp. - * - * 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 - * - * http://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 com.navercorp.spring.batch.plus.sample.job.flow.transition.step.nested - -import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.Job -import org.springframework.batch.core.Step -import org.springframework.batch.repeat.RepeatStatus -import org.springframework.context.annotation.Bean -import org.springframework.context.annotation.Configuration -import org.springframework.transaction.PlatformTransactionManager - -@Configuration -open class TestJobConfig( - private val batch: BatchDsl, - private val transactionManager: PlatformTransactionManager, -) { - - @Bean - open fun testJob(): Job = batch { - job("testJob") { - step(testStep()) { - on("COMPLETED") { - end() - } - on("FAILED") { - step(transitionStep()) { - on("COMPLETED") { - fail() - } - on("*") { - step("nestedStep") { - tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) - } - } - } - } - on("*") { - stop() - } - } - } - } - - @Bean - open fun testStep(): Step = batch { - step("testStep") { - tasklet( - { _, _ -> throw IllegalStateException("testStep failed") }, - transactionManager, - ) - } - } - - @Bean - open fun transitionStep(): Step = batch { - step("transitionStep") { - tasklet( - { _, _ -> throw IllegalStateException("transitionStep failed") }, - transactionManager, - ) - } - } -} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/step/variable/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/step/variable/SampleApplicationTest.kt deleted file mode 100644 index b5d2f7ff..00000000 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/step/variable/SampleApplicationTest.kt +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Spring Batch Plus - * - * Copyright 2022-present NAVER Corp. - * - * 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 - * - * http://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 com.navercorp.spring.batch.plus.sample.job.flow.transition.step.variable - -import org.junit.jupiter.api.Test -import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher -import org.springframework.beans.factory.getBean -import org.springframework.boot.autoconfigure.SpringBootApplication -import org.springframework.boot.runApplication - -@SpringBootApplication -open class SampleApplicationTest { - @Test - fun run() { - val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() - val job = applicationContext.getBean() - - val jobParameters = JobParametersBuilder() - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) - - assert(BatchStatus.COMPLETED == jobExecution.status) - println(jobExecution) - } -} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/step/variable/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/step/variable/TestJobConfig.kt deleted file mode 100644 index c31babae..00000000 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/step/variable/TestJobConfig.kt +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Spring Batch Plus - * - * Copyright 2022-present NAVER Corp. - * - * 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 - * - * http://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 com.navercorp.spring.batch.plus.sample.job.flow.transition.step.variable - -import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.Job -import org.springframework.batch.core.Step -import org.springframework.batch.repeat.RepeatStatus -import org.springframework.context.annotation.Bean -import org.springframework.context.annotation.Configuration -import org.springframework.transaction.PlatformTransactionManager - -@Configuration -open class TestJobConfig( - private val batch: BatchDsl, - private val transactionManager: PlatformTransactionManager, -) { - - @Bean - open fun testJob(): Job = batch { - job("testJob") { - step(testStep()) { - on("COMPLETED") { - end() - } - on("FAILED") { - step(transitionStep()) - } - on("*") { - stop() - } - } - } - } - - @Bean - open fun testStep(): Step = batch { - step("testStep") { - tasklet( - { _, _ -> throw IllegalStateException("testStep failed") }, - transactionManager, - ) - } - } - - @Bean - open fun transitionStep(): Step = batch { - step("transitionStep") { - tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) - } - } -} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/stopandrestart/step/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/stopandrestart/step/TestJobConfig.kt deleted file mode 100644 index 6b65fe3e..00000000 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/stopandrestart/step/TestJobConfig.kt +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Spring Batch Plus - * - * Copyright 2022-present NAVER Corp. - * - * 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 - * - * http://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 com.navercorp.spring.batch.plus.sample.job.flow.transition.stopandrestart.step - -import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.Job -import org.springframework.batch.core.Step -import org.springframework.batch.repeat.RepeatStatus -import org.springframework.context.annotation.Bean -import org.springframework.context.annotation.Configuration -import org.springframework.transaction.PlatformTransactionManager - -@Configuration -open class TestJobConfig( - private val batch: BatchDsl, - private val transactionManager: PlatformTransactionManager, -) { - - @Bean - open fun testJob(): Job = batch { - job("testJob") { - step(testStep()) { - on("COMPLETED") { - stopAndRestartToStep("restartStep") { - tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) - } - } - on("*") { - stop() - } - } - } - } - - @Bean - open fun testStep(): Step = batch { - step("testStep") { - tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) - } - } -} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/finish/end/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/variable/SampleApplicationTest.kt similarity index 75% rename from spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/finish/end/SampleApplicationTest.kt rename to spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/variable/SampleApplicationTest.kt index 5a40c11d..c2e6f210 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/finish/end/SampleApplicationTest.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/variable/SampleApplicationTest.kt @@ -16,13 +16,13 @@ * limitations under the License. */ -package com.navercorp.spring.batch.plus.sample.job.flow.transition.finish.end +package com.navercorp.spring.batch.plus.sample.job.flow.transition.variable import org.junit.jupiter.api.Test import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator import org.springframework.beans.factory.getBean import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.runApplication @@ -32,12 +32,13 @@ open class SampleApplicationTest { @Test fun run() { val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() + val jobOperator = applicationContext.getBean() val job = applicationContext.getBean() - val jobParameters = JobParametersBuilder() - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) + val jobParameters = + JobParametersBuilder() + .toJobParameters() + val jobExecution = jobOperator.start(job, jobParameters) assert(BatchStatus.COMPLETED == jobExecution.status) println(jobExecution) diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/step/transition/init/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/variable/TestJobConfig.kt similarity index 59% rename from spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/step/transition/init/TestJobConfig.kt rename to spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/variable/TestJobConfig.kt index 8e1fbbcf..5d7787c1 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/step/transition/init/TestJobConfig.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/variable/TestJobConfig.kt @@ -16,11 +16,12 @@ * limitations under the License. */ -package com.navercorp.spring.batch.plus.sample.job.flow.step.transition.init +package com.navercorp.spring.batch.plus.sample.job.flow.transition.variable import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.Job -import org.springframework.batch.repeat.RepeatStatus +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.flow.Flow +import org.springframework.batch.infrastructure.repeat.RepeatStatus import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.transaction.PlatformTransactionManager @@ -30,31 +31,36 @@ open class TestJobConfig( private val batch: BatchDsl, private val transactionManager: PlatformTransactionManager, ) { + @Bean + open fun testJob(): Job = + batch { + job("testJob") { + flow(testFlow()) { + on("COMPLETED") { + end() + } + on("FAILED") { + step("transitionStep") { + tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + } + } + on("*") { + stop() + } + } + } + } @Bean - open fun testJob(): Job = batch { - job("testJob") { - step( - "testStep", - { + open fun testFlow(): Flow = + batch { + flow("testFlow") { + step("testStep") { tasklet( { _, _ -> throw IllegalStateException("testStep failed") }, transactionManager, ) - }, - ) { - on("COMPLETED") { - end() - } - on("FAILED") { - step("transitionStep") { - tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) - } - } - on("*") { - stop() } } } - } } diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/split/README.md b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/split/README.md new file mode 100644 index 00000000..9a65e3ed --- /dev/null +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/split/README.md @@ -0,0 +1,6 @@ +# Job Split Samples + +## Invariants + +- Flow-job split examples from the Kotlin DSL job guide should have runnable + samples in this package. diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/split/bean/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/split/bean/SampleApplicationTest.kt index 570aa59c..d5bda71f 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/split/bean/SampleApplicationTest.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/split/bean/SampleApplicationTest.kt @@ -20,9 +20,9 @@ package com.navercorp.spring.batch.plus.sample.job.split.bean import org.junit.jupiter.api.Test import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator import org.springframework.beans.factory.getBean import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.runApplication @@ -32,12 +32,13 @@ open class SampleApplicationTest { @Test fun run() { val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() + val jobOperator = applicationContext.getBean() val job = applicationContext.getBean() - val jobParameters = JobParametersBuilder() - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) + val jobParameters = + JobParametersBuilder() + .toJobParameters() + val jobExecution = jobOperator.start(job, jobParameters) assert(BatchStatus.COMPLETED == jobExecution.status) println(jobExecution) diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/split/bean/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/split/bean/TestJobConfig.kt index 4b514c56..d8c848d6 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/split/bean/TestJobConfig.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/split/bean/TestJobConfig.kt @@ -19,9 +19,9 @@ package com.navercorp.spring.batch.plus.sample.job.split.bean import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.Job +import org.springframework.batch.core.job.Job import org.springframework.batch.core.job.flow.Flow -import org.springframework.batch.repeat.RepeatStatus +import org.springframework.batch.infrastructure.repeat.RepeatStatus import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.core.task.SimpleAsyncTaskExecutor @@ -32,42 +32,45 @@ open class TestJobConfig( private val batch: BatchDsl, private val transactionManager: PlatformTransactionManager, ) { - @Bean - open fun testJob(): Job = batch { - job("testJob") { - split(SimpleAsyncTaskExecutor()) { - flowBean("testFlow1") - flowBean("testFlow2") - flowBean("testFlow3") + open fun testJob(): Job = + batch { + job("testJob") { + split(SimpleAsyncTaskExecutor()) { + flowBean("testFlow1") + flowBean("testFlow2") + flowBean("testFlow3") + } } } - } @Bean - open fun testFlow1(): Flow = batch { - flow("testFlow1") { - step("testStep1") { - tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + open fun testFlow1(): Flow = + batch { + flow("testFlow1") { + step("testStep1") { + tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + } } } - } @Bean - open fun testFlow2(): Flow = batch { - flow("testFlow2") { - step("testStep1") { - tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + open fun testFlow2(): Flow = + batch { + flow("testFlow2") { + step("testStep1") { + tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + } } } - } @Bean - open fun testFlow3(): Flow = batch { - flow("testFlow3") { - step("testStep1") { - tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + open fun testFlow3(): Flow = + batch { + flow("testFlow3") { + step("testStep1") { + tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + } } } - } } diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/split/init/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/split/init/SampleApplicationTest.kt index e4f94830..46de6d53 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/split/init/SampleApplicationTest.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/split/init/SampleApplicationTest.kt @@ -20,9 +20,9 @@ package com.navercorp.spring.batch.plus.sample.job.split.init import org.junit.jupiter.api.Test import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator import org.springframework.beans.factory.getBean import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.runApplication @@ -32,12 +32,13 @@ open class SampleApplicationTest { @Test fun run() { val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() + val jobOperator = applicationContext.getBean() val job = applicationContext.getBean() - val jobParameters = JobParametersBuilder() - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) + val jobParameters = + JobParametersBuilder() + .toJobParameters() + val jobExecution = jobOperator.start(job, jobParameters) assert(BatchStatus.COMPLETED == jobExecution.status) println(jobExecution) diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/split/init/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/split/init/TestJobConfig.kt index 2e85b6d3..183060cd 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/split/init/TestJobConfig.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/split/init/TestJobConfig.kt @@ -19,8 +19,8 @@ package com.navercorp.spring.batch.plus.sample.job.split.init import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.Job -import org.springframework.batch.repeat.RepeatStatus +import org.springframework.batch.core.job.Job +import org.springframework.batch.infrastructure.repeat.RepeatStatus import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.core.task.SimpleAsyncTaskExecutor @@ -31,27 +31,27 @@ open class TestJobConfig( private val batch: BatchDsl, private val transactionManager: PlatformTransactionManager, ) { - @Bean - open fun testJob(): Job = batch { - job("testJob") { - split(SimpleAsyncTaskExecutor()) { - flow("testFlow1") { - step("testStep1") { - tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + open fun testJob(): Job = + batch { + job("testJob") { + split(SimpleAsyncTaskExecutor()) { + flow("testFlow1") { + step("testStep1") { + tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + } } - } - flow("testFlow2") { - step("testStep2") { - tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + flow("testFlow2") { + step("testStep2") { + tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + } } - } - flow("testFlow3") { - step("testStep3") { - tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + flow("testFlow3") { + step("testStep3") { + tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + } } } } } - } } diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/split/variable/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/split/variable/SampleApplicationTest.kt index fd4a7deb..4e79f182 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/split/variable/SampleApplicationTest.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/split/variable/SampleApplicationTest.kt @@ -20,9 +20,9 @@ package com.navercorp.spring.batch.plus.sample.job.split.variable import org.junit.jupiter.api.Test import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator import org.springframework.beans.factory.getBean import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.runApplication @@ -32,12 +32,13 @@ open class SampleApplicationTest { @Test fun run() { val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() + val jobOperator = applicationContext.getBean() val job = applicationContext.getBean() - val jobParameters = JobParametersBuilder() - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) + val jobParameters = + JobParametersBuilder() + .toJobParameters() + val jobExecution = jobOperator.start(job, jobParameters) assert(BatchStatus.COMPLETED == jobExecution.status) println(jobExecution) diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/split/variable/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/split/variable/TestJobConfig.kt index e031be37..9ebf5926 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/split/variable/TestJobConfig.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/split/variable/TestJobConfig.kt @@ -19,9 +19,9 @@ package com.navercorp.spring.batch.plus.sample.job.split.variable import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.Job +import org.springframework.batch.core.job.Job import org.springframework.batch.core.job.flow.Flow -import org.springframework.batch.repeat.RepeatStatus +import org.springframework.batch.infrastructure.repeat.RepeatStatus import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.core.task.SimpleAsyncTaskExecutor @@ -32,40 +32,43 @@ open class TestJobConfig( private val batch: BatchDsl, private val transactionManager: PlatformTransactionManager, ) { - @Bean - open fun testJob(): Job = batch { - job("testJob") { - val testFlow3 = batch { - flow("testFlow3") { - step("testStep3") { - tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + open fun testJob(): Job = + batch { + job("testJob") { + val testFlow3 = + batch { + flow("testFlow3") { + step("testStep3") { + tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + } + } } + split(SimpleAsyncTaskExecutor()) { + flow(testFlow1()) + flow(testFlow2()) + flow(testFlow3) } } - split(SimpleAsyncTaskExecutor()) { - flow(testFlow1()) - flow(testFlow2()) - flow(testFlow3) - } } - } @Bean - open fun testFlow1(): Flow = batch { - flow("testFlow1") { - step("testStep1") { - tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + open fun testFlow1(): Flow = + batch { + flow("testFlow1") { + step("testStep1") { + tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + } } } - } @Bean - open fun testFlow2(): Flow = batch { - flow("testFlow2") { - step("testStep2") { - tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + open fun testFlow2(): Flow = + batch { + flow("testFlow2") { + step("testStep2") { + tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + } } } - } } diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/step/README.md b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/step/README.md new file mode 100644 index 00000000..9a6152d5 --- /dev/null +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/step/README.md @@ -0,0 +1,10 @@ +# Job Step Selection Samples + +## Invariants + +- The [`sequential`](sequential) package should cover step selections by bean + lookup, inline creation, and variable input on the simple-job path. +- The [`transition`](transition) package should cover the same input forms on + the flow-job path. +- General transition DSL examples are covered in the sibling + [`transition`](../transition) package. diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/step/sequential/bean/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/step/sequential/bean/SampleApplicationTest.kt new file mode 100644 index 00000000..96ce96e9 --- /dev/null +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/step/sequential/bean/SampleApplicationTest.kt @@ -0,0 +1,46 @@ +/* + * Spring Batch Plus + * + * Copyright 2022-present NAVER Corp. + * + * 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 + * + * http://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 com.navercorp.spring.batch.plus.sample.job.step.sequential.bean + +import org.junit.jupiter.api.Test +import org.springframework.batch.core.BatchStatus +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator +import org.springframework.beans.factory.getBean +import org.springframework.boot.autoconfigure.SpringBootApplication +import org.springframework.boot.runApplication + +@SpringBootApplication +open class SampleApplicationTest { + @Test + fun run() { + val applicationContext = runApplication() + val jobOperator = applicationContext.getBean() + val job = applicationContext.getBean() + + val jobParameters = + JobParametersBuilder() + .toJobParameters() + val jobExecution = jobOperator.start(job, jobParameters) + + assert(BatchStatus.COMPLETED == jobExecution.status) + println(jobExecution) + } +} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/step/plain/init/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/step/sequential/bean/TestJobConfig.kt similarity index 68% rename from spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/step/plain/init/TestJobConfig.kt rename to spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/step/sequential/bean/TestJobConfig.kt index 0bf11a2c..6b498ac5 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/step/plain/init/TestJobConfig.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/step/sequential/bean/TestJobConfig.kt @@ -16,11 +16,12 @@ * limitations under the License. */ -package com.navercorp.spring.batch.plus.sample.job.flow.step.plain.init +package com.navercorp.spring.batch.plus.sample.job.step.sequential.bean import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.Job -import org.springframework.batch.repeat.RepeatStatus +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.step.Step +import org.springframework.batch.infrastructure.repeat.RepeatStatus import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.transaction.PlatformTransactionManager @@ -30,19 +31,37 @@ open class TestJobConfig( private val batch: BatchDsl, private val transactionManager: PlatformTransactionManager, ) { + @Bean + open fun testJob(): Job = + batch { + job("testJob") { + stepBean("testStep1") + stepBean("testStep2") + stepBean("testStep3") + } + } @Bean - open fun testJob(): Job = batch { - job("testJob") { + open fun testStep1(): Step = + batch { step("testStep1") { tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) } + } + + @Bean + open fun testStep2(): Step = + batch { step("testStep2") { tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) } + } + + @Bean + open fun testStep3(): Step = + batch { step("testStep3") { tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) } } - } } diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/step/sequential/init/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/step/sequential/init/SampleApplicationTest.kt new file mode 100644 index 00000000..6eece17b --- /dev/null +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/step/sequential/init/SampleApplicationTest.kt @@ -0,0 +1,46 @@ +/* + * Spring Batch Plus + * + * Copyright 2022-present NAVER Corp. + * + * 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 + * + * http://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 com.navercorp.spring.batch.plus.sample.job.step.sequential.init + +import org.junit.jupiter.api.Test +import org.springframework.batch.core.BatchStatus +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator +import org.springframework.beans.factory.getBean +import org.springframework.boot.autoconfigure.SpringBootApplication +import org.springframework.boot.runApplication + +@SpringBootApplication +open class SampleApplicationTest { + @Test + fun run() { + val applicationContext = runApplication() + val jobOperator = applicationContext.getBean() + val job = applicationContext.getBean() + + val jobParameters = + JobParametersBuilder() + .toJobParameters() + val jobExecution = jobOperator.start(job, jobParameters) + + assert(BatchStatus.COMPLETED == jobExecution.status) + println(jobExecution) + } +} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/flow/plain/init/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/step/sequential/init/TestJobConfig.kt similarity index 75% rename from spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/flow/plain/init/TestJobConfig.kt rename to spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/step/sequential/init/TestJobConfig.kt index 01a62f2f..a06e1df6 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/flow/plain/init/TestJobConfig.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/step/sequential/init/TestJobConfig.kt @@ -16,11 +16,11 @@ * limitations under the License. */ -package com.navercorp.spring.batch.plus.sample.job.flow.flow.plain.init +package com.navercorp.spring.batch.plus.sample.job.step.sequential.init import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.Job -import org.springframework.batch.repeat.RepeatStatus +import org.springframework.batch.core.job.Job +import org.springframework.batch.infrastructure.repeat.RepeatStatus import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.transaction.PlatformTransactionManager @@ -30,23 +30,19 @@ open class TestJobConfig( private val batch: BatchDsl, private val transactionManager: PlatformTransactionManager, ) { - @Bean - open fun testJob(): Job = batch { - job("testJob") { - flow("testFlow1") { - step("testFlow1Step1") { + open fun testJob(): Job = + batch { + job("testJob") { + step("testStep1") { tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) } - step("testFlow1Step2") { + step("testStep2") { tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) } - } - flow("testFlow2") { - step("testFlow2Step1") { + step("testStep3") { tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) } } } - } } diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/step/sequential/variable/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/step/sequential/variable/SampleApplicationTest.kt new file mode 100644 index 00000000..0533e853 --- /dev/null +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/step/sequential/variable/SampleApplicationTest.kt @@ -0,0 +1,46 @@ +/* + * Spring Batch Plus + * + * Copyright 2022-present NAVER Corp. + * + * 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 + * + * http://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 com.navercorp.spring.batch.plus.sample.job.step.sequential.variable + +import org.junit.jupiter.api.Test +import org.springframework.batch.core.BatchStatus +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator +import org.springframework.beans.factory.getBean +import org.springframework.boot.autoconfigure.SpringBootApplication +import org.springframework.boot.runApplication + +@SpringBootApplication +open class SampleApplicationTest { + @Test + fun run() { + val applicationContext = runApplication() + val jobOperator = applicationContext.getBean() + val job = applicationContext.getBean() + + val jobParameters = + JobParametersBuilder() + .toJobParameters() + val jobExecution = jobOperator.start(job, jobParameters) + + assert(BatchStatus.COMPLETED == jobExecution.status) + println(jobExecution) + } +} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/flow/plain/variable/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/step/sequential/variable/TestJobConfig.kt similarity index 57% rename from spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/flow/plain/variable/TestJobConfig.kt rename to spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/step/sequential/variable/TestJobConfig.kt index 3c0e4954..4d3d48f8 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/flow/plain/variable/TestJobConfig.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/step/sequential/variable/TestJobConfig.kt @@ -16,12 +16,12 @@ * limitations under the License. */ -package com.navercorp.spring.batch.plus.sample.job.flow.flow.plain.variable +package com.navercorp.spring.batch.plus.sample.job.step.sequential.variable import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.Job -import org.springframework.batch.core.job.flow.Flow -import org.springframework.batch.repeat.RepeatStatus +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.step.Step +import org.springframework.batch.infrastructure.repeat.RepeatStatus import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.transaction.PlatformTransactionManager @@ -31,42 +31,36 @@ open class TestJobConfig( private val batch: BatchDsl, private val transactionManager: PlatformTransactionManager, ) { - @Bean - open fun testJob(): Job = batch { - job("testJob") { - val testFlow3 = batch { - flow("testFlow3") { - step("testFlow3Step1") { - tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + open fun testJob(): Job = + batch { + job("testJob") { + val testStep3 = + batch { + step("testStep3") { + tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + } } - } - } - flow(testFlow1()) - flow(testFlow2()) - flow(testFlow3) + step(testStep1()) + step(testStep2()) + step(testStep3) + } } - } @Bean - open fun testFlow1(): Flow = batch { - flow("testFlow1") { - step("testFlow1Step1") { - tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) - } - step("testFlow1Step2") { + open fun testStep1(): Step = + batch { + step("testStep1") { tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) } } - } @Bean - open fun testFlow2(): Flow = batch { - flow("testFlow2") { - step("testFlow2Step1") { + open fun testStep2(): Step = + batch { + step("testStep2") { tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) } } - } } diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/step/transition/bean/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/step/transition/bean/SampleApplicationTest.kt new file mode 100644 index 00000000..e6b6747c --- /dev/null +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/step/transition/bean/SampleApplicationTest.kt @@ -0,0 +1,46 @@ +/* + * Spring Batch Plus + * + * Copyright 2022-present NAVER Corp. + * + * 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 + * + * http://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 com.navercorp.spring.batch.plus.sample.job.step.transition.bean + +import org.junit.jupiter.api.Test +import org.springframework.batch.core.BatchStatus +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator +import org.springframework.beans.factory.getBean +import org.springframework.boot.autoconfigure.SpringBootApplication +import org.springframework.boot.runApplication + +@SpringBootApplication +open class SampleApplicationTest { + @Test + fun run() { + val applicationContext = runApplication() + val jobOperator = applicationContext.getBean() + val job = applicationContext.getBean() + + val jobParameters = + JobParametersBuilder() + .toJobParameters() + val jobExecution = jobOperator.start(job, jobParameters) + + assert(BatchStatus.COMPLETED == jobExecution.status) + println(jobExecution) + } +} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/step/transition/bean/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/step/transition/bean/TestJobConfig.kt new file mode 100644 index 00000000..14332d6e --- /dev/null +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/step/transition/bean/TestJobConfig.kt @@ -0,0 +1,64 @@ +/* + * Spring Batch Plus + * + * Copyright 2022-present NAVER Corp. + * + * 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 + * + * http://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 com.navercorp.spring.batch.plus.sample.job.step.transition.bean + +import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.step.Step +import org.springframework.batch.infrastructure.repeat.RepeatStatus +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import org.springframework.transaction.PlatformTransactionManager + +@Configuration +open class TestJobConfig( + private val batch: BatchDsl, + private val transactionManager: PlatformTransactionManager, +) { + @Bean + open fun testJob(): Job = + batch { + job("testJob") { + stepBean("testStep") { + on("COMPLETED") { + end() + } + on("FAILED") { + step("transitionStep") { + tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + } + } + on("*") { + stop() + } + } + } + } + + @Bean + open fun testStep(): Step = + batch { + step("testStep") { + tasklet( + { _, _ -> throw IllegalStateException("testStep failed") }, + transactionManager, + ) + } + } +} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/step/transition/init/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/step/transition/init/SampleApplicationTest.kt new file mode 100644 index 00000000..710ea86e --- /dev/null +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/step/transition/init/SampleApplicationTest.kt @@ -0,0 +1,46 @@ +/* + * Spring Batch Plus + * + * Copyright 2022-present NAVER Corp. + * + * 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 + * + * http://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 com.navercorp.spring.batch.plus.sample.job.step.transition.init + +import org.junit.jupiter.api.Test +import org.springframework.batch.core.BatchStatus +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator +import org.springframework.beans.factory.getBean +import org.springframework.boot.autoconfigure.SpringBootApplication +import org.springframework.boot.runApplication + +@SpringBootApplication +open class SampleApplicationTest { + @Test + fun run() { + val applicationContext = runApplication() + val jobOperator = applicationContext.getBean() + val job = applicationContext.getBean() + + val jobParameters = + JobParametersBuilder() + .toJobParameters() + val jobExecution = jobOperator.start(job, jobParameters) + + assert(BatchStatus.COMPLETED == jobExecution.status) + println(jobExecution) + } +} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/flow/transition/init/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/step/transition/init/TestJobConfig.kt similarity index 64% rename from spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/flow/transition/init/TestJobConfig.kt rename to spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/step/transition/init/TestJobConfig.kt index cef15d48..89affff1 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/flow/transition/init/TestJobConfig.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/step/transition/init/TestJobConfig.kt @@ -16,11 +16,11 @@ * limitations under the License. */ -package com.navercorp.spring.batch.plus.sample.job.flow.flow.transition.init +package com.navercorp.spring.batch.plus.sample.job.step.transition.init import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.Job -import org.springframework.batch.repeat.RepeatStatus +import org.springframework.batch.core.job.Job +import org.springframework.batch.infrastructure.repeat.RepeatStatus import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.transaction.PlatformTransactionManager @@ -30,33 +30,31 @@ open class TestJobConfig( private val batch: BatchDsl, private val transactionManager: PlatformTransactionManager, ) { - @Bean - open fun testJob(): Job = batch { - job("testJob") { - flow( - "testFlow", - { - step("testStep") { + open fun testJob(): Job = + batch { + job("testJob") { + step( + "testStep", + { tasklet( { _, _ -> throw IllegalStateException("testStep failed") }, transactionManager, ) + }, + ) { + on("COMPLETED") { + end() } - }, - ) { - on("COMPLETED") { - end() - } - on("FAILED") { - step("transitionStep") { - tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + on("FAILED") { + step("transitionStep") { + tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + } + } + on("*") { + stop() } - } - on("*") { - stop() } } } - } } diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/step/transition/variable/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/step/transition/variable/SampleApplicationTest.kt new file mode 100644 index 00000000..6e19b9ef --- /dev/null +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/step/transition/variable/SampleApplicationTest.kt @@ -0,0 +1,46 @@ +/* + * Spring Batch Plus + * + * Copyright 2022-present NAVER Corp. + * + * 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 + * + * http://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 com.navercorp.spring.batch.plus.sample.job.step.transition.variable + +import org.junit.jupiter.api.Test +import org.springframework.batch.core.BatchStatus +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator +import org.springframework.beans.factory.getBean +import org.springframework.boot.autoconfigure.SpringBootApplication +import org.springframework.boot.runApplication + +@SpringBootApplication +open class SampleApplicationTest { + @Test + fun run() { + val applicationContext = runApplication() + val jobOperator = applicationContext.getBean() + val job = applicationContext.getBean() + + val jobParameters = + JobParametersBuilder() + .toJobParameters() + val jobExecution = jobOperator.start(job, jobParameters) + + assert(BatchStatus.COMPLETED == jobExecution.status) + println(jobExecution) + } +} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/step/transition/variable/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/step/transition/variable/TestJobConfig.kt new file mode 100644 index 00000000..5fa0af53 --- /dev/null +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/step/transition/variable/TestJobConfig.kt @@ -0,0 +1,64 @@ +/* + * Spring Batch Plus + * + * Copyright 2022-present NAVER Corp. + * + * 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 + * + * http://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 com.navercorp.spring.batch.plus.sample.job.step.transition.variable + +import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.step.Step +import org.springframework.batch.infrastructure.repeat.RepeatStatus +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import org.springframework.transaction.PlatformTransactionManager + +@Configuration +open class TestJobConfig( + private val batch: BatchDsl, + private val transactionManager: PlatformTransactionManager, +) { + @Bean + open fun testJob(): Job = + batch { + job("testJob") { + step(testStep()) { + on("COMPLETED") { + end() + } + on("FAILED") { + step("transitionStep") { + tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + } + } + on("*") { + stop() + } + } + } + } + + @Bean + open fun testStep(): Step = + batch { + step("testStep") { + tasklet( + { _, _ -> throw IllegalStateException("testStep failed") }, + transactionManager, + ) + } + } +} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/README.md b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/README.md new file mode 100644 index 00000000..46abe3bf --- /dev/null +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/README.md @@ -0,0 +1,18 @@ +# Job Transition Samples + +## Invariants + +- Every transition scenario documented by the Kotlin DSL job flow guide should + have a runnable sample in this package. + +## Packages + +- [`step`](step) demonstrates selecting a step as the next state and continuing + from it. +- [`flow`](flow) demonstrates selecting a flow as the next state and continuing + from it. +- [`decider`](decider) demonstrates routing execution through a decision state. +- [`terminal`](terminal) demonstrates completing a transition without selecting + another state. +- [`stopandrestart`](stopandrestart) demonstrates stopping a job while defining + where the next execution resumes. diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/decider/bean/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/decider/bean/SampleApplicationTest.kt new file mode 100644 index 00000000..d3294d20 --- /dev/null +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/decider/bean/SampleApplicationTest.kt @@ -0,0 +1,46 @@ +/* + * Spring Batch Plus + * + * Copyright 2022-present NAVER Corp. + * + * 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 + * + * http://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 com.navercorp.spring.batch.plus.sample.job.transition.decider.bean + +import org.junit.jupiter.api.Test +import org.springframework.batch.core.BatchStatus +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator +import org.springframework.beans.factory.getBean +import org.springframework.boot.autoconfigure.SpringBootApplication +import org.springframework.boot.runApplication + +@SpringBootApplication +open class SampleApplicationTest { + @Test + fun run() { + val applicationContext = runApplication() + val jobOperator = applicationContext.getBean() + val job = applicationContext.getBean() + + val jobParameters = + JobParametersBuilder() + .toJobParameters() + val jobExecution = jobOperator.start(job, jobParameters) + + assert(BatchStatus.COMPLETED == jobExecution.status) + println(jobExecution) + } +} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/decider/bean/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/decider/bean/TestJobConfig.kt new file mode 100644 index 00000000..517e3a8d --- /dev/null +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/decider/bean/TestJobConfig.kt @@ -0,0 +1,88 @@ +/* + * Spring Batch Plus + * + * Copyright 2022-present NAVER Corp. + * + * 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 + * + * http://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 com.navercorp.spring.batch.plus.sample.job.transition.decider.bean + +import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.flow.FlowExecutionStatus +import org.springframework.batch.core.job.flow.JobExecutionDecider +import org.springframework.batch.core.step.Step +import org.springframework.batch.infrastructure.repeat.RepeatStatus +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import org.springframework.transaction.PlatformTransactionManager + +@Configuration +open class TestJobConfig( + private val batch: BatchDsl, + private val transactionManager: PlatformTransactionManager, +) { + @Bean + open fun testJob(): Job = + batch { + job("testJob") { + step(testStep()) { + on("COMPLETED") { + end() + } + on("FAILED") { + deciderBean("testDecider") { + on("COMPLETED") { + stop() + } + on("BATCH TEST") { + step(transitionStep()) + } + on("*") { + fail() + } + } + } + on("*") { + stop() + } + } + } + } + + @Bean + open fun testStep(): Step = + batch { + step("testStep") { + tasklet( + { _, _ -> throw IllegalStateException("testStep failed") }, + transactionManager, + ) + } + } + + @Bean + open fun testDecider(): JobExecutionDecider = + JobExecutionDecider { _, _ -> + FlowExecutionStatus("BATCH TEST") + } + + @Bean + open fun transitionStep(): Step = + batch { + step("transitionStep") { + tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + } + } +} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/decider/variable/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/decider/variable/SampleApplicationTest.kt new file mode 100644 index 00000000..8290f320 --- /dev/null +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/decider/variable/SampleApplicationTest.kt @@ -0,0 +1,46 @@ +/* + * Spring Batch Plus + * + * Copyright 2022-present NAVER Corp. + * + * 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 + * + * http://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 com.navercorp.spring.batch.plus.sample.job.transition.decider.variable + +import org.junit.jupiter.api.Test +import org.springframework.batch.core.BatchStatus +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator +import org.springframework.beans.factory.getBean +import org.springframework.boot.autoconfigure.SpringBootApplication +import org.springframework.boot.runApplication + +@SpringBootApplication +open class SampleApplicationTest { + @Test + fun run() { + val applicationContext = runApplication() + val jobOperator = applicationContext.getBean() + val job = applicationContext.getBean() + + val jobParameters = + JobParametersBuilder() + .toJobParameters() + val jobExecution = jobOperator.start(job, jobParameters) + + assert(BatchStatus.COMPLETED == jobExecution.status) + println(jobExecution) + } +} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/decider/variable/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/decider/variable/TestJobConfig.kt new file mode 100644 index 00000000..7c0cea0d --- /dev/null +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/decider/variable/TestJobConfig.kt @@ -0,0 +1,88 @@ +/* + * Spring Batch Plus + * + * Copyright 2022-present NAVER Corp. + * + * 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 + * + * http://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 com.navercorp.spring.batch.plus.sample.job.transition.decider.variable + +import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.flow.FlowExecutionStatus +import org.springframework.batch.core.job.flow.JobExecutionDecider +import org.springframework.batch.core.step.Step +import org.springframework.batch.infrastructure.repeat.RepeatStatus +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import org.springframework.transaction.PlatformTransactionManager + +@Configuration +open class TestJobConfig( + private val batch: BatchDsl, + private val transactionManager: PlatformTransactionManager, +) { + @Bean + open fun testJob(): Job = + batch { + job("testJob") { + step(testStep()) { + on("COMPLETED") { + end() + } + on("FAILED") { + decider(testDecider()) { + on("COMPLETED") { + stop() + } + on("BATCH TEST") { + step(transitionStep()) + } + on("*") { + fail() + } + } + } + on("*") { + stop() + } + } + } + } + + @Bean + open fun testStep(): Step = + batch { + step("testStep") { + tasklet( + { _, _ -> throw IllegalStateException("testStep failed") }, + transactionManager, + ) + } + } + + @Bean + open fun testDecider(): JobExecutionDecider = + JobExecutionDecider { _, _ -> + FlowExecutionStatus("BATCH TEST") + } + + @Bean + open fun transitionStep(): Step = + batch { + step("transitionStep") { + tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + } + } +} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/flow/bean/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/flow/bean/SampleApplicationTest.kt new file mode 100644 index 00000000..0a9a8d5b --- /dev/null +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/flow/bean/SampleApplicationTest.kt @@ -0,0 +1,46 @@ +/* + * Spring Batch Plus + * + * Copyright 2022-present NAVER Corp. + * + * 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 + * + * http://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 com.navercorp.spring.batch.plus.sample.job.transition.flow.bean + +import org.junit.jupiter.api.Test +import org.springframework.batch.core.BatchStatus +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator +import org.springframework.beans.factory.getBean +import org.springframework.boot.autoconfigure.SpringBootApplication +import org.springframework.boot.runApplication + +@SpringBootApplication +open class SampleApplicationTest { + @Test + fun run() { + val applicationContext = runApplication() + val jobOperator = applicationContext.getBean() + val job = applicationContext.getBean() + + val jobParameters = + JobParametersBuilder() + .toJobParameters() + val jobExecution = jobOperator.start(job, jobParameters) + + assert(BatchStatus.COMPLETED == jobExecution.status) + println(jobExecution) + } +} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/flow/bean/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/flow/bean/TestJobConfig.kt new file mode 100644 index 00000000..e8bbf41a --- /dev/null +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/flow/bean/TestJobConfig.kt @@ -0,0 +1,73 @@ +/* + * Spring Batch Plus + * + * Copyright 2022-present NAVER Corp. + * + * 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 + * + * http://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 com.navercorp.spring.batch.plus.sample.job.transition.flow.bean + +import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.flow.Flow +import org.springframework.batch.core.step.Step +import org.springframework.batch.infrastructure.repeat.RepeatStatus +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import org.springframework.transaction.PlatformTransactionManager + +@Configuration +open class TestJobConfig( + private val batch: BatchDsl, + private val transactionManager: PlatformTransactionManager, +) { + @Bean + open fun testJob(): Job = + batch { + job("testJob") { + step(testStep()) { + on("COMPLETED") { + end() + } + on("FAILED") { + flowBean("transitionFlow") + } + on("*") { + stop() + } + } + } + } + + @Bean + open fun testStep(): Step = + batch { + step("testStep") { + tasklet( + { _, _ -> throw IllegalStateException("testStep failed") }, + transactionManager, + ) + } + } + + @Bean + open fun transitionFlow(): Flow = + batch { + flow("transitionFlow") { + step("transitionStep") { + tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + } + } + } +} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/flow/init/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/flow/init/SampleApplicationTest.kt new file mode 100644 index 00000000..99daa5f7 --- /dev/null +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/flow/init/SampleApplicationTest.kt @@ -0,0 +1,46 @@ +/* + * Spring Batch Plus + * + * Copyright 2022-present NAVER Corp. + * + * 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 + * + * http://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 com.navercorp.spring.batch.plus.sample.job.transition.flow.init + +import org.junit.jupiter.api.Test +import org.springframework.batch.core.BatchStatus +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator +import org.springframework.beans.factory.getBean +import org.springframework.boot.autoconfigure.SpringBootApplication +import org.springframework.boot.runApplication + +@SpringBootApplication +open class SampleApplicationTest { + @Test + fun run() { + val applicationContext = runApplication() + val jobOperator = applicationContext.getBean() + val job = applicationContext.getBean() + + val jobParameters = + JobParametersBuilder() + .toJobParameters() + val jobExecution = jobOperator.start(job, jobParameters) + + assert(BatchStatus.COMPLETED == jobExecution.status) + println(jobExecution) + } +} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/flow/init/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/flow/init/TestJobConfig.kt new file mode 100644 index 00000000..477b2f08 --- /dev/null +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/flow/init/TestJobConfig.kt @@ -0,0 +1,66 @@ +/* + * Spring Batch Plus + * + * Copyright 2022-present NAVER Corp. + * + * 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 + * + * http://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 com.navercorp.spring.batch.plus.sample.job.transition.flow.init + +import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.step.Step +import org.springframework.batch.infrastructure.repeat.RepeatStatus +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import org.springframework.transaction.PlatformTransactionManager + +@Configuration +open class TestJobConfig( + private val batch: BatchDsl, + private val transactionManager: PlatformTransactionManager, +) { + @Bean + open fun testJob(): Job = + batch { + job("testJob") { + step(testStep()) { + on("COMPLETED") { + end() + } + on("FAILED") { + flow("transitionFlow") { + step("transitionStep") { + tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + } + } + } + on("*") { + stop() + } + } + } + } + + @Bean + open fun testStep(): Step = + batch { + step("testStep") { + tasklet( + { _, _ -> throw IllegalStateException("testStep failed") }, + transactionManager, + ) + } + } +} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/flow/nested/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/flow/nested/SampleApplicationTest.kt new file mode 100644 index 00000000..e16c990d --- /dev/null +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/flow/nested/SampleApplicationTest.kt @@ -0,0 +1,46 @@ +/* + * Spring Batch Plus + * + * Copyright 2022-present NAVER Corp. + * + * 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 + * + * http://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 com.navercorp.spring.batch.plus.sample.job.transition.flow.nested + +import org.junit.jupiter.api.Test +import org.springframework.batch.core.BatchStatus +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator +import org.springframework.beans.factory.getBean +import org.springframework.boot.autoconfigure.SpringBootApplication +import org.springframework.boot.runApplication + +@SpringBootApplication +open class SampleApplicationTest { + @Test + fun run() { + val applicationContext = runApplication() + val jobOperator = applicationContext.getBean() + val job = applicationContext.getBean() + + val jobParameters = + JobParametersBuilder() + .toJobParameters() + val jobExecution = jobOperator.start(job, jobParameters) + + assert(BatchStatus.COMPLETED == jobExecution.status) + println(jobExecution) + } +} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/flow/nested/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/flow/nested/TestJobConfig.kt new file mode 100644 index 00000000..5e928aa0 --- /dev/null +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/flow/nested/TestJobConfig.kt @@ -0,0 +1,85 @@ +/* + * Spring Batch Plus + * + * Copyright 2022-present NAVER Corp. + * + * 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 + * + * http://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 com.navercorp.spring.batch.plus.sample.job.transition.flow.nested + +import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.flow.Flow +import org.springframework.batch.core.step.Step +import org.springframework.batch.infrastructure.repeat.RepeatStatus +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import org.springframework.transaction.PlatformTransactionManager + +@Configuration +open class TestJobConfig( + private val batch: BatchDsl, + private val transactionManager: PlatformTransactionManager, +) { + @Bean + open fun testJob(): Job = + batch { + job("testJob") { + step(testStep()) { + on("COMPLETED") { + end() + } + on("FAILED") { + flow(transitionFlow()) { + on("COMPLETED") { + fail() + } + on("*") { + step("nestedStep") { + tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + } + } + } + } + on("*") { + stop() + } + } + } + } + + @Bean + open fun testStep(): Step = + batch { + step("testStep") { + tasklet( + { _, _ -> throw IllegalStateException("testStep failed") }, + transactionManager, + ) + } + } + + @Bean + open fun transitionFlow(): Flow = + batch { + flow("transitionFlow") { + step("transitionStep") { + tasklet( + { _, _ -> throw IllegalStateException("transitionStep failed") }, + transactionManager, + ) + } + } + } +} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/flow/variable/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/flow/variable/SampleApplicationTest.kt new file mode 100644 index 00000000..fbb3bc7f --- /dev/null +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/flow/variable/SampleApplicationTest.kt @@ -0,0 +1,46 @@ +/* + * Spring Batch Plus + * + * Copyright 2022-present NAVER Corp. + * + * 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 + * + * http://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 com.navercorp.spring.batch.plus.sample.job.transition.flow.variable + +import org.junit.jupiter.api.Test +import org.springframework.batch.core.BatchStatus +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator +import org.springframework.beans.factory.getBean +import org.springframework.boot.autoconfigure.SpringBootApplication +import org.springframework.boot.runApplication + +@SpringBootApplication +open class SampleApplicationTest { + @Test + fun run() { + val applicationContext = runApplication() + val jobOperator = applicationContext.getBean() + val job = applicationContext.getBean() + + val jobParameters = + JobParametersBuilder() + .toJobParameters() + val jobExecution = jobOperator.start(job, jobParameters) + + assert(BatchStatus.COMPLETED == jobExecution.status) + println(jobExecution) + } +} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/flow/variable/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/flow/variable/TestJobConfig.kt new file mode 100644 index 00000000..25f0c2a3 --- /dev/null +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/flow/variable/TestJobConfig.kt @@ -0,0 +1,73 @@ +/* + * Spring Batch Plus + * + * Copyright 2022-present NAVER Corp. + * + * 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 + * + * http://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 com.navercorp.spring.batch.plus.sample.job.transition.flow.variable + +import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.flow.Flow +import org.springframework.batch.core.step.Step +import org.springframework.batch.infrastructure.repeat.RepeatStatus +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import org.springframework.transaction.PlatformTransactionManager + +@Configuration +open class TestJobConfig( + private val batch: BatchDsl, + private val transactionManager: PlatformTransactionManager, +) { + @Bean + open fun testJob(): Job = + batch { + job("testJob") { + step(testStep()) { + on("COMPLETED") { + end() + } + on("FAILED") { + flow(transitionFlow()) + } + on("*") { + stop() + } + } + } + } + + @Bean + open fun testStep(): Step = + batch { + step("testStep") { + tasklet( + { _, _ -> throw IllegalStateException("testStep failed") }, + transactionManager, + ) + } + } + + @Bean + open fun transitionFlow(): Flow = + batch { + flow("transitionFlow") { + step("transitionStep") { + tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + } + } + } +} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/step/bean/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/step/bean/SampleApplicationTest.kt new file mode 100644 index 00000000..9d1686d3 --- /dev/null +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/step/bean/SampleApplicationTest.kt @@ -0,0 +1,46 @@ +/* + * Spring Batch Plus + * + * Copyright 2022-present NAVER Corp. + * + * 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 + * + * http://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 com.navercorp.spring.batch.plus.sample.job.transition.step.bean + +import org.junit.jupiter.api.Test +import org.springframework.batch.core.BatchStatus +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator +import org.springframework.beans.factory.getBean +import org.springframework.boot.autoconfigure.SpringBootApplication +import org.springframework.boot.runApplication + +@SpringBootApplication +open class SampleApplicationTest { + @Test + fun run() { + val applicationContext = runApplication() + val jobOperator = applicationContext.getBean() + val job = applicationContext.getBean() + + val jobParameters = + JobParametersBuilder() + .toJobParameters() + val jobExecution = jobOperator.start(job, jobParameters) + + assert(BatchStatus.COMPLETED == jobExecution.status) + println(jobExecution) + } +} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/step/bean/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/step/bean/TestJobConfig.kt new file mode 100644 index 00000000..d4139ac2 --- /dev/null +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/step/bean/TestJobConfig.kt @@ -0,0 +1,70 @@ +/* + * Spring Batch Plus + * + * Copyright 2022-present NAVER Corp. + * + * 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 + * + * http://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 com.navercorp.spring.batch.plus.sample.job.transition.step.bean + +import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.step.Step +import org.springframework.batch.infrastructure.repeat.RepeatStatus +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import org.springframework.transaction.PlatformTransactionManager + +@Configuration +open class TestJobConfig( + private val batch: BatchDsl, + private val transactionManager: PlatformTransactionManager, +) { + @Bean + open fun testJob(): Job = + batch { + job("testJob") { + step(testStep()) { + on("COMPLETED") { + end() + } + on("FAILED") { + stepBean("transitionStep") + } + on("*") { + stop() + } + } + } + } + + @Bean + open fun testStep(): Step = + batch { + step("testStep") { + tasklet( + { _, _ -> throw IllegalStateException("testStep failed") }, + transactionManager, + ) + } + } + + @Bean + open fun transitionStep(): Step = + batch { + step("transitionStep") { + tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + } + } +} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/step/init/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/step/init/SampleApplicationTest.kt new file mode 100644 index 00000000..32703a70 --- /dev/null +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/step/init/SampleApplicationTest.kt @@ -0,0 +1,46 @@ +/* + * Spring Batch Plus + * + * Copyright 2022-present NAVER Corp. + * + * 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 + * + * http://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 com.navercorp.spring.batch.plus.sample.job.transition.step.init + +import org.junit.jupiter.api.Test +import org.springframework.batch.core.BatchStatus +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator +import org.springframework.beans.factory.getBean +import org.springframework.boot.autoconfigure.SpringBootApplication +import org.springframework.boot.runApplication + +@SpringBootApplication +open class SampleApplicationTest { + @Test + fun run() { + val applicationContext = runApplication() + val jobOperator = applicationContext.getBean() + val job = applicationContext.getBean() + + val jobParameters = + JobParametersBuilder() + .toJobParameters() + val jobExecution = jobOperator.start(job, jobParameters) + + assert(BatchStatus.COMPLETED == jobExecution.status) + println(jobExecution) + } +} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/flow/transition/variable/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/step/init/TestJobConfig.kt similarity index 63% rename from spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/flow/transition/variable/TestJobConfig.kt rename to spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/step/init/TestJobConfig.kt index cd179182..f2c57128 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/flow/transition/variable/TestJobConfig.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/step/init/TestJobConfig.kt @@ -16,12 +16,12 @@ * limitations under the License. */ -package com.navercorp.spring.batch.plus.sample.job.flow.flow.transition.variable +package com.navercorp.spring.batch.plus.sample.job.transition.step.init import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.Job -import org.springframework.batch.core.job.flow.Flow -import org.springframework.batch.repeat.RepeatStatus +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.step.Step +import org.springframework.batch.infrastructure.repeat.RepeatStatus import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.transaction.PlatformTransactionManager @@ -31,29 +31,29 @@ open class TestJobConfig( private val batch: BatchDsl, private val transactionManager: PlatformTransactionManager, ) { - @Bean - open fun testJob(): Job = batch { - job("testJob") { - flow(testFlow()) { - on("COMPLETED") { - end() - } - on("FAILED") { - step("transitionStep") { - tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + open fun testJob(): Job = + batch { + job("testJob") { + step(testStep()) { + on("COMPLETED") { + end() + } + on("FAILED") { + step("transitionStep") { + tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + } + } + on("*") { + stop() } - } - on("*") { - stop() } } } - } @Bean - open fun testFlow(): Flow = batch { - flow("testFlow") { + open fun testStep(): Step = + batch { step("testStep") { tasklet( { _, _ -> throw IllegalStateException("testStep failed") }, @@ -61,5 +61,4 @@ open class TestJobConfig( ) } } - } } diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/step/nested/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/step/nested/SampleApplicationTest.kt new file mode 100644 index 00000000..3d6d00ae --- /dev/null +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/step/nested/SampleApplicationTest.kt @@ -0,0 +1,46 @@ +/* + * Spring Batch Plus + * + * Copyright 2022-present NAVER Corp. + * + * 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 + * + * http://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 com.navercorp.spring.batch.plus.sample.job.transition.step.nested + +import org.junit.jupiter.api.Test +import org.springframework.batch.core.BatchStatus +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator +import org.springframework.beans.factory.getBean +import org.springframework.boot.autoconfigure.SpringBootApplication +import org.springframework.boot.runApplication + +@SpringBootApplication +open class SampleApplicationTest { + @Test + fun run() { + val applicationContext = runApplication() + val jobOperator = applicationContext.getBean() + val job = applicationContext.getBean() + + val jobParameters = + JobParametersBuilder() + .toJobParameters() + val jobExecution = jobOperator.start(job, jobParameters) + + assert(BatchStatus.COMPLETED == jobExecution.status) + println(jobExecution) + } +} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/step/nested/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/step/nested/TestJobConfig.kt new file mode 100644 index 00000000..575ee439 --- /dev/null +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/step/nested/TestJobConfig.kt @@ -0,0 +1,82 @@ +/* + * Spring Batch Plus + * + * Copyright 2022-present NAVER Corp. + * + * 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 + * + * http://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 com.navercorp.spring.batch.plus.sample.job.transition.step.nested + +import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.step.Step +import org.springframework.batch.infrastructure.repeat.RepeatStatus +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import org.springframework.transaction.PlatformTransactionManager + +@Configuration +open class TestJobConfig( + private val batch: BatchDsl, + private val transactionManager: PlatformTransactionManager, +) { + @Bean + open fun testJob(): Job = + batch { + job("testJob") { + step(testStep()) { + on("COMPLETED") { + end() + } + on("FAILED") { + step(transitionStep()) { + on("COMPLETED") { + fail() + } + on("*") { + step("nestedStep") { + tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + } + } + } + } + on("*") { + stop() + } + } + } + } + + @Bean + open fun testStep(): Step = + batch { + step("testStep") { + tasklet( + { _, _ -> throw IllegalStateException("testStep failed") }, + transactionManager, + ) + } + } + + @Bean + open fun transitionStep(): Step = + batch { + step("transitionStep") { + tasklet( + { _, _ -> throw IllegalStateException("transitionStep failed") }, + transactionManager, + ) + } + } +} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/step/variable/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/step/variable/SampleApplicationTest.kt new file mode 100644 index 00000000..2adf4e48 --- /dev/null +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/step/variable/SampleApplicationTest.kt @@ -0,0 +1,46 @@ +/* + * Spring Batch Plus + * + * Copyright 2022-present NAVER Corp. + * + * 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 + * + * http://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 com.navercorp.spring.batch.plus.sample.job.transition.step.variable + +import org.junit.jupiter.api.Test +import org.springframework.batch.core.BatchStatus +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator +import org.springframework.beans.factory.getBean +import org.springframework.boot.autoconfigure.SpringBootApplication +import org.springframework.boot.runApplication + +@SpringBootApplication +open class SampleApplicationTest { + @Test + fun run() { + val applicationContext = runApplication() + val jobOperator = applicationContext.getBean() + val job = applicationContext.getBean() + + val jobParameters = + JobParametersBuilder() + .toJobParameters() + val jobExecution = jobOperator.start(job, jobParameters) + + assert(BatchStatus.COMPLETED == jobExecution.status) + println(jobExecution) + } +} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/step/variable/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/step/variable/TestJobConfig.kt new file mode 100644 index 00000000..8a0057f5 --- /dev/null +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/step/variable/TestJobConfig.kt @@ -0,0 +1,70 @@ +/* + * Spring Batch Plus + * + * Copyright 2022-present NAVER Corp. + * + * 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 + * + * http://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 com.navercorp.spring.batch.plus.sample.job.transition.step.variable + +import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.step.Step +import org.springframework.batch.infrastructure.repeat.RepeatStatus +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import org.springframework.transaction.PlatformTransactionManager + +@Configuration +open class TestJobConfig( + private val batch: BatchDsl, + private val transactionManager: PlatformTransactionManager, +) { + @Bean + open fun testJob(): Job = + batch { + job("testJob") { + step(testStep()) { + on("COMPLETED") { + end() + } + on("FAILED") { + step(transitionStep()) + } + on("*") { + stop() + } + } + } + } + + @Bean + open fun testStep(): Step = + batch { + step("testStep") { + tasklet( + { _, _ -> throw IllegalStateException("testStep failed") }, + transactionManager, + ) + } + } + + @Bean + open fun transitionStep(): Step = + batch { + step("transitionStep") { + tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + } + } +} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/stopandrestart/decider/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/stopandrestart/decider/bean/SampleApplicationTest.kt similarity index 70% rename from spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/stopandrestart/decider/SampleApplicationTest.kt rename to spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/stopandrestart/decider/bean/SampleApplicationTest.kt index 4be92876..e606a4f8 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/stopandrestart/decider/SampleApplicationTest.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/stopandrestart/decider/bean/SampleApplicationTest.kt @@ -16,13 +16,13 @@ * limitations under the License. */ -package com.navercorp.spring.batch.plus.sample.job.flow.transition.stopandrestart.decider +package com.navercorp.spring.batch.plus.sample.job.transition.stopandrestart.decider.bean import org.junit.jupiter.api.Test import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator import org.springframework.beans.factory.getBean import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.runApplication @@ -32,14 +32,15 @@ open class SampleApplicationTest { @Test fun run() { val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() + val jobOperator = applicationContext.getBean() val job = applicationContext.getBean() - val jobParameters = JobParametersBuilder() - .toJobParameters() + val jobParameters = + JobParametersBuilder() + .toJobParameters() - val firstJobExecution = jobLauncher.run(job, jobParameters) - val secondJobExecution = jobLauncher.run(job, jobParameters) + val firstJobExecution = jobOperator.start(job, jobParameters) + val secondJobExecution = jobOperator.start(job, jobParameters) assert(BatchStatus.STOPPED == firstJobExecution.status) println("firstJobExecution: $firstJobExecution") diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/stopandrestart/decider/bean/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/stopandrestart/decider/bean/TestJobConfig.kt new file mode 100644 index 00000000..50249e0f --- /dev/null +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/stopandrestart/decider/bean/TestJobConfig.kt @@ -0,0 +1,74 @@ +/* + * Spring Batch Plus + * + * Copyright 2022-present NAVER Corp. + * + * 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 + * + * http://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 com.navercorp.spring.batch.plus.sample.job.transition.stopandrestart.decider.bean + +import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.flow.FlowExecutionStatus +import org.springframework.batch.core.job.flow.JobExecutionDecider +import org.springframework.batch.core.step.Step +import org.springframework.batch.infrastructure.repeat.RepeatStatus +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import org.springframework.transaction.PlatformTransactionManager + +@Configuration +open class TestJobConfig( + private val batch: BatchDsl, + private val transactionManager: PlatformTransactionManager, +) { + @Bean + open fun testJob(): Job = + batch { + job("testJob") { + step(testStep()) { + on("COMPLETED") { + stopAndRestartToDeciderBean("testDecider") { + on("COMPLETED") { + end() + } + on("BATCH TEST") { + fail() + } + on("*") { + end() + } + } + } + on("*") { + stop() + } + } + } + } + + @Bean + open fun testStep(): Step = + batch { + step("testStep") { + tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + } + } + + @Bean + open fun testDecider(): JobExecutionDecider = + JobExecutionDecider { _, _ -> + FlowExecutionStatus("BATCH TEST") + } +} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/stopandrestart/decider/variable/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/stopandrestart/decider/variable/SampleApplicationTest.kt new file mode 100644 index 00000000..8562fc03 --- /dev/null +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/stopandrestart/decider/variable/SampleApplicationTest.kt @@ -0,0 +1,51 @@ +/* + * Spring Batch Plus + * + * Copyright 2022-present NAVER Corp. + * + * 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 + * + * http://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 com.navercorp.spring.batch.plus.sample.job.transition.stopandrestart.decider.variable + +import org.junit.jupiter.api.Test +import org.springframework.batch.core.BatchStatus +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator +import org.springframework.beans.factory.getBean +import org.springframework.boot.autoconfigure.SpringBootApplication +import org.springframework.boot.runApplication + +@SpringBootApplication +open class SampleApplicationTest { + @Test + fun run() { + val applicationContext = runApplication() + val jobOperator = applicationContext.getBean() + val job = applicationContext.getBean() + + val jobParameters = + JobParametersBuilder() + .toJobParameters() + + val firstJobExecution = jobOperator.start(job, jobParameters) + val secondJobExecution = jobOperator.start(job, jobParameters) + + assert(BatchStatus.STOPPED == firstJobExecution.status) + println("firstJobExecution: $firstJobExecution") + + assert(BatchStatus.FAILED == secondJobExecution.status) + println("secondJobExecution: $secondJobExecution") + } +} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/stopandrestart/decider/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/stopandrestart/decider/variable/TestJobConfig.kt similarity index 51% rename from spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/stopandrestart/decider/TestJobConfig.kt rename to spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/stopandrestart/decider/variable/TestJobConfig.kt index 1f70e8f5..47b47f04 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/stopandrestart/decider/TestJobConfig.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/stopandrestart/decider/variable/TestJobConfig.kt @@ -16,14 +16,14 @@ * limitations under the License. */ -package com.navercorp.spring.batch.plus.sample.job.flow.transition.stopandrestart.decider +package com.navercorp.spring.batch.plus.sample.job.transition.stopandrestart.decider.variable import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.Job -import org.springframework.batch.core.Step +import org.springframework.batch.core.job.Job import org.springframework.batch.core.job.flow.FlowExecutionStatus import org.springframework.batch.core.job.flow.JobExecutionDecider -import org.springframework.batch.repeat.RepeatStatus +import org.springframework.batch.core.step.Step +import org.springframework.batch.infrastructure.repeat.RepeatStatus import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.transaction.PlatformTransactionManager @@ -33,40 +33,42 @@ open class TestJobConfig( private val batch: BatchDsl, private val transactionManager: PlatformTransactionManager, ) { - @Bean - open fun testJob(): Job = batch { - job("testJob") { - step(testStep()) { - on("COMPLETED") { - stopAndRestartToDecider(testDecider()) { - on("COMPLETED") { - end() - } - on("BATCH TEST") { - fail() - } - on("*") { - end() + open fun testJob(): Job = + batch { + job("testJob") { + step(testStep()) { + on("COMPLETED") { + stopAndRestartToDecider(testDecider()) { + on("COMPLETED") { + end() + } + on("BATCH TEST") { + fail() + } + on("*") { + end() + } } } - } - on("*") { - stop() + on("*") { + stop() + } } } } - } @Bean - open fun testStep(): Step = batch { - step("testStep") { - tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + open fun testStep(): Step = + batch { + step("testStep") { + tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + } } - } @Bean - open fun testDecider(): JobExecutionDecider = JobExecutionDecider { _, _ -> - FlowExecutionStatus("BATCH TEST") - } + open fun testDecider(): JobExecutionDecider = + JobExecutionDecider { _, _ -> + FlowExecutionStatus("BATCH TEST") + } } diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/stopandrestart/flow/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/stopandrestart/flow/bean/SampleApplicationTest.kt similarity index 70% rename from spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/stopandrestart/flow/SampleApplicationTest.kt rename to spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/stopandrestart/flow/bean/SampleApplicationTest.kt index 96de180c..e40a68bd 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/stopandrestart/flow/SampleApplicationTest.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/stopandrestart/flow/bean/SampleApplicationTest.kt @@ -16,13 +16,13 @@ * limitations under the License. */ -package com.navercorp.spring.batch.plus.sample.job.flow.transition.stopandrestart.flow +package com.navercorp.spring.batch.plus.sample.job.transition.stopandrestart.flow.bean import org.junit.jupiter.api.Test import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator import org.springframework.beans.factory.getBean import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.runApplication @@ -32,14 +32,15 @@ open class SampleApplicationTest { @Test fun run() { val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() + val jobOperator = applicationContext.getBean() val job = applicationContext.getBean() - val jobParameters = JobParametersBuilder() - .toJobParameters() + val jobParameters = + JobParametersBuilder() + .toJobParameters() - val firstJobExecution = jobLauncher.run(job, jobParameters) - val secondJobExecution = jobLauncher.run(job, jobParameters) + val firstJobExecution = jobOperator.start(job, jobParameters) + val secondJobExecution = jobOperator.start(job, jobParameters) assert(BatchStatus.STOPPED == firstJobExecution.status) println("firstJobExecution: $firstJobExecution") diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/flow/bean/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/stopandrestart/flow/bean/TestJobConfig.kt similarity index 59% rename from spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/flow/bean/TestJobConfig.kt rename to spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/stopandrestart/flow/bean/TestJobConfig.kt index b7ef99ef..a1b40722 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/flow/bean/TestJobConfig.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/stopandrestart/flow/bean/TestJobConfig.kt @@ -16,13 +16,13 @@ * limitations under the License. */ -package com.navercorp.spring.batch.plus.sample.job.flow.transition.flow.bean +package com.navercorp.spring.batch.plus.sample.job.transition.stopandrestart.flow.bean import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.Job -import org.springframework.batch.core.Step +import org.springframework.batch.core.job.Job import org.springframework.batch.core.job.flow.Flow -import org.springframework.batch.repeat.RepeatStatus +import org.springframework.batch.core.step.Step +import org.springframework.batch.infrastructure.repeat.RepeatStatus import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.transaction.PlatformTransactionManager @@ -32,40 +32,36 @@ open class TestJobConfig( private val batch: BatchDsl, private val transactionManager: PlatformTransactionManager, ) { - @Bean - open fun testJob(): Job = batch { - job("testJob") { - step(testStep()) { - on("COMPLETED") { - end() - } - on("FAILED") { - flowBean("transitionFlow") - } - on("*") { - stop() + open fun testJob(): Job = + batch { + job("testJob") { + step(testStep()) { + on("COMPLETED") { + stopAndRestartToFlowBean("restartFlow") + } + on("*") { + stop() + } } } } - } @Bean - open fun testStep(): Step = batch { - step("testStep") { - tasklet( - { _, _ -> throw IllegalStateException("testStep failed") }, - transactionManager, - ) + open fun testStep(): Step = + batch { + step("testStep") { + tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + } } - } @Bean - open fun transitionFlow(): Flow = batch { - flow("transitionFlow") { - step("transitionStep") { - tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + open fun restartFlow(): Flow = + batch { + flow("restartFlow") { + step("restartStep") { + tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + } } } - } } diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/stopandrestart/step/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/stopandrestart/flow/init/SampleApplicationTest.kt similarity index 70% rename from spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/stopandrestart/step/SampleApplicationTest.kt rename to spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/stopandrestart/flow/init/SampleApplicationTest.kt index c064cecd..1a369a73 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/stopandrestart/step/SampleApplicationTest.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/stopandrestart/flow/init/SampleApplicationTest.kt @@ -16,13 +16,13 @@ * limitations under the License. */ -package com.navercorp.spring.batch.plus.sample.job.flow.transition.stopandrestart.step +package com.navercorp.spring.batch.plus.sample.job.transition.stopandrestart.flow.init import org.junit.jupiter.api.Test import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator import org.springframework.beans.factory.getBean import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.runApplication @@ -32,14 +32,15 @@ open class SampleApplicationTest { @Test fun run() { val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() + val jobOperator = applicationContext.getBean() val job = applicationContext.getBean() - val jobParameters = JobParametersBuilder() - .toJobParameters() + val jobParameters = + JobParametersBuilder() + .toJobParameters() - val firstJobExecution = jobLauncher.run(job, jobParameters) - val secondJobExecution = jobLauncher.run(job, jobParameters) + val firstJobExecution = jobOperator.start(job, jobParameters) + val secondJobExecution = jobOperator.start(job, jobParameters) assert(BatchStatus.STOPPED == firstJobExecution.status) println("firstJobExecution: $firstJobExecution") diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/stopandrestart/flow/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/stopandrestart/flow/init/TestJobConfig.kt similarity index 64% rename from spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/stopandrestart/flow/TestJobConfig.kt rename to spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/stopandrestart/flow/init/TestJobConfig.kt index 6fcd16d3..2abf062e 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/stopandrestart/flow/TestJobConfig.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/stopandrestart/flow/init/TestJobConfig.kt @@ -16,12 +16,12 @@ * limitations under the License. */ -package com.navercorp.spring.batch.plus.sample.job.flow.transition.stopandrestart.flow +package com.navercorp.spring.batch.plus.sample.job.transition.stopandrestart.flow.init import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.Job -import org.springframework.batch.core.Step -import org.springframework.batch.repeat.RepeatStatus +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.step.Step +import org.springframework.batch.infrastructure.repeat.RepeatStatus import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.transaction.PlatformTransactionManager @@ -31,31 +31,30 @@ open class TestJobConfig( private val batch: BatchDsl, private val transactionManager: PlatformTransactionManager, ) { - @Bean - open fun testJob(): Job = batch { - job("testJob") { - step(testStep()) { - on("COMPLETED") { - stopAndRestartToFlow("restartFlow") { - flow("restartFlow") { + open fun testJob(): Job = + batch { + job("testJob") { + step(testStep()) { + on("COMPLETED") { + stopAndRestartToFlow("restartFlow") { step("restartStep") { tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) } } } - } - on("*") { - stop() + on("*") { + stop() + } } } } - } @Bean - open fun testStep(): Step = batch { - step("testStep") { - tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + open fun testStep(): Step = + batch { + step("testStep") { + tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + } } - } } diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/stopandrestart/flow/variable/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/stopandrestart/flow/variable/SampleApplicationTest.kt new file mode 100644 index 00000000..2fbf0de1 --- /dev/null +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/stopandrestart/flow/variable/SampleApplicationTest.kt @@ -0,0 +1,51 @@ +/* + * Spring Batch Plus + * + * Copyright 2022-present NAVER Corp. + * + * 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 + * + * http://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 com.navercorp.spring.batch.plus.sample.job.transition.stopandrestart.flow.variable + +import org.junit.jupiter.api.Test +import org.springframework.batch.core.BatchStatus +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator +import org.springframework.beans.factory.getBean +import org.springframework.boot.autoconfigure.SpringBootApplication +import org.springframework.boot.runApplication + +@SpringBootApplication +open class SampleApplicationTest { + @Test + fun run() { + val applicationContext = runApplication() + val jobOperator = applicationContext.getBean() + val job = applicationContext.getBean() + + val jobParameters = + JobParametersBuilder() + .toJobParameters() + + val firstJobExecution = jobOperator.start(job, jobParameters) + val secondJobExecution = jobOperator.start(job, jobParameters) + + assert(BatchStatus.STOPPED == firstJobExecution.status) + println("firstJobExecution: $firstJobExecution") + + assert(BatchStatus.COMPLETED == secondJobExecution.status) + println("secondJobExecution: $secondJobExecution") + } +} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/flow/variable/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/stopandrestart/flow/variable/TestJobConfig.kt similarity index 59% rename from spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/flow/variable/TestJobConfig.kt rename to spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/stopandrestart/flow/variable/TestJobConfig.kt index 70068ba4..03af63f4 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/flow/variable/TestJobConfig.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/stopandrestart/flow/variable/TestJobConfig.kt @@ -16,13 +16,13 @@ * limitations under the License. */ -package com.navercorp.spring.batch.plus.sample.job.flow.transition.flow.variable +package com.navercorp.spring.batch.plus.sample.job.transition.stopandrestart.flow.variable import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.Job -import org.springframework.batch.core.Step +import org.springframework.batch.core.job.Job import org.springframework.batch.core.job.flow.Flow -import org.springframework.batch.repeat.RepeatStatus +import org.springframework.batch.core.step.Step +import org.springframework.batch.infrastructure.repeat.RepeatStatus import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.transaction.PlatformTransactionManager @@ -32,40 +32,36 @@ open class TestJobConfig( private val batch: BatchDsl, private val transactionManager: PlatformTransactionManager, ) { - @Bean - open fun testJob(): Job = batch { - job("testJob") { - step(testStep()) { - on("COMPLETED") { - end() - } - on("FAILED") { - flow(transitionFlow()) - } - on("*") { - stop() + open fun testJob(): Job = + batch { + job("testJob") { + step(testStep()) { + on("COMPLETED") { + stopAndRestartToFlow(restartFlow()) + } + on("*") { + stop() + } } } } - } @Bean - open fun testStep(): Step = batch { - step("testStep") { - tasklet( - { _, _ -> throw IllegalStateException("testStep failed") }, - transactionManager, - ) + open fun testStep(): Step = + batch { + step("testStep") { + tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + } } - } @Bean - open fun transitionFlow(): Flow = batch { - flow("transitionFlow") { - step("transitionStep") { - tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + open fun restartFlow(): Flow = + batch { + flow("restartFlow") { + step("restartStep") { + tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + } } } - } } diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/stopandrestart/step/bean/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/stopandrestart/step/bean/SampleApplicationTest.kt new file mode 100644 index 00000000..3fda164d --- /dev/null +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/stopandrestart/step/bean/SampleApplicationTest.kt @@ -0,0 +1,51 @@ +/* + * Spring Batch Plus + * + * Copyright 2022-present NAVER Corp. + * + * 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 + * + * http://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 com.navercorp.spring.batch.plus.sample.job.transition.stopandrestart.step.bean + +import org.junit.jupiter.api.Test +import org.springframework.batch.core.BatchStatus +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator +import org.springframework.beans.factory.getBean +import org.springframework.boot.autoconfigure.SpringBootApplication +import org.springframework.boot.runApplication + +@SpringBootApplication +open class SampleApplicationTest { + @Test + fun run() { + val applicationContext = runApplication() + val jobOperator = applicationContext.getBean() + val job = applicationContext.getBean() + + val jobParameters = + JobParametersBuilder() + .toJobParameters() + + val firstJobExecution = jobOperator.start(job, jobParameters) + val secondJobExecution = jobOperator.start(job, jobParameters) + + assert(BatchStatus.STOPPED == firstJobExecution.status) + println("firstJobExecution: $firstJobExecution") + + assert(BatchStatus.COMPLETED == secondJobExecution.status) + println("secondJobExecution: $secondJobExecution") + } +} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/flow/plain/bean/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/stopandrestart/step/bean/TestJobConfig.kt similarity index 63% rename from spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/flow/plain/bean/TestJobConfig.kt rename to spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/stopandrestart/step/bean/TestJobConfig.kt index 82ba6fae..7df70e1c 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/flow/plain/bean/TestJobConfig.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/stopandrestart/step/bean/TestJobConfig.kt @@ -16,12 +16,12 @@ * limitations under the License. */ -package com.navercorp.spring.batch.plus.sample.job.flow.flow.plain.bean +package com.navercorp.spring.batch.plus.sample.job.transition.stopandrestart.step.bean import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.Job -import org.springframework.batch.core.job.flow.Flow -import org.springframework.batch.repeat.RepeatStatus +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.step.Step +import org.springframework.batch.infrastructure.repeat.RepeatStatus import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.transaction.PlatformTransactionManager @@ -31,33 +31,34 @@ open class TestJobConfig( private val batch: BatchDsl, private val transactionManager: PlatformTransactionManager, ) { - @Bean - open fun testJob(): Job = batch { - job("testJob") { - flowBean("testFlow1") - flowBean("testFlow2") + open fun testJob(): Job = + batch { + job("testJob") { + step(testStep()) { + on("COMPLETED") { + stopAndRestartToStepBean("restartStep") + } + on("*") { + stop() + } + } + } } - } @Bean - open fun testFlow1(): Flow = batch { - flow("testFlow1") { - step("testFlow1Step1") { - tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) - } - step("testFlow1Step2") { + open fun testStep(): Step = + batch { + step("testStep") { tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) } } - } @Bean - open fun testFlow2(): Flow = batch { - flow("testFlow2") { - step("testFlow2Step1") { + open fun restartStep(): Step = + batch { + step("restartStep") { tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) } } - } } diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/stopandrestart/step/init/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/stopandrestart/step/init/SampleApplicationTest.kt new file mode 100644 index 00000000..9d490978 --- /dev/null +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/stopandrestart/step/init/SampleApplicationTest.kt @@ -0,0 +1,51 @@ +/* + * Spring Batch Plus + * + * Copyright 2022-present NAVER Corp. + * + * 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 + * + * http://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 com.navercorp.spring.batch.plus.sample.job.transition.stopandrestart.step.init + +import org.junit.jupiter.api.Test +import org.springframework.batch.core.BatchStatus +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator +import org.springframework.beans.factory.getBean +import org.springframework.boot.autoconfigure.SpringBootApplication +import org.springframework.boot.runApplication + +@SpringBootApplication +open class SampleApplicationTest { + @Test + fun run() { + val applicationContext = runApplication() + val jobOperator = applicationContext.getBean() + val job = applicationContext.getBean() + + val jobParameters = + JobParametersBuilder() + .toJobParameters() + + val firstJobExecution = jobOperator.start(job, jobParameters) + val secondJobExecution = jobOperator.start(job, jobParameters) + + assert(BatchStatus.STOPPED == firstJobExecution.status) + println("firstJobExecution: $firstJobExecution") + + assert(BatchStatus.COMPLETED == secondJobExecution.status) + println("secondJobExecution: $secondJobExecution") + } +} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/jobstep/variable/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/stopandrestart/step/init/TestJobConfig.kt similarity index 61% rename from spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/jobstep/variable/TestJobConfig.kt rename to spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/stopandrestart/step/init/TestJobConfig.kt index 550514ee..52c25520 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/jobstep/variable/TestJobConfig.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/stopandrestart/step/init/TestJobConfig.kt @@ -16,11 +16,12 @@ * limitations under the License. */ -package com.navercorp.spring.batch.plus.sample.step.jobstep.variable +package com.navercorp.spring.batch.plus.sample.job.transition.stopandrestart.step.init import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.Job -import org.springframework.batch.repeat.RepeatStatus +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.step.Step +import org.springframework.batch.infrastructure.repeat.RepeatStatus import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.transaction.PlatformTransactionManager @@ -30,22 +31,28 @@ open class TestJobConfig( private val batch: BatchDsl, private val transactionManager: PlatformTransactionManager, ) { - @Bean - open fun testJob(): Job = batch { - job("testJob") { - step("testStep") { - job(anotherJob()) + open fun testJob(): Job = + batch { + job("testJob") { + step(testStep()) { + on("COMPLETED") { + stopAndRestartToStep("restartStep") { + tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + } + } + on("*") { + stop() + } + } } } - } @Bean - open fun anotherJob() = batch { - job("anotherJob") { - step("anotherJobStep") { + open fun testStep(): Step = + batch { + step("testStep") { tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) } } - } } diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/stopandrestart/step/variable/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/stopandrestart/step/variable/SampleApplicationTest.kt new file mode 100644 index 00000000..9f400fad --- /dev/null +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/stopandrestart/step/variable/SampleApplicationTest.kt @@ -0,0 +1,51 @@ +/* + * Spring Batch Plus + * + * Copyright 2022-present NAVER Corp. + * + * 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 + * + * http://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 com.navercorp.spring.batch.plus.sample.job.transition.stopandrestart.step.variable + +import org.junit.jupiter.api.Test +import org.springframework.batch.core.BatchStatus +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator +import org.springframework.beans.factory.getBean +import org.springframework.boot.autoconfigure.SpringBootApplication +import org.springframework.boot.runApplication + +@SpringBootApplication +open class SampleApplicationTest { + @Test + fun run() { + val applicationContext = runApplication() + val jobOperator = applicationContext.getBean() + val job = applicationContext.getBean() + + val jobParameters = + JobParametersBuilder() + .toJobParameters() + + val firstJobExecution = jobOperator.start(job, jobParameters) + val secondJobExecution = jobOperator.start(job, jobParameters) + + assert(BatchStatus.STOPPED == firstJobExecution.status) + println("firstJobExecution: $firstJobExecution") + + assert(BatchStatus.COMPLETED == secondJobExecution.status) + println("secondJobExecution: $secondJobExecution") + } +} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/stopandrestart/step/variable/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/stopandrestart/step/variable/TestJobConfig.kt new file mode 100644 index 00000000..94c999e8 --- /dev/null +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/stopandrestart/step/variable/TestJobConfig.kt @@ -0,0 +1,64 @@ +/* + * Spring Batch Plus + * + * Copyright 2022-present NAVER Corp. + * + * 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 + * + * http://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 com.navercorp.spring.batch.plus.sample.job.transition.stopandrestart.step.variable + +import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.step.Step +import org.springframework.batch.infrastructure.repeat.RepeatStatus +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import org.springframework.transaction.PlatformTransactionManager + +@Configuration +open class TestJobConfig( + private val batch: BatchDsl, + private val transactionManager: PlatformTransactionManager, +) { + @Bean + open fun testJob(): Job = + batch { + job("testJob") { + step(testStep()) { + on("COMPLETED") { + stopAndRestartToStep(restartStep()) + } + on("*") { + stop() + } + } + } + } + + @Bean + open fun testStep(): Step = + batch { + step("testStep") { + tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + } + } + + @Bean + open fun restartStep(): Step = + batch { + step("restartStep") { + tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + } + } +} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/terminal/end/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/terminal/end/SampleApplicationTest.kt new file mode 100644 index 00000000..7a326733 --- /dev/null +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/terminal/end/SampleApplicationTest.kt @@ -0,0 +1,46 @@ +/* + * Spring Batch Plus + * + * Copyright 2022-present NAVER Corp. + * + * 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 + * + * http://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 com.navercorp.spring.batch.plus.sample.job.transition.terminal.end + +import org.junit.jupiter.api.Test +import org.springframework.batch.core.BatchStatus +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator +import org.springframework.beans.factory.getBean +import org.springframework.boot.autoconfigure.SpringBootApplication +import org.springframework.boot.runApplication + +@SpringBootApplication +open class SampleApplicationTest { + @Test + fun run() { + val applicationContext = runApplication() + val jobOperator = applicationContext.getBean() + val job = applicationContext.getBean() + + val jobParameters = + JobParametersBuilder() + .toJobParameters() + val jobExecution = jobOperator.start(job, jobParameters) + + assert(BatchStatus.COMPLETED == jobExecution.status) + println(jobExecution) + } +} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/flow/transition/bean/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/terminal/end/TestJobConfig.kt similarity index 64% rename from spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/flow/transition/bean/TestJobConfig.kt rename to spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/terminal/end/TestJobConfig.kt index f56c2247..daa386ee 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/flow/transition/bean/TestJobConfig.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/terminal/end/TestJobConfig.kt @@ -16,12 +16,11 @@ * limitations under the License. */ -package com.navercorp.spring.batch.plus.sample.job.flow.flow.transition.bean +package com.navercorp.spring.batch.plus.sample.job.transition.terminal.end import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.Job -import org.springframework.batch.core.job.flow.Flow -import org.springframework.batch.repeat.RepeatStatus +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.step.Step import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.transaction.PlatformTransactionManager @@ -31,29 +30,27 @@ open class TestJobConfig( private val batch: BatchDsl, private val transactionManager: PlatformTransactionManager, ) { - @Bean - open fun testJob(): Job = batch { - job("testJob") { - flowBean("testFlow") { - on("COMPLETED") { - end() - } - on("FAILED") { - step("transitionStep") { - tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + open fun testJob(): Job = + batch { + job("testJob") { + step(testStep()) { + on("COMPLETED") { + stop() + } + on("FAILED") { + end("SKIPPED") + } + on("*") { + stop() } - } - on("*") { - stop() } } } - } @Bean - open fun testFlow(): Flow = batch { - flow("testFlow") { + open fun testStep(): Step = + batch { step("testStep") { tasklet( { _, _ -> throw IllegalStateException("testStep failed") }, @@ -61,5 +58,4 @@ open class TestJobConfig( ) } } - } } diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/finish/fail/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/terminal/fail/SampleApplicationTest.kt similarity index 71% rename from spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/finish/fail/SampleApplicationTest.kt rename to spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/terminal/fail/SampleApplicationTest.kt index 7d247d0b..6704aec5 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/finish/fail/SampleApplicationTest.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/terminal/fail/SampleApplicationTest.kt @@ -16,13 +16,13 @@ * limitations under the License. */ -package com.navercorp.spring.batch.plus.sample.job.flow.transition.finish.fail +package com.navercorp.spring.batch.plus.sample.job.transition.terminal.fail import org.junit.jupiter.api.Test import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator import org.springframework.beans.factory.getBean import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.runApplication @@ -32,12 +32,13 @@ open class SampleApplicationTest { @Test fun run() { val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() + val jobOperator = applicationContext.getBean() val job = applicationContext.getBean() - val jobParameters = JobParametersBuilder() - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) + val jobParameters = + JobParametersBuilder() + .toJobParameters() + val jobExecution = jobOperator.start(job, jobParameters) assert(BatchStatus.FAILED == jobExecution.status) println(jobExecution) diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/flowstep/variable/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/terminal/fail/TestJobConfig.kt similarity index 67% rename from spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/flowstep/variable/TestJobConfig.kt rename to spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/terminal/fail/TestJobConfig.kt index 3392d091..38588743 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/flowstep/variable/TestJobConfig.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/terminal/fail/TestJobConfig.kt @@ -16,12 +16,12 @@ * limitations under the License. */ -package com.navercorp.spring.batch.plus.sample.step.flowstep.variable +package com.navercorp.spring.batch.plus.sample.job.transition.terminal.fail import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.Job -import org.springframework.batch.core.job.flow.Flow -import org.springframework.batch.repeat.RepeatStatus +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.step.Step +import org.springframework.batch.infrastructure.repeat.RepeatStatus import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.transaction.PlatformTransactionManager @@ -31,22 +31,26 @@ open class TestJobConfig( private val batch: BatchDsl, private val transactionManager: PlatformTransactionManager, ) { - @Bean - open fun testJob(): Job = batch { - job("testJob") { - step("testStep") { - flow(anotherFlow()) + open fun testJob(): Job = + batch { + job("testJob") { + step(testStep()) { + on("COMPLETED") { + fail() + } + on("*") { + stop() + } + } } } - } @Bean - open fun anotherFlow(): Flow = batch { - flow("anotherFlow") { - step("anotherFlowStep") { + open fun testStep(): Step = + batch { + step("testStep") { tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) } } - } } diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/finish/stop/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/terminal/stop/SampleApplicationTest.kt similarity index 71% rename from spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/finish/stop/SampleApplicationTest.kt rename to spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/terminal/stop/SampleApplicationTest.kt index c742f0d4..d9d9e301 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/finish/stop/SampleApplicationTest.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/terminal/stop/SampleApplicationTest.kt @@ -16,13 +16,13 @@ * limitations under the License. */ -package com.navercorp.spring.batch.plus.sample.job.flow.transition.finish.stop +package com.navercorp.spring.batch.plus.sample.job.transition.terminal.stop import org.junit.jupiter.api.Test import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator import org.springframework.beans.factory.getBean import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.runApplication @@ -32,12 +32,13 @@ open class SampleApplicationTest { @Test fun run() { val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() + val jobOperator = applicationContext.getBean() val job = applicationContext.getBean() - val jobParameters = JobParametersBuilder() - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) + val jobParameters = + JobParametersBuilder() + .toJobParameters() + val jobExecution = jobOperator.start(job, jobParameters) assert(BatchStatus.STOPPED == jobExecution.status) println(jobExecution) diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/flowstep/bean/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/terminal/stop/TestJobConfig.kt similarity index 67% rename from spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/flowstep/bean/TestJobConfig.kt rename to spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/terminal/stop/TestJobConfig.kt index d1c7145c..f2c604bf 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/flowstep/bean/TestJobConfig.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/transition/terminal/stop/TestJobConfig.kt @@ -16,12 +16,12 @@ * limitations under the License. */ -package com.navercorp.spring.batch.plus.sample.step.flowstep.bean +package com.navercorp.spring.batch.plus.sample.job.transition.terminal.stop import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.Job -import org.springframework.batch.core.job.flow.Flow -import org.springframework.batch.repeat.RepeatStatus +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.step.Step +import org.springframework.batch.infrastructure.repeat.RepeatStatus import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.transaction.PlatformTransactionManager @@ -31,22 +31,26 @@ open class TestJobConfig( private val batch: BatchDsl, private val transactionManager: PlatformTransactionManager, ) { - @Bean - open fun testJob(): Job = batch { - job("testJob") { - step("testStep") { - flowBean("anotherFlow") + open fun testJob(): Job = + batch { + job("testJob") { + step(testStep()) { + on("COMPLETED") { + stop() + } + on("*") { + end() + } + } } } - } @Bean - open fun anotherFlow(): Flow = batch { - flow("anotherFlow") { - step("anotherFlowStep") { + open fun testStep(): Step = + batch { + step("testStep") { tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) } } - } } diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/README.md b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/README.md new file mode 100644 index 00000000..92300e9d --- /dev/null +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/README.md @@ -0,0 +1,6 @@ +# Chunk-Oriented Step Config Samples + +## Invariants + +- Every non-fault-tolerant chunk-oriented step configuration capability exposed + by the Kotlin DSL should have a runnable sample in this package. diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/annotationlistener/mixed/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/annotationlistener/mixed/TestJobConfig.kt deleted file mode 100644 index 562fe8c2..00000000 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/annotationlistener/mixed/TestJobConfig.kt +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Spring Batch Plus - * - * Copyright 2022-present NAVER Corp. - * - * 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 - * - * http://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 com.navercorp.spring.batch.plus.sample.step.chunkorientedstep.config.annotationlistener.mixed - -import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.Job -import org.springframework.batch.core.annotation.AfterProcess -import org.springframework.batch.core.annotation.AfterRead -import org.springframework.batch.core.annotation.BeforeWrite -import org.springframework.batch.item.Chunk -import org.springframework.batch.item.ItemProcessor -import org.springframework.batch.item.ItemReader -import org.springframework.batch.item.ItemWriter -import org.springframework.context.annotation.Bean -import org.springframework.context.annotation.Configuration -import org.springframework.transaction.PlatformTransactionManager - -@Configuration -open class TestJobConfig( - private val batch: BatchDsl, - private val transactionManager: PlatformTransactionManager, -) { - - class TestListener { - @AfterRead - fun afterRead(item: Any) { - println("afterRead (item: $item)") - } - - @AfterProcess - fun afterProcess(item: Any, result: Any?) { - println("afterProcess: $item, result: $result") - } - - @BeforeWrite - fun beforeWrite(chunk: Chunk) { - println("beforeWrite: ${chunk.items}") - } - } - - @Bean - open fun testJob(): Job = batch { - job("testJob") { - step("testStep") { - chunk(3, transactionManager) { - reader(testItemReader()) - processor(testItemProcessor()) - writer(testItemWriter()) - listener(TestListener()) - } - } - } - } - - @Bean - open fun testItemReader(): ItemReader { - return object : ItemReader { - private var count = 0 - - override fun read(): Int? { - return if (count < 11) { - count++ - } else { - null - } - } - } - } - - @Bean - open fun testItemProcessor(): ItemProcessor { - return ItemProcessor { item -> - item.toString() - } - } - - @Bean - open fun testItemWriter(): ItemWriter { - return ItemWriter { items -> - println("[${Thread.currentThread().name}] write $items") - } - } -} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/annotationlistener/processorlistener/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/annotationlistener/processorlistener/SampleApplicationTest.kt deleted file mode 100644 index 38795109..00000000 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/annotationlistener/processorlistener/SampleApplicationTest.kt +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Spring Batch Plus - * - * Copyright 2022-present NAVER Corp. - * - * 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 - * - * http://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 com.navercorp.spring.batch.plus.sample.step.chunkorientedstep.config.annotationlistener.processorlistener - -import org.junit.jupiter.api.Test -import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher -import org.springframework.beans.factory.getBean -import org.springframework.boot.autoconfigure.SpringBootApplication -import org.springframework.boot.runApplication - -@SpringBootApplication -open class SampleApplicationTest { - @Test - fun run() { - val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() - val job = applicationContext.getBean() - - val jobParameters = JobParametersBuilder() - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) - - assert(BatchStatus.COMPLETED == jobExecution.status) - println(jobExecution) - } -} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/annotationlistener/readerlistener/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/annotationlistener/readerlistener/SampleApplicationTest.kt deleted file mode 100644 index 20eeba7f..00000000 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/annotationlistener/readerlistener/SampleApplicationTest.kt +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Spring Batch Plus - * - * Copyright 2022-present NAVER Corp. - * - * 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 - * - * http://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 com.navercorp.spring.batch.plus.sample.step.chunkorientedstep.config.annotationlistener.readerlistener - -import org.junit.jupiter.api.Test -import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher -import org.springframework.beans.factory.getBean -import org.springframework.boot.autoconfigure.SpringBootApplication -import org.springframework.boot.runApplication - -@SpringBootApplication -open class SampleApplicationTest { - @Test - fun run() { - val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() - val job = applicationContext.getBean() - - val jobParameters = JobParametersBuilder() - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) - - assert(BatchStatus.COMPLETED == jobExecution.status) - println(jobExecution) - } -} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/annotationlistener/writerlistener/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/annotationlistener/writerlistener/SampleApplicationTest.kt deleted file mode 100644 index 9c7d1c4e..00000000 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/annotationlistener/writerlistener/SampleApplicationTest.kt +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Spring Batch Plus - * - * Copyright 2022-present NAVER Corp. - * - * 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 - * - * http://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 com.navercorp.spring.batch.plus.sample.step.chunkorientedstep.config.annotationlistener.writerlistener - -import org.junit.jupiter.api.Test -import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher -import org.springframework.beans.factory.getBean -import org.springframework.boot.autoconfigure.SpringBootApplication -import org.springframework.boot.runApplication - -@SpringBootApplication -open class SampleApplicationTest { - @Test - fun run() { - val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() - val job = applicationContext.getBean() - - val jobParameters = JobParametersBuilder() - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) - - assert(BatchStatus.COMPLETED == jobExecution.status) - println(jobExecution) - } -} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/chunklistener/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/chunklistener/SampleApplicationTest.kt deleted file mode 100644 index 853a627f..00000000 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/chunklistener/SampleApplicationTest.kt +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Spring Batch Plus - * - * Copyright 2022-present NAVER Corp. - * - * 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 - * - * http://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 com.navercorp.spring.batch.plus.sample.step.chunkorientedstep.config.chunklistener - -import org.junit.jupiter.api.Test -import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher -import org.springframework.beans.factory.getBean -import org.springframework.boot.autoconfigure.SpringBootApplication -import org.springframework.boot.runApplication - -@SpringBootApplication -open class SampleApplicationTest { - @Test - fun run() { - val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() - val job = applicationContext.getBean() - - val jobParameters = JobParametersBuilder() - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) - - assert(BatchStatus.COMPLETED == jobExecution.status) - println(jobExecution) - } -} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/chunklistener/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/chunklistener/TestJobConfig.kt deleted file mode 100644 index f96878ce..00000000 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/chunklistener/TestJobConfig.kt +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Spring Batch Plus - * - * Copyright 2022-present NAVER Corp. - * - * 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 - * - * http://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 com.navercorp.spring.batch.plus.sample.step.chunkorientedstep.config.chunklistener - -import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.ChunkListener -import org.springframework.batch.core.Job -import org.springframework.batch.core.scope.context.ChunkContext -import org.springframework.batch.item.ItemProcessor -import org.springframework.batch.item.ItemReader -import org.springframework.batch.item.ItemWriter -import org.springframework.context.annotation.Bean -import org.springframework.context.annotation.Configuration -import org.springframework.transaction.PlatformTransactionManager - -@Configuration -open class TestJobConfig( - private val batch: BatchDsl, - private val transactionManager: PlatformTransactionManager, -) { - - @Bean - open fun testJob(): Job = batch { - job("testJob") { - step("testStep") { - chunk(3, transactionManager) { - reader(testItemReader()) - processor(testItemProcessor()) - writer(testItemWriter()) - listener( - object : ChunkListener { - override fun beforeChunk(context: ChunkContext) { - println("beforeChunk: $context") - } - - override fun afterChunk(context: ChunkContext) { - println("afterChunk: $context") - } - - override fun afterChunkError(context: ChunkContext) { - } - }, - ) - } - } - } - } - - @Bean - open fun testItemReader(): ItemReader { - return object : ItemReader { - private var count = 0 - - override fun read(): Int? { - return if (count < 11) { - count++ - } else { - null - } - } - } - } - - @Bean - open fun testItemProcessor(): ItemProcessor { - return ItemProcessor { item -> - item.toString() - } - } - - @Bean - open fun testItemWriter(): ItemWriter { - return ItemWriter { items -> - println("[${Thread.currentThread().name}] write $items") - } - } -} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/exceptionhandler/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/exceptionhandler/SampleApplicationTest.kt deleted file mode 100644 index 071bee7d..00000000 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/exceptionhandler/SampleApplicationTest.kt +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Spring Batch Plus - * - * Copyright 2022-present NAVER Corp. - * - * 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 - * - * http://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 com.navercorp.spring.batch.plus.sample.step.chunkorientedstep.config.exceptionhandler - -import org.junit.jupiter.api.Test -import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher -import org.springframework.beans.factory.getBean -import org.springframework.boot.autoconfigure.SpringBootApplication -import org.springframework.boot.runApplication - -@SpringBootApplication -open class SampleApplicationTest { - @Test - fun run() { - val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() - val job = applicationContext.getBean() - - val jobParameters = JobParametersBuilder() - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) - - assert(BatchStatus.FAILED == jobExecution.status) - println(jobExecution) - } -} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/exceptionhandler/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/exceptionhandler/TestJobConfig.kt deleted file mode 100644 index 2473c6be..00000000 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/exceptionhandler/TestJobConfig.kt +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Spring Batch Plus - * - * Copyright 2022-present NAVER Corp. - * - * 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 - * - * http://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 com.navercorp.spring.batch.plus.sample.step.chunkorientedstep.config.exceptionhandler - -import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.Job -import org.springframework.batch.item.ItemReader -import org.springframework.batch.item.ItemWriter -import org.springframework.context.annotation.Bean -import org.springframework.context.annotation.Configuration -import org.springframework.transaction.PlatformTransactionManager - -@Configuration -open class TestJobConfig( - private val batch: BatchDsl, - private val transactionManager: PlatformTransactionManager, -) { - - @Bean - open fun testJob(): Job = batch { - job("testJob") { - step("testStep") { - chunk(3, transactionManager) { - reader(testItemReader()) - writer(testItemWriter()) - exceptionHandler { _, throwable -> - println("handle exception ${throwable.message}") - throw throwable - } - // same as - // exceptionHandler( - // object : ExceptionHandler { - // override fun handleException(context: RepeatContext, throwable: Throwable) { - // println("handle exception ${throwable.message}") - // throw throwable - // } - // } - // ) - } - } - } - } - - @Bean - open fun testItemReader(): ItemReader { - return ItemReader { - throw IllegalStateException("Error in read") - } - } - - @Bean - open fun testItemWriter(): ItemWriter { - return ItemWriter { items -> - println("write $items") - } - } -} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/executor/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/executor/SampleApplicationTest.kt deleted file mode 100644 index 81e5854f..00000000 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/executor/SampleApplicationTest.kt +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Spring Batch Plus - * - * Copyright 2022-present NAVER Corp. - * - * 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 - * - * http://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 com.navercorp.spring.batch.plus.sample.step.chunkorientedstep.config.executor - -import org.junit.jupiter.api.Test -import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher -import org.springframework.beans.factory.getBean -import org.springframework.boot.autoconfigure.SpringBootApplication -import org.springframework.boot.runApplication - -@SpringBootApplication -open class SampleApplicationTest { - @Test - fun run() { - val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() - val job = applicationContext.getBean() - - val jobParameters = JobParametersBuilder() - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) - - assert(BatchStatus.COMPLETED == jobExecution.status) - println(jobExecution) - } -} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/annotationlistener/chunklistener/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/interruptionpolicy/SampleApplicationTest.kt similarity index 74% rename from spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/annotationlistener/chunklistener/SampleApplicationTest.kt rename to spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/interruptionpolicy/SampleApplicationTest.kt index 0d832820..c6c7da1f 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/annotationlistener/chunklistener/SampleApplicationTest.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/interruptionpolicy/SampleApplicationTest.kt @@ -16,13 +16,13 @@ * limitations under the License. */ -package com.navercorp.spring.batch.plus.sample.step.chunkorientedstep.config.annotationlistener.chunklistener +package com.navercorp.spring.batch.plus.sample.step.chunkorientedstep.config.interruptionpolicy import org.junit.jupiter.api.Test import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator import org.springframework.beans.factory.getBean import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.runApplication @@ -32,12 +32,13 @@ open class SampleApplicationTest { @Test fun run() { val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() + val jobOperator = applicationContext.getBean() val job = applicationContext.getBean() - val jobParameters = JobParametersBuilder() - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) + val jobParameters = + JobParametersBuilder() + .toJobParameters() + val jobExecution = jobOperator.start(job, jobParameters) assert(BatchStatus.COMPLETED == jobExecution.status) println(jobExecution) diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/interruptionpolicy/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/interruptionpolicy/TestJobConfig.kt new file mode 100644 index 00000000..4c6c2b40 --- /dev/null +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/interruptionpolicy/TestJobConfig.kt @@ -0,0 +1,65 @@ +/* + * Spring Batch Plus + * + * Copyright 2022-present NAVER Corp. + * + * 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 + * + * http://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 com.navercorp.spring.batch.plus.sample.step.chunkorientedstep.config.interruptionpolicy + +import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.step.ThreadStepInterruptionPolicy +import org.springframework.batch.infrastructure.item.ItemReader +import org.springframework.batch.infrastructure.item.ItemWriter +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration + +@Configuration +open class TestJobConfig( + private val batch: BatchDsl, +) { + @Bean + open fun testJob(): Job = + batch { + job("testJob") { + step("testStep") { + chunk(3) { + reader(testItemReader()) + writer(testItemWriter()) + interruptionPolicy(ThreadStepInterruptionPolicy()) + } + } + } + } + + @Bean + open fun testItemReader(): ItemReader = + object : ItemReader { + private var count = 0 + + override fun read(): Int? = + if (count < 20) { + count++ + } else { + null + } + } + + @Bean + open fun testItemWriter(): ItemWriter = + ItemWriter { items -> + println("write $items") + } +} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/listener/annotation/chunklistener/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/listener/annotation/chunklistener/SampleApplicationTest.kt new file mode 100644 index 00000000..8db9f06d --- /dev/null +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/listener/annotation/chunklistener/SampleApplicationTest.kt @@ -0,0 +1,46 @@ +/* + * Spring Batch Plus + * + * Copyright 2022-present NAVER Corp. + * + * 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 + * + * http://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 com.navercorp.spring.batch.plus.sample.step.chunkorientedstep.config.listener.annotation.chunklistener + +import org.junit.jupiter.api.Test +import org.springframework.batch.core.BatchStatus +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator +import org.springframework.beans.factory.getBean +import org.springframework.boot.autoconfigure.SpringBootApplication +import org.springframework.boot.runApplication + +@SpringBootApplication +open class SampleApplicationTest { + @Test + fun run() { + val applicationContext = runApplication() + val jobOperator = applicationContext.getBean() + val job = applicationContext.getBean() + + val jobParameters = + JobParametersBuilder() + .toJobParameters() + val jobExecution = jobOperator.start(job, jobParameters) + + assert(BatchStatus.COMPLETED == jobExecution.status) + println(jobExecution) + } +} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/annotationlistener/chunklistener/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/listener/annotation/chunklistener/TestJobConfig.kt similarity index 54% rename from spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/annotationlistener/chunklistener/TestJobConfig.kt rename to spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/listener/annotation/chunklistener/TestJobConfig.kt index 3fffe044..fb276281 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/annotationlistener/chunklistener/TestJobConfig.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/listener/annotation/chunklistener/TestJobConfig.kt @@ -16,36 +16,33 @@ * limitations under the License. */ -package com.navercorp.spring.batch.plus.sample.step.chunkorientedstep.config.annotationlistener.chunklistener +package com.navercorp.spring.batch.plus.sample.step.chunkorientedstep.config.listener.annotation.chunklistener import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.Job import org.springframework.batch.core.annotation.AfterChunk import org.springframework.batch.core.annotation.AfterChunkError import org.springframework.batch.core.annotation.BeforeChunk -import org.springframework.batch.core.scope.context.ChunkContext -import org.springframework.batch.item.ItemProcessor -import org.springframework.batch.item.ItemReader -import org.springframework.batch.item.ItemWriter +import org.springframework.batch.core.job.Job +import org.springframework.batch.infrastructure.item.Chunk +import org.springframework.batch.infrastructure.item.ItemProcessor +import org.springframework.batch.infrastructure.item.ItemReader +import org.springframework.batch.infrastructure.item.ItemWriter import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration -import org.springframework.transaction.PlatformTransactionManager @Configuration open class TestJobConfig( private val batch: BatchDsl, - private val transactionManager: PlatformTransactionManager, ) { - class TestListener { @BeforeChunk - fun beforeChunk(context: ChunkContext) { - println("beforeChunk: $context") + fun beforeChunk(chunk: Chunk) { + println("beforeChunk: $chunk") } @AfterChunk - fun afterChunk(context: ChunkContext) { - println("afterChunk: $context") + fun afterChunk(chunk: Chunk) { + println("afterChunk: $chunk") } @AfterChunkError @@ -54,45 +51,42 @@ open class TestJobConfig( } @Bean - open fun testJob(): Job = batch { - job("testJob") { - step("testStep") { - chunk(3, transactionManager) { - reader(testItemReader()) - processor(testItemProcessor()) - writer(testItemWriter()) - listener(TestListener()) + open fun testJob(): Job = + batch { + job("testJob") { + step("testStep") { + chunk(3) { + reader(testItemReader()) + processor(testItemProcessor()) + writer(testItemWriter()) + listener(TestListener()) + } } } } - } @Bean - open fun testItemReader(): ItemReader { - return object : ItemReader { + open fun testItemReader(): ItemReader = + object : ItemReader { private var count = 0 - override fun read(): Int? { - return if (count < 11) { + override fun read(): Int? = + if (count < 11) { count++ } else { null } - } } - } @Bean - open fun testItemProcessor(): ItemProcessor { - return ItemProcessor { item -> + open fun testItemProcessor(): ItemProcessor = + ItemProcessor { item -> item.toString() } - } @Bean - open fun testItemWriter(): ItemWriter { - return ItemWriter { items -> + open fun testItemWriter(): ItemWriter = + ItemWriter { items -> println("write $items") } - } } diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/listener/annotation/processorlistener/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/listener/annotation/processorlistener/SampleApplicationTest.kt new file mode 100644 index 00000000..a917d1dd --- /dev/null +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/listener/annotation/processorlistener/SampleApplicationTest.kt @@ -0,0 +1,46 @@ +/* + * Spring Batch Plus + * + * Copyright 2022-present NAVER Corp. + * + * 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 + * + * http://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 com.navercorp.spring.batch.plus.sample.step.chunkorientedstep.config.listener.annotation.processorlistener + +import org.junit.jupiter.api.Test +import org.springframework.batch.core.BatchStatus +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator +import org.springframework.beans.factory.getBean +import org.springframework.boot.autoconfigure.SpringBootApplication +import org.springframework.boot.runApplication + +@SpringBootApplication +open class SampleApplicationTest { + @Test + fun run() { + val applicationContext = runApplication() + val jobOperator = applicationContext.getBean() + val job = applicationContext.getBean() + + val jobParameters = + JobParametersBuilder() + .toJobParameters() + val jobExecution = jobOperator.start(job, jobParameters) + + assert(BatchStatus.COMPLETED == jobExecution.status) + println(jobExecution) + } +} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/annotationlistener/processorlistener/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/listener/annotation/processorlistener/TestJobConfig.kt similarity index 59% rename from spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/annotationlistener/processorlistener/TestJobConfig.kt rename to spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/listener/annotation/processorlistener/TestJobConfig.kt index 1b56569a..b2461e5f 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/annotationlistener/processorlistener/TestJobConfig.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/listener/annotation/processorlistener/TestJobConfig.kt @@ -16,26 +16,23 @@ * limitations under the License. */ -package com.navercorp.spring.batch.plus.sample.step.chunkorientedstep.config.annotationlistener.processorlistener +package com.navercorp.spring.batch.plus.sample.step.chunkorientedstep.config.listener.annotation.processorlistener import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.Job import org.springframework.batch.core.annotation.AfterProcess import org.springframework.batch.core.annotation.BeforeProcess import org.springframework.batch.core.annotation.OnProcessError -import org.springframework.batch.item.ItemProcessor -import org.springframework.batch.item.ItemReader -import org.springframework.batch.item.ItemWriter +import org.springframework.batch.core.job.Job +import org.springframework.batch.infrastructure.item.ItemProcessor +import org.springframework.batch.infrastructure.item.ItemReader +import org.springframework.batch.infrastructure.item.ItemWriter import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration -import org.springframework.transaction.PlatformTransactionManager @Configuration open class TestJobConfig( private val batch: BatchDsl, - private val transactionManager: PlatformTransactionManager, ) { - class TestListener { @BeforeProcess fun beforeProcess(item: Any) { @@ -43,56 +40,59 @@ open class TestJobConfig( } @AfterProcess - fun afterProcess(item: Any, result: Any?) { + fun afterProcess( + item: Any, + result: Any?, + ) { println("afterProcess: $item, result: $result") } @OnProcessError - fun onProcessError(item: Any, e: Exception) { + fun onProcessError( + item: Any, + e: Exception, + ) { println("onProcessError: $item, exception: $e") } } @Bean - open fun testJob(): Job = batch { - job("testJob") { - step("testStep") { - chunk(3, transactionManager) { - reader(testItemReader()) - processor(testItemProcessor()) - writer(testItemWriter()) - listener(TestListener()) + open fun testJob(): Job = + batch { + job("testJob") { + step("testStep") { + chunk(3) { + reader(testItemReader()) + processor(testItemProcessor()) + writer(testItemWriter()) + listener(TestListener()) + } } } } - } @Bean - open fun testItemReader(): ItemReader { - return object : ItemReader { + open fun testItemReader(): ItemReader = + object : ItemReader { private var count = 0 - override fun read(): Int? { - return if (count < 11) { + override fun read(): Int? = + if (count < 11) { count++ } else { null } - } } - } @Bean - open fun testItemProcessor(): ItemProcessor { - return ItemProcessor { item -> + open fun testItemProcessor(): ItemProcessor = + ItemProcessor { item -> item.toString() } - } @Bean - open fun testItemWriter(): ItemWriter { - return ItemWriter { items -> + open fun testItemWriter(): ItemWriter = + ItemWriter { items -> println("[${Thread.currentThread().name}] write $items") } - } } diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/listener/annotation/readerlistener/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/listener/annotation/readerlistener/SampleApplicationTest.kt new file mode 100644 index 00000000..6109dfb5 --- /dev/null +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/listener/annotation/readerlistener/SampleApplicationTest.kt @@ -0,0 +1,46 @@ +/* + * Spring Batch Plus + * + * Copyright 2022-present NAVER Corp. + * + * 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 + * + * http://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 com.navercorp.spring.batch.plus.sample.step.chunkorientedstep.config.listener.annotation.readerlistener + +import org.junit.jupiter.api.Test +import org.springframework.batch.core.BatchStatus +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator +import org.springframework.beans.factory.getBean +import org.springframework.boot.autoconfigure.SpringBootApplication +import org.springframework.boot.runApplication + +@SpringBootApplication +open class SampleApplicationTest { + @Test + fun run() { + val applicationContext = runApplication() + val jobOperator = applicationContext.getBean() + val job = applicationContext.getBean() + + val jobParameters = + JobParametersBuilder() + .toJobParameters() + val jobExecution = jobOperator.start(job, jobParameters) + + assert(BatchStatus.COMPLETED == jobExecution.status) + println(jobExecution) + } +} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/annotationlistener/readerlistener/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/listener/annotation/readerlistener/TestJobConfig.kt similarity index 61% rename from spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/annotationlistener/readerlistener/TestJobConfig.kt rename to spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/listener/annotation/readerlistener/TestJobConfig.kt index 09412cf7..9af0854e 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/annotationlistener/readerlistener/TestJobConfig.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/listener/annotation/readerlistener/TestJobConfig.kt @@ -16,26 +16,23 @@ * limitations under the License. */ -package com.navercorp.spring.batch.plus.sample.step.chunkorientedstep.config.annotationlistener.readerlistener +package com.navercorp.spring.batch.plus.sample.step.chunkorientedstep.config.listener.annotation.readerlistener import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.Job import org.springframework.batch.core.annotation.AfterRead import org.springframework.batch.core.annotation.BeforeRead import org.springframework.batch.core.annotation.OnReadError -import org.springframework.batch.item.ItemProcessor -import org.springframework.batch.item.ItemReader -import org.springframework.batch.item.ItemWriter +import org.springframework.batch.core.job.Job +import org.springframework.batch.infrastructure.item.ItemProcessor +import org.springframework.batch.infrastructure.item.ItemReader +import org.springframework.batch.infrastructure.item.ItemWriter import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration -import org.springframework.transaction.PlatformTransactionManager @Configuration open class TestJobConfig( private val batch: BatchDsl, - private val transactionManager: PlatformTransactionManager, ) { - class TestListener { @BeforeRead fun beforeRead() { @@ -54,45 +51,42 @@ open class TestJobConfig( } @Bean - open fun testJob(): Job = batch { - job("testJob") { - step("testStep") { - chunk(3, transactionManager) { - reader(testItemReader()) - processor(testItemProcessor()) - writer(testItemWriter()) - listener(TestListener()) + open fun testJob(): Job = + batch { + job("testJob") { + step("testStep") { + chunk(3) { + reader(testItemReader()) + processor(testItemProcessor()) + writer(testItemWriter()) + listener(TestListener()) + } } } } - } @Bean - open fun testItemReader(): ItemReader { - return object : ItemReader { + open fun testItemReader(): ItemReader = + object : ItemReader { private var count = 0 - override fun read(): Int? { - return if (count < 11) { + override fun read(): Int? = + if (count < 11) { count++ } else { null } - } } - } @Bean - open fun testItemProcessor(): ItemProcessor { - return ItemProcessor { item -> + open fun testItemProcessor(): ItemProcessor = + ItemProcessor { item -> item.toString() } - } @Bean - open fun testItemWriter(): ItemWriter { - return ItemWriter { items -> + open fun testItemWriter(): ItemWriter = + ItemWriter { items -> println("write $items") } - } } diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/listener/annotation/stepexecutionlistener/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/listener/annotation/stepexecutionlistener/SampleApplicationTest.kt new file mode 100644 index 00000000..5aae517c --- /dev/null +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/listener/annotation/stepexecutionlistener/SampleApplicationTest.kt @@ -0,0 +1,46 @@ +/* + * Spring Batch Plus + * + * Copyright 2022-present NAVER Corp. + * + * 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 + * + * http://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 com.navercorp.spring.batch.plus.sample.step.chunkorientedstep.config.listener.annotation.stepexecutionlistener + +import org.junit.jupiter.api.Test +import org.springframework.batch.core.BatchStatus +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator +import org.springframework.beans.factory.getBean +import org.springframework.boot.autoconfigure.SpringBootApplication +import org.springframework.boot.runApplication + +@SpringBootApplication +open class SampleApplicationTest { + @Test + fun run() { + val applicationContext = runApplication() + val jobOperator = applicationContext.getBean() + val job = applicationContext.getBean() + + val jobParameters = + JobParametersBuilder() + .toJobParameters() + val jobExecution = jobOperator.start(job, jobParameters) + + assert(BatchStatus.COMPLETED == jobExecution.status) + println(jobExecution) + } +} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/listener/annotation/stepexecutionlistener/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/listener/annotation/stepexecutionlistener/TestJobConfig.kt new file mode 100644 index 00000000..f92ed283 --- /dev/null +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/listener/annotation/stepexecutionlistener/TestJobConfig.kt @@ -0,0 +1,89 @@ +/* + * Spring Batch Plus + * + * Copyright 2022-present NAVER Corp. + * + * 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 + * + * http://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 com.navercorp.spring.batch.plus.sample.step.chunkorientedstep.config.listener.annotation.stepexecutionlistener + +import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl +import org.springframework.batch.core.ExitStatus +import org.springframework.batch.core.annotation.AfterStep +import org.springframework.batch.core.annotation.BeforeStep +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.step.StepExecution +import org.springframework.batch.infrastructure.item.ItemProcessor +import org.springframework.batch.infrastructure.item.ItemReader +import org.springframework.batch.infrastructure.item.ItemWriter +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration + +@Configuration +open class TestJobConfig( + private val batch: BatchDsl, +) { + class TestListener { + @BeforeStep + fun beforeStep(stepExecution: StepExecution) { + println("beforeStep: $stepExecution") + } + + @AfterStep + fun afterStep(stepExecution: StepExecution): ExitStatus? { + println("afterStep: $stepExecution") + return null + } + } + + @Bean + open fun testJob(): Job = + batch { + job("testJob") { + step("testStep") { + chunk(3) { + reader(testItemReader()) + processor(testItemProcessor()) + writer(testItemWriter()) + listener(TestListener()) + } + } + } + } + + @Bean + open fun testItemReader(): ItemReader = + object : ItemReader { + private var count = 0 + + override fun read(): Int? = + if (count < 11) { + count++ + } else { + null + } + } + + @Bean + open fun testItemProcessor(): ItemProcessor = + ItemProcessor { item -> + item.toString() + } + + @Bean + open fun testItemWriter(): ItemWriter = + ItemWriter { items -> + println("write $items") + } +} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/listener/annotation/writerlistener/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/listener/annotation/writerlistener/SampleApplicationTest.kt new file mode 100644 index 00000000..57bc8772 --- /dev/null +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/listener/annotation/writerlistener/SampleApplicationTest.kt @@ -0,0 +1,46 @@ +/* + * Spring Batch Plus + * + * Copyright 2022-present NAVER Corp. + * + * 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 + * + * http://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 com.navercorp.spring.batch.plus.sample.step.chunkorientedstep.config.listener.annotation.writerlistener + +import org.junit.jupiter.api.Test +import org.springframework.batch.core.BatchStatus +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator +import org.springframework.beans.factory.getBean +import org.springframework.boot.autoconfigure.SpringBootApplication +import org.springframework.boot.runApplication + +@SpringBootApplication +open class SampleApplicationTest { + @Test + fun run() { + val applicationContext = runApplication() + val jobOperator = applicationContext.getBean() + val job = applicationContext.getBean() + + val jobParameters = + JobParametersBuilder() + .toJobParameters() + val jobExecution = jobOperator.start(job, jobParameters) + + assert(BatchStatus.COMPLETED == jobExecution.status) + println(jobExecution) + } +} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/annotationlistener/writerlistener/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/listener/annotation/writerlistener/TestJobConfig.kt similarity index 59% rename from spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/annotationlistener/writerlistener/TestJobConfig.kt rename to spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/listener/annotation/writerlistener/TestJobConfig.kt index 75dd3471..8bf9af25 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/annotationlistener/writerlistener/TestJobConfig.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/listener/annotation/writerlistener/TestJobConfig.kt @@ -16,27 +16,24 @@ * limitations under the License. */ -package com.navercorp.spring.batch.plus.sample.step.chunkorientedstep.config.annotationlistener.writerlistener +package com.navercorp.spring.batch.plus.sample.step.chunkorientedstep.config.listener.annotation.writerlistener import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.Job import org.springframework.batch.core.annotation.AfterWrite import org.springframework.batch.core.annotation.BeforeWrite import org.springframework.batch.core.annotation.OnWriteError -import org.springframework.batch.item.Chunk -import org.springframework.batch.item.ItemProcessor -import org.springframework.batch.item.ItemReader -import org.springframework.batch.item.ItemWriter +import org.springframework.batch.core.job.Job +import org.springframework.batch.infrastructure.item.Chunk +import org.springframework.batch.infrastructure.item.ItemProcessor +import org.springframework.batch.infrastructure.item.ItemReader +import org.springframework.batch.infrastructure.item.ItemWriter import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration -import org.springframework.transaction.PlatformTransactionManager @Configuration open class TestJobConfig( private val batch: BatchDsl, - private val transactionManager: PlatformTransactionManager, ) { - class TestListener { @BeforeWrite fun beforeWrite(chunk: Chunk) { @@ -49,51 +46,51 @@ open class TestJobConfig( } @OnWriteError - fun onWriteError(exception: Exception, chunk: Chunk) { + fun onWriteError( + exception: Exception, + chunk: Chunk, + ) { println("afterWrite: ${chunk.items}, exception: $exception") } } @Bean - open fun testJob(): Job = batch { - job("testJob") { - step("testStep") { - chunk(3, transactionManager) { - reader(testItemReader()) - processor(testItemProcessor()) - writer(testItemWriter()) - listener(TestListener()) + open fun testJob(): Job = + batch { + job("testJob") { + step("testStep") { + chunk(3) { + reader(testItemReader()) + processor(testItemProcessor()) + writer(testItemWriter()) + listener(TestListener()) + } } } } - } @Bean - open fun testItemReader(): ItemReader { - return object : ItemReader { + open fun testItemReader(): ItemReader = + object : ItemReader { private var count = 0 - override fun read(): Int? { - return if (count < 11) { + override fun read(): Int? = + if (count < 11) { count++ } else { null } - } } - } @Bean - open fun testItemProcessor(): ItemProcessor { - return ItemProcessor { item -> + open fun testItemProcessor(): ItemProcessor = + ItemProcessor { item -> item.toString() } - } @Bean - open fun testItemWriter(): ItemWriter { - return ItemWriter { items -> + open fun testItemWriter(): ItemWriter = + ItemWriter { items -> println("write $items") } - } } diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/listener/steplistener/chunklistener/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/listener/steplistener/chunklistener/SampleApplicationTest.kt new file mode 100644 index 00000000..999e467a --- /dev/null +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/listener/steplistener/chunklistener/SampleApplicationTest.kt @@ -0,0 +1,46 @@ +/* + * Spring Batch Plus + * + * Copyright 2022-present NAVER Corp. + * + * 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 + * + * http://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 com.navercorp.spring.batch.plus.sample.step.chunkorientedstep.config.listener.steplistener.chunklistener + +import org.junit.jupiter.api.Test +import org.springframework.batch.core.BatchStatus +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator +import org.springframework.beans.factory.getBean +import org.springframework.boot.autoconfigure.SpringBootApplication +import org.springframework.boot.runApplication + +@SpringBootApplication +open class SampleApplicationTest { + @Test + fun run() { + val applicationContext = runApplication() + val jobOperator = applicationContext.getBean() + val job = applicationContext.getBean() + + val jobParameters = + JobParametersBuilder() + .toJobParameters() + val jobExecution = jobOperator.start(job, jobParameters) + + assert(BatchStatus.COMPLETED == jobExecution.status) + println(jobExecution) + } +} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/listener/steplistener/chunklistener/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/listener/steplistener/chunklistener/TestJobConfig.kt new file mode 100644 index 00000000..56c7ed43 --- /dev/null +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/listener/steplistener/chunklistener/TestJobConfig.kt @@ -0,0 +1,90 @@ +/* + * Spring Batch Plus + * + * Copyright 2022-present NAVER Corp. + * + * 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 + * + * http://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 com.navercorp.spring.batch.plus.sample.step.chunkorientedstep.config.listener.steplistener.chunklistener + +import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.listener.ChunkListener +import org.springframework.batch.infrastructure.item.Chunk +import org.springframework.batch.infrastructure.item.ItemProcessor +import org.springframework.batch.infrastructure.item.ItemReader +import org.springframework.batch.infrastructure.item.ItemWriter +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration + +@Configuration +open class TestJobConfig( + private val batch: BatchDsl, +) { + @Bean + open fun testJob(): Job = + batch { + job("testJob") { + step("testStep") { + chunk(3) { + reader(testItemReader()) + processor(testItemProcessor()) + writer(testItemWriter()) + listener( + object : ChunkListener { + override fun beforeChunk(chunk: Chunk) { + println("beforeChunk: $chunk") + } + + override fun afterChunk(chunk: Chunk) { + println("afterChunk: $chunk") + } + + override fun onChunkError( + exception: Exception, + chunk: Chunk, + ) { + } + }, + ) + } + } + } + } + + @Bean + open fun testItemReader(): ItemReader = + object : ItemReader { + private var count = 0 + + override fun read(): Int? = + if (count < 11) { + count++ + } else { + null + } + } + + @Bean + open fun testItemProcessor(): ItemProcessor = + ItemProcessor { item -> + item.toString() + } + + @Bean + open fun testItemWriter(): ItemWriter = + ItemWriter { items -> + println("[${Thread.currentThread().name}] write $items") + } +} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/listener/steplistener/processorlistener/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/listener/steplistener/processorlistener/SampleApplicationTest.kt new file mode 100644 index 00000000..b7ded639 --- /dev/null +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/listener/steplistener/processorlistener/SampleApplicationTest.kt @@ -0,0 +1,46 @@ +/* + * Spring Batch Plus + * + * Copyright 2022-present NAVER Corp. + * + * 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 + * + * http://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 com.navercorp.spring.batch.plus.sample.step.chunkorientedstep.config.listener.steplistener.processorlistener + +import org.junit.jupiter.api.Test +import org.springframework.batch.core.BatchStatus +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator +import org.springframework.beans.factory.getBean +import org.springframework.boot.autoconfigure.SpringBootApplication +import org.springframework.boot.runApplication + +@SpringBootApplication +open class SampleApplicationTest { + @Test + fun run() { + val applicationContext = runApplication() + val jobOperator = applicationContext.getBean() + val job = applicationContext.getBean() + + val jobParameters = + JobParametersBuilder() + .toJobParameters() + val jobExecution = jobOperator.start(job, jobParameters) + + assert(BatchStatus.COMPLETED == jobExecution.status) + println(jobExecution) + } +} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/listener/steplistener/processorlistener/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/listener/steplistener/processorlistener/TestJobConfig.kt new file mode 100644 index 00000000..ce4657da --- /dev/null +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/listener/steplistener/processorlistener/TestJobConfig.kt @@ -0,0 +1,92 @@ +/* + * Spring Batch Plus + * + * Copyright 2022-present NAVER Corp. + * + * 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 + * + * http://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 com.navercorp.spring.batch.plus.sample.step.chunkorientedstep.config.listener.steplistener.processorlistener + +import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.listener.ItemProcessListener +import org.springframework.batch.infrastructure.item.ItemProcessor +import org.springframework.batch.infrastructure.item.ItemReader +import org.springframework.batch.infrastructure.item.ItemWriter +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration + +@Configuration +open class TestJobConfig( + private val batch: BatchDsl, +) { + @Bean + open fun testJob(): Job = + batch { + job("testJob") { + step("testStep") { + chunk(3) { + reader(testItemReader()) + processor(testItemProcessor()) + writer(testItemWriter()) + listener( + object : ItemProcessListener { + override fun beforeProcess(item: Int) { + println("beforeProcess: $item") + } + + override fun afterProcess( + item: Int, + result: String?, + ) { + println("afterProcess: $item, result: $result") + } + + override fun onProcessError( + item: Int, + e: Exception, + ) { + } + }, + ) + } + } + } + } + + @Bean + open fun testItemReader(): ItemReader = + object : ItemReader { + private var count = 0 + + override fun read(): Int? = + if (count < 11) { + count++ + } else { + null + } + } + + @Bean + open fun testItemProcessor(): ItemProcessor = + ItemProcessor { item -> + item.toString() + } + + @Bean + open fun testItemWriter(): ItemWriter = + ItemWriter { items -> + println("write $items") + } +} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/listener/steplistener/readerlistener/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/listener/steplistener/readerlistener/SampleApplicationTest.kt new file mode 100644 index 00000000..8884258b --- /dev/null +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/listener/steplistener/readerlistener/SampleApplicationTest.kt @@ -0,0 +1,46 @@ +/* + * Spring Batch Plus + * + * Copyright 2022-present NAVER Corp. + * + * 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 + * + * http://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 com.navercorp.spring.batch.plus.sample.step.chunkorientedstep.config.listener.steplistener.readerlistener + +import org.junit.jupiter.api.Test +import org.springframework.batch.core.BatchStatus +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator +import org.springframework.beans.factory.getBean +import org.springframework.boot.autoconfigure.SpringBootApplication +import org.springframework.boot.runApplication + +@SpringBootApplication +open class SampleApplicationTest { + @Test + fun run() { + val applicationContext = runApplication() + val jobOperator = applicationContext.getBean() + val job = applicationContext.getBean() + + val jobParameters = + JobParametersBuilder() + .toJobParameters() + val jobExecution = jobOperator.start(job, jobParameters) + + assert(BatchStatus.COMPLETED == jobExecution.status) + println(jobExecution) + } +} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/listener/steplistener/readerlistener/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/listener/steplistener/readerlistener/TestJobConfig.kt new file mode 100644 index 00000000..24af41ed --- /dev/null +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/listener/steplistener/readerlistener/TestJobConfig.kt @@ -0,0 +1,86 @@ +/* + * Spring Batch Plus + * + * Copyright 2022-present NAVER Corp. + * + * 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 + * + * http://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 com.navercorp.spring.batch.plus.sample.step.chunkorientedstep.config.listener.steplistener.readerlistener + +import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.listener.ItemReadListener +import org.springframework.batch.infrastructure.item.ItemProcessor +import org.springframework.batch.infrastructure.item.ItemReader +import org.springframework.batch.infrastructure.item.ItemWriter +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration + +@Configuration +open class TestJobConfig( + private val batch: BatchDsl, +) { + @Bean + open fun testJob(): Job = + batch { + job("testJob") { + step("testStep") { + chunk(3) { + reader(testItemReader()) + processor(testItemProcessor()) + writer(testItemWriter()) + listener( + object : ItemReadListener { + override fun beforeRead() { + println("beforeRead") + } + + override fun onReadError(ex: Exception) { + } + + override fun afterRead(item: Int) { + println("afterRead (item: $item)") + } + }, + ) + } + } + } + } + + @Bean + open fun testItemReader(): ItemReader = + object : ItemReader { + private var count = 0 + + override fun read(): Int? = + if (count < 11) { + count++ + } else { + null + } + } + + @Bean + open fun testItemProcessor(): ItemProcessor = + ItemProcessor { item -> + item.toString() + } + + @Bean + open fun testItemWriter(): ItemWriter = + ItemWriter { items -> + println("write $items") + } +} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/listener/steplistener/stepexecutionlistener/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/listener/steplistener/stepexecutionlistener/SampleApplicationTest.kt new file mode 100644 index 00000000..cdaf1294 --- /dev/null +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/listener/steplistener/stepexecutionlistener/SampleApplicationTest.kt @@ -0,0 +1,46 @@ +/* + * Spring Batch Plus + * + * Copyright 2022-present NAVER Corp. + * + * 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 + * + * http://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 com.navercorp.spring.batch.plus.sample.step.chunkorientedstep.config.listener.steplistener.stepexecutionlistener + +import org.junit.jupiter.api.Test +import org.springframework.batch.core.BatchStatus +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator +import org.springframework.beans.factory.getBean +import org.springframework.boot.autoconfigure.SpringBootApplication +import org.springframework.boot.runApplication + +@SpringBootApplication +open class SampleApplicationTest { + @Test + fun run() { + val applicationContext = runApplication() + val jobOperator = applicationContext.getBean() + val job = applicationContext.getBean() + + val jobParameters = + JobParametersBuilder() + .toJobParameters() + val jobExecution = jobOperator.start(job, jobParameters) + + assert(BatchStatus.COMPLETED == jobExecution.status) + println(jobExecution) + } +} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/listener/steplistener/stepexecutionlistener/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/listener/steplistener/stepexecutionlistener/TestJobConfig.kt new file mode 100644 index 00000000..61767d4b --- /dev/null +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/listener/steplistener/stepexecutionlistener/TestJobConfig.kt @@ -0,0 +1,86 @@ +/* + * Spring Batch Plus + * + * Copyright 2022-present NAVER Corp. + * + * 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 + * + * http://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 com.navercorp.spring.batch.plus.sample.step.chunkorientedstep.config.listener.steplistener.stepexecutionlistener + +import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl +import org.springframework.batch.core.ExitStatus +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.listener.StepExecutionListener +import org.springframework.batch.core.step.StepExecution +import org.springframework.batch.infrastructure.item.ItemProcessor +import org.springframework.batch.infrastructure.item.ItemReader +import org.springframework.batch.infrastructure.item.ItemWriter +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration + +@Configuration +open class TestJobConfig( + private val batch: BatchDsl, +) { + @Bean + open fun testJob(): Job = + batch { + job("testJob") { + step("testStep") { + chunk(3) { + reader(testItemReader()) + processor(testItemProcessor()) + writer(testItemWriter()) + listener( + object : StepExecutionListener { + override fun beforeStep(stepExecution: StepExecution) { + println("beforeStep: $stepExecution") + } + + override fun afterStep(stepExecution: StepExecution): ExitStatus? { + println("afterStep: $stepExecution") + return null + } + }, + ) + } + } + } + } + + @Bean + open fun testItemReader(): ItemReader = + object : ItemReader { + private var count = 0 + + override fun read(): Int? = + if (count < 11) { + count++ + } else { + null + } + } + + @Bean + open fun testItemProcessor(): ItemProcessor = + ItemProcessor { item -> + item.toString() + } + + @Bean + open fun testItemWriter(): ItemWriter = + ItemWriter { items -> + println("write $items") + } +} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/listener/steplistener/writerlistener/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/listener/steplistener/writerlistener/SampleApplicationTest.kt new file mode 100644 index 00000000..d6b4cbfe --- /dev/null +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/listener/steplistener/writerlistener/SampleApplicationTest.kt @@ -0,0 +1,46 @@ +/* + * Spring Batch Plus + * + * Copyright 2022-present NAVER Corp. + * + * 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 + * + * http://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 com.navercorp.spring.batch.plus.sample.step.chunkorientedstep.config.listener.steplistener.writerlistener + +import org.junit.jupiter.api.Test +import org.springframework.batch.core.BatchStatus +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator +import org.springframework.beans.factory.getBean +import org.springframework.boot.autoconfigure.SpringBootApplication +import org.springframework.boot.runApplication + +@SpringBootApplication +open class SampleApplicationTest { + @Test + fun run() { + val applicationContext = runApplication() + val jobOperator = applicationContext.getBean() + val job = applicationContext.getBean() + + val jobParameters = + JobParametersBuilder() + .toJobParameters() + val jobExecution = jobOperator.start(job, jobParameters) + + assert(BatchStatus.COMPLETED == jobExecution.status) + println(jobExecution) + } +} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/listener/steplistener/writerlistener/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/listener/steplistener/writerlistener/TestJobConfig.kt new file mode 100644 index 00000000..674aacf4 --- /dev/null +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/listener/steplistener/writerlistener/TestJobConfig.kt @@ -0,0 +1,90 @@ +/* + * Spring Batch Plus + * + * Copyright 2022-present NAVER Corp. + * + * 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 + * + * http://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 com.navercorp.spring.batch.plus.sample.step.chunkorientedstep.config.listener.steplistener.writerlistener + +import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.listener.ItemWriteListener +import org.springframework.batch.infrastructure.item.Chunk +import org.springframework.batch.infrastructure.item.ItemProcessor +import org.springframework.batch.infrastructure.item.ItemReader +import org.springframework.batch.infrastructure.item.ItemWriter +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration + +@Configuration +open class TestJobConfig( + private val batch: BatchDsl, +) { + @Bean + open fun testJob(): Job = + batch { + job("testJob") { + step("testStep") { + chunk(3) { + reader(testItemReader()) + processor(testItemProcessor()) + writer(testItemWriter()) + listener( + object : ItemWriteListener { + override fun beforeWrite(chunk: Chunk) { + println("beforeWrite: ${chunk.items}") + } + + override fun afterWrite(chunk: Chunk) { + println("afterWrite: ${chunk.items}") + } + + override fun onWriteError( + exception: Exception, + Chunk: Chunk, + ) { + } + }, + ) + } + } + } + } + + @Bean + open fun testItemReader(): ItemReader = + object : ItemReader { + private var count = 0 + + override fun read(): Int? = + if (count < 11) { + count++ + } else { + null + } + } + + @Bean + open fun testItemProcessor(): ItemProcessor = + ItemProcessor { item -> + item.toString() + } + + @Bean + open fun testItemWriter(): ItemWriter = + ItemWriter { items -> + println("write $items") + } +} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/observationregistry/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/observationregistry/SampleApplicationTest.kt new file mode 100644 index 00000000..d2f1a3d6 --- /dev/null +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/observationregistry/SampleApplicationTest.kt @@ -0,0 +1,46 @@ +/* + * Spring Batch Plus + * + * Copyright 2022-present NAVER Corp. + * + * 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 + * + * http://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 com.navercorp.spring.batch.plus.sample.step.chunkorientedstep.config.observationregistry + +import org.junit.jupiter.api.Test +import org.springframework.batch.core.BatchStatus +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator +import org.springframework.beans.factory.getBean +import org.springframework.boot.autoconfigure.SpringBootApplication +import org.springframework.boot.runApplication + +@SpringBootApplication +open class SampleApplicationTest { + @Test + fun run() { + val applicationContext = runApplication() + val jobOperator = applicationContext.getBean() + val job = applicationContext.getBean() + + val jobParameters = + JobParametersBuilder() + .toJobParameters() + val jobExecution = jobOperator.start(job, jobParameters) + + assert(BatchStatus.COMPLETED == jobExecution.status) + println(jobExecution) + } +} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/observationregistry/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/observationregistry/TestJobConfig.kt new file mode 100644 index 00000000..6445eb9b --- /dev/null +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/observationregistry/TestJobConfig.kt @@ -0,0 +1,65 @@ +/* + * Spring Batch Plus + * + * Copyright 2022-present NAVER Corp. + * + * 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 + * + * http://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 com.navercorp.spring.batch.plus.sample.step.chunkorientedstep.config.observationregistry + +import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl +import io.micrometer.observation.ObservationRegistry +import org.springframework.batch.core.job.Job +import org.springframework.batch.infrastructure.item.ItemReader +import org.springframework.batch.infrastructure.item.ItemWriter +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration + +@Configuration +open class TestJobConfig( + private val batch: BatchDsl, +) { + @Bean + open fun testJob(): Job = + batch { + job("testJob") { + step("testStep") { + chunk(3) { + reader(testItemReader()) + writer(testItemWriter()) + observationRegistry(ObservationRegistry.create()) + } + } + } + } + + @Bean + open fun testItemReader(): ItemReader = + object : ItemReader { + private var count = 0 + + override fun read(): Int? = + if (count < 20) { + count++ + } else { + null + } + } + + @Bean + open fun testItemWriter(): ItemWriter = + ItemWriter { items -> + println("write $items") + } +} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/processorlistener/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/processorlistener/SampleApplicationTest.kt deleted file mode 100644 index 8791d4dc..00000000 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/processorlistener/SampleApplicationTest.kt +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Spring Batch Plus - * - * Copyright 2022-present NAVER Corp. - * - * 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 - * - * http://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 com.navercorp.spring.batch.plus.sample.step.chunkorientedstep.config.processorlistener - -import org.junit.jupiter.api.Test -import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher -import org.springframework.beans.factory.getBean -import org.springframework.boot.autoconfigure.SpringBootApplication -import org.springframework.boot.runApplication - -@SpringBootApplication -open class SampleApplicationTest { - @Test - fun run() { - val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() - val job = applicationContext.getBean() - - val jobParameters = JobParametersBuilder() - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) - - assert(BatchStatus.COMPLETED == jobExecution.status) - println(jobExecution) - } -} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/processorlistener/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/processorlistener/TestJobConfig.kt deleted file mode 100644 index bb3f05cc..00000000 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/processorlistener/TestJobConfig.kt +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Spring Batch Plus - * - * Copyright 2022-present NAVER Corp. - * - * 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 - * - * http://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 com.navercorp.spring.batch.plus.sample.step.chunkorientedstep.config.processorlistener - -import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.ItemProcessListener -import org.springframework.batch.core.Job -import org.springframework.batch.item.ItemProcessor -import org.springframework.batch.item.ItemReader -import org.springframework.batch.item.ItemWriter -import org.springframework.context.annotation.Bean -import org.springframework.context.annotation.Configuration -import org.springframework.transaction.PlatformTransactionManager - -@Configuration -open class TestJobConfig( - private val batch: BatchDsl, - private val transactionManager: PlatformTransactionManager, -) { - - @Bean - open fun testJob(): Job = batch { - job("testJob") { - step("testStep") { - chunk(3, transactionManager) { - reader(testItemReader()) - processor(testItemProcessor()) - writer(testItemWriter()) - listener( - object : ItemProcessListener { - override fun beforeProcess(item: Int) { - println("beforeProcess: $item") - } - - override fun afterProcess(item: Int, result: String?) { - println("afterProcess: $item, result: $result") - } - - override fun onProcessError(item: Int, e: Exception) { - } - }, - ) - } - } - } - } - - @Bean - open fun testItemReader(): ItemReader { - return object : ItemReader { - private var count = 0 - - override fun read(): Int? { - return if (count < 11) { - count++ - } else { - null - } - } - } - } - - @Bean - open fun testItemProcessor(): ItemProcessor { - return ItemProcessor { item -> - item.toString() - } - } - - @Bean - open fun testItemWriter(): ItemWriter { - return ItemWriter { items -> - println("write $items") - } - } -} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/readerlistener/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/readerlistener/SampleApplicationTest.kt deleted file mode 100644 index 3d6f1fd5..00000000 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/readerlistener/SampleApplicationTest.kt +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Spring Batch Plus - * - * Copyright 2022-present NAVER Corp. - * - * 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 - * - * http://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 com.navercorp.spring.batch.plus.sample.step.chunkorientedstep.config.readerlistener - -import org.junit.jupiter.api.Test -import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher -import org.springframework.beans.factory.getBean -import org.springframework.boot.autoconfigure.SpringBootApplication -import org.springframework.boot.runApplication - -@SpringBootApplication -open class SampleApplicationTest { - @Test - fun run() { - val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() - val job = applicationContext.getBean() - - val jobParameters = JobParametersBuilder() - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) - - assert(BatchStatus.COMPLETED == jobExecution.status) - println(jobExecution) - } -} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/readerlistener/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/readerlistener/TestJobConfig.kt deleted file mode 100644 index 2ef278c1..00000000 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/readerlistener/TestJobConfig.kt +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Spring Batch Plus - * - * Copyright 2022-present NAVER Corp. - * - * 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 - * - * http://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 com.navercorp.spring.batch.plus.sample.step.chunkorientedstep.config.readerlistener - -import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.ItemReadListener -import org.springframework.batch.core.Job -import org.springframework.batch.item.ItemProcessor -import org.springframework.batch.item.ItemReader -import org.springframework.batch.item.ItemWriter -import org.springframework.context.annotation.Bean -import org.springframework.context.annotation.Configuration -import org.springframework.transaction.PlatformTransactionManager - -@Configuration -open class TestJobConfig( - private val batch: BatchDsl, - private val transactionManager: PlatformTransactionManager, -) { - - @Bean - open fun testJob(): Job = batch { - job("testJob") { - step("testStep") { - chunk(3, transactionManager) { - reader(testItemReader()) - processor(testItemProcessor()) - writer(testItemWriter()) - listener( - object : ItemReadListener { - override fun beforeRead() { - println("beforeRead") - } - - override fun onReadError(ex: Exception) { - } - - override fun afterRead(item: Int) { - println("afterRead (item: $item)") - } - }, - ) - } - } - } - } - - @Bean - open fun testItemReader(): ItemReader { - return object : ItemReader { - private var count = 0 - - override fun read(): Int? { - return if (count < 11) { - count++ - } else { - null - } - } - } - } - - @Bean - open fun testItemProcessor(): ItemProcessor { - return ItemProcessor { item -> - item.toString() - } - } - - @Bean - open fun testItemWriter(): ItemWriter { - return ItemWriter { items -> - println("write $items") - } - } -} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/stepoperation/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/stepoperation/SampleApplicationTest.kt deleted file mode 100644 index ea6cfe60..00000000 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/stepoperation/SampleApplicationTest.kt +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Spring Batch Plus - * - * Copyright 2022-present NAVER Corp. - * - * 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 - * - * http://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 com.navercorp.spring.batch.plus.sample.step.chunkorientedstep.config.stepoperation - -import org.junit.jupiter.api.Test -import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher -import org.springframework.beans.factory.getBean -import org.springframework.boot.autoconfigure.SpringBootApplication -import org.springframework.boot.runApplication - -@SpringBootApplication -open class SampleApplicationTest { - @Test - fun run() { - val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() - val job = applicationContext.getBean() - - val jobParameters = JobParametersBuilder() - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) - - assert(BatchStatus.COMPLETED == jobExecution.status) - println(jobExecution) - } -} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/stepoperation/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/stepoperation/TestJobConfig.kt deleted file mode 100644 index 3539d94a..00000000 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/stepoperation/TestJobConfig.kt +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Spring Batch Plus - * - * Copyright 2022-present NAVER Corp. - * - * 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 - * - * http://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 com.navercorp.spring.batch.plus.sample.step.chunkorientedstep.config.stepoperation - -import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.Job -import org.springframework.batch.item.ItemReader -import org.springframework.batch.item.ItemWriter -import org.springframework.batch.repeat.RepeatCallback -import org.springframework.batch.repeat.RepeatOperations -import org.springframework.batch.repeat.RepeatStatus -import org.springframework.batch.repeat.support.RepeatTemplate -import org.springframework.context.annotation.Bean -import org.springframework.context.annotation.Configuration -import org.springframework.transaction.PlatformTransactionManager - -@Configuration -open class TestJobConfig( - private val batch: BatchDsl, - private val transactionManager: PlatformTransactionManager, -) { - - @Bean - open fun testJob(): Job = batch { - job("testJob") { - step("testStep") { - chunk(3, transactionManager) { - reader(testItemReader()) - writer(testItemWriter()) - stepOperations( - object : RepeatOperations { - override fun iterate(callback: RepeatCallback): RepeatStatus { - val delegate = RepeatTemplate() - println("custom iterate") - return delegate.iterate(callback) - } - }, - ) - } - } - } - } - - @Bean - open fun testItemReader(): ItemReader { - return object : ItemReader { - private var count = 0 - - override fun read(): Int? { - return if (count < 20) { - count++ - } else { - null - } - } - } - } - - @Bean - open fun testItemWriter(): ItemWriter { - return ItemWriter { items -> - println("[${Thread.currentThread().name}] write $items") - } - } -} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/stream/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/stream/SampleApplicationTest.kt index 717f11a0..292ea2cd 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/stream/SampleApplicationTest.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/stream/SampleApplicationTest.kt @@ -20,9 +20,9 @@ package com.navercorp.spring.batch.plus.sample.step.chunkorientedstep.config.str import org.junit.jupiter.api.Test import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator import org.springframework.beans.factory.getBean import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.runApplication @@ -32,12 +32,13 @@ open class SampleApplicationTest { @Test fun run() { val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() + val jobOperator = applicationContext.getBean() val job = applicationContext.getBean() - val jobParameters = JobParametersBuilder() - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) + val jobParameters = + JobParametersBuilder() + .toJobParameters() + val jobExecution = jobOperator.start(job, jobParameters) assert(BatchStatus.COMPLETED == jobExecution.status) println(jobExecution) diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/stream/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/stream/TestJobConfig.kt index dd1a34b1..6be7cea2 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/stream/TestJobConfig.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/stream/TestJobConfig.kt @@ -19,76 +19,70 @@ package com.navercorp.spring.batch.plus.sample.step.chunkorientedstep.config.stream import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.Job -import org.springframework.batch.item.ExecutionContext -import org.springframework.batch.item.ItemProcessor -import org.springframework.batch.item.ItemReader -import org.springframework.batch.item.ItemStream -import org.springframework.batch.item.ItemWriter +import org.springframework.batch.core.job.Job +import org.springframework.batch.infrastructure.item.ExecutionContext +import org.springframework.batch.infrastructure.item.ItemProcessor +import org.springframework.batch.infrastructure.item.ItemReader +import org.springframework.batch.infrastructure.item.ItemStream +import org.springframework.batch.infrastructure.item.ItemWriter import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration -import org.springframework.transaction.PlatformTransactionManager @Configuration open class TestJobConfig( private val batch: BatchDsl, - private val transactionManager: PlatformTransactionManager, ) { - @Bean - open fun testJob(): Job = batch { - job("testJob") { - step("testStep") { - chunk(3, transactionManager) { - reader(testItemReader()) - processor(testItemProcessor()) - writer(testItemWriter()) - stream( - object : ItemStream { - override fun open(executionContext: ExecutionContext) { - println("open stream") - } + open fun testJob(): Job = + batch { + job("testJob") { + step("testStep") { + chunk(3) { + reader(testItemReader()) + processor(testItemProcessor()) + writer(testItemWriter()) + stream( + object : ItemStream { + override fun open(executionContext: ExecutionContext) { + println("open stream") + } - override fun update(executionContext: ExecutionContext) { - println("update stream") - } + override fun update(executionContext: ExecutionContext) { + println("update stream") + } - override fun close() { - println("close stream") - } - }, - ) + override fun close() { + println("close stream") + } + }, + ) + } } } } - } @Bean - open fun testItemReader(): ItemReader { - return object : ItemReader { + open fun testItemReader(): ItemReader = + object : ItemReader { private var count = 0 - override fun read(): Int? { - return if (count < 11) { + override fun read(): Int? = + if (count < 11) { count++ } else { null } - } } - } @Bean - open fun testItemProcessor(): ItemProcessor { - return ItemProcessor { item -> + open fun testItemProcessor(): ItemProcessor = + ItemProcessor { item -> item.toString() } - } @Bean - open fun testItemWriter(): ItemWriter { - return ItemWriter { items -> + open fun testItemWriter(): ItemWriter = + ItemWriter { items -> println("[${Thread.currentThread().name}] write $items") } - } } diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/chunksize/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/taskexecutor/SampleApplicationTest.kt similarity index 74% rename from spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/chunksize/SampleApplicationTest.kt rename to spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/taskexecutor/SampleApplicationTest.kt index 8d566230..5bd40715 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/chunksize/SampleApplicationTest.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/taskexecutor/SampleApplicationTest.kt @@ -16,13 +16,13 @@ * limitations under the License. */ -package com.navercorp.spring.batch.plus.sample.step.chunkorientedstep.chunksize +package com.navercorp.spring.batch.plus.sample.step.chunkorientedstep.config.taskexecutor import org.junit.jupiter.api.Test import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator import org.springframework.beans.factory.getBean import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.runApplication @@ -32,12 +32,13 @@ open class SampleApplicationTest { @Test fun run() { val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() + val jobOperator = applicationContext.getBean() val job = applicationContext.getBean() - val jobParameters = JobParametersBuilder() - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) + val jobParameters = + JobParametersBuilder() + .toJobParameters() + val jobExecution = jobOperator.start(job, jobParameters) assert(BatchStatus.COMPLETED == jobExecution.status) println(jobExecution) diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/executor/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/taskexecutor/TestJobConfig.kt similarity index 56% rename from spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/executor/TestJobConfig.kt rename to spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/taskexecutor/TestJobConfig.kt index 38b0d4b7..c1d8d459 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/executor/TestJobConfig.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/taskexecutor/TestJobConfig.kt @@ -16,61 +16,54 @@ * limitations under the License. */ -package com.navercorp.spring.batch.plus.sample.step.chunkorientedstep.config.executor +package com.navercorp.spring.batch.plus.sample.step.chunkorientedstep.config.taskexecutor import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.Job -import org.springframework.batch.item.ItemReader -import org.springframework.batch.item.ItemWriter +import org.springframework.batch.core.job.Job +import org.springframework.batch.infrastructure.item.ItemReader +import org.springframework.batch.infrastructure.item.ItemWriter import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration +import org.springframework.core.task.AsyncTaskExecutor import org.springframework.core.task.SimpleAsyncTaskExecutor -import org.springframework.core.task.TaskExecutor -import org.springframework.transaction.PlatformTransactionManager @Configuration open class TestJobConfig( private val batch: BatchDsl, - private val transactionManager: PlatformTransactionManager, ) { - @Bean - open fun customExecutor(): TaskExecutor { - return SimpleAsyncTaskExecutor() - } + open fun customExecutor(): AsyncTaskExecutor = SimpleAsyncTaskExecutor() @Bean - open fun testJob(): Job = batch { - job("testJob") { - step("testStep") { - chunk(3, transactionManager) { - reader(testItemReader()) - writer(testItemWriter()) - taskExecutor(customExecutor()) + open fun testJob(): Job = + batch { + job("testJob") { + step("testStep") { + chunk(3) { + reader(testItemReader()) + writer(testItemWriter()) + taskExecutor(customExecutor()) + } } } } - } @Bean - open fun testItemReader(): ItemReader { - return object : ItemReader { + open fun testItemReader(): ItemReader = + object : ItemReader { private var count = 0 - override fun read(): Int? { - return if (count < 20) { + override fun read(): Int? = + if (count < 20) { count++ } else { null } - } } - } @Bean - open fun testItemWriter(): ItemWriter { - return ItemWriter { items -> + open fun testItemWriter(): ItemWriter = + ItemWriter { items -> println("[${Thread.currentThread().name}] write $items") } - } } diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/transactionattribute/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/transactionattribute/SampleApplicationTest.kt index 567761af..0763f2ec 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/transactionattribute/SampleApplicationTest.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/transactionattribute/SampleApplicationTest.kt @@ -20,9 +20,9 @@ package com.navercorp.spring.batch.plus.sample.step.chunkorientedstep.config.tra import org.junit.jupiter.api.Test import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator import org.springframework.beans.factory.getBean import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.runApplication @@ -32,12 +32,13 @@ open class SampleApplicationTest { @Test fun run() { val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() + val jobOperator = applicationContext.getBean() val job = applicationContext.getBean() - val jobParameters = JobParametersBuilder() - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) + val jobParameters = + JobParametersBuilder() + .toJobParameters() + val jobExecution = jobOperator.start(job, jobParameters) assert(BatchStatus.COMPLETED == jobExecution.status) println(jobExecution) diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/transactionattribute/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/transactionattribute/TestJobConfig.kt index 3b1e1e29..673428e5 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/transactionattribute/TestJobConfig.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/transactionattribute/TestJobConfig.kt @@ -19,58 +19,53 @@ package com.navercorp.spring.batch.plus.sample.step.chunkorientedstep.config.transactionattribute import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.Job -import org.springframework.batch.item.ItemReader -import org.springframework.batch.item.ItemWriter +import org.springframework.batch.core.job.Job +import org.springframework.batch.infrastructure.item.ItemReader +import org.springframework.batch.infrastructure.item.ItemWriter import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration -import org.springframework.transaction.PlatformTransactionManager import org.springframework.transaction.interceptor.DefaultTransactionAttribute import org.springframework.transaction.support.TransactionSynchronizationManager @Configuration open class TestJobConfig( private val batch: BatchDsl, - private val transactionManager: PlatformTransactionManager, ) { - @Bean - open fun testJob(): Job = batch { - job("testJob") { - step("testStep") { - chunk(3, transactionManager) { - reader(testItemReader()) - writer(testItemWriter()) - transactionAttribute( - DefaultTransactionAttribute().apply { - setName("test-tx") - }, - ) + open fun testJob(): Job = + batch { + job("testJob") { + step("testStep") { + chunk(3) { + reader(testItemReader()) + writer(testItemWriter()) + transactionAttribute( + DefaultTransactionAttribute().apply { + setName("test-tx") + }, + ) + } } } } - } @Bean - open fun testItemReader(): ItemReader { - return object : ItemReader { + open fun testItemReader(): ItemReader = + object : ItemReader { private var count = 0 - override fun read(): Int? { - return if (count < 20) { + override fun read(): Int? = + if (count < 20) { count++ } else { null } - } } - } @Bean - open fun testItemWriter(): ItemWriter { - return ItemWriter { items -> + open fun testItemWriter(): ItemWriter = + ItemWriter { items -> val transactionName = TransactionSynchronizationManager.getCurrentTransactionName() println("write $items (transactionName: $transactionName)") } - } } diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/annotationlistener/mixed/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/transactionmanager/SampleApplicationTest.kt similarity index 74% rename from spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/annotationlistener/mixed/SampleApplicationTest.kt rename to spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/transactionmanager/SampleApplicationTest.kt index 3201e74d..4d9ae987 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/annotationlistener/mixed/SampleApplicationTest.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/transactionmanager/SampleApplicationTest.kt @@ -16,13 +16,13 @@ * limitations under the License. */ -package com.navercorp.spring.batch.plus.sample.step.chunkorientedstep.config.annotationlistener.mixed +package com.navercorp.spring.batch.plus.sample.step.chunkorientedstep.config.transactionmanager import org.junit.jupiter.api.Test import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator import org.springframework.beans.factory.getBean import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.runApplication @@ -32,12 +32,13 @@ open class SampleApplicationTest { @Test fun run() { val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() + val jobOperator = applicationContext.getBean() val job = applicationContext.getBean() - val jobParameters = JobParametersBuilder() - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) + val jobParameters = + JobParametersBuilder() + .toJobParameters() + val jobExecution = jobOperator.start(job, jobParameters) assert(BatchStatus.COMPLETED == jobExecution.status) println(jobExecution) diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/chunksize/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/transactionmanager/TestJobConfig.kt similarity index 58% rename from spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/chunksize/TestJobConfig.kt rename to spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/transactionmanager/TestJobConfig.kt index 8d3cfb9a..3d0002dd 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/chunksize/TestJobConfig.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/transactionmanager/TestJobConfig.kt @@ -16,13 +16,12 @@ * limitations under the License. */ -package com.navercorp.spring.batch.plus.sample.step.chunkorientedstep.chunksize +package com.navercorp.spring.batch.plus.sample.step.chunkorientedstep.config.transactionmanager import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.Job -import org.springframework.batch.item.ItemProcessor -import org.springframework.batch.item.ItemReader -import org.springframework.batch.item.ItemWriter +import org.springframework.batch.core.job.Job +import org.springframework.batch.infrastructure.item.ItemReader +import org.springframework.batch.infrastructure.item.ItemWriter import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.transaction.PlatformTransactionManager @@ -32,46 +31,36 @@ open class TestJobConfig( private val batch: BatchDsl, private val transactionManager: PlatformTransactionManager, ) { - @Bean - open fun testJob(): Job = batch { - job("testJob") { - step("testStep") { - chunk(3, transactionManager) { - reader(testItemReader()) - processor(testItemProcessor()) - writer(testItemWriter()) + open fun testJob(): Job = + batch { + job("testJob") { + step("testStep") { + chunk(3) { + transactionManager(transactionManager) + reader(testItemReader()) + writer(testItemWriter()) + } } } } - } @Bean - open fun testItemReader(): ItemReader { - return object : ItemReader { + open fun testItemReader(): ItemReader = + object : ItemReader { private var count = 0 - override fun read(): Int? { - return if (count < 11) { + override fun read(): Int? = + if (count < 20) { count++ } else { null } - } - } - } - - @Bean - open fun testItemProcessor(): ItemProcessor { - return ItemProcessor { item -> - item.toString() } - } @Bean - open fun testItemWriter(): ItemWriter { - return ItemWriter { items -> + open fun testItemWriter(): ItemWriter = + ItemWriter { items -> println("write $items") } - } } diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/writerlistener/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/writerlistener/SampleApplicationTest.kt deleted file mode 100644 index 50d29e4e..00000000 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/writerlistener/SampleApplicationTest.kt +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Spring Batch Plus - * - * Copyright 2022-present NAVER Corp. - * - * 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 - * - * http://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 com.navercorp.spring.batch.plus.sample.step.chunkorientedstep.config.writerlistener - -import org.junit.jupiter.api.Test -import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher -import org.springframework.beans.factory.getBean -import org.springframework.boot.autoconfigure.SpringBootApplication -import org.springframework.boot.runApplication - -@SpringBootApplication -open class SampleApplicationTest { - @Test - fun run() { - val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() - val job = applicationContext.getBean() - - val jobParameters = JobParametersBuilder() - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) - - assert(BatchStatus.COMPLETED == jobExecution.status) - println(jobExecution) - } -} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/writerlistener/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/writerlistener/TestJobConfig.kt deleted file mode 100644 index 0a6f61e8..00000000 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/config/writerlistener/TestJobConfig.kt +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Spring Batch Plus - * - * Copyright 2022-present NAVER Corp. - * - * 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 - * - * http://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 com.navercorp.spring.batch.plus.sample.step.chunkorientedstep.config.writerlistener - -import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.ItemWriteListener -import org.springframework.batch.core.Job -import org.springframework.batch.item.Chunk -import org.springframework.batch.item.ItemProcessor -import org.springframework.batch.item.ItemReader -import org.springframework.batch.item.ItemWriter -import org.springframework.context.annotation.Bean -import org.springframework.context.annotation.Configuration -import org.springframework.transaction.PlatformTransactionManager - -@Configuration -open class TestJobConfig( - private val batch: BatchDsl, - private val transactionManager: PlatformTransactionManager, -) { - - @Bean - open fun testJob(): Job = batch { - job("testJob") { - step("testStep") { - chunk(3, transactionManager) { - reader(testItemReader()) - processor(testItemProcessor()) - writer(testItemWriter()) - listener( - object : ItemWriteListener { - override fun beforeWrite(chunk: Chunk) { - println("beforeWrite: ${chunk.items}") - } - - override fun afterWrite(chunk: Chunk) { - println("afterWrite: ${chunk.items}") - } - - override fun onWriteError(exception: Exception, Chunk: Chunk) { - } - }, - ) - } - } - } - } - - @Bean - open fun testItemReader(): ItemReader { - return object : ItemReader { - private var count = 0 - - override fun read(): Int? { - return if (count < 11) { - count++ - } else { - null - } - } - } - } - - @Bean - open fun testItemProcessor(): ItemProcessor { - return ItemProcessor { item -> - item.toString() - } - } - - @Bean - open fun testItemWriter(): ItemWriter { - return ItemWriter { items -> - println("write $items") - } - } -} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/creation/README.md b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/creation/README.md new file mode 100644 index 00000000..0b20a3a8 --- /dev/null +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/creation/README.md @@ -0,0 +1,6 @@ +# Chunk-Oriented Step Creation Samples + +## Invariants + +- Every non-deprecated chunk-oriented step creation capability exposed by the + Kotlin DSL should have a runnable sample in this package. diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/chunkpolicy/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/creation/chunksize/SampleApplicationTest.kt similarity index 74% rename from spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/chunkpolicy/SampleApplicationTest.kt rename to spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/creation/chunksize/SampleApplicationTest.kt index 89c138d6..7460247f 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/chunkpolicy/SampleApplicationTest.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/creation/chunksize/SampleApplicationTest.kt @@ -16,13 +16,13 @@ * limitations under the License. */ -package com.navercorp.spring.batch.plus.sample.step.chunkorientedstep.chunkpolicy +package com.navercorp.spring.batch.plus.sample.step.chunkorientedstep.creation.chunksize import org.junit.jupiter.api.Test import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator import org.springframework.beans.factory.getBean import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.runApplication @@ -32,12 +32,13 @@ open class SampleApplicationTest { @Test fun run() { val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() + val jobOperator = applicationContext.getBean() val job = applicationContext.getBean() - val jobParameters = JobParametersBuilder() - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) + val jobParameters = + JobParametersBuilder() + .toJobParameters() + val jobExecution = jobOperator.start(job, jobParameters) assert(BatchStatus.COMPLETED == jobExecution.status) println(jobExecution) diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/chunkpolicy/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/creation/chunksize/TestJobConfig.kt similarity index 52% rename from spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/chunkpolicy/TestJobConfig.kt rename to spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/creation/chunksize/TestJobConfig.kt index 3837a270..6e810720 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/chunkpolicy/TestJobConfig.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/creation/chunksize/TestJobConfig.kt @@ -16,63 +16,56 @@ * limitations under the License. */ -package com.navercorp.spring.batch.plus.sample.step.chunkorientedstep.chunkpolicy +package com.navercorp.spring.batch.plus.sample.step.chunkorientedstep.creation.chunksize import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.Job -import org.springframework.batch.item.ItemProcessor -import org.springframework.batch.item.ItemReader -import org.springframework.batch.item.ItemWriter -import org.springframework.batch.repeat.policy.SimpleCompletionPolicy +import org.springframework.batch.core.job.Job +import org.springframework.batch.infrastructure.item.ItemProcessor +import org.springframework.batch.infrastructure.item.ItemReader +import org.springframework.batch.infrastructure.item.ItemWriter import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration -import org.springframework.transaction.PlatformTransactionManager @Configuration open class TestJobConfig( private val batch: BatchDsl, - private val transactionManager: PlatformTransactionManager, ) { - @Bean - open fun testJob(): Job = batch { - job("testJob") { - step("testStep") { - chunk(SimpleCompletionPolicy(3), transactionManager) { - reader(testItemReader()) - processor(testItemProcessor()) - writer(testItemWriter()) + open fun testJob(): Job = + batch { + job("testJob") { + step("testStep") { + chunk(3) { + reader(testItemReader()) + processor(testItemProcessor()) + writer(testItemWriter()) + } } } } - } @Bean - open fun testItemReader(): ItemReader { - return object : ItemReader { + open fun testItemReader(): ItemReader = + object : ItemReader { private var count = 0 - override fun read(): Int? { - return if (count < 11) { + override fun read(): Int? = + if (count < 11) { count++ } else { null } - } } - } @Bean - open fun testItemProcessor(): ItemProcessor { - return ItemProcessor { item -> + open fun testItemProcessor(): ItemProcessor = + ItemProcessor { item -> item.toString() } - } @Bean - open fun testItemWriter(): ItemWriter { - return ItemWriter { items -> + open fun testItemWriter(): ItemWriter = + ItemWriter { items -> println("write $items") } - } } diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/faulttolerant/README.md b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/faulttolerant/README.md new file mode 100644 index 00000000..c1fdb962 --- /dev/null +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/faulttolerant/README.md @@ -0,0 +1,6 @@ +# Fault-Tolerant Chunk-Oriented Step Samples + +## Invariants + +- Every retry and skip capability exposed by the Kotlin DSL for + chunk-oriented steps should have a runnable sample in this package. diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/faulttolerant/backoffpolicy/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/faulttolerant/backoffpolicy/SampleApplicationTest.kt deleted file mode 100644 index c36fd02c..00000000 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/faulttolerant/backoffpolicy/SampleApplicationTest.kt +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Spring Batch Plus - * - * Copyright 2022-present NAVER Corp. - * - * 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 - * - * http://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 com.navercorp.spring.batch.plus.sample.step.chunkorientedstep.faulttolerant.backoffpolicy - -import org.junit.jupiter.api.Test -import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher -import org.springframework.beans.factory.getBean -import org.springframework.boot.autoconfigure.SpringBootApplication -import org.springframework.boot.runApplication - -@SpringBootApplication -open class SampleApplicationTest { - @Test - fun run() { - val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() - val job = applicationContext.getBean() - - val jobParameters = JobParametersBuilder() - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) - - assert(BatchStatus.COMPLETED == jobExecution.status) - println(jobExecution) - } -} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/faulttolerant/backoffpolicy/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/faulttolerant/backoffpolicy/TestJobConfig.kt deleted file mode 100644 index 07f8df34..00000000 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/faulttolerant/backoffpolicy/TestJobConfig.kt +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Spring Batch Plus - * - * Copyright 2022-present NAVER Corp. - * - * 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 - * - * http://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 com.navercorp.spring.batch.plus.sample.step.chunkorientedstep.faulttolerant.backoffpolicy - -import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.Job -import org.springframework.batch.item.ItemProcessor -import org.springframework.batch.item.ItemReader -import org.springframework.batch.item.ItemWriter -import org.springframework.context.annotation.Bean -import org.springframework.context.annotation.Configuration -import org.springframework.retry.RetryContext -import org.springframework.retry.backoff.BackOffContext -import org.springframework.retry.backoff.BackOffPolicy -import org.springframework.transaction.PlatformTransactionManager - -@Configuration -open class TestJobConfig( - private val batch: BatchDsl, - private val transactionManager: PlatformTransactionManager, -) { - - @Bean - open fun testJob(): Job = batch { - job("testJob") { - step("testStep") { - chunk(3, transactionManager) { - reader(testItemReader()) - processor(testItemProcessor()) - writer(testItemWriter()) - faultTolerant { - retry() - retryLimit(4) - backOffPolicy( - object : BackOffPolicy { - override fun start(context: RetryContext?): BackOffContext? { - return null - } - - override fun backOff(backOffContext: BackOffContext?) { - println("backOff (context: $backOffContext)") - } - }, - ) - } - } - } - } - } - - @Bean - open fun testItemReader(): ItemReader { - return object : ItemReader { - private var count = 0 - - override fun read(): Int? { - if (count < 11) { - return count++ - } else { - return null - } - } - } - } - - @Bean - open fun testItemProcessor(): ItemProcessor { - var tryCount = 0 - - return ItemProcessor { item -> - if (item == 5 && tryCount < 3) { - ++tryCount - throw IllegalStateException("Error (tryCount: $tryCount)") - } - - item.toString() - } - } - - @Bean - open fun testItemWriter(): ItemWriter { - return ItemWriter { items -> - println("write $items") - } - } -} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/faulttolerant/keygenerator/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/faulttolerant/keygenerator/SampleApplicationTest.kt deleted file mode 100644 index 9b0ce2b5..00000000 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/faulttolerant/keygenerator/SampleApplicationTest.kt +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Spring Batch Plus - * - * Copyright 2022-present NAVER Corp. - * - * 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 - * - * http://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 com.navercorp.spring.batch.plus.sample.step.chunkorientedstep.faulttolerant.keygenerator - -import org.junit.jupiter.api.Test -import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher -import org.springframework.beans.factory.getBean -import org.springframework.boot.autoconfigure.SpringBootApplication -import org.springframework.boot.runApplication - -@SpringBootApplication -open class SampleApplicationTest { - @Test - fun run() { - val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() - val job = applicationContext.getBean() - - val jobParameters = JobParametersBuilder() - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) - - assert(BatchStatus.COMPLETED == jobExecution.status) - println(jobExecution) - } -} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/faulttolerant/keygenerator/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/faulttolerant/keygenerator/TestJobConfig.kt deleted file mode 100644 index 50b26c1e..00000000 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/faulttolerant/keygenerator/TestJobConfig.kt +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Spring Batch Plus - * - * Copyright 2022-present NAVER Corp. - * - * 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 - * - * http://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 com.navercorp.spring.batch.plus.sample.step.chunkorientedstep.faulttolerant.keygenerator - -import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.Job -import org.springframework.batch.item.ItemProcessor -import org.springframework.batch.item.ItemReader -import org.springframework.batch.item.ItemWriter -import org.springframework.context.annotation.Bean -import org.springframework.context.annotation.Configuration -import org.springframework.transaction.PlatformTransactionManager - -@Configuration -open class TestJobConfig( - private val batch: BatchDsl, - private val transactionManager: PlatformTransactionManager, -) { - - @Bean - open fun testJob(): Job = batch { - job("testJob") { - step("testStep") { - chunk(3, transactionManager) { - reader(testItemReader()) - processor(testItemProcessor()) - writer(testItemWriter()) - faultTolerant { - keyGenerator { item -> - println("get key of $item") - item.toString() - } - // same as - // keyGenerator( - // object : KeyGenerator { - // override fun getKey(item: Any): Any { - // println("get key of $item") - // return item.toString() - // } - // } - // ) - retry() - retryLimit(4) - } - } - } - } - } - - @Bean - open fun testItemReader(): ItemReader { - return object : ItemReader { - private var count = 0 - - override fun read(): Int? { - if (count < 11) { - return count++ - } else { - return null - } - } - } - } - - @Bean - open fun testItemProcessor(): ItemProcessor { - var tryCount = 0 - - return ItemProcessor { item -> - if (item == 5 && tryCount < 3) { - ++tryCount - throw IllegalStateException("Error (tryCount: $tryCount)") - } - - item.toString() - } - } - - @Bean - open fun testItemWriter(): ItemWriter { - return ItemWriter { items -> - println("write $items") - } - } -} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/faulttolerant/noretry/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/faulttolerant/noretry/SampleApplicationTest.kt deleted file mode 100644 index e7a82736..00000000 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/faulttolerant/noretry/SampleApplicationTest.kt +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Spring Batch Plus - * - * Copyright 2022-present NAVER Corp. - * - * 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 - * - * http://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 com.navercorp.spring.batch.plus.sample.step.chunkorientedstep.faulttolerant.noretry - -import org.junit.jupiter.api.Test -import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher -import org.springframework.beans.factory.getBean -import org.springframework.boot.autoconfigure.SpringBootApplication -import org.springframework.boot.runApplication - -@SpringBootApplication -open class SampleApplicationTest { - @Test - fun run() { - val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() - val job = applicationContext.getBean() - - val jobParameters = JobParametersBuilder() - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) - - assert(BatchStatus.FAILED == jobExecution.status) - println(jobExecution) - } -} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/faulttolerant/noretry/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/faulttolerant/noretry/TestJobConfig.kt deleted file mode 100644 index fa8f3899..00000000 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/faulttolerant/noretry/TestJobConfig.kt +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Spring Batch Plus - * - * Copyright 2022-present NAVER Corp. - * - * 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 - * - * http://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 com.navercorp.spring.batch.plus.sample.step.chunkorientedstep.faulttolerant.noretry - -import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.Job -import org.springframework.batch.item.ItemProcessor -import org.springframework.batch.item.ItemReader -import org.springframework.batch.item.ItemWriter -import org.springframework.context.annotation.Bean -import org.springframework.context.annotation.Configuration -import org.springframework.transaction.PlatformTransactionManager - -@Configuration -open class TestJobConfig( - private val batch: BatchDsl, - private val transactionManager: PlatformTransactionManager, -) { - - @Bean - open fun testJob(): Job = batch { - job("testJob") { - step("testStep") { - chunk(3, transactionManager) { - reader(testItemReader()) - processor(testItemProcessor()) - writer(testItemWriter()) - faultTolerant { - retry() - retryLimit(Int.MAX_VALUE) - noRetry() - } - } - } - } - } - - @Bean - open fun testItemReader(): ItemReader { - return object : ItemReader { - private var count = 0 - - override fun read(): Int? { - if (count < 11) { - return count++ - } else { - return null - } - } - } - } - - @Bean - open fun testItemProcessor(): ItemProcessor { - var tryCount = 0 - - return ItemProcessor { item -> - if (item == 5 && tryCount < 3) { - ++tryCount - throw IllegalArgumentException("I cannot be retried") - } - - item.toString() - } - } - - @Bean - open fun testItemWriter(): ItemWriter { - return ItemWriter { items -> - println("write $items") - } - } -} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/faulttolerant/noskip/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/faulttolerant/noskip/SampleApplicationTest.kt deleted file mode 100644 index 91f09c54..00000000 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/faulttolerant/noskip/SampleApplicationTest.kt +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Spring Batch Plus - * - * Copyright 2022-present NAVER Corp. - * - * 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 - * - * http://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 com.navercorp.spring.batch.plus.sample.step.chunkorientedstep.faulttolerant.noskip - -import org.junit.jupiter.api.Test -import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher -import org.springframework.beans.factory.getBean -import org.springframework.boot.autoconfigure.SpringBootApplication -import org.springframework.boot.runApplication - -@SpringBootApplication -open class SampleApplicationTest { - @Test - fun run() { - val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() - val job = applicationContext.getBean() - - val jobParameters = JobParametersBuilder() - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) - - assert(BatchStatus.FAILED == jobExecution.status) - println(jobExecution) - } -} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/faulttolerant/noskip/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/faulttolerant/noskip/TestJobConfig.kt deleted file mode 100644 index 72bb95ba..00000000 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/faulttolerant/noskip/TestJobConfig.kt +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Spring Batch Plus - * - * Copyright 2022-present NAVER Corp. - * - * 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 - * - * http://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 com.navercorp.spring.batch.plus.sample.step.chunkorientedstep.faulttolerant.noskip - -import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.Job -import org.springframework.batch.item.ItemProcessor -import org.springframework.batch.item.ItemReader -import org.springframework.batch.item.ItemWriter -import org.springframework.context.annotation.Bean -import org.springframework.context.annotation.Configuration -import org.springframework.transaction.PlatformTransactionManager - -@Configuration -open class TestJobConfig( - private val batch: BatchDsl, - private val transactionManager: PlatformTransactionManager, -) { - - @Bean - open fun testJob(): Job = batch { - job("testJob") { - step("testStep") { - chunk(3, transactionManager) { - reader(testItemReader()) - processor(testItemProcessor()) - writer(testItemWriter()) - faultTolerant { - skip() - skipLimit(4) - noSkip() - } - } - } - } - } - - @Bean - open fun testItemReader(): ItemReader { - return object : ItemReader { - private var count = 0 - - override fun read(): Int? { - if (count < 11) { - return count++ - } else { - return null - } - } - } - } - - @Bean - open fun testItemProcessor(): ItemProcessor { - return ItemProcessor { item -> - if (item % 3 == 0) { - throw IllegalStateException("Error") - } - - if (item == 5) { - throw IllegalArgumentException("I cannot be skipped") - } - - item.toString() - } - } - - @Bean - open fun testItemWriter(): ItemWriter { - return ItemWriter { items -> - println("write $items") - } - } -} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/faulttolerant/processornontx/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/faulttolerant/processornontx/SampleApplicationTest.kt deleted file mode 100644 index e790532c..00000000 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/faulttolerant/processornontx/SampleApplicationTest.kt +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Spring Batch Plus - * - * Copyright 2022-present NAVER Corp. - * - * 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 - * - * http://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 com.navercorp.spring.batch.plus.sample.step.chunkorientedstep.faulttolerant.processornontx - -import org.junit.jupiter.api.Test -import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher -import org.springframework.beans.factory.getBean -import org.springframework.boot.autoconfigure.SpringBootApplication -import org.springframework.boot.runApplication - -@SpringBootApplication -open class SampleApplicationTest { - @Test - fun run() { - val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() - val job = applicationContext.getBean() - - val jobParameters = JobParametersBuilder() - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) - - assert(BatchStatus.COMPLETED == jobExecution.status) - println(jobExecution) - } -} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/faulttolerant/processornontx/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/faulttolerant/processornontx/TestJobConfig.kt deleted file mode 100644 index d22ba606..00000000 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/faulttolerant/processornontx/TestJobConfig.kt +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Spring Batch Plus - * - * Copyright 2022-present NAVER Corp. - * - * 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 - * - * http://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 com.navercorp.spring.batch.plus.sample.step.chunkorientedstep.faulttolerant.processornontx - -import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.Job -import org.springframework.batch.item.ItemProcessor -import org.springframework.batch.item.ItemReader -import org.springframework.batch.item.ItemWriter -import org.springframework.context.annotation.Bean -import org.springframework.context.annotation.Configuration -import org.springframework.transaction.PlatformTransactionManager - -@Configuration -open class TestJobConfig( - private val batch: BatchDsl, - private val transactionManager: PlatformTransactionManager, -) { - - @Bean - open fun testJob(): Job = batch { - job("testJob") { - step("testStep") { - chunk(3, transactionManager) { - reader(testItemReader()) - processor(testItemProcessor()) - writer(testItemWriter()) - faultTolerant { - retry() - retryLimit(4) - processorNonTransactional() - } - } - } - } - } - - @Bean - open fun testItemReader(): ItemReader { - return object : ItemReader { - private var count = 0 - - override fun read(): Int? { - if (count < 11) { - val next = count - println("read: $next") - count++ - return next - } else { - return null - } - } - } - } - - @Bean - open fun testItemProcessor(): ItemProcessor { - var tryCount = 0 - - return ItemProcessor { item -> - println("process: $item") - if (item == 5 && tryCount < 3) { - ++tryCount - throw IllegalStateException("Error (tryCount: $tryCount)") - } - - item.toString() - } - } - - @Bean - open fun testItemWriter(): ItemWriter { - return ItemWriter { items -> - println("write $items") - } - } -} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/faulttolerant/retry/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/faulttolerant/retry/SampleApplicationTest.kt index 01c93aeb..e157549c 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/faulttolerant/retry/SampleApplicationTest.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/faulttolerant/retry/SampleApplicationTest.kt @@ -20,9 +20,9 @@ package com.navercorp.spring.batch.plus.sample.step.chunkorientedstep.faulttoler import org.junit.jupiter.api.Test import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator import org.springframework.beans.factory.getBean import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.runApplication @@ -32,12 +32,13 @@ open class SampleApplicationTest { @Test fun run() { val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() + val jobOperator = applicationContext.getBean() val job = applicationContext.getBean() - val jobParameters = JobParametersBuilder() - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) + val jobParameters = + JobParametersBuilder() + .toJobParameters() + val jobExecution = jobOperator.start(job, jobParameters) assert(BatchStatus.COMPLETED == jobExecution.status) println(jobExecution) diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/faulttolerant/retry/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/faulttolerant/retry/TestJobConfig.kt index 6c833749..a62367cc 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/faulttolerant/retry/TestJobConfig.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/faulttolerant/retry/TestJobConfig.kt @@ -19,36 +19,33 @@ package com.navercorp.spring.batch.plus.sample.step.chunkorientedstep.faulttolerant.retry import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.Job -import org.springframework.batch.item.ItemProcessor -import org.springframework.batch.item.ItemReader -import org.springframework.batch.item.ItemWriter +import org.springframework.batch.core.job.Job +import org.springframework.batch.infrastructure.item.ItemProcessor +import org.springframework.batch.infrastructure.item.ItemReader +import org.springframework.batch.infrastructure.item.ItemWriter import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration -import org.springframework.transaction.PlatformTransactionManager @Configuration open class TestJobConfig( private val batch: BatchDsl, - private val transactionManager: PlatformTransactionManager, ) { - @Bean - open fun testJob(): Job = batch { - job("testJob") { - step("testStep") { - chunk(3, transactionManager) { - reader(testItemReader()) - processor(testItemProcessor()) - writer(testItemWriter()) - faultTolerant { + open fun testJob(): Job = + batch { + job("testJob") { + step("testStep") { + chunk(3) { + reader(testItemReader()) + processor(testItemProcessor()) + writer(testItemWriter()) + faultTolerant() retry() - retryLimit(4) + retryLimit(4L) } } } } - } @Bean open fun testItemReader(): ItemReader { @@ -80,9 +77,8 @@ open class TestJobConfig( } @Bean - open fun testItemWriter(): ItemWriter { - return ItemWriter { items -> + open fun testItemWriter(): ItemWriter = + ItemWriter { items -> println("write $items") } - } } diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/faulttolerant/retrycontextcache/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/faulttolerant/retrycontextcache/SampleApplicationTest.kt deleted file mode 100644 index 3d9ea9a8..00000000 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/faulttolerant/retrycontextcache/SampleApplicationTest.kt +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Spring Batch Plus - * - * Copyright 2022-present NAVER Corp. - * - * 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 - * - * http://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 com.navercorp.spring.batch.plus.sample.step.chunkorientedstep.faulttolerant.retrycontextcache - -import org.junit.jupiter.api.Test -import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher -import org.springframework.beans.factory.getBean -import org.springframework.boot.autoconfigure.SpringBootApplication -import org.springframework.boot.runApplication - -@SpringBootApplication -open class SampleApplicationTest { - @Test - fun run() { - val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() - val job = applicationContext.getBean() - - val jobParameters = JobParametersBuilder() - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) - - assert(BatchStatus.COMPLETED == jobExecution.status) - println(jobExecution) - } -} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/faulttolerant/retrycontextcache/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/faulttolerant/retrycontextcache/TestJobConfig.kt deleted file mode 100644 index 5594c49d..00000000 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/faulttolerant/retrycontextcache/TestJobConfig.kt +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Spring Batch Plus - * - * Copyright 2022-present NAVER Corp. - * - * 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 - * - * http://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 com.navercorp.spring.batch.plus.sample.step.chunkorientedstep.faulttolerant.retrycontextcache - -import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.Job -import org.springframework.batch.item.ItemProcessor -import org.springframework.batch.item.ItemReader -import org.springframework.batch.item.ItemWriter -import org.springframework.context.annotation.Bean -import org.springframework.context.annotation.Configuration -import org.springframework.retry.policy.MapRetryContextCache -import org.springframework.transaction.PlatformTransactionManager - -@Configuration -open class TestJobConfig( - private val batch: BatchDsl, - private val transactionManager: PlatformTransactionManager, -) { - - @Bean - open fun testJob(): Job = batch { - job("testJob") { - step("testStep") { - chunk(3, transactionManager) { - reader(testItemReader()) - processor(testItemProcessor()) - writer(testItemWriter()) - faultTolerant { - retry() - retryLimit(4) - retryContextCache( - object : MapRetryContextCache() { - override fun containsKey(key: Any?): Boolean { - println("contains key: $key") - return super.containsKey(key) - } - }, - ) - } - } - } - } - } - - @Bean - open fun testItemReader(): ItemReader { - return object : ItemReader { - private var count = 0 - - override fun read(): Int? { - if (count < 11) { - return count++ - } else { - return null - } - } - } - } - - @Bean - open fun testItemProcessor(): ItemProcessor { - var tryCount = 0 - - return ItemProcessor { item -> - if (item == 5 && tryCount < 3) { - ++tryCount - throw IllegalStateException("Error (tryCount: $tryCount)") - } - - item.toString() - } - } - - @Bean - open fun testItemWriter(): ItemWriter { - return ItemWriter { items -> - println("write $items") - } - } -} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/faulttolerant/retrylistener/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/faulttolerant/retrylistener/SampleApplicationTest.kt index d331387c..9ee88a45 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/faulttolerant/retrylistener/SampleApplicationTest.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/faulttolerant/retrylistener/SampleApplicationTest.kt @@ -20,9 +20,9 @@ package com.navercorp.spring.batch.plus.sample.step.chunkorientedstep.faulttoler import org.junit.jupiter.api.Test import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator import org.springframework.beans.factory.getBean import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.runApplication @@ -32,12 +32,13 @@ open class SampleApplicationTest { @Test fun run() { val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() + val jobOperator = applicationContext.getBean() val job = applicationContext.getBean() - val jobParameters = JobParametersBuilder() - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) + val jobParameters = + JobParametersBuilder() + .toJobParameters() + val jobExecution = jobOperator.start(job, jobParameters) assert(BatchStatus.COMPLETED == jobExecution.status) println(jobExecution) diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/faulttolerant/retrylistener/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/faulttolerant/retrylistener/TestJobConfig.kt index 7f985807..b04cadb1 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/faulttolerant/retrylistener/TestJobConfig.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/faulttolerant/retrylistener/TestJobConfig.kt @@ -19,66 +19,65 @@ package com.navercorp.spring.batch.plus.sample.step.chunkorientedstep.faulttolerant.retrylistener import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.Job -import org.springframework.batch.item.ItemProcessor -import org.springframework.batch.item.ItemReader -import org.springframework.batch.item.ItemWriter +import org.springframework.batch.core.job.Job +import org.springframework.batch.infrastructure.item.ItemProcessor +import org.springframework.batch.infrastructure.item.ItemReader +import org.springframework.batch.infrastructure.item.ItemWriter import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration -import org.springframework.retry.RetryCallback -import org.springframework.retry.RetryContext -import org.springframework.retry.RetryListener -import org.springframework.transaction.PlatformTransactionManager +import org.springframework.core.retry.RetryException +import org.springframework.core.retry.RetryListener +import org.springframework.core.retry.RetryPolicy +import org.springframework.core.retry.RetryState +import org.springframework.core.retry.Retryable @Configuration open class TestJobConfig( private val batch: BatchDsl, - private val transactionManager: PlatformTransactionManager, ) { - @Bean - open fun testJob(): Job = batch { - job("testJob") { - step("testStep") { - chunk(3, transactionManager) { - reader(testItemReader()) - processor(testItemProcessor()) - writer(testItemWriter()) - faultTolerant { - listener( + open fun testJob(): Job = + batch { + job("testJob") { + step("testStep") { + chunk(3) { + reader(testItemReader()) + processor(testItemProcessor()) + writer(testItemWriter()) + faultTolerant() + retryListener( object : RetryListener { - override fun open( - context: RetryContext?, - callback: RetryCallback?, - ): Boolean { - println("RetryListener::open (context: $context") - return true + override fun beforeRetry( + retryPolicy: RetryPolicy, + retryable: Retryable<*>, + retryState: RetryState, + ) { + println("RetryListener::beforeRetry (state: $retryState)") } - override fun close( - context: RetryContext?, - callback: RetryCallback?, - throwable: Throwable?, + override fun onRetryFailure( + retryPolicy: RetryPolicy, + retryable: Retryable<*>, + throwable: Throwable, ) { - println("RetryListener::close (error: ${throwable?.message})") + println("RetryListener::onRetryFailure (error: ${throwable.message})") } - override fun onError( - context: RetryContext?, - callback: RetryCallback?, - throwable: Throwable?, + override fun onRetryPolicyExhaustion( + retryPolicy: RetryPolicy, + retryable: Retryable<*>, + exception: RetryException, ) { - println("RetryListener::onError (error: ${throwable?.message})") + println("RetryListener::onRetryPolicyExhaustion (error: ${exception.message})") } }, ) retry() - retryLimit(4) + retryLimit(4L) } } } } - } @Bean open fun testItemReader(): ItemReader { @@ -110,9 +109,8 @@ open class TestJobConfig( } @Bean - open fun testItemWriter(): ItemWriter { - return ItemWriter { items -> + open fun testItemWriter(): ItemWriter = + ItemWriter { items -> println("write $items") } - } } diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/faulttolerant/retrypolicy/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/faulttolerant/retrypolicy/SampleApplicationTest.kt index 564b41a6..daa1842e 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/faulttolerant/retrypolicy/SampleApplicationTest.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/faulttolerant/retrypolicy/SampleApplicationTest.kt @@ -20,9 +20,9 @@ package com.navercorp.spring.batch.plus.sample.step.chunkorientedstep.faulttoler import org.junit.jupiter.api.Test import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator import org.springframework.beans.factory.getBean import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.runApplication @@ -32,12 +32,13 @@ open class SampleApplicationTest { @Test fun run() { val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() + val jobOperator = applicationContext.getBean() val job = applicationContext.getBean() - val jobParameters = JobParametersBuilder() - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) + val jobParameters = + JobParametersBuilder() + .toJobParameters() + val jobExecution = jobOperator.start(job, jobParameters) assert(BatchStatus.COMPLETED == jobExecution.status) println(jobExecution) diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/faulttolerant/retrypolicy/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/faulttolerant/retrypolicy/TestJobConfig.kt index 13e1ac6d..dd0e9d5a 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/faulttolerant/retrypolicy/TestJobConfig.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/faulttolerant/retrypolicy/TestJobConfig.kt @@ -19,37 +19,34 @@ package com.navercorp.spring.batch.plus.sample.step.chunkorientedstep.faulttolerant.retrypolicy import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.Job -import org.springframework.batch.item.ItemProcessor -import org.springframework.batch.item.ItemReader -import org.springframework.batch.item.ItemWriter +import org.springframework.batch.core.job.Job +import org.springframework.batch.infrastructure.item.ItemProcessor +import org.springframework.batch.infrastructure.item.ItemReader +import org.springframework.batch.infrastructure.item.ItemWriter import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration -import org.springframework.retry.policy.SimpleRetryPolicy -import org.springframework.transaction.PlatformTransactionManager +import org.springframework.core.retry.RetryPolicy @Configuration open class TestJobConfig( private val batch: BatchDsl, - private val transactionManager: PlatformTransactionManager, ) { - @Bean - open fun testJob(): Job = batch { - job("testJob") { - step("testStep") { - chunk(3, transactionManager) { - reader(testItemReader()) - processor(testItemProcessor()) - writer(testItemWriter()) - faultTolerant { + open fun testJob(): Job = + batch { + job("testJob") { + step("testStep") { + chunk(3) { + reader(testItemReader()) + processor(testItemProcessor()) + writer(testItemWriter()) + faultTolerant() retry() - retryPolicy(SimpleRetryPolicy(4)) + retryPolicy(RetryPolicy.withMaxRetries(4)) } } } } - } @Bean open fun testItemReader(): ItemReader { @@ -81,9 +78,8 @@ open class TestJobConfig( } @Bean - open fun testItemWriter(): ItemWriter { - return ItemWriter { items -> + open fun testItemWriter(): ItemWriter = + ItemWriter { items -> println("write $items") } - } } diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/faulttolerant/rollback/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/faulttolerant/rollback/SampleApplicationTest.kt deleted file mode 100644 index 3ca323a0..00000000 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/faulttolerant/rollback/SampleApplicationTest.kt +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Spring Batch Plus - * - * Copyright 2022-present NAVER Corp. - * - * 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 - * - * http://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 com.navercorp.spring.batch.plus.sample.step.chunkorientedstep.faulttolerant.rollback - -import org.junit.jupiter.api.Test -import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher -import org.springframework.beans.factory.getBean -import org.springframework.boot.autoconfigure.SpringBootApplication -import org.springframework.boot.runApplication - -@SpringBootApplication -open class SampleApplicationTest { - @Test - fun run() { - val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() - val job = applicationContext.getBean() - - val jobParameters = JobParametersBuilder() - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) - - assert(BatchStatus.COMPLETED == jobExecution.status) - println(jobExecution) - } -} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/faulttolerant/rollback/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/faulttolerant/rollback/TestJobConfig.kt deleted file mode 100644 index b1536e28..00000000 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/faulttolerant/rollback/TestJobConfig.kt +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Spring Batch Plus - * - * Copyright 2022-present NAVER Corp. - * - * 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 - * - * http://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 com.navercorp.spring.batch.plus.sample.step.chunkorientedstep.faulttolerant.rollback - -import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.Job -import org.springframework.batch.item.ItemProcessor -import org.springframework.batch.item.ItemReader -import org.springframework.batch.item.ItemWriter -import org.springframework.context.annotation.Bean -import org.springframework.context.annotation.Configuration -import org.springframework.transaction.PlatformTransactionManager - -@Configuration -open class TestJobConfig( - private val batch: BatchDsl, - private val transactionManager: PlatformTransactionManager, -) { - - @Bean - open fun testJob(): Job = batch { - job("testJob") { - step("testStep") { - chunk(3, transactionManager) { - reader(testItemReader()) - processor(testItemProcessor()) - writer(testItemWriter()) - faultTolerant { - noRollback() - } - } - } - } - } - - @Bean - open fun testItemReader(): ItemReader { - return object : ItemReader { - private var count = 0 - - override fun read(): Int? { - if (count < 11) { - return count++ - } else { - return null - } - } - } - } - - @Bean - open fun testItemProcessor(): ItemProcessor { - return ItemProcessor { item -> - if (item % 3 == 0) { - throw IllegalStateException("Error") - } - - item.toString() - } - } - - @Bean - open fun testItemWriter(): ItemWriter { - return ItemWriter { items -> - println("write $items") - } - } -} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/faulttolerant/skip/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/faulttolerant/skip/SampleApplicationTest.kt index f516cd40..7482a2ff 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/faulttolerant/skip/SampleApplicationTest.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/faulttolerant/skip/SampleApplicationTest.kt @@ -20,9 +20,9 @@ package com.navercorp.spring.batch.plus.sample.step.chunkorientedstep.faulttoler import org.junit.jupiter.api.Test import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator import org.springframework.beans.factory.getBean import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.runApplication @@ -32,12 +32,13 @@ open class SampleApplicationTest { @Test fun run() { val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() + val jobOperator = applicationContext.getBean() val job = applicationContext.getBean() - val jobParameters = JobParametersBuilder() - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) + val jobParameters = + JobParametersBuilder() + .toJobParameters() + val jobExecution = jobOperator.start(job, jobParameters) assert(BatchStatus.COMPLETED == jobExecution.status) println(jobExecution) diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/faulttolerant/skip/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/faulttolerant/skip/TestJobConfig.kt index 8ded8c2f..7cc2e91b 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/faulttolerant/skip/TestJobConfig.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/faulttolerant/skip/TestJobConfig.kt @@ -19,36 +19,33 @@ package com.navercorp.spring.batch.plus.sample.step.chunkorientedstep.faulttolerant.skip import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.Job -import org.springframework.batch.item.ItemProcessor -import org.springframework.batch.item.ItemReader -import org.springframework.batch.item.ItemWriter +import org.springframework.batch.core.job.Job +import org.springframework.batch.infrastructure.item.ItemProcessor +import org.springframework.batch.infrastructure.item.ItemReader +import org.springframework.batch.infrastructure.item.ItemWriter import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration -import org.springframework.transaction.PlatformTransactionManager @Configuration open class TestJobConfig( private val batch: BatchDsl, - private val transactionManager: PlatformTransactionManager, ) { - @Bean - open fun testJob(): Job = batch { - job("testJob") { - step("testStep") { - chunk(3, transactionManager) { - reader(testItemReader()) - processor(testItemProcessor()) - writer(testItemWriter()) - faultTolerant { + open fun testJob(): Job = + batch { + job("testJob") { + step("testStep") { + chunk(3) { + reader(testItemReader()) + processor(testItemProcessor()) + writer(testItemWriter()) + faultTolerant() skip() - skipLimit(4) + skipLimit(4L) } } } } - } @Bean open fun testItemReader(): ItemReader { @@ -66,20 +63,18 @@ open class TestJobConfig( } @Bean - open fun testItemProcessor(): ItemProcessor { - return ItemProcessor { item -> + open fun testItemProcessor(): ItemProcessor = + ItemProcessor { item -> if (item % 3 == 0) { throw IllegalStateException("Error") } item.toString() } - } @Bean - open fun testItemWriter(): ItemWriter { - return ItemWriter { items -> + open fun testItemWriter(): ItemWriter = + ItemWriter { items -> println("write $items") } - } } diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/faulttolerant/skiplistener/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/faulttolerant/skiplistener/SampleApplicationTest.kt index 4245201d..3cecc75c 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/faulttolerant/skiplistener/SampleApplicationTest.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/faulttolerant/skiplistener/SampleApplicationTest.kt @@ -20,9 +20,9 @@ package com.navercorp.spring.batch.plus.sample.step.chunkorientedstep.faulttoler import org.junit.jupiter.api.Test import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator import org.springframework.beans.factory.getBean import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.runApplication @@ -32,12 +32,13 @@ open class SampleApplicationTest { @Test fun run() { val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() + val jobOperator = applicationContext.getBean() val job = applicationContext.getBean() - val jobParameters = JobParametersBuilder() - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) + val jobParameters = + JobParametersBuilder() + .toJobParameters() + val jobExecution = jobOperator.start(job, jobParameters) assert(BatchStatus.COMPLETED == jobExecution.status) println(jobExecution) diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/faulttolerant/skiplistener/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/faulttolerant/skiplistener/TestJobConfig.kt index e7809578..14ae3cfe 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/faulttolerant/skiplistener/TestJobConfig.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/faulttolerant/skiplistener/TestJobConfig.kt @@ -19,50 +19,53 @@ package com.navercorp.spring.batch.plus.sample.step.chunkorientedstep.faulttolerant.skiplistener import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.Job -import org.springframework.batch.core.SkipListener -import org.springframework.batch.item.ItemProcessor -import org.springframework.batch.item.ItemReader -import org.springframework.batch.item.ItemWriter +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.listener.SkipListener +import org.springframework.batch.infrastructure.item.ItemProcessor +import org.springframework.batch.infrastructure.item.ItemReader +import org.springframework.batch.infrastructure.item.ItemWriter import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration -import org.springframework.transaction.PlatformTransactionManager @Configuration open class TestJobConfig( private val batch: BatchDsl, - private val transactionManager: PlatformTransactionManager, ) { - @Bean - open fun testJob(): Job = batch { - job("testJob") { - step("testStep") { - chunk(3, transactionManager) { - reader(testItemReader()) - processor(testItemProcessor()) - writer(testItemWriter()) - faultTolerant { - listener( + open fun testJob(): Job = + batch { + job("testJob") { + step("testStep") { + chunk(3) { + reader(testItemReader()) + processor(testItemProcessor()) + writer(testItemWriter()) + faultTolerant() + skipListener( object : SkipListener { override fun onSkipInRead(t: Throwable) { println("Ignore exception of read (exception: ${t.message})") } - override fun onSkipInProcess(item: Int, t: Throwable) { + override fun onSkipInProcess( + item: Int, + t: Throwable, + ) { } - override fun onSkipInWrite(item: String, t: Throwable) { + override fun onSkipInWrite( + item: String, + t: Throwable, + ) { } }, ) skip() - skipLimit(1) + skipLimit(1L) } } } } - } @Bean open fun testItemReader(): ItemReader { @@ -86,16 +89,14 @@ open class TestJobConfig( } @Bean - open fun testItemProcessor(): ItemProcessor { - return ItemProcessor { item -> + open fun testItemProcessor(): ItemProcessor = + ItemProcessor { item -> item.toString() } - } @Bean - open fun testItemWriter(): ItemWriter { - return ItemWriter { items -> + open fun testItemWriter(): ItemWriter = + ItemWriter { items -> println("write $items") } - } } diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/faulttolerant/skiplistenerannotation/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/faulttolerant/skiplistenerannotation/SampleApplicationTest.kt index 8c045cea..96541bd8 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/faulttolerant/skiplistenerannotation/SampleApplicationTest.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/faulttolerant/skiplistenerannotation/SampleApplicationTest.kt @@ -20,9 +20,9 @@ package com.navercorp.spring.batch.plus.sample.step.chunkorientedstep.faulttoler import org.junit.jupiter.api.Test import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator import org.springframework.beans.factory.getBean import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.runApplication @@ -32,12 +32,13 @@ open class SampleApplicationTest { @Test fun run() { val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() + val jobOperator = applicationContext.getBean() val job = applicationContext.getBean() - val jobParameters = JobParametersBuilder() - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) + val jobParameters = + JobParametersBuilder() + .toJobParameters() + val jobExecution = jobOperator.start(job, jobParameters) assert(BatchStatus.COMPLETED == jobExecution.status) println(jobExecution) diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/faulttolerant/skiplistenerannotation/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/faulttolerant/skiplistenerannotation/TestJobConfig.kt index 4796bc39..ffebf4af 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/faulttolerant/skiplistenerannotation/TestJobConfig.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/faulttolerant/skiplistenerannotation/TestJobConfig.kt @@ -19,58 +19,62 @@ package com.navercorp.spring.batch.plus.sample.step.chunkorientedstep.faulttolerant.skiplistenerannotation import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.Job import org.springframework.batch.core.annotation.OnSkipInProcess import org.springframework.batch.core.annotation.OnSkipInRead import org.springframework.batch.core.annotation.OnSkipInWrite -import org.springframework.batch.item.ItemProcessor -import org.springframework.batch.item.ItemReader -import org.springframework.batch.item.ItemWriter +import org.springframework.batch.core.job.Job +import org.springframework.batch.infrastructure.item.ItemProcessor +import org.springframework.batch.infrastructure.item.ItemReader +import org.springframework.batch.infrastructure.item.ItemWriter import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration -import org.springframework.transaction.PlatformTransactionManager @Configuration open class TestJobConfig( private val batch: BatchDsl, - private val transactionManager: PlatformTransactionManager, ) { - class TestListener { - @OnSkipInRead fun onSkipInRead(t: Throwable) { println("Ignore exception of read (exception: ${t.message})") } @OnSkipInProcess - fun onSkipInProcess(item: Any, t: Throwable) { + fun onSkipInProcess( + item: Any, + t: Throwable, + ) { println("Ignore exception of process (item: $item, exception: ${t.message})") } @OnSkipInWrite - fun onSkipInWrite(item: Any, t: Throwable) { + fun onSkipInWrite( + item: Any, + t: Throwable, + ) { println("Ignore exception of write (item: $item, exception: ${t.message})") } } @Bean - open fun testJob(): Job = batch { - job("testJob") { - step("testStep") { - chunk(3, transactionManager) { - reader(testItemReader()) - processor(testItemProcessor()) - writer(testItemWriter()) - listener(TestListener()) - faultTolerant { + open fun testJob(): Job = + batch { + job("testJob") { + step("testStep") { + chunk(3) { + reader(testItemReader()) + processor(testItemProcessor()) + writer(testItemWriter()) + // TODO: Keep this pending until annotation-based skip callbacks are observable + // through ChunkOrientedStepBuilder.listener(Object). + listener(TestListener()) + faultTolerant() skip() - skipLimit(1) + skipLimit(1L) } } } } - } @Bean open fun testItemReader(): ItemReader { @@ -94,16 +98,14 @@ open class TestJobConfig( } @Bean - open fun testItemProcessor(): ItemProcessor { - return ItemProcessor { item -> + open fun testItemProcessor(): ItemProcessor = + ItemProcessor { item -> item.toString() } - } @Bean - open fun testItemWriter(): ItemWriter { - return ItemWriter { items -> + open fun testItemWriter(): ItemWriter = + ItemWriter { items -> println("write $items") } - } } diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/faulttolerant/skippolicy/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/faulttolerant/skippolicy/SampleApplicationTest.kt index 32550414..4c77d9a4 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/faulttolerant/skippolicy/SampleApplicationTest.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/faulttolerant/skippolicy/SampleApplicationTest.kt @@ -20,9 +20,9 @@ package com.navercorp.spring.batch.plus.sample.step.chunkorientedstep.faulttoler import org.junit.jupiter.api.Test import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator import org.springframework.beans.factory.getBean import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.runApplication @@ -32,12 +32,13 @@ open class SampleApplicationTest { @Test fun run() { val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() + val jobOperator = applicationContext.getBean() val job = applicationContext.getBean() - val jobParameters = JobParametersBuilder() - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) + val jobParameters = + JobParametersBuilder() + .toJobParameters() + val jobExecution = jobOperator.start(job, jobParameters) assert(BatchStatus.COMPLETED == jobExecution.status) println(jobExecution) diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/faulttolerant/skippolicy/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/faulttolerant/skippolicy/TestJobConfig.kt index 33d387de..353e946a 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/faulttolerant/skippolicy/TestJobConfig.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/faulttolerant/skippolicy/TestJobConfig.kt @@ -19,30 +19,28 @@ package com.navercorp.spring.batch.plus.sample.step.chunkorientedstep.faulttolerant.skippolicy import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.Job +import org.springframework.batch.core.job.Job import org.springframework.batch.core.step.skip.LimitCheckingItemSkipPolicy -import org.springframework.batch.item.ItemProcessor -import org.springframework.batch.item.ItemReader -import org.springframework.batch.item.ItemWriter +import org.springframework.batch.infrastructure.item.ItemProcessor +import org.springframework.batch.infrastructure.item.ItemReader +import org.springframework.batch.infrastructure.item.ItemWriter import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration -import org.springframework.transaction.PlatformTransactionManager @Configuration open class TestJobConfig( private val batch: BatchDsl, - private val transactionManager: PlatformTransactionManager, ) { - @Bean - open fun testJob(): Job = batch { - job("testJob") { - step("testStep") { - chunk(3, transactionManager) { - reader(testItemReader()) - processor(testItemProcessor()) - writer(testItemWriter()) - faultTolerant { + open fun testJob(): Job = + batch { + job("testJob") { + step("testStep") { + chunk(3) { + reader(testItemReader()) + processor(testItemProcessor()) + writer(testItemWriter()) + faultTolerant() skipPolicy( LimitCheckingItemSkipPolicy( 4, @@ -53,7 +51,6 @@ open class TestJobConfig( } } } - } @Bean open fun testItemReader(): ItemReader { @@ -71,20 +68,18 @@ open class TestJobConfig( } @Bean - open fun testItemProcessor(): ItemProcessor { - return ItemProcessor { item -> + open fun testItemProcessor(): ItemProcessor = + ItemProcessor { item -> if (item % 3 == 0) { throw IllegalStateException("Error") } item.toString() } - } @Bean - open fun testItemWriter(): ItemWriter { - return ItemWriter { items -> + open fun testItemWriter(): ItemWriter = + ItemWriter { items -> println("write $items") } - } } diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/repeatoperation/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/repeatoperation/SampleApplicationTest.kt deleted file mode 100644 index 8b3f695c..00000000 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/repeatoperation/SampleApplicationTest.kt +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Spring Batch Plus - * - * Copyright 2022-present NAVER Corp. - * - * 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 - * - * http://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 com.navercorp.spring.batch.plus.sample.step.chunkorientedstep.repeatoperation - -import org.junit.jupiter.api.Test -import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher -import org.springframework.beans.factory.getBean -import org.springframework.boot.autoconfigure.SpringBootApplication -import org.springframework.boot.runApplication - -@SpringBootApplication -open class SampleApplicationTest { - @Test - fun run() { - val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() - val job = applicationContext.getBean() - - val jobParameters = JobParametersBuilder() - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) - - assert(BatchStatus.COMPLETED == jobExecution.status) - println(jobExecution) - } -} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/repeatoperation/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/repeatoperation/TestJobConfig.kt deleted file mode 100644 index c787af12..00000000 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/chunkorientedstep/repeatoperation/TestJobConfig.kt +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Spring Batch Plus - * - * Copyright 2022-present NAVER Corp. - * - * 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 - * - * http://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 com.navercorp.spring.batch.plus.sample.step.chunkorientedstep.repeatoperation - -import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.Job -import org.springframework.batch.item.ItemProcessor -import org.springframework.batch.item.ItemReader -import org.springframework.batch.item.ItemWriter -import org.springframework.batch.repeat.policy.SimpleCompletionPolicy -import org.springframework.batch.repeat.support.RepeatTemplate -import org.springframework.context.annotation.Bean -import org.springframework.context.annotation.Configuration -import org.springframework.transaction.PlatformTransactionManager - -@Configuration -open class TestJobConfig( - private val batch: BatchDsl, - private val transactionManager: PlatformTransactionManager, -) { - - @Bean - open fun testJob(): Job = batch { - job("testJob") { - step("testStep") { - val repeatOperations = RepeatTemplate().apply { - setCompletionPolicy(SimpleCompletionPolicy(3)) - } - chunk(repeatOperations, transactionManager) { - reader(testItemReader()) - processor(testItemProcessor()) - writer(testItemWriter()) - } - } - } - } - - @Bean - open fun testItemReader(): ItemReader { - return object : ItemReader { - private var count = 0 - - override fun read(): Int? { - return if (count < 11) { - count++ - } else { - null - } - } - } - } - - @Bean - open fun testItemProcessor(): ItemProcessor { - return ItemProcessor { item -> - item.toString() - } - } - - @Bean - open fun testItemWriter(): ItemWriter { - return ItemWriter { items -> - println("write $items") - } - } -} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/configuration/README.md b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/configuration/README.md new file mode 100644 index 00000000..30e6bb4d --- /dev/null +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/configuration/README.md @@ -0,0 +1,6 @@ +# Step Config Samples + +## Invariants + +- Every common step configuration option exposed by `StepBuilderDsl` should have + a runnable sample in this package. diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/configuration/allowstartifcomplete/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/configuration/allowstartifcomplete/SampleApplicationTest.kt index 983d572a..e38903b1 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/configuration/allowstartifcomplete/SampleApplicationTest.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/configuration/allowstartifcomplete/SampleApplicationTest.kt @@ -20,9 +20,9 @@ package com.navercorp.spring.batch.plus.sample.step.configuration.allowstartifco import org.junit.jupiter.api.Test import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator import org.springframework.beans.factory.getBean import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.runApplication @@ -32,15 +32,16 @@ open class SampleApplicationTest { @Test fun run() { val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() + val jobOperator = applicationContext.getBean() val job = applicationContext.getBean() - val jobParameters = JobParametersBuilder() - .toJobParameters() + val jobParameters = + JobParametersBuilder() + .toJobParameters() - val firstJobExecution = jobLauncher.run(job, jobParameters) - val secondJobExecution = jobLauncher.run(job, jobParameters) - val thirdJobExecution = jobLauncher.run(job, jobParameters) + val firstJobExecution = jobOperator.start(job, jobParameters) + val secondJobExecution = jobOperator.start(job, jobParameters) + val thirdJobExecution = jobOperator.start(job, jobParameters) // always alwaysRunStep is invoked assert(BatchStatus.FAILED == firstJobExecution.status) diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/configuration/allowstartifcomplete/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/configuration/allowstartifcomplete/TestJobConfig.kt index a6f28932..3413569c 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/configuration/allowstartifcomplete/TestJobConfig.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/configuration/allowstartifcomplete/TestJobConfig.kt @@ -19,8 +19,8 @@ package com.navercorp.spring.batch.plus.sample.step.configuration.allowstartifcomplete import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.Job -import org.springframework.batch.repeat.RepeatStatus +import org.springframework.batch.core.job.Job +import org.springframework.batch.infrastructure.repeat.RepeatStatus import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.transaction.PlatformTransactionManager @@ -30,28 +30,28 @@ open class TestJobConfig( private val batch: BatchDsl, private val transactionManager: PlatformTransactionManager, ) { - @Bean - open fun testJob(): Job = batch { - job("testJob") { - step("alwaysRunStep") { - allowStartIfComplete(true) - tasklet( - { _, _ -> - println("always run") - RepeatStatus.FINISHED - }, - transactionManager, - ) - } - step("alwaysFailsStep") { - tasklet( - { _, _ -> - throw IllegalStateException("always failed") - }, - transactionManager, - ) + open fun testJob(): Job = + batch { + job("testJob") { + step("alwaysRunStep") { + allowStartIfComplete(true) + tasklet( + { _, _ -> + println("always run") + RepeatStatus.FINISHED + }, + transactionManager, + ) + } + step("alwaysFailsStep") { + tasklet( + { _, _ -> + throw IllegalStateException("always failed") + }, + transactionManager, + ) + } } } - } } diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/configuration/listenerannotation/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/configuration/listenerannotation/SampleApplicationTest.kt index a855a183..c1602e2e 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/configuration/listenerannotation/SampleApplicationTest.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/configuration/listenerannotation/SampleApplicationTest.kt @@ -20,9 +20,9 @@ package com.navercorp.spring.batch.plus.sample.step.configuration.listenerannota import org.junit.jupiter.api.Test import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator import org.springframework.beans.factory.getBean import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.runApplication @@ -32,12 +32,13 @@ open class SampleApplicationTest { @Test fun run() { val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() + val jobOperator = applicationContext.getBean() val job = applicationContext.getBean() - val jobParameters = JobParametersBuilder() - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) + val jobParameters = + JobParametersBuilder() + .toJobParameters() + val jobExecution = jobOperator.start(job, jobParameters) assert(BatchStatus.COMPLETED == jobExecution.status) println(jobExecution) diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/configuration/listenerannotation/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/configuration/listenerannotation/TestJobConfig.kt index 01f71c01..10701b12 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/configuration/listenerannotation/TestJobConfig.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/configuration/listenerannotation/TestJobConfig.kt @@ -19,10 +19,10 @@ package com.navercorp.spring.batch.plus.sample.step.configuration.listenerannotation import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.Job import org.springframework.batch.core.annotation.AfterStep import org.springframework.batch.core.annotation.BeforeStep -import org.springframework.batch.repeat.RepeatStatus +import org.springframework.batch.core.job.Job +import org.springframework.batch.infrastructure.repeat.RepeatStatus import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.transaction.PlatformTransactionManager @@ -32,7 +32,6 @@ open class TestJobConfig( private val batch: BatchDsl, private val transactionManager: PlatformTransactionManager, ) { - class TestListener { @BeforeStep fun beforeStep() { @@ -46,12 +45,13 @@ open class TestJobConfig( } @Bean - open fun testJob(): Job = batch { - job("testJob") { - step("testStep") { - listener(TestListener()) - tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + open fun testJob(): Job = + batch { + job("testJob") { + step("testStep") { + listener(TestListener()) + tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + } } } - } } diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/configuration/listenerobject/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/configuration/listenerobject/SampleApplicationTest.kt index d6ab8751..2950ac9e 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/configuration/listenerobject/SampleApplicationTest.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/configuration/listenerobject/SampleApplicationTest.kt @@ -20,9 +20,9 @@ package com.navercorp.spring.batch.plus.sample.step.configuration.listenerobject import org.junit.jupiter.api.Test import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator import org.springframework.beans.factory.getBean import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.runApplication @@ -32,12 +32,13 @@ open class SampleApplicationTest { @Test fun run() { val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() + val jobOperator = applicationContext.getBean() val job = applicationContext.getBean() - val jobParameters = JobParametersBuilder() - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) + val jobParameters = + JobParametersBuilder() + .toJobParameters() + val jobExecution = jobOperator.start(job, jobParameters) assert(BatchStatus.COMPLETED == jobExecution.status) println(jobExecution) diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/configuration/listenerobject/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/configuration/listenerobject/TestJobConfig.kt index 36c4c96e..60256c80 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/configuration/listenerobject/TestJobConfig.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/configuration/listenerobject/TestJobConfig.kt @@ -20,10 +20,10 @@ package com.navercorp.spring.batch.plus.sample.step.configuration.listenerobject import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl import org.springframework.batch.core.ExitStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.StepExecution -import org.springframework.batch.core.StepExecutionListener -import org.springframework.batch.repeat.RepeatStatus +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.listener.StepExecutionListener +import org.springframework.batch.core.step.StepExecution +import org.springframework.batch.infrastructure.repeat.RepeatStatus import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.transaction.PlatformTransactionManager @@ -33,25 +33,25 @@ open class TestJobConfig( private val batch: BatchDsl, private val transactionManager: PlatformTransactionManager, ) { - @Bean - open fun testJob(): Job = batch { - job("testJob") { - step("testStep") { - listener( - object : StepExecutionListener { - override fun beforeStep(stepExecution: StepExecution) { - println("beforeStep") - } + open fun testJob(): Job = + batch { + job("testJob") { + step("testStep") { + listener( + object : StepExecutionListener { + override fun beforeStep(stepExecution: StepExecution) { + println("beforeStep") + } - override fun afterStep(stepExecution: StepExecution): ExitStatus? { - println("afterStep") - return null - } - }, - ) - tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + override fun afterStep(stepExecution: StepExecution): ExitStatus? { + println("afterStep") + return null + } + }, + ) + tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + } } } - } } diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/configuration/meterregistry/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/configuration/meterregistry/SampleApplicationTest.kt deleted file mode 100644 index 510e1802..00000000 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/configuration/meterregistry/SampleApplicationTest.kt +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Spring Batch Plus - * - * Copyright 2022-present NAVER Corp. - * - * 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 - * - * http://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 com.navercorp.spring.batch.plus.sample.step.configuration.meterregistry - -import org.junit.jupiter.api.Test -import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher -import org.springframework.beans.factory.getBean -import org.springframework.boot.autoconfigure.SpringBootApplication -import org.springframework.boot.runApplication - -@SpringBootApplication -open class SampleApplicationTest { - @Test - fun run() { - val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() - val job = applicationContext.getBean() - - val jobParameters = JobParametersBuilder() - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) - - assert(BatchStatus.COMPLETED == jobExecution.status) - println(jobExecution) - } -} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/configuration/observationconvention/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/configuration/observationconvention/SampleApplicationTest.kt deleted file mode 100644 index 110eb2d0..00000000 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/configuration/observationconvention/SampleApplicationTest.kt +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Spring Batch Plus - * - * Copyright 2022-present NAVER Corp. - * - * 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 - * - * http://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 com.navercorp.spring.batch.plus.sample.step.configuration.observationconvention - -import org.junit.jupiter.api.Test -import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher -import org.springframework.beans.factory.getBean -import org.springframework.boot.autoconfigure.SpringBootApplication -import org.springframework.boot.runApplication - -@SpringBootApplication -open class SampleApplicationTest { - @Test - fun run() { - val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() - val job = applicationContext.getBean() - - val jobParameters = JobParametersBuilder() - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) - - assert(BatchStatus.COMPLETED == jobExecution.status) - println(jobExecution) - } -} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/configuration/observationconvention/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/configuration/observationconvention/TestJobConfig.kt deleted file mode 100644 index 36a6adb8..00000000 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/configuration/observationconvention/TestJobConfig.kt +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Spring Batch Plus - * - * Copyright 2022-present NAVER Corp. - * - * 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 - * - * http://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 com.navercorp.spring.batch.plus.sample.step.configuration.observationconvention - -import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.Job -import org.springframework.batch.core.observability.DefaultBatchStepObservationConvention -import org.springframework.batch.repeat.RepeatStatus -import org.springframework.context.annotation.Bean -import org.springframework.context.annotation.Configuration -import org.springframework.transaction.PlatformTransactionManager - -@Configuration -open class TestJobConfig( - private val batch: BatchDsl, - private val transactionManager: PlatformTransactionManager, -) { - - @Bean - open fun testJob(): Job = batch { - job("testJob") { - step("testStep") { - observationConvention(DefaultBatchStepObservationConvention()) - tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) - } - } - } -} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/configuration/observationregistry/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/configuration/observationregistry/SampleApplicationTest.kt index 39320822..c6764b6b 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/configuration/observationregistry/SampleApplicationTest.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/configuration/observationregistry/SampleApplicationTest.kt @@ -20,9 +20,9 @@ package com.navercorp.spring.batch.plus.sample.step.configuration.observationreg import org.junit.jupiter.api.Test import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator import org.springframework.beans.factory.getBean import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.runApplication @@ -32,12 +32,13 @@ open class SampleApplicationTest { @Test fun run() { val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() + val jobOperator = applicationContext.getBean() val job = applicationContext.getBean() - val jobParameters = JobParametersBuilder() - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) + val jobParameters = + JobParametersBuilder() + .toJobParameters() + val jobExecution = jobOperator.start(job, jobParameters) assert(BatchStatus.COMPLETED == jobExecution.status) println(jobExecution) diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/configuration/observationregistry/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/configuration/observationregistry/TestJobConfig.kt index d8ba114a..73eceba6 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/configuration/observationregistry/TestJobConfig.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/configuration/observationregistry/TestJobConfig.kt @@ -20,8 +20,8 @@ package com.navercorp.spring.batch.plus.sample.step.configuration.observationreg import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl import io.micrometer.observation.ObservationRegistry -import org.springframework.batch.core.Job -import org.springframework.batch.repeat.RepeatStatus +import org.springframework.batch.core.job.Job +import org.springframework.batch.infrastructure.repeat.RepeatStatus import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.transaction.PlatformTransactionManager @@ -31,14 +31,14 @@ open class TestJobConfig( private val batch: BatchDsl, private val transactionManager: PlatformTransactionManager, ) { - @Bean - open fun testJob(): Job = batch { - job("testJob") { - step("testStep") { - observationRegistry(ObservationRegistry.create()) - tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + open fun testJob(): Job = + batch { + job("testJob") { + step("testStep") { + observationRegistry(ObservationRegistry.create()) + tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + } } } - } } diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/configuration/startlimit/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/configuration/startlimit/SampleApplicationTest.kt index e357a5bc..b6818c47 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/configuration/startlimit/SampleApplicationTest.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/configuration/startlimit/SampleApplicationTest.kt @@ -20,9 +20,9 @@ package com.navercorp.spring.batch.plus.sample.step.configuration.startlimit import org.junit.jupiter.api.Test import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator import org.springframework.beans.factory.getBean import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.runApplication @@ -32,16 +32,17 @@ open class SampleApplicationTest { @Test fun run() { val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() + val jobOperator = applicationContext.getBean() val job = applicationContext.getBean() - val jobParameters = JobParametersBuilder() - .toJobParameters() + val jobParameters = + JobParametersBuilder() + .toJobParameters() // failed - val firstJobExecution = jobLauncher.run(job, jobParameters) - val secondJobExecution = jobLauncher.run(job, jobParameters) - val thirdJobExecution = jobLauncher.run(job, jobParameters) + val firstJobExecution = jobOperator.start(job, jobParameters) + val secondJobExecution = jobOperator.start(job, jobParameters) + val thirdJobExecution = jobOperator.start(job, jobParameters) assert(BatchStatus.FAILED == firstJobExecution.status) println(firstJobExecution) diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/configuration/startlimit/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/configuration/startlimit/TestJobConfig.kt index fd3e71d6..44303111 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/configuration/startlimit/TestJobConfig.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/configuration/startlimit/TestJobConfig.kt @@ -19,8 +19,8 @@ package com.navercorp.spring.batch.plus.sample.step.configuration.startlimit import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.Job -import org.springframework.batch.repeat.RepeatStatus +import org.springframework.batch.core.job.Job +import org.springframework.batch.infrastructure.repeat.RepeatStatus import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.transaction.PlatformTransactionManager @@ -30,24 +30,24 @@ open class TestJobConfig( private val batch: BatchDsl, private val transactionManager: PlatformTransactionManager, ) { - private var count = 0 @Bean - open fun testJob(): Job = batch { - job("testJob") { - step("testStep") { - startLimit(2) - tasklet( - { _, _ -> - if (count < 2) { - throw IllegalStateException("count is less than 2 (count: ${count++})") - } - RepeatStatus.FINISHED - }, - transactionManager, - ) + open fun testJob(): Job = + batch { + job("testJob") { + step("testStep") { + startLimit(2) + tasklet( + { _, _ -> + if (count < 2) { + throw IllegalStateException("count is less than 2 (count: ${count++})") + } + RepeatStatus.FINISHED + }, + transactionManager, + ) + } } } - } } diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/creation/README.md b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/creation/README.md new file mode 100644 index 00000000..076d952a --- /dev/null +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/creation/README.md @@ -0,0 +1,6 @@ +# Step Creation Samples + +## Invariants + +- Generic step creation examples from the Kotlin DSL step guide should have a + runnable sample in this package. diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/creation/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/creation/SampleApplicationTest.kt index 3b6a0020..a6996f06 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/creation/SampleApplicationTest.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/creation/SampleApplicationTest.kt @@ -20,9 +20,9 @@ package com.navercorp.spring.batch.plus.sample.step.creation import org.junit.jupiter.api.Test import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator import org.springframework.beans.factory.getBean import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.runApplication @@ -32,12 +32,13 @@ open class SampleApplicationTest { @Test fun run() { val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() + val jobOperator = applicationContext.getBean() val job = applicationContext.getBean() - val jobParameters = JobParametersBuilder() - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) + val jobParameters = + JobParametersBuilder() + .toJobParameters() + val jobExecution = jobOperator.start(job, jobParameters) assert(BatchStatus.COMPLETED == jobExecution.status) println(jobExecution) diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/creation/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/creation/TestJobConfig.kt index b1cb3a07..3b6a06aa 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/creation/TestJobConfig.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/creation/TestJobConfig.kt @@ -19,8 +19,8 @@ package com.navercorp.spring.batch.plus.sample.step.creation import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.Job -import org.springframework.batch.repeat.RepeatStatus +import org.springframework.batch.core.job.Job +import org.springframework.batch.infrastructure.repeat.RepeatStatus import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.transaction.PlatformTransactionManager @@ -30,39 +30,41 @@ open class TestJobConfig( private val batch: BatchDsl, private val transactionManager: PlatformTransactionManager, ) { - @Bean - open fun testJob(): Job = batch { - job("testJob") { - // within job - step("testStep1") { - tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + open fun testJob(): Job = + batch { + job("testJob") { + // within job + step("testStep1") { + tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + } + step("testStep2") { + tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + } + flow(testFlow()) + step(testStep()) } - step("testStep2") { - tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) - } - flow(testFlow()) - step(testStep()) } - } @Bean - open fun testStep() = batch { - step("testStep") { - tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + open fun testStep() = + batch { + step("testStep") { + tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + } } - } @Bean - open fun testFlow() = batch { - flow("testFlow") { - // within flow - step("flowStep1") { - tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) - } - step("flowStep2") { - tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + open fun testFlow() = + batch { + flow("testFlow") { + // within flow + step("flowStep1") { + tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + } + step("flowStep2") { + tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + } } } - } } diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/flowstep/bean/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/flowstep/bean/SampleApplicationTest.kt deleted file mode 100644 index 3e85270a..00000000 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/flowstep/bean/SampleApplicationTest.kt +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Spring Batch Plus - * - * Copyright 2022-present NAVER Corp. - * - * 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 - * - * http://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 com.navercorp.spring.batch.plus.sample.step.flowstep.bean - -import org.junit.jupiter.api.Test -import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher -import org.springframework.beans.factory.getBean -import org.springframework.boot.autoconfigure.SpringBootApplication -import org.springframework.boot.runApplication - -@SpringBootApplication -open class SampleApplicationTest { - @Test - fun run() { - val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() - val job = applicationContext.getBean() - - val jobParameters = JobParametersBuilder() - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) - - assert(BatchStatus.COMPLETED == jobExecution.status) - println(jobExecution) - } -} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/flowstep/creation/README.md b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/flowstep/creation/README.md new file mode 100644 index 00000000..f4ed4628 --- /dev/null +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/flowstep/creation/README.md @@ -0,0 +1,6 @@ +# Flow Step Creation Samples + +## Invariants + +- Every supported way to create a flow step with the Kotlin DSL should have a + runnable sample in this package. diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/flowstep/creation/bean/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/flowstep/creation/bean/SampleApplicationTest.kt new file mode 100644 index 00000000..8744fe4d --- /dev/null +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/flowstep/creation/bean/SampleApplicationTest.kt @@ -0,0 +1,46 @@ +/* + * Spring Batch Plus + * + * Copyright 2022-present NAVER Corp. + * + * 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 + * + * http://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 com.navercorp.spring.batch.plus.sample.step.flowstep.creation.bean + +import org.junit.jupiter.api.Test +import org.springframework.batch.core.BatchStatus +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator +import org.springframework.beans.factory.getBean +import org.springframework.boot.autoconfigure.SpringBootApplication +import org.springframework.boot.runApplication + +@SpringBootApplication +open class SampleApplicationTest { + @Test + fun run() { + val applicationContext = runApplication() + val jobOperator = applicationContext.getBean() + val job = applicationContext.getBean() + + val jobParameters = + JobParametersBuilder() + .toJobParameters() + val jobExecution = jobOperator.start(job, jobParameters) + + assert(BatchStatus.COMPLETED == jobExecution.status) + println(jobExecution) + } +} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/flowstep/creation/bean/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/flowstep/creation/bean/TestJobConfig.kt new file mode 100644 index 00000000..442f6abb --- /dev/null +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/flowstep/creation/bean/TestJobConfig.kt @@ -0,0 +1,53 @@ +/* + * Spring Batch Plus + * + * Copyright 2022-present NAVER Corp. + * + * 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 + * + * http://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 com.navercorp.spring.batch.plus.sample.step.flowstep.creation.bean + +import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.flow.Flow +import org.springframework.batch.infrastructure.repeat.RepeatStatus +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import org.springframework.transaction.PlatformTransactionManager + +@Configuration +open class TestJobConfig( + private val batch: BatchDsl, + private val transactionManager: PlatformTransactionManager, +) { + @Bean + open fun testJob(): Job = + batch { + job("testJob") { + step("testStep") { + flowBean("anotherFlow") + } + } + } + + @Bean + open fun anotherFlow(): Flow = + batch { + flow("anotherFlow") { + step("anotherFlowStep") { + tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + } + } + } +} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/flowstep/creation/init/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/flowstep/creation/init/SampleApplicationTest.kt new file mode 100644 index 00000000..8d584edc --- /dev/null +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/flowstep/creation/init/SampleApplicationTest.kt @@ -0,0 +1,46 @@ +/* + * Spring Batch Plus + * + * Copyright 2022-present NAVER Corp. + * + * 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 + * + * http://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 com.navercorp.spring.batch.plus.sample.step.flowstep.creation.init + +import org.junit.jupiter.api.Test +import org.springframework.batch.core.BatchStatus +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator +import org.springframework.beans.factory.getBean +import org.springframework.boot.autoconfigure.SpringBootApplication +import org.springframework.boot.runApplication + +@SpringBootApplication +open class SampleApplicationTest { + @Test + fun run() { + val applicationContext = runApplication() + val jobOperator = applicationContext.getBean() + val job = applicationContext.getBean() + + val jobParameters = + JobParametersBuilder() + .toJobParameters() + val jobExecution = jobOperator.start(job, jobParameters) + + assert(BatchStatus.COMPLETED == jobExecution.status) + println(jobExecution) + } +} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/flowstep/init/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/flowstep/creation/init/TestJobConfig.kt similarity index 68% rename from spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/flowstep/init/TestJobConfig.kt rename to spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/flowstep/creation/init/TestJobConfig.kt index a401c30e..55ba6c1b 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/flowstep/init/TestJobConfig.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/flowstep/creation/init/TestJobConfig.kt @@ -16,11 +16,11 @@ * limitations under the License. */ -package com.navercorp.spring.batch.plus.sample.step.flowstep.init +package com.navercorp.spring.batch.plus.sample.step.flowstep.creation.init import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.Job -import org.springframework.batch.repeat.RepeatStatus +import org.springframework.batch.core.job.Job +import org.springframework.batch.infrastructure.repeat.RepeatStatus import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.transaction.PlatformTransactionManager @@ -30,17 +30,17 @@ open class TestJobConfig( private val batch: BatchDsl, private val transactionManager: PlatformTransactionManager, ) { - @Bean - open fun testJob(): Job = batch { - job("testJob") { - step("testStep") { - flow("anotherFlow") { - step("anotherFlowStep") { - tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + open fun testJob(): Job = + batch { + job("testJob") { + step("testStep") { + flow("anotherFlow") { + step("anotherFlowStep") { + tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + } } } } } - } } diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/flowstep/creation/variable/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/flowstep/creation/variable/SampleApplicationTest.kt new file mode 100644 index 00000000..8ba26d59 --- /dev/null +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/flowstep/creation/variable/SampleApplicationTest.kt @@ -0,0 +1,46 @@ +/* + * Spring Batch Plus + * + * Copyright 2022-present NAVER Corp. + * + * 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 + * + * http://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 com.navercorp.spring.batch.plus.sample.step.flowstep.creation.variable + +import org.junit.jupiter.api.Test +import org.springframework.batch.core.BatchStatus +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator +import org.springframework.beans.factory.getBean +import org.springframework.boot.autoconfigure.SpringBootApplication +import org.springframework.boot.runApplication + +@SpringBootApplication +open class SampleApplicationTest { + @Test + fun run() { + val applicationContext = runApplication() + val jobOperator = applicationContext.getBean() + val job = applicationContext.getBean() + + val jobParameters = + JobParametersBuilder() + .toJobParameters() + val jobExecution = jobOperator.start(job, jobParameters) + + assert(BatchStatus.COMPLETED == jobExecution.status) + println(jobExecution) + } +} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/flowstep/creation/variable/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/flowstep/creation/variable/TestJobConfig.kt new file mode 100644 index 00000000..2c244549 --- /dev/null +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/flowstep/creation/variable/TestJobConfig.kt @@ -0,0 +1,53 @@ +/* + * Spring Batch Plus + * + * Copyright 2022-present NAVER Corp. + * + * 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 + * + * http://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 com.navercorp.spring.batch.plus.sample.step.flowstep.creation.variable + +import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.flow.Flow +import org.springframework.batch.infrastructure.repeat.RepeatStatus +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import org.springframework.transaction.PlatformTransactionManager + +@Configuration +open class TestJobConfig( + private val batch: BatchDsl, + private val transactionManager: PlatformTransactionManager, +) { + @Bean + open fun testJob(): Job = + batch { + job("testJob") { + step("testStep") { + flow(anotherFlow()) + } + } + } + + @Bean + open fun anotherFlow(): Flow = + batch { + flow("anotherFlow") { + step("anotherFlowStep") { + tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + } + } + } +} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/flowstep/init/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/flowstep/init/SampleApplicationTest.kt deleted file mode 100644 index 8c75ad8a..00000000 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/flowstep/init/SampleApplicationTest.kt +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Spring Batch Plus - * - * Copyright 2022-present NAVER Corp. - * - * 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 - * - * http://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 com.navercorp.spring.batch.plus.sample.step.flowstep.init - -import org.junit.jupiter.api.Test -import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher -import org.springframework.beans.factory.getBean -import org.springframework.boot.autoconfigure.SpringBootApplication -import org.springframework.boot.runApplication - -@SpringBootApplication -open class SampleApplicationTest { - @Test - fun run() { - val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() - val job = applicationContext.getBean() - - val jobParameters = JobParametersBuilder() - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) - - assert(BatchStatus.COMPLETED == jobExecution.status) - println(jobExecution) - } -} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/flowstep/variable/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/flowstep/variable/SampleApplicationTest.kt deleted file mode 100644 index 664a213e..00000000 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/flowstep/variable/SampleApplicationTest.kt +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Spring Batch Plus - * - * Copyright 2022-present NAVER Corp. - * - * 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 - * - * http://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 com.navercorp.spring.batch.plus.sample.step.flowstep.variable - -import org.junit.jupiter.api.Test -import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher -import org.springframework.beans.factory.getBean -import org.springframework.boot.autoconfigure.SpringBootApplication -import org.springframework.boot.runApplication - -@SpringBootApplication -open class SampleApplicationTest { - @Test - fun run() { - val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() - val job = applicationContext.getBean() - - val jobParameters = JobParametersBuilder() - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) - - assert(BatchStatus.COMPLETED == jobExecution.status) - println(jobExecution) - } -} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/jobstep/bean/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/jobstep/bean/TestJobConfig.kt deleted file mode 100644 index d4a8806c..00000000 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/jobstep/bean/TestJobConfig.kt +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Spring Batch Plus - * - * Copyright 2022-present NAVER Corp. - * - * 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 - * - * http://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 com.navercorp.spring.batch.plus.sample.step.jobstep.bean - -import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.Job -import org.springframework.batch.repeat.RepeatStatus -import org.springframework.context.annotation.Bean -import org.springframework.context.annotation.Configuration -import org.springframework.transaction.PlatformTransactionManager - -@Configuration -open class TestJobConfig( - private val batch: BatchDsl, - private val transactionManager: PlatformTransactionManager, -) { - - @Bean - open fun testJob(): Job = batch { - job("testJob") { - step("testStep") { - jobBean("anotherJob") - } - } - } - - @Bean - open fun anotherJob() = batch { - job("anotherJob") { - step("anotherJobStep") { - tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) - } - } - } -} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/jobstep/config/README.md b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/jobstep/config/README.md new file mode 100644 index 00000000..ab1336f6 --- /dev/null +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/jobstep/config/README.md @@ -0,0 +1,6 @@ +# Job Step Config Samples + +## Invariants + +- Every job step configuration option exposed by the Kotlin DSL should have a + runnable sample in this package. diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/jobstep/config/extractor/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/jobstep/config/extractor/SampleApplicationTest.kt index efc94346..781db97e 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/jobstep/config/extractor/SampleApplicationTest.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/jobstep/config/extractor/SampleApplicationTest.kt @@ -20,9 +20,9 @@ package com.navercorp.spring.batch.plus.sample.step.jobstep.config.extractor import org.junit.jupiter.api.Test import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator import org.springframework.beans.factory.getBean import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.runApplication @@ -32,13 +32,14 @@ open class SampleApplicationTest { @Test fun run() { val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() + val jobOperator = applicationContext.getBean() val job = applicationContext.getBean("testJob") - val jobParameters = JobParametersBuilder() - .addString("test", "tt") - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) + val jobParameters = + JobParametersBuilder() + .addString("test", "tt") + .toJobParameters() + val jobExecution = jobOperator.start(job, jobParameters) assert(BatchStatus.COMPLETED == jobExecution.status) println(jobExecution) diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/jobstep/config/extractor/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/jobstep/config/extractor/TestJobConfig.kt index c8c0ac45..c60714f1 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/jobstep/config/extractor/TestJobConfig.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/jobstep/config/extractor/TestJobConfig.kt @@ -19,9 +19,9 @@ package com.navercorp.spring.batch.plus.sample.step.jobstep.config.extractor import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.repeat.RepeatStatus +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.infrastructure.repeat.RepeatStatus import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.transaction.PlatformTransactionManager @@ -31,38 +31,45 @@ open class TestJobConfig( private val batch: BatchDsl, private val transactionManager: PlatformTransactionManager, ) { - @Bean - open fun testJob(): Job = batch { - job("testJob") { - step("testStep") { - job(anotherJob()) { - parametersExtractor { _, _ -> - JobParametersBuilder() - .addString("extra", "value") - .toJobParameters() + open fun testJob(): Job = + batch { + job("testJob") { + step("testStep") { + job(anotherJob()) { + parametersExtractor { _, _ -> + JobParametersBuilder() + .addString("extra", "value") + .toJobParameters() + } + // same as + // parametersExtractor( + // object : JobParametersExtractor { + // override fun getJobParameters(job: Job, stepExecution: StepExecution): JobParameters { + // return JobParametersBuilder() + // .addString("extra", "value") + // .toJobParameters() + // } + // } + // ) } - // same as - // parametersExtractor( - // object : JobParametersExtractor { - // override fun getJobParameters(job: Job, stepExecution: StepExecution): JobParameters { - // return JobParametersBuilder() - // .addString("extra", "value") - // .toJobParameters() - // } - // } - // ) } } } - } @Bean - open fun anotherJob() = batch { - job("anotherJob") { - step("anotherJobStep") { - tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + open fun anotherJob() = + batch { + job("anotherJob") { + step("anotherJobStep") { + tasklet( + { contribution, _ -> + println("extra: '${contribution.stepExecution.jobParameters.getString("extra")}'") + RepeatStatus.FINISHED + }, + transactionManager, + ) + } } } - } } diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/jobstep/config/launcher/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/jobstep/config/operator/SampleApplicationTest.kt similarity index 75% rename from spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/jobstep/config/launcher/SampleApplicationTest.kt rename to spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/jobstep/config/operator/SampleApplicationTest.kt index 7a7c9092..670d85b0 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/jobstep/config/launcher/SampleApplicationTest.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/jobstep/config/operator/SampleApplicationTest.kt @@ -16,13 +16,13 @@ * limitations under the License. */ -package com.navercorp.spring.batch.plus.sample.step.jobstep.config.launcher +package com.navercorp.spring.batch.plus.sample.step.jobstep.config.operator import org.junit.jupiter.api.Test import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator import org.springframework.beans.factory.getBean import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.runApplication @@ -32,12 +32,13 @@ open class SampleApplicationTest { @Test fun run() { val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() + val jobOperator = applicationContext.getBean() val job = applicationContext.getBean("testJob") - val jobParameters = JobParametersBuilder() - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) + val jobParameters = + JobParametersBuilder() + .toJobParameters() + val jobExecution = jobOperator.start(job, jobParameters) assert(BatchStatus.COMPLETED == jobExecution.status) println(jobExecution) diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/jobstep/config/launcher/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/jobstep/config/operator/TestJobConfig.kt similarity index 50% rename from spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/jobstep/config/launcher/TestJobConfig.kt rename to spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/jobstep/config/operator/TestJobConfig.kt index 8c9cc291..c4996f8f 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/jobstep/config/launcher/TestJobConfig.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/jobstep/config/operator/TestJobConfig.kt @@ -16,12 +16,14 @@ * limitations under the License. */ -package com.navercorp.spring.batch.plus.sample.step.jobstep.config.launcher +package com.navercorp.spring.batch.plus.sample.step.jobstep.config.operator import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.Job -import org.springframework.batch.core.launch.JobLauncher -import org.springframework.batch.repeat.RepeatStatus +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.JobExecution +import org.springframework.batch.core.job.parameters.JobParameters +import org.springframework.batch.core.launch.JobOperator +import org.springframework.batch.infrastructure.repeat.RepeatStatus import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.transaction.PlatformTransactionManager @@ -30,38 +32,38 @@ import org.springframework.transaction.PlatformTransactionManager open class TestJobConfig( private val batch: BatchDsl, private val transactionManager: PlatformTransactionManager, - private val jobLauncher: JobLauncher, + private val jobOperator: JobOperator, ) { - @Bean - open fun testJob(): Job = batch { - job("testJob") { - step("testStep") { - job(anotherJob()) { - launcher { job, jobParameters -> - println("launch anotherJob!!!") - jobLauncher.run(job, jobParameters) + open fun testJob(): Job = + batch { + job("testJob") { + step("testStep") { + job(anotherJob()) { + operator(loggingJobOperator(jobOperator)) } - // same as - // launcher( - // object : JobLauncher { - // override fun run(job: Job, jobParameters: JobParameters): JobExecution { - // println("launch anotherJob!!!") - // return jobLauncher.run(job, jobParameters) - // } - // } - // ) } } } - } + + private fun loggingJobOperator(delegate: JobOperator): JobOperator = + object : JobOperator by delegate { + override fun start( + job: Job, + jobParameters: JobParameters, + ): JobExecution { + println("launch ${job.name}!!!") + return delegate.start(job, jobParameters) + } + } @Bean - open fun anotherJob() = batch { - job("anotherJob") { - step("anotherJobStep") { - tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + open fun anotherJob() = + batch { + job("anotherJob") { + step("anotherJobStep") { + tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + } } } - } } diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/jobstep/creation/README.md b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/jobstep/creation/README.md new file mode 100644 index 00000000..068e5deb --- /dev/null +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/jobstep/creation/README.md @@ -0,0 +1,6 @@ +# Job Step Creation Samples + +## Invariants + +- Every supported way to create a job step with the Kotlin DSL should have a + runnable sample in this package. diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/jobstep/bean/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/jobstep/creation/bean/SampleApplicationTest.kt similarity index 71% rename from spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/jobstep/bean/SampleApplicationTest.kt rename to spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/jobstep/creation/bean/SampleApplicationTest.kt index 4bc6f24b..9ea311a4 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/jobstep/bean/SampleApplicationTest.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/jobstep/creation/bean/SampleApplicationTest.kt @@ -16,13 +16,13 @@ * limitations under the License. */ -package com.navercorp.spring.batch.plus.sample.step.jobstep.bean +package com.navercorp.spring.batch.plus.sample.step.jobstep.creation.bean import org.junit.jupiter.api.Test import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator import org.springframework.beans.factory.getBean import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.runApplication @@ -32,12 +32,13 @@ open class SampleApplicationTest { @Test fun run() { val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() + val jobOperator = applicationContext.getBean() val job = applicationContext.getBean("testJob") - val jobParameters = JobParametersBuilder() - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) + val jobParameters = + JobParametersBuilder() + .toJobParameters() + val jobExecution = jobOperator.start(job, jobParameters) assert(BatchStatus.COMPLETED == jobExecution.status) println(jobExecution) diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/finish/stop/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/jobstep/creation/bean/TestJobConfig.kt similarity index 65% rename from spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/finish/stop/TestJobConfig.kt rename to spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/jobstep/creation/bean/TestJobConfig.kt index 6afb31ae..7f35e46c 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/finish/stop/TestJobConfig.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/jobstep/creation/bean/TestJobConfig.kt @@ -16,12 +16,11 @@ * limitations under the License. */ -package com.navercorp.spring.batch.plus.sample.job.flow.transition.finish.stop +package com.navercorp.spring.batch.plus.sample.step.jobstep.creation.bean import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.Job -import org.springframework.batch.core.Step -import org.springframework.batch.repeat.RepeatStatus +import org.springframework.batch.core.job.Job +import org.springframework.batch.infrastructure.repeat.RepeatStatus import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.transaction.PlatformTransactionManager @@ -31,25 +30,23 @@ open class TestJobConfig( private val batch: BatchDsl, private val transactionManager: PlatformTransactionManager, ) { - @Bean - open fun testJob(): Job = batch { - job("testJob") { - step(testStep()) { - on("COMPLETED") { - stop() - } - on("*") { - end() + open fun testJob(): Job = + batch { + job("testJob") { + step("testStep") { + jobBean("anotherJob") } } } - } @Bean - open fun testStep(): Step = batch { - step("testStep") { - tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + open fun anotherJob() = + batch { + job("anotherJob") { + step("anotherJobStep") { + tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + } + } } - } } diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/jobstep/variable/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/jobstep/creation/variable/SampleApplicationTest.kt similarity index 71% rename from spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/jobstep/variable/SampleApplicationTest.kt rename to spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/jobstep/creation/variable/SampleApplicationTest.kt index c022610d..7e33a188 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/jobstep/variable/SampleApplicationTest.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/jobstep/creation/variable/SampleApplicationTest.kt @@ -16,13 +16,13 @@ * limitations under the License. */ -package com.navercorp.spring.batch.plus.sample.step.jobstep.variable +package com.navercorp.spring.batch.plus.sample.step.jobstep.creation.variable import org.junit.jupiter.api.Test import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator import org.springframework.beans.factory.getBean import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.runApplication @@ -32,12 +32,13 @@ open class SampleApplicationTest { @Test fun run() { val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() + val jobOperator = applicationContext.getBean() val job = applicationContext.getBean("testJob") - val jobParameters = JobParametersBuilder() - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) + val jobParameters = + JobParametersBuilder() + .toJobParameters() + val jobExecution = jobOperator.start(job, jobParameters) assert(BatchStatus.COMPLETED == jobExecution.status) println(jobExecution) diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/finish/fail/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/jobstep/creation/variable/TestJobConfig.kt similarity index 65% rename from spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/finish/fail/TestJobConfig.kt rename to spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/jobstep/creation/variable/TestJobConfig.kt index 16df90c1..76f4968f 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/job/flow/transition/finish/fail/TestJobConfig.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/jobstep/creation/variable/TestJobConfig.kt @@ -16,12 +16,11 @@ * limitations under the License. */ -package com.navercorp.spring.batch.plus.sample.job.flow.transition.finish.fail +package com.navercorp.spring.batch.plus.sample.step.jobstep.creation.variable import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.Job -import org.springframework.batch.core.Step -import org.springframework.batch.repeat.RepeatStatus +import org.springframework.batch.core.job.Job +import org.springframework.batch.infrastructure.repeat.RepeatStatus import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.transaction.PlatformTransactionManager @@ -31,25 +30,23 @@ open class TestJobConfig( private val batch: BatchDsl, private val transactionManager: PlatformTransactionManager, ) { - @Bean - open fun testJob(): Job = batch { - job("testJob") { - step(testStep()) { - on("COMPLETED") { - fail() - } - on("*") { - stop() + open fun testJob(): Job = + batch { + job("testJob") { + step("testStep") { + job(anotherJob()) } } } - } @Bean - open fun testStep(): Step = batch { - step("testStep") { - tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + open fun anotherJob() = + batch { + job("anotherJob") { + step("anotherJobStep") { + tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + } + } } - } } diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/partitionstep/config/README.md b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/partitionstep/config/README.md new file mode 100644 index 00000000..5fc237e9 --- /dev/null +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/partitionstep/config/README.md @@ -0,0 +1,6 @@ +# Partition Step Config Samples + +## Invariants + +- Every partition step splitter and aggregator option exposed by the Kotlin DSL + should have a runnable sample in this package. diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/partitionstep/splitter/direct/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/partitionstep/config/aggregator/SampleApplicationTest.kt similarity index 74% rename from spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/partitionstep/splitter/direct/SampleApplicationTest.kt rename to spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/partitionstep/config/aggregator/SampleApplicationTest.kt index 63711248..78696396 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/partitionstep/splitter/direct/SampleApplicationTest.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/partitionstep/config/aggregator/SampleApplicationTest.kt @@ -16,13 +16,13 @@ * limitations under the License. */ -package com.navercorp.spring.batch.plus.sample.step.partitionstep.splitter.direct +package com.navercorp.spring.batch.plus.sample.step.partitionstep.config.aggregator import org.junit.jupiter.api.Test import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator import org.springframework.beans.factory.getBean import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.runApplication @@ -32,12 +32,13 @@ open class SampleApplicationTest { @Test fun run() { val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() + val jobOperator = applicationContext.getBean() val job = applicationContext.getBean("testJob") - val jobParameters = JobParametersBuilder() - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) + val jobParameters = + JobParametersBuilder() + .toJobParameters() + val jobExecution = jobOperator.start(job, jobParameters) assert(BatchStatus.COMPLETED == jobExecution.status) println(jobExecution) diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/partitionstep/aggregator/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/partitionstep/config/aggregator/TestJobConfig.kt similarity index 50% rename from spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/partitionstep/aggregator/TestJobConfig.kt rename to spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/partitionstep/config/aggregator/TestJobConfig.kt index 01e6ea70..6ac98e59 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/partitionstep/aggregator/TestJobConfig.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/partitionstep/config/aggregator/TestJobConfig.kt @@ -16,14 +16,14 @@ * limitations under the License. */ -package com.navercorp.spring.batch.plus.sample.step.partitionstep.aggregator +package com.navercorp.spring.batch.plus.sample.step.partitionstep.config.aggregator import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.Job -import org.springframework.batch.core.Step +import org.springframework.batch.core.job.Job import org.springframework.batch.core.partition.support.DefaultStepExecutionAggregator -import org.springframework.batch.item.ExecutionContext -import org.springframework.batch.repeat.RepeatStatus +import org.springframework.batch.core.step.Step +import org.springframework.batch.infrastructure.item.ExecutionContext +import org.springframework.batch.infrastructure.repeat.RepeatStatus import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.core.task.SimpleAsyncTaskExecutor @@ -34,38 +34,39 @@ open class TestJobConfig( private val batch: BatchDsl, private val transactionManager: PlatformTransactionManager, ) { - @Bean - open fun testJob(): Job = batch { - job("testJob") { - step("testStep") { - partitioner { - splitter("workerStep") { gridSize -> - (0 until gridSize).associate { - "partition-$it" to ExecutionContext() + open fun testJob(): Job = + batch { + job("testJob") { + step("testStep") { + partitioner { + partitionHandler { + taskExecutor(SimpleAsyncTaskExecutor()) + step(testStep()) + gridSize(4) } + splitter("workerStep") { gridSize -> + (0 until gridSize).associate { + "partition-$it" to ExecutionContext() + } + } + aggregator(DefaultStepExecutionAggregator()) } - partitionHandler { - taskExecutor(SimpleAsyncTaskExecutor()) - step(testStep()) - gridSize(4) - } - aggregator(DefaultStepExecutionAggregator()) } } } - } @Bean - open fun testStep(): Step = batch { - step("actualStep") { - tasklet( - { contribution, _ -> - println("[${Thread.currentThread().name}][${contribution.stepExecution.stepName}] run actual tasklet") - RepeatStatus.FINISHED - }, - transactionManager, - ) + open fun testStep(): Step = + batch { + step("actualStep") { + tasklet( + { contribution, _ -> + println("[${Thread.currentThread().name}][${contribution.stepExecution.stepName}] run actual tasklet") + RepeatStatus.FINISHED + }, + transactionManager, + ) + } } - } } diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/partitionstep/aggregator/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/partitionstep/config/splitter/builtin/SampleApplicationTest.kt similarity index 74% rename from spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/partitionstep/aggregator/SampleApplicationTest.kt rename to spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/partitionstep/config/splitter/builtin/SampleApplicationTest.kt index d49f2d59..ebdef6a1 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/partitionstep/aggregator/SampleApplicationTest.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/partitionstep/config/splitter/builtin/SampleApplicationTest.kt @@ -16,13 +16,13 @@ * limitations under the License. */ -package com.navercorp.spring.batch.plus.sample.step.partitionstep.aggregator +package com.navercorp.spring.batch.plus.sample.step.partitionstep.config.splitter.builtin import org.junit.jupiter.api.Test import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator import org.springframework.beans.factory.getBean import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.runApplication @@ -32,12 +32,13 @@ open class SampleApplicationTest { @Test fun run() { val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() + val jobOperator = applicationContext.getBean() val job = applicationContext.getBean("testJob") - val jobParameters = JobParametersBuilder() - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) + val jobParameters = + JobParametersBuilder() + .toJobParameters() + val jobExecution = jobOperator.start(job, jobParameters) assert(BatchStatus.COMPLETED == jobExecution.status) println(jobExecution) diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/partitionstep/splitter/inner/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/partitionstep/config/splitter/builtin/TestJobConfig.kt similarity index 50% rename from spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/partitionstep/splitter/inner/TestJobConfig.kt rename to spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/partitionstep/config/splitter/builtin/TestJobConfig.kt index 38ab6c47..a05c4b12 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/partitionstep/splitter/inner/TestJobConfig.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/partitionstep/config/splitter/builtin/TestJobConfig.kt @@ -16,13 +16,13 @@ * limitations under the License. */ -package com.navercorp.spring.batch.plus.sample.step.partitionstep.splitter.inner +package com.navercorp.spring.batch.plus.sample.step.partitionstep.config.splitter.builtin import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.Job -import org.springframework.batch.core.Step -import org.springframework.batch.item.ExecutionContext -import org.springframework.batch.repeat.RepeatStatus +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.step.Step +import org.springframework.batch.infrastructure.item.ExecutionContext +import org.springframework.batch.infrastructure.repeat.RepeatStatus import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.core.task.SimpleAsyncTaskExecutor @@ -33,38 +33,38 @@ open class TestJobConfig( private val batch: BatchDsl, private val transactionManager: PlatformTransactionManager, ) { - @Bean - open fun testJob(): Job = batch { - job("testJob") { - step("testStep") { - partitioner { - // use SimpleStepExecutionSplitter internally - splitter("workerStep") { gridSize -> - (0 until gridSize).associate { - "partition-$it" to ExecutionContext() + open fun testJob(): Job = + batch { + job("testJob") { + step("testStep") { + partitioner { + partitionHandler { + taskExecutor(SimpleAsyncTaskExecutor()) + step(testStep()) + gridSize(4) + } + splitter("workerStep") { gridSize -> + (0 until gridSize).associate { + "partition-$it" to ExecutionContext() + } } - } - partitionHandler { - taskExecutor(SimpleAsyncTaskExecutor()) - step(testStep()) - gridSize(4) } } } } - } @Bean - open fun testStep(): Step = batch { - step("actualStep") { - tasklet( - { contribution, _ -> - println("[${Thread.currentThread().name}][${contribution.stepExecution.stepName}] run actual tasklet") - RepeatStatus.FINISHED - }, - transactionManager, - ) + open fun testStep(): Step = + batch { + step("actualStep") { + tasklet( + { contribution, _ -> + println("[${Thread.currentThread().name}][${contribution.stepExecution.stepName}] run actual tasklet") + RepeatStatus.FINISHED + }, + transactionManager, + ) + } } - } } diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/partitionstep/partitionhandler/direct/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/partitionstep/config/splitter/direct/SampleApplicationTest.kt similarity index 74% rename from spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/partitionstep/partitionhandler/direct/SampleApplicationTest.kt rename to spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/partitionstep/config/splitter/direct/SampleApplicationTest.kt index 54013af2..13a8ee1a 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/partitionstep/partitionhandler/direct/SampleApplicationTest.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/partitionstep/config/splitter/direct/SampleApplicationTest.kt @@ -16,13 +16,13 @@ * limitations under the License. */ -package com.navercorp.spring.batch.plus.sample.step.partitionstep.partitionhandler.direct +package com.navercorp.spring.batch.plus.sample.step.partitionstep.config.splitter.direct import org.junit.jupiter.api.Test import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator import org.springframework.beans.factory.getBean import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.runApplication @@ -32,12 +32,13 @@ open class SampleApplicationTest { @Test fun run() { val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() + val jobOperator = applicationContext.getBean() val job = applicationContext.getBean("testJob") - val jobParameters = JobParametersBuilder() - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) + val jobParameters = + JobParametersBuilder() + .toJobParameters() + val jobExecution = jobOperator.start(job, jobParameters) assert(BatchStatus.COMPLETED == jobExecution.status) println(jobExecution) diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/partitionstep/config/splitter/direct/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/partitionstep/config/splitter/direct/TestJobConfig.kt new file mode 100644 index 00000000..88303ded --- /dev/null +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/partitionstep/config/splitter/direct/TestJobConfig.kt @@ -0,0 +1,87 @@ +/* + * Spring Batch Plus + * + * Copyright 2022-present NAVER Corp. + * + * 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 + * + * http://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 com.navercorp.spring.batch.plus.sample.step.partitionstep.config.splitter.direct + +import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.partition.StepExecutionSplitter +import org.springframework.batch.core.repository.JobRepository +import org.springframework.batch.core.step.Step +import org.springframework.batch.core.step.StepExecution +import org.springframework.batch.infrastructure.repeat.RepeatStatus +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import org.springframework.core.task.SimpleAsyncTaskExecutor +import org.springframework.transaction.PlatformTransactionManager + +@Configuration +open class TestJobConfig( + private val batch: BatchDsl, + private val jobRepository: JobRepository, + private val transactionManager: PlatformTransactionManager, +) { + @Bean + open fun testJob(): Job = + batch { + job("testJob") { + step("testStep") { + partitioner { + partitionHandler { + taskExecutor(SimpleAsyncTaskExecutor()) + step(actualStep()) + gridSize(4) + } + splitter( + object : StepExecutionSplitter { + override fun getStepName(): String = "workerStep" + + override fun split( + stepExecution: StepExecution, + gridSize: Int, + ): Set { + val jobExecution = stepExecution.jobExecution + return (0 until gridSize) + .map { + jobRepository.createStepExecution( + "$stepName:partition-$it", + jobExecution, + ) + }.toSet() + } + }, + ) + } + } + } + } + + @Bean + open fun actualStep(): Step = + batch { + step("actualStep") { + tasklet( + { contribution, _ -> + println("[${Thread.currentThread().name}][${contribution.stepExecution.stepName}] run actual tasklet") + RepeatStatus.FINISHED + }, + transactionManager, + ) + } + } +} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/partitionstep/creation/README.md b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/partitionstep/creation/README.md new file mode 100644 index 00000000..a4046229 --- /dev/null +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/partitionstep/creation/README.md @@ -0,0 +1,6 @@ +# Partition Step Creation Samples + +## Invariants + +- Every supported way to provide a partition handler with the Kotlin DSL should + have a runnable sample in this package. diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/partitionstep/creation/builtinhandler/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/partitionstep/creation/builtinhandler/SampleApplicationTest.kt new file mode 100644 index 00000000..5f0f0a8c --- /dev/null +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/partitionstep/creation/builtinhandler/SampleApplicationTest.kt @@ -0,0 +1,46 @@ +/* + * Spring Batch Plus + * + * Copyright 2022-present NAVER Corp. + * + * 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 + * + * http://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 com.navercorp.spring.batch.plus.sample.step.partitionstep.creation.builtinhandler + +import org.junit.jupiter.api.Test +import org.springframework.batch.core.BatchStatus +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator +import org.springframework.beans.factory.getBean +import org.springframework.boot.autoconfigure.SpringBootApplication +import org.springframework.boot.runApplication + +@SpringBootApplication +open class SampleApplicationTest { + @Test + fun run() { + val applicationContext = runApplication() + val jobOperator = applicationContext.getBean() + val job = applicationContext.getBean("testJob") + + val jobParameters = + JobParametersBuilder() + .toJobParameters() + val jobExecution = jobOperator.start(job, jobParameters) + + assert(BatchStatus.COMPLETED == jobExecution.status) + println(jobExecution) + } +} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/partitionstep/partitionhandler/inner/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/partitionstep/creation/builtinhandler/TestJobConfig.kt similarity index 50% rename from spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/partitionstep/partitionhandler/inner/TestJobConfig.kt rename to spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/partitionstep/creation/builtinhandler/TestJobConfig.kt index 365d9af7..943c978f 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/partitionstep/partitionhandler/inner/TestJobConfig.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/partitionstep/creation/builtinhandler/TestJobConfig.kt @@ -16,13 +16,13 @@ * limitations under the License. */ -package com.navercorp.spring.batch.plus.sample.step.partitionstep.partitionhandler.inner +package com.navercorp.spring.batch.plus.sample.step.partitionstep.creation.builtinhandler import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.Job -import org.springframework.batch.core.Step -import org.springframework.batch.item.ExecutionContext -import org.springframework.batch.repeat.RepeatStatus +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.step.Step +import org.springframework.batch.infrastructure.item.ExecutionContext +import org.springframework.batch.infrastructure.repeat.RepeatStatus import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.core.task.SimpleAsyncTaskExecutor @@ -33,38 +33,38 @@ open class TestJobConfig( private val batch: BatchDsl, private val transactionManager: PlatformTransactionManager, ) { - @Bean - open fun testJob(): Job = batch { - job("testJob") { - step("testStep") { - partitioner { - splitter("workerStep") { gridSize -> - (0 until gridSize).associate { - "partition-$it" to ExecutionContext() + open fun testJob(): Job = + batch { + job("testJob") { + step("testStep") { + partitioner { + partitionHandler { + taskExecutor(SimpleAsyncTaskExecutor()) + step(actualStep()) + gridSize(4) + } + splitter("workerStep") { gridSize -> + (0 until gridSize).associate { + "partition-$it" to ExecutionContext() + } } - } - // use TaskExecutorPartitionHandler internally - partitionHandler { - taskExecutor(SimpleAsyncTaskExecutor()) - step(actualStep()) - gridSize(4) } } } } - } @Bean - open fun actualStep(): Step = batch { - step("actualStep") { - tasklet( - { contribution, _ -> - println("[${Thread.currentThread().name}][${contribution.stepExecution.stepName}] run actual tasklet") - RepeatStatus.FINISHED - }, - transactionManager, - ) + open fun actualStep(): Step = + batch { + step("actualStep") { + tasklet( + { contribution, _ -> + println("[${Thread.currentThread().name}][${contribution.stepExecution.stepName}] run actual tasklet") + RepeatStatus.FINISHED + }, + transactionManager, + ) + } } - } } diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/partitionstep/partitionhandler/inner/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/partitionstep/creation/directhandler/SampleApplicationTest.kt similarity index 74% rename from spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/partitionstep/partitionhandler/inner/SampleApplicationTest.kt rename to spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/partitionstep/creation/directhandler/SampleApplicationTest.kt index 514e8254..d765ba71 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/partitionstep/partitionhandler/inner/SampleApplicationTest.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/partitionstep/creation/directhandler/SampleApplicationTest.kt @@ -16,13 +16,13 @@ * limitations under the License. */ -package com.navercorp.spring.batch.plus.sample.step.partitionstep.partitionhandler.inner +package com.navercorp.spring.batch.plus.sample.step.partitionstep.creation.directhandler import org.junit.jupiter.api.Test import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator import org.springframework.beans.factory.getBean import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.runApplication @@ -32,12 +32,13 @@ open class SampleApplicationTest { @Test fun run() { val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() + val jobOperator = applicationContext.getBean() val job = applicationContext.getBean("testJob") - val jobParameters = JobParametersBuilder() - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) + val jobParameters = + JobParametersBuilder() + .toJobParameters() + val jobExecution = jobOperator.start(job, jobParameters) assert(BatchStatus.COMPLETED == jobExecution.status) println(jobExecution) diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/partitionstep/creation/directhandler/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/partitionstep/creation/directhandler/TestJobConfig.kt new file mode 100644 index 00000000..9f7de924 --- /dev/null +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/partitionstep/creation/directhandler/TestJobConfig.kt @@ -0,0 +1,73 @@ +/* + * Spring Batch Plus + * + * Copyright 2022-present NAVER Corp. + * + * 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 + * + * http://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 com.navercorp.spring.batch.plus.sample.step.partitionstep.creation.directhandler + +import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.partition.support.TaskExecutorPartitionHandler +import org.springframework.batch.core.step.Step +import org.springframework.batch.infrastructure.item.ExecutionContext +import org.springframework.batch.infrastructure.repeat.RepeatStatus +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import org.springframework.core.task.SimpleAsyncTaskExecutor +import org.springframework.transaction.PlatformTransactionManager + +@Configuration +open class TestJobConfig( + private val batch: BatchDsl, + private val transactionManager: PlatformTransactionManager, +) { + @Bean + open fun testJob(): Job = + batch { + job("testJob") { + step("testStep") { + partitioner { + partitionHandler( + TaskExecutorPartitionHandler().apply { + setTaskExecutor(SimpleAsyncTaskExecutor()) + step = actualStep() + gridSize = 4 + }, + ) + splitter("workerStep") { gridSize -> + (0 until gridSize).associate { + "partition-$it" to ExecutionContext() + } + } + } + } + } + } + + @Bean + open fun actualStep(): Step = + batch { + step("actualStep") { + tasklet( + { contribution, _ -> + println("[${Thread.currentThread().name}][${contribution.stepExecution.stepName}] run actual tasklet") + RepeatStatus.FINISHED + }, + transactionManager, + ) + } + } +} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/partitionstep/partitionhandler/direct/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/partitionstep/partitionhandler/direct/TestJobConfig.kt deleted file mode 100644 index 2f0c7596..00000000 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/partitionstep/partitionhandler/direct/TestJobConfig.kt +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Spring Batch Plus - * - * Copyright 2022-present NAVER Corp. - * - * 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 - * - * http://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 com.navercorp.spring.batch.plus.sample.step.partitionstep.partitionhandler.direct - -import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.Job -import org.springframework.batch.core.Step -import org.springframework.batch.core.partition.support.TaskExecutorPartitionHandler -import org.springframework.batch.item.ExecutionContext -import org.springframework.batch.repeat.RepeatStatus -import org.springframework.context.annotation.Bean -import org.springframework.context.annotation.Configuration -import org.springframework.core.task.SimpleAsyncTaskExecutor -import org.springframework.transaction.PlatformTransactionManager - -@Configuration -open class TestJobConfig( - private val batch: BatchDsl, - private val transactionManager: PlatformTransactionManager, -) { - - @Bean - open fun testJob(): Job = batch { - job("testJob") { - step("testStep") { - partitioner { - splitter("workerStep") { gridSize -> - (0 until gridSize).associate { - "partition-$it" to ExecutionContext() - } - } - partitionHandler( - TaskExecutorPartitionHandler().apply { - setTaskExecutor(SimpleAsyncTaskExecutor()) - step = actualStep() - gridSize = 4 - }, - ) - } - } - } - } - - @Bean - open fun actualStep(): Step = batch { - step("actualStep") { - tasklet( - { contribution, _ -> - println("[${Thread.currentThread().name}][${contribution.stepExecution.stepName}] run actual tasklet") - RepeatStatus.FINISHED - }, - transactionManager, - ) - } - } -} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/partitionstep/splitter/direct/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/partitionstep/splitter/direct/TestJobConfig.kt deleted file mode 100644 index 783a5139..00000000 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/partitionstep/splitter/direct/TestJobConfig.kt +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Spring Batch Plus - * - * Copyright 2022-present NAVER Corp. - * - * 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 - * - * http://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 com.navercorp.spring.batch.plus.sample.step.partitionstep.splitter.direct - -import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.Job -import org.springframework.batch.core.Step -import org.springframework.batch.core.StepExecution -import org.springframework.batch.core.partition.StepExecutionSplitter -import org.springframework.batch.core.repository.JobRepository -import org.springframework.batch.repeat.RepeatStatus -import org.springframework.context.annotation.Bean -import org.springframework.context.annotation.Configuration -import org.springframework.core.task.SimpleAsyncTaskExecutor -import org.springframework.transaction.PlatformTransactionManager - -@Configuration -open class TestJobConfig( - private val batch: BatchDsl, - private val transactionManager: PlatformTransactionManager, - private val jobRepository: JobRepository, -) { - - @Bean - open fun testJob(): Job = batch { - job("testJob") { - step("testStep") { - partitioner { - splitter( - object : StepExecutionSplitter { - override fun getStepName(): String = "workerStep" - - override fun split(stepExecution: StepExecution, gridSize: Int): Set { - val jobExecution = stepExecution.jobExecution - val stepExecutions = (0 until gridSize) - .map { - jobExecution.createStepExecution("$stepName:partition-$it") - } - jobRepository.addAll(stepExecutions) - return stepExecutions.toSet() - } - }, - ) - partitionHandler { - taskExecutor(SimpleAsyncTaskExecutor()) - step(actualStep()) - gridSize(4) - } - } - } - } - } - - @Bean - open fun actualStep(): Step = batch { - step("actualStep") { - tasklet( - { contribution, _ -> - println("[${Thread.currentThread().name}][${contribution.stepExecution.stepName}] run actual tasklet") - RepeatStatus.FINISHED - }, - transactionManager, - ) - } - } -} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/partitionstep/splitter/inner/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/partitionstep/splitter/inner/SampleApplicationTest.kt deleted file mode 100644 index 4bbefdc0..00000000 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/partitionstep/splitter/inner/SampleApplicationTest.kt +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Spring Batch Plus - * - * Copyright 2022-present NAVER Corp. - * - * 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 - * - * http://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 com.navercorp.spring.batch.plus.sample.step.partitionstep.splitter.inner - -import org.junit.jupiter.api.Test -import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher -import org.springframework.beans.factory.getBean -import org.springframework.boot.autoconfigure.SpringBootApplication -import org.springframework.boot.runApplication - -@SpringBootApplication -open class SampleApplicationTest { - @Test - fun run() { - val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() - val job = applicationContext.getBean("testJob") - - val jobParameters = JobParametersBuilder() - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) - - assert(BatchStatus.COMPLETED == jobExecution.status) - println(jobExecution) - } -} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/taskletstep/config/README.md b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/taskletstep/config/README.md new file mode 100644 index 00000000..85d168d9 --- /dev/null +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/taskletstep/config/README.md @@ -0,0 +1,6 @@ +# Tasklet Step Config Samples + +## Invariants + +- Every tasklet step configuration option exposed by the Kotlin DSL should have + a runnable sample in this package. diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/taskletstep/config/exceptionhandler/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/taskletstep/config/exceptionhandler/SampleApplicationTest.kt index 1452146f..aef0d190 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/taskletstep/config/exceptionhandler/SampleApplicationTest.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/taskletstep/config/exceptionhandler/SampleApplicationTest.kt @@ -20,9 +20,9 @@ package com.navercorp.spring.batch.plus.sample.step.taskletstep.config.exception import org.junit.jupiter.api.Test import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator import org.springframework.beans.factory.getBean import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.runApplication @@ -32,12 +32,13 @@ open class SampleApplicationTest { @Test fun run() { val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() + val jobOperator = applicationContext.getBean() val job = applicationContext.getBean() - val jobParameters = JobParametersBuilder() - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) + val jobParameters = + JobParametersBuilder() + .toJobParameters() + val jobExecution = jobOperator.start(job, jobParameters) assert(BatchStatus.FAILED == jobExecution.status) println(jobExecution) diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/taskletstep/config/exceptionhandler/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/taskletstep/config/exceptionhandler/TestJobConfig.kt index 2ce6bc6f..44d26a8d 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/taskletstep/config/exceptionhandler/TestJobConfig.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/taskletstep/config/exceptionhandler/TestJobConfig.kt @@ -19,7 +19,7 @@ package com.navercorp.spring.batch.plus.sample.step.taskletstep.config.exceptionhandler import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.Job +import org.springframework.batch.core.job.Job import org.springframework.batch.core.step.tasklet.Tasklet import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration @@ -30,32 +30,33 @@ open class TestJobConfig( private val batch: BatchDsl, private val transactionManager: PlatformTransactionManager, ) { - @Bean - open fun testJob(): Job = batch { - job("testJob") { - step("testStep") { - tasklet(testTasklet(), transactionManager) { - exceptionHandler { _, throwable -> - println("handle exception ${throwable.message}") - throw throwable + open fun testJob(): Job = + batch { + job("testJob") { + step("testStep") { + tasklet(testTasklet(), transactionManager) { + exceptionHandler { _, throwable -> + println("handle exception ${throwable.message}") + throw throwable + } + // same as + // exceptionHandler( + // object : ExceptionHandler { + // override fun handleException(context: RepeatContext, throwable: Throwable) { + // println("handle exception ${throwable.message}") + // throw throwable + // } + // } + // ) } - // same as - // exceptionHandler( - // object : ExceptionHandler { - // override fun handleException(context: RepeatContext, throwable: Throwable) { - // println("handle exception ${throwable.message}") - // throw throwable - // } - // } - // ) } } } - } @Bean - open fun testTasklet(): Tasklet = Tasklet { _, _ -> - throw IllegalStateException("testTasklet error") - } + open fun testTasklet(): Tasklet = + Tasklet { _, _ -> + throw IllegalStateException("testTasklet error") + } } diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/taskletstep/config/executor/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/taskletstep/config/executor/SampleApplicationTest.kt index 48a25dcd..366bf6ee 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/taskletstep/config/executor/SampleApplicationTest.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/taskletstep/config/executor/SampleApplicationTest.kt @@ -20,9 +20,9 @@ package com.navercorp.spring.batch.plus.sample.step.taskletstep.config.executor import org.junit.jupiter.api.Test import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator import org.springframework.beans.factory.getBean import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.runApplication @@ -32,12 +32,13 @@ open class SampleApplicationTest { @Test fun run() { val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() + val jobOperator = applicationContext.getBean() val job = applicationContext.getBean() - val jobParameters = JobParametersBuilder() - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) + val jobParameters = + JobParametersBuilder() + .toJobParameters() + val jobExecution = jobOperator.start(job, jobParameters) assert(BatchStatus.COMPLETED == jobExecution.status) println(jobExecution) diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/taskletstep/config/executor/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/taskletstep/config/executor/TestJobConfig.kt index 658be126..e75bf97b 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/taskletstep/config/executor/TestJobConfig.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/taskletstep/config/executor/TestJobConfig.kt @@ -19,9 +19,9 @@ package com.navercorp.spring.batch.plus.sample.step.taskletstep.config.executor import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.Job +import org.springframework.batch.core.job.Job import org.springframework.batch.core.step.tasklet.Tasklet -import org.springframework.batch.repeat.RepeatStatus +import org.springframework.batch.infrastructure.repeat.RepeatStatus import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.core.task.SimpleAsyncTaskExecutor @@ -33,31 +33,31 @@ open class TestJobConfig( private val batch: BatchDsl, private val transactionManager: PlatformTransactionManager, ) { - @Bean - open fun customExecutor(): TaskExecutor { - return object : SimpleAsyncTaskExecutor() { + open fun customExecutor(): TaskExecutor = + object : SimpleAsyncTaskExecutor() { override fun execute(task: Runnable) { println("run in custom executor") super.execute(task) } } - } @Bean - open fun testJob(): Job = batch { - job("testJob") { - step("testStep") { - tasklet(testTasklet(), transactionManager) { - taskExecutor(customExecutor()) + open fun testJob(): Job = + batch { + job("testJob") { + step("testStep") { + tasklet(testTasklet(), transactionManager) { + taskExecutor(customExecutor()) + } } } } - } @Bean - open fun testTasklet(): Tasklet = Tasklet { _, _ -> - println("run testTasklet") - RepeatStatus.FINISHED - } + open fun testTasklet(): Tasklet = + Tasklet { _, _ -> + println("run testTasklet") + RepeatStatus.FINISHED + } } diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/taskletstep/config/listenerannotation/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/taskletstep/config/listenerannotation/SampleApplicationTest.kt index 733606a8..f590f68c 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/taskletstep/config/listenerannotation/SampleApplicationTest.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/taskletstep/config/listenerannotation/SampleApplicationTest.kt @@ -20,9 +20,9 @@ package com.navercorp.spring.batch.plus.sample.step.taskletstep.config.listenera import org.junit.jupiter.api.Test import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator import org.springframework.beans.factory.getBean import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.runApplication @@ -32,12 +32,13 @@ open class SampleApplicationTest { @Test fun run() { val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() + val jobOperator = applicationContext.getBean() val job = applicationContext.getBean() - val jobParameters = JobParametersBuilder() - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) + val jobParameters = + JobParametersBuilder() + .toJobParameters() + val jobExecution = jobOperator.start(job, jobParameters) assert(BatchStatus.COMPLETED == jobExecution.status) println(jobExecution) diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/taskletstep/config/listenerannotation/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/taskletstep/config/listenerannotation/TestJobConfig.kt index af885e58..84119774 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/taskletstep/config/listenerannotation/TestJobConfig.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/taskletstep/config/listenerannotation/TestJobConfig.kt @@ -19,13 +19,13 @@ package com.navercorp.spring.batch.plus.sample.step.taskletstep.config.listenerannotation import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.Job import org.springframework.batch.core.annotation.AfterChunk -import org.springframework.batch.core.annotation.AfterChunkError +import org.springframework.batch.core.annotation.AfterStep import org.springframework.batch.core.annotation.BeforeChunk -import org.springframework.batch.core.scope.context.ChunkContext +import org.springframework.batch.core.annotation.BeforeStep +import org.springframework.batch.core.job.Job import org.springframework.batch.core.step.tasklet.Tasklet -import org.springframework.batch.repeat.RepeatStatus +import org.springframework.batch.infrastructure.repeat.RepeatStatus import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.transaction.PlatformTransactionManager @@ -35,37 +35,44 @@ open class TestJobConfig( private val batch: BatchDsl, private val transactionManager: PlatformTransactionManager, ) { - class TestListener { - @BeforeChunk - fun beforeChunk(context: ChunkContext) { - println("beforeChunk: $context") + @BeforeStep + fun beforeStep() { + println("beforeStep") } - @AfterChunk - fun afterChunk(context: ChunkContext) { - println("afterChunk: $context") + @AfterStep + fun afterStep() { + println("afterStep") + } + + @BeforeChunk + fun beforeChunk() { + println("beforeChunk") } - @AfterChunkError - fun afterChunkError() { + @AfterChunk + fun afterChunk() { + println("afterChunk") } } @Bean - open fun testJob(): Job = batch { - job("testJob") { - step("testStep") { - tasklet(testTasklet(), transactionManager) { - listener(TestListener()) + open fun testJob(): Job = + batch { + job("testJob") { + step("testStep") { + tasklet(testTasklet(), transactionManager) { + listener(TestListener()) + } } } } - } @Bean - open fun testTasklet(): Tasklet = Tasklet { _, _ -> - println("run testTasklet") - RepeatStatus.FINISHED - } + open fun testTasklet(): Tasklet = + Tasklet { _, _ -> + println("run testTasklet") + RepeatStatus.FINISHED + } } diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/taskletstep/config/listenerobject/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/taskletstep/config/listenerobject/SampleApplicationTest.kt index 59dac36b..3699538a 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/taskletstep/config/listenerobject/SampleApplicationTest.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/taskletstep/config/listenerobject/SampleApplicationTest.kt @@ -20,9 +20,9 @@ package com.navercorp.spring.batch.plus.sample.step.taskletstep.config.listenero import org.junit.jupiter.api.Test import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator import org.springframework.beans.factory.getBean import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.runApplication @@ -32,12 +32,13 @@ open class SampleApplicationTest { @Test fun run() { val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() + val jobOperator = applicationContext.getBean() val job = applicationContext.getBean() - val jobParameters = JobParametersBuilder() - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) + val jobParameters = + JobParametersBuilder() + .toJobParameters() + val jobExecution = jobOperator.start(job, jobParameters) assert(BatchStatus.COMPLETED == jobExecution.status) println(jobExecution) diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/taskletstep/config/listenerobject/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/taskletstep/config/listenerobject/TestJobConfig.kt index 0d096998..4fef2ec0 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/taskletstep/config/listenerobject/TestJobConfig.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/taskletstep/config/listenerobject/TestJobConfig.kt @@ -19,11 +19,11 @@ package com.navercorp.spring.batch.plus.sample.step.taskletstep.config.listenerobject import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.ChunkListener -import org.springframework.batch.core.Job +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.listener.ChunkListener import org.springframework.batch.core.scope.context.ChunkContext import org.springframework.batch.core.step.tasklet.Tasklet -import org.springframework.batch.repeat.RepeatStatus +import org.springframework.batch.infrastructure.repeat.RepeatStatus import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.transaction.PlatformTransactionManager @@ -33,34 +33,35 @@ open class TestJobConfig( private val batch: BatchDsl, private val transactionManager: PlatformTransactionManager, ) { - @Bean - open fun testJob(): Job = batch { - job("testJob") { - step("testStep") { - tasklet(testTasklet(), transactionManager) { - listener( - object : ChunkListener { - override fun beforeChunk(context: ChunkContext) { - println("beforeChunk: $context") - } + open fun testJob(): Job = + batch { + job("testJob") { + step("testStep") { + tasklet(testTasklet(), transactionManager) { + listener( + object : ChunkListener { + override fun beforeChunk(context: ChunkContext) { + println("beforeChunk: $context") + } - override fun afterChunk(context: ChunkContext) { - println("afterChunk: $context") - } + override fun afterChunk(context: ChunkContext) { + println("afterChunk: $context") + } - override fun afterChunkError(context: ChunkContext) { - } - }, - ) + override fun afterChunkError(context: ChunkContext) { + } + }, + ) + } } } } - } @Bean - open fun testTasklet(): Tasklet = Tasklet { _, _ -> - println("run testTasklet") - RepeatStatus.FINISHED - } + open fun testTasklet(): Tasklet = + Tasklet { _, _ -> + println("run testTasklet") + RepeatStatus.FINISHED + } } diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/taskletstep/config/stepoperation/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/taskletstep/config/stepoperation/SampleApplicationTest.kt index 8c49b286..1ebe8947 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/taskletstep/config/stepoperation/SampleApplicationTest.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/taskletstep/config/stepoperation/SampleApplicationTest.kt @@ -20,9 +20,9 @@ package com.navercorp.spring.batch.plus.sample.step.taskletstep.config.stepopera import org.junit.jupiter.api.Test import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator import org.springframework.beans.factory.getBean import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.runApplication @@ -32,12 +32,13 @@ open class SampleApplicationTest { @Test fun run() { val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() + val jobOperator = applicationContext.getBean() val job = applicationContext.getBean() - val jobParameters = JobParametersBuilder() - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) + val jobParameters = + JobParametersBuilder() + .toJobParameters() + val jobExecution = jobOperator.start(job, jobParameters) assert(BatchStatus.COMPLETED == jobExecution.status) println(jobExecution) diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/taskletstep/config/stepoperation/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/taskletstep/config/stepoperation/TestJobConfig.kt index d1eb40c9..7e2528d4 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/taskletstep/config/stepoperation/TestJobConfig.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/taskletstep/config/stepoperation/TestJobConfig.kt @@ -19,12 +19,12 @@ package com.navercorp.spring.batch.plus.sample.step.taskletstep.config.stepoperation import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.Job +import org.springframework.batch.core.job.Job import org.springframework.batch.core.step.tasklet.Tasklet -import org.springframework.batch.repeat.RepeatCallback -import org.springframework.batch.repeat.RepeatOperations -import org.springframework.batch.repeat.RepeatStatus -import org.springframework.batch.repeat.support.RepeatTemplate +import org.springframework.batch.infrastructure.repeat.RepeatCallback +import org.springframework.batch.infrastructure.repeat.RepeatOperations +import org.springframework.batch.infrastructure.repeat.RepeatStatus +import org.springframework.batch.infrastructure.repeat.support.RepeatTemplate import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.transaction.PlatformTransactionManager @@ -34,29 +34,30 @@ open class TestJobConfig( private val batch: BatchDsl, private val transactionManager: PlatformTransactionManager, ) { - @Bean - open fun testJob(): Job = batch { - job("testJob") { - step("testStep") { - tasklet(testTasklet(), transactionManager) { - stepOperations( - object : RepeatOperations { - override fun iterate(callback: RepeatCallback): RepeatStatus { - val delegate = RepeatTemplate() - println("custom iterate") - return delegate.iterate(callback) - } - }, - ) + open fun testJob(): Job = + batch { + job("testJob") { + step("testStep") { + tasklet(testTasklet(), transactionManager) { + stepOperations( + object : RepeatOperations { + override fun iterate(callback: RepeatCallback): RepeatStatus { + val delegate = RepeatTemplate() + println("custom iterate") + return delegate.iterate(callback) + } + }, + ) + } } } } - } @Bean - open fun testTasklet(): Tasklet = Tasklet { _, _ -> - println("run testTasklet") - RepeatStatus.FINISHED - } + open fun testTasklet(): Tasklet = + Tasklet { _, _ -> + println("run testTasklet") + RepeatStatus.FINISHED + } } diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/taskletstep/config/stream/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/taskletstep/config/stream/SampleApplicationTest.kt index 79b6bd3a..fa40b7af 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/taskletstep/config/stream/SampleApplicationTest.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/taskletstep/config/stream/SampleApplicationTest.kt @@ -20,9 +20,9 @@ package com.navercorp.spring.batch.plus.sample.step.taskletstep.config.stream import org.junit.jupiter.api.Test import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator import org.springframework.beans.factory.getBean import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.runApplication @@ -32,12 +32,13 @@ open class SampleApplicationTest { @Test fun run() { val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() + val jobOperator = applicationContext.getBean() val job = applicationContext.getBean() - val jobParameters = JobParametersBuilder() - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) + val jobParameters = + JobParametersBuilder() + .toJobParameters() + val jobExecution = jobOperator.start(job, jobParameters) assert(BatchStatus.COMPLETED == jobExecution.status) println(jobExecution) diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/taskletstep/config/stream/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/taskletstep/config/stream/TestJobConfig.kt index 2f68e7f6..d7e1e31c 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/taskletstep/config/stream/TestJobConfig.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/taskletstep/config/stream/TestJobConfig.kt @@ -19,11 +19,11 @@ package com.navercorp.spring.batch.plus.sample.step.taskletstep.config.stream import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.Job +import org.springframework.batch.core.job.Job import org.springframework.batch.core.step.tasklet.Tasklet -import org.springframework.batch.item.ExecutionContext -import org.springframework.batch.item.ItemStream -import org.springframework.batch.repeat.RepeatStatus +import org.springframework.batch.infrastructure.item.ExecutionContext +import org.springframework.batch.infrastructure.item.ItemStream +import org.springframework.batch.infrastructure.repeat.RepeatStatus import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.transaction.PlatformTransactionManager @@ -33,35 +33,36 @@ open class TestJobConfig( private val batch: BatchDsl, private val transactionManager: PlatformTransactionManager, ) { - @Bean - open fun testJob(): Job = batch { - job("testJob") { - step("testStep") { - tasklet(testTasklet(), transactionManager) { - stream( - object : ItemStream { - override fun open(executionContext: ExecutionContext) { - println("open stream") - } + open fun testJob(): Job = + batch { + job("testJob") { + step("testStep") { + tasklet(testTasklet(), transactionManager) { + stream( + object : ItemStream { + override fun open(executionContext: ExecutionContext) { + println("open stream") + } - override fun update(executionContext: ExecutionContext) { - println("update stream") - } + override fun update(executionContext: ExecutionContext) { + println("update stream") + } - override fun close() { - println("close stream") - } - }, - ) + override fun close() { + println("close stream") + } + }, + ) + } } } } - } @Bean - open fun testTasklet(): Tasklet = Tasklet { _, _ -> - println("run testTasklet") - RepeatStatus.FINISHED - } + open fun testTasklet(): Tasklet = + Tasklet { _, _ -> + println("run testTasklet") + RepeatStatus.FINISHED + } } diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/taskletstep/config/transactionattribute/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/taskletstep/config/transactionattribute/SampleApplicationTest.kt index 21c3b2c2..4b6d5064 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/taskletstep/config/transactionattribute/SampleApplicationTest.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/taskletstep/config/transactionattribute/SampleApplicationTest.kt @@ -20,9 +20,9 @@ package com.navercorp.spring.batch.plus.sample.step.taskletstep.config.transacti import org.junit.jupiter.api.Test import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator import org.springframework.beans.factory.getBean import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.runApplication @@ -32,12 +32,13 @@ open class SampleApplicationTest { @Test fun run() { val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() + val jobOperator = applicationContext.getBean() val job = applicationContext.getBean() - val jobParameters = JobParametersBuilder() - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) + val jobParameters = + JobParametersBuilder() + .toJobParameters() + val jobExecution = jobOperator.start(job, jobParameters) assert(BatchStatus.COMPLETED == jobExecution.status) println(jobExecution) diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/taskletstep/config/transactionattribute/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/taskletstep/config/transactionattribute/TestJobConfig.kt index 6587b574..d0553fcb 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/taskletstep/config/transactionattribute/TestJobConfig.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/taskletstep/config/transactionattribute/TestJobConfig.kt @@ -19,9 +19,9 @@ package com.navercorp.spring.batch.plus.sample.step.taskletstep.config.transactionattribute import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.Job +import org.springframework.batch.core.job.Job import org.springframework.batch.core.step.tasklet.Tasklet -import org.springframework.batch.repeat.RepeatStatus +import org.springframework.batch.infrastructure.repeat.RepeatStatus import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.transaction.PlatformTransactionManager @@ -33,27 +33,28 @@ open class TestJobConfig( private val batch: BatchDsl, private val transactionManager: PlatformTransactionManager, ) { - @Bean - open fun testJob(): Job = batch { - job("testJob") { - step("testStep") { - tasklet(testTasklet(), transactionManager) { - transactionAttribute( - DefaultTransactionAttribute().apply { - setName("test-tx") - }, - ) + open fun testJob(): Job = + batch { + job("testJob") { + step("testStep") { + tasklet(testTasklet(), transactionManager) { + transactionAttribute( + DefaultTransactionAttribute().apply { + setName("test-tx") + }, + ) + } } } } - } @Bean - open fun testTasklet(): Tasklet = Tasklet { _, _ -> - // print false - val transactionName = TransactionSynchronizationManager.getCurrentTransactionName() - println("run testTasklet (transactionName: $transactionName}") - RepeatStatus.FINISHED - } + open fun testTasklet(): Tasklet = + Tasklet { _, _ -> + // print false + val transactionName = TransactionSynchronizationManager.getCurrentTransactionName() + println("run testTasklet (transactionName: $transactionName}") + RepeatStatus.FINISHED + } } diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/taskletstep/bean/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/taskletstep/config/transactionmanager/SampleApplicationTest.kt similarity index 74% rename from spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/taskletstep/bean/SampleApplicationTest.kt rename to spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/taskletstep/config/transactionmanager/SampleApplicationTest.kt index b5a70afb..9f15a113 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/taskletstep/bean/SampleApplicationTest.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/taskletstep/config/transactionmanager/SampleApplicationTest.kt @@ -16,13 +16,13 @@ * limitations under the License. */ -package com.navercorp.spring.batch.plus.sample.step.taskletstep.bean +package com.navercorp.spring.batch.plus.sample.step.taskletstep.config.transactionmanager import org.junit.jupiter.api.Test import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator import org.springframework.beans.factory.getBean import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.runApplication @@ -32,13 +32,13 @@ open class SampleApplicationTest { @Test fun run() { val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() + val jobOperator = applicationContext.getBean() val job = applicationContext.getBean() - val jobParameters = JobParametersBuilder() - .addString("param", "I am test") - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) + val jobParameters = + JobParametersBuilder() + .toJobParameters() + val jobExecution = jobOperator.start(job, jobParameters) assert(BatchStatus.COMPLETED == jobExecution.status) println(jobExecution) diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/taskletstep/config/transactionmanager/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/taskletstep/config/transactionmanager/TestJobConfig.kt new file mode 100644 index 00000000..39f47f74 --- /dev/null +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/taskletstep/config/transactionmanager/TestJobConfig.kt @@ -0,0 +1,52 @@ +/* + * Spring Batch Plus + * + * Copyright 2022-present NAVER Corp. + * + * 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 + * + * http://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 com.navercorp.spring.batch.plus.sample.step.taskletstep.config.transactionmanager + +import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.step.tasklet.Tasklet +import org.springframework.batch.infrastructure.repeat.RepeatStatus +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import org.springframework.transaction.PlatformTransactionManager + +@Configuration +open class TestJobConfig( + private val batch: BatchDsl, + private val transactionManager: PlatformTransactionManager, +) { + @Bean + open fun testJob(): Job = + batch { + job("testJob") { + step("testStep") { + tasklet(testTasklet()) { + transactionManager(transactionManager) + } + } + } + } + + @Bean + open fun testTasklet(): Tasklet = + Tasklet { _, _ -> + println("run testTasklet") + RepeatStatus.FINISHED + } +} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/taskletstep/creation/README.md b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/taskletstep/creation/README.md new file mode 100644 index 00000000..6bafe1b7 --- /dev/null +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/taskletstep/creation/README.md @@ -0,0 +1,6 @@ +# Tasklet Step Creation Samples + +## Invariants + +- Every supported way to create a tasklet step with the Kotlin DSL should have a + runnable sample in this package. diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/taskletstep/creation/beandefaulttransactionmanager/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/taskletstep/creation/beandefaulttransactionmanager/SampleApplicationTest.kt new file mode 100644 index 00000000..d430cf2b --- /dev/null +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/taskletstep/creation/beandefaulttransactionmanager/SampleApplicationTest.kt @@ -0,0 +1,47 @@ +/* + * Spring Batch Plus + * + * Copyright 2022-present NAVER Corp. + * + * 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 + * + * http://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 com.navercorp.spring.batch.plus.sample.step.taskletstep.creation.beandefaulttransactionmanager + +import org.junit.jupiter.api.Test +import org.springframework.batch.core.BatchStatus +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator +import org.springframework.beans.factory.getBean +import org.springframework.boot.autoconfigure.SpringBootApplication +import org.springframework.boot.runApplication + +@SpringBootApplication +open class SampleApplicationTest { + @Test + fun run() { + val applicationContext = runApplication() + val jobOperator = applicationContext.getBean() + val job = applicationContext.getBean() + + val jobParameters = + JobParametersBuilder() + .addString("param", "I am test") + .toJobParameters() + val jobExecution = jobOperator.start(job, jobParameters) + + assert(BatchStatus.COMPLETED == jobExecution.status) + println(jobExecution) + } +} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/taskletstep/creation/beandefaulttransactionmanager/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/taskletstep/creation/beandefaulttransactionmanager/TestJobConfig.kt new file mode 100644 index 00000000..30e325c6 --- /dev/null +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/taskletstep/creation/beandefaulttransactionmanager/TestJobConfig.kt @@ -0,0 +1,53 @@ +/* + * Spring Batch Plus + * + * Copyright 2022-present NAVER Corp. + * + * 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 + * + * http://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 com.navercorp.spring.batch.plus.sample.step.taskletstep.creation.beandefaulttransactionmanager + +import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl +import org.springframework.batch.core.configuration.annotation.StepScope +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.step.tasklet.Tasklet +import org.springframework.batch.infrastructure.repeat.RepeatStatus +import org.springframework.beans.factory.annotation.Value +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration + +@Configuration +open class TestJobConfig( + private val batch: BatchDsl, +) { + @Bean + open fun testJob(): Job = + batch { + job("testJob") { + step("testStep") { + taskletBean("testTasklet") + } + } + } + + @Bean + @StepScope + open fun testTasklet( + @Value("#{jobParameters['param']}") paramValue: String, + ): Tasklet = + Tasklet { _, _ -> + println("param is '$paramValue'") + RepeatStatus.FINISHED + } +} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/taskletstep/creation/beanwithtransactionmanager/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/taskletstep/creation/beanwithtransactionmanager/SampleApplicationTest.kt new file mode 100644 index 00000000..fec722c5 --- /dev/null +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/taskletstep/creation/beanwithtransactionmanager/SampleApplicationTest.kt @@ -0,0 +1,47 @@ +/* + * Spring Batch Plus + * + * Copyright 2022-present NAVER Corp. + * + * 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 + * + * http://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 com.navercorp.spring.batch.plus.sample.step.taskletstep.creation.beanwithtransactionmanager + +import org.junit.jupiter.api.Test +import org.springframework.batch.core.BatchStatus +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator +import org.springframework.beans.factory.getBean +import org.springframework.boot.autoconfigure.SpringBootApplication +import org.springframework.boot.runApplication + +@SpringBootApplication +open class SampleApplicationTest { + @Test + fun run() { + val applicationContext = runApplication() + val jobOperator = applicationContext.getBean() + val job = applicationContext.getBean() + + val jobParameters = + JobParametersBuilder() + .addString("param", "I am test") + .toJobParameters() + val jobExecution = jobOperator.start(job, jobParameters) + + assert(BatchStatus.COMPLETED == jobExecution.status) + println(jobExecution) + } +} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/taskletstep/bean/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/taskletstep/creation/beanwithtransactionmanager/TestJobConfig.kt similarity index 74% rename from spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/taskletstep/bean/TestJobConfig.kt rename to spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/taskletstep/creation/beanwithtransactionmanager/TestJobConfig.kt index 250611ad..00f8b44f 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/taskletstep/bean/TestJobConfig.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/taskletstep/creation/beanwithtransactionmanager/TestJobConfig.kt @@ -16,13 +16,13 @@ * limitations under the License. */ -package com.navercorp.spring.batch.plus.sample.step.taskletstep.bean +package com.navercorp.spring.batch.plus.sample.step.taskletstep.creation.beanwithtransactionmanager import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.Job import org.springframework.batch.core.configuration.annotation.StepScope +import org.springframework.batch.core.job.Job import org.springframework.batch.core.step.tasklet.Tasklet -import org.springframework.batch.repeat.RepeatStatus +import org.springframework.batch.infrastructure.repeat.RepeatStatus import org.springframework.beans.factory.annotation.Value import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration @@ -33,22 +33,23 @@ open class TestJobConfig( private val batch: BatchDsl, private val transactionManager: PlatformTransactionManager, ) { - @Bean - open fun testJob(): Job = batch { - job("testJob") { - step("testStep") { - taskletBean("testTasklet", transactionManager) + open fun testJob(): Job = + batch { + job("testJob") { + step("testStep") { + taskletBean("testTasklet", transactionManager) + } } } - } @Bean @StepScope open fun testTasklet( @Value("#{jobParameters['param']}") paramValue: String, - ): Tasklet = Tasklet { _, _ -> - println("param is '$paramValue'") - RepeatStatus.FINISHED - } + ): Tasklet = + Tasklet { _, _ -> + println("param is '$paramValue'") + RepeatStatus.FINISHED + } } diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/taskletstep/creation/variabledefaulttransactionmanager/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/taskletstep/creation/variabledefaulttransactionmanager/SampleApplicationTest.kt new file mode 100644 index 00000000..6e140db7 --- /dev/null +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/taskletstep/creation/variabledefaulttransactionmanager/SampleApplicationTest.kt @@ -0,0 +1,46 @@ +/* + * Spring Batch Plus + * + * Copyright 2022-present NAVER Corp. + * + * 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 + * + * http://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 com.navercorp.spring.batch.plus.sample.step.taskletstep.creation.variabledefaulttransactionmanager + +import org.junit.jupiter.api.Test +import org.springframework.batch.core.BatchStatus +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator +import org.springframework.beans.factory.getBean +import org.springframework.boot.autoconfigure.SpringBootApplication +import org.springframework.boot.runApplication + +@SpringBootApplication +open class SampleApplicationTest { + @Test + fun run() { + val applicationContext = runApplication() + val jobOperator = applicationContext.getBean() + val job = applicationContext.getBean() + + val jobParameters = + JobParametersBuilder() + .toJobParameters() + val jobExecution = jobOperator.start(job, jobParameters) + + assert(BatchStatus.COMPLETED == jobExecution.status) + println(jobExecution) + } +} diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/configuration/meterregistry/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/taskletstep/creation/variabledefaulttransactionmanager/TestJobConfig.kt similarity index 60% rename from spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/configuration/meterregistry/TestJobConfig.kt rename to spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/taskletstep/creation/variabledefaulttransactionmanager/TestJobConfig.kt index 3b9c0f67..efc2f687 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/configuration/meterregistry/TestJobConfig.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/taskletstep/creation/variabledefaulttransactionmanager/TestJobConfig.kt @@ -16,29 +16,33 @@ * limitations under the License. */ -package com.navercorp.spring.batch.plus.sample.step.configuration.meterregistry +package com.navercorp.spring.batch.plus.sample.step.taskletstep.creation.variabledefaulttransactionmanager import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import io.micrometer.core.instrument.simple.SimpleMeterRegistry -import org.springframework.batch.core.Job -import org.springframework.batch.repeat.RepeatStatus +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.step.tasklet.Tasklet +import org.springframework.batch.infrastructure.repeat.RepeatStatus import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration -import org.springframework.transaction.PlatformTransactionManager @Configuration open class TestJobConfig( private val batch: BatchDsl, - private val transactionManager: PlatformTransactionManager, ) { - @Bean - open fun testJob(): Job = batch { - job("testJob") { - step("testStep") { - meterRegistry(SimpleMeterRegistry()) - tasklet({ _, _ -> RepeatStatus.FINISHED }, transactionManager) + open fun testJob(): Job = + batch { + job("testJob") { + step("testStep") { + tasklet(testTasklet()) + } } } - } + + @Bean + open fun testTasklet(): Tasklet = + Tasklet { _, _ -> + println("run testTasklet") + RepeatStatus.FINISHED + } } diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/taskletstep/variable/SampleApplicationTest.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/taskletstep/creation/variablewithtransactionmanager/SampleApplicationTest.kt similarity index 73% rename from spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/taskletstep/variable/SampleApplicationTest.kt rename to spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/taskletstep/creation/variablewithtransactionmanager/SampleApplicationTest.kt index 8648c5bc..10a3d8e4 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/taskletstep/variable/SampleApplicationTest.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/taskletstep/creation/variablewithtransactionmanager/SampleApplicationTest.kt @@ -16,13 +16,13 @@ * limitations under the License. */ -package com.navercorp.spring.batch.plus.sample.step.taskletstep.variable +package com.navercorp.spring.batch.plus.sample.step.taskletstep.creation.variablewithtransactionmanager import org.junit.jupiter.api.Test import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator import org.springframework.beans.factory.getBean import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.runApplication @@ -32,12 +32,13 @@ open class SampleApplicationTest { @Test fun run() { val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() + val jobOperator = applicationContext.getBean() val job = applicationContext.getBean() - val jobParameters = JobParametersBuilder() - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) + val jobParameters = + JobParametersBuilder() + .toJobParameters() + val jobExecution = jobOperator.start(job, jobParameters) assert(BatchStatus.COMPLETED == jobExecution.status) println(jobExecution) diff --git a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/taskletstep/variable/TestJobConfig.kt b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/taskletstep/creation/variablewithtransactionmanager/TestJobConfig.kt similarity index 70% rename from spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/taskletstep/variable/TestJobConfig.kt rename to spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/taskletstep/creation/variablewithtransactionmanager/TestJobConfig.kt index 75b80ff4..57b7aec2 100644 --- a/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/taskletstep/variable/TestJobConfig.kt +++ b/spring-batch-plus-sample/kotlin-dsl-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/step/taskletstep/creation/variablewithtransactionmanager/TestJobConfig.kt @@ -16,12 +16,12 @@ * limitations under the License. */ -package com.navercorp.spring.batch.plus.sample.step.taskletstep.variable +package com.navercorp.spring.batch.plus.sample.step.taskletstep.creation.variablewithtransactionmanager import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl -import org.springframework.batch.core.Job +import org.springframework.batch.core.job.Job import org.springframework.batch.core.step.tasklet.Tasklet -import org.springframework.batch.repeat.RepeatStatus +import org.springframework.batch.infrastructure.repeat.RepeatStatus import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.transaction.PlatformTransactionManager @@ -31,19 +31,20 @@ open class TestJobConfig( private val batch: BatchDsl, private val transactionManager: PlatformTransactionManager, ) { - @Bean - open fun testJob(): Job = batch { - job("testJob") { - step("testStep") { - tasklet(testTasklet(), transactionManager) + open fun testJob(): Job = + batch { + job("testJob") { + step("testStep") { + tasklet(testTasklet(), transactionManager) + } } } - } @Bean - open fun testTasklet(): Tasklet = Tasklet { _, _ -> - println("run testTasklet") - RepeatStatus.FINISHED - } + open fun testTasklet(): Tasklet = + Tasklet { _, _ -> + println("run testTasklet") + RepeatStatus.FINISHED + } } diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/build.gradle.kts b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/build.gradle.kts index 3b3c9145..77eb3465 100644 --- a/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/build.gradle.kts +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/build.gradle.kts @@ -1,3 +1,5 @@ +import org.jetbrains.kotlin.gradle.dsl.JvmTarget + buildscript { repositories { gradlePluginPortal() // give accees to gradle community plugins @@ -17,12 +19,9 @@ repositories { kotlin { jvmToolchain(17) -} - -tasks.withType { - kotlinOptions { + compilerOptions { freeCompilerArgs = listOf("-Xjsr305=strict") // enable jsr305 null-safety in kotlin - jvmTarget = "17" + jvmTarget = JvmTarget.JVM_17 } } @@ -33,15 +32,15 @@ tasks.named("test") { dependencyManagement { imports { - mavenBom("org.springframework.boot:spring-boot-dependencies:3.5.0") + mavenBom("org.springframework.boot:spring-boot-dependencies:4.0.7") } } dependencies { - implementation("org.springframework.boot:spring-boot-starter-batch") + implementation("org.springframework.boot:spring-boot-starter-batch-jdbc") implementation(project(":spring-boot-starter-batch-plus-kotlin")) implementation("io.projectreactor:reactor-core:3.5.0") - runtimeOnly("com.h2database:h2:2.1.214") + runtimeOnly("com.h2database:h2:2.4.240") testImplementation("org.springframework.boot:spring-boot-starter-test") testRuntimeOnly("org.junit.platform:junit-platform-launcher") diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/flux/README.md b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/flux/README.md new file mode 100644 index 00000000..02f0ac45 --- /dev/null +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/flux/README.md @@ -0,0 +1,8 @@ +# Flux Reader Adapter Samples + +## Invariants + +- Samples should cover a single delegate whose reader produces items as a `Flux`. +- Every supported combination of reader, processor, and writer roles should have + a runnable sample. +- Lifecycle callback support should have a runnable sample. diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/flux/callback/SampleApplicationTest.kt b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/flux/callback/SampleApplicationTest.kt index 0681d417..39f379df 100644 --- a/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/flux/callback/SampleApplicationTest.kt +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/flux/callback/SampleApplicationTest.kt @@ -20,9 +20,9 @@ package com.navercorp.spring.batch.plus.sample.flux.callback import org.junit.jupiter.api.Test import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator import org.springframework.beans.factory.getBean import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.runApplication @@ -32,13 +32,14 @@ open class SampleApplicationTest { @Test fun run() { val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() + val jobOperator = applicationContext.getBean() val job = applicationContext.getBean("testJob") - val jobParameters = JobParametersBuilder() - .addLong("totalCount", 20L) - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) + val jobParameters = + JobParametersBuilder() + .addLong("totalCount", 20L) + .toJobParameters() + val jobExecution = jobOperator.start(job, jobParameters) assert(BatchStatus.COMPLETED == jobExecution.status) println(jobExecution) diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/flux/callback/SampleTasklet.kt b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/flux/callback/SampleTasklet.kt index 7e6c638f..004ac1a0 100644 --- a/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/flux/callback/SampleTasklet.kt +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/flux/callback/SampleTasklet.kt @@ -20,8 +20,8 @@ package com.navercorp.spring.batch.plus.sample.flux.callback import com.navercorp.spring.batch.plus.step.adapter.ItemStreamFluxReaderProcessorWriter import org.springframework.batch.core.configuration.annotation.StepScope -import org.springframework.batch.item.Chunk -import org.springframework.batch.item.ExecutionContext +import org.springframework.batch.infrastructure.item.Chunk +import org.springframework.batch.infrastructure.item.ExecutionContext import org.springframework.beans.factory.annotation.Value import org.springframework.stereotype.Component import reactor.core.publisher.Flux @@ -29,7 +29,7 @@ import reactor.core.publisher.Flux @Component @StepScope open class SampleTasklet( - @Value("#{jobParameters['totalCount']}") private var totalCount: Long, + @param:Value("#{jobParameters['totalCount']}") private var totalCount: Long, ) : ItemStreamFluxReaderProcessorWriter { private var count = 0 @@ -57,9 +57,7 @@ open class SampleTasklet( println("onCloseRead") } - override fun process(item: Int): String? { - return "'$item'" - } + override fun process(item: Int): String? = "'$item'" override fun onOpenWrite(executionContext: ExecutionContext) { println("onOpenWrite") diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/flux/callback/TestJobConfig.kt b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/flux/callback/TestJobConfig.kt index c63c7af8..6d533545 100644 --- a/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/flux/callback/TestJobConfig.kt +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/flux/callback/TestJobConfig.kt @@ -22,7 +22,7 @@ import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl import com.navercorp.spring.batch.plus.kotlin.step.adapter.asItemProcessor import com.navercorp.spring.batch.plus.kotlin.step.adapter.asItemStreamReader import com.navercorp.spring.batch.plus.kotlin.step.adapter.asItemStreamWriter -import org.springframework.batch.core.Job +import org.springframework.batch.core.job.Job import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.transaction.PlatformTransactionManager @@ -32,19 +32,18 @@ open class TestJobConfig( private val batch: BatchDsl, private val transactionManager: PlatformTransactionManager, ) { - @Bean - open fun testJob( - sampleTasklet: com.navercorp.spring.batch.plus.sample.flux.callback.SampleTasklet, - ): Job = batch { - job("testJob") { - step("testStep") { - chunk(3, transactionManager) { - reader(sampleTasklet.asItemStreamReader()) - processor(sampleTasklet.asItemProcessor()) - writer(sampleTasklet.asItemStreamWriter()) + open fun testJob(sampleTasklet: SampleTasklet): Job = + batch { + job("testJob") { + step("testStep") { + chunk(3) { + transactionManager(transactionManager) + reader(sampleTasklet.asItemStreamReader()) + processor(sampleTasklet.asItemProcessor()) + writer(sampleTasklet.asItemStreamWriter()) + } } } } - } } diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/flux/readerprocessor/SampleApplicationTest.kt b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/flux/readerprocessor/SampleApplicationTest.kt index d00f4482..9d548839 100644 --- a/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/flux/readerprocessor/SampleApplicationTest.kt +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/flux/readerprocessor/SampleApplicationTest.kt @@ -20,9 +20,9 @@ package com.navercorp.spring.batch.plus.sample.flux.readerprocessor import org.junit.jupiter.api.Test import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator import org.springframework.beans.factory.getBean import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.runApplication @@ -32,13 +32,14 @@ open class SampleApplicationTest { @Test fun run() { val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() + val jobOperator = applicationContext.getBean() val job = applicationContext.getBean("testJob") - val jobParameters = JobParametersBuilder() - .addLong("totalCount", 20L) - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) + val jobParameters = + JobParametersBuilder() + .addLong("totalCount", 20L) + .toJobParameters() + val jobExecution = jobOperator.start(job, jobParameters) assert(BatchStatus.COMPLETED == jobExecution.status) println(jobExecution) diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/flux/readerprocessor/SampleTasklet.kt b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/flux/readerprocessor/SampleTasklet.kt index 6d0ec653..c997f729 100644 --- a/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/flux/readerprocessor/SampleTasklet.kt +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/flux/readerprocessor/SampleTasklet.kt @@ -20,7 +20,7 @@ package com.navercorp.spring.batch.plus.sample.flux.readerprocessor import com.navercorp.spring.batch.plus.step.adapter.ItemStreamFluxReaderProcessor import org.springframework.batch.core.configuration.annotation.StepScope -import org.springframework.batch.item.ExecutionContext +import org.springframework.batch.infrastructure.item.ExecutionContext import org.springframework.beans.factory.annotation.Value import org.springframework.stereotype.Component import reactor.core.publisher.Flux @@ -28,7 +28,7 @@ import reactor.core.publisher.Flux @Component @StepScope open class SampleTasklet( - @Value("#{jobParameters['totalCount']}") private var totalCount: Long, + @param:Value("#{jobParameters['totalCount']}") private var totalCount: Long, ) : ItemStreamFluxReaderProcessor { private var count = 0 @@ -44,7 +44,5 @@ open class SampleTasklet( } } - override fun process(item: Int): String? { - return "'$item'" - } + override fun process(item: Int): String? = "'$item'" } diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/flux/readerprocessor/TestJobConfig.kt b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/flux/readerprocessor/TestJobConfig.kt index 23dc2f79..ba9b9db0 100644 --- a/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/flux/readerprocessor/TestJobConfig.kt +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/flux/readerprocessor/TestJobConfig.kt @@ -21,7 +21,7 @@ package com.navercorp.spring.batch.plus.sample.flux.readerprocessor import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl import com.navercorp.spring.batch.plus.kotlin.step.adapter.asItemProcessor import com.navercorp.spring.batch.plus.kotlin.step.adapter.asItemStreamReader -import org.springframework.batch.core.Job +import org.springframework.batch.core.job.Job import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.transaction.PlatformTransactionManager @@ -32,17 +32,17 @@ open class TestJobConfig( private val transactionManager: PlatformTransactionManager, ) { @Bean - open fun testJob( - sampleTasklet: SampleTasklet, - ): Job = batch { - job("testJob") { - step("testStep") { - chunk(3, transactionManager) { - reader(sampleTasklet.asItemStreamReader()) - processor(sampleTasklet.asItemProcessor()) - writer { chunk -> println(chunk.items) } + open fun testJob(sampleTasklet: SampleTasklet): Job = + batch { + job("testJob") { + step("testStep") { + chunk(3) { + transactionManager(transactionManager) + reader(sampleTasklet.asItemStreamReader()) + processor(sampleTasklet.asItemProcessor()) + writer { chunk -> println(chunk.items) } + } } } } - } } diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/flux/readerprocessorwriter/SampleApplicationTest.kt b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/flux/readerprocessorwriter/SampleApplicationTest.kt index d5626923..63926089 100644 --- a/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/flux/readerprocessorwriter/SampleApplicationTest.kt +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/flux/readerprocessorwriter/SampleApplicationTest.kt @@ -20,9 +20,9 @@ package com.navercorp.spring.batch.plus.sample.flux.readerprocessorwriter import org.junit.jupiter.api.Test import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator import org.springframework.beans.factory.getBean import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.runApplication @@ -32,13 +32,14 @@ open class SampleApplicationTest { @Test fun run() { val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() + val jobOperator = applicationContext.getBean() val job = applicationContext.getBean("testJob") - val jobParameters = JobParametersBuilder() - .addLong("totalCount", 20L) - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) + val jobParameters = + JobParametersBuilder() + .addLong("totalCount", 20L) + .toJobParameters() + val jobExecution = jobOperator.start(job, jobParameters) assert(BatchStatus.COMPLETED == jobExecution.status) println(jobExecution) diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/flux/readerprocessorwriter/SampleTasklet.kt b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/flux/readerprocessorwriter/SampleTasklet.kt index 8dfceb32..e664f436 100644 --- a/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/flux/readerprocessorwriter/SampleTasklet.kt +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/flux/readerprocessorwriter/SampleTasklet.kt @@ -20,8 +20,8 @@ package com.navercorp.spring.batch.plus.sample.flux.readerprocessorwriter import com.navercorp.spring.batch.plus.step.adapter.ItemStreamFluxReaderProcessorWriter import org.springframework.batch.core.configuration.annotation.StepScope -import org.springframework.batch.item.Chunk -import org.springframework.batch.item.ExecutionContext +import org.springframework.batch.infrastructure.item.Chunk +import org.springframework.batch.infrastructure.item.ExecutionContext import org.springframework.beans.factory.annotation.Value import org.springframework.stereotype.Component import reactor.core.publisher.Flux @@ -29,7 +29,7 @@ import reactor.core.publisher.Flux @Component @StepScope open class SampleTasklet( - @Value("#{jobParameters['totalCount']}") private var totalCount: Long, + @param:Value("#{jobParameters['totalCount']}") private var totalCount: Long, ) : ItemStreamFluxReaderProcessorWriter { private var count = 0 @@ -45,9 +45,7 @@ open class SampleTasklet( } } - override fun process(item: Int): String? { - return "'$item'" - } + override fun process(item: Int): String? = "'$item'" override fun write(chunk: Chunk) { println(chunk.items) diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/flux/readerprocessorwriter/TestJobConfig.kt b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/flux/readerprocessorwriter/TestJobConfig.kt index 5bd4c41c..9c2cb02d 100644 --- a/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/flux/readerprocessorwriter/TestJobConfig.kt +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/flux/readerprocessorwriter/TestJobConfig.kt @@ -22,7 +22,7 @@ import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl import com.navercorp.spring.batch.plus.kotlin.step.adapter.asItemProcessor import com.navercorp.spring.batch.plus.kotlin.step.adapter.asItemStreamReader import com.navercorp.spring.batch.plus.kotlin.step.adapter.asItemStreamWriter -import org.springframework.batch.core.Job +import org.springframework.batch.core.job.Job import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.transaction.PlatformTransactionManager @@ -33,17 +33,17 @@ open class TestJobConfig( private val transactionManager: PlatformTransactionManager, ) { @Bean - open fun testJob( - sampleTasklet: com.navercorp.spring.batch.plus.sample.flux.readerprocessorwriter.SampleTasklet, - ): Job = batch { - job("testJob") { - step("testStep") { - chunk(3, transactionManager) { - reader(sampleTasklet.asItemStreamReader()) - processor(sampleTasklet.asItemProcessor()) - writer(sampleTasklet.asItemStreamWriter()) + open fun testJob(sampleTasklet: SampleTasklet): Job = + batch { + job("testJob") { + step("testStep") { + chunk(3) { + transactionManager(transactionManager) + reader(sampleTasklet.asItemStreamReader()) + processor(sampleTasklet.asItemProcessor()) + writer(sampleTasklet.asItemStreamWriter()) + } } } } - } } diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/flux/readerwriter/SampleApplicationTest.kt b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/flux/readerwriter/SampleApplicationTest.kt index 22ab239d..fb5c81af 100644 --- a/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/flux/readerwriter/SampleApplicationTest.kt +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/flux/readerwriter/SampleApplicationTest.kt @@ -20,9 +20,9 @@ package com.navercorp.spring.batch.plus.sample.flux.readerwriter import org.junit.jupiter.api.Test import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator import org.springframework.beans.factory.getBean import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.runApplication @@ -32,13 +32,14 @@ open class SampleApplicationTest { @Test fun run() { val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() + val jobOperator = applicationContext.getBean() val job = applicationContext.getBean("testJob") - val jobParameters = JobParametersBuilder() - .addLong("totalCount", 20L) - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) + val jobParameters = + JobParametersBuilder() + .addLong("totalCount", 20L) + .toJobParameters() + val jobExecution = jobOperator.start(job, jobParameters) assert(BatchStatus.COMPLETED == jobExecution.status) println(jobExecution) diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/flux/readerwriter/SampleTasklet.kt b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/flux/readerwriter/SampleTasklet.kt index 7617a974..e3254c73 100644 --- a/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/flux/readerwriter/SampleTasklet.kt +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/flux/readerwriter/SampleTasklet.kt @@ -20,8 +20,8 @@ package com.navercorp.spring.batch.plus.sample.flux.readerwriter import com.navercorp.spring.batch.plus.step.adapter.ItemStreamFluxReaderWriter import org.springframework.batch.core.configuration.annotation.StepScope -import org.springframework.batch.item.Chunk -import org.springframework.batch.item.ExecutionContext +import org.springframework.batch.infrastructure.item.Chunk +import org.springframework.batch.infrastructure.item.ExecutionContext import org.springframework.beans.factory.annotation.Value import org.springframework.stereotype.Component import reactor.core.publisher.Flux @@ -29,7 +29,7 @@ import reactor.core.publisher.Flux @Component @StepScope open class SampleTasklet( - @Value("#{jobParameters['totalCount']}") private var totalCount: Long, + @param:Value("#{jobParameters['totalCount']}") private var totalCount: Long, ) : ItemStreamFluxReaderWriter { private var count = 0 diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/flux/readerwriter/TestJobConfig.kt b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/flux/readerwriter/TestJobConfig.kt index 06fcbc9a..e7e9f720 100644 --- a/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/flux/readerwriter/TestJobConfig.kt +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/flux/readerwriter/TestJobConfig.kt @@ -21,7 +21,7 @@ package com.navercorp.spring.batch.plus.sample.flux.readerwriter import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl import com.navercorp.spring.batch.plus.kotlin.step.adapter.asItemStreamReader import com.navercorp.spring.batch.plus.kotlin.step.adapter.asItemStreamWriter -import org.springframework.batch.core.Job +import org.springframework.batch.core.job.Job import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.transaction.PlatformTransactionManager @@ -31,18 +31,17 @@ open class TestJobConfig( private val batch: BatchDsl, private val transactionManager: PlatformTransactionManager, ) { - @Bean - open fun testJob( - sampleTasklet: com.navercorp.spring.batch.plus.sample.flux.readerwriter.SampleTasklet, - ): Job = batch { - job("testJob") { - step("testStep") { - chunk(3, transactionManager) { - reader(sampleTasklet.asItemStreamReader()) - writer(sampleTasklet.asItemStreamWriter()) + open fun testJob(sampleTasklet: SampleTasklet): Job = + batch { + job("testJob") { + step("testStep") { + chunk(3) { + transactionManager(transactionManager) + reader(sampleTasklet.asItemStreamReader()) + writer(sampleTasklet.asItemStreamWriter()) + } } } } - } } diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/iterable/README.md b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/iterable/README.md new file mode 100644 index 00000000..694c7631 --- /dev/null +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/iterable/README.md @@ -0,0 +1,9 @@ +# Iterable Reader Adapter Samples + +## Invariants + +- Samples should cover a single delegate whose reader produces items as an + `Iterable`. +- Every supported combination of reader, processor, and writer roles should have + a runnable sample. +- Lifecycle callback support should have a runnable sample. diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/iterable/callback/SampleApplicationTest.kt b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/iterable/callback/SampleApplicationTest.kt index 41a1d88c..21f6d063 100644 --- a/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/iterable/callback/SampleApplicationTest.kt +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/iterable/callback/SampleApplicationTest.kt @@ -20,9 +20,9 @@ package com.navercorp.spring.batch.plus.sample.iterable.callback import org.junit.jupiter.api.Test import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator import org.springframework.beans.factory.getBean import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.runApplication @@ -32,13 +32,14 @@ open class SampleApplicationTest { @Test fun run() { val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() + val jobOperator = applicationContext.getBean() val job = applicationContext.getBean("testJob") - val jobParameters = JobParametersBuilder() - .addLong("totalCount", 20L) - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) + val jobParameters = + JobParametersBuilder() + .addLong("totalCount", 20L) + .toJobParameters() + val jobExecution = jobOperator.start(job, jobParameters) assert(BatchStatus.COMPLETED == jobExecution.status) println(jobExecution) diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/iterable/callback/SampleTasklet.kt b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/iterable/callback/SampleTasklet.kt index d11aef68..090c8a4a 100644 --- a/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/iterable/callback/SampleTasklet.kt +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/iterable/callback/SampleTasklet.kt @@ -20,15 +20,15 @@ package com.navercorp.spring.batch.plus.sample.iterable.callback import com.navercorp.spring.batch.plus.step.adapter.ItemStreamIterableReaderProcessorWriter import org.springframework.batch.core.configuration.annotation.StepScope -import org.springframework.batch.item.Chunk -import org.springframework.batch.item.ExecutionContext +import org.springframework.batch.infrastructure.item.Chunk +import org.springframework.batch.infrastructure.item.ExecutionContext import org.springframework.beans.factory.annotation.Value import org.springframework.stereotype.Component @Component @StepScope open class SampleTasklet( - @Value("#{jobParameters['totalCount']}") private var totalCount: Long, + @param:Value("#{jobParameters['totalCount']}") private var totalCount: Long, ) : ItemStreamIterableReaderProcessorWriter { private var count = 0 @@ -40,13 +40,9 @@ open class SampleTasklet( println("totalCount: $totalCount") return Iterable { object : Iterator { - override fun hasNext(): Boolean { - return count < totalCount - } + override fun hasNext(): Boolean = count < totalCount - override fun next(): Int { - return count++ - } + override fun next(): Int = count++ } } } @@ -59,9 +55,7 @@ open class SampleTasklet( println("onCloseRead") } - override fun process(item: Int): String? { - return "'$item'" - } + override fun process(item: Int): String? = "'$item'" override fun onOpenWrite(executionContext: ExecutionContext) { println("onOpenWrite") diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/iterable/callback/TestJobConfig.kt b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/iterable/callback/TestJobConfig.kt index c21741e9..2b74bcc2 100644 --- a/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/iterable/callback/TestJobConfig.kt +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/iterable/callback/TestJobConfig.kt @@ -22,7 +22,7 @@ import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl import com.navercorp.spring.batch.plus.kotlin.step.adapter.asItemProcessor import com.navercorp.spring.batch.plus.kotlin.step.adapter.asItemStreamReader import com.navercorp.spring.batch.plus.kotlin.step.adapter.asItemStreamWriter -import org.springframework.batch.core.Job +import org.springframework.batch.core.job.Job import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.transaction.PlatformTransactionManager @@ -32,19 +32,18 @@ open class TestJobConfig( private val batch: BatchDsl, private val transactionManager: PlatformTransactionManager, ) { - @Bean - open fun testJob( - sampleTasklet: com.navercorp.spring.batch.plus.sample.iterable.callback.SampleTasklet, - ): Job = batch { - job("testJob") { - step("testStep") { - chunk(3, transactionManager) { - reader(sampleTasklet.asItemStreamReader()) - processor(sampleTasklet.asItemProcessor()) - writer(sampleTasklet.asItemStreamWriter()) + open fun testJob(sampleTasklet: SampleTasklet): Job = + batch { + job("testJob") { + step("testStep") { + chunk(3) { + transactionManager(transactionManager) + reader(sampleTasklet.asItemStreamReader()) + processor(sampleTasklet.asItemProcessor()) + writer(sampleTasklet.asItemStreamWriter()) + } } } } - } } diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/iterable/readerprocessor/SampleApplicationTest.kt b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/iterable/readerprocessor/SampleApplicationTest.kt index e808d9a0..bef074ea 100644 --- a/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/iterable/readerprocessor/SampleApplicationTest.kt +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/iterable/readerprocessor/SampleApplicationTest.kt @@ -20,9 +20,9 @@ package com.navercorp.spring.batch.plus.sample.iterable.readerprocessor import org.junit.jupiter.api.Test import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator import org.springframework.beans.factory.getBean import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.runApplication @@ -32,13 +32,14 @@ open class SampleApplicationTest { @Test fun run() { val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() + val jobOperator = applicationContext.getBean() val job = applicationContext.getBean("testJob") - val jobParameters = JobParametersBuilder() - .addLong("totalCount", 20L) - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) + val jobParameters = + JobParametersBuilder() + .addLong("totalCount", 20L) + .toJobParameters() + val jobExecution = jobOperator.start(job, jobParameters) assert(BatchStatus.COMPLETED == jobExecution.status) println(jobExecution) diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/iterable/readerprocessor/SampleTasklet.kt b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/iterable/readerprocessor/SampleTasklet.kt index 1ad20bc1..199fe8a4 100644 --- a/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/iterable/readerprocessor/SampleTasklet.kt +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/iterable/readerprocessor/SampleTasklet.kt @@ -20,14 +20,14 @@ package com.navercorp.spring.batch.plus.sample.iterable.readerprocessor import com.navercorp.spring.batch.plus.step.adapter.ItemStreamIterableReaderProcessor import org.springframework.batch.core.configuration.annotation.StepScope -import org.springframework.batch.item.ExecutionContext +import org.springframework.batch.infrastructure.item.ExecutionContext import org.springframework.beans.factory.annotation.Value import org.springframework.stereotype.Component @Component @StepScope open class SampleTasklet( - @Value("#{jobParameters['totalCount']}") private var totalCount: Long, + @param:Value("#{jobParameters['totalCount']}") private var totalCount: Long, ) : ItemStreamIterableReaderProcessor { private var count = 0 @@ -35,18 +35,12 @@ open class SampleTasklet( println("totalCount: $totalCount") return Iterable { object : Iterator { - override fun hasNext(): Boolean { - return count < totalCount - } + override fun hasNext(): Boolean = count < totalCount - override fun next(): Int { - return count++ - } + override fun next(): Int = count++ } } } - override fun process(item: Int): String? { - return "'$item'" - } + override fun process(item: Int): String? = "'$item'" } diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/iterable/readerprocessor/TestJobConfig.kt b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/iterable/readerprocessor/TestJobConfig.kt index 1da5c164..37bc6fbc 100644 --- a/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/iterable/readerprocessor/TestJobConfig.kt +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/iterable/readerprocessor/TestJobConfig.kt @@ -21,7 +21,7 @@ package com.navercorp.spring.batch.plus.sample.iterable.readerprocessor import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl import com.navercorp.spring.batch.plus.kotlin.step.adapter.asItemProcessor import com.navercorp.spring.batch.plus.kotlin.step.adapter.asItemStreamReader -import org.springframework.batch.core.Job +import org.springframework.batch.core.job.Job import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.transaction.PlatformTransactionManager @@ -32,17 +32,17 @@ open class TestJobConfig( private val transactionManager: PlatformTransactionManager, ) { @Bean - open fun testJob( - sampleTasklet: SampleTasklet, - ): Job = batch { - job("testJob") { - step("testStep") { - chunk(3, transactionManager) { - reader(sampleTasklet.asItemStreamReader()) - processor(sampleTasklet.asItemProcessor()) - writer { chunk -> println(chunk.items) } + open fun testJob(sampleTasklet: SampleTasklet): Job = + batch { + job("testJob") { + step("testStep") { + chunk(3) { + transactionManager(transactionManager) + reader(sampleTasklet.asItemStreamReader()) + processor(sampleTasklet.asItemProcessor()) + writer { chunk -> println(chunk.items) } + } } } } - } } diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/iterable/readerprocessorwriter/SampleApplicationTest.kt b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/iterable/readerprocessorwriter/SampleApplicationTest.kt index 139d559a..80e39d2a 100644 --- a/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/iterable/readerprocessorwriter/SampleApplicationTest.kt +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/iterable/readerprocessorwriter/SampleApplicationTest.kt @@ -20,9 +20,9 @@ package com.navercorp.spring.batch.plus.sample.iterable.readerprocessorwriter import org.junit.jupiter.api.Test import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator import org.springframework.beans.factory.getBean import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.runApplication @@ -32,13 +32,14 @@ open class SampleApplicationTest { @Test fun run() { val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() + val jobOperator = applicationContext.getBean() val job = applicationContext.getBean("testJob") - val jobParameters = JobParametersBuilder() - .addLong("totalCount", 20L) - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) + val jobParameters = + JobParametersBuilder() + .addLong("totalCount", 20L) + .toJobParameters() + val jobExecution = jobOperator.start(job, jobParameters) assert(BatchStatus.COMPLETED == jobExecution.status) println(jobExecution) diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/iterable/readerprocessorwriter/SampleTasklet.kt b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/iterable/readerprocessorwriter/SampleTasklet.kt index f37734a7..dae95f9b 100644 --- a/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/iterable/readerprocessorwriter/SampleTasklet.kt +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/iterable/readerprocessorwriter/SampleTasklet.kt @@ -20,15 +20,15 @@ package com.navercorp.spring.batch.plus.sample.iterable.readerprocessorwriter import com.navercorp.spring.batch.plus.step.adapter.ItemStreamIterableReaderProcessorWriter import org.springframework.batch.core.configuration.annotation.StepScope -import org.springframework.batch.item.Chunk -import org.springframework.batch.item.ExecutionContext +import org.springframework.batch.infrastructure.item.Chunk +import org.springframework.batch.infrastructure.item.ExecutionContext import org.springframework.beans.factory.annotation.Value import org.springframework.stereotype.Component @Component @StepScope open class SampleTasklet( - @Value("#{jobParameters['totalCount']}") private var totalCount: Long, + @param:Value("#{jobParameters['totalCount']}") private var totalCount: Long, ) : ItemStreamIterableReaderProcessorWriter { private var count = 0 @@ -36,20 +36,14 @@ open class SampleTasklet( println("totalCount: $totalCount") return Iterable { object : Iterator { - override fun hasNext(): Boolean { - return count < totalCount - } + override fun hasNext(): Boolean = count < totalCount - override fun next(): Int { - return count++ - } + override fun next(): Int = count++ } } } - override fun process(item: Int): String? { - return "'$item'" - } + override fun process(item: Int): String? = "'$item'" override fun write(chunk: Chunk) { println(chunk.items) diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/iterable/readerprocessorwriter/TestJobConfig.kt b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/iterable/readerprocessorwriter/TestJobConfig.kt index 03f8c4c2..be2345a0 100644 --- a/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/iterable/readerprocessorwriter/TestJobConfig.kt +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/iterable/readerprocessorwriter/TestJobConfig.kt @@ -22,7 +22,7 @@ import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl import com.navercorp.spring.batch.plus.kotlin.step.adapter.asItemProcessor import com.navercorp.spring.batch.plus.kotlin.step.adapter.asItemStreamReader import com.navercorp.spring.batch.plus.kotlin.step.adapter.asItemStreamWriter -import org.springframework.batch.core.Job +import org.springframework.batch.core.job.Job import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.transaction.PlatformTransactionManager @@ -33,17 +33,17 @@ open class TestJobConfig( private val transactionManager: PlatformTransactionManager, ) { @Bean - open fun testJob( - sampleTasklet: com.navercorp.spring.batch.plus.sample.iterable.readerprocessorwriter.SampleTasklet, - ): Job = batch { - job("testJob") { - step("testStep") { - chunk(3, transactionManager) { - reader(sampleTasklet.asItemStreamReader()) - processor(sampleTasklet.asItemProcessor()) - writer(sampleTasklet.asItemStreamWriter()) + open fun testJob(sampleTasklet: SampleTasklet): Job = + batch { + job("testJob") { + step("testStep") { + chunk(3) { + transactionManager(transactionManager) + reader(sampleTasklet.asItemStreamReader()) + processor(sampleTasklet.asItemProcessor()) + writer(sampleTasklet.asItemStreamWriter()) + } } } } - } } diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/iterable/readerwriter/SampleApplicationTest.kt b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/iterable/readerwriter/SampleApplicationTest.kt index eee53a24..46b0390b 100644 --- a/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/iterable/readerwriter/SampleApplicationTest.kt +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/iterable/readerwriter/SampleApplicationTest.kt @@ -20,9 +20,9 @@ package com.navercorp.spring.batch.plus.sample.iterable.readerwriter import org.junit.jupiter.api.Test import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator import org.springframework.beans.factory.getBean import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.runApplication @@ -32,13 +32,14 @@ open class SampleApplicationTest { @Test fun run() { val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() + val jobOperator = applicationContext.getBean() val job = applicationContext.getBean("testJob") - val jobParameters = JobParametersBuilder() - .addLong("totalCount", 20L) - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) + val jobParameters = + JobParametersBuilder() + .addLong("totalCount", 20L) + .toJobParameters() + val jobExecution = jobOperator.start(job, jobParameters) assert(BatchStatus.COMPLETED == jobExecution.status) println(jobExecution) diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/iterable/readerwriter/SampleTasklet.kt b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/iterable/readerwriter/SampleTasklet.kt index 46e43f2b..4d8c625e 100644 --- a/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/iterable/readerwriter/SampleTasklet.kt +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/iterable/readerwriter/SampleTasklet.kt @@ -20,15 +20,15 @@ package com.navercorp.spring.batch.plus.sample.iterable.readerwriter import com.navercorp.spring.batch.plus.step.adapter.ItemStreamIterableReaderWriter import org.springframework.batch.core.configuration.annotation.StepScope -import org.springframework.batch.item.Chunk -import org.springframework.batch.item.ExecutionContext +import org.springframework.batch.infrastructure.item.Chunk +import org.springframework.batch.infrastructure.item.ExecutionContext import org.springframework.beans.factory.annotation.Value import org.springframework.stereotype.Component @Component @StepScope open class SampleTasklet( - @Value("#{jobParameters['totalCount']}") private var totalCount: Long, + @param:Value("#{jobParameters['totalCount']}") private var totalCount: Long, ) : ItemStreamIterableReaderWriter { private var count = 0 @@ -36,13 +36,9 @@ open class SampleTasklet( println("totalCount: $totalCount") return Iterable { object : Iterator { - override fun hasNext(): Boolean { - return count < totalCount - } + override fun hasNext(): Boolean = count < totalCount - override fun next(): Int { - return count++ - } + override fun next(): Int = count++ } } } diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/iterable/readerwriter/TestJobConfig.kt b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/iterable/readerwriter/TestJobConfig.kt index de584d52..c296deb2 100644 --- a/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/iterable/readerwriter/TestJobConfig.kt +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/iterable/readerwriter/TestJobConfig.kt @@ -21,7 +21,7 @@ package com.navercorp.spring.batch.plus.sample.iterable.readerwriter import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl import com.navercorp.spring.batch.plus.kotlin.step.adapter.asItemStreamReader import com.navercorp.spring.batch.plus.kotlin.step.adapter.asItemStreamWriter -import org.springframework.batch.core.Job +import org.springframework.batch.core.job.Job import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.transaction.PlatformTransactionManager @@ -31,18 +31,17 @@ open class TestJobConfig( private val batch: BatchDsl, private val transactionManager: PlatformTransactionManager, ) { - @Bean - open fun testJob( - sampleTasklet: com.navercorp.spring.batch.plus.sample.iterable.readerwriter.SampleTasklet, - ): Job = batch { - job("testJob") { - step("testStep") { - chunk(3, transactionManager) { - reader(sampleTasklet.asItemStreamReader()) - writer(sampleTasklet.asItemStreamWriter()) + open fun testJob(sampleTasklet: SampleTasklet): Job = + batch { + job("testJob") { + step("testStep") { + chunk(3) { + transactionManager(transactionManager) + reader(sampleTasklet.asItemStreamReader()) + writer(sampleTasklet.asItemStreamWriter()) + } } } } - } } diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/iterator/README.md b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/iterator/README.md new file mode 100644 index 00000000..f6bc3d38 --- /dev/null +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/iterator/README.md @@ -0,0 +1,9 @@ +# Iterator Reader Adapter Samples + +## Invariants + +- Samples should cover a single delegate whose reader produces items as an + `Iterator`. +- Every supported combination of reader, processor, and writer roles should have + a runnable sample. +- Lifecycle callback support should have a runnable sample. diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/iterator/callback/SampleApplicationTest.kt b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/iterator/callback/SampleApplicationTest.kt index 446c55da..3039a2f3 100644 --- a/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/iterator/callback/SampleApplicationTest.kt +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/iterator/callback/SampleApplicationTest.kt @@ -20,9 +20,9 @@ package com.navercorp.spring.batch.plus.sample.iterator.callback import org.junit.jupiter.api.Test import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator import org.springframework.beans.factory.getBean import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.runApplication @@ -32,13 +32,14 @@ open class SampleApplicationTest { @Test fun run() { val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() + val jobOperator = applicationContext.getBean() val job = applicationContext.getBean("testJob") - val jobParameters = JobParametersBuilder() - .addLong("totalCount", 20L) - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) + val jobParameters = + JobParametersBuilder() + .addLong("totalCount", 20L) + .toJobParameters() + val jobExecution = jobOperator.start(job, jobParameters) assert(BatchStatus.COMPLETED == jobExecution.status) println(jobExecution) diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/iterator/callback/SampleTasklet.kt b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/iterator/callback/SampleTasklet.kt index f2e4aa9d..f6e79ad4 100644 --- a/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/iterator/callback/SampleTasklet.kt +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/iterator/callback/SampleTasklet.kt @@ -20,15 +20,15 @@ package com.navercorp.spring.batch.plus.sample.iterator.callback import com.navercorp.spring.batch.plus.step.adapter.ItemStreamIteratorReaderProcessorWriter import org.springframework.batch.core.configuration.annotation.StepScope -import org.springframework.batch.item.Chunk -import org.springframework.batch.item.ExecutionContext +import org.springframework.batch.infrastructure.item.Chunk +import org.springframework.batch.infrastructure.item.ExecutionContext import org.springframework.beans.factory.annotation.Value import org.springframework.stereotype.Component @Component @StepScope open class SampleTasklet( - @Value("#{jobParameters['totalCount']}") private var totalCount: Long, + @param:Value("#{jobParameters['totalCount']}") private var totalCount: Long, ) : ItemStreamIteratorReaderProcessorWriter { private var count = 0 @@ -39,13 +39,9 @@ open class SampleTasklet( override fun readIterator(executionContext: ExecutionContext): Iterator { println("totalCount: $totalCount") return object : Iterator { - override fun hasNext(): Boolean { - return count < totalCount - } + override fun hasNext(): Boolean = count < totalCount - override fun next(): Int { - return count++ - } + override fun next(): Int = count++ } } @@ -57,9 +53,7 @@ open class SampleTasklet( println("onCloseRead") } - override fun process(item: Int): String? { - return "'$item'" - } + override fun process(item: Int): String? = "'$item'" override fun onOpenWrite(executionContext: ExecutionContext) { println("onOpenWrite") diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/iterator/callback/TestJobConfig.kt b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/iterator/callback/TestJobConfig.kt index 1152fde0..a4580934 100644 --- a/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/iterator/callback/TestJobConfig.kt +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/iterator/callback/TestJobConfig.kt @@ -22,7 +22,7 @@ import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl import com.navercorp.spring.batch.plus.kotlin.step.adapter.asItemProcessor import com.navercorp.spring.batch.plus.kotlin.step.adapter.asItemStreamReader import com.navercorp.spring.batch.plus.kotlin.step.adapter.asItemStreamWriter -import org.springframework.batch.core.Job +import org.springframework.batch.core.job.Job import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.transaction.PlatformTransactionManager @@ -32,19 +32,18 @@ open class TestJobConfig( private val batch: BatchDsl, private val transactionManager: PlatformTransactionManager, ) { - @Bean - open fun testJob( - sampleTasklet: com.navercorp.spring.batch.plus.sample.iterator.callback.SampleTasklet, - ): Job = batch { - job("testJob") { - step("testStep") { - chunk(3, transactionManager) { - reader(sampleTasklet.asItemStreamReader()) - processor(sampleTasklet.asItemProcessor()) - writer(sampleTasklet.asItemStreamWriter()) + open fun testJob(sampleTasklet: SampleTasklet): Job = + batch { + job("testJob") { + step("testStep") { + chunk(3) { + transactionManager(transactionManager) + reader(sampleTasklet.asItemStreamReader()) + processor(sampleTasklet.asItemProcessor()) + writer(sampleTasklet.asItemStreamWriter()) + } } } } - } } diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/iterator/readerprocessor/SampleApplicationTest.kt b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/iterator/readerprocessor/SampleApplicationTest.kt index cdecc7f8..801aecd2 100644 --- a/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/iterator/readerprocessor/SampleApplicationTest.kt +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/iterator/readerprocessor/SampleApplicationTest.kt @@ -20,9 +20,9 @@ package com.navercorp.spring.batch.plus.sample.iterator.readerprocessor import org.junit.jupiter.api.Test import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator import org.springframework.beans.factory.getBean import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.runApplication @@ -32,13 +32,14 @@ open class SampleApplicationTest { @Test fun run() { val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() + val jobOperator = applicationContext.getBean() val job = applicationContext.getBean("testJob") - val jobParameters = JobParametersBuilder() - .addLong("totalCount", 20L) - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) + val jobParameters = + JobParametersBuilder() + .addLong("totalCount", 20L) + .toJobParameters() + val jobExecution = jobOperator.start(job, jobParameters) assert(BatchStatus.COMPLETED == jobExecution.status) println(jobExecution) diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/iterator/readerprocessor/SampleTasklet.kt b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/iterator/readerprocessor/SampleTasklet.kt index 54900579..30fef3b0 100644 --- a/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/iterator/readerprocessor/SampleTasklet.kt +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/iterator/readerprocessor/SampleTasklet.kt @@ -20,31 +20,25 @@ package com.navercorp.spring.batch.plus.sample.iterator.readerprocessor import com.navercorp.spring.batch.plus.step.adapter.ItemStreamIteratorReaderProcessor import org.springframework.batch.core.configuration.annotation.StepScope -import org.springframework.batch.item.ExecutionContext +import org.springframework.batch.infrastructure.item.ExecutionContext import org.springframework.beans.factory.annotation.Value import org.springframework.stereotype.Component @Component @StepScope open class SampleTasklet( - @Value("#{jobParameters['totalCount']}") private var totalCount: Long, + @param:Value("#{jobParameters['totalCount']}") private var totalCount: Long, ) : ItemStreamIteratorReaderProcessor { private var count = 0 override fun readIterator(executionContext: ExecutionContext): Iterator { println("totalCount: $totalCount") return object : Iterator { - override fun hasNext(): Boolean { - return count < totalCount - } + override fun hasNext(): Boolean = count < totalCount - override fun next(): Int { - return count++ - } + override fun next(): Int = count++ } } - override fun process(item: Int): String? { - return "'$item'" - } + override fun process(item: Int): String? = "'$item'" } diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/iterator/readerprocessor/TestJobConfig.kt b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/iterator/readerprocessor/TestJobConfig.kt index 3ed24a0f..e1231b5b 100644 --- a/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/iterator/readerprocessor/TestJobConfig.kt +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/iterator/readerprocessor/TestJobConfig.kt @@ -21,7 +21,7 @@ package com.navercorp.spring.batch.plus.sample.iterator.readerprocessor import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl import com.navercorp.spring.batch.plus.kotlin.step.adapter.asItemProcessor import com.navercorp.spring.batch.plus.kotlin.step.adapter.asItemStreamReader -import org.springframework.batch.core.Job +import org.springframework.batch.core.job.Job import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.transaction.PlatformTransactionManager @@ -32,17 +32,17 @@ open class TestJobConfig( private val transactionManager: PlatformTransactionManager, ) { @Bean - open fun testJob( - sampleTasklet: SampleTasklet, - ): Job = batch { - job("testJob") { - step("testStep") { - chunk(3, transactionManager) { - reader(sampleTasklet.asItemStreamReader()) - processor(sampleTasklet.asItemProcessor()) - writer { chunk -> println(chunk.items) } + open fun testJob(sampleTasklet: SampleTasklet): Job = + batch { + job("testJob") { + step("testStep") { + chunk(3) { + transactionManager(transactionManager) + reader(sampleTasklet.asItemStreamReader()) + processor(sampleTasklet.asItemProcessor()) + writer { chunk -> println(chunk.items) } + } } } } - } } diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/iterator/readerprocessorwriter/SampleApplicationTest.kt b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/iterator/readerprocessorwriter/SampleApplicationTest.kt index 5947b440..38e4ab48 100644 --- a/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/iterator/readerprocessorwriter/SampleApplicationTest.kt +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/iterator/readerprocessorwriter/SampleApplicationTest.kt @@ -20,9 +20,9 @@ package com.navercorp.spring.batch.plus.sample.iterator.readerprocessorwriter import org.junit.jupiter.api.Test import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator import org.springframework.beans.factory.getBean import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.runApplication @@ -32,13 +32,14 @@ open class SampleApplicationTest { @Test fun run() { val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() + val jobOperator = applicationContext.getBean() val job = applicationContext.getBean("testJob") - val jobParameters = JobParametersBuilder() - .addLong("totalCount", 20L) - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) + val jobParameters = + JobParametersBuilder() + .addLong("totalCount", 20L) + .toJobParameters() + val jobExecution = jobOperator.start(job, jobParameters) assert(BatchStatus.COMPLETED == jobExecution.status) println(jobExecution) diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/iterator/readerprocessorwriter/SampleTasklet.kt b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/iterator/readerprocessorwriter/SampleTasklet.kt index 8701e52f..10650abc 100644 --- a/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/iterator/readerprocessorwriter/SampleTasklet.kt +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/iterator/readerprocessorwriter/SampleTasklet.kt @@ -20,34 +20,28 @@ package com.navercorp.spring.batch.plus.sample.iterator.readerprocessorwriter import com.navercorp.spring.batch.plus.step.adapter.ItemStreamIteratorReaderProcessorWriter import org.springframework.batch.core.configuration.annotation.StepScope -import org.springframework.batch.item.Chunk -import org.springframework.batch.item.ExecutionContext +import org.springframework.batch.infrastructure.item.Chunk +import org.springframework.batch.infrastructure.item.ExecutionContext import org.springframework.beans.factory.annotation.Value import org.springframework.stereotype.Component @Component @StepScope open class SampleTasklet( - @Value("#{jobParameters['totalCount']}") private var totalCount: Long, + @param:Value("#{jobParameters['totalCount']}") private var totalCount: Long, ) : ItemStreamIteratorReaderProcessorWriter { private var count = 0 override fun readIterator(executionContext: ExecutionContext): Iterator { println("totalCount: $totalCount") return object : Iterator { - override fun hasNext(): Boolean { - return count < totalCount - } + override fun hasNext(): Boolean = count < totalCount - override fun next(): Int { - return count++ - } + override fun next(): Int = count++ } } - override fun process(item: Int): String? { - return "'$item'" - } + override fun process(item: Int): String? = "'$item'" override fun write(chunk: Chunk) { println(chunk.items) diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/iterator/readerprocessorwriter/TestJobConfig.kt b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/iterator/readerprocessorwriter/TestJobConfig.kt index 3131fdfc..926c11fe 100644 --- a/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/iterator/readerprocessorwriter/TestJobConfig.kt +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/iterator/readerprocessorwriter/TestJobConfig.kt @@ -22,7 +22,7 @@ import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl import com.navercorp.spring.batch.plus.kotlin.step.adapter.asItemProcessor import com.navercorp.spring.batch.plus.kotlin.step.adapter.asItemStreamReader import com.navercorp.spring.batch.plus.kotlin.step.adapter.asItemStreamWriter -import org.springframework.batch.core.Job +import org.springframework.batch.core.job.Job import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.transaction.PlatformTransactionManager @@ -33,17 +33,17 @@ open class TestJobConfig( private val transactionManager: PlatformTransactionManager, ) { @Bean - open fun testJob( - sampleTasklet: com.navercorp.spring.batch.plus.sample.iterator.readerprocessorwriter.SampleTasklet, - ): Job = batch { - job("testJob") { - step("testStep") { - chunk(3, transactionManager) { - reader(sampleTasklet.asItemStreamReader()) - processor(sampleTasklet.asItemProcessor()) - writer(sampleTasklet.asItemStreamWriter()) + open fun testJob(sampleTasklet: SampleTasklet): Job = + batch { + job("testJob") { + step("testStep") { + chunk(3) { + transactionManager(transactionManager) + reader(sampleTasklet.asItemStreamReader()) + processor(sampleTasklet.asItemProcessor()) + writer(sampleTasklet.asItemStreamWriter()) + } } } } - } } diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/iterator/readerwriter/SampleApplicationTest.kt b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/iterator/readerwriter/SampleApplicationTest.kt index 1f5655c0..b68b8dca 100644 --- a/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/iterator/readerwriter/SampleApplicationTest.kt +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/iterator/readerwriter/SampleApplicationTest.kt @@ -20,9 +20,9 @@ package com.navercorp.spring.batch.plus.sample.iterator.readerwriter import org.junit.jupiter.api.Test import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator import org.springframework.beans.factory.getBean import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.runApplication @@ -32,13 +32,14 @@ open class SampleApplicationTest { @Test fun run() { val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() + val jobOperator = applicationContext.getBean() val job = applicationContext.getBean("testJob") - val jobParameters = JobParametersBuilder() - .addLong("totalCount", 20L) - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) + val jobParameters = + JobParametersBuilder() + .addLong("totalCount", 20L) + .toJobParameters() + val jobExecution = jobOperator.start(job, jobParameters) assert(BatchStatus.COMPLETED == jobExecution.status) println(jobExecution) diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/iterator/readerwriter/SampleTasklet.kt b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/iterator/readerwriter/SampleTasklet.kt index 6c14f4ac..605a935b 100644 --- a/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/iterator/readerwriter/SampleTasklet.kt +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/iterator/readerwriter/SampleTasklet.kt @@ -20,28 +20,24 @@ package com.navercorp.spring.batch.plus.sample.iterator.readerwriter import com.navercorp.spring.batch.plus.step.adapter.ItemStreamIteratorReaderWriter import org.springframework.batch.core.configuration.annotation.StepScope -import org.springframework.batch.item.Chunk -import org.springframework.batch.item.ExecutionContext +import org.springframework.batch.infrastructure.item.Chunk +import org.springframework.batch.infrastructure.item.ExecutionContext import org.springframework.beans.factory.annotation.Value import org.springframework.stereotype.Component @Component @StepScope open class SampleTasklet( - @Value("#{jobParameters['totalCount']}") private var totalCount: Long, + @param:Value("#{jobParameters['totalCount']}") private var totalCount: Long, ) : ItemStreamIteratorReaderWriter { private var count = 0 override fun readIterator(executionContext: ExecutionContext): Iterator { println("totalCount: $totalCount") return object : Iterator { - override fun hasNext(): Boolean { - return count < totalCount - } + override fun hasNext(): Boolean = count < totalCount - override fun next(): Int { - return count++ - } + override fun next(): Int = count++ } } diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/iterator/readerwriter/TestJobConfig.kt b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/iterator/readerwriter/TestJobConfig.kt index c70baeb9..c9d97fb0 100644 --- a/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/iterator/readerwriter/TestJobConfig.kt +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/iterator/readerwriter/TestJobConfig.kt @@ -21,7 +21,7 @@ package com.navercorp.spring.batch.plus.sample.iterator.readerwriter import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl import com.navercorp.spring.batch.plus.kotlin.step.adapter.asItemStreamReader import com.navercorp.spring.batch.plus.kotlin.step.adapter.asItemStreamWriter -import org.springframework.batch.core.Job +import org.springframework.batch.core.job.Job import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.transaction.PlatformTransactionManager @@ -31,18 +31,17 @@ open class TestJobConfig( private val batch: BatchDsl, private val transactionManager: PlatformTransactionManager, ) { - @Bean - open fun testJob( - sampleTasklet: com.navercorp.spring.batch.plus.sample.iterator.readerwriter.SampleTasklet, - ): Job = batch { - job("testJob") { - step("testStep") { - chunk(3, transactionManager) { - reader(sampleTasklet.asItemStreamReader()) - writer(sampleTasklet.asItemStreamWriter()) + open fun testJob(sampleTasklet: SampleTasklet): Job = + batch { + job("testJob") { + step("testStep") { + chunk(3) { + transactionManager(transactionManager) + reader(sampleTasklet.asItemStreamReader()) + writer(sampleTasklet.asItemStreamWriter()) + } } } } - } } diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/simple/README.md b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/simple/README.md new file mode 100644 index 00000000..ec6d05d3 --- /dev/null +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/simple/README.md @@ -0,0 +1,9 @@ +# Simple Reader Adapter Samples + +## Invariants + +- Samples should cover a single delegate whose reader produces one item at a + time. +- Every supported combination of reader, processor, and writer roles should have + a runnable sample. +- Lifecycle callback support should have a runnable sample. diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/simple/callback/SampleApplicationTest.kt b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/simple/callback/SampleApplicationTest.kt index e8c61b06..e5e0810b 100644 --- a/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/simple/callback/SampleApplicationTest.kt +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/simple/callback/SampleApplicationTest.kt @@ -20,9 +20,9 @@ package com.navercorp.spring.batch.plus.sample.simple.callback import org.junit.jupiter.api.Test import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator import org.springframework.beans.factory.getBean import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.runApplication @@ -32,13 +32,14 @@ open class SampleApplicationTest { @Test fun run() { val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() + val jobOperator = applicationContext.getBean() val job = applicationContext.getBean("testJob") - val jobParameters = JobParametersBuilder() - .addLong("totalCount", 20L) - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) + val jobParameters = + JobParametersBuilder() + .addLong("totalCount", 20L) + .toJobParameters() + val jobExecution = jobOperator.start(job, jobParameters) assert(BatchStatus.COMPLETED == jobExecution.status) println(jobExecution) diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/simple/callback/SampleTasklet.kt b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/simple/callback/SampleTasklet.kt index 73974705..c77b5091 100644 --- a/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/simple/callback/SampleTasklet.kt +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/simple/callback/SampleTasklet.kt @@ -20,15 +20,15 @@ package com.navercorp.spring.batch.plus.sample.simple.callback import com.navercorp.spring.batch.plus.step.adapter.ItemStreamSimpleReaderProcessorWriter import org.springframework.batch.core.configuration.annotation.StepScope -import org.springframework.batch.item.Chunk -import org.springframework.batch.item.ExecutionContext +import org.springframework.batch.infrastructure.item.Chunk +import org.springframework.batch.infrastructure.item.ExecutionContext import org.springframework.beans.factory.annotation.Value import org.springframework.stereotype.Component @Component @StepScope open class SampleTasklet( - @Value("#{jobParameters['totalCount']}") private var totalCount: Long, + @param:Value("#{jobParameters['totalCount']}") private var totalCount: Long, ) : ItemStreamSimpleReaderProcessorWriter { private var count = 0 @@ -36,13 +36,12 @@ open class SampleTasklet( println("onOpenRead") } - override fun read(): Int? { - return if (count < totalCount) { + override fun read(): Int? = + if (count < totalCount) { count++ } else { null } - } override fun onUpdateRead(executionContext: ExecutionContext) { println("onUpdateRead") @@ -52,9 +51,7 @@ open class SampleTasklet( println("onCloseRead") } - override fun process(item: Int): String? { - return "'$item'" - } + override fun process(item: Int): String? = "'$item'" override fun onOpenWrite(executionContext: ExecutionContext) { println("onOpenWrite") diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/simple/callback/TestJobConfig.kt b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/simple/callback/TestJobConfig.kt index 8da405ff..6c4e5c7d 100644 --- a/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/simple/callback/TestJobConfig.kt +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/simple/callback/TestJobConfig.kt @@ -22,7 +22,7 @@ import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl import com.navercorp.spring.batch.plus.kotlin.step.adapter.asItemProcessor import com.navercorp.spring.batch.plus.kotlin.step.adapter.asItemStreamReader import com.navercorp.spring.batch.plus.kotlin.step.adapter.asItemStreamWriter -import org.springframework.batch.core.Job +import org.springframework.batch.core.job.Job import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.transaction.PlatformTransactionManager @@ -32,19 +32,18 @@ open class TestJobConfig( private val batch: BatchDsl, private val transactionManager: PlatformTransactionManager, ) { - @Bean - open fun testJob( - sampleTasklet: com.navercorp.spring.batch.plus.sample.simple.callback.SampleTasklet, - ): Job = batch { - job("testJob") { - step("testStep") { - chunk(3, transactionManager) { - reader(sampleTasklet.asItemStreamReader()) - processor(sampleTasklet.asItemProcessor()) - writer(sampleTasklet.asItemStreamWriter()) + open fun testJob(sampleTasklet: SampleTasklet): Job = + batch { + job("testJob") { + step("testStep") { + chunk(3) { + transactionManager(transactionManager) + reader(sampleTasklet.asItemStreamReader()) + processor(sampleTasklet.asItemProcessor()) + writer(sampleTasklet.asItemStreamWriter()) + } } } } - } } diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/simple/readerprocessor/SampleApplicationTest.kt b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/simple/readerprocessor/SampleApplicationTest.kt index 0f0261fb..3881a38d 100644 --- a/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/simple/readerprocessor/SampleApplicationTest.kt +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/simple/readerprocessor/SampleApplicationTest.kt @@ -20,9 +20,9 @@ package com.navercorp.spring.batch.plus.sample.simple.readerprocessor import org.junit.jupiter.api.Test import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator import org.springframework.beans.factory.getBean import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.runApplication @@ -32,13 +32,14 @@ open class SampleApplicationTest { @Test fun run() { val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() + val jobOperator = applicationContext.getBean() val job = applicationContext.getBean("testJob") - val jobParameters = JobParametersBuilder() - .addLong("totalCount", 20L) - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) + val jobParameters = + JobParametersBuilder() + .addLong("totalCount", 20L) + .toJobParameters() + val jobExecution = jobOperator.start(job, jobParameters) assert(BatchStatus.COMPLETED == jobExecution.status) println(jobExecution) diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/simple/readerprocessor/SampleTasklet.kt b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/simple/readerprocessor/SampleTasklet.kt index 402f1156..ddbef77d 100644 --- a/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/simple/readerprocessor/SampleTasklet.kt +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/simple/readerprocessor/SampleTasklet.kt @@ -26,19 +26,16 @@ import org.springframework.stereotype.Component @Component @StepScope open class SampleTasklet( - @Value("#{jobParameters['totalCount']}") private var totalCount: Long, + @param:Value("#{jobParameters['totalCount']}") private var totalCount: Long, ) : ItemStreamSimpleReaderProcessor { private var count = 0 - override fun read(): Int? { - return if (count < totalCount) { + override fun read(): Int? = + if (count < totalCount) { count++ } else { null } - } - override fun process(item: Int): String? { - return "'$item'" - } + override fun process(item: Int): String? = "'$item'" } diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/simple/readerprocessor/TestJobConfig.kt b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/simple/readerprocessor/TestJobConfig.kt index 64dc8b94..d0c9346d 100644 --- a/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/simple/readerprocessor/TestJobConfig.kt +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/simple/readerprocessor/TestJobConfig.kt @@ -21,7 +21,7 @@ package com.navercorp.spring.batch.plus.sample.simple.readerprocessor import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl import com.navercorp.spring.batch.plus.kotlin.step.adapter.asItemProcessor import com.navercorp.spring.batch.plus.kotlin.step.adapter.asItemStreamReader -import org.springframework.batch.core.Job +import org.springframework.batch.core.job.Job import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.transaction.PlatformTransactionManager @@ -32,17 +32,17 @@ open class TestJobConfig( private val transactionManager: PlatformTransactionManager, ) { @Bean - open fun testJob( - sampleTasklet: SampleTasklet, - ): Job = batch { - job("testJob") { - step("testStep") { - chunk(3, transactionManager) { - reader(sampleTasklet.asItemStreamReader()) - processor(sampleTasklet.asItemProcessor()) - writer { chunk -> println(chunk.items) } + open fun testJob(sampleTasklet: SampleTasklet): Job = + batch { + job("testJob") { + step("testStep") { + chunk(3) { + transactionManager(transactionManager) + reader(sampleTasklet.asItemStreamReader()) + processor(sampleTasklet.asItemProcessor()) + writer { chunk -> println(chunk.items) } + } } } } - } } diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/simple/readerprocessorwriter/SampleApplicationTest.kt b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/simple/readerprocessorwriter/SampleApplicationTest.kt index 2fbbad97..2f159d60 100644 --- a/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/simple/readerprocessorwriter/SampleApplicationTest.kt +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/simple/readerprocessorwriter/SampleApplicationTest.kt @@ -20,9 +20,9 @@ package com.navercorp.spring.batch.plus.sample.simple.readerprocessorwriter import org.junit.jupiter.api.Test import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator import org.springframework.beans.factory.getBean import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.runApplication @@ -32,13 +32,14 @@ open class SampleApplicationTest { @Test fun run() { val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() + val jobOperator = applicationContext.getBean() val job = applicationContext.getBean("testJob") - val jobParameters = JobParametersBuilder() - .addLong("totalCount", 20L) - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) + val jobParameters = + JobParametersBuilder() + .addLong("totalCount", 20L) + .toJobParameters() + val jobExecution = jobOperator.start(job, jobParameters) assert(BatchStatus.COMPLETED == jobExecution.status) println(jobExecution) diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/simple/readerprocessorwriter/SampleTasklet.kt b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/simple/readerprocessorwriter/SampleTasklet.kt index 22b3757d..5c240d2c 100644 --- a/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/simple/readerprocessorwriter/SampleTasklet.kt +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/simple/readerprocessorwriter/SampleTasklet.kt @@ -20,28 +20,25 @@ package com.navercorp.spring.batch.plus.sample.simple.readerprocessorwriter import com.navercorp.spring.batch.plus.step.adapter.ItemStreamSimpleReaderProcessorWriter import org.springframework.batch.core.configuration.annotation.StepScope -import org.springframework.batch.item.Chunk +import org.springframework.batch.infrastructure.item.Chunk import org.springframework.beans.factory.annotation.Value import org.springframework.stereotype.Component @Component @StepScope open class SampleTasklet( - @Value("#{jobParameters['totalCount']}") private var totalCount: Long, + @param:Value("#{jobParameters['totalCount']}") private var totalCount: Long, ) : ItemStreamSimpleReaderProcessorWriter { private var count = 0 - override fun read(): Int? { - return if (count < totalCount) { + override fun read(): Int? = + if (count < totalCount) { count++ } else { null } - } - override fun process(item: Int): String? { - return "'$item'" - } + override fun process(item: Int): String? = "'$item'" override fun write(chunk: Chunk) { println(chunk.items) diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/simple/readerprocessorwriter/TestJobConfig.kt b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/simple/readerprocessorwriter/TestJobConfig.kt index 57ad809c..f9ed7175 100644 --- a/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/simple/readerprocessorwriter/TestJobConfig.kt +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/simple/readerprocessorwriter/TestJobConfig.kt @@ -22,7 +22,7 @@ import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl import com.navercorp.spring.batch.plus.kotlin.step.adapter.asItemProcessor import com.navercorp.spring.batch.plus.kotlin.step.adapter.asItemStreamReader import com.navercorp.spring.batch.plus.kotlin.step.adapter.asItemStreamWriter -import org.springframework.batch.core.Job +import org.springframework.batch.core.job.Job import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.transaction.PlatformTransactionManager @@ -33,17 +33,17 @@ open class TestJobConfig( private val transactionManager: PlatformTransactionManager, ) { @Bean - open fun testJob( - sampleTasklet: com.navercorp.spring.batch.plus.sample.simple.readerprocessorwriter.SampleTasklet, - ): Job = batch { - job("testJob") { - step("testStep") { - chunk(3, transactionManager) { - reader(sampleTasklet.asItemStreamReader()) - processor(sampleTasklet.asItemProcessor()) - writer(sampleTasklet.asItemStreamWriter()) + open fun testJob(sampleTasklet: SampleTasklet): Job = + batch { + job("testJob") { + step("testStep") { + chunk(3) { + transactionManager(transactionManager) + reader(sampleTasklet.asItemStreamReader()) + processor(sampleTasklet.asItemProcessor()) + writer(sampleTasklet.asItemStreamWriter()) + } } } } - } } diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/simple/readerwriter/SampleApplicationTest.kt b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/simple/readerwriter/SampleApplicationTest.kt index 9cb62638..49cc4eed 100644 --- a/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/simple/readerwriter/SampleApplicationTest.kt +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/simple/readerwriter/SampleApplicationTest.kt @@ -20,9 +20,9 @@ package com.navercorp.spring.batch.plus.sample.simple.readerwriter import org.junit.jupiter.api.Test import org.springframework.batch.core.BatchStatus -import org.springframework.batch.core.Job -import org.springframework.batch.core.JobParametersBuilder -import org.springframework.batch.core.launch.JobLauncher +import org.springframework.batch.core.job.Job +import org.springframework.batch.core.job.parameters.JobParametersBuilder +import org.springframework.batch.core.launch.JobOperator import org.springframework.beans.factory.getBean import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.runApplication @@ -33,13 +33,14 @@ open class SampleApplicationTest { fun run() { val applicationContext = runApplication() - val jobLauncher = applicationContext.getBean() + val jobOperator = applicationContext.getBean() val job = applicationContext.getBean("testJob") - val jobParameters = JobParametersBuilder() - .addLong("totalCount", 20L) - .toJobParameters() - val jobExecution = jobLauncher.run(job, jobParameters) + val jobParameters = + JobParametersBuilder() + .addLong("totalCount", 20L) + .toJobParameters() + val jobExecution = jobOperator.start(job, jobParameters) assert(BatchStatus.COMPLETED == jobExecution.status) println(jobExecution) diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/simple/readerwriter/SampleTasklet.kt b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/simple/readerwriter/SampleTasklet.kt index 1945fa44..858479b5 100644 --- a/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/simple/readerwriter/SampleTasklet.kt +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/simple/readerwriter/SampleTasklet.kt @@ -20,24 +20,23 @@ package com.navercorp.spring.batch.plus.sample.simple.readerwriter import com.navercorp.spring.batch.plus.step.adapter.ItemStreamSimpleReaderWriter import org.springframework.batch.core.configuration.annotation.StepScope -import org.springframework.batch.item.Chunk +import org.springframework.batch.infrastructure.item.Chunk import org.springframework.beans.factory.annotation.Value import org.springframework.stereotype.Component @Component @StepScope open class SampleTasklet( - @Value("#{jobParameters['totalCount']}") private var totalCount: Long, + @param:Value("#{jobParameters['totalCount']}") private var totalCount: Long, ) : ItemStreamSimpleReaderWriter { private var count = 0 - override fun read(): Int? { - return if (count < totalCount) { + override fun read(): Int? = + if (count < totalCount) { count++ } else { null } - } override fun write(chunk: Chunk) { println(chunk.items) diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/simple/readerwriter/TestJobConfig.kt b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/simple/readerwriter/TestJobConfig.kt index 2d7745fe..7be4f8c3 100644 --- a/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/simple/readerwriter/TestJobConfig.kt +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-kotlin-sample/src/test/kotlin/com/navercorp/spring/batch/plus/sample/simple/readerwriter/TestJobConfig.kt @@ -21,7 +21,7 @@ package com.navercorp.spring.batch.plus.sample.simple.readerwriter import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl import com.navercorp.spring.batch.plus.kotlin.step.adapter.asItemStreamReader import com.navercorp.spring.batch.plus.kotlin.step.adapter.asItemStreamWriter -import org.springframework.batch.core.Job +import org.springframework.batch.core.job.Job import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.transaction.PlatformTransactionManager @@ -31,18 +31,17 @@ open class TestJobConfig( private val batch: BatchDsl, private val transactionManager: PlatformTransactionManager, ) { - @Bean - open fun testJob( - sampleTasklet: com.navercorp.spring.batch.plus.sample.simple.readerwriter.SampleTasklet, - ): Job = batch { - job("testJob") { - step("testStep") { - chunk(3, transactionManager) { - reader(sampleTasklet.asItemStreamReader()) - writer(sampleTasklet.asItemStreamWriter()) + open fun testJob(sampleTasklet: SampleTasklet): Job = + batch { + job("testJob") { + step("testStep") { + chunk(3) { + transactionManager(transactionManager) + reader(sampleTasklet.asItemStreamReader()) + writer(sampleTasklet.asItemStreamWriter()) + } } } } - } } diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-sample/build.gradle.kts b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/build.gradle.kts index 8a80ce28..19d1efb3 100644 --- a/spring-batch-plus-sample/single-class-reader-processor-writer-sample/build.gradle.kts +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/build.gradle.kts @@ -27,15 +27,15 @@ tasks.named("test") { dependencyManagement { imports { - mavenBom("org.springframework.boot:spring-boot-dependencies:3.5.0") + mavenBom("org.springframework.boot:spring-boot-dependencies:4.0.7") } } dependencies { - implementation("org.springframework.boot:spring-boot-starter-batch") + implementation("org.springframework.boot:spring-boot-starter-batch-jdbc") implementation(project(":spring-boot-starter-batch-plus")) - implementation("io.projectreactor:reactor-core:3.5.0") - runtimeOnly("com.h2database:h2:2.1.214") + implementation("io.projectreactor:reactor-core:3.8.4") + runtimeOnly("com.h2database:h2:2.4.240") testImplementation("org.springframework.boot:spring-boot-starter-test") testRuntimeOnly("org.junit.platform:junit-platform-launcher") diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/flux/README.md b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/flux/README.md new file mode 100644 index 00000000..02f0ac45 --- /dev/null +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/flux/README.md @@ -0,0 +1,8 @@ +# Flux Reader Adapter Samples + +## Invariants + +- Samples should cover a single delegate whose reader produces items as a `Flux`. +- Every supported combination of reader, processor, and writer roles should have + a runnable sample. +- Lifecycle callback support should have a runnable sample. diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/flux/callback/SampleApplicationTest.java b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/flux/callback/SampleApplicationTest.java index d64b8fa8..dadb7e81 100644 --- a/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/flux/callback/SampleApplicationTest.java +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/flux/callback/SampleApplicationTest.java @@ -20,11 +20,11 @@ import org.junit.jupiter.api.Test; import org.springframework.batch.core.BatchStatus; -import org.springframework.batch.core.Job; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.JobParameters; -import org.springframework.batch.core.JobParametersBuilder; -import org.springframework.batch.core.launch.JobLauncher; +import org.springframework.batch.core.job.Job; +import org.springframework.batch.core.job.JobExecution; +import org.springframework.batch.core.job.parameters.JobParameters; +import org.springframework.batch.core.job.parameters.JobParametersBuilder; +import org.springframework.batch.core.launch.JobOperator; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ApplicationContext; @@ -34,13 +34,13 @@ public class SampleApplicationTest { @Test void run() throws Exception { ApplicationContext applicationContext = SpringApplication.run(SampleApplicationTest.class); - JobLauncher jobLauncher = applicationContext.getBean(JobLauncher.class); + JobOperator jobOperator = applicationContext.getBean(JobOperator.class); Job job = applicationContext.getBean("testJob", Job.class); JobParameters jobParameters = new JobParametersBuilder() .addLong("totalCount", 20L) .toJobParameters(); - JobExecution jobExecution = jobLauncher.run(job, jobParameters); + JobExecution jobExecution = jobOperator.start(job, jobParameters); assert BatchStatus.COMPLETED.equals(jobExecution.getStatus()); System.out.printf("%s%n", jobExecution); diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/flux/callback/SampleTasklet.java b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/flux/callback/SampleTasklet.java index bb2e08ce..fec235d9 100644 --- a/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/flux/callback/SampleTasklet.java +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/flux/callback/SampleTasklet.java @@ -19,10 +19,9 @@ package com.navercorp.spring.batch.plus.sample.flux.callback; import org.springframework.batch.core.configuration.annotation.StepScope; -import org.springframework.batch.item.Chunk; -import org.springframework.batch.item.ExecutionContext; +import org.springframework.batch.infrastructure.item.Chunk; +import org.springframework.batch.infrastructure.item.ExecutionContext; import org.springframework.beans.factory.annotation.Value; -import org.springframework.lang.NonNull; import org.springframework.stereotype.Component; import reactor.core.publisher.Flux; @@ -39,13 +38,12 @@ public class SampleTasklet implements ItemStreamFluxReaderProcessorWriter readFlux(@NonNull ExecutionContext executionContext) { + public Flux readFlux(ExecutionContext executionContext) { System.out.println("totalCount: " + totalCount); return Flux.generate(sink -> { if (count < totalCount) { @@ -58,7 +56,7 @@ public Flux readFlux(@NonNull ExecutionContext executionConte } @Override - public void onUpdateRead(@NonNull ExecutionContext executionContext) { + public void onUpdateRead(ExecutionContext executionContext) { System.out.println("onUpdateRead"); } @@ -68,24 +66,24 @@ public void onCloseRead() { } @Override - public String process(@NonNull Integer item) { + public String process(Integer item) { return "'" + item.toString() + "'"; } @Override - public void onOpenWrite(@NonNull ExecutionContext executionContext) { + public void onOpenWrite(ExecutionContext executionContext) { System.out.println("onOpenWrite"); } @Override - public void write(@NonNull Chunk chunk) { + public void write(Chunk chunk) { System.out.println(chunk.getItems()); } @Override - public void onUpdateWrite(@NonNull ExecutionContext executionContext) { + public void onUpdateWrite(ExecutionContext executionContext) { System.out.println("onUpdateWrite"); - executionContext.putString("samplekey", "samplevlaue"); + executionContext.putString("samplekey", "samplevalue"); } @Override diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/flux/callback/TestJobConfig.java b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/flux/callback/TestJobConfig.java index 851ecbaf..5b64ec5f 100644 --- a/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/flux/callback/TestJobConfig.java +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/flux/callback/TestJobConfig.java @@ -22,7 +22,7 @@ import static com.navercorp.spring.batch.plus.step.adapter.AdapterFactory.itemStreamReader; import static com.navercorp.spring.batch.plus.step.adapter.AdapterFactory.itemStreamWriter; -import org.springframework.batch.core.Job; +import org.springframework.batch.core.job.Job; import org.springframework.batch.core.job.builder.JobBuilder; import org.springframework.batch.core.repository.JobRepository; import org.springframework.batch.core.step.builder.StepBuilder; @@ -42,7 +42,8 @@ public Job testJob( return new JobBuilder("testJob", jobRepository) .start( new StepBuilder("testStep", jobRepository) - .chunk(3, transactionManager) + .chunk(3) + .transactionManager(transactionManager) .reader(itemStreamReader(sampleTasklet)) .processor(itemProcessor(sampleTasklet)) .writer(itemStreamWriter(sampleTasklet)) diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/flux/readerprocessor/SampleApplicationTest.java b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/flux/readerprocessor/SampleApplicationTest.java index d9eeba3d..f249ae5e 100644 --- a/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/flux/readerprocessor/SampleApplicationTest.java +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/flux/readerprocessor/SampleApplicationTest.java @@ -20,11 +20,11 @@ import org.junit.jupiter.api.Test; import org.springframework.batch.core.BatchStatus; -import org.springframework.batch.core.Job; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.JobParameters; -import org.springframework.batch.core.JobParametersBuilder; -import org.springframework.batch.core.launch.JobLauncher; +import org.springframework.batch.core.job.Job; +import org.springframework.batch.core.job.JobExecution; +import org.springframework.batch.core.job.parameters.JobParameters; +import org.springframework.batch.core.job.parameters.JobParametersBuilder; +import org.springframework.batch.core.launch.JobOperator; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ApplicationContext; @@ -34,13 +34,13 @@ public class SampleApplicationTest { @Test void run() throws Exception { ApplicationContext applicationContext = SpringApplication.run(SampleApplicationTest.class); - JobLauncher jobLauncher = applicationContext.getBean(JobLauncher.class); + JobOperator jobOperator = applicationContext.getBean(JobOperator.class); Job job = applicationContext.getBean("testJob", Job.class); JobParameters jobParameters = new JobParametersBuilder() .addLong("totalCount", 20L) .toJobParameters(); - JobExecution jobExecution = jobLauncher.run(job, jobParameters); + JobExecution jobExecution = jobOperator.start(job, jobParameters); assert BatchStatus.COMPLETED.equals(jobExecution.getStatus()); System.out.printf("%s%n", jobExecution); diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/flux/readerprocessor/SampleTasklet.java b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/flux/readerprocessor/SampleTasklet.java index abeb765b..72ab47e6 100644 --- a/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/flux/readerprocessor/SampleTasklet.java +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/flux/readerprocessor/SampleTasklet.java @@ -19,9 +19,8 @@ package com.navercorp.spring.batch.plus.sample.flux.readerprocessor; import org.springframework.batch.core.configuration.annotation.StepScope; -import org.springframework.batch.item.ExecutionContext; +import org.springframework.batch.infrastructure.item.ExecutionContext; import org.springframework.beans.factory.annotation.Value; -import org.springframework.lang.NonNull; import org.springframework.stereotype.Component; import reactor.core.publisher.Flux; @@ -37,9 +36,8 @@ class SampleTasklet implements ItemStreamFluxReaderProcessor { private int count = 0; - @NonNull @Override - public Flux readFlux(@NonNull ExecutionContext executionContext) { + public Flux readFlux(ExecutionContext executionContext) { System.out.println("totalCount: " + totalCount); return Flux.generate(sink -> { if (count < totalCount) { @@ -52,7 +50,7 @@ public Flux readFlux(@NonNull ExecutionContext executionConte } @Override - public String process(@NonNull Integer item) { + public String process(Integer item) { return "'" + item.toString() + "'"; } } diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/flux/readerprocessor/TestJobConfig.java b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/flux/readerprocessor/TestJobConfig.java index 3b1d6c1b..ee828edc 100644 --- a/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/flux/readerprocessor/TestJobConfig.java +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/flux/readerprocessor/TestJobConfig.java @@ -21,7 +21,7 @@ import static com.navercorp.spring.batch.plus.step.adapter.AdapterFactory.itemProcessor; import static com.navercorp.spring.batch.plus.step.adapter.AdapterFactory.itemStreamReader; -import org.springframework.batch.core.Job; +import org.springframework.batch.core.job.Job; import org.springframework.batch.core.job.builder.JobBuilder; import org.springframework.batch.core.repository.JobRepository; import org.springframework.batch.core.step.builder.StepBuilder; @@ -41,7 +41,8 @@ public Job testJob( return new JobBuilder("testJob", jobRepository) .start( new StepBuilder("testStep", jobRepository) - .chunk(3, transactionManager) + .chunk(3) + .transactionManager(transactionManager) .reader(itemStreamReader(sampleTasklet)) .processor(itemProcessor(sampleTasklet)) .writer(chunk -> System.out.println(chunk.getItems())) diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/flux/readerprocessorwriter/SampleApplicationTest.java b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/flux/readerprocessorwriter/SampleApplicationTest.java index ab9348c8..bcd10806 100644 --- a/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/flux/readerprocessorwriter/SampleApplicationTest.java +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/flux/readerprocessorwriter/SampleApplicationTest.java @@ -20,11 +20,11 @@ import org.junit.jupiter.api.Test; import org.springframework.batch.core.BatchStatus; -import org.springframework.batch.core.Job; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.JobParameters; -import org.springframework.batch.core.JobParametersBuilder; -import org.springframework.batch.core.launch.JobLauncher; +import org.springframework.batch.core.job.Job; +import org.springframework.batch.core.job.JobExecution; +import org.springframework.batch.core.job.parameters.JobParameters; +import org.springframework.batch.core.job.parameters.JobParametersBuilder; +import org.springframework.batch.core.launch.JobOperator; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ApplicationContext; @@ -34,13 +34,13 @@ public class SampleApplicationTest { @Test void run() throws Exception { ApplicationContext applicationContext = SpringApplication.run(SampleApplicationTest.class); - JobLauncher jobLauncher = applicationContext.getBean(JobLauncher.class); + JobOperator jobOperator = applicationContext.getBean(JobOperator.class); Job job = applicationContext.getBean("testJob", Job.class); JobParameters jobParameters = new JobParametersBuilder() .addLong("totalCount", 20L) .toJobParameters(); - JobExecution jobExecution = jobLauncher.run(job, jobParameters); + JobExecution jobExecution = jobOperator.start(job, jobParameters); assert BatchStatus.COMPLETED.equals(jobExecution.getStatus()); System.out.printf("%s%n", jobExecution); diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/flux/readerprocessorwriter/SampleTasklet.java b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/flux/readerprocessorwriter/SampleTasklet.java index 795b599a..4bb0f35f 100644 --- a/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/flux/readerprocessorwriter/SampleTasklet.java +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/flux/readerprocessorwriter/SampleTasklet.java @@ -19,10 +19,9 @@ package com.navercorp.spring.batch.plus.sample.flux.readerprocessorwriter; import org.springframework.batch.core.configuration.annotation.StepScope; -import org.springframework.batch.item.Chunk; -import org.springframework.batch.item.ExecutionContext; +import org.springframework.batch.infrastructure.item.Chunk; +import org.springframework.batch.infrastructure.item.ExecutionContext; import org.springframework.beans.factory.annotation.Value; -import org.springframework.lang.NonNull; import org.springframework.stereotype.Component; import reactor.core.publisher.Flux; @@ -38,9 +37,8 @@ class SampleTasklet implements ItemStreamFluxReaderProcessorWriter readFlux(@NonNull ExecutionContext executionContext) { + public Flux readFlux(ExecutionContext executionContext) { System.out.println("totalCount: " + totalCount); return Flux.generate(sink -> { if (count < totalCount) { @@ -53,12 +51,12 @@ public Flux readFlux(@NonNull ExecutionContext executionConte } @Override - public String process(@NonNull Integer item) { + public String process(Integer item) { return "'" + item.toString() + "'"; } @Override - public void write(@NonNull Chunk chunk) { + public void write(Chunk chunk) { System.out.println(chunk.getItems()); } } diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/flux/readerprocessorwriter/TestJobConfig.java b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/flux/readerprocessorwriter/TestJobConfig.java index f685bf9e..51aeafda 100644 --- a/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/flux/readerprocessorwriter/TestJobConfig.java +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/flux/readerprocessorwriter/TestJobConfig.java @@ -22,7 +22,7 @@ import static com.navercorp.spring.batch.plus.step.adapter.AdapterFactory.itemStreamReader; import static com.navercorp.spring.batch.plus.step.adapter.AdapterFactory.itemStreamWriter; -import org.springframework.batch.core.Job; +import org.springframework.batch.core.job.Job; import org.springframework.batch.core.job.builder.JobBuilder; import org.springframework.batch.core.repository.JobRepository; import org.springframework.batch.core.step.builder.StepBuilder; @@ -42,7 +42,8 @@ public Job testJob( return new JobBuilder("testJob", jobRepository) .start( new StepBuilder("testStep", jobRepository) - .chunk(3, transactionManager) + .chunk(3) + .transactionManager(transactionManager) .reader(itemStreamReader(sampleTasklet)) .processor(itemProcessor(sampleTasklet)) .writer(itemStreamWriter(sampleTasklet)) diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/flux/readerwriter/SampleApplicationTest.java b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/flux/readerwriter/SampleApplicationTest.java index d6bfb710..2364c5a1 100644 --- a/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/flux/readerwriter/SampleApplicationTest.java +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/flux/readerwriter/SampleApplicationTest.java @@ -20,11 +20,11 @@ import org.junit.jupiter.api.Test; import org.springframework.batch.core.BatchStatus; -import org.springframework.batch.core.Job; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.JobParameters; -import org.springframework.batch.core.JobParametersBuilder; -import org.springframework.batch.core.launch.JobLauncher; +import org.springframework.batch.core.job.Job; +import org.springframework.batch.core.job.JobExecution; +import org.springframework.batch.core.job.parameters.JobParameters; +import org.springframework.batch.core.job.parameters.JobParametersBuilder; +import org.springframework.batch.core.launch.JobOperator; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ApplicationContext; @@ -34,13 +34,13 @@ public class SampleApplicationTest { @Test void run() throws Exception { ApplicationContext applicationContext = SpringApplication.run(SampleApplicationTest.class); - JobLauncher jobLauncher = applicationContext.getBean(JobLauncher.class); + JobOperator jobOperator = applicationContext.getBean(JobOperator.class); Job job = applicationContext.getBean("testJob", Job.class); JobParameters jobParameters = new JobParametersBuilder() .addLong("totalCount", 20L) .toJobParameters(); - JobExecution jobExecution = jobLauncher.run(job, jobParameters); + JobExecution jobExecution = jobOperator.start(job, jobParameters); assert BatchStatus.COMPLETED.equals(jobExecution.getStatus()); System.out.printf("%s%n", jobExecution); diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/flux/readerwriter/SampleTasklet.java b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/flux/readerwriter/SampleTasklet.java index de12d482..ccbe2c05 100644 --- a/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/flux/readerwriter/SampleTasklet.java +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/flux/readerwriter/SampleTasklet.java @@ -19,10 +19,9 @@ package com.navercorp.spring.batch.plus.sample.flux.readerwriter; import org.springframework.batch.core.configuration.annotation.StepScope; -import org.springframework.batch.item.Chunk; -import org.springframework.batch.item.ExecutionContext; +import org.springframework.batch.infrastructure.item.Chunk; +import org.springframework.batch.infrastructure.item.ExecutionContext; import org.springframework.beans.factory.annotation.Value; -import org.springframework.lang.NonNull; import org.springframework.stereotype.Component; import reactor.core.publisher.Flux; @@ -38,9 +37,8 @@ class SampleTasklet implements ItemStreamFluxReaderWriter { private int count = 0; - @NonNull @Override - public Flux readFlux(@NonNull ExecutionContext executionContext) { + public Flux readFlux(ExecutionContext executionContext) { System.out.println("totalCount: " + totalCount); return Flux.generate(sink -> { if (count < totalCount) { @@ -53,7 +51,7 @@ public Flux readFlux(@NonNull ExecutionContext executionConte } @Override - public void write(@NonNull Chunk chunk) { + public void write(Chunk chunk) { System.out.println(chunk.getItems()); } } diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/flux/readerwriter/TestJobConfig.java b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/flux/readerwriter/TestJobConfig.java index 40f7685c..7cc46ab9 100644 --- a/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/flux/readerwriter/TestJobConfig.java +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/flux/readerwriter/TestJobConfig.java @@ -21,7 +21,7 @@ import static com.navercorp.spring.batch.plus.step.adapter.AdapterFactory.itemStreamReader; import static com.navercorp.spring.batch.plus.step.adapter.AdapterFactory.itemStreamWriter; -import org.springframework.batch.core.Job; +import org.springframework.batch.core.job.Job; import org.springframework.batch.core.job.builder.JobBuilder; import org.springframework.batch.core.repository.JobRepository; import org.springframework.batch.core.step.builder.StepBuilder; @@ -41,7 +41,8 @@ public Job testJob( return new JobBuilder("testJob", jobRepository) .start( new StepBuilder("testStep", jobRepository) - .chunk(3, transactionManager) + .chunk(3) + .transactionManager(transactionManager) .reader(itemStreamReader(sampleTasklet)) .writer(itemStreamWriter(sampleTasklet)) .build() diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/iterable/README.md b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/iterable/README.md new file mode 100644 index 00000000..694c7631 --- /dev/null +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/iterable/README.md @@ -0,0 +1,9 @@ +# Iterable Reader Adapter Samples + +## Invariants + +- Samples should cover a single delegate whose reader produces items as an + `Iterable`. +- Every supported combination of reader, processor, and writer roles should have + a runnable sample. +- Lifecycle callback support should have a runnable sample. diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/iterable/callback/SampleApplicationTest.java b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/iterable/callback/SampleApplicationTest.java index 9f732a89..e47b3169 100644 --- a/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/iterable/callback/SampleApplicationTest.java +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/iterable/callback/SampleApplicationTest.java @@ -20,11 +20,11 @@ import org.junit.jupiter.api.Test; import org.springframework.batch.core.BatchStatus; -import org.springframework.batch.core.Job; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.JobParameters; -import org.springframework.batch.core.JobParametersBuilder; -import org.springframework.batch.core.launch.JobLauncher; +import org.springframework.batch.core.job.Job; +import org.springframework.batch.core.job.JobExecution; +import org.springframework.batch.core.job.parameters.JobParameters; +import org.springframework.batch.core.job.parameters.JobParametersBuilder; +import org.springframework.batch.core.launch.JobOperator; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ApplicationContext; @@ -34,13 +34,13 @@ public class SampleApplicationTest { @Test void run() throws Exception { ApplicationContext applicationContext = SpringApplication.run(SampleApplicationTest.class); - JobLauncher jobLauncher = applicationContext.getBean(JobLauncher.class); + JobOperator jobOperator = applicationContext.getBean(JobOperator.class); Job job = applicationContext.getBean("testJob", Job.class); JobParameters jobParameters = new JobParametersBuilder() .addLong("totalCount", 20L) .toJobParameters(); - JobExecution jobExecution = jobLauncher.run(job, jobParameters); + JobExecution jobExecution = jobOperator.start(job, jobParameters); assert BatchStatus.COMPLETED.equals(jobExecution.getStatus()); System.out.printf("%s%n", jobExecution); diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/iterable/callback/SampleTasklet.java b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/iterable/callback/SampleTasklet.java index d9b036f6..dd30a9c7 100644 --- a/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/iterable/callback/SampleTasklet.java +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/iterable/callback/SampleTasklet.java @@ -21,10 +21,9 @@ import java.util.Iterator; import org.springframework.batch.core.configuration.annotation.StepScope; -import org.springframework.batch.item.Chunk; -import org.springframework.batch.item.ExecutionContext; +import org.springframework.batch.infrastructure.item.Chunk; +import org.springframework.batch.infrastructure.item.ExecutionContext; import org.springframework.beans.factory.annotation.Value; -import org.springframework.lang.NonNull; import org.springframework.stereotype.Component; import com.navercorp.spring.batch.plus.step.adapter.ItemStreamIterableReaderProcessorWriter; @@ -39,13 +38,12 @@ public class SampleTasklet implements ItemStreamIterableReaderProcessorWriter readIterable(@NonNull ExecutionContext executionContext) { + public Iterable readIterable(ExecutionContext executionContext) { System.out.println("totalCount: " + totalCount); return () -> new Iterator<>() { @Override @@ -61,7 +59,7 @@ public Integer next() { } @Override - public void onUpdateRead(@NonNull ExecutionContext executionContext) { + public void onUpdateRead(ExecutionContext executionContext) { System.out.println("onUpdateRead"); } @@ -71,24 +69,24 @@ public void onCloseRead() { } @Override - public String process(@NonNull Integer item) { + public String process(Integer item) { return "'" + item.toString() + "'"; } @Override - public void onOpenWrite(@NonNull ExecutionContext executionContext) { + public void onOpenWrite(ExecutionContext executionContext) { System.out.println("onOpenWrite"); } @Override - public void write(@NonNull Chunk chunk) { + public void write(Chunk chunk) { System.out.println(chunk.getItems()); } @Override - public void onUpdateWrite(@NonNull ExecutionContext executionContext) { + public void onUpdateWrite(ExecutionContext executionContext) { System.out.println("onUpdateWrite"); - executionContext.putString("samplekey", "samplevlaue"); + executionContext.putString("samplekey", "samplevalue"); } @Override diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/iterable/callback/TestJobConfig.java b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/iterable/callback/TestJobConfig.java index a31924ad..756bb06a 100644 --- a/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/iterable/callback/TestJobConfig.java +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/iterable/callback/TestJobConfig.java @@ -22,7 +22,7 @@ import static com.navercorp.spring.batch.plus.step.adapter.AdapterFactory.itemStreamReader; import static com.navercorp.spring.batch.plus.step.adapter.AdapterFactory.itemStreamWriter; -import org.springframework.batch.core.Job; +import org.springframework.batch.core.job.Job; import org.springframework.batch.core.job.builder.JobBuilder; import org.springframework.batch.core.repository.JobRepository; import org.springframework.batch.core.step.builder.StepBuilder; @@ -42,7 +42,8 @@ public Job testJob( return new JobBuilder("testJob", jobRepository) .start( new StepBuilder("testStep", jobRepository) - .chunk(3, transactionManager) + .chunk(3) + .transactionManager(transactionManager) .reader(itemStreamReader(sampleTasklet)) .processor(itemProcessor(sampleTasklet)) .writer(itemStreamWriter(sampleTasklet)) diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/iterable/readerprocessor/SampleApplicationTest.java b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/iterable/readerprocessor/SampleApplicationTest.java index 874cace3..96c06164 100644 --- a/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/iterable/readerprocessor/SampleApplicationTest.java +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/iterable/readerprocessor/SampleApplicationTest.java @@ -20,11 +20,11 @@ import org.junit.jupiter.api.Test; import org.springframework.batch.core.BatchStatus; -import org.springframework.batch.core.Job; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.JobParameters; -import org.springframework.batch.core.JobParametersBuilder; -import org.springframework.batch.core.launch.JobLauncher; +import org.springframework.batch.core.job.Job; +import org.springframework.batch.core.job.JobExecution; +import org.springframework.batch.core.job.parameters.JobParameters; +import org.springframework.batch.core.job.parameters.JobParametersBuilder; +import org.springframework.batch.core.launch.JobOperator; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ApplicationContext; @@ -34,13 +34,13 @@ public class SampleApplicationTest { @Test void run() throws Exception { ApplicationContext applicationContext = SpringApplication.run(SampleApplicationTest.class); - JobLauncher jobLauncher = applicationContext.getBean(JobLauncher.class); + JobOperator jobOperator = applicationContext.getBean(JobOperator.class); Job job = applicationContext.getBean("testJob", Job.class); JobParameters jobParameters = new JobParametersBuilder() .addLong("totalCount", 20L) .toJobParameters(); - JobExecution jobExecution = jobLauncher.run(job, jobParameters); + JobExecution jobExecution = jobOperator.start(job, jobParameters); assert BatchStatus.COMPLETED.equals(jobExecution.getStatus()); System.out.printf("%s%n", jobExecution); diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/iterable/readerprocessor/SampleTasklet.java b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/iterable/readerprocessor/SampleTasklet.java index 53028024..4cceea1c 100644 --- a/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/iterable/readerprocessor/SampleTasklet.java +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/iterable/readerprocessor/SampleTasklet.java @@ -21,9 +21,8 @@ import java.util.Iterator; import org.springframework.batch.core.configuration.annotation.StepScope; -import org.springframework.batch.item.ExecutionContext; +import org.springframework.batch.infrastructure.item.ExecutionContext; import org.springframework.beans.factory.annotation.Value; -import org.springframework.lang.NonNull; import org.springframework.stereotype.Component; import com.navercorp.spring.batch.plus.step.adapter.ItemStreamIterableReaderProcessor; @@ -37,9 +36,8 @@ class SampleTasklet implements ItemStreamIterableReaderProcessor readIterable(@NonNull ExecutionContext executionContext) { + public Iterable readIterable(ExecutionContext executionContext) { System.out.println("totalCount: " + totalCount); return () -> new Iterator<>() { @Override @@ -55,7 +53,7 @@ public Integer next() { } @Override - public String process(@NonNull Integer item) { + public String process(Integer item) { return "'" + item.toString() + "'"; } } diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/iterable/readerprocessor/TestJobConfig.java b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/iterable/readerprocessor/TestJobConfig.java index 7ff6e342..1d9f4610 100644 --- a/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/iterable/readerprocessor/TestJobConfig.java +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/iterable/readerprocessor/TestJobConfig.java @@ -21,7 +21,7 @@ import static com.navercorp.spring.batch.plus.step.adapter.AdapterFactory.itemProcessor; import static com.navercorp.spring.batch.plus.step.adapter.AdapterFactory.itemStreamReader; -import org.springframework.batch.core.Job; +import org.springframework.batch.core.job.Job; import org.springframework.batch.core.job.builder.JobBuilder; import org.springframework.batch.core.repository.JobRepository; import org.springframework.batch.core.step.builder.StepBuilder; @@ -41,7 +41,8 @@ public Job testJob( return new JobBuilder("testJob", jobRepository) .start( new StepBuilder("testStep", jobRepository) - .chunk(3, transactionManager) + .chunk(3) + .transactionManager(transactionManager) .reader(itemStreamReader(sampleTasklet)) .processor(itemProcessor(sampleTasklet)) .writer(chunk -> System.out.println(chunk.getItems())) diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/iterable/readerprocessorwriter/SampleApplicationTest.java b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/iterable/readerprocessorwriter/SampleApplicationTest.java index 015f6490..5cbace7c 100644 --- a/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/iterable/readerprocessorwriter/SampleApplicationTest.java +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/iterable/readerprocessorwriter/SampleApplicationTest.java @@ -20,11 +20,11 @@ import org.junit.jupiter.api.Test; import org.springframework.batch.core.BatchStatus; -import org.springframework.batch.core.Job; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.JobParameters; -import org.springframework.batch.core.JobParametersBuilder; -import org.springframework.batch.core.launch.JobLauncher; +import org.springframework.batch.core.job.Job; +import org.springframework.batch.core.job.JobExecution; +import org.springframework.batch.core.job.parameters.JobParameters; +import org.springframework.batch.core.job.parameters.JobParametersBuilder; +import org.springframework.batch.core.launch.JobOperator; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ApplicationContext; @@ -34,13 +34,13 @@ public class SampleApplicationTest { @Test void run() throws Exception { ApplicationContext applicationContext = SpringApplication.run(SampleApplicationTest.class); - JobLauncher jobLauncher = applicationContext.getBean(JobLauncher.class); + JobOperator jobOperator = applicationContext.getBean(JobOperator.class); Job job = applicationContext.getBean("testJob", Job.class); JobParameters jobParameters = new JobParametersBuilder() .addLong("totalCount", 20L) .toJobParameters(); - JobExecution jobExecution = jobLauncher.run(job, jobParameters); + JobExecution jobExecution = jobOperator.start(job, jobParameters); assert BatchStatus.COMPLETED.equals(jobExecution.getStatus()); System.out.printf("%s%n", jobExecution); diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/iterable/readerprocessorwriter/SampleTasklet.java b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/iterable/readerprocessorwriter/SampleTasklet.java index f433c18a..6adafc5a 100644 --- a/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/iterable/readerprocessorwriter/SampleTasklet.java +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/iterable/readerprocessorwriter/SampleTasklet.java @@ -21,10 +21,9 @@ import java.util.Iterator; import org.springframework.batch.core.configuration.annotation.StepScope; -import org.springframework.batch.item.Chunk; -import org.springframework.batch.item.ExecutionContext; +import org.springframework.batch.infrastructure.item.Chunk; +import org.springframework.batch.infrastructure.item.ExecutionContext; import org.springframework.beans.factory.annotation.Value; -import org.springframework.lang.NonNull; import org.springframework.stereotype.Component; import com.navercorp.spring.batch.plus.step.adapter.ItemStreamIterableReaderProcessorWriter; @@ -38,9 +37,8 @@ class SampleTasklet implements ItemStreamIterableReaderProcessorWriter readIterable(@NonNull ExecutionContext executionContext) { + public Iterable readIterable(ExecutionContext executionContext) { System.out.println("totalCount: " + totalCount); return () -> new Iterator<>() { @Override @@ -56,12 +54,12 @@ public Integer next() { } @Override - public String process(@NonNull Integer item) { + public String process(Integer item) { return "'" + item.toString() + "'"; } @Override - public void write(@NonNull Chunk chunk) { + public void write(Chunk chunk) { System.out.println(chunk.getItems()); } } diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/iterable/readerprocessorwriter/TestJobConfig.java b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/iterable/readerprocessorwriter/TestJobConfig.java index 4e891c6e..81dfa5ae 100644 --- a/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/iterable/readerprocessorwriter/TestJobConfig.java +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/iterable/readerprocessorwriter/TestJobConfig.java @@ -22,7 +22,7 @@ import static com.navercorp.spring.batch.plus.step.adapter.AdapterFactory.itemStreamReader; import static com.navercorp.spring.batch.plus.step.adapter.AdapterFactory.itemStreamWriter; -import org.springframework.batch.core.Job; +import org.springframework.batch.core.job.Job; import org.springframework.batch.core.job.builder.JobBuilder; import org.springframework.batch.core.repository.JobRepository; import org.springframework.batch.core.step.builder.StepBuilder; @@ -42,7 +42,8 @@ public Job testJob( return new JobBuilder("testJob", jobRepository) .start( new StepBuilder("testStep", jobRepository) - .chunk(3, transactionManager) + .chunk(3) + .transactionManager(transactionManager) .reader(itemStreamReader(sampleTasklet)) .processor(itemProcessor(sampleTasklet)) .writer(itemStreamWriter(sampleTasklet)) diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/iterable/readerwriter/SampleApplicationTest.java b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/iterable/readerwriter/SampleApplicationTest.java index 6b48cb24..601a63ec 100644 --- a/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/iterable/readerwriter/SampleApplicationTest.java +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/iterable/readerwriter/SampleApplicationTest.java @@ -20,11 +20,11 @@ import org.junit.jupiter.api.Test; import org.springframework.batch.core.BatchStatus; -import org.springframework.batch.core.Job; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.JobParameters; -import org.springframework.batch.core.JobParametersBuilder; -import org.springframework.batch.core.launch.JobLauncher; +import org.springframework.batch.core.job.Job; +import org.springframework.batch.core.job.JobExecution; +import org.springframework.batch.core.job.parameters.JobParameters; +import org.springframework.batch.core.job.parameters.JobParametersBuilder; +import org.springframework.batch.core.launch.JobOperator; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ApplicationContext; @@ -34,13 +34,13 @@ public class SampleApplicationTest { @Test void run() throws Exception { ApplicationContext applicationContext = SpringApplication.run(SampleApplicationTest.class); - JobLauncher jobLauncher = applicationContext.getBean(JobLauncher.class); + JobOperator jobOperator = applicationContext.getBean(JobOperator.class); Job job = applicationContext.getBean("testJob", Job.class); JobParameters jobParameters = new JobParametersBuilder() .addLong("totalCount", 20L) .toJobParameters(); - JobExecution jobExecution = jobLauncher.run(job, jobParameters); + JobExecution jobExecution = jobOperator.start(job, jobParameters); assert BatchStatus.COMPLETED.equals(jobExecution.getStatus()); System.out.printf("%s%n", jobExecution); diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/iterable/readerwriter/SampleTasklet.java b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/iterable/readerwriter/SampleTasklet.java index b0a90652..004ed7cd 100644 --- a/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/iterable/readerwriter/SampleTasklet.java +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/iterable/readerwriter/SampleTasklet.java @@ -21,10 +21,9 @@ import java.util.Iterator; import org.springframework.batch.core.configuration.annotation.StepScope; -import org.springframework.batch.item.Chunk; -import org.springframework.batch.item.ExecutionContext; +import org.springframework.batch.infrastructure.item.Chunk; +import org.springframework.batch.infrastructure.item.ExecutionContext; import org.springframework.beans.factory.annotation.Value; -import org.springframework.lang.NonNull; import org.springframework.stereotype.Component; import com.navercorp.spring.batch.plus.step.adapter.ItemStreamIterableReaderWriter; @@ -38,9 +37,8 @@ class SampleTasklet implements ItemStreamIterableReaderWriter { private int count = 0; - @NonNull @Override - public Iterable readIterable(@NonNull ExecutionContext executionContext) { + public Iterable readIterable(ExecutionContext executionContext) { System.out.println("totalCount: " + totalCount); return () -> new Iterator<>() { @Override @@ -56,7 +54,7 @@ public Integer next() { } @Override - public void write(@NonNull Chunk chunk) { + public void write(Chunk chunk) { System.out.println(chunk.getItems()); } } diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/iterable/readerwriter/TestJobConfig.java b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/iterable/readerwriter/TestJobConfig.java index d096c161..f965c556 100644 --- a/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/iterable/readerwriter/TestJobConfig.java +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/iterable/readerwriter/TestJobConfig.java @@ -21,7 +21,7 @@ import static com.navercorp.spring.batch.plus.step.adapter.AdapterFactory.itemStreamReader; import static com.navercorp.spring.batch.plus.step.adapter.AdapterFactory.itemStreamWriter; -import org.springframework.batch.core.Job; +import org.springframework.batch.core.job.Job; import org.springframework.batch.core.job.builder.JobBuilder; import org.springframework.batch.core.repository.JobRepository; import org.springframework.batch.core.step.builder.StepBuilder; @@ -41,7 +41,8 @@ public Job testJob( return new JobBuilder("testJob", jobRepository) .start( new StepBuilder("testStep", jobRepository) - .chunk(3, transactionManager) + .chunk(3) + .transactionManager(transactionManager) .reader(itemStreamReader(sampleTasklet)) .writer(itemStreamWriter(sampleTasklet)) .build() diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/iterator/README.md b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/iterator/README.md new file mode 100644 index 00000000..f6bc3d38 --- /dev/null +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/iterator/README.md @@ -0,0 +1,9 @@ +# Iterator Reader Adapter Samples + +## Invariants + +- Samples should cover a single delegate whose reader produces items as an + `Iterator`. +- Every supported combination of reader, processor, and writer roles should have + a runnable sample. +- Lifecycle callback support should have a runnable sample. diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/iterator/callback/SampleApplicationTest.java b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/iterator/callback/SampleApplicationTest.java index 83903d17..58ee139c 100644 --- a/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/iterator/callback/SampleApplicationTest.java +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/iterator/callback/SampleApplicationTest.java @@ -20,11 +20,11 @@ import org.junit.jupiter.api.Test; import org.springframework.batch.core.BatchStatus; -import org.springframework.batch.core.Job; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.JobParameters; -import org.springframework.batch.core.JobParametersBuilder; -import org.springframework.batch.core.launch.JobLauncher; +import org.springframework.batch.core.job.Job; +import org.springframework.batch.core.job.JobExecution; +import org.springframework.batch.core.job.parameters.JobParameters; +import org.springframework.batch.core.job.parameters.JobParametersBuilder; +import org.springframework.batch.core.launch.JobOperator; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ApplicationContext; @@ -34,13 +34,13 @@ public class SampleApplicationTest { @Test void run() throws Exception { ApplicationContext applicationContext = SpringApplication.run(SampleApplicationTest.class); - JobLauncher jobLauncher = applicationContext.getBean(JobLauncher.class); + JobOperator jobOperator = applicationContext.getBean(JobOperator.class); Job job = applicationContext.getBean("testJob", Job.class); JobParameters jobParameters = new JobParametersBuilder() .addLong("totalCount", 20L) .toJobParameters(); - JobExecution jobExecution = jobLauncher.run(job, jobParameters); + JobExecution jobExecution = jobOperator.start(job, jobParameters); assert BatchStatus.COMPLETED.equals(jobExecution.getStatus()); System.out.printf("%s%n", jobExecution); diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/iterator/callback/SampleTasklet.java b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/iterator/callback/SampleTasklet.java index 3e2cba4c..68608834 100644 --- a/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/iterator/callback/SampleTasklet.java +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/iterator/callback/SampleTasklet.java @@ -21,10 +21,9 @@ import java.util.Iterator; import org.springframework.batch.core.configuration.annotation.StepScope; -import org.springframework.batch.item.Chunk; -import org.springframework.batch.item.ExecutionContext; +import org.springframework.batch.infrastructure.item.Chunk; +import org.springframework.batch.infrastructure.item.ExecutionContext; import org.springframework.beans.factory.annotation.Value; -import org.springframework.lang.NonNull; import org.springframework.stereotype.Component; import com.navercorp.spring.batch.plus.step.adapter.ItemStreamIteratorReaderProcessorWriter; @@ -39,13 +38,12 @@ public class SampleTasklet implements ItemStreamIteratorReaderProcessorWriter readIterator(@NonNull ExecutionContext executionContext) { + public Iterator readIterator(ExecutionContext executionContext) { System.out.println("totalCount: " + totalCount); return new Iterator<>() { @Override @@ -61,7 +59,7 @@ public Integer next() { } @Override - public void onUpdateRead(@NonNull ExecutionContext executionContext) { + public void onUpdateRead(ExecutionContext executionContext) { System.out.println("onUpdateRead"); } @@ -71,24 +69,24 @@ public void onCloseRead() { } @Override - public String process(@NonNull Integer item) { + public String process(Integer item) { return "'" + item.toString() + "'"; } @Override - public void onOpenWrite(@NonNull ExecutionContext executionContext) { + public void onOpenWrite(ExecutionContext executionContext) { System.out.println("onOpenWrite"); } @Override - public void write(@NonNull Chunk chunk) { + public void write(Chunk chunk) { System.out.println(chunk.getItems()); } @Override - public void onUpdateWrite(@NonNull ExecutionContext executionContext) { + public void onUpdateWrite(ExecutionContext executionContext) { System.out.println("onUpdateWrite"); - executionContext.putString("samplekey", "samplevlaue"); + executionContext.putString("samplekey", "samplevalue"); } @Override diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/iterator/callback/TestJobConfig.java b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/iterator/callback/TestJobConfig.java index bb877174..1d903172 100644 --- a/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/iterator/callback/TestJobConfig.java +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/iterator/callback/TestJobConfig.java @@ -22,7 +22,7 @@ import static com.navercorp.spring.batch.plus.step.adapter.AdapterFactory.itemStreamReader; import static com.navercorp.spring.batch.plus.step.adapter.AdapterFactory.itemStreamWriter; -import org.springframework.batch.core.Job; +import org.springframework.batch.core.job.Job; import org.springframework.batch.core.job.builder.JobBuilder; import org.springframework.batch.core.repository.JobRepository; import org.springframework.batch.core.step.builder.StepBuilder; @@ -42,7 +42,8 @@ public Job testJob( return new JobBuilder("testJob", jobRepository) .start( new StepBuilder("testStep", jobRepository) - .chunk(3, transactionManager) + .chunk(3) + .transactionManager(transactionManager) .reader(itemStreamReader(sampleTasklet)) .processor(itemProcessor(sampleTasklet)) .writer(itemStreamWriter(sampleTasklet)) diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/iterator/readerprocessor/SampleApplicationTest.java b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/iterator/readerprocessor/SampleApplicationTest.java index 7f7a57c2..b5a781d1 100644 --- a/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/iterator/readerprocessor/SampleApplicationTest.java +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/iterator/readerprocessor/SampleApplicationTest.java @@ -20,11 +20,11 @@ import org.junit.jupiter.api.Test; import org.springframework.batch.core.BatchStatus; -import org.springframework.batch.core.Job; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.JobParameters; -import org.springframework.batch.core.JobParametersBuilder; -import org.springframework.batch.core.launch.JobLauncher; +import org.springframework.batch.core.job.Job; +import org.springframework.batch.core.job.JobExecution; +import org.springframework.batch.core.job.parameters.JobParameters; +import org.springframework.batch.core.job.parameters.JobParametersBuilder; +import org.springframework.batch.core.launch.JobOperator; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ApplicationContext; @@ -34,13 +34,13 @@ public class SampleApplicationTest { @Test void run() throws Exception { ApplicationContext applicationContext = SpringApplication.run(SampleApplicationTest.class); - JobLauncher jobLauncher = applicationContext.getBean(JobLauncher.class); + JobOperator jobOperator = applicationContext.getBean(JobOperator.class); Job job = applicationContext.getBean("testJob", Job.class); JobParameters jobParameters = new JobParametersBuilder() .addLong("totalCount", 20L) .toJobParameters(); - JobExecution jobExecution = jobLauncher.run(job, jobParameters); + JobExecution jobExecution = jobOperator.start(job, jobParameters); assert BatchStatus.COMPLETED.equals(jobExecution.getStatus()); System.out.printf("%s%n", jobExecution); diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/iterator/readerprocessor/SampleTasklet.java b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/iterator/readerprocessor/SampleTasklet.java index db14fdbd..d8889a5f 100644 --- a/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/iterator/readerprocessor/SampleTasklet.java +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/iterator/readerprocessor/SampleTasklet.java @@ -21,9 +21,8 @@ import java.util.Iterator; import org.springframework.batch.core.configuration.annotation.StepScope; -import org.springframework.batch.item.ExecutionContext; +import org.springframework.batch.infrastructure.item.ExecutionContext; import org.springframework.beans.factory.annotation.Value; -import org.springframework.lang.NonNull; import org.springframework.stereotype.Component; import com.navercorp.spring.batch.plus.step.adapter.ItemStreamIteratorReaderProcessor; @@ -37,9 +36,8 @@ class SampleTasklet implements ItemStreamIteratorReaderProcessor readIterator(@NonNull ExecutionContext executionContext) { + public Iterator readIterator(ExecutionContext executionContext) { System.out.println("totalCount: " + totalCount); return new Iterator<>() { @Override @@ -55,7 +53,7 @@ public Integer next() { } @Override - public String process(@NonNull Integer item) { + public String process(Integer item) { return "'" + item.toString() + "'"; } } diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/iterator/readerprocessor/TestJobConfig.java b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/iterator/readerprocessor/TestJobConfig.java index 13aa896e..c2bf2cd1 100644 --- a/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/iterator/readerprocessor/TestJobConfig.java +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/iterator/readerprocessor/TestJobConfig.java @@ -21,7 +21,7 @@ import static com.navercorp.spring.batch.plus.step.adapter.AdapterFactory.itemProcessor; import static com.navercorp.spring.batch.plus.step.adapter.AdapterFactory.itemStreamReader; -import org.springframework.batch.core.Job; +import org.springframework.batch.core.job.Job; import org.springframework.batch.core.job.builder.JobBuilder; import org.springframework.batch.core.repository.JobRepository; import org.springframework.batch.core.step.builder.StepBuilder; @@ -41,7 +41,8 @@ public Job testJob( return new JobBuilder("testJob", jobRepository) .start( new StepBuilder("testStep", jobRepository) - .chunk(3, transactionManager) + .chunk(3) + .transactionManager(transactionManager) .reader(itemStreamReader(sampleTasklet)) .processor(itemProcessor(sampleTasklet)) .writer(chunk -> System.out.println(chunk.getItems())) diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/iterator/readerprocessorwriter/SampleApplicationTest.java b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/iterator/readerprocessorwriter/SampleApplicationTest.java index 21f25795..bcc22b75 100644 --- a/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/iterator/readerprocessorwriter/SampleApplicationTest.java +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/iterator/readerprocessorwriter/SampleApplicationTest.java @@ -20,11 +20,11 @@ import org.junit.jupiter.api.Test; import org.springframework.batch.core.BatchStatus; -import org.springframework.batch.core.Job; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.JobParameters; -import org.springframework.batch.core.JobParametersBuilder; -import org.springframework.batch.core.launch.JobLauncher; +import org.springframework.batch.core.job.Job; +import org.springframework.batch.core.job.JobExecution; +import org.springframework.batch.core.job.parameters.JobParameters; +import org.springframework.batch.core.job.parameters.JobParametersBuilder; +import org.springframework.batch.core.launch.JobOperator; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ApplicationContext; @@ -34,13 +34,13 @@ public class SampleApplicationTest { @Test void run() throws Exception { ApplicationContext applicationContext = SpringApplication.run(SampleApplicationTest.class); - JobLauncher jobLauncher = applicationContext.getBean(JobLauncher.class); + JobOperator jobOperator = applicationContext.getBean(JobOperator.class); Job job = applicationContext.getBean("testJob", Job.class); JobParameters jobParameters = new JobParametersBuilder() .addLong("totalCount", 20L) .toJobParameters(); - JobExecution jobExecution = jobLauncher.run(job, jobParameters); + JobExecution jobExecution = jobOperator.start(job, jobParameters); assert BatchStatus.COMPLETED.equals(jobExecution.getStatus()); System.out.printf("%s%n", jobExecution); diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/iterator/readerprocessorwriter/SampleTasklet.java b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/iterator/readerprocessorwriter/SampleTasklet.java index a287e2a6..3c1e1dd4 100644 --- a/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/iterator/readerprocessorwriter/SampleTasklet.java +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/iterator/readerprocessorwriter/SampleTasklet.java @@ -21,10 +21,9 @@ import java.util.Iterator; import org.springframework.batch.core.configuration.annotation.StepScope; -import org.springframework.batch.item.Chunk; -import org.springframework.batch.item.ExecutionContext; +import org.springframework.batch.infrastructure.item.Chunk; +import org.springframework.batch.infrastructure.item.ExecutionContext; import org.springframework.beans.factory.annotation.Value; -import org.springframework.lang.NonNull; import org.springframework.stereotype.Component; import com.navercorp.spring.batch.plus.step.adapter.ItemStreamIteratorReaderProcessorWriter; @@ -38,9 +37,8 @@ class SampleTasklet implements ItemStreamIteratorReaderProcessorWriter readIterator(@NonNull ExecutionContext executionContext) { + public Iterator readIterator(ExecutionContext executionContext) { System.out.println("totalCount: " + totalCount); return new Iterator<>() { @Override @@ -56,12 +54,12 @@ public Integer next() { } @Override - public String process(@NonNull Integer item) { + public String process(Integer item) { return "'" + item.toString() + "'"; } @Override - public void write(@NonNull Chunk chunk) { + public void write(Chunk chunk) { System.out.println(chunk.getItems()); } } diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/iterator/readerprocessorwriter/TestJobConfig.java b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/iterator/readerprocessorwriter/TestJobConfig.java index 226da478..8b13a891 100644 --- a/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/iterator/readerprocessorwriter/TestJobConfig.java +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/iterator/readerprocessorwriter/TestJobConfig.java @@ -22,7 +22,7 @@ import static com.navercorp.spring.batch.plus.step.adapter.AdapterFactory.itemStreamReader; import static com.navercorp.spring.batch.plus.step.adapter.AdapterFactory.itemStreamWriter; -import org.springframework.batch.core.Job; +import org.springframework.batch.core.job.Job; import org.springframework.batch.core.job.builder.JobBuilder; import org.springframework.batch.core.repository.JobRepository; import org.springframework.batch.core.step.builder.StepBuilder; @@ -42,7 +42,8 @@ public Job testJob( return new JobBuilder("testJob", jobRepository) .start( new StepBuilder("testStep", jobRepository) - .chunk(3, transactionManager) + .chunk(3) + .transactionManager(transactionManager) .reader(itemStreamReader(sampleTasklet)) .processor(itemProcessor(sampleTasklet)) .writer(itemStreamWriter(sampleTasklet)) diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/iterator/readerwriter/SampleApplicationTest.java b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/iterator/readerwriter/SampleApplicationTest.java index e01e204b..828a3b01 100644 --- a/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/iterator/readerwriter/SampleApplicationTest.java +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/iterator/readerwriter/SampleApplicationTest.java @@ -20,11 +20,11 @@ import org.junit.jupiter.api.Test; import org.springframework.batch.core.BatchStatus; -import org.springframework.batch.core.Job; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.JobParameters; -import org.springframework.batch.core.JobParametersBuilder; -import org.springframework.batch.core.launch.JobLauncher; +import org.springframework.batch.core.job.Job; +import org.springframework.batch.core.job.JobExecution; +import org.springframework.batch.core.job.parameters.JobParameters; +import org.springframework.batch.core.job.parameters.JobParametersBuilder; +import org.springframework.batch.core.launch.JobOperator; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ApplicationContext; @@ -34,13 +34,13 @@ public class SampleApplicationTest { @Test void run() throws Exception { ApplicationContext applicationContext = SpringApplication.run(SampleApplicationTest.class); - JobLauncher jobLauncher = applicationContext.getBean(JobLauncher.class); + JobOperator jobOperator = applicationContext.getBean(JobOperator.class); Job job = applicationContext.getBean("testJob", Job.class); JobParameters jobParameters = new JobParametersBuilder() .addLong("totalCount", 20L) .toJobParameters(); - JobExecution jobExecution = jobLauncher.run(job, jobParameters); + JobExecution jobExecution = jobOperator.start(job, jobParameters); assert BatchStatus.COMPLETED.equals(jobExecution.getStatus()); System.out.printf("%s%n", jobExecution); diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/iterator/readerwriter/SampleTasklet.java b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/iterator/readerwriter/SampleTasklet.java index d974aeb4..8c370dc0 100644 --- a/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/iterator/readerwriter/SampleTasklet.java +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/iterator/readerwriter/SampleTasklet.java @@ -21,10 +21,9 @@ import java.util.Iterator; import org.springframework.batch.core.configuration.annotation.StepScope; -import org.springframework.batch.item.Chunk; -import org.springframework.batch.item.ExecutionContext; +import org.springframework.batch.infrastructure.item.Chunk; +import org.springframework.batch.infrastructure.item.ExecutionContext; import org.springframework.beans.factory.annotation.Value; -import org.springframework.lang.NonNull; import org.springframework.stereotype.Component; import com.navercorp.spring.batch.plus.step.adapter.ItemStreamIteratorReaderWriter; @@ -38,9 +37,8 @@ class SampleTasklet implements ItemStreamIteratorReaderWriter { private int count = 0; - @NonNull @Override - public Iterator readIterator(@NonNull ExecutionContext executionContext) { + public Iterator readIterator(ExecutionContext executionContext) { System.out.println("totalCount: " + totalCount); return new Iterator<>() { @Override @@ -56,7 +54,7 @@ public Integer next() { } @Override - public void write(@NonNull Chunk chunk) { + public void write(Chunk chunk) { System.out.println(chunk.getItems()); } } diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/iterator/readerwriter/TestJobConfig.java b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/iterator/readerwriter/TestJobConfig.java index cfd347a8..d611b4f5 100644 --- a/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/iterator/readerwriter/TestJobConfig.java +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/iterator/readerwriter/TestJobConfig.java @@ -21,7 +21,7 @@ import static com.navercorp.spring.batch.plus.step.adapter.AdapterFactory.itemStreamReader; import static com.navercorp.spring.batch.plus.step.adapter.AdapterFactory.itemStreamWriter; -import org.springframework.batch.core.Job; +import org.springframework.batch.core.job.Job; import org.springframework.batch.core.job.builder.JobBuilder; import org.springframework.batch.core.repository.JobRepository; import org.springframework.batch.core.step.builder.StepBuilder; @@ -41,7 +41,8 @@ public Job testJob( return new JobBuilder("testJob", jobRepository) .start( new StepBuilder("testStep", jobRepository) - .chunk(3, transactionManager) + .chunk(3) + .transactionManager(transactionManager) .reader(itemStreamReader(sampleTasklet)) .writer(itemStreamWriter(sampleTasklet)) .build() diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/simple/README.md b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/simple/README.md new file mode 100644 index 00000000..ec6d05d3 --- /dev/null +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/simple/README.md @@ -0,0 +1,9 @@ +# Simple Reader Adapter Samples + +## Invariants + +- Samples should cover a single delegate whose reader produces one item at a + time. +- Every supported combination of reader, processor, and writer roles should have + a runnable sample. +- Lifecycle callback support should have a runnable sample. diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/simple/callback/SampleApplicationTest.java b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/simple/callback/SampleApplicationTest.java index 5e35ad4e..1d3f8a0c 100644 --- a/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/simple/callback/SampleApplicationTest.java +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/simple/callback/SampleApplicationTest.java @@ -20,11 +20,11 @@ import org.junit.jupiter.api.Test; import org.springframework.batch.core.BatchStatus; -import org.springframework.batch.core.Job; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.JobParameters; -import org.springframework.batch.core.JobParametersBuilder; -import org.springframework.batch.core.launch.JobLauncher; +import org.springframework.batch.core.job.Job; +import org.springframework.batch.core.job.JobExecution; +import org.springframework.batch.core.job.parameters.JobParameters; +import org.springframework.batch.core.job.parameters.JobParametersBuilder; +import org.springframework.batch.core.launch.JobOperator; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ApplicationContext; @@ -34,13 +34,13 @@ public class SampleApplicationTest { @Test void run() throws Exception { ApplicationContext applicationContext = SpringApplication.run(SampleApplicationTest.class); - JobLauncher jobLauncher = applicationContext.getBean(JobLauncher.class); + JobOperator jobOperator = applicationContext.getBean(JobOperator.class); Job job = applicationContext.getBean("testJob", Job.class); JobParameters jobParameters = new JobParametersBuilder() .addLong("totalCount", 20L) .toJobParameters(); - JobExecution jobExecution = jobLauncher.run(job, jobParameters); + JobExecution jobExecution = jobOperator.start(job, jobParameters); assert BatchStatus.COMPLETED.equals(jobExecution.getStatus()); System.out.printf("%s%n", jobExecution); diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/simple/callback/SampleTasklet.java b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/simple/callback/SampleTasklet.java index 0723f2c3..6307f3ff 100644 --- a/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/simple/callback/SampleTasklet.java +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/simple/callback/SampleTasklet.java @@ -19,10 +19,9 @@ package com.navercorp.spring.batch.plus.sample.simple.callback; import org.springframework.batch.core.configuration.annotation.StepScope; -import org.springframework.batch.item.Chunk; -import org.springframework.batch.item.ExecutionContext; +import org.springframework.batch.infrastructure.item.Chunk; +import org.springframework.batch.infrastructure.item.ExecutionContext; import org.springframework.beans.factory.annotation.Value; -import org.springframework.lang.NonNull; import org.springframework.stereotype.Component; import com.navercorp.spring.batch.plus.step.adapter.ItemStreamSimpleReaderProcessorWriter; @@ -37,7 +36,7 @@ public class SampleTasklet implements ItemStreamSimpleReaderProcessorWriter chunk) { + public void write(Chunk chunk) { System.out.println(chunk.getItems()); } @Override - public void onUpdateWrite(@NonNull ExecutionContext executionContext) { + public void onUpdateWrite(ExecutionContext executionContext) { System.out.println("onUpdateWrite"); - executionContext.putString("samplekey", "samplevlaue"); + executionContext.putString("samplekey", "samplevalue"); } @Override diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/simple/callback/TestJobConfig.java b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/simple/callback/TestJobConfig.java index 242ea677..1f79ae47 100644 --- a/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/simple/callback/TestJobConfig.java +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/simple/callback/TestJobConfig.java @@ -22,7 +22,7 @@ import static com.navercorp.spring.batch.plus.step.adapter.AdapterFactory.itemStreamReader; import static com.navercorp.spring.batch.plus.step.adapter.AdapterFactory.itemStreamWriter; -import org.springframework.batch.core.Job; +import org.springframework.batch.core.job.Job; import org.springframework.batch.core.job.builder.JobBuilder; import org.springframework.batch.core.repository.JobRepository; import org.springframework.batch.core.step.builder.StepBuilder; @@ -42,7 +42,8 @@ public Job testJob( return new JobBuilder("testJob", jobRepository) .start( new StepBuilder("testStep", jobRepository) - .chunk(3, transactionManager) + .chunk(3) + .transactionManager(transactionManager) .reader(itemStreamReader(sampleTasklet)) .processor(itemProcessor(sampleTasklet)) .writer(itemStreamWriter(sampleTasklet)) diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/simple/readerprocessor/SampleApplicationTest.java b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/simple/readerprocessor/SampleApplicationTest.java index ce39cd1c..5480c890 100644 --- a/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/simple/readerprocessor/SampleApplicationTest.java +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/simple/readerprocessor/SampleApplicationTest.java @@ -20,11 +20,11 @@ import org.junit.jupiter.api.Test; import org.springframework.batch.core.BatchStatus; -import org.springframework.batch.core.Job; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.JobParameters; -import org.springframework.batch.core.JobParametersBuilder; -import org.springframework.batch.core.launch.JobLauncher; +import org.springframework.batch.core.job.Job; +import org.springframework.batch.core.job.JobExecution; +import org.springframework.batch.core.job.parameters.JobParameters; +import org.springframework.batch.core.job.parameters.JobParametersBuilder; +import org.springframework.batch.core.launch.JobOperator; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ApplicationContext; @@ -34,13 +34,13 @@ public class SampleApplicationTest { @Test void run() throws Exception { ApplicationContext applicationContext = SpringApplication.run(SampleApplicationTest.class); - JobLauncher jobLauncher = applicationContext.getBean(JobLauncher.class); + JobOperator jobOperator = applicationContext.getBean(JobOperator.class); Job job = applicationContext.getBean("testJob", Job.class); JobParameters jobParameters = new JobParametersBuilder() .addLong("totalCount", 20L) .toJobParameters(); - JobExecution jobExecution = jobLauncher.run(job, jobParameters); + JobExecution jobExecution = jobOperator.start(job, jobParameters); assert BatchStatus.COMPLETED.equals(jobExecution.getStatus()); System.out.printf("%s%n", jobExecution); diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/simple/readerprocessor/SampleTasklet.java b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/simple/readerprocessor/SampleTasklet.java index c91c95e1..882419a3 100644 --- a/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/simple/readerprocessor/SampleTasklet.java +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/simple/readerprocessor/SampleTasklet.java @@ -20,7 +20,6 @@ import org.springframework.batch.core.configuration.annotation.StepScope; import org.springframework.beans.factory.annotation.Value; -import org.springframework.lang.NonNull; import org.springframework.stereotype.Component; import com.navercorp.spring.batch.plus.step.adapter.ItemStreamSimpleReaderProcessor; @@ -44,7 +43,7 @@ public Integer read() { } @Override - public String process(@NonNull Integer item) { + public String process(Integer item) { return "'" + item.toString() + "'"; } } diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/simple/readerprocessor/TestJobConfig.java b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/simple/readerprocessor/TestJobConfig.java index 716ad77b..37469c16 100644 --- a/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/simple/readerprocessor/TestJobConfig.java +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/simple/readerprocessor/TestJobConfig.java @@ -21,7 +21,7 @@ import static com.navercorp.spring.batch.plus.step.adapter.AdapterFactory.itemProcessor; import static com.navercorp.spring.batch.plus.step.adapter.AdapterFactory.itemStreamReader; -import org.springframework.batch.core.Job; +import org.springframework.batch.core.job.Job; import org.springframework.batch.core.job.builder.JobBuilder; import org.springframework.batch.core.repository.JobRepository; import org.springframework.batch.core.step.builder.StepBuilder; @@ -41,7 +41,8 @@ public Job testJob( return new JobBuilder("testJob", jobRepository) .start( new StepBuilder("testStep", jobRepository) - .chunk(3, transactionManager) + .chunk(3) + .transactionManager(transactionManager) .reader(itemStreamReader(sampleTasklet)) .processor(itemProcessor(sampleTasklet)) .writer(chunk -> System.out.println(chunk.getItems())) diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/simple/readerprocessorwriter/SampleApplicationTest.java b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/simple/readerprocessorwriter/SampleApplicationTest.java index 4e4003f6..13488bb9 100644 --- a/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/simple/readerprocessorwriter/SampleApplicationTest.java +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/simple/readerprocessorwriter/SampleApplicationTest.java @@ -20,11 +20,11 @@ import org.junit.jupiter.api.Test; import org.springframework.batch.core.BatchStatus; -import org.springframework.batch.core.Job; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.JobParameters; -import org.springframework.batch.core.JobParametersBuilder; -import org.springframework.batch.core.launch.JobLauncher; +import org.springframework.batch.core.job.Job; +import org.springframework.batch.core.job.JobExecution; +import org.springframework.batch.core.job.parameters.JobParameters; +import org.springframework.batch.core.job.parameters.JobParametersBuilder; +import org.springframework.batch.core.launch.JobOperator; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ApplicationContext; @@ -34,13 +34,13 @@ public class SampleApplicationTest { @Test void run() throws Exception { ApplicationContext applicationContext = SpringApplication.run(SampleApplicationTest.class); - JobLauncher jobLauncher = applicationContext.getBean(JobLauncher.class); + JobOperator jobOperator = applicationContext.getBean(JobOperator.class); Job job = applicationContext.getBean("testJob", Job.class); JobParameters jobParameters = new JobParametersBuilder() .addLong("totalCount", 20L) .toJobParameters(); - JobExecution jobExecution = jobLauncher.run(job, jobParameters); + JobExecution jobExecution = jobOperator.start(job, jobParameters); assert BatchStatus.COMPLETED.equals(jobExecution.getStatus()); System.out.printf("%s%n", jobExecution); diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/simple/readerprocessorwriter/SampleTasklet.java b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/simple/readerprocessorwriter/SampleTasklet.java index 06f037a0..16cd3f07 100644 --- a/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/simple/readerprocessorwriter/SampleTasklet.java +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/simple/readerprocessorwriter/SampleTasklet.java @@ -19,9 +19,8 @@ package com.navercorp.spring.batch.plus.sample.simple.readerprocessorwriter; import org.springframework.batch.core.configuration.annotation.StepScope; -import org.springframework.batch.item.Chunk; +import org.springframework.batch.infrastructure.item.Chunk; import org.springframework.beans.factory.annotation.Value; -import org.springframework.lang.NonNull; import org.springframework.stereotype.Component; import com.navercorp.spring.batch.plus.step.adapter.ItemStreamSimpleReaderProcessorWriter; @@ -45,12 +44,12 @@ public Integer read() { } @Override - public String process(@NonNull Integer item) { + public String process(Integer item) { return "'" + item.toString() + "'"; } @Override - public void write(@NonNull Chunk chunk) { + public void write(Chunk chunk) { System.out.println(chunk.getItems()); } } diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/simple/readerprocessorwriter/TestJobConfig.java b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/simple/readerprocessorwriter/TestJobConfig.java index 14b91e19..0a5c4037 100644 --- a/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/simple/readerprocessorwriter/TestJobConfig.java +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/simple/readerprocessorwriter/TestJobConfig.java @@ -22,7 +22,7 @@ import static com.navercorp.spring.batch.plus.step.adapter.AdapterFactory.itemStreamReader; import static com.navercorp.spring.batch.plus.step.adapter.AdapterFactory.itemStreamWriter; -import org.springframework.batch.core.Job; +import org.springframework.batch.core.job.Job; import org.springframework.batch.core.job.builder.JobBuilder; import org.springframework.batch.core.repository.JobRepository; import org.springframework.batch.core.step.builder.StepBuilder; @@ -35,14 +35,15 @@ public class TestJobConfig { @Bean public Job testJob( - com.navercorp.spring.batch.plus.sample.simple.readerprocessorwriter.SampleTasklet sampleTasklet, + SampleTasklet sampleTasklet, JobRepository jobRepository, PlatformTransactionManager transactionManager ) { return new JobBuilder("testJob", jobRepository) .start( new StepBuilder("testStep", jobRepository) - .chunk(3, transactionManager) + .chunk(3) + .transactionManager(transactionManager) .reader(itemStreamReader(sampleTasklet)) .processor(itemProcessor(sampleTasklet)) .writer(itemStreamWriter(sampleTasklet)) diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/simple/readerwriter/SampleApplicationTest.java b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/simple/readerwriter/SampleApplicationTest.java index 80a3ea0c..dd02c3e8 100644 --- a/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/simple/readerwriter/SampleApplicationTest.java +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/simple/readerwriter/SampleApplicationTest.java @@ -20,11 +20,11 @@ import org.junit.jupiter.api.Test; import org.springframework.batch.core.BatchStatus; -import org.springframework.batch.core.Job; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.JobParameters; -import org.springframework.batch.core.JobParametersBuilder; -import org.springframework.batch.core.launch.JobLauncher; +import org.springframework.batch.core.job.Job; +import org.springframework.batch.core.job.JobExecution; +import org.springframework.batch.core.job.parameters.JobParameters; +import org.springframework.batch.core.job.parameters.JobParametersBuilder; +import org.springframework.batch.core.launch.JobOperator; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ApplicationContext; @@ -34,13 +34,13 @@ public class SampleApplicationTest { @Test void run() throws Exception { ApplicationContext applicationContext = SpringApplication.run(SampleApplicationTest.class); - JobLauncher jobLauncher = applicationContext.getBean(JobLauncher.class); + JobOperator jobOperator = applicationContext.getBean(JobOperator.class); Job job = applicationContext.getBean("testJob", Job.class); JobParameters jobParameters = new JobParametersBuilder() .addLong("totalCount", 20L) .toJobParameters(); - JobExecution jobExecution = jobLauncher.run(job, jobParameters); + JobExecution jobExecution = jobOperator.start(job, jobParameters); assert BatchStatus.COMPLETED.equals(jobExecution.getStatus()); System.out.printf("%s%n", jobExecution); diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/simple/readerwriter/SampleTasklet.java b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/simple/readerwriter/SampleTasklet.java index 2e30dfc1..702e7c86 100644 --- a/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/simple/readerwriter/SampleTasklet.java +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/simple/readerwriter/SampleTasklet.java @@ -19,9 +19,8 @@ package com.navercorp.spring.batch.plus.sample.simple.readerwriter; import org.springframework.batch.core.configuration.annotation.StepScope; -import org.springframework.batch.item.Chunk; +import org.springframework.batch.infrastructure.item.Chunk; import org.springframework.beans.factory.annotation.Value; -import org.springframework.lang.NonNull; import org.springframework.stereotype.Component; import com.navercorp.spring.batch.plus.step.adapter.ItemStreamSimpleReaderWriter; @@ -45,7 +44,7 @@ public Integer read() { } @Override - public void write(@NonNull Chunk chunk) { + public void write(Chunk chunk) { System.out.println(chunk.getItems()); } } diff --git a/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/simple/readerwriter/TestJobConfig.java b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/simple/readerwriter/TestJobConfig.java index 6e6e25af..fa25327f 100644 --- a/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/simple/readerwriter/TestJobConfig.java +++ b/spring-batch-plus-sample/single-class-reader-processor-writer-sample/src/test/java/com/navercorp/spring/batch/plus/sample/simple/readerwriter/TestJobConfig.java @@ -21,7 +21,7 @@ import static com.navercorp.spring.batch.plus.step.adapter.AdapterFactory.itemStreamReader; import static com.navercorp.spring.batch.plus.step.adapter.AdapterFactory.itemStreamWriter; -import org.springframework.batch.core.Job; +import org.springframework.batch.core.job.Job; import org.springframework.batch.core.job.builder.JobBuilder; import org.springframework.batch.core.repository.JobRepository; import org.springframework.batch.core.step.builder.StepBuilder; @@ -41,7 +41,8 @@ public Job testJob( return new JobBuilder("testJob", jobRepository) .start( new StepBuilder("testStep", jobRepository) - .chunk(3, transactionManager) + .chunk(3) + .transactionManager(transactionManager) .reader(itemStreamReader(sampleTasklet)) .writer(itemStreamWriter(sampleTasklet)) .build() diff --git a/spring-batch-plus/build.gradle.kts b/spring-batch-plus/build.gradle.kts index 4c81d6d9..9d630823 100644 --- a/spring-batch-plus/build.gradle.kts +++ b/spring-batch-plus/build.gradle.kts @@ -4,6 +4,8 @@ plugins { } dependencies { + api(libs.jspecify) + compileOnly(libs.findbugs.jsr305) compileOnly(libs.spring.batch.core) compileOnly(libs.spring.jdbc) @@ -14,6 +16,7 @@ dependencies { testImplementation(libs.spring.batch.core) testImplementation(libs.spring.batch.test) testImplementation(libs.reactor.core) + testRuntimeOnly(libs.junit.platform.launcher) testRuntimeOnly(libs.h2) testRuntimeOnly(libs.log4j) } diff --git a/spring-batch-plus/src/integrationTest/java/com/navercorp/spring/batch/plus/item/adapter/ItemStreamReaderProcessorWriterIntegrationTest.java b/spring-batch-plus/src/integrationTest/java/com/navercorp/spring/batch/plus/item/adapter/ItemStreamReaderProcessorWriterIntegrationTest.java index 48dd63b2..94b86cf1 100644 --- a/spring-batch-plus/src/integrationTest/java/com/navercorp/spring/batch/plus/item/adapter/ItemStreamReaderProcessorWriterIntegrationTest.java +++ b/spring-batch-plus/src/integrationTest/java/com/navercorp/spring/batch/plus/item/adapter/ItemStreamReaderProcessorWriterIntegrationTest.java @@ -30,25 +30,25 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.batch.core.BatchStatus; -import org.springframework.batch.core.Job; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.JobParameters; -import org.springframework.batch.core.JobParametersBuilder; import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing; +import org.springframework.batch.core.configuration.annotation.EnableJdbcJobRepository; import org.springframework.batch.core.configuration.annotation.StepScope; +import org.springframework.batch.core.job.Job; +import org.springframework.batch.core.job.JobExecution; import org.springframework.batch.core.job.builder.JobBuilder; -import org.springframework.batch.core.launch.JobLauncher; +import org.springframework.batch.core.job.parameters.JobParameters; +import org.springframework.batch.core.job.parameters.JobParametersBuilder; +import org.springframework.batch.core.launch.JobOperator; import org.springframework.batch.core.repository.JobRepository; import org.springframework.batch.core.step.builder.StepBuilder; -import org.springframework.batch.item.Chunk; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.batch.support.transaction.ResourcelessTransactionManager; +import org.springframework.batch.infrastructure.item.Chunk; +import org.springframework.batch.infrastructure.item.ExecutionContext; +import org.springframework.batch.infrastructure.support.transaction.ResourcelessTransactionManager; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.jdbc.datasource.DataSourceTransactionManager; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType; -import org.springframework.lang.NonNull; import org.springframework.transaction.TransactionManager; import reactor.core.publisher.Flux; @@ -56,11 +56,11 @@ // note: it's deprecated. Do not change it. @SuppressWarnings({"unchecked", "deprecation"}) class ItemStreamReaderProcessorWriterIntegrationTest { + protected static final Logger logger = + LoggerFactory.getLogger(ItemStreamReaderProcessorWriterIntegrationTest.class); private static final int TEST_REPEAT_COUNT = 5; - private static final Logger logger = LoggerFactory.getLogger(ItemStreamReaderProcessorWriterIntegrationTest.class); - private static int onOpenReadCallCount = 0; private static int readContextCallCount = 0; private static int onUpdateReadCallCount = 0; @@ -109,20 +109,21 @@ void testReaderProcessorWriter() throws Exception { Job job = new JobBuilder("testJob", jobRepository) .start( new StepBuilder("testStep", jobRepository) - .chunk(chunkCount, new ResourcelessTransactionManager()) + .chunk(chunkCount) + .transactionManager(new ResourcelessTransactionManager()) .reader(AdapterFactory.itemStreamReader(testTasklet)) .processor(AdapterFactory.itemProcessor(testTasklet)) .writer(AdapterFactory.itemStreamWriter(testTasklet)) .build() ) .build(); - JobLauncher jobLauncher = context.getBean(JobLauncher.class); + JobOperator jobOperator = context.getBean(JobOperator.class); int beforeRepeatCount = ThreadLocalRandom.current().nextInt(0, 3); for (int i = 0; i < beforeRepeatCount; ++i) { JobParameters jobParameters = new JobParametersBuilder() .addString(UUID.randomUUID().toString(), UUID.randomUUID().toString()) .toJobParameters(); - jobLauncher.run(job, jobParameters); + jobOperator.start(job, jobParameters); } logger.debug("beforeRepeatCount: {}", beforeRepeatCount); @@ -130,7 +131,7 @@ void testReaderProcessorWriter() throws Exception { JobParameters jobParameters = new JobParametersBuilder() .addString(UUID.randomUUID().toString(), UUID.randomUUID().toString()) .toJobParameters(); - JobExecution jobExecution = jobLauncher.run(job, jobParameters); + JobExecution jobExecution = jobOperator.start(job, jobParameters); // then assertThat(jobExecution.getStatus()).isEqualTo(BatchStatus.COMPLETED); @@ -154,20 +155,21 @@ void testReaderProcessorWriterWithSameTaskletShouldKeepContext() throws Exceptio Job job = new JobBuilder("testJob", jobRepository) .start( new StepBuilder("testStep", jobRepository) - .chunk(chunkCount, new ResourcelessTransactionManager()) + .chunk(chunkCount) + .transactionManager(new ResourcelessTransactionManager()) .reader(AdapterFactory.itemStreamReader(testTasklet)) .processor(AdapterFactory.itemProcessor(testTasklet)) .writer(AdapterFactory.itemStreamWriter(testTasklet)) .build() ) .build(); - JobLauncher jobLauncher = context.getBean(JobLauncher.class); + JobOperator jobOperator = context.getBean(JobOperator.class); int beforeRepeatCount = ThreadLocalRandom.current().nextInt(0, 3); for (int i = 0; i < beforeRepeatCount; ++i) { JobParameters jobParameters = new JobParametersBuilder() .addString(UUID.randomUUID().toString(), UUID.randomUUID().toString()) .toJobParameters(); - jobLauncher.run(job, jobParameters); + jobOperator.start(job, jobParameters); } logger.debug("beforeRepeatCount: {}", beforeRepeatCount); @@ -175,7 +177,7 @@ void testReaderProcessorWriterWithSameTaskletShouldKeepContext() throws Exceptio JobParameters jobParameters = new JobParametersBuilder() .addString(UUID.randomUUID().toString(), UUID.randomUUID().toString()) .toJobParameters(); - JobExecution jobExecution = jobLauncher.run(job, jobParameters); + JobExecution jobExecution = jobOperator.start(job, jobParameters); // then assertThat(jobExecution.getStatus()).isEqualTo(BatchStatus.COMPLETED); @@ -195,20 +197,21 @@ void testStepScopeReaderProcessorWriter() throws Exception { Job job = new JobBuilder("testJob", jobRepository) .start( new StepBuilder("testStep", jobRepository) - .chunk(chunkCount, new ResourcelessTransactionManager()) + .chunk(chunkCount) + .transactionManager(new ResourcelessTransactionManager()) .reader(AdapterFactory.itemStreamReader(testTasklet)) .processor(AdapterFactory.itemProcessor(testTasklet)) .writer(AdapterFactory.itemStreamWriter(testTasklet)) .build() ) .build(); - JobLauncher jobLauncher = context.getBean(JobLauncher.class); + JobOperator jobOperator = context.getBean(JobOperator.class); int beforeRepeatCount = ThreadLocalRandom.current().nextInt(0, 3); for (int i = 0; i < beforeRepeatCount; ++i) { JobParameters jobParameters = new JobParametersBuilder() .addString(UUID.randomUUID().toString(), UUID.randomUUID().toString()) .toJobParameters(); - jobLauncher.run(job, jobParameters); + jobOperator.start(job, jobParameters); } logger.debug("beforeRepeatCount: {}", beforeRepeatCount); @@ -216,7 +219,7 @@ void testStepScopeReaderProcessorWriter() throws Exception { JobParameters jobParameters = new JobParametersBuilder() .addString(UUID.randomUUID().toString(), UUID.randomUUID().toString()) .toJobParameters(); - JobExecution jobExecution = jobLauncher.run(job, jobParameters); + JobExecution jobExecution = jobOperator.start(job, jobParameters); // then assertThat(jobExecution.getStatus()).isEqualTo(BatchStatus.COMPLETED); @@ -240,20 +243,21 @@ void testStepScopeReaderProcessorWriterWithSameTaskletShouldNotKeepCountContext( Job job = new JobBuilder("testJob", jobRepository) .start( new StepBuilder("testStep", jobRepository) - .chunk(chunkCount, new ResourcelessTransactionManager()) + .chunk(chunkCount) + .transactionManager(new ResourcelessTransactionManager()) .reader(AdapterFactory.itemStreamReader(testTasklet)) .processor(AdapterFactory.itemProcessor(testTasklet)) .writer(AdapterFactory.itemStreamWriter(testTasklet)) .build() ) .build(); - JobLauncher jobLauncher = context.getBean(JobLauncher.class); + JobOperator jobOperator = context.getBean(JobOperator.class); int beforeRepeatCount = ThreadLocalRandom.current().nextInt(0, 3); for (int i = 0; i < beforeRepeatCount; ++i) { JobParameters jobParameters = new JobParametersBuilder() .addString(UUID.randomUUID().toString(), UUID.randomUUID().toString()) .toJobParameters(); - jobLauncher.run(job, jobParameters); + jobOperator.start(job, jobParameters); } logger.debug("beforeRepeatCount: {}", beforeRepeatCount); @@ -261,7 +265,7 @@ void testStepScopeReaderProcessorWriterWithSameTaskletShouldNotKeepCountContext( JobParameters jobParameters = new JobParametersBuilder() .addString(UUID.randomUUID().toString(), UUID.randomUUID().toString()) .toJobParameters(); - JobExecution jobExecution = jobLauncher.run(job, jobParameters); + JobExecution jobExecution = jobOperator.start(job, jobParameters); // then assertThat(jobExecution.getStatus()).isEqualTo(BatchStatus.COMPLETED); @@ -271,7 +275,8 @@ void testStepScopeReaderProcessorWriterWithSameTaskletShouldNotKeepCountContext( } @SuppressWarnings("unused") - @EnableBatchProcessing( + @EnableBatchProcessing + @EnableJdbcJobRepository( dataSourceRef = "metadataDataSource", transactionManagerRef = "metadataTransactionManager" ) @@ -298,13 +303,12 @@ ItemStreamReaderProcessorWriter testTasklet() { private int count = 0; @Override - public void onOpenRead(@NonNull ExecutionContext executionContext) { + public void onOpenRead(ExecutionContext executionContext) { ++onOpenReadCallCount; } - @NonNull @Override - public Flux readFlux(@NonNull ExecutionContext executionContext) { + public Flux readFlux(ExecutionContext executionContext) { ++readContextCallCount; return Flux.generate(sink -> { if (count < itemCount) { @@ -317,7 +321,7 @@ public Flux readFlux(@NonNull ExecutionContext executionContext) { } @Override - public void onUpdateRead(@NonNull ExecutionContext executionContext) { + public void onUpdateRead(ExecutionContext executionContext) { ++onUpdateReadCallCount; } @@ -327,23 +331,23 @@ public void onCloseRead() { } @Override - public Integer process(@NonNull Integer item) { + public Integer process(Integer item) { ++processCallCount; return item; } @Override - public void onOpenWrite(@NonNull ExecutionContext executionContext) { + public void onOpenWrite(ExecutionContext executionContext) { ++onOpenWriteCallCount; } @Override - public void write(@NonNull Chunk chunk) { + public void write(Chunk chunk) { ++writeCallCount; } @Override - public void onUpdateWrite(@NonNull ExecutionContext executionContext) { + public void onUpdateWrite(ExecutionContext executionContext) { ++onUpdateWriteCallCount; } @@ -362,13 +366,12 @@ ItemStreamReaderProcessorWriter stepScopeTestTasklet() { private int count = 0; @Override - public void onOpenRead(@NonNull ExecutionContext executionContext) { + public void onOpenRead(ExecutionContext executionContext) { ++onOpenReadCallCount; } - @NonNull @Override - public Flux readFlux(@NonNull ExecutionContext executionContext) { + public Flux readFlux(ExecutionContext executionContext) { ++readContextCallCount; return Flux.generate(sink -> { if (count < itemCount) { @@ -381,7 +384,7 @@ public Flux readFlux(@NonNull ExecutionContext executionContext) { } @Override - public void onUpdateRead(@NonNull ExecutionContext executionContext) { + public void onUpdateRead(ExecutionContext executionContext) { ++onUpdateReadCallCount; } @@ -391,23 +394,23 @@ public void onCloseRead() { } @Override - public void onOpenWrite(@NonNull ExecutionContext executionContext) { + public void onOpenWrite(ExecutionContext executionContext) { ++onOpenWriteCallCount; } @Override - public Integer process(@NonNull Integer item) { + public Integer process(Integer item) { ++processCallCount; return item; } @Override - public void write(@NonNull Chunk chunk) { + public void write(Chunk chunk) { ++writeCallCount; } @Override - public void onUpdateWrite(@NonNull ExecutionContext executionContext) { + public void onUpdateWrite(ExecutionContext executionContext) { ++onUpdateWriteCallCount; } diff --git a/spring-batch-plus/src/integrationTest/java/com/navercorp/spring/batch/plus/item/adapter/ItemStreamReaderWriterIntegrationTest.java b/spring-batch-plus/src/integrationTest/java/com/navercorp/spring/batch/plus/item/adapter/ItemStreamReaderWriterIntegrationTest.java index 33411f26..0fc9ba4c 100644 --- a/spring-batch-plus/src/integrationTest/java/com/navercorp/spring/batch/plus/item/adapter/ItemStreamReaderWriterIntegrationTest.java +++ b/spring-batch-plus/src/integrationTest/java/com/navercorp/spring/batch/plus/item/adapter/ItemStreamReaderWriterIntegrationTest.java @@ -30,25 +30,25 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.batch.core.BatchStatus; -import org.springframework.batch.core.Job; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.JobParameters; -import org.springframework.batch.core.JobParametersBuilder; import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing; +import org.springframework.batch.core.configuration.annotation.EnableJdbcJobRepository; import org.springframework.batch.core.configuration.annotation.StepScope; +import org.springframework.batch.core.job.Job; +import org.springframework.batch.core.job.JobExecution; import org.springframework.batch.core.job.builder.JobBuilder; -import org.springframework.batch.core.launch.JobLauncher; +import org.springframework.batch.core.job.parameters.JobParameters; +import org.springframework.batch.core.job.parameters.JobParametersBuilder; +import org.springframework.batch.core.launch.JobOperator; import org.springframework.batch.core.repository.JobRepository; import org.springframework.batch.core.step.builder.StepBuilder; -import org.springframework.batch.item.Chunk; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.batch.support.transaction.ResourcelessTransactionManager; +import org.springframework.batch.infrastructure.item.Chunk; +import org.springframework.batch.infrastructure.item.ExecutionContext; +import org.springframework.batch.infrastructure.support.transaction.ResourcelessTransactionManager; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.jdbc.datasource.DataSourceTransactionManager; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType; -import org.springframework.lang.NonNull; import org.springframework.transaction.TransactionManager; import reactor.core.publisher.Flux; @@ -56,11 +56,10 @@ // note: it's deprecated. Do not change it. @SuppressWarnings({"unchecked", "deprecation"}) class ItemStreamReaderWriterIntegrationTest { + protected static final Logger logger = LoggerFactory.getLogger(ItemStreamReaderWriterIntegrationTest.class); private static final int TEST_REPEAT_COUNT = 5; - private static final Logger logger = LoggerFactory.getLogger(ItemStreamReaderWriterIntegrationTest.class); - private static int onOpenReadCallCount = 0; private static int readContextCallCount = 0; private static int onUpdateReadCallCount = 0; @@ -105,19 +104,20 @@ void testReaderWriter() throws Exception { Job job = new JobBuilder("testJob", jobRepository) .start( new StepBuilder("testStep", jobRepository) - .chunk(chunkCount, new ResourcelessTransactionManager()) + .chunk(chunkCount) + .transactionManager(new ResourcelessTransactionManager()) .reader(AdapterFactory.itemStreamReader(testTasklet)) .writer(AdapterFactory.itemStreamWriter(testTasklet)) .build() ) .build(); - JobLauncher jobLauncher = context.getBean(JobLauncher.class); + JobOperator jobOperator = context.getBean(JobOperator.class); int beforeRepeatCount = ThreadLocalRandom.current().nextInt(0, 3); for (int i = 0; i < beforeRepeatCount; ++i) { JobParameters jobParameters = new JobParametersBuilder() .addString(UUID.randomUUID().toString(), UUID.randomUUID().toString()) .toJobParameters(); - jobLauncher.run(job, jobParameters); + jobOperator.start(job, jobParameters); } logger.debug("beforeRepeatCount: {}", beforeRepeatCount); @@ -125,7 +125,7 @@ void testReaderWriter() throws Exception { JobParameters jobParameters = new JobParametersBuilder() .addString(UUID.randomUUID().toString(), UUID.randomUUID().toString()) .toJobParameters(); - JobExecution jobExecution = jobLauncher.run(job, jobParameters); + JobExecution jobExecution = jobOperator.start(job, jobParameters); // then assertThat(jobExecution.getStatus()).isEqualTo(BatchStatus.COMPLETED); @@ -149,19 +149,20 @@ void testReaderWriterWithSameTaskletShouldKeepCountContext() throws Exception { Job job = new JobBuilder("testJob", jobRepository) .start( new StepBuilder("testStep", jobRepository) - .chunk(chunkCount, new ResourcelessTransactionManager()) + .chunk(chunkCount) + .transactionManager(new ResourcelessTransactionManager()) .reader(AdapterFactory.itemStreamReader(testTasklet)) .writer(AdapterFactory.itemStreamWriter(testTasklet)) .build() ) .build(); - JobLauncher jobLauncher = context.getBean(JobLauncher.class); + JobOperator jobOperator = context.getBean(JobOperator.class); int beforeRepeatCount = ThreadLocalRandom.current().nextInt(0, 3); for (int i = 0; i < beforeRepeatCount; ++i) { JobParameters jobParameters = new JobParametersBuilder() .addString(UUID.randomUUID().toString(), UUID.randomUUID().toString()) .toJobParameters(); - jobLauncher.run(job, jobParameters); + jobOperator.start(job, jobParameters); } logger.debug("beforeRepeatCount: {}", beforeRepeatCount); @@ -169,7 +170,7 @@ void testReaderWriterWithSameTaskletShouldKeepCountContext() throws Exception { JobParameters jobParameters = new JobParametersBuilder() .addString(UUID.randomUUID().toString(), UUID.randomUUID().toString()) .toJobParameters(); - JobExecution jobExecution = jobLauncher.run(job, jobParameters); + JobExecution jobExecution = jobOperator.start(job, jobParameters); // then assertThat(jobExecution.getStatus()).isEqualTo(BatchStatus.COMPLETED); @@ -188,19 +189,20 @@ void testStepScopeReaderWriter() throws Exception { Job job = new JobBuilder("testJob", jobRepository) .start( new StepBuilder("testStep", jobRepository) - .chunk(chunkCount, new ResourcelessTransactionManager()) + .chunk(chunkCount) + .transactionManager(new ResourcelessTransactionManager()) .reader(AdapterFactory.itemStreamReader(testTasklet)) .writer(AdapterFactory.itemStreamWriter(testTasklet)) .build() ) .build(); - JobLauncher jobLauncher = context.getBean(JobLauncher.class); + JobOperator jobOperator = context.getBean(JobOperator.class); int beforeRepeatCount = ThreadLocalRandom.current().nextInt(0, 3); for (int i = 0; i < beforeRepeatCount; ++i) { JobParameters jobParameters = new JobParametersBuilder() .addString(UUID.randomUUID().toString(), UUID.randomUUID().toString()) .toJobParameters(); - jobLauncher.run(job, jobParameters); + jobOperator.start(job, jobParameters); } logger.debug("beforeRepeatCount: {}", beforeRepeatCount); @@ -208,7 +210,7 @@ void testStepScopeReaderWriter() throws Exception { JobParameters jobParameters = new JobParametersBuilder() .addString(UUID.randomUUID().toString(), UUID.randomUUID().toString()) .toJobParameters(); - JobExecution jobExecution = jobLauncher.run(job, jobParameters); + JobExecution jobExecution = jobOperator.start(job, jobParameters); // then assertThat(jobExecution.getStatus()).isEqualTo(BatchStatus.COMPLETED); @@ -232,19 +234,20 @@ void testStepScopeReaderWriterWithSameTaskletShouldNotKeepCountContext() throws Job job = new JobBuilder("testJob", jobRepository) .start( new StepBuilder("testStep", jobRepository) - .chunk(chunkCount, new ResourcelessTransactionManager()) + .chunk(chunkCount) + .transactionManager(new ResourcelessTransactionManager()) .reader(AdapterFactory.itemStreamReader(testTasklet)) .writer(AdapterFactory.itemStreamWriter(testTasklet)) .build() ) .build(); - JobLauncher jobLauncher = context.getBean(JobLauncher.class); + JobOperator jobOperator = context.getBean(JobOperator.class); int beforeRepeatCount = ThreadLocalRandom.current().nextInt(0, 3); for (int i = 0; i < beforeRepeatCount; ++i) { JobParameters jobParameters = new JobParametersBuilder() .addString(UUID.randomUUID().toString(), UUID.randomUUID().toString()) .toJobParameters(); - jobLauncher.run(job, jobParameters); + jobOperator.start(job, jobParameters); } logger.debug("beforeRepeatCount: {}", beforeRepeatCount); @@ -252,7 +255,7 @@ void testStepScopeReaderWriterWithSameTaskletShouldNotKeepCountContext() throws JobParameters jobParameters = new JobParametersBuilder() .addString(UUID.randomUUID().toString(), UUID.randomUUID().toString()) .toJobParameters(); - JobExecution jobExecution = jobLauncher.run(job, jobParameters); + JobExecution jobExecution = jobOperator.start(job, jobParameters); // then assertThat(jobExecution.getStatus()).isEqualTo(BatchStatus.COMPLETED); @@ -261,7 +264,8 @@ void testStepScopeReaderWriterWithSameTaskletShouldNotKeepCountContext() throws } @SuppressWarnings("unused") - @EnableBatchProcessing( + @EnableBatchProcessing + @EnableJdbcJobRepository( dataSourceRef = "metadataDataSource", transactionManagerRef = "metadataTransactionManager" ) @@ -288,13 +292,12 @@ ItemStreamReaderWriter testTasklet() { private int count = 0; @Override - public void onOpenRead(@NonNull ExecutionContext executionContext) { + public void onOpenRead(ExecutionContext executionContext) { ++onOpenReadCallCount; } - @NonNull @Override - public Flux readFlux(@NonNull ExecutionContext executionContext) { + public Flux readFlux(ExecutionContext executionContext) { ++readContextCallCount; return Flux.generate(sink -> { if (count < itemCount) { @@ -307,7 +310,7 @@ public Flux readFlux(@NonNull ExecutionContext executionContext) { } @Override - public void onUpdateRead(@NonNull ExecutionContext executionContext) { + public void onUpdateRead(ExecutionContext executionContext) { ++onUpdateReadCallCount; } @@ -317,17 +320,17 @@ public void onCloseRead() { } @Override - public void onOpenWrite(@NonNull ExecutionContext executionContext) { + public void onOpenWrite(ExecutionContext executionContext) { ++onOpenWriteCallCount; } @Override - public void write(@NonNull Chunk chunk) { + public void write(Chunk chunk) { ++writeCallCount; } @Override - public void onUpdateWrite(@NonNull ExecutionContext executionContext) { + public void onUpdateWrite(ExecutionContext executionContext) { ++onUpdateWriteCallCount; } @@ -346,13 +349,12 @@ ItemStreamReaderWriter stepScopeTestTasklet() { private int count = 0; @Override - public void onOpenRead(@NonNull ExecutionContext executionContext) { + public void onOpenRead(ExecutionContext executionContext) { ++onOpenReadCallCount; } - @NonNull @Override - public Flux readFlux(@NonNull ExecutionContext executionContext) { + public Flux readFlux(ExecutionContext executionContext) { ++readContextCallCount; return Flux.generate(sink -> { if (count < itemCount) { @@ -365,7 +367,7 @@ public Flux readFlux(@NonNull ExecutionContext executionContext) { } @Override - public void onUpdateRead(@NonNull ExecutionContext executionContext) { + public void onUpdateRead(ExecutionContext executionContext) { ++onUpdateReadCallCount; } @@ -375,17 +377,17 @@ public void onCloseRead() { } @Override - public void onOpenWrite(@NonNull ExecutionContext executionContext) { + public void onOpenWrite(ExecutionContext executionContext) { ++onOpenWriteCallCount; } @Override - public void write(@NonNull Chunk chunk) { + public void write(Chunk chunk) { ++writeCallCount; } @Override - public void onUpdateWrite(@NonNull ExecutionContext executionContext) { + public void onUpdateWrite(ExecutionContext executionContext) { ++onUpdateWriteCallCount; } diff --git a/spring-batch-plus/src/integrationTest/java/com/navercorp/spring/batch/plus/job/ClearRunIdIncrementerIntegrationTest.java b/spring-batch-plus/src/integrationTest/java/com/navercorp/spring/batch/plus/job/ClearRunIdIncrementerIntegrationTest.java new file mode 100644 index 00000000..83569847 --- /dev/null +++ b/spring-batch-plus/src/integrationTest/java/com/navercorp/spring/batch/plus/job/ClearRunIdIncrementerIntegrationTest.java @@ -0,0 +1,163 @@ +/* + * Spring Batch Plus + * + * Copyright 2022-present NAVER Corp. + * + * 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 + * + * http://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 com.navercorp.spring.batch.plus.job; + +import static org.assertj.core.api.Assertions.*; + +import java.util.UUID; +import java.util.concurrent.ThreadLocalRandom; + +import javax.sql.DataSource; + +import org.junit.jupiter.api.Test; +import org.springframework.batch.core.BatchStatus; +import org.springframework.batch.core.ExitStatus; +import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing; +import org.springframework.batch.core.configuration.annotation.EnableJdbcJobRepository; +import org.springframework.batch.core.job.Job; +import org.springframework.batch.core.job.JobExecution; +import org.springframework.batch.core.job.JobInstance; +import org.springframework.batch.core.job.builder.JobBuilder; +import org.springframework.batch.core.job.parameters.JobParameters; +import org.springframework.batch.core.job.parameters.JobParametersBuilder; +import org.springframework.batch.core.job.parameters.JobParametersIncrementer; +import org.springframework.batch.core.job.parameters.RunIdIncrementer; +import org.springframework.batch.core.launch.JobOperator; +import org.springframework.batch.core.repository.JobRepository; +import org.springframework.batch.core.step.Step; +import org.springframework.batch.core.step.builder.StepBuilder; +import org.springframework.batch.infrastructure.item.ExecutionContext; +import org.springframework.batch.infrastructure.repeat.RepeatStatus; +import org.springframework.batch.infrastructure.support.transaction.ResourcelessTransactionManager; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.jdbc.datasource.DataSourceTransactionManager; +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType; +import org.springframework.transaction.TransactionManager; + +/** + * Covers the next-instance parameter propagation difference between the standard and clearing incrementers. + */ +class ClearRunIdIncrementerIntegrationTest { + + @Test + void startNextInstanceShouldCarryPreviousNonRunIdParametersForwardWhenRunIdIncrementerIsUsed() { + long previousRunId = ThreadLocalRandom.current().nextLong(1, Long.MAX_VALUE); + String previousParameterName = UUID.randomUUID().toString(); + String previousParameterValue = UUID.randomUUID().toString(); + JobParametersIncrementer incrementer = new RunIdIncrementer(); + + JobExecution jobExecution = startNextInstanceAfterCompletedExecution(incrementer, previousRunId, + previousParameterName, previousParameterValue); + + JobParameters actual = jobExecution.getJobParameters(); + + assertThat(jobExecution.getStatus()).isEqualTo(BatchStatus.COMPLETED); + assertThat(actual.getLong("run.id")).isEqualTo(previousRunId + 1); + assertThat(actual.getString(previousParameterName)).isEqualTo(previousParameterValue); + assertThat(actual.parameters()).hasSize(2); + } + + @Test + void startNextInstanceShouldDiscardPreviousNonRunIdParametersWhenClearRunIdIncrementerIsUsed() { + long previousRunId = ThreadLocalRandom.current().nextLong(1, Long.MAX_VALUE); + String previousParameterName = UUID.randomUUID().toString(); + String previousParameterValue = UUID.randomUUID().toString(); + JobParametersIncrementer incrementer = ClearRunIdIncrementer.create(); + + JobExecution jobExecution = startNextInstanceAfterCompletedExecution(incrementer, previousRunId, + previousParameterName, previousParameterValue); + + JobParameters actual = jobExecution.getJobParameters(); + + assertThat(jobExecution.getStatus()).isEqualTo(BatchStatus.COMPLETED); + assertThat(actual.getLong("run.id")).isEqualTo(previousRunId + 1); + assertThat(actual.parameters()).hasSize(1); + } + + private JobExecution startNextInstanceAfterCompletedExecution( + JobParametersIncrementer incrementer, + long previousRunId, + String previousParameterName, + String previousParameterValue + ) { + try (AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext()) { + context.register(BatchConfiguration.class); + context.refresh(); + JobRepository jobRepository = context.getBean(JobRepository.class); + Step step = new StepBuilder("testStep", jobRepository) + .tasklet( + (contribution, chunkContext) -> RepeatStatus.FINISHED, + new ResourcelessTransactionManager() + ) + .build(); + Job job = new JobBuilder("testJob", jobRepository) + .incrementer(incrementer) + .start(step) + .build(); + JobOperator jobOperator = context.getBean(JobOperator.class); + JobParameters previousParameters = new JobParametersBuilder() + .addLong("run.id", previousRunId) + .addString(previousParameterName, previousParameterValue) + .toJobParameters(); + seedCompletedJobExecution(jobRepository, job, previousParameters); + + return jobOperator.startNextInstance(job); + } + } + + private void seedCompletedJobExecution( + JobRepository jobRepository, + Job job, + JobParameters jobParameters + ) { + JobInstance jobInstance = jobRepository.createJobInstance(job.getName(), jobParameters); + JobExecution jobExecution = jobRepository.createJobExecution( + jobInstance, + jobParameters, + new ExecutionContext() + ); + jobExecution.setStatus(BatchStatus.COMPLETED); + jobExecution.setExitStatus(ExitStatus.COMPLETED); + jobRepository.update(jobExecution); + } + + @EnableBatchProcessing + @EnableJdbcJobRepository( + dataSourceRef = "metadataDataSource", + transactionManagerRef = "metadataTransactionManager" + ) + private static class BatchConfiguration { + + @Bean + TransactionManager metadataTransactionManager() { + return new DataSourceTransactionManager(metadataDataSource()); + } + + @Bean + DataSource metadataDataSource() { + return new EmbeddedDatabaseBuilder() + .setType(EmbeddedDatabaseType.H2) + .addScript("/org/springframework/batch/core/schema-h2.sql") + .generateUniqueName(true) + .build(); + } + } +} diff --git a/spring-batch-plus/src/integrationTest/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamFluxReaderProcessorIT.java b/spring-batch-plus/src/integrationTest/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamFluxReaderProcessorIntegrationTest.java similarity index 83% rename from spring-batch-plus/src/integrationTest/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamFluxReaderProcessorIT.java rename to spring-batch-plus/src/integrationTest/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamFluxReaderProcessorIntegrationTest.java index cdd24800..2deac3d7 100644 --- a/spring-batch-plus/src/integrationTest/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamFluxReaderProcessorIT.java +++ b/spring-batch-plus/src/integrationTest/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamFluxReaderProcessorIntegrationTest.java @@ -31,35 +31,38 @@ import org.junit.jupiter.api.RepeatedTest; import org.springframework.batch.core.BatchStatus; -import org.springframework.batch.core.Job; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.JobParameters; -import org.springframework.batch.core.JobParametersBuilder; import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing; +import org.springframework.batch.core.configuration.annotation.EnableJdbcJobRepository; import org.springframework.batch.core.configuration.annotation.StepScope; +import org.springframework.batch.core.job.Job; +import org.springframework.batch.core.job.JobExecution; import org.springframework.batch.core.job.builder.JobBuilder; -import org.springframework.batch.core.launch.JobLauncher; +import org.springframework.batch.core.job.parameters.JobParameters; +import org.springframework.batch.core.job.parameters.JobParametersBuilder; +import org.springframework.batch.core.launch.JobOperator; import org.springframework.batch.core.repository.JobRepository; import org.springframework.batch.core.step.builder.StepBuilder; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.batch.support.transaction.ResourcelessTransactionManager; +import org.springframework.batch.infrastructure.item.ExecutionContext; +import org.springframework.batch.infrastructure.support.transaction.ResourcelessTransactionManager; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.jdbc.datasource.DataSourceTransactionManager; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType; -import org.springframework.lang.NonNull; import org.springframework.transaction.TransactionManager; import reactor.core.publisher.Flux; +/** + * Covers how delegate scope controls state isolation across step executions. + */ @SuppressWarnings({"unchecked", "unused"}) -class ItemStreamFluxReaderProcessorIT { +class ItemStreamFluxReaderProcessorIntegrationTest { private static final int TEST_REPEAT_COUNT = 5; @RepeatedTest(TEST_REPEAT_COUNT) - void fluxReaderProcessorShouldNotKeepCountWhenStepScoped() throws Exception { + void stepScopedDelegateShouldUseFreshStateForEachStepExecution() throws Exception { int itemCount = ThreadLocalRandom.current().nextInt(10, 100); int chunkCount = ThreadLocalRandom.current().nextInt(1, 10); InvokeCountContext invokeCountContext = new InvokeCountContext(); @@ -74,7 +77,8 @@ void fluxReaderProcessorShouldNotKeepCountWhenStepScoped() throws Exception { Job job = new JobBuilder("testJob", jobRepository) .start( new StepBuilder("testStep", jobRepository) - .chunk(chunkCount, new ResourcelessTransactionManager()) + .chunk(chunkCount) + .transactionManager(new ResourcelessTransactionManager()) .reader(itemStreamReader(testTasklet)) .processor(itemProcessor(testTasklet)) .writer($ -> { @@ -82,7 +86,7 @@ void fluxReaderProcessorShouldNotKeepCountWhenStepScoped() throws Exception { .build() ) .build(); - JobLauncher jobLauncher = context.getBean(JobLauncher.class); + JobOperator jobOperator = context.getBean(JobOperator.class); int repeatCount = ThreadLocalRandom.current().nextInt(1, 5); List jobExecutions = new ArrayList<>(); @@ -90,24 +94,21 @@ void fluxReaderProcessorShouldNotKeepCountWhenStepScoped() throws Exception { JobParameters jobParameters = new JobParametersBuilder() .addString(UUID.randomUUID().toString(), UUID.randomUUID().toString()) .toJobParameters(); - JobExecution jobExecution = jobLauncher.run(job, jobParameters); + JobExecution jobExecution = jobOperator.start(job, jobParameters); jobExecutions.add(jobExecution); } assertThat(jobExecutions).allSatisfy(it -> assertThat(it.getStatus()).isEqualTo(BatchStatus.COMPLETED)); - // read context should be invoked assertThat(invokeCountContext.readContextCallCount).isEqualTo(repeatCount); - // stream callback should be invoked assertThat(invokeCountContext.onOpenReadCallCount).isEqualTo(repeatCount); assertThat(invokeCountContext.onUpdateReadCallCount).isGreaterThanOrEqualTo(repeatCount); assertThat(invokeCountContext.onCloseReadCallCount).isEqualTo(repeatCount); - // 'count' field is isolated per job instances since it is step scoped. so count is 0 for all job instances assertThat(invokeCountContext.processCallCount).isEqualTo(repeatCount * itemCount); int writeCountPerIteration = (int)Math.ceil((double)itemCount / (double)chunkCount); } @RepeatedTest(TEST_REPEAT_COUNT) - void fluxReaderProcessorShouldKeepCountWhenNotStepScoped() throws Exception { + void singletonDelegateShouldReuseStateAcrossStepExecutions() throws Exception { int itemCount = ThreadLocalRandom.current().nextInt(10, 100); int chunkCount = ThreadLocalRandom.current().nextInt(1, 10); InvokeCountContext invokeCountContext = new InvokeCountContext(); @@ -122,7 +123,8 @@ void fluxReaderProcessorShouldKeepCountWhenNotStepScoped() throws Exception { Job job = new JobBuilder("testJob", jobRepository) .start( new StepBuilder("testStep", jobRepository) - .chunk(chunkCount, new ResourcelessTransactionManager()) + .chunk(chunkCount) + .transactionManager(new ResourcelessTransactionManager()) .reader(itemStreamReader(testTasklet)) .processor(itemProcessor(testTasklet)) .writer($ -> { @@ -130,7 +132,7 @@ void fluxReaderProcessorShouldKeepCountWhenNotStepScoped() throws Exception { .build() ) .build(); - JobLauncher jobLauncher = context.getBean(JobLauncher.class); + JobOperator jobOperator = context.getBean(JobOperator.class); int repeatCount = ThreadLocalRandom.current().nextInt(1, 5); List jobExecutions = new ArrayList<>(); @@ -138,23 +140,21 @@ void fluxReaderProcessorShouldKeepCountWhenNotStepScoped() throws Exception { JobParameters jobParameters = new JobParametersBuilder() .addString(UUID.randomUUID().toString(), UUID.randomUUID().toString()) .toJobParameters(); - JobExecution jobExecution = jobLauncher.run(job, jobParameters); + JobExecution jobExecution = jobOperator.start(job, jobParameters); jobExecutions.add(jobExecution); } assertThat(jobExecutions).allSatisfy(it -> assertThat(it.getStatus()).isEqualTo(BatchStatus.COMPLETED)); - // read context should be invoked assertThat(invokeCountContext.readContextCallCount).isEqualTo(repeatCount); - // stream callback should be invoked assertThat(invokeCountContext.onOpenReadCallCount).isEqualTo(repeatCount); assertThat(invokeCountContext.onUpdateReadCallCount).isGreaterThanOrEqualTo(repeatCount); assertThat(invokeCountContext.onCloseReadCallCount).isEqualTo(repeatCount); - // process, write should be invoked only once per iteration assertThat(invokeCountContext.processCallCount).isEqualTo(itemCount); int writeCountPerIteration = (int)Math.ceil((double)itemCount / (double)chunkCount); } - @EnableBatchProcessing( + @EnableBatchProcessing + @EnableJdbcJobRepository( dataSourceRef = "metadataDataSource", transactionManagerRef = "metadataTransactionManager" ) @@ -182,7 +182,8 @@ TestTasklet testTasklet( } } - @EnableBatchProcessing( + @EnableBatchProcessing + @EnableJdbcJobRepository( dataSourceRef = "metadataDataSource", transactionManagerRef = "metadataTransactionManager" ) @@ -221,13 +222,12 @@ public TestTasklet(InvokeCountContext invokeCountContext, int itemCount) { } @Override - public void onOpenRead(@NonNull ExecutionContext executionContext) { + public void onOpenRead(ExecutionContext executionContext) { this.invokeCountContext.onOpenReadCallCount++; } - @NonNull @Override - public Flux readFlux(@NonNull ExecutionContext executionContext) { + public Flux readFlux(ExecutionContext executionContext) { this.invokeCountContext.readContextCallCount++; return Flux.generate(sink -> { if (count < itemCount) { @@ -240,7 +240,7 @@ public Flux readFlux(@NonNull ExecutionContext executionContext) { } @Override - public void onUpdateRead(@NonNull ExecutionContext executionContext) { + public void onUpdateRead(ExecutionContext executionContext) { this.invokeCountContext.onUpdateReadCallCount++; } @@ -250,7 +250,7 @@ public void onCloseRead() { } @Override - public Integer process(@NonNull Integer item) { + public Integer process(Integer item) { this.invokeCountContext.processCallCount++; return item; } diff --git a/spring-batch-plus/src/integrationTest/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamFluxReaderProcessorWriterIT.java b/spring-batch-plus/src/integrationTest/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamFluxReaderProcessorWriterIntegrationTest.java similarity index 83% rename from spring-batch-plus/src/integrationTest/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamFluxReaderProcessorWriterIT.java rename to spring-batch-plus/src/integrationTest/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamFluxReaderProcessorWriterIntegrationTest.java index 8d1a7685..aea80cd3 100644 --- a/spring-batch-plus/src/integrationTest/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamFluxReaderProcessorWriterIT.java +++ b/spring-batch-plus/src/integrationTest/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamFluxReaderProcessorWriterIntegrationTest.java @@ -32,36 +32,39 @@ import org.junit.jupiter.api.RepeatedTest; import org.springframework.batch.core.BatchStatus; -import org.springframework.batch.core.Job; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.JobParameters; -import org.springframework.batch.core.JobParametersBuilder; import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing; +import org.springframework.batch.core.configuration.annotation.EnableJdbcJobRepository; import org.springframework.batch.core.configuration.annotation.StepScope; +import org.springframework.batch.core.job.Job; +import org.springframework.batch.core.job.JobExecution; import org.springframework.batch.core.job.builder.JobBuilder; -import org.springframework.batch.core.launch.JobLauncher; +import org.springframework.batch.core.job.parameters.JobParameters; +import org.springframework.batch.core.job.parameters.JobParametersBuilder; +import org.springframework.batch.core.launch.JobOperator; import org.springframework.batch.core.repository.JobRepository; import org.springframework.batch.core.step.builder.StepBuilder; -import org.springframework.batch.item.Chunk; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.batch.support.transaction.ResourcelessTransactionManager; +import org.springframework.batch.infrastructure.item.Chunk; +import org.springframework.batch.infrastructure.item.ExecutionContext; +import org.springframework.batch.infrastructure.support.transaction.ResourcelessTransactionManager; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.jdbc.datasource.DataSourceTransactionManager; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType; -import org.springframework.lang.NonNull; import org.springframework.transaction.TransactionManager; import reactor.core.publisher.Flux; +/** + * Covers how delegate scope controls state isolation across step executions. + */ @SuppressWarnings({"unchecked", "unused"}) -class ItemStreamFluxReaderProcessorWriterIT { +class ItemStreamFluxReaderProcessorWriterIntegrationTest { private static final int TEST_REPEAT_COUNT = 5; @RepeatedTest(TEST_REPEAT_COUNT) - void fluxReaderProcessorWriterShouldNotKeepCountWhenStepScoped() throws Exception { + void stepScopedDelegateShouldUseFreshStateForEachStepExecution() throws Exception { int itemCount = ThreadLocalRandom.current().nextInt(10, 100); int chunkCount = ThreadLocalRandom.current().nextInt(1, 10); InvokeCountContext invokeCountContext = new InvokeCountContext(); @@ -76,14 +79,15 @@ void fluxReaderProcessorWriterShouldNotKeepCountWhenStepScoped() throws Exceptio Job job = new JobBuilder("testJob", jobRepository) .start( new StepBuilder("testStep", jobRepository) - .chunk(chunkCount, new ResourcelessTransactionManager()) + .chunk(chunkCount) + .transactionManager(new ResourcelessTransactionManager()) .reader(itemStreamReader(testTasklet)) .processor(itemProcessor(testTasklet)) .writer(itemStreamWriter(testTasklet)) .build() ) .build(); - JobLauncher jobLauncher = context.getBean(JobLauncher.class); + JobOperator jobOperator = context.getBean(JobOperator.class); int repeatCount = ThreadLocalRandom.current().nextInt(1, 5); List jobExecutions = new ArrayList<>(); @@ -91,28 +95,25 @@ void fluxReaderProcessorWriterShouldNotKeepCountWhenStepScoped() throws Exceptio JobParameters jobParameters = new JobParametersBuilder() .addString(UUID.randomUUID().toString(), UUID.randomUUID().toString()) .toJobParameters(); - JobExecution jobExecution = jobLauncher.run(job, jobParameters); + JobExecution jobExecution = jobOperator.start(job, jobParameters); jobExecutions.add(jobExecution); } assertThat(jobExecutions).allSatisfy(it -> assertThat(it.getStatus()).isEqualTo(BatchStatus.COMPLETED)); - // read context should be invoked assertThat(invokeCountContext.readContextCallCount).isEqualTo(repeatCount); - // stream callback should be invoked assertThat(invokeCountContext.onOpenReadCallCount).isEqualTo(repeatCount); assertThat(invokeCountContext.onUpdateReadCallCount).isGreaterThanOrEqualTo(repeatCount); assertThat(invokeCountContext.onCloseReadCallCount).isEqualTo(repeatCount); assertThat(invokeCountContext.onOpenWriteCallCount).isEqualTo(repeatCount); assertThat(invokeCountContext.onUpdateWriteCallCount).isGreaterThanOrEqualTo(repeatCount); assertThat(invokeCountContext.onCloseWriteCallCount).isEqualTo(repeatCount); - // 'count' field is isolated per job instances since it is step scoped. so count is 0 for all job instances assertThat(invokeCountContext.processCallCount).isEqualTo(repeatCount * itemCount); int writeCountPerIteration = (int)Math.ceil((double)itemCount / (double)chunkCount); assertThat(invokeCountContext.writeCallCount).isEqualTo(repeatCount * writeCountPerIteration); } @RepeatedTest(TEST_REPEAT_COUNT) - void fluxReaderProcessorWriterShouldKeepCountWhenNotStepScoped() throws Exception { + void singletonDelegateShouldReuseStateAcrossStepExecutions() throws Exception { int itemCount = ThreadLocalRandom.current().nextInt(10, 100); int chunkCount = ThreadLocalRandom.current().nextInt(1, 10); InvokeCountContext invokeCountContext = new InvokeCountContext(); @@ -127,14 +128,15 @@ void fluxReaderProcessorWriterShouldKeepCountWhenNotStepScoped() throws Exceptio Job job = new JobBuilder("testJob", jobRepository) .start( new StepBuilder("testStep", jobRepository) - .chunk(chunkCount, new ResourcelessTransactionManager()) + .chunk(chunkCount) + .transactionManager(new ResourcelessTransactionManager()) .reader(itemStreamReader(testTasklet)) .processor(itemProcessor(testTasklet)) .writer(itemStreamWriter(testTasklet)) .build() ) .build(); - JobLauncher jobLauncher = context.getBean(JobLauncher.class); + JobOperator jobOperator = context.getBean(JobOperator.class); int repeatCount = ThreadLocalRandom.current().nextInt(1, 5); List jobExecutions = new ArrayList<>(); @@ -142,27 +144,25 @@ void fluxReaderProcessorWriterShouldKeepCountWhenNotStepScoped() throws Exceptio JobParameters jobParameters = new JobParametersBuilder() .addString(UUID.randomUUID().toString(), UUID.randomUUID().toString()) .toJobParameters(); - JobExecution jobExecution = jobLauncher.run(job, jobParameters); + JobExecution jobExecution = jobOperator.start(job, jobParameters); jobExecutions.add(jobExecution); } assertThat(jobExecutions).allSatisfy(it -> assertThat(it.getStatus()).isEqualTo(BatchStatus.COMPLETED)); - // read context should be invoked assertThat(invokeCountContext.readContextCallCount).isEqualTo(repeatCount); - // stream callback should be invoked assertThat(invokeCountContext.onOpenReadCallCount).isEqualTo(repeatCount); assertThat(invokeCountContext.onUpdateReadCallCount).isGreaterThanOrEqualTo(repeatCount); assertThat(invokeCountContext.onCloseReadCallCount).isEqualTo(repeatCount); assertThat(invokeCountContext.onOpenWriteCallCount).isEqualTo(repeatCount); assertThat(invokeCountContext.onUpdateWriteCallCount).isGreaterThanOrEqualTo(repeatCount); assertThat(invokeCountContext.onCloseWriteCallCount).isEqualTo(repeatCount); - // process, write should be invoked only once per iteration assertThat(invokeCountContext.processCallCount).isEqualTo(itemCount); int writeCountPerIteration = (int)Math.ceil((double)itemCount / (double)chunkCount); assertThat(invokeCountContext.writeCallCount).isEqualTo(writeCountPerIteration); } - @EnableBatchProcessing( + @EnableBatchProcessing + @EnableJdbcJobRepository( dataSourceRef = "metadataDataSource", transactionManagerRef = "metadataTransactionManager" ) @@ -190,7 +190,8 @@ TestTasklet testTasklet( } } - @EnableBatchProcessing( + @EnableBatchProcessing + @EnableJdbcJobRepository( dataSourceRef = "metadataDataSource", transactionManagerRef = "metadataTransactionManager" ) @@ -229,13 +230,12 @@ public TestTasklet(InvokeCountContext invokeCountContext, int itemCount) { } @Override - public void onOpenRead(@NonNull ExecutionContext executionContext) { + public void onOpenRead(ExecutionContext executionContext) { this.invokeCountContext.onOpenReadCallCount++; } - @NonNull @Override - public Flux readFlux(@NonNull ExecutionContext executionContext) { + public Flux readFlux(ExecutionContext executionContext) { this.invokeCountContext.readContextCallCount++; return Flux.generate(sink -> { if (count < itemCount) { @@ -248,7 +248,7 @@ public Flux readFlux(@NonNull ExecutionContext executionContext) { } @Override - public void onUpdateRead(@NonNull ExecutionContext executionContext) { + public void onUpdateRead(ExecutionContext executionContext) { this.invokeCountContext.onUpdateReadCallCount++; } @@ -258,23 +258,23 @@ public void onCloseRead() { } @Override - public Integer process(@NonNull Integer item) { + public Integer process(Integer item) { this.invokeCountContext.processCallCount++; return item; } @Override - public void onOpenWrite(@NonNull ExecutionContext executionContext) { + public void onOpenWrite(ExecutionContext executionContext) { this.invokeCountContext.onOpenWriteCallCount++; } @Override - public void write(@NonNull Chunk chunk) { + public void write(Chunk chunk) { this.invokeCountContext.writeCallCount++; } @Override - public void onUpdateWrite(@NonNull ExecutionContext executionContext) { + public void onUpdateWrite(ExecutionContext executionContext) { this.invokeCountContext.onUpdateWriteCallCount++; } diff --git a/spring-batch-plus/src/integrationTest/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamFluxReaderWriterIT.java b/spring-batch-plus/src/integrationTest/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamFluxReaderWriterIntegrationTest.java similarity index 82% rename from spring-batch-plus/src/integrationTest/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamFluxReaderWriterIT.java rename to spring-batch-plus/src/integrationTest/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamFluxReaderWriterIntegrationTest.java index ecd48047..07a9066a 100644 --- a/spring-batch-plus/src/integrationTest/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamFluxReaderWriterIT.java +++ b/spring-batch-plus/src/integrationTest/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamFluxReaderWriterIntegrationTest.java @@ -31,36 +31,39 @@ import org.junit.jupiter.api.RepeatedTest; import org.springframework.batch.core.BatchStatus; -import org.springframework.batch.core.Job; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.JobParameters; -import org.springframework.batch.core.JobParametersBuilder; import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing; +import org.springframework.batch.core.configuration.annotation.EnableJdbcJobRepository; import org.springframework.batch.core.configuration.annotation.StepScope; +import org.springframework.batch.core.job.Job; +import org.springframework.batch.core.job.JobExecution; import org.springframework.batch.core.job.builder.JobBuilder; -import org.springframework.batch.core.launch.JobLauncher; +import org.springframework.batch.core.job.parameters.JobParameters; +import org.springframework.batch.core.job.parameters.JobParametersBuilder; +import org.springframework.batch.core.launch.JobOperator; import org.springframework.batch.core.repository.JobRepository; import org.springframework.batch.core.step.builder.StepBuilder; -import org.springframework.batch.item.Chunk; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.batch.support.transaction.ResourcelessTransactionManager; +import org.springframework.batch.infrastructure.item.Chunk; +import org.springframework.batch.infrastructure.item.ExecutionContext; +import org.springframework.batch.infrastructure.support.transaction.ResourcelessTransactionManager; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.jdbc.datasource.DataSourceTransactionManager; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType; -import org.springframework.lang.NonNull; import org.springframework.transaction.TransactionManager; import reactor.core.publisher.Flux; +/** + * Covers how delegate scope controls state isolation across step executions. + */ @SuppressWarnings({"unchecked", "unused"}) -class ItemStreamFluxReaderWriterIT { +class ItemStreamFluxReaderWriterIntegrationTest { private static final int TEST_REPEAT_COUNT = 5; @RepeatedTest(TEST_REPEAT_COUNT) - void fluxReaderWriterShouldNotKeepCountWhenStepScoped() throws Exception { + void stepScopedDelegateShouldUseFreshStateForEachStepExecution() throws Exception { int itemCount = ThreadLocalRandom.current().nextInt(10, 100); int chunkCount = ThreadLocalRandom.current().nextInt(1, 10); InvokeCountContext invokeCountContext = new InvokeCountContext(); @@ -75,13 +78,14 @@ void fluxReaderWriterShouldNotKeepCountWhenStepScoped() throws Exception { Job job = new JobBuilder("testJob", jobRepository) .start( new StepBuilder("testStep", jobRepository) - .chunk(chunkCount, new ResourcelessTransactionManager()) + .chunk(chunkCount) + .transactionManager(new ResourcelessTransactionManager()) .reader(itemStreamReader(testTasklet)) .writer(itemStreamWriter(testTasklet)) .build() ) .build(); - JobLauncher jobLauncher = context.getBean(JobLauncher.class); + JobOperator jobOperator = context.getBean(JobOperator.class); int repeatCount = ThreadLocalRandom.current().nextInt(1, 5); List jobExecutions = new ArrayList<>(); @@ -89,27 +93,24 @@ void fluxReaderWriterShouldNotKeepCountWhenStepScoped() throws Exception { JobParameters jobParameters = new JobParametersBuilder() .addString(UUID.randomUUID().toString(), UUID.randomUUID().toString()) .toJobParameters(); - JobExecution jobExecution = jobLauncher.run(job, jobParameters); + JobExecution jobExecution = jobOperator.start(job, jobParameters); jobExecutions.add(jobExecution); } assertThat(jobExecutions).allSatisfy(it -> assertThat(it.getStatus()).isEqualTo(BatchStatus.COMPLETED)); - // read context should be invoked assertThat(invokeCountContext.readContextCallCount).isEqualTo(repeatCount); - // stream callback should be invoked assertThat(invokeCountContext.onOpenReadCallCount).isEqualTo(repeatCount); assertThat(invokeCountContext.onUpdateReadCallCount).isGreaterThanOrEqualTo(repeatCount); assertThat(invokeCountContext.onCloseReadCallCount).isEqualTo(repeatCount); assertThat(invokeCountContext.onOpenWriteCallCount).isEqualTo(repeatCount); assertThat(invokeCountContext.onUpdateWriteCallCount).isGreaterThanOrEqualTo(repeatCount); assertThat(invokeCountContext.onCloseWriteCallCount).isEqualTo(repeatCount); - // 'count' field is isolated per job instances since it is step scoped. so count is 0 for all job instances int writeCountPerIteration = (int)Math.ceil((double)itemCount / (double)chunkCount); assertThat(invokeCountContext.writeCallCount).isEqualTo(repeatCount * writeCountPerIteration); } @RepeatedTest(TEST_REPEAT_COUNT) - void fluxReaderWriterShouldKeepCountWhenNotStepScoped() throws Exception { + void singletonDelegateShouldReuseStateAcrossStepExecutions() throws Exception { int itemCount = ThreadLocalRandom.current().nextInt(10, 100); int chunkCount = ThreadLocalRandom.current().nextInt(1, 10); InvokeCountContext invokeCountContext = new InvokeCountContext(); @@ -124,13 +125,14 @@ void fluxReaderWriterShouldKeepCountWhenNotStepScoped() throws Exception { Job job = new JobBuilder("testJob", jobRepository) .start( new StepBuilder("testStep", jobRepository) - .chunk(chunkCount, new ResourcelessTransactionManager()) + .chunk(chunkCount) + .transactionManager(new ResourcelessTransactionManager()) .reader(itemStreamReader(testTasklet)) .writer(itemStreamWriter(testTasklet)) .build() ) .build(); - JobLauncher jobLauncher = context.getBean(JobLauncher.class); + JobOperator jobOperator = context.getBean(JobOperator.class); int repeatCount = ThreadLocalRandom.current().nextInt(1, 5); List jobExecutions = new ArrayList<>(); @@ -138,26 +140,24 @@ void fluxReaderWriterShouldKeepCountWhenNotStepScoped() throws Exception { JobParameters jobParameters = new JobParametersBuilder() .addString(UUID.randomUUID().toString(), UUID.randomUUID().toString()) .toJobParameters(); - JobExecution jobExecution = jobLauncher.run(job, jobParameters); + JobExecution jobExecution = jobOperator.start(job, jobParameters); jobExecutions.add(jobExecution); } assertThat(jobExecutions).allSatisfy(it -> assertThat(it.getStatus()).isEqualTo(BatchStatus.COMPLETED)); - // read context should be invoked assertThat(invokeCountContext.readContextCallCount).isEqualTo(repeatCount); - // stream callback should be invoked assertThat(invokeCountContext.onOpenReadCallCount).isEqualTo(repeatCount); assertThat(invokeCountContext.onUpdateReadCallCount).isGreaterThanOrEqualTo(repeatCount); assertThat(invokeCountContext.onCloseReadCallCount).isEqualTo(repeatCount); assertThat(invokeCountContext.onOpenWriteCallCount).isEqualTo(repeatCount); assertThat(invokeCountContext.onUpdateWriteCallCount).isGreaterThanOrEqualTo(repeatCount); assertThat(invokeCountContext.onCloseWriteCallCount).isEqualTo(repeatCount); - // process, write should be invoked only once per iteration int writeCountPerIteration = (int)Math.ceil((double)itemCount / (double)chunkCount); assertThat(invokeCountContext.writeCallCount).isEqualTo(writeCountPerIteration); } - @EnableBatchProcessing( + @EnableBatchProcessing + @EnableJdbcJobRepository( dataSourceRef = "metadataDataSource", transactionManagerRef = "metadataTransactionManager" ) @@ -185,7 +185,8 @@ TestTasklet testTasklet( } } - @EnableBatchProcessing( + @EnableBatchProcessing + @EnableJdbcJobRepository( dataSourceRef = "metadataDataSource", transactionManagerRef = "metadataTransactionManager" ) @@ -224,13 +225,12 @@ public TestTasklet(InvokeCountContext invokeCountContext, int itemCount) { } @Override - public void onOpenRead(@NonNull ExecutionContext executionContext) { + public void onOpenRead(ExecutionContext executionContext) { this.invokeCountContext.onOpenReadCallCount++; } - @NonNull @Override - public Flux readFlux(@NonNull ExecutionContext executionContext) { + public Flux readFlux(ExecutionContext executionContext) { this.invokeCountContext.readContextCallCount++; return Flux.generate(sink -> { if (count < itemCount) { @@ -243,7 +243,7 @@ public Flux readFlux(@NonNull ExecutionContext executionContext) { } @Override - public void onUpdateRead(@NonNull ExecutionContext executionContext) { + public void onUpdateRead(ExecutionContext executionContext) { this.invokeCountContext.onUpdateReadCallCount++; } @@ -253,17 +253,17 @@ public void onCloseRead() { } @Override - public void onOpenWrite(@NonNull ExecutionContext executionContext) { + public void onOpenWrite(ExecutionContext executionContext) { this.invokeCountContext.onOpenWriteCallCount++; } @Override - public void write(@NonNull Chunk chunk) { + public void write(Chunk chunk) { this.invokeCountContext.writeCallCount++; } @Override - public void onUpdateWrite(@NonNull ExecutionContext executionContext) { + public void onUpdateWrite(ExecutionContext executionContext) { this.invokeCountContext.onUpdateWriteCallCount++; } diff --git a/spring-batch-plus/src/integrationTest/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamIterableReaderProcessorIT.java b/spring-batch-plus/src/integrationTest/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamIterableReaderProcessorIntegrationTest.java similarity index 83% rename from spring-batch-plus/src/integrationTest/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamIterableReaderProcessorIT.java rename to spring-batch-plus/src/integrationTest/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamIterableReaderProcessorIntegrationTest.java index 23e07601..598f672e 100644 --- a/spring-batch-plus/src/integrationTest/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamIterableReaderProcessorIT.java +++ b/spring-batch-plus/src/integrationTest/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamIterableReaderProcessorIntegrationTest.java @@ -32,33 +32,36 @@ import org.junit.jupiter.api.RepeatedTest; import org.springframework.batch.core.BatchStatus; -import org.springframework.batch.core.Job; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.JobParameters; -import org.springframework.batch.core.JobParametersBuilder; import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing; +import org.springframework.batch.core.configuration.annotation.EnableJdbcJobRepository; import org.springframework.batch.core.configuration.annotation.StepScope; +import org.springframework.batch.core.job.Job; +import org.springframework.batch.core.job.JobExecution; import org.springframework.batch.core.job.builder.JobBuilder; -import org.springframework.batch.core.launch.JobLauncher; +import org.springframework.batch.core.job.parameters.JobParameters; +import org.springframework.batch.core.job.parameters.JobParametersBuilder; +import org.springframework.batch.core.launch.JobOperator; import org.springframework.batch.core.repository.JobRepository; import org.springframework.batch.core.step.builder.StepBuilder; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.batch.support.transaction.ResourcelessTransactionManager; +import org.springframework.batch.infrastructure.item.ExecutionContext; +import org.springframework.batch.infrastructure.support.transaction.ResourcelessTransactionManager; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.jdbc.datasource.DataSourceTransactionManager; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType; -import org.springframework.lang.NonNull; import org.springframework.transaction.TransactionManager; +/** + * Covers how delegate scope controls state isolation across step executions. + */ @SuppressWarnings({"unchecked", "unused"}) -class ItemStreamIterableReaderProcessorIT { +class ItemStreamIterableReaderProcessorIntegrationTest { private static final int TEST_REPEAT_COUNT = 5; @RepeatedTest(TEST_REPEAT_COUNT) - void iterableReaderProcessorShouldNotKeepCountWhenStepScoped() throws Exception { + void stepScopedDelegateShouldUseFreshStateForEachStepExecution() throws Exception { int itemCount = ThreadLocalRandom.current().nextInt(10, 100); int chunkCount = ThreadLocalRandom.current().nextInt(1, 10); InvokeCountContext invokeCountContext = new InvokeCountContext(); @@ -73,7 +76,8 @@ void iterableReaderProcessorShouldNotKeepCountWhenStepScoped() throws Exception Job job = new JobBuilder("testJob", jobRepository) .start( new StepBuilder("testStep", jobRepository) - .chunk(chunkCount, new ResourcelessTransactionManager()) + .chunk(chunkCount) + .transactionManager(new ResourcelessTransactionManager()) .reader(itemStreamReader(testTasklet)) .processor(itemProcessor(testTasklet)) .writer($ -> { @@ -81,7 +85,7 @@ void iterableReaderProcessorShouldNotKeepCountWhenStepScoped() throws Exception .build() ) .build(); - JobLauncher jobLauncher = context.getBean(JobLauncher.class); + JobOperator jobOperator = context.getBean(JobOperator.class); int repeatCount = ThreadLocalRandom.current().nextInt(1, 5); List jobExecutions = new ArrayList<>(); @@ -89,24 +93,21 @@ void iterableReaderProcessorShouldNotKeepCountWhenStepScoped() throws Exception JobParameters jobParameters = new JobParametersBuilder() .addString(UUID.randomUUID().toString(), UUID.randomUUID().toString()) .toJobParameters(); - JobExecution jobExecution = jobLauncher.run(job, jobParameters); + JobExecution jobExecution = jobOperator.start(job, jobParameters); jobExecutions.add(jobExecution); } assertThat(jobExecutions).allSatisfy(it -> assertThat(it.getStatus()).isEqualTo(BatchStatus.COMPLETED)); - // read context should be invoked assertThat(invokeCountContext.readContextCallCount).isEqualTo(repeatCount); - // stream callback should be invoked assertThat(invokeCountContext.onOpenReadCallCount).isEqualTo(repeatCount); assertThat(invokeCountContext.onUpdateReadCallCount).isGreaterThanOrEqualTo(repeatCount); assertThat(invokeCountContext.onCloseReadCallCount).isEqualTo(repeatCount); - // 'count' field is isolated per job instances since it is step scoped. so count is 0 for all job instances assertThat(invokeCountContext.processCallCount).isEqualTo(repeatCount * itemCount); int writeCountPerIteration = (int)Math.ceil((double)itemCount / (double)chunkCount); } @RepeatedTest(TEST_REPEAT_COUNT) - void iterableReaderProcessorShouldKeepCountWhenNotStepScoped() throws Exception { + void singletonDelegateShouldReuseStateAcrossStepExecutions() throws Exception { int itemCount = ThreadLocalRandom.current().nextInt(10, 100); int chunkCount = ThreadLocalRandom.current().nextInt(1, 10); InvokeCountContext invokeCountContext = new InvokeCountContext(); @@ -121,7 +122,8 @@ void iterableReaderProcessorShouldKeepCountWhenNotStepScoped() throws Exception Job job = new JobBuilder("testJob", jobRepository) .start( new StepBuilder("testStep", jobRepository) - .chunk(chunkCount, new ResourcelessTransactionManager()) + .chunk(chunkCount) + .transactionManager(new ResourcelessTransactionManager()) .reader(itemStreamReader(testTasklet)) .processor(itemProcessor(testTasklet)) .writer($ -> { @@ -129,7 +131,7 @@ void iterableReaderProcessorShouldKeepCountWhenNotStepScoped() throws Exception .build() ) .build(); - JobLauncher jobLauncher = context.getBean(JobLauncher.class); + JobOperator jobOperator = context.getBean(JobOperator.class); int repeatCount = ThreadLocalRandom.current().nextInt(1, 5); List jobExecutions = new ArrayList<>(); @@ -137,23 +139,21 @@ void iterableReaderProcessorShouldKeepCountWhenNotStepScoped() throws Exception JobParameters jobParameters = new JobParametersBuilder() .addString(UUID.randomUUID().toString(), UUID.randomUUID().toString()) .toJobParameters(); - JobExecution jobExecution = jobLauncher.run(job, jobParameters); + JobExecution jobExecution = jobOperator.start(job, jobParameters); jobExecutions.add(jobExecution); } assertThat(jobExecutions).allSatisfy(it -> assertThat(it.getStatus()).isEqualTo(BatchStatus.COMPLETED)); - // read context should be invoked assertThat(invokeCountContext.readContextCallCount).isEqualTo(repeatCount); - // stream callback should be invoked assertThat(invokeCountContext.onOpenReadCallCount).isEqualTo(repeatCount); assertThat(invokeCountContext.onUpdateReadCallCount).isGreaterThanOrEqualTo(repeatCount); assertThat(invokeCountContext.onCloseReadCallCount).isEqualTo(repeatCount); - // process, write should be invoked only once per iteration assertThat(invokeCountContext.processCallCount).isEqualTo(itemCount); int writeCountPerIteration = (int)Math.ceil((double)itemCount / (double)chunkCount); } - @EnableBatchProcessing( + @EnableBatchProcessing + @EnableJdbcJobRepository( dataSourceRef = "metadataDataSource", transactionManagerRef = "metadataTransactionManager" ) @@ -181,7 +181,8 @@ TestTasklet testTasklet( } } - @EnableBatchProcessing( + @EnableBatchProcessing + @EnableJdbcJobRepository( dataSourceRef = "metadataDataSource", transactionManagerRef = "metadataTransactionManager" ) @@ -220,13 +221,12 @@ public TestTasklet(InvokeCountContext invokeCountContext, int itemCount) { } @Override - public void onOpenRead(@NonNull ExecutionContext executionContext) { + public void onOpenRead(ExecutionContext executionContext) { this.invokeCountContext.onOpenReadCallCount++; } - @NonNull @Override - public Iterable readIterable(@NonNull ExecutionContext executionContext) { + public Iterable readIterable(ExecutionContext executionContext) { this.invokeCountContext.readContextCallCount++; return () -> new Iterator<>() { @Override @@ -246,7 +246,7 @@ public Integer next() { } @Override - public void onUpdateRead(@NonNull ExecutionContext executionContext) { + public void onUpdateRead(ExecutionContext executionContext) { this.invokeCountContext.onUpdateReadCallCount++; } @@ -256,7 +256,7 @@ public void onCloseRead() { } @Override - public Integer process(@NonNull Integer item) { + public Integer process(Integer item) { this.invokeCountContext.processCallCount++; return item; } diff --git a/spring-batch-plus/src/integrationTest/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamIterableReaderProcessorWriterIT.java b/spring-batch-plus/src/integrationTest/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamIterableReaderProcessorWriterIntegrationTest.java similarity index 83% rename from spring-batch-plus/src/integrationTest/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamIterableReaderProcessorWriterIT.java rename to spring-batch-plus/src/integrationTest/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamIterableReaderProcessorWriterIntegrationTest.java index 91d83484..d3e5f72c 100644 --- a/spring-batch-plus/src/integrationTest/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamIterableReaderProcessorWriterIT.java +++ b/spring-batch-plus/src/integrationTest/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamIterableReaderProcessorWriterIntegrationTest.java @@ -33,34 +33,37 @@ import org.junit.jupiter.api.RepeatedTest; import org.springframework.batch.core.BatchStatus; -import org.springframework.batch.core.Job; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.JobParameters; -import org.springframework.batch.core.JobParametersBuilder; import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing; +import org.springframework.batch.core.configuration.annotation.EnableJdbcJobRepository; import org.springframework.batch.core.configuration.annotation.StepScope; +import org.springframework.batch.core.job.Job; +import org.springframework.batch.core.job.JobExecution; import org.springframework.batch.core.job.builder.JobBuilder; -import org.springframework.batch.core.launch.JobLauncher; +import org.springframework.batch.core.job.parameters.JobParameters; +import org.springframework.batch.core.job.parameters.JobParametersBuilder; +import org.springframework.batch.core.launch.JobOperator; import org.springframework.batch.core.repository.JobRepository; import org.springframework.batch.core.step.builder.StepBuilder; -import org.springframework.batch.item.Chunk; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.batch.support.transaction.ResourcelessTransactionManager; +import org.springframework.batch.infrastructure.item.Chunk; +import org.springframework.batch.infrastructure.item.ExecutionContext; +import org.springframework.batch.infrastructure.support.transaction.ResourcelessTransactionManager; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.jdbc.datasource.DataSourceTransactionManager; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType; -import org.springframework.lang.NonNull; import org.springframework.transaction.TransactionManager; +/** + * Covers how delegate scope controls state isolation across step executions. + */ @SuppressWarnings({"unchecked", "unused"}) -class ItemStreamIterableReaderProcessorWriterIT { +class ItemStreamIterableReaderProcessorWriterIntegrationTest { private static final int TEST_REPEAT_COUNT = 5; @RepeatedTest(TEST_REPEAT_COUNT) - void iterableReaderProcessorWriterShouldNotKeepCountWhenStepScoped() throws Exception { + void stepScopedDelegateShouldUseFreshStateForEachStepExecution() throws Exception { int itemCount = ThreadLocalRandom.current().nextInt(10, 100); int chunkCount = ThreadLocalRandom.current().nextInt(1, 10); InvokeCountContext invokeCountContext = new InvokeCountContext(); @@ -75,14 +78,15 @@ void iterableReaderProcessorWriterShouldNotKeepCountWhenStepScoped() throws Exce Job job = new JobBuilder("testJob", jobRepository) .start( new StepBuilder("testStep", jobRepository) - .chunk(chunkCount, new ResourcelessTransactionManager()) + .chunk(chunkCount) + .transactionManager(new ResourcelessTransactionManager()) .reader(itemStreamReader(testTasklet)) .processor(itemProcessor(testTasklet)) .writer(itemStreamWriter(testTasklet)) .build() ) .build(); - JobLauncher jobLauncher = context.getBean(JobLauncher.class); + JobOperator jobOperator = context.getBean(JobOperator.class); int repeatCount = ThreadLocalRandom.current().nextInt(1, 5); List jobExecutions = new ArrayList<>(); @@ -90,28 +94,25 @@ void iterableReaderProcessorWriterShouldNotKeepCountWhenStepScoped() throws Exce JobParameters jobParameters = new JobParametersBuilder() .addString(UUID.randomUUID().toString(), UUID.randomUUID().toString()) .toJobParameters(); - JobExecution jobExecution = jobLauncher.run(job, jobParameters); + JobExecution jobExecution = jobOperator.start(job, jobParameters); jobExecutions.add(jobExecution); } assertThat(jobExecutions).allSatisfy(it -> assertThat(it.getStatus()).isEqualTo(BatchStatus.COMPLETED)); - // read context should be invoked assertThat(invokeCountContext.readContextCallCount).isEqualTo(repeatCount); - // stream callback should be invoked assertThat(invokeCountContext.onOpenReadCallCount).isEqualTo(repeatCount); assertThat(invokeCountContext.onUpdateReadCallCount).isGreaterThanOrEqualTo(repeatCount); assertThat(invokeCountContext.onCloseReadCallCount).isEqualTo(repeatCount); assertThat(invokeCountContext.onOpenWriteCallCount).isEqualTo(repeatCount); assertThat(invokeCountContext.onUpdateWriteCallCount).isGreaterThanOrEqualTo(repeatCount); assertThat(invokeCountContext.onCloseWriteCallCount).isEqualTo(repeatCount); - // 'count' field is isolated per job instances since it is step scoped. so count is 0 for all job instances assertThat(invokeCountContext.processCallCount).isEqualTo(repeatCount * itemCount); int writeCountPerIteration = (int)Math.ceil((double)itemCount / (double)chunkCount); assertThat(invokeCountContext.writeCallCount).isEqualTo(repeatCount * writeCountPerIteration); } @RepeatedTest(TEST_REPEAT_COUNT) - void iterableReaderProcessorWriterShouldKeepCountWhenNotStepScoped() throws Exception { + void singletonDelegateShouldReuseStateAcrossStepExecutions() throws Exception { int itemCount = ThreadLocalRandom.current().nextInt(10, 100); int chunkCount = ThreadLocalRandom.current().nextInt(1, 10); InvokeCountContext invokeCountContext = new InvokeCountContext(); @@ -126,14 +127,15 @@ void iterableReaderProcessorWriterShouldKeepCountWhenNotStepScoped() throws Exce Job job = new JobBuilder("testJob", jobRepository) .start( new StepBuilder("testStep", jobRepository) - .chunk(chunkCount, new ResourcelessTransactionManager()) + .chunk(chunkCount) + .transactionManager(new ResourcelessTransactionManager()) .reader(itemStreamReader(testTasklet)) .processor(itemProcessor(testTasklet)) .writer(itemStreamWriter(testTasklet)) .build() ) .build(); - JobLauncher jobLauncher = context.getBean(JobLauncher.class); + JobOperator jobOperator = context.getBean(JobOperator.class); int repeatCount = ThreadLocalRandom.current().nextInt(1, 5); List jobExecutions = new ArrayList<>(); @@ -141,27 +143,25 @@ void iterableReaderProcessorWriterShouldKeepCountWhenNotStepScoped() throws Exce JobParameters jobParameters = new JobParametersBuilder() .addString(UUID.randomUUID().toString(), UUID.randomUUID().toString()) .toJobParameters(); - JobExecution jobExecution = jobLauncher.run(job, jobParameters); + JobExecution jobExecution = jobOperator.start(job, jobParameters); jobExecutions.add(jobExecution); } assertThat(jobExecutions).allSatisfy(it -> assertThat(it.getStatus()).isEqualTo(BatchStatus.COMPLETED)); - // read context should be invoked assertThat(invokeCountContext.readContextCallCount).isEqualTo(repeatCount); - // stream callback should be invoked assertThat(invokeCountContext.onOpenReadCallCount).isEqualTo(repeatCount); assertThat(invokeCountContext.onUpdateReadCallCount).isGreaterThanOrEqualTo(repeatCount); assertThat(invokeCountContext.onCloseReadCallCount).isEqualTo(repeatCount); assertThat(invokeCountContext.onOpenWriteCallCount).isEqualTo(repeatCount); assertThat(invokeCountContext.onUpdateWriteCallCount).isGreaterThanOrEqualTo(repeatCount); assertThat(invokeCountContext.onCloseWriteCallCount).isEqualTo(repeatCount); - // process, write should be invoked only once per iteration assertThat(invokeCountContext.processCallCount).isEqualTo(itemCount); int writeCountPerIteration = (int)Math.ceil((double)itemCount / (double)chunkCount); assertThat(invokeCountContext.writeCallCount).isEqualTo(writeCountPerIteration); } - @EnableBatchProcessing( + @EnableBatchProcessing + @EnableJdbcJobRepository( dataSourceRef = "metadataDataSource", transactionManagerRef = "metadataTransactionManager" ) @@ -189,7 +189,8 @@ TestTasklet testTasklet( } } - @EnableBatchProcessing( + @EnableBatchProcessing + @EnableJdbcJobRepository( dataSourceRef = "metadataDataSource", transactionManagerRef = "metadataTransactionManager" ) @@ -228,13 +229,12 @@ public TestTasklet(InvokeCountContext invokeCountContext, int itemCount) { } @Override - public void onOpenRead(@NonNull ExecutionContext executionContext) { + public void onOpenRead(ExecutionContext executionContext) { this.invokeCountContext.onOpenReadCallCount++; } - @NonNull @Override - public Iterable readIterable(@NonNull ExecutionContext executionContext) { + public Iterable readIterable(ExecutionContext executionContext) { this.invokeCountContext.readContextCallCount++; return () -> new Iterator<>() { @Override @@ -254,7 +254,7 @@ public Integer next() { } @Override - public void onUpdateRead(@NonNull ExecutionContext executionContext) { + public void onUpdateRead(ExecutionContext executionContext) { this.invokeCountContext.onUpdateReadCallCount++; } @@ -264,23 +264,23 @@ public void onCloseRead() { } @Override - public Integer process(@NonNull Integer item) { + public Integer process(Integer item) { this.invokeCountContext.processCallCount++; return item; } @Override - public void onOpenWrite(@NonNull ExecutionContext executionContext) { + public void onOpenWrite(ExecutionContext executionContext) { this.invokeCountContext.onOpenWriteCallCount++; } @Override - public void write(@NonNull Chunk chunk) { + public void write(Chunk chunk) { this.invokeCountContext.writeCallCount++; } @Override - public void onUpdateWrite(@NonNull ExecutionContext executionContext) { + public void onUpdateWrite(ExecutionContext executionContext) { this.invokeCountContext.onUpdateWriteCallCount++; } diff --git a/spring-batch-plus/src/integrationTest/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamIterableReaderWriterIT.java b/spring-batch-plus/src/integrationTest/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamIterableReaderWriterIntegrationTest.java similarity index 82% rename from spring-batch-plus/src/integrationTest/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamIterableReaderWriterIT.java rename to spring-batch-plus/src/integrationTest/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamIterableReaderWriterIntegrationTest.java index fd5f062d..3e3fe71c 100644 --- a/spring-batch-plus/src/integrationTest/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamIterableReaderWriterIT.java +++ b/spring-batch-plus/src/integrationTest/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamIterableReaderWriterIntegrationTest.java @@ -32,34 +32,37 @@ import org.junit.jupiter.api.RepeatedTest; import org.springframework.batch.core.BatchStatus; -import org.springframework.batch.core.Job; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.JobParameters; -import org.springframework.batch.core.JobParametersBuilder; import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing; +import org.springframework.batch.core.configuration.annotation.EnableJdbcJobRepository; import org.springframework.batch.core.configuration.annotation.StepScope; +import org.springframework.batch.core.job.Job; +import org.springframework.batch.core.job.JobExecution; import org.springframework.batch.core.job.builder.JobBuilder; -import org.springframework.batch.core.launch.JobLauncher; +import org.springframework.batch.core.job.parameters.JobParameters; +import org.springframework.batch.core.job.parameters.JobParametersBuilder; +import org.springframework.batch.core.launch.JobOperator; import org.springframework.batch.core.repository.JobRepository; import org.springframework.batch.core.step.builder.StepBuilder; -import org.springframework.batch.item.Chunk; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.batch.support.transaction.ResourcelessTransactionManager; +import org.springframework.batch.infrastructure.item.Chunk; +import org.springframework.batch.infrastructure.item.ExecutionContext; +import org.springframework.batch.infrastructure.support.transaction.ResourcelessTransactionManager; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.jdbc.datasource.DataSourceTransactionManager; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType; -import org.springframework.lang.NonNull; import org.springframework.transaction.TransactionManager; +/** + * Covers how delegate scope controls state isolation across step executions. + */ @SuppressWarnings({"unchecked", "unused"}) -class ItemStreamIterableReaderWriterIT { +class ItemStreamIterableReaderWriterIntegrationTest { private static final int TEST_REPEAT_COUNT = 5; @RepeatedTest(TEST_REPEAT_COUNT) - void iterableReaderWriterShouldNotKeepCountWhenStepScoped() throws Exception { + void stepScopedDelegateShouldUseFreshStateForEachStepExecution() throws Exception { int itemCount = ThreadLocalRandom.current().nextInt(10, 100); int chunkCount = ThreadLocalRandom.current().nextInt(1, 10); InvokeCountContext invokeCountContext = new InvokeCountContext(); @@ -74,13 +77,14 @@ void iterableReaderWriterShouldNotKeepCountWhenStepScoped() throws Exception { Job job = new JobBuilder("testJob", jobRepository) .start( new StepBuilder("testStep", jobRepository) - .chunk(chunkCount, new ResourcelessTransactionManager()) + .chunk(chunkCount) + .transactionManager(new ResourcelessTransactionManager()) .reader(itemStreamReader(testTasklet)) .writer(itemStreamWriter(testTasklet)) .build() ) .build(); - JobLauncher jobLauncher = context.getBean(JobLauncher.class); + JobOperator jobOperator = context.getBean(JobOperator.class); int repeatCount = ThreadLocalRandom.current().nextInt(1, 5); List jobExecutions = new ArrayList<>(); @@ -88,27 +92,24 @@ void iterableReaderWriterShouldNotKeepCountWhenStepScoped() throws Exception { JobParameters jobParameters = new JobParametersBuilder() .addString(UUID.randomUUID().toString(), UUID.randomUUID().toString()) .toJobParameters(); - JobExecution jobExecution = jobLauncher.run(job, jobParameters); + JobExecution jobExecution = jobOperator.start(job, jobParameters); jobExecutions.add(jobExecution); } assertThat(jobExecutions).allSatisfy(it -> assertThat(it.getStatus()).isEqualTo(BatchStatus.COMPLETED)); - // read context should be invoked assertThat(invokeCountContext.readContextCallCount).isEqualTo(repeatCount); - // stream callback should be invoked assertThat(invokeCountContext.onOpenReadCallCount).isEqualTo(repeatCount); assertThat(invokeCountContext.onUpdateReadCallCount).isGreaterThanOrEqualTo(repeatCount); assertThat(invokeCountContext.onCloseReadCallCount).isEqualTo(repeatCount); assertThat(invokeCountContext.onOpenWriteCallCount).isEqualTo(repeatCount); assertThat(invokeCountContext.onUpdateWriteCallCount).isGreaterThanOrEqualTo(repeatCount); assertThat(invokeCountContext.onCloseWriteCallCount).isEqualTo(repeatCount); - // 'count' field is isolated per job instances since it is step scoped. so count is 0 for all job instances int writeCountPerIteration = (int)Math.ceil((double)itemCount / (double)chunkCount); assertThat(invokeCountContext.writeCallCount).isEqualTo(repeatCount * writeCountPerIteration); } @RepeatedTest(TEST_REPEAT_COUNT) - void iterableReaderWriterShouldKeepCountWhenNotStepScoped() throws Exception { + void singletonDelegateShouldReuseStateAcrossStepExecutions() throws Exception { int itemCount = ThreadLocalRandom.current().nextInt(10, 100); int chunkCount = ThreadLocalRandom.current().nextInt(1, 10); InvokeCountContext invokeCountContext = new InvokeCountContext(); @@ -123,13 +124,14 @@ void iterableReaderWriterShouldKeepCountWhenNotStepScoped() throws Exception { Job job = new JobBuilder("testJob", jobRepository) .start( new StepBuilder("testStep", jobRepository) - .chunk(chunkCount, new ResourcelessTransactionManager()) + .chunk(chunkCount) + .transactionManager(new ResourcelessTransactionManager()) .reader(itemStreamReader(testTasklet)) .writer(itemStreamWriter(testTasklet)) .build() ) .build(); - JobLauncher jobLauncher = context.getBean(JobLauncher.class); + JobOperator jobOperator = context.getBean(JobOperator.class); int repeatCount = ThreadLocalRandom.current().nextInt(1, 5); List jobExecutions = new ArrayList<>(); @@ -137,26 +139,24 @@ void iterableReaderWriterShouldKeepCountWhenNotStepScoped() throws Exception { JobParameters jobParameters = new JobParametersBuilder() .addString(UUID.randomUUID().toString(), UUID.randomUUID().toString()) .toJobParameters(); - JobExecution jobExecution = jobLauncher.run(job, jobParameters); + JobExecution jobExecution = jobOperator.start(job, jobParameters); jobExecutions.add(jobExecution); } assertThat(jobExecutions).allSatisfy(it -> assertThat(it.getStatus()).isEqualTo(BatchStatus.COMPLETED)); - // read context should be invoked assertThat(invokeCountContext.readContextCallCount).isEqualTo(repeatCount); - // stream callback should be invoked assertThat(invokeCountContext.onOpenReadCallCount).isEqualTo(repeatCount); assertThat(invokeCountContext.onUpdateReadCallCount).isGreaterThanOrEqualTo(repeatCount); assertThat(invokeCountContext.onCloseReadCallCount).isEqualTo(repeatCount); assertThat(invokeCountContext.onOpenWriteCallCount).isEqualTo(repeatCount); assertThat(invokeCountContext.onUpdateWriteCallCount).isGreaterThanOrEqualTo(repeatCount); assertThat(invokeCountContext.onCloseWriteCallCount).isEqualTo(repeatCount); - // process, write should be invoked only once per iteration int writeCountPerIteration = (int)Math.ceil((double)itemCount / (double)chunkCount); assertThat(invokeCountContext.writeCallCount).isEqualTo(writeCountPerIteration); } - @EnableBatchProcessing( + @EnableBatchProcessing + @EnableJdbcJobRepository( dataSourceRef = "metadataDataSource", transactionManagerRef = "metadataTransactionManager" ) @@ -184,7 +184,8 @@ TestTasklet testTasklet( } } - @EnableBatchProcessing( + @EnableBatchProcessing + @EnableJdbcJobRepository( dataSourceRef = "metadataDataSource", transactionManagerRef = "metadataTransactionManager" ) @@ -223,13 +224,12 @@ public TestTasklet(InvokeCountContext invokeCountContext, int itemCount) { } @Override - public void onOpenRead(@NonNull ExecutionContext executionContext) { + public void onOpenRead(ExecutionContext executionContext) { this.invokeCountContext.onOpenReadCallCount++; } - @NonNull @Override - public Iterable readIterable(@NonNull ExecutionContext executionContext) { + public Iterable readIterable(ExecutionContext executionContext) { this.invokeCountContext.readContextCallCount++; return () -> new Iterator<>() { @Override @@ -249,7 +249,7 @@ public Integer next() { } @Override - public void onUpdateRead(@NonNull ExecutionContext executionContext) { + public void onUpdateRead(ExecutionContext executionContext) { this.invokeCountContext.onUpdateReadCallCount++; } @@ -259,17 +259,17 @@ public void onCloseRead() { } @Override - public void onOpenWrite(@NonNull ExecutionContext executionContext) { + public void onOpenWrite(ExecutionContext executionContext) { this.invokeCountContext.onOpenWriteCallCount++; } @Override - public void write(@NonNull Chunk chunk) { + public void write(Chunk chunk) { this.invokeCountContext.writeCallCount++; } @Override - public void onUpdateWrite(@NonNull ExecutionContext executionContext) { + public void onUpdateWrite(ExecutionContext executionContext) { this.invokeCountContext.onUpdateWriteCallCount++; } diff --git a/spring-batch-plus/src/integrationTest/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamIteratorReaderProcessorIT.java b/spring-batch-plus/src/integrationTest/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamIteratorReaderProcessorIntegrationTest.java similarity index 82% rename from spring-batch-plus/src/integrationTest/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamIteratorReaderProcessorIT.java rename to spring-batch-plus/src/integrationTest/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamIteratorReaderProcessorIntegrationTest.java index 8193f12e..bc3bcef2 100644 --- a/spring-batch-plus/src/integrationTest/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamIteratorReaderProcessorIT.java +++ b/spring-batch-plus/src/integrationTest/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamIteratorReaderProcessorIntegrationTest.java @@ -32,33 +32,36 @@ import org.junit.jupiter.api.RepeatedTest; import org.springframework.batch.core.BatchStatus; -import org.springframework.batch.core.Job; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.JobParameters; -import org.springframework.batch.core.JobParametersBuilder; import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing; +import org.springframework.batch.core.configuration.annotation.EnableJdbcJobRepository; import org.springframework.batch.core.configuration.annotation.StepScope; +import org.springframework.batch.core.job.Job; +import org.springframework.batch.core.job.JobExecution; import org.springframework.batch.core.job.builder.JobBuilder; -import org.springframework.batch.core.launch.JobLauncher; +import org.springframework.batch.core.job.parameters.JobParameters; +import org.springframework.batch.core.job.parameters.JobParametersBuilder; +import org.springframework.batch.core.launch.JobOperator; import org.springframework.batch.core.repository.JobRepository; import org.springframework.batch.core.step.builder.StepBuilder; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.batch.support.transaction.ResourcelessTransactionManager; +import org.springframework.batch.infrastructure.item.ExecutionContext; +import org.springframework.batch.infrastructure.support.transaction.ResourcelessTransactionManager; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.jdbc.datasource.DataSourceTransactionManager; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType; -import org.springframework.lang.NonNull; import org.springframework.transaction.TransactionManager; +/** + * Covers how delegate scope controls state isolation across step executions. + */ @SuppressWarnings({"unchecked", "unused"}) -class ItemStreamIteratorReaderProcessorIT { +class ItemStreamIteratorReaderProcessorIntegrationTest { private static final int TEST_REPEAT_COUNT = 5; @RepeatedTest(TEST_REPEAT_COUNT) - void iteratorReaderProcessorShouldNotKeepCountWhenStepScoped() throws Exception { + void stepScopedDelegateShouldUseFreshStateForEachStepExecution() throws Exception { int itemCount = ThreadLocalRandom.current().nextInt(10, 100); int chunkCount = ThreadLocalRandom.current().nextInt(1, 10); InvokeCountContext invokeCountContext = new InvokeCountContext(); @@ -73,7 +76,8 @@ void iteratorReaderProcessorShouldNotKeepCountWhenStepScoped() throws Exception Job job = new JobBuilder("testJob", jobRepository) .start( new StepBuilder("testStep", jobRepository) - .chunk(chunkCount, new ResourcelessTransactionManager()) + .chunk(chunkCount) + .transactionManager(new ResourcelessTransactionManager()) .reader(itemStreamReader(testTasklet)) .processor(itemProcessor(testTasklet)) .writer($ -> { @@ -81,7 +85,7 @@ void iteratorReaderProcessorShouldNotKeepCountWhenStepScoped() throws Exception .build() ) .build(); - JobLauncher jobLauncher = context.getBean(JobLauncher.class); + JobOperator jobOperator = context.getBean(JobOperator.class); int repeatCount = ThreadLocalRandom.current().nextInt(1, 5); List jobExecutions = new ArrayList<>(); @@ -89,23 +93,20 @@ void iteratorReaderProcessorShouldNotKeepCountWhenStepScoped() throws Exception JobParameters jobParameters = new JobParametersBuilder() .addString(UUID.randomUUID().toString(), UUID.randomUUID().toString()) .toJobParameters(); - JobExecution jobExecution = jobLauncher.run(job, jobParameters); + JobExecution jobExecution = jobOperator.start(job, jobParameters); jobExecutions.add(jobExecution); } assertThat(jobExecutions).allSatisfy(it -> assertThat(it.getStatus()).isEqualTo(BatchStatus.COMPLETED)); - // read context should be invoked assertThat(invokeCountContext.readContextCallCount).isEqualTo(repeatCount); - // stream callback should be invoked assertThat(invokeCountContext.onOpenReadCallCount).isEqualTo(repeatCount); assertThat(invokeCountContext.onUpdateReadCallCount).isGreaterThanOrEqualTo(repeatCount); assertThat(invokeCountContext.onCloseReadCallCount).isEqualTo(repeatCount); - // 'count' field is isolated per job instances since it is step scoped. so count is 0 for all job instances assertThat(invokeCountContext.processCallCount).isEqualTo(repeatCount * itemCount); } @RepeatedTest(TEST_REPEAT_COUNT) - void iteratorReaderProcessorShouldKeepCountWhenNotStepScoped() throws Exception { + void singletonDelegateShouldReuseStateAcrossStepExecutions() throws Exception { int itemCount = ThreadLocalRandom.current().nextInt(10, 100); int chunkCount = ThreadLocalRandom.current().nextInt(1, 10); InvokeCountContext invokeCountContext = new InvokeCountContext(); @@ -120,7 +121,8 @@ void iteratorReaderProcessorShouldKeepCountWhenNotStepScoped() throws Exception Job job = new JobBuilder("testJob", jobRepository) .start( new StepBuilder("testStep", jobRepository) - .chunk(chunkCount, new ResourcelessTransactionManager()) + .chunk(chunkCount) + .transactionManager(new ResourcelessTransactionManager()) .reader(itemStreamReader(testTasklet)) .processor(itemProcessor(testTasklet)) .writer($ -> { @@ -128,7 +130,7 @@ void iteratorReaderProcessorShouldKeepCountWhenNotStepScoped() throws Exception .build() ) .build(); - JobLauncher jobLauncher = context.getBean(JobLauncher.class); + JobOperator jobOperator = context.getBean(JobOperator.class); int repeatCount = ThreadLocalRandom.current().nextInt(1, 5); List jobExecutions = new ArrayList<>(); @@ -136,22 +138,20 @@ void iteratorReaderProcessorShouldKeepCountWhenNotStepScoped() throws Exception JobParameters jobParameters = new JobParametersBuilder() .addString(UUID.randomUUID().toString(), UUID.randomUUID().toString()) .toJobParameters(); - JobExecution jobExecution = jobLauncher.run(job, jobParameters); + JobExecution jobExecution = jobOperator.start(job, jobParameters); jobExecutions.add(jobExecution); } assertThat(jobExecutions).allSatisfy(it -> assertThat(it.getStatus()).isEqualTo(BatchStatus.COMPLETED)); - // read context should be invoked assertThat(invokeCountContext.readContextCallCount).isEqualTo(repeatCount); - // stream callback should be invoked assertThat(invokeCountContext.onOpenReadCallCount).isEqualTo(repeatCount); assertThat(invokeCountContext.onUpdateReadCallCount).isGreaterThanOrEqualTo(repeatCount); assertThat(invokeCountContext.onCloseReadCallCount).isEqualTo(repeatCount); - // process, write should be invoked only once per iteration assertThat(invokeCountContext.processCallCount).isEqualTo(itemCount); } - @EnableBatchProcessing( + @EnableBatchProcessing + @EnableJdbcJobRepository( dataSourceRef = "metadataDataSource", transactionManagerRef = "metadataTransactionManager" ) @@ -179,7 +179,8 @@ TestTasklet testTasklet( } } - @EnableBatchProcessing( + @EnableBatchProcessing + @EnableJdbcJobRepository( dataSourceRef = "metadataDataSource", transactionManagerRef = "metadataTransactionManager" ) @@ -218,13 +219,12 @@ public TestTasklet(InvokeCountContext invokeCountContext, int itemCount) { } @Override - public void onOpenRead(@NonNull ExecutionContext executionContext) { + public void onOpenRead(ExecutionContext executionContext) { this.invokeCountContext.onOpenReadCallCount++; } - @NonNull @Override - public Iterator readIterator(@NonNull ExecutionContext executionContext) { + public Iterator readIterator(ExecutionContext executionContext) { this.invokeCountContext.readContextCallCount++; return new Iterator<>() { @Override @@ -244,7 +244,7 @@ public Integer next() { } @Override - public void onUpdateRead(@NonNull ExecutionContext executionContext) { + public void onUpdateRead(ExecutionContext executionContext) { this.invokeCountContext.onUpdateReadCallCount++; } @@ -254,7 +254,7 @@ public void onCloseRead() { } @Override - public Integer process(@NonNull Integer item) { + public Integer process(Integer item) { this.invokeCountContext.processCallCount++; return item; } diff --git a/spring-batch-plus/src/integrationTest/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamIteratorReaderProcessorWriterIT.java b/spring-batch-plus/src/integrationTest/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamIteratorReaderProcessorWriterIntegrationTest.java similarity index 82% rename from spring-batch-plus/src/integrationTest/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamIteratorReaderProcessorWriterIT.java rename to spring-batch-plus/src/integrationTest/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamIteratorReaderProcessorWriterIntegrationTest.java index 34329980..b9573e5a 100644 --- a/spring-batch-plus/src/integrationTest/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamIteratorReaderProcessorWriterIT.java +++ b/spring-batch-plus/src/integrationTest/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamIteratorReaderProcessorWriterIntegrationTest.java @@ -33,34 +33,37 @@ import org.junit.jupiter.api.RepeatedTest; import org.springframework.batch.core.BatchStatus; -import org.springframework.batch.core.Job; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.JobParameters; -import org.springframework.batch.core.JobParametersBuilder; import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing; +import org.springframework.batch.core.configuration.annotation.EnableJdbcJobRepository; import org.springframework.batch.core.configuration.annotation.StepScope; +import org.springframework.batch.core.job.Job; +import org.springframework.batch.core.job.JobExecution; import org.springframework.batch.core.job.builder.JobBuilder; -import org.springframework.batch.core.launch.JobLauncher; +import org.springframework.batch.core.job.parameters.JobParameters; +import org.springframework.batch.core.job.parameters.JobParametersBuilder; +import org.springframework.batch.core.launch.JobOperator; import org.springframework.batch.core.repository.JobRepository; import org.springframework.batch.core.step.builder.StepBuilder; -import org.springframework.batch.item.Chunk; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.batch.support.transaction.ResourcelessTransactionManager; +import org.springframework.batch.infrastructure.item.Chunk; +import org.springframework.batch.infrastructure.item.ExecutionContext; +import org.springframework.batch.infrastructure.support.transaction.ResourcelessTransactionManager; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.jdbc.datasource.DataSourceTransactionManager; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType; -import org.springframework.lang.NonNull; import org.springframework.transaction.TransactionManager; +/** + * Covers how delegate scope controls state isolation across step executions. + */ @SuppressWarnings({"unchecked", "unused"}) -class ItemStreamIteratorReaderProcessorWriterIT { +class ItemStreamIteratorReaderProcessorWriterIntegrationTest { private static final int TEST_REPEAT_COUNT = 5; @RepeatedTest(TEST_REPEAT_COUNT) - void iteratorReaderProcessorWriterShouldNotKeepCountWhenStepScoped() throws Exception { + void stepScopedDelegateShouldUseFreshStateForEachStepExecution() throws Exception { int itemCount = ThreadLocalRandom.current().nextInt(10, 100); int chunkCount = ThreadLocalRandom.current().nextInt(1, 10); InvokeCountContext invokeCountContext = new InvokeCountContext(); @@ -75,14 +78,15 @@ void iteratorReaderProcessorWriterShouldNotKeepCountWhenStepScoped() throws Exce Job job = new JobBuilder("testJob", jobRepository) .start( new StepBuilder("testStep", jobRepository) - .chunk(chunkCount, new ResourcelessTransactionManager()) + .chunk(chunkCount) + .transactionManager(new ResourcelessTransactionManager()) .reader(itemStreamReader(testTasklet)) .processor(itemProcessor(testTasklet)) .writer(itemStreamWriter(testTasklet)) .build() ) .build(); - JobLauncher jobLauncher = context.getBean(JobLauncher.class); + JobOperator jobOperator = context.getBean(JobOperator.class); int repeatCount = ThreadLocalRandom.current().nextInt(1, 5); List jobExecutions = new ArrayList<>(); @@ -90,28 +94,25 @@ void iteratorReaderProcessorWriterShouldNotKeepCountWhenStepScoped() throws Exce JobParameters jobParameters = new JobParametersBuilder() .addString(UUID.randomUUID().toString(), UUID.randomUUID().toString()) .toJobParameters(); - JobExecution jobExecution = jobLauncher.run(job, jobParameters); + JobExecution jobExecution = jobOperator.start(job, jobParameters); jobExecutions.add(jobExecution); } assertThat(jobExecutions).allSatisfy(it -> assertThat(it.getStatus()).isEqualTo(BatchStatus.COMPLETED)); - // read context should be invoked assertThat(invokeCountContext.readContextCallCount).isEqualTo(repeatCount); - // stream callback should be invoked assertThat(invokeCountContext.onOpenReadCallCount).isEqualTo(repeatCount); assertThat(invokeCountContext.onUpdateReadCallCount).isGreaterThanOrEqualTo(repeatCount); assertThat(invokeCountContext.onCloseReadCallCount).isEqualTo(repeatCount); assertThat(invokeCountContext.onOpenWriteCallCount).isEqualTo(repeatCount); assertThat(invokeCountContext.onUpdateWriteCallCount).isGreaterThanOrEqualTo(repeatCount); assertThat(invokeCountContext.onCloseWriteCallCount).isEqualTo(repeatCount); - // 'count' field is isolated per job instances since it is step scoped. so count is 0 for all job instances assertThat(invokeCountContext.processCallCount).isEqualTo(repeatCount * itemCount); int writeCountPerIteration = (int)Math.ceil((double)itemCount / (double)chunkCount); assertThat(invokeCountContext.writeCallCount).isEqualTo(repeatCount * writeCountPerIteration); } @RepeatedTest(TEST_REPEAT_COUNT) - void iteratorReaderProcessorWriterShouldKeepCountWhenNotStepScoped() throws Exception { + void singletonDelegateShouldReuseStateAcrossStepExecutions() throws Exception { int itemCount = ThreadLocalRandom.current().nextInt(10, 100); int chunkCount = ThreadLocalRandom.current().nextInt(1, 10); InvokeCountContext invokeCountContext = new InvokeCountContext(); @@ -126,14 +127,15 @@ void iteratorReaderProcessorWriterShouldKeepCountWhenNotStepScoped() throws Exce Job job = new JobBuilder("testJob", jobRepository) .start( new StepBuilder("testStep", jobRepository) - .chunk(chunkCount, new ResourcelessTransactionManager()) + .chunk(chunkCount) + .transactionManager(new ResourcelessTransactionManager()) .reader(itemStreamReader(testTasklet)) .processor(itemProcessor(testTasklet)) .writer(itemStreamWriter(testTasklet)) .build() ) .build(); - JobLauncher jobLauncher = context.getBean(JobLauncher.class); + JobOperator jobOperator = context.getBean(JobOperator.class); int repeatCount = ThreadLocalRandom.current().nextInt(1, 5); List jobExecutions = new ArrayList<>(); @@ -141,27 +143,25 @@ void iteratorReaderProcessorWriterShouldKeepCountWhenNotStepScoped() throws Exce JobParameters jobParameters = new JobParametersBuilder() .addString(UUID.randomUUID().toString(), UUID.randomUUID().toString()) .toJobParameters(); - JobExecution jobExecution = jobLauncher.run(job, jobParameters); + JobExecution jobExecution = jobOperator.start(job, jobParameters); jobExecutions.add(jobExecution); } assertThat(jobExecutions).allSatisfy(it -> assertThat(it.getStatus()).isEqualTo(BatchStatus.COMPLETED)); - // read context should be invoked assertThat(invokeCountContext.readContextCallCount).isEqualTo(repeatCount); - // stream callback should be invoked assertThat(invokeCountContext.onOpenReadCallCount).isEqualTo(repeatCount); assertThat(invokeCountContext.onUpdateReadCallCount).isGreaterThanOrEqualTo(repeatCount); assertThat(invokeCountContext.onCloseReadCallCount).isEqualTo(repeatCount); assertThat(invokeCountContext.onOpenWriteCallCount).isEqualTo(repeatCount); assertThat(invokeCountContext.onUpdateWriteCallCount).isGreaterThanOrEqualTo(repeatCount); assertThat(invokeCountContext.onCloseWriteCallCount).isEqualTo(repeatCount); - // process, write should be invoked only once per iteration assertThat(invokeCountContext.processCallCount).isEqualTo(itemCount); int writeCountPerIteration = (int)Math.ceil((double)itemCount / (double)chunkCount); assertThat(invokeCountContext.writeCallCount).isEqualTo(writeCountPerIteration); } - @EnableBatchProcessing( + @EnableBatchProcessing + @EnableJdbcJobRepository( dataSourceRef = "metadataDataSource", transactionManagerRef = "metadataTransactionManager" ) @@ -189,7 +189,8 @@ TestTasklet testTasklet( } } - @EnableBatchProcessing( + @EnableBatchProcessing + @EnableJdbcJobRepository( dataSourceRef = "metadataDataSource", transactionManagerRef = "metadataTransactionManager" ) @@ -228,13 +229,12 @@ public TestTasklet(InvokeCountContext invokeCountContext, int itemCount) { } @Override - public void onOpenRead(@NonNull ExecutionContext executionContext) { + public void onOpenRead(ExecutionContext executionContext) { this.invokeCountContext.onOpenReadCallCount++; } - @NonNull @Override - public Iterator readIterator(@NonNull ExecutionContext executionContext) { + public Iterator readIterator(ExecutionContext executionContext) { this.invokeCountContext.readContextCallCount++; return new Iterator<>() { @Override @@ -254,7 +254,7 @@ public Integer next() { } @Override - public void onUpdateRead(@NonNull ExecutionContext executionContext) { + public void onUpdateRead(ExecutionContext executionContext) { this.invokeCountContext.onUpdateReadCallCount++; } @@ -264,23 +264,23 @@ public void onCloseRead() { } @Override - public Integer process(@NonNull Integer item) { + public Integer process(Integer item) { this.invokeCountContext.processCallCount++; return item; } @Override - public void onOpenWrite(@NonNull ExecutionContext executionContext) { + public void onOpenWrite(ExecutionContext executionContext) { this.invokeCountContext.onOpenWriteCallCount++; } @Override - public void write(@NonNull Chunk chunk) { + public void write(Chunk chunk) { this.invokeCountContext.writeCallCount++; } @Override - public void onUpdateWrite(@NonNull ExecutionContext executionContext) { + public void onUpdateWrite(ExecutionContext executionContext) { this.invokeCountContext.onUpdateWriteCallCount++; } diff --git a/spring-batch-plus/src/integrationTest/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamIteratorReaderWriterIT.java b/spring-batch-plus/src/integrationTest/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamIteratorReaderWriterIntegrationTest.java similarity index 82% rename from spring-batch-plus/src/integrationTest/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamIteratorReaderWriterIT.java rename to spring-batch-plus/src/integrationTest/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamIteratorReaderWriterIntegrationTest.java index 8058a921..5361ae0a 100644 --- a/spring-batch-plus/src/integrationTest/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamIteratorReaderWriterIT.java +++ b/spring-batch-plus/src/integrationTest/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamIteratorReaderWriterIntegrationTest.java @@ -32,34 +32,37 @@ import org.junit.jupiter.api.RepeatedTest; import org.springframework.batch.core.BatchStatus; -import org.springframework.batch.core.Job; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.JobParameters; -import org.springframework.batch.core.JobParametersBuilder; import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing; +import org.springframework.batch.core.configuration.annotation.EnableJdbcJobRepository; import org.springframework.batch.core.configuration.annotation.StepScope; +import org.springframework.batch.core.job.Job; +import org.springframework.batch.core.job.JobExecution; import org.springframework.batch.core.job.builder.JobBuilder; -import org.springframework.batch.core.launch.JobLauncher; +import org.springframework.batch.core.job.parameters.JobParameters; +import org.springframework.batch.core.job.parameters.JobParametersBuilder; +import org.springframework.batch.core.launch.JobOperator; import org.springframework.batch.core.repository.JobRepository; import org.springframework.batch.core.step.builder.StepBuilder; -import org.springframework.batch.item.Chunk; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.batch.support.transaction.ResourcelessTransactionManager; +import org.springframework.batch.infrastructure.item.Chunk; +import org.springframework.batch.infrastructure.item.ExecutionContext; +import org.springframework.batch.infrastructure.support.transaction.ResourcelessTransactionManager; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.jdbc.datasource.DataSourceTransactionManager; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType; -import org.springframework.lang.NonNull; import org.springframework.transaction.TransactionManager; +/** + * Covers how delegate scope controls state isolation across step executions. + */ @SuppressWarnings({"unchecked", "unused"}) -class ItemStreamIteratorReaderWriterIT { +class ItemStreamIteratorReaderWriterIntegrationTest { private static final int TEST_REPEAT_COUNT = 5; @RepeatedTest(TEST_REPEAT_COUNT) - void iteratorReaderWriterShouldNotKeepCountWhenStepScoped() throws Exception { + void stepScopedDelegateShouldUseFreshStateForEachStepExecution() throws Exception { int itemCount = ThreadLocalRandom.current().nextInt(10, 100); int chunkCount = ThreadLocalRandom.current().nextInt(1, 10); InvokeCountContext invokeCountContext = new InvokeCountContext(); @@ -74,13 +77,14 @@ void iteratorReaderWriterShouldNotKeepCountWhenStepScoped() throws Exception { Job job = new JobBuilder("testJob", jobRepository) .start( new StepBuilder("testStep", jobRepository) - .chunk(chunkCount, new ResourcelessTransactionManager()) + .chunk(chunkCount) + .transactionManager(new ResourcelessTransactionManager()) .reader(itemStreamReader(testTasklet)) .writer(itemStreamWriter(testTasklet)) .build() ) .build(); - JobLauncher jobLauncher = context.getBean(JobLauncher.class); + JobOperator jobOperator = context.getBean(JobOperator.class); int repeatCount = ThreadLocalRandom.current().nextInt(1, 5); List jobExecutions = new ArrayList<>(); @@ -88,27 +92,24 @@ void iteratorReaderWriterShouldNotKeepCountWhenStepScoped() throws Exception { JobParameters jobParameters = new JobParametersBuilder() .addString(UUID.randomUUID().toString(), UUID.randomUUID().toString()) .toJobParameters(); - JobExecution jobExecution = jobLauncher.run(job, jobParameters); + JobExecution jobExecution = jobOperator.start(job, jobParameters); jobExecutions.add(jobExecution); } assertThat(jobExecutions).allSatisfy(it -> assertThat(it.getStatus()).isEqualTo(BatchStatus.COMPLETED)); - // read context should be invoked assertThat(invokeCountContext.readContextCallCount).isEqualTo(repeatCount); - // stream callback should be invoked assertThat(invokeCountContext.onOpenReadCallCount).isEqualTo(repeatCount); assertThat(invokeCountContext.onUpdateReadCallCount).isGreaterThanOrEqualTo(repeatCount); assertThat(invokeCountContext.onCloseReadCallCount).isEqualTo(repeatCount); assertThat(invokeCountContext.onOpenWriteCallCount).isEqualTo(repeatCount); assertThat(invokeCountContext.onUpdateWriteCallCount).isGreaterThanOrEqualTo(repeatCount); assertThat(invokeCountContext.onCloseWriteCallCount).isEqualTo(repeatCount); - // 'count' field is isolated per job instances since it is step scoped. so count is 0 for all job instances int writeCountPerIteration = (int)Math.ceil((double)itemCount / (double)chunkCount); assertThat(invokeCountContext.writeCallCount).isEqualTo(repeatCount * writeCountPerIteration); } @RepeatedTest(TEST_REPEAT_COUNT) - void iteratorReaderWriterShouldKeepCountWhenNotStepScoped() throws Exception { + void singletonDelegateShouldReuseStateAcrossStepExecutions() throws Exception { int itemCount = ThreadLocalRandom.current().nextInt(10, 100); int chunkCount = ThreadLocalRandom.current().nextInt(1, 10); InvokeCountContext invokeCountContext = new InvokeCountContext(); @@ -123,13 +124,14 @@ void iteratorReaderWriterShouldKeepCountWhenNotStepScoped() throws Exception { Job job = new JobBuilder("testJob", jobRepository) .start( new StepBuilder("testStep", jobRepository) - .chunk(chunkCount, new ResourcelessTransactionManager()) + .chunk(chunkCount) + .transactionManager(new ResourcelessTransactionManager()) .reader(itemStreamReader(testTasklet)) .writer(itemStreamWriter(testTasklet)) .build() ) .build(); - JobLauncher jobLauncher = context.getBean(JobLauncher.class); + JobOperator jobOperator = context.getBean(JobOperator.class); int repeatCount = ThreadLocalRandom.current().nextInt(1, 5); List jobExecutions = new ArrayList<>(); @@ -137,26 +139,24 @@ void iteratorReaderWriterShouldKeepCountWhenNotStepScoped() throws Exception { JobParameters jobParameters = new JobParametersBuilder() .addString(UUID.randomUUID().toString(), UUID.randomUUID().toString()) .toJobParameters(); - JobExecution jobExecution = jobLauncher.run(job, jobParameters); + JobExecution jobExecution = jobOperator.start(job, jobParameters); jobExecutions.add(jobExecution); } assertThat(jobExecutions).allSatisfy(it -> assertThat(it.getStatus()).isEqualTo(BatchStatus.COMPLETED)); - // read context should be invoked assertThat(invokeCountContext.readContextCallCount).isEqualTo(repeatCount); - // stream callback should be invoked assertThat(invokeCountContext.onOpenReadCallCount).isEqualTo(repeatCount); assertThat(invokeCountContext.onUpdateReadCallCount).isGreaterThanOrEqualTo(repeatCount); assertThat(invokeCountContext.onCloseReadCallCount).isEqualTo(repeatCount); assertThat(invokeCountContext.onOpenWriteCallCount).isEqualTo(repeatCount); assertThat(invokeCountContext.onUpdateWriteCallCount).isGreaterThanOrEqualTo(repeatCount); assertThat(invokeCountContext.onCloseWriteCallCount).isEqualTo(repeatCount); - // process, write should be invoked only once per iteration int writeCountPerIteration = (int)Math.ceil((double)itemCount / (double)chunkCount); assertThat(invokeCountContext.writeCallCount).isEqualTo(writeCountPerIteration); } - @EnableBatchProcessing( + @EnableBatchProcessing + @EnableJdbcJobRepository( dataSourceRef = "metadataDataSource", transactionManagerRef = "metadataTransactionManager" ) @@ -184,7 +184,8 @@ TestTasklet testTasklet( } } - @EnableBatchProcessing( + @EnableBatchProcessing + @EnableJdbcJobRepository( dataSourceRef = "metadataDataSource", transactionManagerRef = "metadataTransactionManager" ) @@ -223,13 +224,12 @@ public TestTasklet(InvokeCountContext invokeCountContext, int itemCount) { } @Override - public void onOpenRead(@NonNull ExecutionContext executionContext) { + public void onOpenRead(ExecutionContext executionContext) { this.invokeCountContext.onOpenReadCallCount++; } - @NonNull @Override - public Iterator readIterator(@NonNull ExecutionContext executionContext) { + public Iterator readIterator(ExecutionContext executionContext) { this.invokeCountContext.readContextCallCount++; return new Iterator<>() { @Override @@ -249,7 +249,7 @@ public Integer next() { } @Override - public void onUpdateRead(@NonNull ExecutionContext executionContext) { + public void onUpdateRead(ExecutionContext executionContext) { this.invokeCountContext.onUpdateReadCallCount++; } @@ -259,17 +259,17 @@ public void onCloseRead() { } @Override - public void onOpenWrite(@NonNull ExecutionContext executionContext) { + public void onOpenWrite(ExecutionContext executionContext) { this.invokeCountContext.onOpenWriteCallCount++; } @Override - public void write(@NonNull Chunk chunk) { + public void write(Chunk chunk) { this.invokeCountContext.writeCallCount++; } @Override - public void onUpdateWrite(@NonNull ExecutionContext executionContext) { + public void onUpdateWrite(ExecutionContext executionContext) { this.invokeCountContext.onUpdateWriteCallCount++; } diff --git a/spring-batch-plus/src/integrationTest/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamSimpleReaderProcessorIT.java b/spring-batch-plus/src/integrationTest/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamSimpleReaderProcessorIntegrationTest.java similarity index 83% rename from spring-batch-plus/src/integrationTest/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamSimpleReaderProcessorIT.java rename to spring-batch-plus/src/integrationTest/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamSimpleReaderProcessorIntegrationTest.java index 16ee812b..d46c38b9 100644 --- a/spring-batch-plus/src/integrationTest/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamSimpleReaderProcessorIT.java +++ b/spring-batch-plus/src/integrationTest/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamSimpleReaderProcessorIntegrationTest.java @@ -31,33 +31,36 @@ import org.junit.jupiter.api.RepeatedTest; import org.springframework.batch.core.BatchStatus; -import org.springframework.batch.core.Job; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.JobParameters; -import org.springframework.batch.core.JobParametersBuilder; import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing; +import org.springframework.batch.core.configuration.annotation.EnableJdbcJobRepository; import org.springframework.batch.core.configuration.annotation.StepScope; +import org.springframework.batch.core.job.Job; +import org.springframework.batch.core.job.JobExecution; import org.springframework.batch.core.job.builder.JobBuilder; -import org.springframework.batch.core.launch.JobLauncher; +import org.springframework.batch.core.job.parameters.JobParameters; +import org.springframework.batch.core.job.parameters.JobParametersBuilder; +import org.springframework.batch.core.launch.JobOperator; import org.springframework.batch.core.repository.JobRepository; import org.springframework.batch.core.step.builder.StepBuilder; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.batch.support.transaction.ResourcelessTransactionManager; +import org.springframework.batch.infrastructure.item.ExecutionContext; +import org.springframework.batch.infrastructure.support.transaction.ResourcelessTransactionManager; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.jdbc.datasource.DataSourceTransactionManager; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType; -import org.springframework.lang.NonNull; import org.springframework.transaction.TransactionManager; +/** + * Covers how delegate scope controls state isolation across step executions. + */ @SuppressWarnings({"unchecked", "unused"}) -class ItemStreamSimpleReaderProcessorIT { +class ItemStreamSimpleReaderProcessorIntegrationTest { private static final int TEST_REPEAT_COUNT = 5; @RepeatedTest(TEST_REPEAT_COUNT) - void simpleReaderProcessorShouldNotKeepCountWhenStepScoped() throws Exception { + void stepScopedDelegateShouldUseFreshStateForEachStepExecution() throws Exception { int itemCount = ThreadLocalRandom.current().nextInt(10, 100); int chunkCount = ThreadLocalRandom.current().nextInt(1, 10); InvokeCountContext invokeCountContext = new InvokeCountContext(); @@ -72,7 +75,8 @@ void simpleReaderProcessorShouldNotKeepCountWhenStepScoped() throws Exception { Job job = new JobBuilder("testJob", jobRepository) .start( new StepBuilder("testStep", jobRepository) - .chunk(chunkCount, new ResourcelessTransactionManager()) + .chunk(chunkCount) + .transactionManager(new ResourcelessTransactionManager()) .reader(itemStreamReader(testTasklet)) .processor(itemProcessor(testTasklet)) .writer($ -> { @@ -80,7 +84,7 @@ void simpleReaderProcessorShouldNotKeepCountWhenStepScoped() throws Exception { .build() ) .build(); - JobLauncher jobLauncher = context.getBean(JobLauncher.class); + JobOperator jobOperator = context.getBean(JobOperator.class); int repeatCount = ThreadLocalRandom.current().nextInt(1, 5); List jobExecutions = new ArrayList<>(); @@ -88,21 +92,19 @@ void simpleReaderProcessorShouldNotKeepCountWhenStepScoped() throws Exception { JobParameters jobParameters = new JobParametersBuilder() .addString(UUID.randomUUID().toString(), UUID.randomUUID().toString()) .toJobParameters(); - JobExecution jobExecution = jobLauncher.run(job, jobParameters); + JobExecution jobExecution = jobOperator.start(job, jobParameters); jobExecutions.add(jobExecution); } assertThat(jobExecutions).allSatisfy(it -> assertThat(it.getStatus()).isEqualTo(BatchStatus.COMPLETED)); - // stream callback should be invoked assertThat(invokeCountContext.onOpenReadCallCount).isEqualTo(repeatCount); assertThat(invokeCountContext.onUpdateReadCallCount).isGreaterThanOrEqualTo(repeatCount); assertThat(invokeCountContext.onCloseReadCallCount).isEqualTo(repeatCount); - // 'count' field is isolated per job instances since it is step scoped. so count is 0 for all job instances assertThat(invokeCountContext.processCallCount).isEqualTo(repeatCount * itemCount); } @RepeatedTest(TEST_REPEAT_COUNT) - void simpleReaderProcessorShouldKeepCountWhenNotStepScoped() throws Exception { + void singletonDelegateShouldReuseStateAcrossStepExecutions() throws Exception { int itemCount = ThreadLocalRandom.current().nextInt(10, 100); int chunkCount = ThreadLocalRandom.current().nextInt(1, 10); InvokeCountContext invokeCountContext = new InvokeCountContext(); @@ -117,7 +119,8 @@ void simpleReaderProcessorShouldKeepCountWhenNotStepScoped() throws Exception { Job job = new JobBuilder("testJob", jobRepository) .start( new StepBuilder("testStep", jobRepository) - .chunk(chunkCount, new ResourcelessTransactionManager()) + .chunk(chunkCount) + .transactionManager(new ResourcelessTransactionManager()) .reader(itemStreamReader(testTasklet)) .processor(itemProcessor(testTasklet)) .writer($ -> { @@ -125,7 +128,7 @@ void simpleReaderProcessorShouldKeepCountWhenNotStepScoped() throws Exception { .build() ) .build(); - JobLauncher jobLauncher = context.getBean(JobLauncher.class); + JobOperator jobOperator = context.getBean(JobOperator.class); int repeatCount = ThreadLocalRandom.current().nextInt(1, 5); List jobExecutions = new ArrayList<>(); @@ -133,20 +136,19 @@ void simpleReaderProcessorShouldKeepCountWhenNotStepScoped() throws Exception { JobParameters jobParameters = new JobParametersBuilder() .addString(UUID.randomUUID().toString(), UUID.randomUUID().toString()) .toJobParameters(); - JobExecution jobExecution = jobLauncher.run(job, jobParameters); + JobExecution jobExecution = jobOperator.start(job, jobParameters); jobExecutions.add(jobExecution); } assertThat(jobExecutions).allSatisfy(it -> assertThat(it.getStatus()).isEqualTo(BatchStatus.COMPLETED)); - // stream callback should be invoked assertThat(invokeCountContext.onOpenReadCallCount).isEqualTo(repeatCount); assertThat(invokeCountContext.onUpdateReadCallCount).isGreaterThanOrEqualTo(repeatCount); assertThat(invokeCountContext.onCloseReadCallCount).isEqualTo(repeatCount); - // process, write should be invoked only once per iteration assertThat(invokeCountContext.processCallCount).isEqualTo(itemCount); } - @EnableBatchProcessing( + @EnableBatchProcessing + @EnableJdbcJobRepository( dataSourceRef = "metadataDataSource", transactionManagerRef = "metadataTransactionManager" ) @@ -173,7 +175,8 @@ TestTasklet testTasklet(InvokeCountContext invokeCountContext, int itemCount) { } } - @EnableBatchProcessing( + @EnableBatchProcessing + @EnableJdbcJobRepository( dataSourceRef = "metadataDataSource", transactionManagerRef = "metadataTransactionManager" ) @@ -211,7 +214,7 @@ public TestTasklet(InvokeCountContext invokeCountContext, int itemCount) { } @Override - public void onOpenRead(@NonNull ExecutionContext executionContext) { + public void onOpenRead(ExecutionContext executionContext) { this.invokeCountContext.onOpenReadCallCount++; } @@ -225,7 +228,7 @@ public Integer read() { } @Override - public void onUpdateRead(@NonNull ExecutionContext executionContext) { + public void onUpdateRead(ExecutionContext executionContext) { this.invokeCountContext.onUpdateReadCallCount++; } @@ -235,7 +238,7 @@ public void onCloseRead() { } @Override - public Integer process(@NonNull Integer item) { + public Integer process(Integer item) { this.invokeCountContext.processCallCount++; return item; } diff --git a/spring-batch-plus/src/integrationTest/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamSimpleReaderProcessorWriterIT.java b/spring-batch-plus/src/integrationTest/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamSimpleReaderProcessorWriterIntegrationTest.java similarity index 83% rename from spring-batch-plus/src/integrationTest/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamSimpleReaderProcessorWriterIT.java rename to spring-batch-plus/src/integrationTest/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamSimpleReaderProcessorWriterIntegrationTest.java index 59816027..e3511edc 100644 --- a/spring-batch-plus/src/integrationTest/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamSimpleReaderProcessorWriterIT.java +++ b/spring-batch-plus/src/integrationTest/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamSimpleReaderProcessorWriterIntegrationTest.java @@ -32,34 +32,37 @@ import org.junit.jupiter.api.RepeatedTest; import org.springframework.batch.core.BatchStatus; -import org.springframework.batch.core.Job; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.JobParameters; -import org.springframework.batch.core.JobParametersBuilder; import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing; +import org.springframework.batch.core.configuration.annotation.EnableJdbcJobRepository; import org.springframework.batch.core.configuration.annotation.StepScope; +import org.springframework.batch.core.job.Job; +import org.springframework.batch.core.job.JobExecution; import org.springframework.batch.core.job.builder.JobBuilder; -import org.springframework.batch.core.launch.JobLauncher; +import org.springframework.batch.core.job.parameters.JobParameters; +import org.springframework.batch.core.job.parameters.JobParametersBuilder; +import org.springframework.batch.core.launch.JobOperator; import org.springframework.batch.core.repository.JobRepository; import org.springframework.batch.core.step.builder.StepBuilder; -import org.springframework.batch.item.Chunk; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.batch.support.transaction.ResourcelessTransactionManager; +import org.springframework.batch.infrastructure.item.Chunk; +import org.springframework.batch.infrastructure.item.ExecutionContext; +import org.springframework.batch.infrastructure.support.transaction.ResourcelessTransactionManager; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.jdbc.datasource.DataSourceTransactionManager; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType; -import org.springframework.lang.NonNull; import org.springframework.transaction.TransactionManager; +/** + * Covers how delegate scope controls state isolation across step executions. + */ @SuppressWarnings({"unchecked", "unused"}) -class ItemStreamSimpleReaderProcessorWriterIT { +class ItemStreamSimpleReaderProcessorWriterIntegrationTest { private static final int TEST_REPEAT_COUNT = 5; @RepeatedTest(TEST_REPEAT_COUNT) - void simpleReaderProcessorWriterShouldNotKeepCountWhenStepScoped() throws Exception { + void stepScopedDelegateShouldUseFreshStateForEachStepExecution() throws Exception { int itemCount = ThreadLocalRandom.current().nextInt(10, 100); int chunkCount = ThreadLocalRandom.current().nextInt(1, 10); InvokeCountContext invokeCountContext = new InvokeCountContext(); @@ -74,14 +77,15 @@ void simpleReaderProcessorWriterShouldNotKeepCountWhenStepScoped() throws Except Job job = new JobBuilder("testJob", jobRepository) .start( new StepBuilder("testStep", jobRepository) - .chunk(chunkCount, new ResourcelessTransactionManager()) + .chunk(chunkCount) + .transactionManager(new ResourcelessTransactionManager()) .reader(itemStreamReader(testTasklet)) .processor(itemProcessor(testTasklet)) .writer(itemStreamWriter(testTasklet)) .build() ) .build(); - JobLauncher jobLauncher = context.getBean(JobLauncher.class); + JobOperator jobOperator = context.getBean(JobOperator.class); int repeatCount = ThreadLocalRandom.current().nextInt(1, 5); List jobExecutions = new ArrayList<>(); @@ -89,26 +93,24 @@ void simpleReaderProcessorWriterShouldNotKeepCountWhenStepScoped() throws Except JobParameters jobParameters = new JobParametersBuilder() .addString(UUID.randomUUID().toString(), UUID.randomUUID().toString()) .toJobParameters(); - JobExecution jobExecution = jobLauncher.run(job, jobParameters); + JobExecution jobExecution = jobOperator.start(job, jobParameters); jobExecutions.add(jobExecution); } assertThat(jobExecutions).allSatisfy(it -> assertThat(it.getStatus()).isEqualTo(BatchStatus.COMPLETED)); - // stream callback should be invoked assertThat(invokeCountContext.onOpenReadCallCount).isEqualTo(repeatCount); assertThat(invokeCountContext.onUpdateReadCallCount).isGreaterThanOrEqualTo(repeatCount); assertThat(invokeCountContext.onCloseReadCallCount).isEqualTo(repeatCount); assertThat(invokeCountContext.onOpenWriteCallCount).isEqualTo(repeatCount); assertThat(invokeCountContext.onUpdateWriteCallCount).isGreaterThanOrEqualTo(repeatCount); assertThat(invokeCountContext.onCloseWriteCallCount).isEqualTo(repeatCount); - // 'count' field is isolated per job instances since it is step scoped. so count is 0 for all job instances assertThat(invokeCountContext.processCallCount).isEqualTo(repeatCount * itemCount); int writeCountPerIteration = (int)Math.ceil((double)itemCount / (double)chunkCount); assertThat(invokeCountContext.writeCallCount).isEqualTo(repeatCount * writeCountPerIteration); } @RepeatedTest(TEST_REPEAT_COUNT) - void simpleReaderProcessorWriterShouldKeepCountWhenNotStepScoped() throws Exception { + void singletonDelegateShouldReuseStateAcrossStepExecutions() throws Exception { int itemCount = ThreadLocalRandom.current().nextInt(10, 100); int chunkCount = ThreadLocalRandom.current().nextInt(1, 10); InvokeCountContext invokeCountContext = new InvokeCountContext(); @@ -123,14 +125,15 @@ void simpleReaderProcessorWriterShouldKeepCountWhenNotStepScoped() throws Except Job job = new JobBuilder("testJob", jobRepository) .start( new StepBuilder("testStep", jobRepository) - .chunk(chunkCount, new ResourcelessTransactionManager()) + .chunk(chunkCount) + .transactionManager(new ResourcelessTransactionManager()) .reader(itemStreamReader(testTasklet)) .processor(itemProcessor(testTasklet)) .writer(itemStreamWriter(testTasklet)) .build() ) .build(); - JobLauncher jobLauncher = context.getBean(JobLauncher.class); + JobOperator jobOperator = context.getBean(JobOperator.class); int repeatCount = ThreadLocalRandom.current().nextInt(1, 5); List jobExecutions = new ArrayList<>(); @@ -138,25 +141,24 @@ void simpleReaderProcessorWriterShouldKeepCountWhenNotStepScoped() throws Except JobParameters jobParameters = new JobParametersBuilder() .addString(UUID.randomUUID().toString(), UUID.randomUUID().toString()) .toJobParameters(); - JobExecution jobExecution = jobLauncher.run(job, jobParameters); + JobExecution jobExecution = jobOperator.start(job, jobParameters); jobExecutions.add(jobExecution); } assertThat(jobExecutions).allSatisfy(it -> assertThat(it.getStatus()).isEqualTo(BatchStatus.COMPLETED)); - // stream callback should be invoked assertThat(invokeCountContext.onOpenReadCallCount).isEqualTo(repeatCount); assertThat(invokeCountContext.onUpdateReadCallCount).isGreaterThanOrEqualTo(repeatCount); assertThat(invokeCountContext.onCloseReadCallCount).isEqualTo(repeatCount); assertThat(invokeCountContext.onOpenWriteCallCount).isEqualTo(repeatCount); assertThat(invokeCountContext.onUpdateWriteCallCount).isGreaterThanOrEqualTo(repeatCount); assertThat(invokeCountContext.onCloseWriteCallCount).isEqualTo(repeatCount); - // process, write should be invoked only once per iteration assertThat(invokeCountContext.processCallCount).isEqualTo(itemCount); int writeCountPerIteration = (int)Math.ceil((double)itemCount / (double)chunkCount); assertThat(invokeCountContext.writeCallCount).isEqualTo(writeCountPerIteration); } - @EnableBatchProcessing( + @EnableBatchProcessing + @EnableJdbcJobRepository( dataSourceRef = "metadataDataSource", transactionManagerRef = "metadataTransactionManager" ) @@ -184,7 +186,8 @@ TestTasklet testTasklet( } } - @EnableBatchProcessing( + @EnableBatchProcessing + @EnableJdbcJobRepository( dataSourceRef = "metadataDataSource", transactionManagerRef = "metadataTransactionManager" ) @@ -222,7 +225,7 @@ public TestTasklet(InvokeCountContext invokeCountContext, int itemCount) { } @Override - public void onOpenRead(@NonNull ExecutionContext executionContext) { + public void onOpenRead(ExecutionContext executionContext) { this.invokeCountContext.onOpenReadCallCount++; } @@ -236,7 +239,7 @@ public Integer read() { } @Override - public void onUpdateRead(@NonNull ExecutionContext executionContext) { + public void onUpdateRead(ExecutionContext executionContext) { this.invokeCountContext.onUpdateReadCallCount++; } @@ -246,23 +249,23 @@ public void onCloseRead() { } @Override - public Integer process(@NonNull Integer item) { + public Integer process(Integer item) { this.invokeCountContext.processCallCount++; return item; } @Override - public void onOpenWrite(@NonNull ExecutionContext executionContext) { + public void onOpenWrite(ExecutionContext executionContext) { this.invokeCountContext.onOpenWriteCallCount++; } @Override - public void write(@NonNull Chunk chunk) { + public void write(Chunk chunk) { this.invokeCountContext.writeCallCount++; } @Override - public void onUpdateWrite(@NonNull ExecutionContext executionContext) { + public void onUpdateWrite(ExecutionContext executionContext) { this.invokeCountContext.onUpdateWriteCallCount++; } diff --git a/spring-batch-plus/src/integrationTest/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamSimpleReaderWriterIT.java b/spring-batch-plus/src/integrationTest/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamSimpleReaderWriterIntegrationTest.java similarity index 83% rename from spring-batch-plus/src/integrationTest/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamSimpleReaderWriterIT.java rename to spring-batch-plus/src/integrationTest/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamSimpleReaderWriterIntegrationTest.java index 8ef4948a..a9dfa9c2 100644 --- a/spring-batch-plus/src/integrationTest/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamSimpleReaderWriterIT.java +++ b/spring-batch-plus/src/integrationTest/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamSimpleReaderWriterIntegrationTest.java @@ -31,34 +31,37 @@ import org.junit.jupiter.api.RepeatedTest; import org.springframework.batch.core.BatchStatus; -import org.springframework.batch.core.Job; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.JobParameters; -import org.springframework.batch.core.JobParametersBuilder; import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing; +import org.springframework.batch.core.configuration.annotation.EnableJdbcJobRepository; import org.springframework.batch.core.configuration.annotation.StepScope; +import org.springframework.batch.core.job.Job; +import org.springframework.batch.core.job.JobExecution; import org.springframework.batch.core.job.builder.JobBuilder; -import org.springframework.batch.core.launch.JobLauncher; +import org.springframework.batch.core.job.parameters.JobParameters; +import org.springframework.batch.core.job.parameters.JobParametersBuilder; +import org.springframework.batch.core.launch.JobOperator; import org.springframework.batch.core.repository.JobRepository; import org.springframework.batch.core.step.builder.StepBuilder; -import org.springframework.batch.item.Chunk; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.batch.support.transaction.ResourcelessTransactionManager; +import org.springframework.batch.infrastructure.item.Chunk; +import org.springframework.batch.infrastructure.item.ExecutionContext; +import org.springframework.batch.infrastructure.support.transaction.ResourcelessTransactionManager; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.jdbc.datasource.DataSourceTransactionManager; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType; -import org.springframework.lang.NonNull; import org.springframework.transaction.TransactionManager; +/** + * Covers how delegate scope controls state isolation across step executions. + */ @SuppressWarnings({"unchecked", "unused"}) -class ItemStreamSimpleReaderWriterIT { +class ItemStreamSimpleReaderWriterIntegrationTest { private static final int TEST_REPEAT_COUNT = 5; @RepeatedTest(TEST_REPEAT_COUNT) - void simpleReaderWriterShouldNotKeepCountWhenStepScoped() throws Exception { + void stepScopedDelegateShouldUseFreshStateForEachStepExecution() throws Exception { int itemCount = ThreadLocalRandom.current().nextInt(10, 100); int chunkCount = ThreadLocalRandom.current().nextInt(1, 10); InvokeCountContext invokeCountContext = new InvokeCountContext(); @@ -73,13 +76,14 @@ void simpleReaderWriterShouldNotKeepCountWhenStepScoped() throws Exception { Job job = new JobBuilder("testJob", jobRepository) .start( new StepBuilder("testStep", jobRepository) - .chunk(chunkCount, new ResourcelessTransactionManager()) + .chunk(chunkCount) + .transactionManager(new ResourcelessTransactionManager()) .reader(itemStreamReader(testTasklet)) .writer(itemStreamWriter(testTasklet)) .build() ) .build(); - JobLauncher jobLauncher = context.getBean(JobLauncher.class); + JobOperator jobOperator = context.getBean(JobOperator.class); int repeatCount = ThreadLocalRandom.current().nextInt(1, 5); List jobExecutions = new ArrayList<>(); @@ -87,25 +91,23 @@ void simpleReaderWriterShouldNotKeepCountWhenStepScoped() throws Exception { JobParameters jobParameters = new JobParametersBuilder() .addString(UUID.randomUUID().toString(), UUID.randomUUID().toString()) .toJobParameters(); - JobExecution jobExecution = jobLauncher.run(job, jobParameters); + JobExecution jobExecution = jobOperator.start(job, jobParameters); jobExecutions.add(jobExecution); } assertThat(jobExecutions).allSatisfy(it -> assertThat(it.getStatus()).isEqualTo(BatchStatus.COMPLETED)); - // stream callback should be invoked assertThat(invokeCountContext.onOpenReadCallCount).isEqualTo(repeatCount); assertThat(invokeCountContext.onUpdateReadCallCount).isGreaterThanOrEqualTo(repeatCount); assertThat(invokeCountContext.onCloseReadCallCount).isEqualTo(repeatCount); assertThat(invokeCountContext.onOpenWriteCallCount).isEqualTo(repeatCount); assertThat(invokeCountContext.onUpdateWriteCallCount).isGreaterThanOrEqualTo(repeatCount); assertThat(invokeCountContext.onCloseWriteCallCount).isEqualTo(repeatCount); - // 'count' field is isolated per job instances since it is step scoped. so count is 0 for all job instances int writeCountPerIteration = (int)Math.ceil((double)itemCount / (double)chunkCount); assertThat(invokeCountContext.writeCallCount).isEqualTo(repeatCount * writeCountPerIteration); } @RepeatedTest(TEST_REPEAT_COUNT) - void simpleReaderWriterShouldKeepCountWhenNotStepScoped() throws Exception { + void singletonDelegateShouldReuseStateAcrossStepExecutions() throws Exception { int itemCount = ThreadLocalRandom.current().nextInt(10, 100); int chunkCount = ThreadLocalRandom.current().nextInt(1, 10); InvokeCountContext invokeCountContext = new InvokeCountContext(); @@ -120,13 +122,14 @@ void simpleReaderWriterShouldKeepCountWhenNotStepScoped() throws Exception { Job job = new JobBuilder("testJob", jobRepository) .start( new StepBuilder("testStep", jobRepository) - .chunk(chunkCount, new ResourcelessTransactionManager()) + .chunk(chunkCount) + .transactionManager(new ResourcelessTransactionManager()) .reader(itemStreamReader(testTasklet)) .writer(itemStreamWriter(testTasklet)) .build() ) .build(); - JobLauncher jobLauncher = context.getBean(JobLauncher.class); + JobOperator jobOperator = context.getBean(JobOperator.class); int repeatCount = ThreadLocalRandom.current().nextInt(1, 5); List jobExecutions = new ArrayList<>(); @@ -134,24 +137,23 @@ void simpleReaderWriterShouldKeepCountWhenNotStepScoped() throws Exception { JobParameters jobParameters = new JobParametersBuilder() .addString(UUID.randomUUID().toString(), UUID.randomUUID().toString()) .toJobParameters(); - JobExecution jobExecution = jobLauncher.run(job, jobParameters); + JobExecution jobExecution = jobOperator.start(job, jobParameters); jobExecutions.add(jobExecution); } assertThat(jobExecutions).allSatisfy(it -> assertThat(it.getStatus()).isEqualTo(BatchStatus.COMPLETED)); - // stream callback should be invoked assertThat(invokeCountContext.onOpenReadCallCount).isEqualTo(repeatCount); assertThat(invokeCountContext.onUpdateReadCallCount).isGreaterThanOrEqualTo(repeatCount); assertThat(invokeCountContext.onCloseReadCallCount).isEqualTo(repeatCount); assertThat(invokeCountContext.onOpenWriteCallCount).isEqualTo(repeatCount); assertThat(invokeCountContext.onUpdateWriteCallCount).isGreaterThanOrEqualTo(repeatCount); assertThat(invokeCountContext.onCloseWriteCallCount).isEqualTo(repeatCount); - // write should be invoked only once per iteration int writeCountPerIteration = (int)Math.ceil((double)itemCount / (double)chunkCount); assertThat(invokeCountContext.writeCallCount).isEqualTo(writeCountPerIteration); } - @EnableBatchProcessing( + @EnableBatchProcessing + @EnableJdbcJobRepository( dataSourceRef = "metadataDataSource", transactionManagerRef = "metadataTransactionManager" ) @@ -178,7 +180,8 @@ TestTasklet testTasklet(InvokeCountContext invokeCountContext, int itemCount) { } } - @EnableBatchProcessing( + @EnableBatchProcessing + @EnableJdbcJobRepository( dataSourceRef = "metadataDataSource", transactionManagerRef = "metadataTransactionManager" ) @@ -216,7 +219,7 @@ public TestTasklet(InvokeCountContext invokeCountContext, int itemCount) { } @Override - public void onOpenRead(@NonNull ExecutionContext executionContext) { + public void onOpenRead(ExecutionContext executionContext) { this.invokeCountContext.onOpenReadCallCount++; } @@ -230,7 +233,7 @@ public Integer read() { } @Override - public void onUpdateRead(@NonNull ExecutionContext executionContext) { + public void onUpdateRead(ExecutionContext executionContext) { this.invokeCountContext.onUpdateReadCallCount++; } @@ -240,17 +243,17 @@ public void onCloseRead() { } @Override - public void onOpenWrite(@NonNull ExecutionContext executionContext) { + public void onOpenWrite(ExecutionContext executionContext) { this.invokeCountContext.onOpenWriteCallCount++; } @Override - public void write(@NonNull Chunk chunk) { + public void write(Chunk chunk) { this.invokeCountContext.writeCallCount++; } @Override - public void onUpdateWrite(@NonNull ExecutionContext executionContext) { + public void onUpdateWrite(ExecutionContext executionContext) { this.invokeCountContext.onUpdateWriteCallCount++; } diff --git a/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/item/adapter/AdapterFactory.java b/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/item/adapter/AdapterFactory.java index 09cb7118..03c66ee2 100644 --- a/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/item/adapter/AdapterFactory.java +++ b/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/item/adapter/AdapterFactory.java @@ -21,10 +21,9 @@ import java.util.Objects; import org.springframework.batch.core.scope.StepScope; -import org.springframework.batch.item.ItemProcessor; -import org.springframework.batch.item.ItemStreamReader; -import org.springframework.batch.item.ItemStreamWriter; -import org.springframework.lang.NonNull; +import org.springframework.batch.infrastructure.item.ItemProcessor; +import org.springframework.batch.infrastructure.item.ItemStreamReader; +import org.springframework.batch.infrastructure.item.ItemStreamWriter; import com.navercorp.spring.batch.plus.step.adapter.ItemStreamFluxReaderDelegate; @@ -50,7 +49,7 @@ public final class AdapterFactory { * @return an adapted ItemStreamReader */ @Deprecated - public static ItemStreamReader itemStreamReader(@NonNull ItemStreamReaderDelegate delegate) { + public static ItemStreamReader itemStreamReader(ItemStreamReaderDelegate delegate) { Objects.requireNonNull(delegate, "ItemStreamReader delegate is null"); return StepScopeItemStreamReader.of(() -> ItemStreamReaderAdapter.of(delegate)); } @@ -68,7 +67,7 @@ public static ItemStreamReader itemStreamReader(@NonNull ItemStreamReader * @return an adapted ItemProcessor */ @Deprecated - public static ItemProcessor itemProcessor(@NonNull ItemProcessorDelegate delegate) { + public static ItemProcessor itemProcessor(ItemProcessorDelegate delegate) { return ItemProcessorAdapter.of(delegate); } @@ -83,7 +82,7 @@ public static ItemProcessor itemProcessor(@NonNull ItemProcessorDel * @return an adapted ItemStreamWriter */ @Deprecated - public static ItemStreamWriter itemStreamWriter(@NonNull ItemStreamWriterDelegate delegate) { + public static ItemStreamWriter itemStreamWriter(ItemStreamWriterDelegate delegate) { return ItemStreamWriterAdapter.of(delegate); } diff --git a/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/item/adapter/ItemProcessorAdapter.java b/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/item/adapter/ItemProcessorAdapter.java index cc240bf1..e0620c51 100644 --- a/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/item/adapter/ItemProcessorAdapter.java +++ b/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/item/adapter/ItemProcessorAdapter.java @@ -20,8 +20,8 @@ import java.util.Objects; -import org.springframework.batch.item.ItemProcessor; -import org.springframework.lang.NonNull; +import org.jspecify.annotations.Nullable; +import org.springframework.batch.infrastructure.item.ItemProcessor; /** * An adapter which adapt {@link ItemProcessorDelegate} to {@link ItemProcessor}. @@ -40,7 +40,7 @@ public class ItemProcessorAdapter implements ItemProcessor { * @param an item type to process * @param a processed item type */ - public static ItemProcessor of(@NonNull ItemProcessorDelegate delegate) { + public static ItemProcessor of(ItemProcessorDelegate delegate) { return new ItemProcessorAdapter<>(delegate); } @@ -50,9 +50,8 @@ protected ItemProcessorAdapter(ItemProcessorDelegate delegate) { this.delegate = Objects.requireNonNull(delegate, "Delegate processor must not be null"); } - @SuppressWarnings("NullableProblems") @Override - public O process(I item) { + public @Nullable O process(I item) { return this.delegate.process(item); } } diff --git a/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/item/adapter/ItemProcessorDelegate.java b/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/item/adapter/ItemProcessorDelegate.java index 73e3d5bb..1e7209c4 100644 --- a/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/item/adapter/ItemProcessorDelegate.java +++ b/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/item/adapter/ItemProcessorDelegate.java @@ -18,9 +18,8 @@ package com.navercorp.spring.batch.plus.item.adapter; -import org.springframework.batch.item.ItemProcessor; -import org.springframework.lang.NonNull; -import org.springframework.lang.Nullable; +import org.jspecify.annotations.Nullable; +import org.springframework.batch.infrastructure.item.ItemProcessor; /** * A delegate for {@link ItemProcessor}. @@ -37,6 +36,5 @@ public interface ItemProcessorDelegate { * @param item an item to process * @return processed item */ - @Nullable - O process(@NonNull I item); + @Nullable O process(I item); } diff --git a/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/item/adapter/ItemStreamReaderAdapter.java b/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/item/adapter/ItemStreamReaderAdapter.java index 784fc341..a94e84b1 100644 --- a/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/item/adapter/ItemStreamReaderAdapter.java +++ b/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/item/adapter/ItemStreamReaderAdapter.java @@ -21,9 +21,9 @@ import java.util.Iterator; import java.util.Objects; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.batch.item.ItemStreamReader; -import org.springframework.lang.NonNull; +import org.jspecify.annotations.Nullable; +import org.springframework.batch.infrastructure.item.ExecutionContext; +import org.springframework.batch.infrastructure.item.ItemStreamReader; import reactor.core.publisher.Flux; @@ -45,17 +45,18 @@ public class ItemStreamReaderAdapter implements ItemStreamReader { * @return an adapted ItemStreamReader * @param a read item type */ - public static ItemStreamReader of(@NonNull ItemStreamReaderDelegate delegate) { + public static ItemStreamReader of(ItemStreamReaderDelegate delegate) { return new ItemStreamReaderAdapter<>(delegate); } + // Prevent the reactive source from advancing beyond the item requested by ItemReader.read(). protected static final int DEFAULT_BATCH_SIZE = 1; protected final ItemStreamReaderDelegate delegate; - protected Flux flux = null; + protected @Nullable Flux flux = null; - protected Iterator iterator = null; + protected @Nullable Iterator iterator = null; protected ItemStreamReaderAdapter(ItemStreamReaderDelegate delegate) { this.delegate = Objects.requireNonNull(delegate, "Delegate reader must not be null"); @@ -69,7 +70,7 @@ public void open(ExecutionContext executionContext) { } @Override - public T read() { + public @Nullable T read() { if (this.iterator == null) { Objects.requireNonNull(this.flux, "Flux isn't set. Call 'open' first."); this.iterator = this.flux.toIterable(DEFAULT_BATCH_SIZE).iterator(); diff --git a/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/item/adapter/ItemStreamReaderDelegate.java b/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/item/adapter/ItemStreamReaderDelegate.java index 37746339..c1d3b6fb 100644 --- a/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/item/adapter/ItemStreamReaderDelegate.java +++ b/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/item/adapter/ItemStreamReaderDelegate.java @@ -18,9 +18,8 @@ package com.navercorp.spring.batch.plus.item.adapter; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.batch.item.ItemStreamReader; -import org.springframework.lang.NonNull; +import org.springframework.batch.infrastructure.item.ExecutionContext; +import org.springframework.batch.infrastructure.item.ItemStreamReader; import reactor.core.publisher.Flux; @@ -40,7 +39,7 @@ public interface ItemStreamReaderDelegate { * * @param executionContext an execution context */ - default void onOpenRead(@NonNull ExecutionContext executionContext) { + default void onOpenRead(ExecutionContext executionContext) { } /** @@ -49,15 +48,14 @@ default void onOpenRead(@NonNull ExecutionContext executionContext) { * @param executionContext an execution context * @return a flux to read item. */ - @NonNull - Flux readFlux(@NonNull ExecutionContext executionContext); + Flux readFlux(ExecutionContext executionContext); /** * A delegate method for {@link ItemStreamReader#update(ExecutionContext)}. * * @param executionContext an execution context */ - default void onUpdateRead(@NonNull ExecutionContext executionContext) { + default void onUpdateRead(ExecutionContext executionContext) { } /** diff --git a/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/item/adapter/ItemStreamReaderProcessorWriter.java b/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/item/adapter/ItemStreamReaderProcessorWriter.java index 563fc080..daf2fa50 100644 --- a/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/item/adapter/ItemStreamReaderProcessorWriter.java +++ b/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/item/adapter/ItemStreamReaderProcessorWriter.java @@ -18,9 +18,9 @@ package com.navercorp.spring.batch.plus.item.adapter; -import org.springframework.batch.item.ItemProcessor; -import org.springframework.batch.item.ItemStreamReader; -import org.springframework.batch.item.ItemStreamWriter; +import org.springframework.batch.infrastructure.item.ItemProcessor; +import org.springframework.batch.infrastructure.item.ItemStreamReader; +import org.springframework.batch.infrastructure.item.ItemStreamWriter; import com.navercorp.spring.batch.plus.step.adapter.ItemStreamFluxReaderProcessorWriter; diff --git a/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/item/adapter/ItemStreamReaderWriter.java b/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/item/adapter/ItemStreamReaderWriter.java index 21e7c109..9e2d2b84 100644 --- a/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/item/adapter/ItemStreamReaderWriter.java +++ b/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/item/adapter/ItemStreamReaderWriter.java @@ -18,8 +18,8 @@ package com.navercorp.spring.batch.plus.item.adapter; -import org.springframework.batch.item.ItemStreamReader; -import org.springframework.batch.item.ItemStreamWriter; +import org.springframework.batch.infrastructure.item.ItemStreamReader; +import org.springframework.batch.infrastructure.item.ItemStreamWriter; import com.navercorp.spring.batch.plus.step.adapter.ItemStreamFluxReaderWriter; diff --git a/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/item/adapter/ItemStreamWriterAdapter.java b/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/item/adapter/ItemStreamWriterAdapter.java index 3a29ab98..e89cd690 100644 --- a/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/item/adapter/ItemStreamWriterAdapter.java +++ b/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/item/adapter/ItemStreamWriterAdapter.java @@ -20,10 +20,9 @@ import java.util.Objects; -import org.springframework.batch.item.Chunk; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.batch.item.ItemStreamWriter; -import org.springframework.lang.NonNull; +import org.springframework.batch.infrastructure.item.Chunk; +import org.springframework.batch.infrastructure.item.ExecutionContext; +import org.springframework.batch.infrastructure.item.ItemStreamWriter; /** * An adapter which adapt {@link ItemStreamWriterDelegate} to {@link ItemStreamWriter}. @@ -41,7 +40,7 @@ public class ItemStreamWriterAdapter implements ItemStreamWriter { * @return an adapted ItemStreamWriter * @param an item type to write */ - public static ItemStreamWriter of(@NonNull ItemStreamWriterDelegate delegate) { + public static ItemStreamWriter of(ItemStreamWriterDelegate delegate) { return new ItemStreamWriterAdapter<>(delegate); } diff --git a/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/item/adapter/ItemStreamWriterDelegate.java b/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/item/adapter/ItemStreamWriterDelegate.java index 381a7f0f..13c0361b 100644 --- a/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/item/adapter/ItemStreamWriterDelegate.java +++ b/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/item/adapter/ItemStreamWriterDelegate.java @@ -18,10 +18,9 @@ package com.navercorp.spring.batch.plus.item.adapter; -import org.springframework.batch.item.Chunk; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.batch.item.ItemStreamWriter; -import org.springframework.lang.NonNull; +import org.springframework.batch.infrastructure.item.Chunk; +import org.springframework.batch.infrastructure.item.ExecutionContext; +import org.springframework.batch.infrastructure.item.ItemStreamWriter; /** * A delegate for {@link ItemStreamWriter}. @@ -36,20 +35,20 @@ public interface ItemStreamWriterDelegate { * A delegate method for {@link ItemStreamWriter#open(ExecutionContext)}. * @param executionContext an execution context */ - default void onOpenWrite(@NonNull ExecutionContext executionContext) { + default void onOpenWrite(ExecutionContext executionContext) { } /** * A delegate method for {@link ItemStreamWriter#write(Chunk)}. * @param chunk chunk to write */ - void write(@NonNull Chunk chunk); + void write(Chunk chunk); /** * A delegate method for {@link ItemStreamWriter#update(ExecutionContext)}. * @param executionContext an execution context */ - default void onUpdateWrite(@NonNull ExecutionContext executionContext) { + default void onUpdateWrite(ExecutionContext executionContext) { } /** diff --git a/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/item/adapter/StepScopeItemStreamReader.java b/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/item/adapter/StepScopeItemStreamReader.java index e671a17c..4aaf01e1 100644 --- a/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/item/adapter/StepScopeItemStreamReader.java +++ b/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/item/adapter/StepScopeItemStreamReader.java @@ -23,13 +23,14 @@ import java.util.Objects; import java.util.function.Supplier; +import org.jspecify.annotations.Nullable; import org.slf4j.Logger; import org.springframework.batch.core.scope.StepScope; import org.springframework.batch.core.scope.context.StepContext; import org.springframework.batch.core.scope.context.StepSynchronizationManager; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.batch.item.ItemStreamException; -import org.springframework.batch.item.ItemStreamReader; +import org.springframework.batch.infrastructure.item.ExecutionContext; +import org.springframework.batch.infrastructure.item.ItemStreamException; +import org.springframework.batch.infrastructure.item.ItemStreamReader; /** * A {@link StepScope} bound proxy implementation. @@ -39,6 +40,9 @@ */ @Deprecated public class StepScopeItemStreamReader implements ItemStreamReader { + protected static final Logger logger = getLogger(StepScopeItemStreamReader.class); + + protected static final String SCOPE_KEY = "StepScopeItemStreamReader@delegate"; /** * Create an {@link ItemStreamReader} instance bound to {@link StepScope}. @@ -52,10 +56,6 @@ public static ItemStreamReader of(Supplier> delegateS return new StepScopeItemStreamReader<>(delegateSupplier); } - protected static final String SCOPE_KEY = "StepScopeItemStreamReader@delegate"; - - protected final Logger logger = getLogger(StepScopeItemStreamReader.class); - protected final Supplier> delegateSupplier; protected StepScopeItemStreamReader(Supplier> readerGenerator) { @@ -69,7 +69,7 @@ public void open(ExecutionContext executionContext) throws ItemStreamException { } @Override - public T read() throws Exception { + public @Nullable T read() throws Exception { return getDelegate().read(); } diff --git a/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/item/adapter/package-info.java b/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/item/adapter/package-info.java index a43e167c..d812a5d0 100644 --- a/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/item/adapter/package-info.java +++ b/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/item/adapter/package-info.java @@ -19,4 +19,7 @@ /** * An extensions for spring batch item adapter concerns. */ +@NullMarked package com.navercorp.spring.batch.plus.item.adapter; + +import org.jspecify.annotations.NullMarked; diff --git a/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/job/ClearRunIdIncrementer.java b/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/job/ClearRunIdIncrementer.java index 9a537424..5e49ed6f 100644 --- a/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/job/ClearRunIdIncrementer.java +++ b/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/job/ClearRunIdIncrementer.java @@ -21,16 +21,17 @@ import java.util.Objects; import java.util.Optional; -import org.springframework.batch.core.JobParameters; -import org.springframework.batch.core.JobParametersBuilder; -import org.springframework.batch.core.JobParametersIncrementer; -import org.springframework.batch.core.launch.support.RunIdIncrementer; -import org.springframework.lang.NonNull; +import org.springframework.batch.core.job.parameters.JobParameters; +import org.springframework.batch.core.job.parameters.JobParametersBuilder; +import org.springframework.batch.core.job.parameters.JobParametersIncrementer; +import org.springframework.batch.core.job.parameters.RunIdIncrementer; /** - * Alternative to {@link RunIdIncrementer}. - * RunIdIncrementer returns not only a new run id but also all previous job parameters. - * It makes unintended job parameters for a job. + * A {@link JobParametersIncrementer} that increments a run-id parameter while + * discarding every other parameter from the supplied {@link JobParameters}. + * + *

Use this instead of {@link RunIdIncrementer} when parameters from the previous job + * execution must not propagate to the next job instance. * * @since 0.1.0 */ @@ -39,20 +40,20 @@ public class ClearRunIdIncrementer implements JobParametersIncrementer { protected static final String DEFAULT_RUN_ID = "run.id"; /** - * Create a new ClearRunIdIncrementer with {@link #DEFAULT_RUN_ID}. - * @return a new ClearRunIdIncrementer instance + * Creates an incrementer using {@link #DEFAULT_RUN_ID} as the run-id parameter name. + * @return a new incrementer */ public static JobParametersIncrementer create() { return create(DEFAULT_RUN_ID); } /** - * Create a new ClearRunIdIncrementer with custom run id. + * Creates an incrementer using the given run-id parameter name. * - * @param runId a run id - * @return a new ClearRunIdIncrementer instance + * @param runId the run-id parameter name + * @return a new incrementer */ - public static JobParametersIncrementer create(@NonNull String runId) { + public static JobParametersIncrementer create(String runId) { return new ClearRunIdIncrementer(runId); } @@ -62,7 +63,6 @@ protected ClearRunIdIncrementer(String runId) { this.runId = Objects.requireNonNull(runId, "Run id must not be null"); } - @NonNull @Override public JobParameters getNext(JobParameters parameters) { long nextId = Optional.ofNullable(parameters) diff --git a/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/job/metadata/CheckMaxJobInstanceIdToDeleteTasklet.java b/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/job/metadata/CheckMaxJobInstanceIdToDeleteTasklet.java index 8b0eb112..e439e579 100644 --- a/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/job/metadata/CheckMaxJobInstanceIdToDeleteTasklet.java +++ b/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/job/metadata/CheckMaxJobInstanceIdToDeleteTasklet.java @@ -27,32 +27,31 @@ import org.slf4j.LoggerFactory; import org.springframework.batch.core.BatchStatus; import org.springframework.batch.core.ExitStatus; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.StepContribution; -import org.springframework.batch.core.StepExecution; -import org.springframework.batch.core.StepExecutionListener; +import org.springframework.batch.core.job.JobExecution; +import org.springframework.batch.core.listener.StepExecutionListener; import org.springframework.batch.core.scope.context.ChunkContext; import org.springframework.batch.core.scope.context.StepContext; +import org.springframework.batch.core.step.StepContribution; +import org.springframework.batch.core.step.StepExecution; import org.springframework.batch.core.step.tasklet.Tasklet; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.batch.repeat.RepeatStatus; +import org.springframework.batch.infrastructure.item.ExecutionContext; +import org.springframework.batch.infrastructure.repeat.RepeatStatus; /** * A tasklet to check metadata of job instances to delete. */ class CheckMaxJobInstanceIdToDeleteTasklet implements Tasklet, StepExecutionListener { + protected static final Logger logger = LoggerFactory.getLogger(CheckMaxJobInstanceIdToDeleteTasklet.class); static final String MAX_ID_KEY = "maxJobInstanceId"; static final ExitStatus EMPTY = new ExitStatus("EMPTY"); - private final Logger logger = LoggerFactory.getLogger(CheckMaxJobInstanceIdToDeleteTasklet.class); + protected final JobMetadataDao dao; - private final JobMetadataDao dao; + protected final String baseDateParameterName; - private final String baseDateParameterName; - - private final DateTimeFormatter baseDateFormatter; + protected final DateTimeFormatter baseDateFormatter; CheckMaxJobInstanceIdToDeleteTasklet( JobMetadataDao dao, @@ -72,7 +71,7 @@ public RepeatStatus execute(StepContribution contribution, ChunkContext chunkCon LocalDate baseDate = LocalDate.parse(baseDateStr, baseDateFormatter); Optional maxJobInstanceId = this.dao.selectMaxJobInstanceIdLessThanCreateTime(baseDate); - if (!maxJobInstanceId.isPresent()) { + if (maxJobInstanceId.isEmpty()) { logger.info("There is no record of job instance executed before {}. No need to delete metadata", baseDate); return RepeatStatus.FINISHED; } diff --git a/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/job/metadata/DeleteMetadataJobBuilder.java b/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/job/metadata/DeleteMetadataJobBuilder.java index 7172045b..a2fe21d6 100644 --- a/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/job/metadata/DeleteMetadataJobBuilder.java +++ b/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/job/metadata/DeleteMetadataJobBuilder.java @@ -23,16 +23,15 @@ import javax.sql.DataSource; -import org.springframework.batch.core.Job; -import org.springframework.batch.core.Step; -import org.springframework.batch.core.job.DefaultJobParametersValidator; +import org.springframework.batch.core.job.Job; import org.springframework.batch.core.job.builder.JobBuilder; +import org.springframework.batch.core.job.parameters.DefaultJobParametersValidator; import org.springframework.batch.core.repository.JobRepository; import org.springframework.batch.core.repository.dao.AbstractJdbcBatchMetadataDao; +import org.springframework.batch.core.step.Step; import org.springframework.batch.core.step.builder.StepBuilder; -import org.springframework.batch.support.transaction.ResourcelessTransactionManager; +import org.springframework.batch.infrastructure.support.transaction.ResourcelessTransactionManager; import org.springframework.jdbc.datasource.DataSourceTransactionManager; -import org.springframework.lang.NonNull; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.interceptor.DefaultTransactionAttribute; @@ -44,25 +43,29 @@ * @since 0.2.0 */ public class DeleteMetadataJobBuilder { - private final JobRepository jobRepository; + protected static final String CHECK_MAX_JOB_INSTANCE_ID_STEP_NAME = "checkMaxJobInstanceId"; - private final DataSource dataSource; + protected static final String DELETE_METADATA_STEP_NAME = "deleteMetadata"; - private String name = "deleteMetadataJob"; + protected final JobRepository jobRepository; - private String tablePrefix = AbstractJdbcBatchMetadataDao.DEFAULT_TABLE_PREFIX; + protected final DataSource dataSource; - private String baseDateParameterName = "baseDate"; + protected String name = "deleteMetadataJob"; - private DateTimeFormatter baseDateFormatter = DateTimeFormatter.ofPattern("yyyy/MM/dd"); + protected String tablePrefix = AbstractJdbcBatchMetadataDao.DEFAULT_TABLE_PREFIX; - private String dryRunParameterName = "dryRun"; + protected String baseDateParameterName = "baseDate"; + + protected DateTimeFormatter baseDateFormatter = DateTimeFormatter.ofPattern("yyyy/MM/dd"); + + protected String dryRunParameterName = "dryRun"; /** * @param jobRepository the target job repository to delete old metadata. * @param dataSource the data source of the job repository */ - public DeleteMetadataJobBuilder(@NonNull JobRepository jobRepository, @NonNull DataSource dataSource) { + public DeleteMetadataJobBuilder(JobRepository jobRepository, DataSource dataSource) { Objects.requireNonNull(jobRepository, "JobRepository must not be null"); Objects.requireNonNull(dataSource, "DataSource must not be null"); @@ -74,7 +77,7 @@ public DeleteMetadataJobBuilder(@NonNull JobRepository jobRepository, @NonNull D * @param name the name of the job to delete metadata. The default value is 'deleteMetaDataJob'. * @return The current instance of the builder for method chaining */ - public DeleteMetadataJobBuilder name(@NonNull String name) { + public DeleteMetadataJobBuilder name(String name) { this.name = Objects.requireNonNull(name, "Job name must not be null"); return this; } @@ -83,7 +86,7 @@ public DeleteMetadataJobBuilder name(@NonNull String name) { * @param tablePrefix The prefix of tables for metadata. The default value is 'BATCH_'. * @return The current instance of the builder for method chaining */ - public DeleteMetadataJobBuilder tablePrefix(@NonNull String tablePrefix) { + public DeleteMetadataJobBuilder tablePrefix(String tablePrefix) { this.tablePrefix = Objects.requireNonNull(tablePrefix, "Metadata table prefix must not be null"); return this; } @@ -93,7 +96,7 @@ public DeleteMetadataJobBuilder tablePrefix(@NonNull String tablePrefix) { * The default value is "baseDate" * @return The current instance of the builder for method chaining */ - public DeleteMetadataJobBuilder baseDateParameterName(@NonNull String baseDateParameterName) { + public DeleteMetadataJobBuilder baseDateParameterName(String baseDateParameterName) { this.baseDateParameterName = Objects.requireNonNull(baseDateParameterName, "BaseDate parameter name must not be null"); return this; @@ -104,7 +107,7 @@ public DeleteMetadataJobBuilder baseDateParameterName(@NonNull String baseDatePa * The default value is DateTimeFormatter.ofPattern("yyyy/MM/dd") * @return The current instance of the builder for method chaining */ - public DeleteMetadataJobBuilder baseDateFormatter(@NonNull DateTimeFormatter baseDateFormatter) { + public DeleteMetadataJobBuilder baseDateFormatter(DateTimeFormatter baseDateFormatter) { this.baseDateFormatter = Objects.requireNonNull(baseDateFormatter, "BaseDate formatter must not be null"); return this; } @@ -114,7 +117,7 @@ public DeleteMetadataJobBuilder baseDateFormatter(@NonNull DateTimeFormatter bas * The default value is "dryRun" * @return The current instance of the builder for method chaining */ - public DeleteMetadataJobBuilder dryRunParameterName(@NonNull String dryRunParameterName) { + public DeleteMetadataJobBuilder dryRunParameterName(String dryRunParameterName) { this.dryRunParameterName = Objects.requireNonNull(dryRunParameterName, "DryRun parameter name must not be null"); return this; @@ -124,13 +127,12 @@ public DeleteMetadataJobBuilder dryRunParameterName(@NonNull String dryRunParame * @return a job to delete old metadata. */ public Job build() { - DefaultJobParametersValidator validator = new DefaultJobParametersValidator(); validator.setRequiredKeys(new String[] {this.baseDateParameterName}); JobMetadataDao dao = new JobMetadataDao(this.dataSource, this.tablePrefix); Step checkStep = this.buildCheckStep(dao); - + Step deleteStep = buildDeleteStep(dao); return new JobBuilder(this.name, this.jobRepository) .validator(validator) .start(checkStep) @@ -139,12 +141,12 @@ public Job build() { .end() .from(checkStep) - .next(buildDeleteStep(dao)) + .next(deleteStep) .end() .build(); } - private Step buildCheckStep(JobMetadataDao dao) { + protected Step buildCheckStep(JobMetadataDao dao) { CheckMaxJobInstanceIdToDeleteTasklet tasklet = new CheckMaxJobInstanceIdToDeleteTasklet( dao, this.baseDateParameterName, @@ -152,20 +154,20 @@ private Step buildCheckStep(JobMetadataDao dao) { ); TransactionAttribute noTransaction = new DefaultTransactionAttribute(Propagation.NOT_SUPPORTED.value()); - return new StepBuilder("checkMaxJobInstanceId", this.jobRepository) + return new StepBuilder(CHECK_MAX_JOB_INSTANCE_ID_STEP_NAME, this.jobRepository) .tasklet(tasklet, new ResourcelessTransactionManager()) .transactionAttribute(noTransaction) .listener(tasklet) .build(); } - private Step buildDeleteStep(JobMetadataDao dao) { + protected Step buildDeleteStep(JobMetadataDao dao) { DeleteMetadataTasklet tasklet = new DeleteMetadataTasklet( dao, this.dryRunParameterName ); PlatformTransactionManager transactionManager = new DataSourceTransactionManager(dataSource); - return new StepBuilder("deleteMetadata", this.jobRepository) + return new StepBuilder(DELETE_METADATA_STEP_NAME, this.jobRepository) .tasklet(tasklet, transactionManager) .listener(tasklet) .build(); diff --git a/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/job/metadata/DeleteMetadataTasklet.java b/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/job/metadata/DeleteMetadataTasklet.java index 0ceb253e..6a5cda34 100644 --- a/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/job/metadata/DeleteMetadataTasklet.java +++ b/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/job/metadata/DeleteMetadataTasklet.java @@ -22,31 +22,29 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.batch.core.JobParameters; -import org.springframework.batch.core.StepContribution; -import org.springframework.batch.core.StepExecution; -import org.springframework.batch.core.StepExecutionListener; +import org.springframework.batch.core.job.parameters.JobParameters; +import org.springframework.batch.core.listener.StepExecutionListener; import org.springframework.batch.core.scope.context.ChunkContext; +import org.springframework.batch.core.step.StepContribution; +import org.springframework.batch.core.step.StepExecution; import org.springframework.batch.core.step.tasklet.Tasklet; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.batch.repeat.RepeatStatus; +import org.springframework.batch.infrastructure.item.ExecutionContext; +import org.springframework.batch.infrastructure.repeat.RepeatStatus; /** * A tasklet to delete metadata of Spring Batch. * This tasklet must be executed after execution of {@link CheckMaxJobInstanceIdToDeleteTasklet} */ class DeleteMetadataTasklet implements Tasklet, StepExecutionListener { + protected static final Logger logger = LoggerFactory.getLogger(DeleteMetadataTasklet.class); static final String LOW_ID_KEY = "lowJobInstanceId"; static final int DELETION_RANGE_LENGTH = 100; - private final Logger logger = LoggerFactory.getLogger(DeleteMetadataTasklet.class); + protected final JobMetadataDao dao; - private final JobMetadataDao dao; - - private final String dryRunParameterName; - private long maxJobInstanceId; + protected final String dryRunParameterName; DeleteMetadataTasklet(JobMetadataDao dao, String dryRunParameterName) { this.dao = dao; @@ -56,22 +54,34 @@ class DeleteMetadataTasklet implements Tasklet, StepExecutionListener { @Override public void beforeStep(StepExecution stepExecution) { ExecutionContext jobExecutionContext = stepExecution.getJobExecution().getExecutionContext(); - this.maxJobInstanceId = jobExecutionContext.getLong(CheckMaxJobInstanceIdToDeleteTasklet.MAX_ID_KEY); - long minJobInstanceId = this.dao.selectMinJobInstanceId(); - ExecutionContext stepExecutionContext = stepExecution.getExecutionContext(); - if (stepExecutionContext.containsKey(LOW_ID_KEY)) { // in case of restart + long maxJobInstanceId = jobExecutionContext.getLong(CheckMaxJobInstanceIdToDeleteTasklet.MAX_ID_KEY); + putMaxJobInstanceId(stepExecutionContext, maxJobInstanceId); + + // Preserve the persisted lower bound when restarting the step. + if (stepExecutionContext.containsKey(LOW_ID_KEY)) { + return; + } + + Optional minJobInstanceId = this.dao.selectMinJobInstanceId(); + if (minJobInstanceId.isEmpty()) { return; } - putLowJobInstanceId(stepExecution, minJobInstanceId); + putLowJobInstanceId(stepExecutionContext, minJobInstanceId.get()); } @Override public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception { StepExecution stepExecution = contribution.getStepExecution(); + ExecutionContext stepExecutionContext = stepExecution.getExecutionContext(); + if (!stepExecutionContext.containsKey(LOW_ID_KEY)) { + logger.info("No job instances found. Skipping metadata deletion"); + return RepeatStatus.FINISHED; + } - long lowJobInstanceId = getLowJobInstanceId(stepExecution); + long lowJobInstanceId = getLowJobInstanceId(stepExecutionContext); + long maxJobInstanceId = getMaxJobInstanceId(stepExecutionContext); long highJobInstanceId = Math.min(lowJobInstanceId + DELETION_RANGE_LENGTH - 1, maxJobInstanceId); boolean dryRun = getDryRunParameter(stepExecution); @@ -84,32 +94,38 @@ public RepeatStatus execute(StepContribution contribution, ChunkContext chunkCon } long nextLowJobInstanceId = highJobInstanceId + 1; - if (nextLowJobInstanceId > this.maxJobInstanceId) { + if (nextLowJobInstanceId > maxJobInstanceId) { return RepeatStatus.FINISHED; } - putLowJobInstanceId(stepExecution, nextLowJobInstanceId); + putLowJobInstanceId(stepExecutionContext, nextLowJobInstanceId); return RepeatStatus.CONTINUABLE; } - private void putLowJobInstanceId(StepExecution stepExecution, long lowJobInstanceId) { - ExecutionContext stepExecutionContext = stepExecution.getExecutionContext(); + protected void putLowJobInstanceId(ExecutionContext stepExecutionContext, long lowJobInstanceId) { stepExecutionContext.put(LOW_ID_KEY, lowJobInstanceId); } - private long getLowJobInstanceId(StepExecution stepExecution) { - ExecutionContext stepExecutionContext = stepExecution.getExecutionContext(); + protected long getLowJobInstanceId(ExecutionContext stepExecutionContext) { return stepExecutionContext.getLong(LOW_ID_KEY); } - private boolean getDryRunParameter(StepExecution stepExecution) { + protected void putMaxJobInstanceId(ExecutionContext stepExecutionContext, long maxJobInstanceId) { + stepExecutionContext.put(CheckMaxJobInstanceIdToDeleteTasklet.MAX_ID_KEY, maxJobInstanceId); + } + + protected long getMaxJobInstanceId(ExecutionContext stepExecutionContext) { + return stepExecutionContext.getLong(CheckMaxJobInstanceIdToDeleteTasklet.MAX_ID_KEY); + } + + protected boolean getDryRunParameter(StepExecution stepExecution) { JobParameters jobParameters = stepExecution.getJobParameters(); return Optional.ofNullable(jobParameters.getString(this.dryRunParameterName)) .map(Boolean::parseBoolean) .orElse(false); } - private int deleteJobMetadata(long lowJobInstanceId, long highJobInstanceId) { + protected int deleteJobMetadata(long lowJobInstanceId, long highJobInstanceId) { dao.deleteStepExecutionContextsByJobInstanceIdRange(lowJobInstanceId, highJobInstanceId); dao.deleteStepExecutionsByJobInstanceIdRange(lowJobInstanceId, highJobInstanceId); dao.deleteJobExecutionContextsByJobInstanceIdRange(lowJobInstanceId, highJobInstanceId); diff --git a/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/job/metadata/JobMetadataDao.java b/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/job/metadata/JobMetadataDao.java index b9d612d1..564c4702 100644 --- a/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/job/metadata/JobMetadataDao.java +++ b/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/job/metadata/JobMetadataDao.java @@ -19,11 +19,13 @@ package com.navercorp.spring.batch.plus.job.metadata; import java.time.LocalDate; +import java.util.Objects; import java.util.Optional; import javax.sql.DataSource; import org.springframework.batch.core.repository.dao.AbstractJdbcBatchMetadataDao; +import org.springframework.jdbc.core.JdbcOperations; import org.springframework.jdbc.core.JdbcTemplate; /** @@ -31,21 +33,21 @@ */ class JobMetadataDao extends AbstractJdbcBatchMetadataDao { - private final String selectMaxJobInstanceId; + protected final String selectMaxJobInstanceId; - private final String selectMinJobInstanceId; + protected final String selectMinJobInstanceId; - private final String deleteJobInstances; + protected final String deleteJobInstances; - private final String deleteJobExecutions; + protected final String deleteJobExecutions; - private final String deleteJobExecutionParams; + protected final String deleteJobExecutionParams; - private final String deleteJobExecutionContexts; + protected final String deleteJobExecutionContexts; - private final String deleteStepExecutions; + protected final String deleteStepExecutions; - private final String deleteStepExecutionContexts; + protected final String deleteStepExecutionContexts; JobMetadataDao(DataSource dataSource, String tablePrefix) { setJdbcTemplate(new JdbcTemplate(dataSource)); @@ -62,36 +64,42 @@ class JobMetadataDao extends AbstractJdbcBatchMetadataDao { } Optional selectMaxJobInstanceIdLessThanCreateTime(LocalDate createTime) { - return Optional.ofNullable( - getJdbcTemplate().queryForObject(selectMaxJobInstanceId, Long.class, createTime) - ); + JdbcOperations jdbcTemplate = Objects.requireNonNull(getJdbcTemplate(), "JdbcOperations must not be null"); + return Optional.ofNullable(jdbcTemplate.queryForObject(selectMaxJobInstanceId, Long.class, createTime)); } - Long selectMinJobInstanceId() { - return getJdbcTemplate().queryForObject(selectMinJobInstanceId, Long.class); + Optional selectMinJobInstanceId() { + JdbcOperations jdbcTemplate = Objects.requireNonNull(getJdbcTemplate(), "JdbcOperations must not be null"); + return Optional.ofNullable(jdbcTemplate.queryForObject(selectMinJobInstanceId, Long.class)); } int deleteJobInstancesByJobInstanceIdRange(long lowJobInstanceId, long highJobInstanceId) { - return getJdbcTemplate().update(deleteJobInstances, lowJobInstanceId, highJobInstanceId); + JdbcOperations jdbcTemplate = Objects.requireNonNull(getJdbcTemplate(), "JdbcOperations must not be null"); + return jdbcTemplate.update(deleteJobInstances, lowJobInstanceId, highJobInstanceId); } int deleteJobExecutionsByJobInstanceIdRange(long lowJobInstanceId, long highJobInstanceId) { - return getJdbcTemplate().update(deleteJobExecutions, lowJobInstanceId, highJobInstanceId); + JdbcOperations jdbcTemplate = Objects.requireNonNull(getJdbcTemplate(), "JdbcOperations must not be null"); + return jdbcTemplate.update(deleteJobExecutions, lowJobInstanceId, highJobInstanceId); } int deleteJobExecutionParamsByJobInstanceIdRange(long lowJobInstanceId, long highJobInstanceId) { - return getJdbcTemplate().update(deleteJobExecutionParams, lowJobInstanceId, highJobInstanceId); + JdbcOperations jdbcTemplate = Objects.requireNonNull(getJdbcTemplate(), "JdbcOperations must not be null"); + return jdbcTemplate.update(deleteJobExecutionParams, lowJobInstanceId, highJobInstanceId); } int deleteJobExecutionContextsByJobInstanceIdRange(long lowJobInstanceId, long highJobInstanceId) { - return getJdbcTemplate().update(deleteJobExecutionContexts, lowJobInstanceId, highJobInstanceId); + JdbcOperations jdbcTemplate = Objects.requireNonNull(getJdbcTemplate(), "JdbcOperations must not be null"); + return jdbcTemplate.update(deleteJobExecutionContexts, lowJobInstanceId, highJobInstanceId); } int deleteStepExecutionsByJobInstanceIdRange(long lowJobInstanceId, long highJobInstanceId) { - return getJdbcTemplate().update(deleteStepExecutions, lowJobInstanceId, highJobInstanceId); + JdbcOperations jdbcTemplate = Objects.requireNonNull(getJdbcTemplate(), "JdbcOperations must not be null"); + return jdbcTemplate.update(deleteStepExecutions, lowJobInstanceId, highJobInstanceId); } int deleteStepExecutionContextsByJobInstanceIdRange(long lowJobInstanceId, long highJobInstanceId) { - return getJdbcTemplate().update(deleteStepExecutionContexts, lowJobInstanceId, highJobInstanceId); + JdbcOperations jdbcTemplate = Objects.requireNonNull(getJdbcTemplate(), "JdbcOperations must not be null"); + return jdbcTemplate.update(deleteStepExecutionContexts, lowJobInstanceId, highJobInstanceId); } } diff --git a/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/job/metadata/package-info.java b/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/job/metadata/package-info.java index 7639e821..29d1c0b6 100644 --- a/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/job/metadata/package-info.java +++ b/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/job/metadata/package-info.java @@ -19,4 +19,7 @@ /** * The job to delete old Spring Batch metadata */ +@NullMarked package com.navercorp.spring.batch.plus.job.metadata; + +import org.jspecify.annotations.NullMarked; diff --git a/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/job/package-info.java b/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/job/package-info.java index e8c1586d..11247f6f 100644 --- a/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/job/package-info.java +++ b/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/job/package-info.java @@ -19,4 +19,7 @@ /** * An extensions for spring batch job concerns. */ +@NullMarked package com.navercorp.spring.batch.plus.job; + +import org.jspecify.annotations.NullMarked; diff --git a/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/AdapterFactory.java b/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/AdapterFactory.java index d861862e..cabbf522 100644 --- a/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/AdapterFactory.java +++ b/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/AdapterFactory.java @@ -21,10 +21,9 @@ import java.util.Objects; import org.springframework.batch.core.scope.StepScope; -import org.springframework.batch.item.ItemProcessor; -import org.springframework.batch.item.ItemStreamReader; -import org.springframework.batch.item.ItemStreamWriter; -import org.springframework.lang.NonNull; +import org.springframework.batch.infrastructure.item.ItemProcessor; +import org.springframework.batch.infrastructure.item.ItemStreamReader; +import org.springframework.batch.infrastructure.item.ItemStreamWriter; /** * An adapter factory for these interfaces @@ -47,7 +46,7 @@ public final class AdapterFactory { * @param delegate a delegate * @return an adapted ItemStreamReader */ - public static ItemStreamReader itemStreamReader(@NonNull ItemStreamFluxReaderDelegate delegate) { + public static ItemStreamReader itemStreamReader(ItemStreamFluxReaderDelegate delegate) { Objects.requireNonNull(delegate, "ItemStreamReader delegate is null"); return StepScopeItemStreamReader.of(() -> ItemStreamFluxReaderAdapter.of(delegate)); } @@ -60,7 +59,7 @@ public static ItemStreamReader itemStreamReader(@NonNull ItemStreamFluxRe * @param delegate a delegate * @return an adapted ItemStreamReader */ - public static ItemStreamReader itemStreamReader(@NonNull ItemStreamIterableReaderDelegate delegate) { + public static ItemStreamReader itemStreamReader(ItemStreamIterableReaderDelegate delegate) { Objects.requireNonNull(delegate, "ItemStreamReader delegate is null"); return StepScopeItemStreamReader.of(() -> ItemStreamIterableReaderAdapter.of(delegate)); } @@ -73,7 +72,7 @@ public static ItemStreamReader itemStreamReader(@NonNull ItemStreamIterab * @param delegate a delegate * @return an adapted ItemStreamReader */ - public static ItemStreamReader itemStreamReader(@NonNull ItemStreamIteratorReaderDelegate delegate) { + public static ItemStreamReader itemStreamReader(ItemStreamIteratorReaderDelegate delegate) { Objects.requireNonNull(delegate, "ItemStreamReader delegate is null"); return StepScopeItemStreamReader.of(() -> ItemStreamIteratorReaderAdapter.of(delegate)); } @@ -86,7 +85,7 @@ public static ItemStreamReader itemStreamReader(@NonNull ItemStreamIterat * @param delegate a delegate * @return an adapted ItemStreamReader */ - public static ItemStreamReader itemStreamReader(@NonNull ItemStreamSimpleReaderDelegate delegate) { + public static ItemStreamReader itemStreamReader(ItemStreamSimpleReaderDelegate delegate) { Objects.requireNonNull(delegate, "ItemStreamReader delegate is null"); return StepScopeItemStreamReader.of(() -> ItemStreamSimpleReaderAdapter.of(delegate)); } @@ -99,7 +98,7 @@ public static ItemStreamReader itemStreamReader(@NonNull ItemStreamSimple * @param delegate a delegate * @return an adapted ItemProcessor */ - public static ItemProcessor itemProcessor(@NonNull ItemProcessorDelegate delegate) { + public static ItemProcessor itemProcessor(ItemProcessorDelegate delegate) { return ItemProcessorAdapter.of(delegate); } @@ -110,7 +109,7 @@ public static ItemProcessor itemProcessor(@NonNull ItemProcessorDel * @param delegate a delegate * @return an adapted ItemStreamWriter */ - public static ItemStreamWriter itemStreamWriter(@NonNull ItemStreamWriterDelegate delegate) { + public static ItemStreamWriter itemStreamWriter(ItemStreamWriterDelegate delegate) { return ItemStreamWriterAdapter.of(delegate); } diff --git a/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/ItemProcessorAdapter.java b/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/ItemProcessorAdapter.java index 96f3701b..cab8f6d6 100644 --- a/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/ItemProcessorAdapter.java +++ b/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/ItemProcessorAdapter.java @@ -20,8 +20,8 @@ import java.util.Objects; -import org.springframework.batch.item.ItemProcessor; -import org.springframework.lang.NonNull; +import org.jspecify.annotations.Nullable; +import org.springframework.batch.infrastructure.item.ItemProcessor; /** * An adapter which adapt {@link ItemProcessorDelegate} to {@link ItemProcessor}. @@ -38,7 +38,7 @@ public class ItemProcessorAdapter implements ItemProcessor { * @param an item type to process * @param a processed item type */ - public static ItemProcessor of(@NonNull ItemProcessorDelegate delegate) { + public static ItemProcessor of(ItemProcessorDelegate delegate) { return new ItemProcessorAdapter<>(delegate); } @@ -49,7 +49,7 @@ protected ItemProcessorAdapter(ItemProcessorDelegate delegate) { } @Override - public O process(@NonNull I item) { + public @Nullable O process(I item) { return this.delegate.process(item); } } diff --git a/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/ItemProcessorDelegate.java b/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/ItemProcessorDelegate.java index 6b0934a0..fd7d38b5 100644 --- a/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/ItemProcessorDelegate.java +++ b/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/ItemProcessorDelegate.java @@ -18,9 +18,8 @@ package com.navercorp.spring.batch.plus.step.adapter; -import org.springframework.batch.item.ItemProcessor; -import org.springframework.lang.NonNull; -import org.springframework.lang.Nullable; +import org.jspecify.annotations.Nullable; +import org.springframework.batch.infrastructure.item.ItemProcessor; /** * A delegate for {@link ItemProcessor}. @@ -35,6 +34,5 @@ public interface ItemProcessorDelegate { * @param item an item to process * @return processed item */ - @Nullable - O process(@NonNull I item); + @Nullable O process(I item); } diff --git a/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamFluxReaderAdapter.java b/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamFluxReaderAdapter.java index 373612a2..0fa9a39c 100644 --- a/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamFluxReaderAdapter.java +++ b/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamFluxReaderAdapter.java @@ -22,9 +22,9 @@ import java.util.Objects; import java.util.Optional; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.batch.item.ItemStreamReader; -import org.springframework.lang.NonNull; +import org.jspecify.annotations.Nullable; +import org.springframework.batch.infrastructure.item.ExecutionContext; +import org.springframework.batch.infrastructure.item.ItemStreamReader; import reactor.core.publisher.Flux; @@ -42,30 +42,31 @@ public class ItemStreamFluxReaderAdapter implements ItemStreamReader { * @return an adapted ItemStreamReader * @param a read item type */ - public static ItemStreamReader of(@NonNull ItemStreamFluxReaderDelegate delegate) { + public static ItemStreamReader of(ItemStreamFluxReaderDelegate delegate) { return new ItemStreamFluxReaderAdapter<>(delegate); } + // Prevent the reactive source from advancing beyond the item requested by ItemReader.read(). protected static final int DEFAULT_BATCH_SIZE = 1; protected final ItemStreamFluxReaderDelegate delegate; - protected Flux flux = null; + protected @Nullable Flux flux = null; - protected Iterator iterator = null; + protected @Nullable Iterator iterator = null; protected ItemStreamFluxReaderAdapter(ItemStreamFluxReaderDelegate delegate) { this.delegate = Objects.requireNonNull(delegate, "Delegate reader must not be null"); } @Override - public void open(@NonNull ExecutionContext executionContext) { + public void open(ExecutionContext executionContext) { this.delegate.onOpenRead(executionContext); this.flux = this.delegate.readFlux(executionContext); } @Override - public T read() { + public @Nullable T read() { Iterator iterator = getIterator(); if (iterator.hasNext()) { return iterator.next(); @@ -75,7 +76,7 @@ public T read() { } @Override - public void update(@NonNull ExecutionContext executionContext) { + public void update(ExecutionContext executionContext) { this.delegate.onUpdateRead(executionContext); } diff --git a/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamFluxReaderDelegate.java b/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamFluxReaderDelegate.java index c135796c..7c1822e8 100644 --- a/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamFluxReaderDelegate.java +++ b/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamFluxReaderDelegate.java @@ -18,9 +18,8 @@ package com.navercorp.spring.batch.plus.step.adapter; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.batch.item.ItemStreamReader; -import org.springframework.lang.NonNull; +import org.springframework.batch.infrastructure.item.ExecutionContext; +import org.springframework.batch.infrastructure.item.ItemStreamReader; import reactor.core.publisher.Flux; @@ -36,7 +35,7 @@ public interface ItemStreamFluxReaderDelegate { * * @param executionContext an execution context */ - default void onOpenRead(@NonNull ExecutionContext executionContext) { + default void onOpenRead(ExecutionContext executionContext) { } /** @@ -45,15 +44,14 @@ default void onOpenRead(@NonNull ExecutionContext executionContext) { * @param executionContext an execution context * @return a flux to read item */ - @NonNull - Flux readFlux(@NonNull ExecutionContext executionContext); + Flux readFlux(ExecutionContext executionContext); /** * A delegate method for {@link ItemStreamReader#update(ExecutionContext)}. * * @param executionContext an execution context */ - default void onUpdateRead(@NonNull ExecutionContext executionContext) { + default void onUpdateRead(ExecutionContext executionContext) { } /** diff --git a/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamFluxReaderProcessor.java b/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamFluxReaderProcessor.java index b09d4817..f86cc692 100644 --- a/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamFluxReaderProcessor.java +++ b/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamFluxReaderProcessor.java @@ -18,14 +18,14 @@ package com.navercorp.spring.batch.plus.step.adapter; -import org.springframework.batch.item.ItemProcessor; -import org.springframework.batch.item.ItemStreamReader; +import org.springframework.batch.infrastructure.item.ItemProcessor; +import org.springframework.batch.infrastructure.item.ItemStreamReader; import reactor.core.publisher.Flux; /** - * A {@link Flux} based adapter for stream reader, processor. It can represent - * {@link ItemStreamReader}, {@link ItemProcessor} in a single class. + * Combines the delegate contracts required to adapt one object into an {@link ItemStreamReader} and + * {@link ItemProcessor}, with reader input supplied as a {@link Flux}. * * @since 1.2.0 */ diff --git a/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamFluxReaderProcessorWriter.java b/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamFluxReaderProcessorWriter.java index dc49d933..19c548de 100644 --- a/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamFluxReaderProcessorWriter.java +++ b/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamFluxReaderProcessorWriter.java @@ -18,15 +18,15 @@ package com.navercorp.spring.batch.plus.step.adapter; -import org.springframework.batch.item.ItemProcessor; -import org.springframework.batch.item.ItemStreamReader; -import org.springframework.batch.item.ItemStreamWriter; +import org.springframework.batch.infrastructure.item.ItemProcessor; +import org.springframework.batch.infrastructure.item.ItemStreamReader; +import org.springframework.batch.infrastructure.item.ItemStreamWriter; import reactor.core.publisher.Flux; /** - * A {@link Flux} based adapter for stream reader, processor, writer. It can represent - * {@link ItemStreamReader}, {@link ItemProcessor}, {@link ItemStreamWriter} in a single class. + * Combines the delegate contracts required to adapt one object into an {@link ItemStreamReader}, + * {@link ItemProcessor}, and {@link ItemStreamWriter}, with reader input supplied as a {@link Flux}. * * @since 1.1.0 */ diff --git a/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamFluxReaderWriter.java b/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamFluxReaderWriter.java index 0c964dff..43d408d5 100644 --- a/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamFluxReaderWriter.java +++ b/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamFluxReaderWriter.java @@ -18,14 +18,14 @@ package com.navercorp.spring.batch.plus.step.adapter; -import org.springframework.batch.item.ItemStreamReader; -import org.springframework.batch.item.ItemStreamWriter; +import org.springframework.batch.infrastructure.item.ItemStreamReader; +import org.springframework.batch.infrastructure.item.ItemStreamWriter; import reactor.core.publisher.Flux; /** - * A {@link Flux} based adapter for stream reader, writer. It can represent - * {@link ItemStreamReader}, {@link ItemStreamWriter} in a single class. + * Combines the delegate contracts required to adapt one object into an {@link ItemStreamReader} and + * {@link ItemStreamWriter}, with reader input supplied as a {@link Flux}. * * @since 1.1.0 */ diff --git a/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamIterableReaderAdapter.java b/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamIterableReaderAdapter.java index 253a1f4c..5c687cc1 100644 --- a/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamIterableReaderAdapter.java +++ b/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamIterableReaderAdapter.java @@ -22,9 +22,9 @@ import java.util.Objects; import java.util.Optional; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.batch.item.ItemStreamReader; -import org.springframework.lang.NonNull; +import org.jspecify.annotations.Nullable; +import org.springframework.batch.infrastructure.item.ExecutionContext; +import org.springframework.batch.infrastructure.item.ItemStreamReader; /** * An adapter which adapt {@link ItemStreamIterableReaderDelegate} to {@link ItemStreamReader}. @@ -40,28 +40,28 @@ public class ItemStreamIterableReaderAdapter implements ItemStreamReader { * @return an adapted ItemStreamReader * @param a read item type */ - public static ItemStreamReader of(@NonNull ItemStreamIterableReaderDelegate delegate) { + public static ItemStreamReader of(ItemStreamIterableReaderDelegate delegate) { return new ItemStreamIterableReaderAdapter<>(delegate); } protected final ItemStreamIterableReaderDelegate delegate; - protected Iterable iterable = null; + protected @Nullable Iterable iterable = null; - protected Iterator iterator = null; + protected @Nullable Iterator iterator = null; protected ItemStreamIterableReaderAdapter(ItemStreamIterableReaderDelegate delegate) { this.delegate = Objects.requireNonNull(delegate, "Delegate reader must not be null"); } @Override - public void open(@NonNull ExecutionContext executionContext) { + public void open(ExecutionContext executionContext) { this.delegate.onOpenRead(executionContext); this.iterable = this.delegate.readIterable(executionContext); } @Override - public T read() { + public @Nullable T read() { Iterator iterator = getIterator(); if (iterator.hasNext()) { return iterator.next(); @@ -71,7 +71,7 @@ public T read() { } @Override - public void update(@NonNull ExecutionContext executionContext) { + public void update(ExecutionContext executionContext) { this.delegate.onUpdateRead(executionContext); } diff --git a/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamIterableReaderDelegate.java b/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamIterableReaderDelegate.java index b003905e..ba9d8c34 100644 --- a/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamIterableReaderDelegate.java +++ b/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamIterableReaderDelegate.java @@ -18,9 +18,8 @@ package com.navercorp.spring.batch.plus.step.adapter; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.batch.item.ItemStreamReader; -import org.springframework.lang.NonNull; +import org.springframework.batch.infrastructure.item.ExecutionContext; +import org.springframework.batch.infrastructure.item.ItemStreamReader; /** * A delegate for {@link ItemStreamReader} which uses {@link Iterable}. @@ -34,7 +33,7 @@ public interface ItemStreamIterableReaderDelegate { * * @param executionContext an execution context */ - default void onOpenRead(@NonNull ExecutionContext executionContext) { + default void onOpenRead(ExecutionContext executionContext) { } /** @@ -43,15 +42,14 @@ default void onOpenRead(@NonNull ExecutionContext executionContext) { * @param executionContext an execution context * @return an iterable to read item */ - @NonNull - Iterable readIterable(@NonNull ExecutionContext executionContext); + Iterable readIterable(ExecutionContext executionContext); /** * A delegate method for {@link ItemStreamReader#update(ExecutionContext)}. * * @param executionContext an execution context */ - default void onUpdateRead(@NonNull ExecutionContext executionContext) { + default void onUpdateRead(ExecutionContext executionContext) { } /** diff --git a/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamIterableReaderProcessor.java b/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamIterableReaderProcessor.java index 3dbf1376..fdfc753a 100644 --- a/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamIterableReaderProcessor.java +++ b/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamIterableReaderProcessor.java @@ -18,12 +18,12 @@ package com.navercorp.spring.batch.plus.step.adapter; -import org.springframework.batch.item.ItemProcessor; -import org.springframework.batch.item.ItemStreamReader; +import org.springframework.batch.infrastructure.item.ItemProcessor; +import org.springframework.batch.infrastructure.item.ItemStreamReader; /** - * An {@link Iterable} based adapter for stream reader, processor. It can represent - * {@link ItemStreamReader}, {@link ItemProcessor} in a single class. + * Combines the delegate contracts required to adapt one object into an {@link ItemStreamReader} and + * {@link ItemProcessor}, with reader input supplied as an {@link Iterable}. * * @since 1.2.0 */ diff --git a/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamIterableReaderProcessorWriter.java b/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamIterableReaderProcessorWriter.java index 6f01e261..5bb91fdf 100644 --- a/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamIterableReaderProcessorWriter.java +++ b/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamIterableReaderProcessorWriter.java @@ -18,13 +18,13 @@ package com.navercorp.spring.batch.plus.step.adapter; -import org.springframework.batch.item.ItemProcessor; -import org.springframework.batch.item.ItemStreamReader; -import org.springframework.batch.item.ItemStreamWriter; +import org.springframework.batch.infrastructure.item.ItemProcessor; +import org.springframework.batch.infrastructure.item.ItemStreamReader; +import org.springframework.batch.infrastructure.item.ItemStreamWriter; /** - * An {@link Iterable} based adapter for stream reader, processor, writer. It can represent - * {@link ItemStreamReader}, {@link ItemProcessor}, {@link ItemStreamWriter} in a single class. + * Combines the delegate contracts required to adapt one object into an {@link ItemStreamReader}, + * {@link ItemProcessor}, and {@link ItemStreamWriter}, with reader input supplied as an {@link Iterable}. * * @since 1.1.0 */ diff --git a/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamIterableReaderWriter.java b/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamIterableReaderWriter.java index 5bd932e5..07da0f61 100644 --- a/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamIterableReaderWriter.java +++ b/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamIterableReaderWriter.java @@ -18,12 +18,12 @@ package com.navercorp.spring.batch.plus.step.adapter; -import org.springframework.batch.item.ItemStreamReader; -import org.springframework.batch.item.ItemStreamWriter; +import org.springframework.batch.infrastructure.item.ItemStreamReader; +import org.springframework.batch.infrastructure.item.ItemStreamWriter; /** - * An {@link Iterable} based adapter for stream reader, writer. It can represent - * {@link ItemStreamReader}, {@link ItemStreamWriter} in a single class. + * Combines the delegate contracts required to adapt one object into an {@link ItemStreamReader} and + * {@link ItemStreamWriter}, with reader input supplied as an {@link Iterable}. * * @since 1.1.0 */ diff --git a/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamIteratorReaderAdapter.java b/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamIteratorReaderAdapter.java index 803f9f86..43283c33 100644 --- a/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamIteratorReaderAdapter.java +++ b/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamIteratorReaderAdapter.java @@ -21,9 +21,9 @@ import java.util.Iterator; import java.util.Objects; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.batch.item.ItemStreamReader; -import org.springframework.lang.NonNull; +import org.jspecify.annotations.Nullable; +import org.springframework.batch.infrastructure.item.ExecutionContext; +import org.springframework.batch.infrastructure.item.ItemStreamReader; /** * An adapter which adapt {@link ItemStreamIteratorReaderDelegate} to {@link ItemStreamReader}. @@ -39,26 +39,26 @@ public class ItemStreamIteratorReaderAdapter implements ItemStreamReader { * @return an adapted ItemStreamReader * @param a read item type */ - public static ItemStreamReader of(@NonNull ItemStreamIteratorReaderDelegate delegate) { + public static ItemStreamReader of(ItemStreamIteratorReaderDelegate delegate) { return new ItemStreamIteratorReaderAdapter<>(delegate); } protected final ItemStreamIteratorReaderDelegate delegate; - protected Iterator iterator = null; + protected @Nullable Iterator iterator = null; protected ItemStreamIteratorReaderAdapter(ItemStreamIteratorReaderDelegate delegate) { this.delegate = Objects.requireNonNull(delegate, "Delegate reader must not be null"); } @Override - public void open(@NonNull ExecutionContext executionContext) { + public void open(ExecutionContext executionContext) { this.delegate.onOpenRead(executionContext); this.iterator = this.delegate.readIterator(executionContext); } @Override - public T read() { + public @Nullable T read() { Iterator iterator = getIterator(); if (iterator.hasNext()) { return iterator.next(); @@ -68,7 +68,7 @@ public T read() { } @Override - public void update(@NonNull ExecutionContext executionContext) { + public void update(ExecutionContext executionContext) { this.delegate.onUpdateRead(executionContext); } diff --git a/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamIteratorReaderDelegate.java b/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamIteratorReaderDelegate.java index 056a8ccb..6c2eec4f 100644 --- a/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamIteratorReaderDelegate.java +++ b/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamIteratorReaderDelegate.java @@ -20,9 +20,8 @@ import java.util.Iterator; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.batch.item.ItemStreamReader; -import org.springframework.lang.NonNull; +import org.springframework.batch.infrastructure.item.ExecutionContext; +import org.springframework.batch.infrastructure.item.ItemStreamReader; /** * A delegate for {@link ItemStreamReader} which uses {@link Iterator}. @@ -36,7 +35,7 @@ public interface ItemStreamIteratorReaderDelegate { * * @param executionContext an execution context */ - default void onOpenRead(@NonNull ExecutionContext executionContext) { + default void onOpenRead(ExecutionContext executionContext) { } /** @@ -45,15 +44,14 @@ default void onOpenRead(@NonNull ExecutionContext executionContext) { * @param executionContext an execution context * @return an iterator to read item */ - @NonNull - Iterator readIterator(@NonNull ExecutionContext executionContext); + Iterator readIterator(ExecutionContext executionContext); /** * A delegate method for {@link ItemStreamReader#update(ExecutionContext)}. * * @param executionContext an execution context */ - default void onUpdateRead(@NonNull ExecutionContext executionContext) { + default void onUpdateRead(ExecutionContext executionContext) { } /** diff --git a/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamIteratorReaderProcessor.java b/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamIteratorReaderProcessor.java index c64969c5..bc011c22 100644 --- a/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamIteratorReaderProcessor.java +++ b/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamIteratorReaderProcessor.java @@ -20,12 +20,12 @@ import java.util.Iterator; -import org.springframework.batch.item.ItemProcessor; -import org.springframework.batch.item.ItemStreamReader; +import org.springframework.batch.infrastructure.item.ItemProcessor; +import org.springframework.batch.infrastructure.item.ItemStreamReader; /** - * An {@link Iterator} based adapter for stream reader, processor. It can represent - * {@link ItemStreamReader}, {@link ItemProcessor} in a single class. + * Combines the delegate contracts required to adapt one object into an {@link ItemStreamReader} and + * {@link ItemProcessor}, with reader input supplied as an {@link Iterator}. * * @since 1.2.0 */ diff --git a/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamIteratorReaderProcessorWriter.java b/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamIteratorReaderProcessorWriter.java index f03e7e1d..b9c63e4c 100644 --- a/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamIteratorReaderProcessorWriter.java +++ b/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamIteratorReaderProcessorWriter.java @@ -20,13 +20,13 @@ import java.util.Iterator; -import org.springframework.batch.item.ItemProcessor; -import org.springframework.batch.item.ItemStreamReader; -import org.springframework.batch.item.ItemStreamWriter; +import org.springframework.batch.infrastructure.item.ItemProcessor; +import org.springframework.batch.infrastructure.item.ItemStreamReader; +import org.springframework.batch.infrastructure.item.ItemStreamWriter; /** - * An {@link Iterator} based adapter for stream reader, processor, writer. It can represent - * {@link ItemStreamReader}, {@link ItemProcessor}, {@link ItemStreamWriter} in a single class. + * Combines the delegate contracts required to adapt one object into an {@link ItemStreamReader}, + * {@link ItemProcessor}, and {@link ItemStreamWriter}, with reader input supplied as an {@link Iterator}. * * @since 1.1.0 */ diff --git a/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamIteratorReaderWriter.java b/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamIteratorReaderWriter.java index 8d383a05..fbb70963 100644 --- a/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamIteratorReaderWriter.java +++ b/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamIteratorReaderWriter.java @@ -20,12 +20,12 @@ import java.util.Iterator; -import org.springframework.batch.item.ItemStreamReader; -import org.springframework.batch.item.ItemStreamWriter; +import org.springframework.batch.infrastructure.item.ItemStreamReader; +import org.springframework.batch.infrastructure.item.ItemStreamWriter; /** - * An {@link Iterator} based adapter for stream reader, writer. It can represent - * {@link ItemStreamReader}, {@link ItemStreamWriter} in a single class. + * Combines the delegate contracts required to adapt one object into an {@link ItemStreamReader} and + * {@link ItemStreamWriter}, with reader input supplied as an {@link Iterator}. * * @since 1.1.0 */ diff --git a/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamSimpleReaderAdapter.java b/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamSimpleReaderAdapter.java index b3378d33..2f0ec7ae 100644 --- a/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamSimpleReaderAdapter.java +++ b/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamSimpleReaderAdapter.java @@ -20,9 +20,9 @@ import java.util.Objects; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.batch.item.ItemStreamReader; -import org.springframework.lang.NonNull; +import org.jspecify.annotations.Nullable; +import org.springframework.batch.infrastructure.item.ExecutionContext; +import org.springframework.batch.infrastructure.item.ItemStreamReader; /** * An adapter which adapt {@link ItemStreamSimpleReaderDelegate} to {@link ItemStreamReader}. @@ -38,7 +38,7 @@ public class ItemStreamSimpleReaderAdapter implements ItemStreamReader { * @return an adapted ItemStreamReader * @param a read item type */ - public static ItemStreamReader of(@NonNull ItemStreamSimpleReaderDelegate delegate) { + public static ItemStreamReader of(ItemStreamSimpleReaderDelegate delegate) { return new ItemStreamSimpleReaderAdapter<>(delegate); } @@ -49,17 +49,17 @@ protected ItemStreamSimpleReaderAdapter(ItemStreamSimpleReaderDelegate delega } @Override - public void open(@NonNull ExecutionContext executionContext) { + public void open(ExecutionContext executionContext) { this.delegate.onOpenRead(executionContext); } @Override - public T read() { + public @Nullable T read() { return this.delegate.read(); } @Override - public void update(@NonNull ExecutionContext executionContext) { + public void update(ExecutionContext executionContext) { this.delegate.onUpdateRead(executionContext); } diff --git a/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamSimpleReaderDelegate.java b/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamSimpleReaderDelegate.java index 92727bbf..06a402cd 100644 --- a/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamSimpleReaderDelegate.java +++ b/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamSimpleReaderDelegate.java @@ -18,10 +18,9 @@ package com.navercorp.spring.batch.plus.step.adapter; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.batch.item.ItemStreamReader; -import org.springframework.lang.NonNull; -import org.springframework.lang.Nullable; +import org.jspecify.annotations.Nullable; +import org.springframework.batch.infrastructure.item.ExecutionContext; +import org.springframework.batch.infrastructure.item.ItemStreamReader; /** * A simple delegate for {@link ItemStreamReader}. @@ -35,23 +34,22 @@ public interface ItemStreamSimpleReaderDelegate { * * @param executionContext an execution context */ - default void onOpenRead(@NonNull ExecutionContext executionContext) { + default void onOpenRead(ExecutionContext executionContext) { } /** * Read each item. * @return an item to read. null if it's end of data. - * Return contract is same as {@link org.springframework.batch.item.ItemReader} + * Return contract is same as {@link org.springframework.batch.infrastructure.item.ItemReader} */ - @Nullable - T read(); + @Nullable T read(); /** * A delegate method for {@link ItemStreamReader#update(ExecutionContext)}. * * @param executionContext an execution context */ - default void onUpdateRead(@NonNull ExecutionContext executionContext) { + default void onUpdateRead(ExecutionContext executionContext) { } /** diff --git a/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamSimpleReaderProcessor.java b/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamSimpleReaderProcessor.java index c0f94619..f3b18b9a 100644 --- a/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamSimpleReaderProcessor.java +++ b/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamSimpleReaderProcessor.java @@ -18,12 +18,12 @@ package com.navercorp.spring.batch.plus.step.adapter; -import org.springframework.batch.item.ItemProcessor; -import org.springframework.batch.item.ItemStreamReader; +import org.springframework.batch.infrastructure.item.ItemProcessor; +import org.springframework.batch.infrastructure.item.ItemStreamReader; /** - * An item ({@link I}) based adapter for stream reader, processor. It can represent - * {@link ItemStreamReader}, {@link ItemProcessor} in a single class. + * Combines the delegate contracts required to adapt one object into an {@link ItemStreamReader} and + * {@link ItemProcessor}, with the reader supplying one item per call. * * @since 1.2.0 */ diff --git a/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamSimpleReaderProcessorWriter.java b/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamSimpleReaderProcessorWriter.java index 4523bba3..7ae9aa6a 100644 --- a/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamSimpleReaderProcessorWriter.java +++ b/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamSimpleReaderProcessorWriter.java @@ -18,13 +18,13 @@ package com.navercorp.spring.batch.plus.step.adapter; -import org.springframework.batch.item.ItemProcessor; -import org.springframework.batch.item.ItemStreamReader; -import org.springframework.batch.item.ItemStreamWriter; +import org.springframework.batch.infrastructure.item.ItemProcessor; +import org.springframework.batch.infrastructure.item.ItemStreamReader; +import org.springframework.batch.infrastructure.item.ItemStreamWriter; /** - * An item ({@link I}) based adapter for stream reader, processor, writer. It can represent - * {@link ItemStreamReader}, {@link ItemProcessor}, {@link ItemStreamWriter} in a single class. + * Combines the delegate contracts required to adapt one object into an {@link ItemStreamReader}, + * {@link ItemProcessor}, and {@link ItemStreamWriter}, with the reader supplying one item per call. * * @since 1.1.0 */ diff --git a/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamSimpleReaderWriter.java b/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamSimpleReaderWriter.java index 3dc0916b..5c7ea969 100644 --- a/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamSimpleReaderWriter.java +++ b/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamSimpleReaderWriter.java @@ -18,12 +18,12 @@ package com.navercorp.spring.batch.plus.step.adapter; -import org.springframework.batch.item.ItemStreamReader; -import org.springframework.batch.item.ItemStreamWriter; +import org.springframework.batch.infrastructure.item.ItemStreamReader; +import org.springframework.batch.infrastructure.item.ItemStreamWriter; /** - * An item ({@link T}) based adapter for stream reader, writer. It can represent - * {@link ItemStreamReader}, {@link ItemStreamWriter} in a single class. + * Combines the delegate contracts required to adapt one object into an {@link ItemStreamReader} and + * {@link ItemStreamWriter}, with the reader supplying one item per call. * * @since 1.1.0 */ diff --git a/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamWriterAdapter.java b/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamWriterAdapter.java index 89e72bc5..50e0c9fe 100644 --- a/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamWriterAdapter.java +++ b/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamWriterAdapter.java @@ -20,10 +20,9 @@ import java.util.Objects; -import org.springframework.batch.item.Chunk; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.batch.item.ItemStreamWriter; -import org.springframework.lang.NonNull; +import org.springframework.batch.infrastructure.item.Chunk; +import org.springframework.batch.infrastructure.item.ExecutionContext; +import org.springframework.batch.infrastructure.item.ItemStreamWriter; /** * An adapter which adapt {@link ItemStreamWriterDelegate} to {@link ItemStreamWriter}. @@ -39,7 +38,7 @@ public class ItemStreamWriterAdapter implements ItemStreamWriter { * @return an adapted ItemStreamWriter * @param an item type to write */ - public static ItemStreamWriter of(@NonNull ItemStreamWriterDelegate delegate) { + public static ItemStreamWriter of(ItemStreamWriterDelegate delegate) { return new ItemStreamWriterAdapter<>(delegate); } @@ -50,17 +49,17 @@ protected ItemStreamWriterAdapter(ItemStreamWriterDelegate delegate) { } @Override - public void open(@NonNull ExecutionContext executionContext) { + public void open(ExecutionContext executionContext) { this.delegate.onOpenWrite(executionContext); } @Override - public void write(@NonNull Chunk chunk) { + public void write(Chunk chunk) { this.delegate.write(chunk); } @Override - public void update(@NonNull ExecutionContext executionContext) { + public void update(ExecutionContext executionContext) { this.delegate.onUpdateWrite(executionContext); } diff --git a/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamWriterDelegate.java b/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamWriterDelegate.java index 12880bed..27fa4cb4 100644 --- a/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamWriterDelegate.java +++ b/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamWriterDelegate.java @@ -18,10 +18,9 @@ package com.navercorp.spring.batch.plus.step.adapter; -import org.springframework.batch.item.Chunk; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.batch.item.ItemStreamWriter; -import org.springframework.lang.NonNull; +import org.springframework.batch.infrastructure.item.Chunk; +import org.springframework.batch.infrastructure.item.ExecutionContext; +import org.springframework.batch.infrastructure.item.ItemStreamWriter; /** * A delegate for {@link ItemStreamWriter}. @@ -34,20 +33,20 @@ public interface ItemStreamWriterDelegate { * A delegate method for {@link ItemStreamWriter#open(ExecutionContext)}. * @param executionContext an execution context */ - default void onOpenWrite(@NonNull ExecutionContext executionContext) { + default void onOpenWrite(ExecutionContext executionContext) { } /** * A delegate method for {@link ItemStreamWriter#write(Chunk)}. * @param chunk chunk to write */ - void write(@NonNull Chunk chunk); + void write(Chunk chunk); /** * A delegate method for {@link ItemStreamWriter#update(ExecutionContext)}. * @param executionContext an execution context */ - default void onUpdateWrite(@NonNull ExecutionContext executionContext) { + default void onUpdateWrite(ExecutionContext executionContext) { } /** diff --git a/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/StepScopeItemStreamReader.java b/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/StepScopeItemStreamReader.java index b50c31b8..c4a666da 100644 --- a/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/StepScopeItemStreamReader.java +++ b/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/StepScopeItemStreamReader.java @@ -23,14 +23,14 @@ import java.util.Objects; import java.util.function.Supplier; +import org.jspecify.annotations.Nullable; import org.slf4j.Logger; import org.springframework.batch.core.scope.StepScope; import org.springframework.batch.core.scope.context.StepContext; import org.springframework.batch.core.scope.context.StepSynchronizationManager; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.batch.item.ItemStreamException; -import org.springframework.batch.item.ItemStreamReader; -import org.springframework.lang.NonNull; +import org.springframework.batch.infrastructure.item.ExecutionContext; +import org.springframework.batch.infrastructure.item.ItemStreamException; +import org.springframework.batch.infrastructure.item.ItemStreamReader; /** * A {@link StepScope} bound proxy implementation. @@ -38,6 +38,9 @@ * @since 1.1.0 */ public class StepScopeItemStreamReader implements ItemStreamReader { + protected static final Logger logger = getLogger(StepScopeItemStreamReader.class); + + protected static final String SCOPE_KEY = "StepScopeItemStreamReader@delegate"; /** * Create an {@link ItemStreamReader} instance bound to {@link StepScope}. @@ -51,10 +54,6 @@ public static ItemStreamReader of(Supplier> delegateS return new StepScopeItemStreamReader<>(delegateSupplier); } - protected static final String SCOPE_KEY = "StepScopeItemStreamReader@delegate"; - - protected final Logger logger = getLogger(StepScopeItemStreamReader.class); - protected final Supplier> delegateSupplier; protected StepScopeItemStreamReader(Supplier> readerGenerator) { @@ -62,17 +61,17 @@ protected StepScopeItemStreamReader(Supplier> readerGenerato } @Override - public void open(@NonNull ExecutionContext executionContext) throws ItemStreamException { + public void open(ExecutionContext executionContext) throws ItemStreamException { getDelegate().open(executionContext); } @Override - public T read() throws Exception { + public @Nullable T read() throws Exception { return getDelegate().read(); } @Override - public void update(@NonNull ExecutionContext executionContext) throws ItemStreamException { + public void update(ExecutionContext executionContext) throws ItemStreamException { getDelegate().update(executionContext); } diff --git a/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/package-info.java b/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/package-info.java index 66df9240..772c5ea7 100644 --- a/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/package-info.java +++ b/spring-batch-plus/src/main/java/com/navercorp/spring/batch/plus/step/adapter/package-info.java @@ -19,4 +19,7 @@ /** * An extensions for spring batch step adapter concerns. */ +@NullMarked package com.navercorp.spring.batch.plus.step.adapter; + +import org.jspecify.annotations.NullMarked; diff --git a/spring-batch-plus/src/test/java/com/navercorp/spring/batch/plus/item/adapter/AdapterFactoryTest.java b/spring-batch-plus/src/test/java/com/navercorp/spring/batch/plus/item/adapter/AdapterFactoryTest.java index 85be5db0..08f59537 100644 --- a/spring-batch-plus/src/test/java/com/navercorp/spring/batch/plus/item/adapter/AdapterFactoryTest.java +++ b/spring-batch-plus/src/test/java/com/navercorp/spring/batch/plus/item/adapter/AdapterFactoryTest.java @@ -22,9 +22,9 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; import org.junit.jupiter.api.Test; -import org.springframework.batch.item.ItemProcessor; -import org.springframework.batch.item.ItemStreamReader; -import org.springframework.batch.item.ItemStreamWriter; +import org.springframework.batch.infrastructure.item.ItemProcessor; +import org.springframework.batch.infrastructure.item.ItemStreamReader; +import org.springframework.batch.infrastructure.item.ItemStreamWriter; import reactor.core.publisher.Flux; diff --git a/spring-batch-plus/src/test/java/com/navercorp/spring/batch/plus/item/adapter/ItemProcessorAdapterTest.java b/spring-batch-plus/src/test/java/com/navercorp/spring/batch/plus/item/adapter/ItemProcessorAdapterTest.java index 2dc64e0d..71f5a1d8 100644 --- a/spring-batch-plus/src/test/java/com/navercorp/spring/batch/plus/item/adapter/ItemProcessorAdapterTest.java +++ b/spring-batch-plus/src/test/java/com/navercorp/spring/batch/plus/item/adapter/ItemProcessorAdapterTest.java @@ -27,7 +27,7 @@ import java.util.concurrent.ThreadLocalRandom; import org.junit.jupiter.api.Test; -import org.springframework.batch.item.ItemProcessor; +import org.springframework.batch.infrastructure.item.ItemProcessor; // note: it's deprecated. Do not change it. @SuppressWarnings({"unchecked", "deprecation"}) diff --git a/spring-batch-plus/src/test/java/com/navercorp/spring/batch/plus/item/adapter/ItemStreamReaderAdapterTest.java b/spring-batch-plus/src/test/java/com/navercorp/spring/batch/plus/item/adapter/ItemStreamReaderAdapterTest.java index 3fd76852..36addb63 100644 --- a/spring-batch-plus/src/test/java/com/navercorp/spring/batch/plus/item/adapter/ItemStreamReaderAdapterTest.java +++ b/spring-batch-plus/src/test/java/com/navercorp/spring/batch/plus/item/adapter/ItemStreamReaderAdapterTest.java @@ -30,8 +30,8 @@ import java.util.List; import org.junit.jupiter.api.Test; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.batch.item.ItemStreamReader; +import org.springframework.batch.infrastructure.item.ExecutionContext; +import org.springframework.batch.infrastructure.item.ItemStreamReader; import reactor.core.publisher.Flux; diff --git a/spring-batch-plus/src/test/java/com/navercorp/spring/batch/plus/item/adapter/ItemStreamWriterAdapterTest.java b/spring-batch-plus/src/test/java/com/navercorp/spring/batch/plus/item/adapter/ItemStreamWriterAdapterTest.java index 90392b9c..04672def 100644 --- a/spring-batch-plus/src/test/java/com/navercorp/spring/batch/plus/item/adapter/ItemStreamWriterAdapterTest.java +++ b/spring-batch-plus/src/test/java/com/navercorp/spring/batch/plus/item/adapter/ItemStreamWriterAdapterTest.java @@ -25,9 +25,9 @@ import static org.mockito.Mockito.verify; import org.junit.jupiter.api.Test; -import org.springframework.batch.item.Chunk; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.batch.item.ItemStreamWriter; +import org.springframework.batch.infrastructure.item.Chunk; +import org.springframework.batch.infrastructure.item.ExecutionContext; +import org.springframework.batch.infrastructure.item.ItemStreamWriter; // note: it's deprecated. Do not change it. @SuppressWarnings({"unchecked", "deprecation"}) diff --git a/spring-batch-plus/src/test/java/com/navercorp/spring/batch/plus/item/adapter/StepScopeItemStreamReaderTest.java b/spring-batch-plus/src/test/java/com/navercorp/spring/batch/plus/item/adapter/StepScopeItemStreamReaderTest.java index cb6cd789..8a8e67b8 100644 --- a/spring-batch-plus/src/test/java/com/navercorp/spring/batch/plus/item/adapter/StepScopeItemStreamReaderTest.java +++ b/spring-batch-plus/src/test/java/com/navercorp/spring/batch/plus/item/adapter/StepScopeItemStreamReaderTest.java @@ -29,9 +29,9 @@ import java.util.concurrent.ThreadLocalRandom; import org.junit.jupiter.api.Test; -import org.springframework.batch.core.StepExecution; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.batch.item.ItemStreamReader; +import org.springframework.batch.core.step.StepExecution; +import org.springframework.batch.infrastructure.item.ExecutionContext; +import org.springframework.batch.infrastructure.item.ItemStreamReader; import org.springframework.batch.test.MetaDataInstanceFactory; import org.springframework.batch.test.StepScopeTestUtils; diff --git a/spring-batch-plus/src/test/java/com/navercorp/spring/batch/plus/job/ClearRunIdIncrementerTest.java b/spring-batch-plus/src/test/java/com/navercorp/spring/batch/plus/job/ClearRunIdIncrementerTest.java index 07cc0a0d..1ff54546 100644 --- a/spring-batch-plus/src/test/java/com/navercorp/spring/batch/plus/job/ClearRunIdIncrementerTest.java +++ b/spring-batch-plus/src/test/java/com/navercorp/spring/batch/plus/job/ClearRunIdIncrementerTest.java @@ -18,21 +18,23 @@ package com.navercorp.spring.batch.plus.job; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.assertj.core.api.Assertions.*; import java.util.UUID; import java.util.concurrent.ThreadLocalRandom; import org.junit.jupiter.api.Test; -import org.springframework.batch.core.JobParameters; -import org.springframework.batch.core.JobParametersBuilder; -import org.springframework.batch.core.JobParametersIncrementer; +import org.springframework.batch.core.job.parameters.JobParameters; +import org.springframework.batch.core.job.parameters.JobParametersBuilder; +import org.springframework.batch.core.job.parameters.JobParametersIncrementer; +/** + * Covers the parameter transformation contract independently of Spring Batch job execution. + */ class ClearRunIdIncrementerTest { @Test - void getNextShouldReturnOneWhenNoPreviousValue() { + void getNextShouldInitializeRunIdToOneWhenPreviousValueDoesNotExist() { JobParametersIncrementer clearRunIdIncrementer = ClearRunIdIncrementer.create(); JobParameters jobParameters = clearRunIdIncrementer.getNext(new JobParameters()); @@ -41,7 +43,7 @@ void getNextShouldReturnOneWhenNoPreviousValue() { } @Test - void getNextShouldReturnPlusOneWhenPreviousExists() { + void getNextShouldIncrementRunIdWhenPreviousValueExists() { JobParametersIncrementer clearRunIdIncrementer = ClearRunIdIncrementer.create(); long previousId = ThreadLocalRandom.current().nextLong(); @@ -54,7 +56,7 @@ void getNextShouldReturnPlusOneWhenPreviousExists() { } @Test - void getNextShouldReturnPlusOneWhenPreviousExistsUsingCustomRunId() { + void getNextShouldUseConfiguredRunIdParameterName() { String runId = UUID.randomUUID().toString(); JobParametersIncrementer clearRunIdIncrementer = ClearRunIdIncrementer.create(runId); @@ -70,7 +72,7 @@ void getNextShouldReturnPlusOneWhenPreviousExistsUsingCustomRunId() { @SuppressWarnings("DataFlowIssue") @Test - void createShouldThrowExceptionWhenPassingNull() { + void createShouldThrowExceptionWhenRunIdParameterNameIsNull() { assertThatThrownBy(() -> ClearRunIdIncrementer.create(null)); } } diff --git a/spring-batch-plus/src/test/java/com/navercorp/spring/batch/plus/job/metadata/CheckMaxJobInstanceIdToDeleteTaskletTest.java b/spring-batch-plus/src/test/java/com/navercorp/spring/batch/plus/job/metadata/CheckMaxJobInstanceIdToDeleteTaskletTest.java index 34513d5c..e02a7d4f 100644 --- a/spring-batch-plus/src/test/java/com/navercorp/spring/batch/plus/job/metadata/CheckMaxJobInstanceIdToDeleteTaskletTest.java +++ b/spring-batch-plus/src/test/java/com/navercorp/spring/batch/plus/job/metadata/CheckMaxJobInstanceIdToDeleteTaskletTest.java @@ -20,6 +20,8 @@ import static com.navercorp.spring.batch.plus.job.metadata.CheckMaxJobInstanceIdToDeleteTasklet.MAX_ID_KEY; import static com.navercorp.spring.batch.plus.job.metadata.MetadataTestSupports.buildJobParams; +import static com.navercorp.spring.batch.plus.job.metadata.MetadataTestSupports.createJobExecution; +import static com.navercorp.spring.batch.plus.job.metadata.MetadataTestSupports.createStepExecution; import static com.navercorp.spring.batch.plus.job.metadata.MetadataTestSupports.dateFrom; import static com.navercorp.spring.batch.plus.job.metadata.MetadataTestSupports.dateTo; import static org.assertj.core.api.Assertions.assertThat; @@ -29,16 +31,16 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.batch.core.ExitStatus; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.JobParameters; -import org.springframework.batch.core.JobParametersBuilder; -import org.springframework.batch.core.StepContribution; -import org.springframework.batch.core.StepExecution; +import org.springframework.batch.core.job.JobExecution; +import org.springframework.batch.core.job.parameters.JobParameters; +import org.springframework.batch.core.job.parameters.JobParametersBuilder; import org.springframework.batch.core.repository.JobRepository; import org.springframework.batch.core.scope.context.ChunkContext; import org.springframework.batch.core.scope.context.StepContext; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.batch.repeat.RepeatStatus; +import org.springframework.batch.core.step.StepContribution; +import org.springframework.batch.core.step.StepExecution; +import org.springframework.batch.infrastructure.item.ExecutionContext; +import org.springframework.batch.infrastructure.repeat.RepeatStatus; import org.springframework.batch.test.JobRepositoryTestUtils; import org.springframework.batch.test.MetaDataInstanceFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -81,11 +83,11 @@ void testExecuteWhenNoMetadata() { @Test void testExecuteWhenNeedToDelete() throws Exception { // given - JobExecution execution1 = jobRepository.createJobExecution("testJob1", buildJobParams()); + JobExecution execution1 = createJobExecution(jobRepository, "testJob1", buildJobParams()); execution1.setCreateTime(dateTo(2022, 3, 14)); jobRepository.update(execution1); - JobExecution execution2 = jobRepository.createJobExecution("testJob2", buildJobParams()); + JobExecution execution2 = createJobExecution(jobRepository, "testJob2", buildJobParams()); execution2.setCreateTime(dateFrom(2022, 3, 15)); jobRepository.update(execution2); @@ -105,13 +107,13 @@ void testExecuteWhenNeedToDelete() throws Exception { assertThat(exitStatus).isEqualTo(ExitStatus.COMPLETED); ExecutionContext jobExecutionContext = stepExecution.getJobExecution().getExecutionContext(); long maxJobInstanceId = jobExecutionContext.getLong(MAX_ID_KEY); - assertThat(maxJobInstanceId).isEqualTo(execution1.getJobId()); + assertThat(maxJobInstanceId).isEqualTo(execution1.getJobInstanceId()); } @Test void testExecuteWhenNoNeedToDelete() throws Exception { // given - JobExecution execution = jobRepository.createJobExecution("testJob2", buildJobParams()); + JobExecution execution = createJobExecution(jobRepository, "testJob2", buildJobParams()); execution.setCreateTime(dateFrom(2022, 2, 15)); jobRepository.update(execution); diff --git a/spring-batch-plus/src/test/java/com/navercorp/spring/batch/plus/job/metadata/DeleteMetadataJobBuilderTest.java b/spring-batch-plus/src/test/java/com/navercorp/spring/batch/plus/job/metadata/DeleteMetadataJobBuilderTest.java index 20bc07b5..bd65f54a 100644 --- a/spring-batch-plus/src/test/java/com/navercorp/spring/batch/plus/job/metadata/DeleteMetadataJobBuilderTest.java +++ b/spring-batch-plus/src/test/java/com/navercorp/spring/batch/plus/job/metadata/DeleteMetadataJobBuilderTest.java @@ -18,6 +18,7 @@ package com.navercorp.spring.batch.plus.job.metadata; +import static com.navercorp.spring.batch.plus.job.metadata.MetadataTestSupports.createJobExecution; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; @@ -28,10 +29,10 @@ import org.junit.jupiter.api.Test; import org.springframework.batch.core.BatchStatus; -import org.springframework.batch.core.Job; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.JobParameters; -import org.springframework.batch.core.JobParametersBuilder; +import org.springframework.batch.core.job.Job; +import org.springframework.batch.core.job.JobExecution; +import org.springframework.batch.core.job.parameters.JobParameters; +import org.springframework.batch.core.job.parameters.JobParametersBuilder; import org.springframework.batch.core.repository.JobRepository; import org.springframework.jdbc.BadSqlGrammarException; @@ -51,7 +52,7 @@ void testBuildAndExecuteJobWithDefaults() throws Exception { .toJobParameters(); Job job = new DeleteMetadataJobBuilder(jobRepository, dataSource).build(); - JobExecution jobExecution = jobRepository.createJobExecution("deleteMetadataJob", jobParams); + JobExecution jobExecution = createJobExecution(jobRepository, "deleteMetadataJob", jobParams); job.execute(jobExecution); // then @@ -76,7 +77,7 @@ void testBuildAndExecuteJobWithCustomTablePrefix() throws Exception { .addString("baseDate", "2022/03/14") .toJobParameters(); - JobExecution jobExecution = jobRepository.createJobExecution("testJob", jobParams); + JobExecution jobExecution = createJobExecution(jobRepository, "testJob", jobParams); job.execute(jobExecution); // then @@ -102,7 +103,7 @@ void testBuildAndExecuteJobWithCustomBaseDateParameterName() throws Exception { .addString(baseDateParameterName, "2022/03/14") .toJobParameters(); - JobExecution jobExecution = jobRepository.createJobExecution("testJob", jobParams); + JobExecution jobExecution = createJobExecution(jobRepository, "testJob", jobParams); job.execute(jobExecution); // then @@ -128,7 +129,7 @@ void testBuildAndExecuteJobWithCustomFormatter() throws Exception { .addString("baseDate", "2022-03-14") .toJobParameters(); - JobExecution jobExecution = jobRepository.createJobExecution("testJob", jobParams); + JobExecution jobExecution = createJobExecution(jobRepository, "testJob", jobParams); job.execute(jobExecution); // then @@ -155,7 +156,7 @@ void testBuildAndExecuteJobWithCustomDryRun() throws Exception { .addString(dryRunParameterName, "true") .toJobParameters(); - JobExecution jobExecution = jobRepository.createJobExecution("testJob", jobParams); + JobExecution jobExecution = createJobExecution(jobRepository, "testJob", jobParams); job.execute(jobExecution); // then @@ -179,7 +180,7 @@ void testBuildAndExecuteJobWithWrongTablePrefix() throws Exception { .tablePrefix("WRONG_") .build(); - JobExecution jobExecution = jobRepository.createJobExecution("testJob", jobParams); + JobExecution jobExecution = createJobExecution(jobRepository, "testJob", jobParams); job.execute(jobExecution); // then diff --git a/spring-batch-plus/src/test/java/com/navercorp/spring/batch/plus/job/metadata/DeleteMetadataJobTest.java b/spring-batch-plus/src/test/java/com/navercorp/spring/batch/plus/job/metadata/DeleteMetadataJobTest.java index 7c19b89f..b82a25bd 100644 --- a/spring-batch-plus/src/test/java/com/navercorp/spring/batch/plus/job/metadata/DeleteMetadataJobTest.java +++ b/spring-batch-plus/src/test/java/com/navercorp/spring/batch/plus/job/metadata/DeleteMetadataJobTest.java @@ -19,6 +19,8 @@ package com.navercorp.spring.batch.plus.job.metadata; import static com.navercorp.spring.batch.plus.job.metadata.MetadataTestSupports.buildJobParams; +import static com.navercorp.spring.batch.plus.job.metadata.MetadataTestSupports.createJobExecution; +import static com.navercorp.spring.batch.plus.job.metadata.MetadataTestSupports.createStepExecution; import static com.navercorp.spring.batch.plus.job.metadata.MetadataTestSupports.dateFrom; import static com.navercorp.spring.batch.plus.job.metadata.MetadataTestSupports.dateTo; import static com.navercorp.spring.batch.plus.job.metadata.MetadataTestSupports.randomBetween; @@ -30,16 +32,15 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.batch.core.ExitStatus; -import org.springframework.batch.core.Job; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.JobParameters; -import org.springframework.batch.core.JobParametersBuilder; -import org.springframework.batch.core.JobParametersInvalidException; -import org.springframework.batch.core.StepExecution; -import org.springframework.batch.core.launch.JobLauncher; -import org.springframework.batch.core.launch.support.TaskExecutorJobLauncher; +import org.springframework.batch.core.job.Job; +import org.springframework.batch.core.job.JobExecution; +import org.springframework.batch.core.job.JobInstance; +import org.springframework.batch.core.job.parameters.InvalidJobParametersException; +import org.springframework.batch.core.job.parameters.JobParameters; +import org.springframework.batch.core.job.parameters.JobParametersBuilder; +import org.springframework.batch.core.launch.JobOperator; +import org.springframework.batch.core.launch.support.TaskExecutorJobOperator; import org.springframework.batch.core.repository.JobRepository; -import org.springframework.batch.test.JobRepositoryTestUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.task.SyncTaskExecutor; import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; @@ -55,24 +56,29 @@ class DeleteMetadataJobTest { Job job; - JobLauncher jobLauncher; + JobOperator jobOperator; @BeforeEach void setUp( @Autowired DataSource dataSource, - @Autowired String tablePrefix, - @Autowired JobRepositoryTestUtils testUtils + @Autowired String tablePrefix ) { - TaskExecutorJobLauncher jobLauncher = new TaskExecutorJobLauncher(); - jobLauncher.setJobRepository(this.jobRepository); - jobLauncher.setTaskExecutor(new SyncTaskExecutor()); - this.jobLauncher = jobLauncher; + TaskExecutorJobOperator jobOperator = new TaskExecutorJobOperator(); + jobOperator.setJobRepository(this.jobRepository); + jobOperator.setTaskExecutor(new SyncTaskExecutor()); + this.jobOperator = jobOperator; this.job = new DeleteMetadataJobBuilder(this.jobRepository, dataSource) .tablePrefix(tablePrefix) .build(); - testUtils.removeJobExecutions(); + // JobOperator.start() in Spring Batch 6.0 creates the JobInstance before validating parameters, + // so failed validations leave orphan instances. Delete by instance to also drop their executions. + for (String jobName : this.jobRepository.getJobNames()) { + for (JobInstance instance : this.jobRepository.findJobInstances(jobName)) { + this.jobRepository.deleteJobInstance(instance); + } + } } @Test @@ -83,9 +89,9 @@ void testRunFailWithInvalidParameter() { .toJobParameters(); // when, then - assertThatExceptionOfType(JobParametersInvalidException.class) + assertThatExceptionOfType(InvalidJobParametersException.class) .isThrownBy(() -> - jobLauncher.run(job, jobParameters) + jobOperator.start(job, jobParameters) ) .withMessageContaining("do not contain required keys: [baseDate]"); } @@ -95,17 +101,17 @@ void testRunWhenNeedNotToDelete() throws Exception { // given int countToCreate = randomBetween(10, 50); for (int i = 0; i < countToCreate; ++i) { - JobExecution jobExecution = jobRepository.createJobExecution("testJobToRemove" + i, buildJobParams()); + JobExecution jobExecution = createJobExecution(jobRepository, "testJobToRemove" + i, buildJobParams()); jobExecution.setCreateTime(dateFrom(2022, 3, 15)); jobRepository.update(jobExecution); - jobRepository.add(new StepExecution("testStep", jobExecution)); + createStepExecution(jobRepository, "testStep", jobExecution); } JobParameters jobParameters = new JobParametersBuilder() .addString("baseDate", "2022/03/15") .toJobParameters(); // when - JobExecution actualExecution = jobLauncher.run(job, jobParameters); + JobExecution actualExecution = jobOperator.start(job, jobParameters); // then assertThat(actualExecution.getExitStatus()).isEqualTo(ExitStatus.COMPLETED); @@ -127,24 +133,24 @@ void testRunWhenNeedToDelete() throws Exception { // given int countToCreateBeforeBaseDate = randomBetween(10, 50); for (int i = 0; i < countToCreateBeforeBaseDate; ++i) { - JobExecution jobExecution = jobRepository.createJobExecution("testJobToRemove" + i, buildJobParams()); + JobExecution jobExecution = createJobExecution(jobRepository, "testJobToRemove" + i, buildJobParams()); jobExecution.setCreateTime(dateTo(2022, 3, 14)); jobRepository.update(jobExecution); - jobRepository.add(new StepExecution("testStep", jobExecution)); + createStepExecution(jobRepository, "testStep", jobExecution); } int countToCreateAfterBaseDate = randomBetween(10, 50); for (int i = 0; i < countToCreateAfterBaseDate; ++i) { - JobExecution jobExecution = jobRepository.createJobExecution("testJobToRemains" + i, buildJobParams()); + JobExecution jobExecution = createJobExecution(jobRepository, "testJobToRemains" + i, buildJobParams()); jobExecution.setCreateTime(dateFrom(2022, 3, 15)); jobRepository.update(jobExecution); - jobRepository.add(new StepExecution("testStep", jobExecution)); + createStepExecution(jobRepository, "testStep", jobExecution); } // when JobParameters jobParameters = new JobParametersBuilder() .addString("baseDate", "2022/03/15") .toJobParameters(); - JobExecution actualExecution = jobLauncher.run(job, jobParameters); + JobExecution actualExecution = jobOperator.start(job, jobParameters); // then assertThat(actualExecution.getExitStatus()).isEqualTo(ExitStatus.COMPLETED); @@ -166,10 +172,10 @@ void testRunShouldNotRemoveWhenDryRun() throws Exception { // given int countToCreate = randomBetween(10, 50); for (int i = 0; i < countToCreate; ++i) { - JobExecution jobExecution = jobRepository.createJobExecution("testJobToRemove" + i, buildJobParams()); + JobExecution jobExecution = createJobExecution(jobRepository, "testJobToRemove" + i, buildJobParams()); jobExecution.setCreateTime(dateTo(2022, 3, 14)); jobRepository.update(jobExecution); - jobRepository.add(new StepExecution("testStep", jobExecution)); + createStepExecution(jobRepository, "testStep", jobExecution); } // when @@ -177,7 +183,7 @@ void testRunShouldNotRemoveWhenDryRun() throws Exception { .addString("baseDate", "2022/03/15") .addString("dryRun", "true") .toJobParameters(); - JobExecution actualExecution = jobLauncher.run(job, jobParameters); + JobExecution actualExecution = jobOperator.start(job, jobParameters); // then assertThat(actualExecution.getExitStatus()).isEqualTo(ExitStatus.COMPLETED); diff --git a/spring-batch-plus/src/test/java/com/navercorp/spring/batch/plus/job/metadata/DeleteMetadataTaskletTest.java b/spring-batch-plus/src/test/java/com/navercorp/spring/batch/plus/job/metadata/DeleteMetadataTaskletTest.java index ac6f8aa1..c2d74b3e 100644 --- a/spring-batch-plus/src/test/java/com/navercorp/spring/batch/plus/job/metadata/DeleteMetadataTaskletTest.java +++ b/spring-batch-plus/src/test/java/com/navercorp/spring/batch/plus/job/metadata/DeleteMetadataTaskletTest.java @@ -21,6 +21,8 @@ import static com.navercorp.spring.batch.plus.job.metadata.DeleteMetadataTasklet.DELETION_RANGE_LENGTH; import static com.navercorp.spring.batch.plus.job.metadata.DeleteMetadataTasklet.LOW_ID_KEY; import static com.navercorp.spring.batch.plus.job.metadata.MetadataTestSupports.buildJobParams; +import static com.navercorp.spring.batch.plus.job.metadata.MetadataTestSupports.createJobExecution; +import static com.navercorp.spring.batch.plus.job.metadata.MetadataTestSupports.createStepExecution; import static com.navercorp.spring.batch.plus.job.metadata.MetadataTestSupports.randomBetween; import static org.assertj.core.api.Assertions.assertThat; @@ -28,16 +30,16 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.JobParameters; -import org.springframework.batch.core.JobParametersBuilder; -import org.springframework.batch.core.StepContribution; -import org.springframework.batch.core.StepExecution; +import org.springframework.batch.core.job.JobExecution; +import org.springframework.batch.core.job.parameters.JobParameters; +import org.springframework.batch.core.job.parameters.JobParametersBuilder; import org.springframework.batch.core.repository.JobRepository; import org.springframework.batch.core.scope.context.ChunkContext; import org.springframework.batch.core.scope.context.StepContext; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.batch.repeat.RepeatStatus; +import org.springframework.batch.core.step.StepContribution; +import org.springframework.batch.core.step.StepExecution; +import org.springframework.batch.infrastructure.item.ExecutionContext; +import org.springframework.batch.infrastructure.repeat.RepeatStatus; import org.springframework.batch.test.JobRepositoryTestUtils; import org.springframework.batch.test.MetaDataInstanceFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -67,9 +69,9 @@ void testExecuteWhen1stStart() throws Exception { int countToDelete = countToCreate - randomBetween(1, countToCreate - 1); long lastJobInstanceId = 0; for (int i = 0; i < countToCreate; i++) { - JobExecution jobExecution = jobRepository.createJobExecution("testJob" + i, buildJobParams()); - jobRepository.add(new StepExecution("testStep", jobExecution)); - lastJobInstanceId = jobExecution.getJobId(); + JobExecution jobExecution = createJobExecution(jobRepository, "testJob" + i, buildJobParams()); + createStepExecution(jobRepository, "testStep", jobExecution); + lastJobInstanceId = jobExecution.getJobInstanceId(); } StepExecution stepExecution = MetaDataInstanceFactory.createStepExecution(); @@ -108,8 +110,8 @@ void testExecuteWhenNothingToDelete() throws Exception { // given int countToCreate = randomBetween(10, 300); for (int i = 0; i < countToCreate; i++) { - JobExecution jobExecution = jobRepository.createJobExecution("testJob" + i, buildJobParams()); - jobRepository.add(new StepExecution("testStep", jobExecution)); + JobExecution jobExecution = createJobExecution(jobRepository, "testJob" + i, buildJobParams()); + createStepExecution(jobRepository, "testStep", jobExecution); } StepExecution stepExecution = MetaDataInstanceFactory.createStepExecution(); @@ -147,9 +149,9 @@ void testExecuteWhenRestart() throws Exception { int countToCreate = randomBetween(10, 300); long lastJobInstanceId = 0; for (int i = 0; i < countToCreate; i++) { - JobExecution jobExecution = jobRepository.createJobExecution("testJob" + i, buildJobParams()); - jobRepository.add(new StepExecution("testStep", jobExecution)); - lastJobInstanceId = jobExecution.getJobId(); + JobExecution jobExecution = createJobExecution(jobRepository, "testJob" + i, buildJobParams()); + createStepExecution(jobRepository, "testStep", jobExecution); + lastJobInstanceId = jobExecution.getJobInstanceId(); } StepExecution stepExecution = MetaDataInstanceFactory.createStepExecution(); @@ -185,9 +187,9 @@ void testExecuteShouldNotRemoveWhenDryRunIsTrue() throws Exception { int countToCreate = randomBetween(1, 10); long lastJobInstanceId = 0; for (int i = 0; i < countToCreate; i++) { - JobExecution jobExecution = jobRepository.createJobExecution("testJob" + i, buildJobParams()); - jobRepository.add(new StepExecution("testStep", jobExecution)); - lastJobInstanceId = jobExecution.getJobId(); + JobExecution jobExecution = createJobExecution(jobRepository, "testJob" + i, buildJobParams()); + createStepExecution(jobRepository, "testStep", jobExecution); + lastJobInstanceId = jobExecution.getJobInstanceId(); } JobParameters jobParameters = new JobParametersBuilder() @@ -229,9 +231,9 @@ void testExecuteShouldNotRemoveWhenDryRunIsNotTrue() throws Exception { int countToCreate = randomBetween(1, 10); long lastJobInstanceId = 0; for (int i = 0; i < countToCreate; i++) { - JobExecution jobExecution = jobRepository.createJobExecution("testJob" + i, buildJobParams()); - jobRepository.add(new StepExecution("testStep", jobExecution)); - lastJobInstanceId = jobExecution.getJobId(); + JobExecution jobExecution = createJobExecution(jobRepository, "testJob" + i, buildJobParams()); + createStepExecution(jobRepository, "testStep", jobExecution); + lastJobInstanceId = jobExecution.getJobInstanceId(); } JobParameters jobParameters = new JobParametersBuilder() diff --git a/spring-batch-plus/src/test/java/com/navercorp/spring/batch/plus/job/metadata/JobMetadataDaoTest.java b/spring-batch-plus/src/test/java/com/navercorp/spring/batch/plus/job/metadata/JobMetadataDaoTest.java index 03e497b9..a449d4e8 100644 --- a/spring-batch-plus/src/test/java/com/navercorp/spring/batch/plus/job/metadata/JobMetadataDaoTest.java +++ b/spring-batch-plus/src/test/java/com/navercorp/spring/batch/plus/job/metadata/JobMetadataDaoTest.java @@ -18,19 +18,16 @@ package com.navercorp.spring.batch.plus.job.metadata; -import static com.navercorp.spring.batch.plus.job.metadata.MetadataTestSupports.buildJobParams; -import static com.navercorp.spring.batch.plus.job.metadata.MetadataTestSupports.dateFrom; -import static com.navercorp.spring.batch.plus.job.metadata.MetadataTestSupports.dateTo; -import static org.assertj.core.api.Assertions.assertThat; +import static com.navercorp.spring.batch.plus.job.metadata.MetadataTestSupports.*; +import static org.assertj.core.api.Assertions.*; import java.time.LocalDate; import java.util.Optional; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.JobInstance; -import org.springframework.batch.core.StepExecution; +import org.springframework.batch.core.job.JobExecution; +import org.springframework.batch.core.job.JobInstance; import org.springframework.batch.core.repository.JobRepository; import org.springframework.batch.test.JobRepositoryTestUtils; import org.springframework.beans.factory.annotation.Autowired; @@ -53,7 +50,7 @@ void setUp(@Autowired JobRepositoryTestUtils testUtils) { @Test void selectMaxJobInstanceIdLessThanCreateTimeWhenEmpty() throws Exception { // given - JobExecution execution = jobRepository.createJobExecution("testJob1", buildJobParams()); + JobExecution execution = createJobExecution(jobRepository, "testJob1", buildJobParams()); execution.setCreateTime(dateFrom(2022, 3, 14)); jobRepository.update(execution); @@ -67,11 +64,11 @@ void selectMaxJobInstanceIdLessThanCreateTimeWhenEmpty() throws Exception { @Test void selectMaxJobInstanceIdLessThanCreateTimeWhenExists() throws Exception { // given - JobExecution execution1 = jobRepository.createJobExecution("testJob1", buildJobParams()); + JobExecution execution1 = createJobExecution(jobRepository, "testJob1", buildJobParams()); execution1.setCreateTime(dateTo(2022, 3, 14)); jobRepository.update(execution1); - JobExecution execution2 = jobRepository.createJobExecution("testJob2", buildJobParams()); + JobExecution execution2 = createJobExecution(jobRepository, "testJob2", buildJobParams()); execution2.setCreateTime(dateFrom(2022, 3, 15)); jobRepository.update(execution2); @@ -80,7 +77,7 @@ void selectMaxJobInstanceIdLessThanCreateTimeWhenExists() throws Exception { // then assertThat(maxJobInstanceId).isPresent(); - assertThat(maxJobInstanceId.get()).isEqualTo(execution1.getJobId()); + assertThat(maxJobInstanceId.get()).isEqualTo(execution1.getJobInstanceId()); } @Test @@ -90,10 +87,10 @@ void testSelectMinJobInstanceId() { jobRepository.createJobInstance("testJob2", buildJobParams()); // when - Long minJobInstanceId = dao.selectMinJobInstanceId(); + Optional minJobInstanceId = dao.selectMinJobInstanceId(); // then - assertThat(minJobInstanceId).isEqualTo(jobInstance1.getId()); + assertThat(minJobInstanceId).hasValue(jobInstance1.getId()); } @Test @@ -112,10 +109,10 @@ void testDeleteJobInstancesByJobInstanceIdRange() { @Test void testDeleteJobExecutionsParamsByJobInstanceIdRange() throws Exception { // given - JobExecution execution1 = jobRepository.createJobExecution("testJob1", buildJobParams()); - JobExecution execution2 = jobRepository.createJobExecution("testJob2", buildJobParams()); - long lowJobInstanceId = execution1.getJobId(); - long highJobInstanceId = execution2.getJobId(); + JobExecution execution1 = createJobExecution(jobRepository, "testJob1", buildJobParams()); + JobExecution execution2 = createJobExecution(jobRepository, "testJob2", buildJobParams()); + long lowJobInstanceId = execution1.getJobInstanceId(); + long highJobInstanceId = execution2.getJobInstanceId(); // when int deletedCount = dao.deleteJobExecutionParamsByJobInstanceIdRange(lowJobInstanceId, highJobInstanceId); @@ -127,10 +124,10 @@ void testDeleteJobExecutionsParamsByJobInstanceIdRange() throws Exception { @Test void testDeleteJobExecutionContextsByJobInstanceIdRange() throws Exception { // given - JobExecution execution1 = jobRepository.createJobExecution("testJob1", buildJobParams()); - JobExecution execution2 = jobRepository.createJobExecution("testJob2", buildJobParams()); - long lowJobInstanceId = execution1.getJobId(); - long highJobInstanceId = execution2.getJobId(); + JobExecution execution1 = createJobExecution(jobRepository, "testJob1", buildJobParams()); + JobExecution execution2 = createJobExecution(jobRepository, "testJob2", buildJobParams()); + long lowJobInstanceId = execution1.getJobInstanceId(); + long highJobInstanceId = execution2.getJobInstanceId(); // when int deletedCount = dao.deleteJobExecutionContextsByJobInstanceIdRange(lowJobInstanceId, highJobInstanceId); @@ -142,12 +139,12 @@ void testDeleteJobExecutionContextsByJobInstanceIdRange() throws Exception { @Test void testDeleteJobExecutionsByJobInstanceIdRange() throws Exception { // given - JobExecution execution1 = jobRepository.createJobExecution("testJob1", buildJobParams()); - JobExecution execution2 = jobRepository.createJobExecution("testJob2", buildJobParams()); - jobRepository.createJobExecution("testJob3", buildJobParams()); + JobExecution execution1 = createJobExecution(jobRepository, "testJob1", buildJobParams()); + JobExecution execution2 = createJobExecution(jobRepository, "testJob2", buildJobParams()); + createJobExecution(jobRepository, "testJob3", buildJobParams()); - long lowJobInstanceId = execution1.getJobId(); - long highJobInstanceId = execution2.getJobId(); + long lowJobInstanceId = execution1.getJobInstanceId(); + long highJobInstanceId = execution2.getJobInstanceId(); dao.deleteJobExecutionContextsByJobInstanceIdRange(lowJobInstanceId, highJobInstanceId); dao.deleteJobExecutionParamsByJobInstanceIdRange(lowJobInstanceId, highJobInstanceId); @@ -161,17 +158,15 @@ void testDeleteJobExecutionsByJobInstanceIdRange() throws Exception { @Test void testDeleteStepExecutionContextsByJobInstanceIdRange() throws Exception { // given - JobExecution jobExecution1 = jobRepository.createJobExecution("testJob1", buildJobParams()); - jobExecution1.createStepExecution("testStep1"); - jobExecution1.createStepExecution("testStep2"); - jobRepository.add(new StepExecution("testStep1", jobExecution1)); - jobRepository.add(new StepExecution("testStep2", jobExecution1)); + JobExecution jobExecution1 = createJobExecution(jobRepository, "testJob1", buildJobParams()); + createStepExecution(jobRepository, "testStep1", jobExecution1); + createStepExecution(jobRepository, "testStep2", jobExecution1); - JobExecution jobExecution2 = jobRepository.createJobExecution("testJob2", buildJobParams()); - jobRepository.add(new StepExecution("testStep3", jobExecution2)); + JobExecution jobExecution2 = createJobExecution(jobRepository, "testJob2", buildJobParams()); + createStepExecution(jobRepository, "testStep3", jobExecution2); - long lowJobInstanceId = jobExecution1.getJobId(); - long highJobInstanceId = jobExecution2.getJobId(); + long lowJobInstanceId = jobExecution1.getJobInstanceId(); + long highJobInstanceId = jobExecution2.getJobInstanceId(); // when int deletedCount = dao.deleteStepExecutionContextsByJobInstanceIdRange(lowJobInstanceId, highJobInstanceId); @@ -183,20 +178,18 @@ void testDeleteStepExecutionContextsByJobInstanceIdRange() throws Exception { @Test void testDeleteStepExecutionsByJobInstanceIdRange() throws Exception { // given - JobExecution jobExecution1 = jobRepository.createJobExecution("testJob1", buildJobParams()); - jobExecution1.createStepExecution("testStep1"); - jobExecution1.createStepExecution("testStep2"); - jobRepository.add(new StepExecution("testStep1", jobExecution1)); - jobRepository.add(new StepExecution("testStep2", jobExecution1)); + JobExecution jobExecution1 = createJobExecution(jobRepository, "testJob1", buildJobParams()); + createStepExecution(jobRepository, "testStep1", jobExecution1); + createStepExecution(jobRepository, "testStep2", jobExecution1); - JobExecution jobExecution2 = jobRepository.createJobExecution("testJob2", buildJobParams()); - jobRepository.add(new StepExecution("testStep3", jobExecution2)); + JobExecution jobExecution2 = createJobExecution(jobRepository, "testJob2", buildJobParams()); + createStepExecution(jobRepository, "testStep3", jobExecution2); - JobExecution jobExecution3 = jobRepository.createJobExecution("testJob3", buildJobParams()); - jobRepository.add(new StepExecution("testStep4", jobExecution3)); + JobExecution jobExecution3 = createJobExecution(jobRepository, "testJob3", buildJobParams()); + createStepExecution(jobRepository, "testStep4", jobExecution3); - long lowJobInstanceId = jobExecution1.getJobId(); - long highJobInstanceId = jobExecution2.getJobId(); + long lowJobInstanceId = jobExecution1.getJobInstanceId(); + long highJobInstanceId = jobExecution2.getJobInstanceId(); dao.deleteStepExecutionContextsByJobInstanceIdRange(lowJobInstanceId, highJobInstanceId); // when diff --git a/spring-batch-plus/src/test/java/com/navercorp/spring/batch/plus/job/metadata/MetadataTestSupports.java b/spring-batch-plus/src/test/java/com/navercorp/spring/batch/plus/job/metadata/MetadataTestSupports.java index 96500043..c3ad20e7 100644 --- a/spring-batch-plus/src/test/java/com/navercorp/spring/batch/plus/job/metadata/MetadataTestSupports.java +++ b/spring-batch-plus/src/test/java/com/navercorp/spring/batch/plus/job/metadata/MetadataTestSupports.java @@ -23,11 +23,26 @@ import java.time.LocalDateTime; import java.util.concurrent.ThreadLocalRandom; -import org.springframework.batch.core.JobParameters; -import org.springframework.batch.core.JobParametersBuilder; +import org.springframework.batch.core.job.JobExecution; +import org.springframework.batch.core.job.JobInstance; +import org.springframework.batch.core.job.parameters.JobParameters; +import org.springframework.batch.core.job.parameters.JobParametersBuilder; +import org.springframework.batch.core.repository.JobRepository; +import org.springframework.batch.core.step.StepExecution; +import org.springframework.batch.infrastructure.item.ExecutionContext; class MetadataTestSupports { + static JobExecution createJobExecution(JobRepository jobRepository, String jobName, JobParameters parameters) { + JobInstance jobInstance = jobRepository.createJobInstance(jobName, parameters); + return jobRepository.createJobExecution(jobInstance, parameters, new ExecutionContext()); + } + + static StepExecution createStepExecution(JobRepository jobRepository, String stepName, JobExecution jobExecution) { + return jobRepository.createStepExecution(stepName, jobExecution); + } + + static LocalDateTime dateTo(int year, int month, int day) { LocalDate to = LocalDate.of(year, month, day); LocalDate from = to.minusDays(10); diff --git a/spring-batch-plus/src/test/java/com/navercorp/spring/batch/plus/job/metadata/TestJobRepositoryConfig.java b/spring-batch-plus/src/test/java/com/navercorp/spring/batch/plus/job/metadata/TestJobRepositoryConfig.java index df8403ec..3a01be4f 100644 --- a/spring-batch-plus/src/test/java/com/navercorp/spring/batch/plus/job/metadata/TestJobRepositoryConfig.java +++ b/spring-batch-plus/src/test/java/com/navercorp/spring/batch/plus/job/metadata/TestJobRepositoryConfig.java @@ -31,7 +31,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.batch.core.repository.JobRepository; -import org.springframework.batch.core.repository.support.JobRepositoryFactoryBean; +import org.springframework.batch.core.repository.support.JdbcJobRepositoryFactoryBean; import org.springframework.batch.test.JobRepositoryTestUtils; import org.springframework.context.annotation.Bean; import org.springframework.core.io.ClassPathResource; @@ -44,8 +44,7 @@ import org.springframework.util.StringUtils; public class TestJobRepositoryConfig { - - private final Logger logger = LoggerFactory.getLogger(TestJobRepositoryConfig.class); + protected static final Logger logger = LoggerFactory.getLogger(TestJobRepositoryConfig.class); @Bean DataSource dataSource(String tablePrefix) throws Exception { @@ -70,7 +69,7 @@ String tablePrefix() { @Bean JobRepository jobRepository(DataSource dataSource, String tablePrefix) throws Exception { - JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean(); + JdbcJobRepositoryFactoryBean factory = new JdbcJobRepositoryFactoryBean(); factory.setDataSource(dataSource); factory.setTransactionManager(new DataSourceTransactionManager(dataSource)); factory.setTablePrefix(tablePrefix); diff --git a/spring-batch-plus/src/test/java/com/navercorp/spring/batch/plus/step/adapter/AdapterFactoryTest.java b/spring-batch-plus/src/test/java/com/navercorp/spring/batch/plus/step/adapter/AdapterFactoryTest.java index 2cf19dde..93600980 100644 --- a/spring-batch-plus/src/test/java/com/navercorp/spring/batch/plus/step/adapter/AdapterFactoryTest.java +++ b/spring-batch-plus/src/test/java/com/navercorp/spring/batch/plus/step/adapter/AdapterFactoryTest.java @@ -25,16 +25,19 @@ import java.util.List; import org.junit.jupiter.api.Test; -import org.springframework.batch.item.ItemProcessor; -import org.springframework.batch.item.ItemStreamReader; -import org.springframework.batch.item.ItemStreamWriter; +import org.springframework.batch.infrastructure.item.ItemProcessor; +import org.springframework.batch.infrastructure.item.ItemStreamReader; +import org.springframework.batch.infrastructure.item.ItemStreamWriter; import reactor.core.publisher.Flux; +/** + * Covers delegate conversion and step-scoped reader wrapping across Spring Batch item components. + */ class AdapterFactoryTest { @Test - void itemStreamReaderShouldReturnStepScopedOneWhenPassingItemReaderWithFluxDelegate() { + void itemStreamReaderShouldReturnStepScopedReaderWhenFluxDelegateIsProvided() { ItemStreamFluxReaderDelegate delegate = executionContext -> Flux.empty(); ItemStreamReader actual = AdapterFactory.itemStreamReader(delegate); @@ -42,7 +45,7 @@ void itemStreamReaderShouldReturnStepScopedOneWhenPassingItemReaderWithFluxDeleg } @Test - void itemStreamReaderShouldReturnStepScopedOneWhenPassingItemReaderWithIterableDelegate() { + void itemStreamReaderShouldReturnStepScopedReaderWhenIterableDelegateIsProvided() { ItemStreamIterableReaderDelegate delegate = executionContext -> List.of(); ItemStreamReader actual = AdapterFactory.itemStreamReader(delegate); @@ -50,7 +53,7 @@ void itemStreamReaderShouldReturnStepScopedOneWhenPassingItemReaderWithIterableD } @Test - void itemStreamReaderShouldReturnStepScopedOneWhenPassingItemReaderWithIteratorDelegate() { + void itemStreamReaderShouldReturnStepScopedReaderWhenIteratorDelegateIsProvided() { ItemStreamIteratorReaderDelegate delegate = executionContext -> Collections.emptyIterator(); ItemStreamReader actual = AdapterFactory.itemStreamReader(delegate); @@ -58,7 +61,7 @@ void itemStreamReaderShouldReturnStepScopedOneWhenPassingItemReaderWithIteratorD } @Test - void itemStreamReaderShouldReturnStepScopedOneWhenPassingItemReaderWithSimpleDelegate() { + void itemStreamReaderShouldReturnStepScopedReaderWhenSimpleDelegateIsProvided() { ItemStreamSimpleReaderDelegate delegate = () -> null; ItemStreamReader actual = AdapterFactory.itemStreamReader(delegate); @@ -66,7 +69,7 @@ void itemStreamReaderShouldReturnStepScopedOneWhenPassingItemReaderWithSimpleDel } @Test - void itemProcessorShouldReturnAdapterWhenPassingProcessorDelegate() { + void itemProcessorShouldReturnProcessorAdapterWhenDelegateIsProvided() { ItemProcessorDelegate delegate = item -> null; ItemProcessor actual = AdapterFactory.itemProcessor(delegate); @@ -74,7 +77,7 @@ void itemProcessorShouldReturnAdapterWhenPassingProcessorDelegate() { } @Test - void itemStreamWriterShouldReturnAdapterWhenPassingWriterDelegate() { + void itemStreamWriterShouldReturnWriterAdapterWhenDelegateIsProvided() { ItemStreamWriterDelegate delegate = items -> { }; ItemStreamWriter actual = AdapterFactory.itemStreamWriter(delegate); @@ -84,7 +87,7 @@ void itemStreamWriterShouldReturnAdapterWhenPassingWriterDelegate() { @SuppressWarnings({"ConstantConditions"}) @Test - void createShouldThrowExceptionWhenPassingNull() { + void adapterCreationShouldRejectNullDelegate() { assertThatThrownBy(() -> AdapterFactory.itemStreamReader((ItemStreamFluxReaderDelegate)null)); assertThatThrownBy(() -> AdapterFactory.itemStreamReader((ItemStreamIterableReaderDelegate)null)); assertThatThrownBy(() -> AdapterFactory.itemStreamReader((ItemStreamIteratorReaderDelegate)null)); diff --git a/spring-batch-plus/src/test/java/com/navercorp/spring/batch/plus/step/adapter/ItemProcessorAdapterTest.java b/spring-batch-plus/src/test/java/com/navercorp/spring/batch/plus/step/adapter/ItemProcessorAdapterTest.java index 2719cf57..71b04669 100644 --- a/spring-batch-plus/src/test/java/com/navercorp/spring/batch/plus/step/adapter/ItemProcessorAdapterTest.java +++ b/spring-batch-plus/src/test/java/com/navercorp/spring/batch/plus/step/adapter/ItemProcessorAdapterTest.java @@ -27,13 +27,16 @@ import java.util.concurrent.ThreadLocalRandom; import org.junit.jupiter.api.Test; -import org.springframework.batch.item.ItemProcessor; +import org.springframework.batch.infrastructure.item.ItemProcessor; +/** + * Covers preservation of the processing delegate contract through its Spring Batch adapter. + */ @SuppressWarnings("unchecked") class ItemProcessorAdapterTest { @Test - void processShouldReturnValueFromDelegate() throws Exception { + void processShouldReturnDelegateResult() throws Exception { Integer expected = ThreadLocalRandom.current().nextInt(); ItemProcessorDelegate delegate = mock(ItemProcessorDelegate.class); when(delegate.process(any())).thenReturn(expected); @@ -46,7 +49,7 @@ void processShouldReturnValueFromDelegate() throws Exception { @SuppressWarnings({"ConstantConditions"}) @Test - void createShouldThrowExceptionWhenPassingNull() { + void ofShouldRejectNullDelegate() { assertThatThrownBy(() -> ItemProcessorAdapter.of(null)); } } diff --git a/spring-batch-plus/src/test/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamFluxReaderAdapterTest.java b/spring-batch-plus/src/test/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamFluxReaderAdapterTest.java index 03f85863..6cd80963 100644 --- a/spring-batch-plus/src/test/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamFluxReaderAdapterTest.java +++ b/spring-batch-plus/src/test/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamFluxReaderAdapterTest.java @@ -19,6 +19,7 @@ package com.navercorp.spring.batch.plus.step.adapter; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatCode; import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; @@ -30,16 +31,19 @@ import java.util.List; import org.junit.jupiter.api.Test; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.batch.item.ItemStreamReader; +import org.springframework.batch.infrastructure.item.ExecutionContext; +import org.springframework.batch.infrastructure.item.ItemStreamReader; import reactor.core.publisher.Flux; +/** + * Covers the blocking reader contract over a Flux-backed stream delegate. + */ @SuppressWarnings("unchecked") class ItemStreamFluxReaderAdapterTest { @Test - void openShouldInvokeProperDelegateMethods() { + void openShouldInitializeFromDelegate() { ItemStreamFluxReaderDelegate delegate = mock(ItemStreamFluxReaderDelegate.class); ItemStreamReader itemStreamReader = ItemStreamFluxReaderAdapter.of(delegate); @@ -50,7 +54,7 @@ void openShouldInvokeProperDelegateMethods() { } @Test - void readShouldReturnValuesFromDelegate() throws Exception { + void readShouldReturnAllSourceItems() throws Exception { List expected = List.of(1, 2, 3); ItemStreamFluxReaderDelegate delegate = mock(ItemStreamFluxReaderDelegate.class); when(delegate.readFlux(any())).thenAnswer($ -> Flux.fromIterable(expected)); @@ -67,7 +71,7 @@ void readShouldReturnValuesFromDelegate() throws Exception { } @Test - void readShouldThrowExceptionWhenNoOpenInvoked() { + void readShouldFailWhenAdapterIsNotOpened() { ItemStreamFluxReaderDelegate delegate = mock(ItemStreamFluxReaderDelegate.class); ItemStreamReader itemStreamReader = ItemStreamFluxReaderAdapter.of(delegate); @@ -75,7 +79,7 @@ void readShouldThrowExceptionWhenNoOpenInvoked() { } @Test - void updateShouldInvokeProperDelegateMethod() { + void updateShouldForwardExecutionContextToDelegate() { ItemStreamFluxReaderDelegate delegate = mock(ItemStreamFluxReaderDelegate.class); ItemStreamReader itemStreamReader = ItemStreamFluxReaderAdapter.of(delegate); @@ -85,7 +89,7 @@ void updateShouldInvokeProperDelegateMethod() { } @Test - void closeShouldInvokeProperDelegateMethod() { + void closeShouldNotifyDelegate() { ItemStreamFluxReaderDelegate delegate = mock(ItemStreamFluxReaderDelegate.class); ItemStreamReader itemStreamReader = ItemStreamFluxReaderAdapter.of(delegate); @@ -94,9 +98,22 @@ void closeShouldInvokeProperDelegateMethod() { verify(delegate, times(1)).onCloseRead(); } + @Test + void lifecycleShouldBeOptional() { + ItemStreamFluxReaderDelegate delegate = $ -> Flux.empty(); + ItemStreamReader itemStreamReader = ItemStreamFluxReaderAdapter.of(delegate); + ExecutionContext executionContext = new ExecutionContext(); + + assertThatCode(() -> { + itemStreamReader.open(executionContext); + itemStreamReader.update(executionContext); + itemStreamReader.close(); + }).doesNotThrowAnyException(); + } + @SuppressWarnings({"ResultOfMethodCallIgnored", "ConstantConditions"}) @Test - void createShouldThrowExceptionWhenPassingNull() { + void ofShouldRejectNullDelegate() { assertThatThrownBy(() -> ItemStreamFluxReaderAdapter.of(null)); } } diff --git a/spring-batch-plus/src/test/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamIterableReaderAdapterTest.java b/spring-batch-plus/src/test/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamIterableReaderAdapterTest.java index f807a892..66022f1f 100644 --- a/spring-batch-plus/src/test/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamIterableReaderAdapterTest.java +++ b/spring-batch-plus/src/test/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamIterableReaderAdapterTest.java @@ -19,6 +19,7 @@ package com.navercorp.spring.batch.plus.step.adapter; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatCode; import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; @@ -30,14 +31,17 @@ import java.util.List; import org.junit.jupiter.api.Test; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.batch.item.ItemStreamReader; +import org.springframework.batch.infrastructure.item.ExecutionContext; +import org.springframework.batch.infrastructure.item.ItemStreamReader; +/** + * Covers the blocking reader contract over an Iterable-backed stream delegate. + */ @SuppressWarnings("unchecked") class ItemStreamIterableReaderAdapterTest { @Test - void openShouldInvokeProperDelegateMethods() { + void openShouldInitializeFromDelegate() { ItemStreamIterableReaderDelegate delegate = mock(ItemStreamIterableReaderDelegate.class); ItemStreamReader itemStreamReader = ItemStreamIterableReaderAdapter.of(delegate); @@ -48,7 +52,7 @@ void openShouldInvokeProperDelegateMethods() { } @Test - void readShouldReturnValuesFromDelegate() throws Exception { + void readShouldReturnAllSourceItems() throws Exception { List expected = List.of(1, 2, 3); ItemStreamIterableReaderDelegate delegate = mock(ItemStreamIterableReaderDelegate.class); when(delegate.readIterable(any())).thenAnswer($ -> expected); @@ -65,7 +69,7 @@ void readShouldReturnValuesFromDelegate() throws Exception { } @Test - void readShouldThrowExceptionWhenNoOpenInvoked() { + void readShouldFailWhenAdapterIsNotOpened() { ItemStreamIterableReaderDelegate delegate = mock(ItemStreamIterableReaderDelegate.class); ItemStreamReader itemStreamReader = ItemStreamIterableReaderAdapter.of(delegate); @@ -73,7 +77,7 @@ void readShouldThrowExceptionWhenNoOpenInvoked() { } @Test - void updateShouldInvokeProperDelegateMethod() { + void updateShouldForwardExecutionContextToDelegate() { ItemStreamIterableReaderDelegate delegate = mock(ItemStreamIterableReaderDelegate.class); ItemStreamReader itemStreamReader = ItemStreamIterableReaderAdapter.of(delegate); @@ -83,7 +87,7 @@ void updateShouldInvokeProperDelegateMethod() { } @Test - void closeShouldInvokeProperDelegateMethod() { + void closeShouldNotifyDelegate() { ItemStreamIterableReaderDelegate delegate = mock(ItemStreamIterableReaderDelegate.class); ItemStreamReader itemStreamReader = ItemStreamIterableReaderAdapter.of(delegate); @@ -92,9 +96,22 @@ void closeShouldInvokeProperDelegateMethod() { verify(delegate, times(1)).onCloseRead(); } + @Test + void lifecycleShouldBeOptional() { + ItemStreamIterableReaderDelegate delegate = $ -> List.of(); + ItemStreamReader itemStreamReader = ItemStreamIterableReaderAdapter.of(delegate); + ExecutionContext executionContext = new ExecutionContext(); + + assertThatCode(() -> { + itemStreamReader.open(executionContext); + itemStreamReader.update(executionContext); + itemStreamReader.close(); + }).doesNotThrowAnyException(); + } + @SuppressWarnings({"ResultOfMethodCallIgnored", "ConstantConditions"}) @Test - void createShouldThrowExceptionWhenPassingNull() { + void ofShouldRejectNullDelegate() { assertThatThrownBy(() -> ItemStreamIterableReaderAdapter.of(null)); } } diff --git a/spring-batch-plus/src/test/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamIteratorReaderAdapterTest.java b/spring-batch-plus/src/test/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamIteratorReaderAdapterTest.java index 286df35f..bf248f25 100644 --- a/spring-batch-plus/src/test/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamIteratorReaderAdapterTest.java +++ b/spring-batch-plus/src/test/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamIteratorReaderAdapterTest.java @@ -19,6 +19,7 @@ package com.navercorp.spring.batch.plus.step.adapter; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatCode; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; @@ -30,14 +31,17 @@ import java.util.List; import org.junit.jupiter.api.Test; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.batch.item.ItemStreamReader; +import org.springframework.batch.infrastructure.item.ExecutionContext; +import org.springframework.batch.infrastructure.item.ItemStreamReader; +/** + * Covers the blocking reader contract over an Iterator-backed stream delegate. + */ @SuppressWarnings("unchecked") class ItemStreamIteratorReaderAdapterTest { @Test - void openShouldInvokeProperDelegateMethods() { + void openShouldInitializeFromDelegate() { ItemStreamIteratorReaderDelegate delegate = mock(ItemStreamIteratorReaderDelegate.class); ItemStreamReader itemStreamReader = ItemStreamIteratorReaderAdapter.of(delegate); @@ -48,7 +52,7 @@ void openShouldInvokeProperDelegateMethods() { } @Test - void readShouldReturnValuesFromDelegate() throws Exception { + void readShouldReturnAllSourceItems() throws Exception { List expected = List.of(1, 2, 3); ItemStreamIteratorReaderDelegate delegate = mock(ItemStreamIteratorReaderDelegate.class); when(delegate.readIterator(any())).thenAnswer($ -> expected.iterator()); @@ -65,7 +69,7 @@ void readShouldReturnValuesFromDelegate() throws Exception { } @Test - void readShouldThrowExceptionWhenNoOpenInvoked() { + void readShouldFailWhenAdapterIsNotOpened() { ItemStreamIteratorReaderDelegate delegate = mock(ItemStreamIteratorReaderDelegate.class); ItemStreamReader itemStreamReader = ItemStreamIteratorReaderAdapter.of(delegate); @@ -73,7 +77,7 @@ void readShouldThrowExceptionWhenNoOpenInvoked() { } @Test - void updateShouldInvokeProperDelegateMethod() { + void updateShouldForwardExecutionContextToDelegate() { ItemStreamIteratorReaderDelegate delegate = mock(ItemStreamIteratorReaderDelegate.class); ItemStreamReader itemStreamReader = ItemStreamIteratorReaderAdapter.of(delegate); @@ -83,7 +87,7 @@ void updateShouldInvokeProperDelegateMethod() { } @Test - void closeShouldInvokeProperDelegateMethod() { + void closeShouldNotifyDelegate() { ItemStreamIteratorReaderDelegate delegate = mock(ItemStreamIteratorReaderDelegate.class); ItemStreamReader itemStreamReader = ItemStreamIteratorReaderAdapter.of(delegate); @@ -92,9 +96,22 @@ void closeShouldInvokeProperDelegateMethod() { verify(delegate, times(1)).onCloseRead(); } + @Test + void lifecycleShouldBeOptional() { + ItemStreamIteratorReaderDelegate delegate = $ -> List.of().iterator(); + ItemStreamReader itemStreamReader = ItemStreamIteratorReaderAdapter.of(delegate); + ExecutionContext executionContext = new ExecutionContext(); + + assertThatCode(() -> { + itemStreamReader.open(executionContext); + itemStreamReader.update(executionContext); + itemStreamReader.close(); + }).doesNotThrowAnyException(); + } + @SuppressWarnings({"ConstantConditions"}) @Test - void createShouldThrowExceptionWhenPassingNull() { + void ofShouldRejectNullDelegate() { assertThatThrownBy(() -> ItemStreamIteratorReaderAdapter.of(null)); } } diff --git a/spring-batch-plus/src/test/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamSimpleReaderAdapterTest.java b/spring-batch-plus/src/test/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamSimpleReaderAdapterTest.java index 57cb45a8..c8617ba6 100644 --- a/spring-batch-plus/src/test/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamSimpleReaderAdapterTest.java +++ b/spring-batch-plus/src/test/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamSimpleReaderAdapterTest.java @@ -18,6 +18,7 @@ package com.navercorp.spring.batch.plus.step.adapter; +import static org.assertj.core.api.Assertions.assertThatCode; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.assertj.core.api.AssertionsForClassTypes.assertThat; import static org.mockito.ArgumentMatchers.any; @@ -29,14 +30,17 @@ import java.util.concurrent.ThreadLocalRandom; import org.junit.jupiter.api.Test; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.batch.item.ItemStreamReader; +import org.springframework.batch.infrastructure.item.ExecutionContext; +import org.springframework.batch.infrastructure.item.ItemStreamReader; +/** + * Covers the blocking reader contract over a delegate that supplies one item per call. + */ @SuppressWarnings("unchecked") class ItemStreamSimpleReaderAdapterTest { @Test - void openShouldInvokeProperDelegateMethod() { + void openShouldNotifyDelegate() { ItemStreamSimpleReaderDelegate delegate = mock(ItemStreamSimpleReaderDelegate.class); ItemStreamReader itemStreamReader = ItemStreamSimpleReaderAdapter.of(delegate); @@ -46,7 +50,7 @@ void openShouldInvokeProperDelegateMethod() { } @Test - void readShouldReturnValuesFromDelegate() throws Exception { + void readShouldReturnDelegateItem() throws Exception { Integer expected = ThreadLocalRandom.current().nextInt(); ItemStreamSimpleReaderDelegate delegate = mock(ItemStreamSimpleReaderDelegate.class); when(delegate.read()).thenReturn(expected); @@ -58,7 +62,7 @@ void readShouldReturnValuesFromDelegate() throws Exception { } @Test - void updateShouldInvokeProperDelegateMethod() { + void updateShouldForwardExecutionContextToDelegate() { ItemStreamSimpleReaderDelegate delegate = mock(ItemStreamSimpleReaderDelegate.class); ItemStreamReader itemStreamReader = ItemStreamSimpleReaderAdapter.of(delegate); @@ -68,7 +72,7 @@ void updateShouldInvokeProperDelegateMethod() { } @Test - void closeShouldInvokeProperDelegateMethod() { + void closeShouldNotifyDelegate() { ItemStreamSimpleReaderDelegate delegate = mock(ItemStreamSimpleReaderDelegate.class); ItemStreamReader itemStreamReader = ItemStreamSimpleReaderAdapter.of(delegate); @@ -77,9 +81,22 @@ void closeShouldInvokeProperDelegateMethod() { verify(delegate, times(1)).onCloseRead(); } + @Test + void lifecycleShouldBeOptional() { + ItemStreamSimpleReaderDelegate delegate = () -> null; + ItemStreamReader itemStreamReader = ItemStreamSimpleReaderAdapter.of(delegate); + ExecutionContext executionContext = new ExecutionContext(); + + assertThatCode(() -> { + itemStreamReader.open(executionContext); + itemStreamReader.update(executionContext); + itemStreamReader.close(); + }).doesNotThrowAnyException(); + } + @SuppressWarnings({"ConstantConditions"}) @Test - void createShouldThrowExceptionWhenPassingNull() { + void ofShouldRejectNullDelegate() { assertThatThrownBy(() -> ItemStreamSimpleReaderAdapter.of(null)); } } diff --git a/spring-batch-plus/src/test/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamWriterAdapterTest.java b/spring-batch-plus/src/test/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamWriterAdapterTest.java index 32824379..5c880832 100644 --- a/spring-batch-plus/src/test/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamWriterAdapterTest.java +++ b/spring-batch-plus/src/test/java/com/navercorp/spring/batch/plus/step/adapter/ItemStreamWriterAdapterTest.java @@ -19,21 +19,25 @@ package com.navercorp.spring.batch.plus.step.adapter; import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.assertj.core.api.AssertionsForClassTypes.assertThatCode; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import org.junit.jupiter.api.Test; -import org.springframework.batch.item.Chunk; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.batch.item.ItemStreamWriter; +import org.springframework.batch.infrastructure.item.Chunk; +import org.springframework.batch.infrastructure.item.ExecutionContext; +import org.springframework.batch.infrastructure.item.ItemStreamWriter; +/** + * Covers the stream lifecycle and chunk-writing contract exposed by the writer adapter. + */ @SuppressWarnings("unchecked") class ItemStreamWriterAdapterTest { @Test - void openShouldInvokeProperDelegateMethod() { + void openShouldNotifyDelegate() { ItemStreamWriterDelegate delegate = mock(ItemStreamWriterDelegate.class); ItemStreamWriter itemStreamWriterAdaptor = ItemStreamWriterAdapter.of(delegate); @@ -43,7 +47,7 @@ void openShouldInvokeProperDelegateMethod() { } @Test - void writeShouldInvokeProperDelegateMethod() throws Exception { + void writeShouldForwardChunkToDelegate() throws Exception { ItemStreamWriterDelegate delegate = mock(ItemStreamWriterDelegate.class); ItemStreamWriter itemStreamWriterAdaptor = ItemStreamWriterAdapter.of(delegate); @@ -53,7 +57,7 @@ void writeShouldInvokeProperDelegateMethod() throws Exception { } @Test - void updateShouldInvokeProperDelegateMethod() { + void updateShouldForwardExecutionContextToDelegate() { ItemStreamWriterDelegate delegate = mock(ItemStreamWriterDelegate.class); ItemStreamWriter itemStreamWriterAdaptor = ItemStreamWriterAdapter.of(delegate); @@ -63,7 +67,7 @@ void updateShouldInvokeProperDelegateMethod() { } @Test - void closeShouldInvokeProperDelegateMethod() { + void closeShouldNotifyDelegate() { ItemStreamWriterDelegate delegate = mock(ItemStreamWriterDelegate.class); ItemStreamWriter itemStreamWriterAdaptor = ItemStreamWriterAdapter.of(delegate); @@ -72,9 +76,23 @@ void closeShouldInvokeProperDelegateMethod() { verify(delegate, times(1)).onCloseWrite(); } + @Test + void lifecycleShouldBeOptional() { + ItemStreamWriterDelegate delegate = $ -> { + }; + ItemStreamWriter itemStreamWriter = ItemStreamWriterAdapter.of(delegate); + ExecutionContext executionContext = new ExecutionContext(); + + assertThatCode(() -> { + itemStreamWriter.open(executionContext); + itemStreamWriter.update(executionContext); + itemStreamWriter.close(); + }).doesNotThrowAnyException(); + } + @SuppressWarnings({"ConstantConditions"}) @Test - void createShouldThrowExceptionWhenPassingNull() { + void ofShouldRejectNullDelegate() { assertThatThrownBy(() -> ItemStreamWriterAdapter.of(null)); } } diff --git a/spring-batch-plus/src/test/java/com/navercorp/spring/batch/plus/step/adapter/StepScopeItemStreamReaderTest.java b/spring-batch-plus/src/test/java/com/navercorp/spring/batch/plus/step/adapter/StepScopeItemStreamReaderTest.java index 3bc2fd46..daf06c55 100644 --- a/spring-batch-plus/src/test/java/com/navercorp/spring/batch/plus/step/adapter/StepScopeItemStreamReaderTest.java +++ b/spring-batch-plus/src/test/java/com/navercorp/spring/batch/plus/step/adapter/StepScopeItemStreamReaderTest.java @@ -29,17 +29,20 @@ import java.util.concurrent.ThreadLocalRandom; import org.junit.jupiter.api.Test; -import org.springframework.batch.core.StepExecution; -import org.springframework.batch.item.ExecutionContext; -import org.springframework.batch.item.ItemStreamReader; +import org.springframework.batch.core.step.StepExecution; +import org.springframework.batch.infrastructure.item.ExecutionContext; +import org.springframework.batch.infrastructure.item.ItemStreamReader; import org.springframework.batch.test.MetaDataInstanceFactory; import org.springframework.batch.test.StepScopeTestUtils; +/** + * Covers delegate creation and reuse within an active Spring Batch step scope. + */ @SuppressWarnings("unchecked") class StepScopeItemStreamReaderTest { @Test - void openShouldInvokeProperDelegateMethod() throws Exception { + void openShouldDelegateToScopedReader() throws Exception { ItemStreamReader delegate = mock(ItemStreamReader.class); ItemStreamReader itemStreamReader = StepScopeItemStreamReader.of(() -> delegate); @@ -53,7 +56,7 @@ void openShouldInvokeProperDelegateMethod() throws Exception { } @Test - void readShouldReturnValueFromDelegate() throws Exception { + void readShouldReturnScopedDelegateItem() throws Exception { Integer expected = ThreadLocalRandom.current().nextInt(); ItemStreamReader delegate = mock(ItemStreamReader.class); when(delegate.read()).thenReturn(expected); @@ -66,7 +69,7 @@ void readShouldReturnValueFromDelegate() throws Exception { } @Test - void updateShouldInvokeProperDelegateMethod() throws Exception { + void updateShouldDelegateToScopedReader() throws Exception { ItemStreamReader delegate = mock(ItemStreamReader.class); ItemStreamReader itemStreamReader = StepScopeItemStreamReader.of(() -> delegate); @@ -80,7 +83,7 @@ void updateShouldInvokeProperDelegateMethod() throws Exception { } @Test - void closeShouldInvokeProperDelegateMethod() throws Exception { + void closeShouldDelegateToScopedReader() throws Exception { ItemStreamReader delegate = mock(ItemStreamReader.class); ItemStreamReader itemStreamReader = StepScopeItemStreamReader.of(() -> delegate); @@ -94,7 +97,7 @@ void closeShouldInvokeProperDelegateMethod() throws Exception { } @Test - void invokeShouldThrowExceptionWhenNoStepScope() { + void operationsShouldFailWhenCalledOutsideStepScope() { ItemStreamReader delegate = mock(ItemStreamReader.class); ItemStreamReader itemStreamReader = StepScopeItemStreamReader.of(() -> delegate); @@ -113,7 +116,7 @@ void invokeShouldThrowExceptionWhenNoStepScope() { } @Test - void createShouldThrowExceptionWhenPassingNull() { + void ofShouldRejectNullDelegateSupplier() { assertThatThrownBy(() -> StepScopeItemStreamReader.of(null)); } } diff --git a/spring-boot-autoconfigure-batch-plus-kotlin/build.gradle.kts b/spring-boot-autoconfigure-batch-plus-kotlin/build.gradle.kts index 1e805468..120bf063 100644 --- a/spring-boot-autoconfigure-batch-plus-kotlin/build.gradle.kts +++ b/spring-boot-autoconfigure-batch-plus-kotlin/build.gradle.kts @@ -8,6 +8,7 @@ dependencies { compileOnly(project(":spring-batch-plus-kotlin")) compileOnly(libs.spring.boot.autoconfigure) + compileOnly(libs.spring.boot.batch.jdbc) compileOnly(libs.spring.batch.core) testImplementation(project(":spring-batch-plus-kotlin")) @@ -16,6 +17,8 @@ dependencies { testImplementation(libs.spring.boot.test) testImplementation(libs.spring.batch.core) testImplementation(libs.spring.jdbc) + testImplementation(libs.spring.data.mongodb) testRuntimeOnly(libs.h2) + testRuntimeOnly(libs.mongodb.driver.sync) } diff --git a/spring-boot-autoconfigure-batch-plus-kotlin/src/integrationTest/kotlin/com/navercorp/spring/boot/autoconfigure/batch/plus/kotlin/BatchPlusAutoConfigurationIT.kt b/spring-boot-autoconfigure-batch-plus-kotlin/src/integrationTest/kotlin/com/navercorp/spring/boot/autoconfigure/batch/plus/kotlin/BatchPlusAutoConfigurationIT.kt index 8979f780..d5efbf1a 100644 --- a/spring-boot-autoconfigure-batch-plus-kotlin/src/integrationTest/kotlin/com/navercorp/spring/boot/autoconfigure/batch/plus/kotlin/BatchPlusAutoConfigurationIT.kt +++ b/spring-boot-autoconfigure-batch-plus-kotlin/src/integrationTest/kotlin/com/navercorp/spring/boot/autoconfigure/batch/plus/kotlin/BatchPlusAutoConfigurationIT.kt @@ -23,6 +23,8 @@ import org.assertj.core.api.Assertions.assertThat import org.assertj.core.api.Assertions.assertThatThrownBy import org.junit.jupiter.api.Test import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing +import org.springframework.batch.core.configuration.annotation.EnableJdbcJobRepository +import org.springframework.batch.core.configuration.annotation.EnableMongoJobRepository import org.springframework.batch.core.repository.JobRepository import org.springframework.beans.factory.BeanFactory import org.springframework.beans.factory.getBean @@ -30,41 +32,76 @@ import org.springframework.boot.autoconfigure.AutoConfigurations import org.springframework.boot.test.context.assertj.AssertableApplicationContext import org.springframework.boot.test.context.runner.ApplicationContextRunner import org.springframework.context.annotation.Bean +import org.springframework.data.mongodb.MongoDatabaseFactory +import org.springframework.data.mongodb.MongoTransactionManager +import org.springframework.data.mongodb.core.MongoOperations import org.springframework.jdbc.datasource.DataSourceTransactionManager import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType import org.springframework.transaction.TransactionManager +import java.lang.reflect.Proxy import javax.sql.DataSource private class BatchPlusAutoConfigurationIT { - - private val contextRunner = ApplicationContextRunner() - .withConfiguration(AutoConfigurations.of(BatchPlusAutoConfiguration::class.java)) + private val contextRunner = + ApplicationContextRunner() + .withConfiguration(AutoConfigurations.of(BatchPlusAutoConfiguration::class.java)) @Test - fun autoConfigure() { - @EnableBatchProcessing( + fun autoConfigureWithJdbcJobRepository() { + @EnableBatchProcessing + @EnableJdbcJobRepository( dataSourceRef = "metadataDataSource", transactionManagerRef = "metadataTransactionManager", ) class BatchConfiguration { - @Bean - fun metadataTransactionManager(): TransactionManager { - return DataSourceTransactionManager(metadataDataSource()) - } + fun metadataTransactionManager(): TransactionManager = DataSourceTransactionManager(metadataDataSource()) @Bean - fun metadataDataSource(): DataSource { - return EmbeddedDatabaseBuilder() + fun metadataDataSource(): DataSource = + EmbeddedDatabaseBuilder() .setType(EmbeddedDatabaseType.H2) .addScript("/org/springframework/batch/core/schema-h2.sql") .generateUniqueName(true) .build() + } + + contextRunner + .withUserConfiguration(BatchConfiguration::class.java) + .run { context: AssertableApplicationContext -> + assertThat(context).hasSingleBean(BatchDsl::class.java) + } + } + + @Test + fun autoConfigureWithMongoJobRepository() { + @EnableBatchProcessing + @EnableMongoJobRepository( + mongoOperationsRef = "metadataMongoOperations", + transactionManagerRef = "metadataMongoTransactionManager", + ) + class BatchConfiguration { + @Bean + fun metadataMongoOperations(): MongoOperations = + Proxy.newProxyInstance( + MongoOperations::class.java.classLoader, + arrayOf(MongoOperations::class.java), + ) { _, _, _ -> null } as MongoOperations + + @Bean + fun metadataMongoTransactionManager(): MongoTransactionManager { + val factory = + Proxy.newProxyInstance( + MongoDatabaseFactory::class.java.classLoader, + arrayOf(MongoDatabaseFactory::class.java), + ) { _, _, _ -> null } as MongoDatabaseFactory + return MongoTransactionManager(factory) } } - contextRunner.withUserConfiguration(BatchConfiguration::class.java) + contextRunner + .withUserConfiguration(BatchConfiguration::class.java) .run { context: AssertableApplicationContext -> assertThat(context).hasSingleBean(BatchDsl::class.java) } @@ -72,7 +109,8 @@ private class BatchPlusAutoConfigurationIT { @Test fun autoConfigureShouldNotRegisterWhenAlreadyRegisteredOneExists() { - @EnableBatchProcessing( + @EnableBatchProcessing + @EnableJdbcJobRepository( dataSourceRef = "metadataDataSource", transactionManagerRef = "metadataTransactionManager", ) @@ -81,29 +119,26 @@ private class BatchPlusAutoConfigurationIT { fun batchDsl( beanFactory: BeanFactory, jobRepository: JobRepository, - ): BatchDsl { - return BatchDsl( + ): BatchDsl = + BatchDsl( beanFactory, jobRepository, ) - } @Bean - fun metadataTransactionManager(): TransactionManager { - return DataSourceTransactionManager(metadataDataSource()) - } + fun metadataTransactionManager(): TransactionManager = DataSourceTransactionManager(metadataDataSource()) @Bean - fun metadataDataSource(): DataSource { - return EmbeddedDatabaseBuilder() + fun metadataDataSource(): DataSource = + EmbeddedDatabaseBuilder() .setType(EmbeddedDatabaseType.H2) .addScript("/org/springframework/batch/core/schema-h2.sql") .generateUniqueName(true) .build() - } } - contextRunner.withUserConfiguration(BatchConfiguration::class.java) + contextRunner + .withUserConfiguration(BatchConfiguration::class.java) .run { context: AssertableApplicationContext -> assertThat(context).hasSingleBean(BatchDsl::class.java) } diff --git a/spring-boot-autoconfigure-batch-plus-kotlin/src/main/kotlin/com/navercorp/spring/boot/autoconfigure/batch/plus/kotlin/BatchPlusAutoConfiguration.kt b/spring-boot-autoconfigure-batch-plus-kotlin/src/main/kotlin/com/navercorp/spring/boot/autoconfigure/batch/plus/kotlin/BatchPlusAutoConfiguration.kt index 4ba4056c..8ddd9a23 100644 --- a/spring-boot-autoconfigure-batch-plus-kotlin/src/main/kotlin/com/navercorp/spring/boot/autoconfigure/batch/plus/kotlin/BatchPlusAutoConfiguration.kt +++ b/spring-boot-autoconfigure-batch-plus-kotlin/src/main/kotlin/com/navercorp/spring/boot/autoconfigure/batch/plus/kotlin/BatchPlusAutoConfiguration.kt @@ -22,9 +22,9 @@ import com.navercorp.spring.batch.plus.kotlin.configuration.BatchDsl import org.springframework.batch.core.repository.JobRepository import org.springframework.beans.factory.BeanFactory import org.springframework.boot.autoconfigure.AutoConfiguration -import org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration import org.springframework.boot.autoconfigure.condition.ConditionalOnBean import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean +import org.springframework.boot.batch.jdbc.autoconfigure.BatchJdbcAutoConfiguration import org.springframework.context.annotation.Bean /** @@ -32,19 +32,17 @@ import org.springframework.context.annotation.Bean * * @since 0.1.0 */ -@AutoConfiguration(after = [BatchAutoConfiguration::class]) +@AutoConfiguration(after = [BatchJdbcAutoConfiguration::class]) class BatchPlusAutoConfiguration { - @Bean @ConditionalOnMissingBean @ConditionalOnBean(value = [JobRepository::class]) fun batchDsl( beanFactory: BeanFactory, jobRepository: JobRepository, - ): BatchDsl { - return BatchDsl( + ): BatchDsl = + BatchDsl( beanFactory, jobRepository, ) - } }