From fd648bfd074b8e911f4ab45b2c0461fe26437785 Mon Sep 17 00:00:00 2001 From: linghengqian Date: Fri, 1 Nov 2024 15:32:56 +0800 Subject: [PATCH] Fixes potential conflict in AOP proxy job class identification in Spring Framework --- RELEASE-NOTES.md | 1 + .../usage/job-api/spring-boot-starter.en.md | 2 +- .../reflect-config.json | 77 +++++++++++++++++-- .../resource-config.json | 3 + .../SpringProxyJobClassNameProvider.java | 20 ++++- .../natived/it/staticd/SpirngBootTest.java | 40 +++++++++- 6 files changed, 134 insertions(+), 9 deletions(-) diff --git a/RELEASE-NOTES.md b/RELEASE-NOTES.md index 18e002d95e..d1d4734247 100644 --- a/RELEASE-NOTES.md +++ b/RELEASE-NOTES.md @@ -20,6 +20,7 @@ 1. Build: Removes non-existent `elasticjob-tracing-api` and `elasticjob-error-handler-spi` module - [#2412](https://github.com/apache/shardingsphere-elasticjob/pull/2412) 1. Spring Boot Starter: Fixes the issue that OneOffJobBootstrap cannot be used under ElasticJob Spring Boot Starter - [#2014](https://github.com/apache/shardingsphere-elasticjob/issues/2014) +1. Spring: Fixes potential conflict in AOP proxy job class identification in Spring Framework - [#2012](https://github.com/apache/shardingsphere-elasticjob/issues/2012) ### Change Logs diff --git a/docs/content/user-manual/usage/job-api/spring-boot-starter.en.md b/docs/content/user-manual/usage/job-api/spring-boot-starter.en.md index 901389477b..8653c9061e 100644 --- a/docs/content/user-manual/usage/job-api/spring-boot-starter.en.md +++ b/docs/content/user-manual/usage/job-api/spring-boot-starter.en.md @@ -107,7 +107,7 @@ import java.util.Objects; @RestController public class OneOffJobController { - // 通过 "@Autowired" 注入 + // Injection via "@Autowired" @Autowired @Qualifier("myOneOffJobBean") private ObjectProvider myOneOffJobProvider; diff --git a/reachability-metadata/src/main/resources/META-INF/native-image/org.apache.shardingsphere.elasticjob/generated-reachability-metadata/reflect-config.json b/reachability-metadata/src/main/resources/META-INF/native-image/org.apache.shardingsphere.elasticjob/generated-reachability-metadata/reflect-config.json index 5681355f1c..0da5ce96e7 100644 --- a/reachability-metadata/src/main/resources/META-INF/native-image/org.apache.shardingsphere.elasticjob/generated-reachability-metadata/reflect-config.json +++ b/reachability-metadata/src/main/resources/META-INF/native-image/org.apache.shardingsphere.elasticjob/generated-reachability-metadata/reflect-config.json @@ -11,6 +11,15 @@ "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.spring.boot.tracing.ElasticJobTracingConfiguration$RDBTracingConfiguration"}, "name":"[Ljava.sql.Statement;" }, +{ + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.tracing.rdb.storage.repository.RDBJobEventRepository"}, + "name":"[Ljava.sql.Statement;" +}, +{ + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.bootstrap.type.OneOffJobBootstrap"}, + "name":"java.util.Properties", + "methods":[{"name":"","parameterTypes":[] }] +}, { "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.kernel.executor.ElasticJobExecutor"}, "name":"java.util.Properties", @@ -36,6 +45,11 @@ "name":"java.util.Properties", "methods":[{"name":"","parameterTypes":[] }] }, +{ + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.spring.boot.job.ElasticJobBootstrapConfiguration"}, + "name":"java.util.Properties", + "methods":[{"name":"","parameterTypes":[] }] +}, { "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.kernel.executor.item.JobItemExecutorFactory"}, "name":"org.apache.shardingsphere.elasticjob.dataflow.executor.DataflowJobExecutor" @@ -67,6 +81,11 @@ "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.kernel.executor.threadpool.ExecutorServiceReloader"}, "name":"org.apache.shardingsphere.elasticjob.kernel.executor.threadpool.type.SingleThreadJobExecutorThreadPoolSizeProvider" }, +{ + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.bootstrap.type.OneOffJobBootstrap"}, + "name":"org.apache.shardingsphere.elasticjob.kernel.internal.config.JobConfigurationPOJO", + "methods":[{"name":"setProps","parameterTypes":["java.util.Properties"] }] +}, { "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.bootstrap.type.ScheduleJobBootstrap"}, "name":"org.apache.shardingsphere.elasticjob.kernel.internal.config.JobConfigurationPOJO", @@ -97,12 +116,21 @@ "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.kernel.internal.failover.FailoverListenerManager$FailoverSettingsChangedJobListener"}, "name":"org.apache.shardingsphere.elasticjob.kernel.internal.config.JobConfigurationPOJO", "allDeclaredFields":true, - "methods":[{"name":"","parameterTypes":[] }, {"name":"setCron","parameterTypes":["java.lang.String"] }, {"name":"setDisabled","parameterTypes":["boolean"] }, {"name":"setFailover","parameterTypes":["boolean"] }, {"name":"setJobExtraConfigurations","parameterTypes":["java.util.Collection"] }, {"name":"setJobName","parameterTypes":["java.lang.String"] }, {"name":"setMaxTimeDiffSeconds","parameterTypes":["int"] }, {"name":"setMisfire","parameterTypes":["boolean"] }, {"name":"setMonitorExecution","parameterTypes":["boolean"] }, {"name":"setOverwrite","parameterTypes":["boolean"] }, {"name":"setReconcileIntervalMinutes","parameterTypes":["int"] }, {"name":"setShardingItemParameters","parameterTypes":["java.lang.String"] }, {"name":"setShardingTotalCount","parameterTypes":["int"] }, {"name":"setStaticSharding","parameterTypes":["boolean"] }] + "methods":[{"name":"","parameterTypes":[] }, {"name":"setCron","parameterTypes":["java.lang.String"] }, {"name":"setDescription","parameterTypes":["java.lang.String"] }, {"name":"setDisabled","parameterTypes":["boolean"] }, {"name":"setFailover","parameterTypes":["boolean"] }, {"name":"setJobExtraConfigurations","parameterTypes":["java.util.Collection"] }, {"name":"setJobName","parameterTypes":["java.lang.String"] }, {"name":"setJobParameter","parameterTypes":["java.lang.String"] }, {"name":"setJobShardingStrategyType","parameterTypes":["java.lang.String"] }, {"name":"setMaxTimeDiffSeconds","parameterTypes":["int"] }, {"name":"setMisfire","parameterTypes":["boolean"] }, {"name":"setMonitorExecution","parameterTypes":["boolean"] }, {"name":"setOverwrite","parameterTypes":["boolean"] }, {"name":"setReconcileIntervalMinutes","parameterTypes":["int"] }, {"name":"setShardingItemParameters","parameterTypes":["java.lang.String"] }, {"name":"setShardingTotalCount","parameterTypes":["int"] }, {"name":"setStaticSharding","parameterTypes":["boolean"] }] +}, +{ + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.kernel.internal.failover.FailoverListenerManager$JobCrashedJobListener"}, + "name":"org.apache.shardingsphere.elasticjob.kernel.internal.config.JobConfigurationPOJO", + "methods":[{"name":"setJobShardingStrategyType","parameterTypes":["java.lang.String"] }] }, { "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.kernel.internal.reconcile.ReconcileService"}, "name":"org.apache.shardingsphere.elasticjob.kernel.internal.config.JobConfigurationPOJO", - "methods":[{"name":"setCron","parameterTypes":["java.lang.String"] }, {"name":"setProps","parameterTypes":["java.util.Properties"] }] + "methods":[{"name":"setCron","parameterTypes":["java.lang.String"] }, {"name":"setJobShardingStrategyType","parameterTypes":["java.lang.String"] }, {"name":"setProps","parameterTypes":["java.util.Properties"] }] +}, +{ + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.kernel.internal.schedule.JobScheduler"}, + "name":"org.apache.shardingsphere.elasticjob.kernel.internal.config.JobConfigurationPOJO" }, { "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.kernel.internal.sharding.ExecutionContextService"}, @@ -118,18 +146,18 @@ "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.kernel.internal.sharding.MonitorExecutionListenerManager$MonitorExecutionSettingsChangedJobListener"}, "name":"org.apache.shardingsphere.elasticjob.kernel.internal.config.JobConfigurationPOJO", "allDeclaredFields":true, - "methods":[{"name":"","parameterTypes":[] }, {"name":"setCron","parameterTypes":["java.lang.String"] }, {"name":"setDisabled","parameterTypes":["boolean"] }, {"name":"setFailover","parameterTypes":["boolean"] }, {"name":"setJobExtraConfigurations","parameterTypes":["java.util.Collection"] }, {"name":"setJobName","parameterTypes":["java.lang.String"] }, {"name":"setMaxTimeDiffSeconds","parameterTypes":["int"] }, {"name":"setMisfire","parameterTypes":["boolean"] }, {"name":"setMonitorExecution","parameterTypes":["boolean"] }, {"name":"setOverwrite","parameterTypes":["boolean"] }, {"name":"setReconcileIntervalMinutes","parameterTypes":["int"] }, {"name":"setShardingItemParameters","parameterTypes":["java.lang.String"] }, {"name":"setShardingTotalCount","parameterTypes":["int"] }, {"name":"setStaticSharding","parameterTypes":["boolean"] }] + "methods":[{"name":"","parameterTypes":[] }, {"name":"setCron","parameterTypes":["java.lang.String"] }, {"name":"setDescription","parameterTypes":["java.lang.String"] }, {"name":"setDisabled","parameterTypes":["boolean"] }, {"name":"setFailover","parameterTypes":["boolean"] }, {"name":"setJobExtraConfigurations","parameterTypes":["java.util.Collection"] }, {"name":"setJobName","parameterTypes":["java.lang.String"] }, {"name":"setJobParameter","parameterTypes":["java.lang.String"] }, {"name":"setJobShardingStrategyType","parameterTypes":["java.lang.String"] }, {"name":"setMaxTimeDiffSeconds","parameterTypes":["int"] }, {"name":"setMisfire","parameterTypes":["boolean"] }, {"name":"setMonitorExecution","parameterTypes":["boolean"] }, {"name":"setOverwrite","parameterTypes":["boolean"] }, {"name":"setReconcileIntervalMinutes","parameterTypes":["int"] }, {"name":"setShardingItemParameters","parameterTypes":["java.lang.String"] }, {"name":"setShardingTotalCount","parameterTypes":["int"] }, {"name":"setStaticSharding","parameterTypes":["boolean"] }] }, { "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.kernel.internal.sharding.ShardingListenerManager$ListenServersChangedJobListener"}, "name":"org.apache.shardingsphere.elasticjob.kernel.internal.config.JobConfigurationPOJO", - "methods":[{"name":"setCron","parameterTypes":["java.lang.String"] }, {"name":"setProps","parameterTypes":["java.util.Properties"] }] + "methods":[{"name":"setCron","parameterTypes":["java.lang.String"] }, {"name":"setJobShardingStrategyType","parameterTypes":["java.lang.String"] }, {"name":"setProps","parameterTypes":["java.util.Properties"] }] }, { "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.kernel.internal.sharding.ShardingListenerManager$ShardingTotalCountChangedJobListener"}, "name":"org.apache.shardingsphere.elasticjob.kernel.internal.config.JobConfigurationPOJO", "allDeclaredFields":true, - "methods":[{"name":"","parameterTypes":[] }, {"name":"setCron","parameterTypes":["java.lang.String"] }, {"name":"setDescription","parameterTypes":["java.lang.String"] }, {"name":"setDisabled","parameterTypes":["boolean"] }, {"name":"setFailover","parameterTypes":["boolean"] }, {"name":"setJobExtraConfigurations","parameterTypes":["java.util.Collection"] }, {"name":"setJobName","parameterTypes":["java.lang.String"] }, {"name":"setJobParameter","parameterTypes":["java.lang.String"] }, {"name":"setMaxTimeDiffSeconds","parameterTypes":["int"] }, {"name":"setMisfire","parameterTypes":["boolean"] }, {"name":"setMonitorExecution","parameterTypes":["boolean"] }, {"name":"setOverwrite","parameterTypes":["boolean"] }, {"name":"setProps","parameterTypes":["java.util.Properties"] }, {"name":"setReconcileIntervalMinutes","parameterTypes":["int"] }, {"name":"setShardingItemParameters","parameterTypes":["java.lang.String"] }, {"name":"setShardingTotalCount","parameterTypes":["int"] }, {"name":"setStaticSharding","parameterTypes":["boolean"] }] + "methods":[{"name":"","parameterTypes":[] }, {"name":"setCron","parameterTypes":["java.lang.String"] }, {"name":"setDescription","parameterTypes":["java.lang.String"] }, {"name":"setDisabled","parameterTypes":["boolean"] }, {"name":"setFailover","parameterTypes":["boolean"] }, {"name":"setJobExtraConfigurations","parameterTypes":["java.util.Collection"] }, {"name":"setJobName","parameterTypes":["java.lang.String"] }, {"name":"setJobParameter","parameterTypes":["java.lang.String"] }, {"name":"setJobShardingStrategyType","parameterTypes":["java.lang.String"] }, {"name":"setMaxTimeDiffSeconds","parameterTypes":["int"] }, {"name":"setMisfire","parameterTypes":["boolean"] }, {"name":"setMonitorExecution","parameterTypes":["boolean"] }, {"name":"setOverwrite","parameterTypes":["boolean"] }, {"name":"setProps","parameterTypes":["java.util.Properties"] }, {"name":"setReconcileIntervalMinutes","parameterTypes":["int"] }, {"name":"setShardingItemParameters","parameterTypes":["java.lang.String"] }, {"name":"setShardingTotalCount","parameterTypes":["int"] }, {"name":"setStaticSharding","parameterTypes":["boolean"] }] }, { "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.kernel.internal.sharding.ShardingService"}, @@ -151,7 +179,8 @@ { "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.spring.boot.job.ElasticJobBootstrapConfiguration"}, "name":"org.apache.shardingsphere.elasticjob.kernel.internal.config.JobConfigurationPOJO", - "queryAllPublicMethods":true + "queryAllPublicMethods":true, + "methods":[{"name":"setCron","parameterTypes":["java.lang.String"] }, {"name":"setProps","parameterTypes":["java.util.Properties"] }] }, { "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.bootstrap.type.ScheduleJobBootstrap"}, @@ -293,10 +322,28 @@ "allDeclaredFields":true, "methods":[{"name":"","parameterTypes":[] }, {"name":"setTracingStorageConfiguration","parameterTypes":["org.apache.shardingsphere.elasticjob.kernel.tracing.yaml.YamlTracingStorageConfiguration"] }, {"name":"setType","parameterTypes":["java.lang.String"] }] }, +{ + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.spring.boot.job.ElasticJobBootstrapConfiguration"}, + "name":"org.apache.shardingsphere.elasticjob.kernel.tracing.yaml.YamlTracingConfiguration", + "queryAllPublicMethods":true +}, +{ + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.spring.boot.job.ElasticJobBootstrapConfiguration"}, + "name":"org.apache.shardingsphere.elasticjob.kernel.tracing.yaml.YamlTracingConfigurationBeanInfo" +}, { "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.kernel.internal.config.JobConfigurationPOJO"}, "name":"org.apache.shardingsphere.elasticjob.kernel.tracing.yaml.YamlTracingConfigurationConverter" }, +{ + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.spring.boot.job.ElasticJobBootstrapConfiguration"}, + "name":"org.apache.shardingsphere.elasticjob.kernel.tracing.yaml.YamlTracingConfigurationCustomizer" +}, +{ + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.spring.boot.job.ElasticJobBootstrapConfiguration"}, + "name":"org.apache.shardingsphere.elasticjob.kernel.tracing.yaml.YamlTracingStorageConfiguration", + "queryAllPublicMethods":true +}, { "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.reg.exception.RegExceptionHandler"}, "name":"org.apache.shardingsphere.elasticjob.reg.zookeeper.exception.ZookeeperCuratorIgnoredExceptionProvider" @@ -314,6 +361,11 @@ "name":"org.apache.shardingsphere.elasticjob.spi.tracing.listener.TracingListener", "queryAllDeclaredMethods":true }, +{ + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.spring.boot.job.ElasticJobBootstrapConfiguration"}, + "name":"org.apache.shardingsphere.elasticjob.spi.yaml.YamlConfiguration", + "queryAllPublicMethods":true +}, { "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.kernel.internal.setup.JobClassNameProviderFactory"}, "name":"org.apache.shardingsphere.elasticjob.spring.core.setup.SpringProxyJobClassNameProvider" @@ -391,8 +443,21 @@ "allDeclaredFields":true, "methods":[{"name":"","parameterTypes":[] }, {"name":"setDataSourceClassName","parameterTypes":["java.lang.String"] }, {"name":"setProps","parameterTypes":["java.util.Map"] }] }, +{ + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.spring.boot.job.ElasticJobBootstrapConfiguration"}, + "name":"org.apache.shardingsphere.elasticjob.tracing.rdb.yaml.YamlDataSourceConfiguration", + "queryAllPublicMethods":true +}, +{ + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.spring.boot.job.ElasticJobBootstrapConfiguration"}, + "name":"org.apache.shardingsphere.elasticjob.tracing.rdb.yaml.YamlDataSourceConfigurationBeanInfo" +}, { "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.kernel.internal.config.JobConfigurationPOJO"}, "name":"org.apache.shardingsphere.elasticjob.tracing.rdb.yaml.YamlDataSourceConfigurationConverter" +}, +{ + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.spring.boot.job.ElasticJobBootstrapConfiguration"}, + "name":"org.apache.shardingsphere.elasticjob.tracing.rdb.yaml.YamlDataSourceConfigurationCustomizer" } ] \ No newline at end of file diff --git a/reachability-metadata/src/main/resources/META-INF/native-image/org.apache.shardingsphere.elasticjob/generated-reachability-metadata/resource-config.json b/reachability-metadata/src/main/resources/META-INF/native-image/org.apache.shardingsphere.elasticjob/generated-reachability-metadata/resource-config.json index 7fe2417552..c0171aa711 100644 --- a/reachability-metadata/src/main/resources/META-INF/native-image/org.apache.shardingsphere.elasticjob/generated-reachability-metadata/resource-config.json +++ b/reachability-metadata/src/main/resources/META-INF/native-image/org.apache.shardingsphere.elasticjob/generated-reachability-metadata/resource-config.json @@ -33,6 +33,9 @@ }, { "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.kernel.internal.config.JobConfigurationPOJO"}, "pattern":"\\QMETA-INF/services/org.apache.shardingsphere.elasticjob.spi.yaml.YamlConfigurationConverter\\E" + }, { + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.tracing.rdb.config.RDBTracingStorageConfiguration"}, + "pattern":"\\QMETA-INF/services/org.apache.shardingsphere.elasticjob.tracing.rdb.storage.datasource.JDBCParameterDecorator\\E" }, { "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.tracing.rdb.storage.repository.RDBJobEventRepository"}, "pattern":"\\QMETA-INF/services/org.apache.shardingsphere.elasticjob.tracing.rdb.storage.type.TracingStorageDatabaseType\\E" diff --git a/spring/core/src/main/java/org/apache/shardingsphere/elasticjob/spring/core/setup/SpringProxyJobClassNameProvider.java b/spring/core/src/main/java/org/apache/shardingsphere/elasticjob/spring/core/setup/SpringProxyJobClassNameProvider.java index 69f9e80eeb..bf81ece7eb 100644 --- a/spring/core/src/main/java/org/apache/shardingsphere/elasticjob/spring/core/setup/SpringProxyJobClassNameProvider.java +++ b/spring/core/src/main/java/org/apache/shardingsphere/elasticjob/spring/core/setup/SpringProxyJobClassNameProvider.java @@ -33,12 +33,30 @@ @Slf4j public final class SpringProxyJobClassNameProvider implements JobClassNameProvider { + private static final String LAMBDA_CHARACTERISTICS = "$$Lambda"; + public SpringProxyJobClassNameProvider() { log.info("create SpringProxyJobClassNameProvider"); } @Override public String getJobClassName(final ElasticJob elasticJob) { - return AopUtils.isAopProxy(elasticJob) ? AopTargetUtils.getTarget(elasticJob).getClass().getName() : elasticJob.getClass().getName(); + if (!AopUtils.isAopProxy(elasticJob)) { + return getJobClassName(elasticJob.getClass()); + } + return getJobClassName(AopTargetUtils.getTarget(elasticJob).getClass()); + } + + private String getJobClassName(final Class elasticJobClass) { + String elasticJobClassName = elasticJobClass.getName(); + return isLambdaClass(elasticJobClass) ? trimLambdaClassSuffix(elasticJobClassName) : elasticJobClassName; + } + + private boolean isLambdaClass(final Class elasticJobClass) { + return elasticJobClass.isSynthetic() && elasticJobClass.getSimpleName().contains(LAMBDA_CHARACTERISTICS); + } + + private String trimLambdaClassSuffix(final String className) { + return className.substring(0, className.lastIndexOf(LAMBDA_CHARACTERISTICS) + LAMBDA_CHARACTERISTICS.length()); } } diff --git a/test/native/src/test/java/org/apache/shardingsphere/elasticjob/test/natived/it/staticd/SpirngBootTest.java b/test/native/src/test/java/org/apache/shardingsphere/elasticjob/test/natived/it/staticd/SpirngBootTest.java index c07a635ea7..a8c32abcb2 100644 --- a/test/native/src/test/java/org/apache/shardingsphere/elasticjob/test/natived/it/staticd/SpirngBootTest.java +++ b/test/native/src/test/java/org/apache/shardingsphere/elasticjob/test/natived/it/staticd/SpirngBootTest.java @@ -21,12 +21,18 @@ import org.apache.curator.retry.ExponentialBackoffRetry; import org.apache.curator.test.InstanceSpec; import org.apache.curator.test.TestingServer; +import org.apache.shardingsphere.elasticjob.api.JobConfiguration; +import org.apache.shardingsphere.elasticjob.bootstrap.type.ScheduleJobBootstrap; +import org.apache.shardingsphere.elasticjob.reg.zookeeper.ZookeeperRegistryCenter; +import org.apache.shardingsphere.elasticjob.simple.job.SimpleJob; import org.awaitility.Awaitility; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.condition.EnabledInNativeImage; +import org.springframework.beans.factory.ObjectProvider; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.DynamicPropertyRegistry; @@ -41,14 +47,19 @@ import java.io.IOException; import java.nio.charset.StandardCharsets; import java.time.Duration; +import java.util.Objects; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) @EnabledInNativeImage class SpirngBootTest { + @Autowired + private ObjectProvider zookeeperRegistryCenterProvider; + private static TestingServer testingServer; private MockMvc mockMvc; @@ -61,7 +72,7 @@ static void elasticjobProperties(final DynamicPropertyRegistry registry) { @BeforeAll static void beforeAll() throws Exception { - testingServer = new TestingServer(6181); + testingServer = new TestingServer(); try ( CuratorZookeeperClient client = new CuratorZookeeperClient(testingServer.getConnectString(), 60 * 1000, 500, null, @@ -103,4 +114,31 @@ public void testOneOffJob() throws Exception { .getContentAsString(); assertThat(contentAsString, is("{\"msg\":\"OK\"}")); } + + @DirtiesContext + @Test + void testIssue2012() { + ZookeeperRegistryCenter zookeeperRegistryCenter = zookeeperRegistryCenterProvider.getIfAvailable(); + Objects.requireNonNull(zookeeperRegistryCenter); + JobConfiguration jobConfig = JobConfiguration.newBuilder("test", 1) + .jobParameter("") + .cron("0 30 2 ? * *") + .overwrite(true) + .jobShardingStrategyType("ROUND_ROBIN") + .monitorExecution(true) + .failover(true) + .build(); + ScheduleJobBootstrap firstJob = new ScheduleJobBootstrap(zookeeperRegistryCenter, + (SimpleJob) shardingContext -> System.out.println("test"), + jobConfig); + ScheduleJobBootstrap secondJob = new ScheduleJobBootstrap(zookeeperRegistryCenter, + (SimpleJob) shardingContext -> System.out.println("test"), + jobConfig); + assertDoesNotThrow(() -> { + firstJob.schedule(); + secondJob.schedule(); + firstJob.shutdown(); + secondJob.shutdown(); + }); + } }