From de2f3c572861fc0b526c76b78e57ab3eba81fa64 Mon Sep 17 00:00:00 2001 From: linghengqian Date: Mon, 29 Jul 2024 16:20:17 +0800 Subject: [PATCH] Provides built-in GraalVM Reachability Metadata and nativeTest on Elasticjob Spring Boot Starter under Spring Boot 3.2.8 --- .github/workflows/graalvm.yml | 3 +- .../bootstrap/type/OneOffJobBootstrap.java | 2 +- .../configuration/graalvm-native-image.cn.md | 23 +++- .../configuration/graalvm-native-image.en.md | 23 +++- pom.xml | 16 +++ .../proxy-config.json | 2 +- .../reflect-config.json | 85 +++++++------- .../resource-config.json | 14 ++- spring/boot-starter/pom.xml | 1 + .../native-image-filter/extra-filter.json | 9 +- test/native/pom.xml | 27 ++++- ...lasticJobSpringBootStarterApplication.java | 31 +++++ .../elasticjob/test/natived/JavaTest.java | 2 +- .../test/natived/SpirngBootTest.java | 108 ++++++++++++++++++ .../controller/OneOffJobController.java | 52 +++++++++ .../job/dataflow/SpringBootDataflowJob.java | 62 ++++++++++ .../job/simple/SpringBootSimpleJob.java | 51 +++++++++ .../repository/SpringBootFooRepository.java | 74 ++++++++++++ .../native/src/test/resources/application.yml | 55 +++++++++ .../{script => test-native/sh}/demo.sh | 0 20 files changed, 580 insertions(+), 60 deletions(-) create mode 100644 test/native/src/test/java/org/apache/shardingsphere/elasticjob/test/natived/ElasticJobSpringBootStarterApplication.java create mode 100644 test/native/src/test/java/org/apache/shardingsphere/elasticjob/test/natived/SpirngBootTest.java create mode 100644 test/native/src/test/java/org/apache/shardingsphere/elasticjob/test/natived/commons/controller/OneOffJobController.java create mode 100644 test/native/src/test/java/org/apache/shardingsphere/elasticjob/test/natived/commons/job/dataflow/SpringBootDataflowJob.java create mode 100644 test/native/src/test/java/org/apache/shardingsphere/elasticjob/test/natived/commons/job/simple/SpringBootSimpleJob.java create mode 100644 test/native/src/test/java/org/apache/shardingsphere/elasticjob/test/natived/commons/repository/SpringBootFooRepository.java create mode 100644 test/native/src/test/resources/application.yml rename test/native/src/test/resources/{script => test-native/sh}/demo.sh (100%) diff --git a/.github/workflows/graalvm.yml b/.github/workflows/graalvm.yml index fcff1f14e3..1216b9307f 100644 --- a/.github/workflows/graalvm.yml +++ b/.github/workflows/graalvm.yml @@ -34,7 +34,7 @@ jobs: os: [ 'ubuntu-latest' ] runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up GraalVM CE ${{ matrix.java }} uses: graalvm/setup-graalvm@v1 with: @@ -42,6 +42,7 @@ jobs: distribution: 'graalvm-community' github-token: ${{ secrets.GITHUB_TOKEN }} cache: 'maven' + native-image-job-reports: 'true' - name: Run nativeTest with GraalVM CE for ${{ matrix.java-version }} continue-on-error: true run: ./mvnw -PnativeTestInElasticJob -T1C -B -e clean test diff --git a/bootstrap/src/main/java/org/apache/shardingsphere/elasticjob/bootstrap/type/OneOffJobBootstrap.java b/bootstrap/src/main/java/org/apache/shardingsphere/elasticjob/bootstrap/type/OneOffJobBootstrap.java index dc0599ccdd..31cfe784d1 100644 --- a/bootstrap/src/main/java/org/apache/shardingsphere/elasticjob/bootstrap/type/OneOffJobBootstrap.java +++ b/bootstrap/src/main/java/org/apache/shardingsphere/elasticjob/bootstrap/type/OneOffJobBootstrap.java @@ -30,7 +30,7 @@ /** * One off job bootstrap. */ -public final class OneOffJobBootstrap implements JobBootstrap { +public class OneOffJobBootstrap implements JobBootstrap { private final JobScheduler jobScheduler; diff --git a/docs/content/user-manual/configuration/graalvm-native-image.cn.md b/docs/content/user-manual/configuration/graalvm-native-image.cn.md index 8a892fa376..3744146324 100644 --- a/docs/content/user-manual/configuration/graalvm-native-image.cn.md +++ b/docs/content/user-manual/configuration/graalvm-native-image.cn.md @@ -104,10 +104,29 @@ graalvmNative { 若 `script.command.line` 设置为构建 GraalVM Native Image 时, 私有项目的 classpath 下的某个 `.sh` 文件在 GraalVM Native Image 下的相对路径, 则此 `.sh` 文件至少提前设置 `rwxr-xr-x` 的 POSIX 文件权限。 因为 `com.oracle.svm.core.jdk.resources.NativeImageResourceFileSystem` 显然不支持 `java.nio.file.attribute.PosixFileAttributeView`。 +长话短说,用户应该避免在作业内包含类似如下的逻辑, + +```java +import java.io.IOException; +import java.net.URL; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.attribute.PosixFilePermissions; + +public class ExampleUtils { + public void setPosixFilePermissions() throws IOException { + URL resource = ExampleUtils.class.getResource("/script/demo.sh"); + assert resource != null; + Path path = Paths.get(resource.getPath()); + Files.setPosixFilePermissions(path, PosixFilePermissions.fromString("rwxr-xr-x")); + } +} +``` -3. ElasticJob 的 Spring 命名空间集成模块 `org.apache.shardingsphere.elasticjob:elasticjob-spring-namespace` 尚未在 GraalVM Native Image 下可用。 +3. `企业微信通知策略`,`钉钉通知策略`,`邮件通知策略`尚未在 GraalVM Native Image 下可用。 -4. ElasticJob 的 Spring Boot Starter 集成模块 `org.apache.shardingsphere.elasticjob:elasticjob-spring-boot-starter` 尚未在 GraalVM Native Image 下可用。 +4. ElasticJob 的 Spring 命名空间集成模块 `org.apache.shardingsphere.elasticjob:elasticjob-spring-namespace` 尚未在 GraalVM Native Image 下可用。 ## 贡献 GraalVM Reachability Metadata diff --git a/docs/content/user-manual/configuration/graalvm-native-image.en.md b/docs/content/user-manual/configuration/graalvm-native-image.en.md index 5b9018c8c5..028f20afc9 100644 --- a/docs/content/user-manual/configuration/graalvm-native-image.en.md +++ b/docs/content/user-manual/configuration/graalvm-native-image.en.md @@ -106,10 +106,29 @@ Users can quickly collect GraalVM Reachability Metadata through the GraalVM Trac if `script.command.line` is set to the relative path of a `.sh` file in the private project's classpath under the GraalVM Native Image when building the GraalVM Native Image, then the `.sh` file must at least have the POSIX file permission of `rwxr-xr-x` set in advance. This is because `com.oracle.svm.core.jdk.resources.NativeImageResourceFileSystem` obviously does not support `java.nio.file.attribute.PosixFileAttributeView`. +Long story short, users should avoid including logic like the following in their jobs, + +```java +import java.io.IOException; +import java.net.URL; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.attribute.PosixFilePermissions; + +public class ExampleUtils { + public void setPosixFilePermissions() throws IOException { + URL resource = ExampleUtils.class.getResource("/script/demo.sh"); + assert resource != null; + Path path = Paths.get(resource.getPath()); + Files.setPosixFilePermissions(path, PosixFilePermissions.fromString("rwxr-xr-x")); + } +} +``` -3. The Spring namespace integration module `org.apache.shardingsphere.elasticjob:elasticjob-spring-namespace` of ElasticJob is not yet available under GraalVM Native Image. +3. `WeCom Notification Policy`, `DingTalk Notification Policy`, and `Email Notification Policy` are not yet available in GraalVM Native Image. -4. The Spring Boot Starter integration module `org.apache.shardingsphere.elasticjob:elasticjob-spring-boot-starter` for ElasticJob is not yet available under GraalVM Native Image. +4. The Spring namespace integration module `org.apache.shardingsphere.elasticjob:elasticjob-spring-namespace` of ElasticJob is not yet available under GraalVM Native Image. ## Contribute GraalVM Reachability Metadata diff --git a/pom.xml b/pom.xml index 15a3aa9ca4..db8ce221dd 100644 --- a/pom.xml +++ b/pom.xml @@ -93,6 +93,9 @@ 2.2.224 4.0.3 + + 3.2.8 + 3.2.1 3.11.0 @@ -1015,6 +1018,19 @@ + + org.springframework.boot + spring-boot-maven-plugin + ${spring-boot-dependencies.version} + + + process-test-aot + + process-test-aot + + + + diff --git a/reachability-metadata/src/main/resources/META-INF/native-image/org.apache.shardingsphere.elasticjob/generated-reachability-metadata/proxy-config.json b/reachability-metadata/src/main/resources/META-INF/native-image/org.apache.shardingsphere.elasticjob/generated-reachability-metadata/proxy-config.json index fd2d4325f4..25cf820544 100644 --- a/reachability-metadata/src/main/resources/META-INF/native-image/org.apache.shardingsphere.elasticjob/generated-reachability-metadata/proxy-config.json +++ b/reachability-metadata/src/main/resources/META-INF/native-image/org.apache.shardingsphere.elasticjob/generated-reachability-metadata/proxy-config.json @@ -1,6 +1,6 @@ [ { - "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.tracing.rdb.storage.converter.RDBTracingStorageConfigurationConverter"}, + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.spring.boot.tracing.ElasticJobTracingConfiguration$RDBTracingConfiguration"}, "interfaces":["java.sql.Connection"] } ] \ 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/reflect-config.json b/reachability-metadata/src/main/resources/META-INF/native-image/org.apache.shardingsphere.elasticjob/generated-reachability-metadata/reflect-config.json index b934e85204..a6240cc3fc 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 @@ -4,9 +4,8 @@ "name":"[Lcom.zaxxer.hikari.util.ConcurrentBag$IConcurrentBagEntry;" }, { - "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.bootstrap.type.ScheduleJobBootstrap"}, - "name":"java.util.Properties", - "methods":[{"name":"","parameterTypes":[] }] + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.spring.boot.tracing.ElasticJobTracingConfiguration$RDBTracingConfiguration"}, + "name":"[Ljava.sql.Statement;" }, { "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.kernel.executor.ElasticJobExecutor"}, @@ -23,11 +22,26 @@ "name":"java.util.Properties", "methods":[{"name":"","parameterTypes":[] }] }, +{ + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.kernel.internal.sharding.ShardingListenerManager$ListenServersChangedJobListener"}, + "name":"java.util.Properties", + "methods":[{"name":"","parameterTypes":[] }] +}, { "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.kernel.internal.sharding.ShardingListenerManager$ShardingTotalCountChangedJobListener"}, "name":"java.util.Properties", "methods":[{"name":"","parameterTypes":[] }] }, +{ + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.bootstrap.type.OneOffJobBootstrap$$SpringCGLIB$$0"}, + "name":"org.apache.shardingsphere.elasticjob.bootstrap.type.OneOffJobBootstrap", + "queryAllDeclaredMethods":true, + "methods":[{"name":"execute","parameterTypes":[] }, {"name":"shutdown","parameterTypes":[] }] +}, +{ + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.bootstrap.type.OneOffJobBootstrap$$SpringCGLIB$$0"}, + "name":"org.apache.shardingsphere.elasticjob.bootstrap.type.OneOffJobBootstrap$$SpringCGLIB$$0" +}, { "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.kernel.executor.item.JobItemExecutorFactory"}, "name":"org.apache.shardingsphere.elasticjob.dataflow.executor.DataflowJobExecutor" @@ -48,7 +62,7 @@ "methods":[{"name":"","parameterTypes":[] }] }, { - "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.kernel.executor.ElasticJobExecutor"}, + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.spring.boot.job.ElasticJobBootstrapConfiguration"}, "name":"org.apache.shardingsphere.elasticjob.http.executor.HttpJobExecutor" }, { @@ -59,21 +73,15 @@ "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", - "queryAllPublicMethods":true -}, { "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.bootstrap.type.ScheduleJobBootstrap"}, "name":"org.apache.shardingsphere.elasticjob.kernel.internal.config.JobConfigurationPOJO", - "queryAllPublicMethods":true, - "methods":[{"name":"setCron","parameterTypes":["java.lang.String"] }, {"name":"setProps","parameterTypes":["java.util.Properties"] }] + "methods":[{"name":"setCron","parameterTypes":["java.lang.String"] }] }, { "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.kernel.executor.ElasticJobExecutor"}, "name":"org.apache.shardingsphere.elasticjob.kernel.internal.config.JobConfigurationPOJO", - "methods":[{"name":"setCron","parameterTypes":["java.lang.String"] }, {"name":"setProps","parameterTypes":["java.util.Properties"] }] + "methods":[{"name":"setProps","parameterTypes":["java.util.Properties"] }] }, { "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.kernel.infra.yaml.YamlEngine"}, @@ -98,15 +106,20 @@ "methods":[{"name":"setCron","parameterTypes":["java.lang.String"] }, {"name":"setProps","parameterTypes":["java.util.Properties"] }] }, { - "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.kernel.internal.schedule.JobScheduler"}, + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.kernel.internal.sharding.ShardingListenerManager$ListenServersChangedJobListener"}, "name":"org.apache.shardingsphere.elasticjob.kernel.internal.config.JobConfigurationPOJO", - "queryAllPublicMethods":true + "methods":[{"name":"setCron","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", "methods":[{"name":"setCron","parameterTypes":["java.lang.String"] }, {"name":"setProps","parameterTypes":["java.util.Properties"] }] }, +{ + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.spring.boot.job.ElasticJobBootstrapConfiguration"}, + "name":"org.apache.shardingsphere.elasticjob.kernel.internal.config.JobConfigurationPOJO", + "queryAllPublicMethods":true +}, { "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.bootstrap.type.ScheduleJobBootstrap"}, "name":"org.apache.shardingsphere.elasticjob.kernel.internal.config.JobConfigurationPOJOBeanInfo" @@ -115,22 +128,20 @@ "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.bootstrap.type.ScheduleJobBootstrap"}, "name":"org.apache.shardingsphere.elasticjob.kernel.internal.config.JobConfigurationPOJOCustomizer" }, -{ - "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.bootstrap.type.OneOffJobBootstrap"}, - "name":"org.apache.shardingsphere.elasticjob.kernel.internal.schedule.JobShutdownHookPlugin", - "queryAllPublicMethods":true -}, { "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.bootstrap.type.ScheduleJobBootstrap"}, - "name":"org.apache.shardingsphere.elasticjob.kernel.internal.schedule.JobShutdownHookPlugin", - "queryAllPublicMethods":true + "name":"org.apache.shardingsphere.elasticjob.kernel.internal.schedule.JobShutdownHookPlugin" }, { "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.kernel.internal.schedule.JobScheduler"}, "name":"org.apache.shardingsphere.elasticjob.kernel.internal.schedule.JobShutdownHookPlugin", - "queryAllPublicMethods":true, "methods":[{"name":"","parameterTypes":[] }, {"name":"setCleanShutdown","parameterTypes":["boolean"] }] }, +{ + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.spring.boot.job.ElasticJobBootstrapConfiguration"}, + "name":"org.apache.shardingsphere.elasticjob.kernel.internal.schedule.JobShutdownHookPlugin", + "queryAllPublicMethods":true +}, { "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.bootstrap.type.ScheduleJobBootstrap"}, "name":"org.apache.shardingsphere.elasticjob.kernel.internal.schedule.JobShutdownHookPluginBeanInfo" @@ -139,15 +150,9 @@ "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.bootstrap.type.ScheduleJobBootstrap"}, "name":"org.apache.shardingsphere.elasticjob.kernel.internal.schedule.JobShutdownHookPluginCustomizer" }, -{ - "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.bootstrap.type.OneOffJobBootstrap"}, - "name":"org.apache.shardingsphere.elasticjob.kernel.internal.sharding.JobInstance", - "queryAllPublicMethods":true -}, { "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.bootstrap.type.ScheduleJobBootstrap"}, - "name":"org.apache.shardingsphere.elasticjob.kernel.internal.sharding.JobInstance", - "queryAllPublicMethods":true + "name":"org.apache.shardingsphere.elasticjob.kernel.internal.sharding.JobInstance" }, { "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.kernel.internal.instance.InstanceNode"}, @@ -156,18 +161,10 @@ "methods":[{"name":"getJobInstanceId","parameterTypes":[] }, {"name":"getLabels","parameterTypes":[] }, {"name":"getServerIp","parameterTypes":[] }] }, { - "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.kernel.internal.instance.InstanceService"}, - "name":"org.apache.shardingsphere.elasticjob.kernel.internal.sharding.JobInstance" -}, -{ - "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.kernel.internal.schedule.JobScheduler"}, + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.spring.boot.job.ElasticJobBootstrapConfiguration"}, "name":"org.apache.shardingsphere.elasticjob.kernel.internal.sharding.JobInstance", "queryAllPublicMethods":true }, -{ - "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.kernel.internal.setup.SetUpFacade"}, - "name":"org.apache.shardingsphere.elasticjob.kernel.internal.sharding.JobInstance" -}, { "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.bootstrap.type.ScheduleJobBootstrap"}, "name":"org.apache.shardingsphere.elasticjob.kernel.internal.sharding.JobInstanceBeanInfo" @@ -191,7 +188,7 @@ "name":"org.apache.shardingsphere.elasticjob.reg.zookeeper.exception.ZookeeperCuratorIgnoredExceptionProvider" }, { - "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.kernel.executor.ElasticJobExecutor"}, + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.spring.boot.job.ElasticJobBootstrapConfiguration"}, "name":"org.apache.shardingsphere.elasticjob.script.executor.ScriptJobExecutor" }, { @@ -199,17 +196,21 @@ "name":"org.apache.shardingsphere.elasticjob.simple.executor.SimpleJobExecutor" }, { - "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.kernel.tracing.event.JobTracingEventBus"}, + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.spring.boot.job.ElasticJobBootstrapConfiguration"}, "name":"org.apache.shardingsphere.elasticjob.spi.tracing.listener.TracingListener", "queryAllDeclaredMethods":true }, { - "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.kernel.tracing.event.JobTracingEventBus"}, + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.kernel.internal.setup.JobClassNameProviderFactory"}, + "name":"org.apache.shardingsphere.elasticjob.spring.core.setup.SpringProxyJobClassNameProvider" +}, +{ + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.spring.boot.job.ElasticJobBootstrapConfiguration"}, "name":"org.apache.shardingsphere.elasticjob.tracing.rdb.listener.RDBTracingListener", "queryAllDeclaredMethods":true }, { - "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.kernel.tracing.event.JobTracingEventBus"}, + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.spring.boot.job.ElasticJobBootstrapConfiguration"}, "name":"org.apache.shardingsphere.elasticjob.tracing.rdb.listener.RDBTracingListenerFactory" }, { 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 101e57e2fc..07292ac065 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 @@ -1,6 +1,9 @@ { "resources":{ "includes":[{ + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.spring.boot.tracing.ElasticJobTracingConfiguration$RDBTracingConfiguration"}, + "pattern":"\\QMETA-INF/services/java.sql.Driver\\E" + }, { "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.kernel.executor.threadpool.ExecutorServiceReloader"}, "pattern":"\\QMETA-INF/services/org.apache.shardingsphere.elasticjob.kernel.executor.threadpool.JobExecutorThreadPoolSizeProvider\\E" }, { @@ -10,16 +13,16 @@ "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.reg.exception.RegExceptionHandler"}, "pattern":"\\QMETA-INF/services/org.apache.shardingsphere.elasticjob.reg.exception.IgnoredExceptionProvider\\E" }, { - "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.bootstrap.type.ScheduleJobBootstrap"}, + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.spring.boot.job.ElasticJobBootstrapConfiguration"}, "pattern":"\\QMETA-INF/services/org.apache.shardingsphere.elasticjob.spi.executor.error.handler.JobErrorHandler\\E" }, { "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.kernel.executor.item.JobItemExecutorFactory"}, "pattern":"\\QMETA-INF/services/org.apache.shardingsphere.elasticjob.spi.executor.item.type.ClassedJobItemExecutor\\E" }, { - "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.kernel.executor.ElasticJobExecutor"}, + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.spring.boot.job.ElasticJobBootstrapConfiguration"}, "pattern":"\\QMETA-INF/services/org.apache.shardingsphere.elasticjob.spi.executor.item.type.TypedJobItemExecutor\\E" }, { - "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.kernel.tracing.event.JobTracingEventBus"}, + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.spring.boot.job.ElasticJobBootstrapConfiguration"}, "pattern":"\\QMETA-INF/services/org.apache.shardingsphere.elasticjob.spi.tracing.listener.TracingListenerFactory\\E" }, { "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.kernel.tracing.storage.TracingStorageConverterFactory"}, @@ -34,7 +37,10 @@ "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.tracing.rdb.storage.sql.SQLPropertiesFactory"}, "pattern":"\\QMETA-INF/sql/H2.properties\\E" }, { - "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.bootstrap.type.ScheduleJobBootstrap"}, + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.spring.boot.tracing.ElasticJobTracingConfiguration$RDBTracingConfiguration"}, + "pattern":"\\Qorg/h2/util/data.zip\\E" + }, { + "condition":{"typeReachable":"org.apache.shardingsphere.elasticjob.spring.boot.job.ElasticJobBootstrapConfiguration"}, "pattern":"\\Qorg/quartz/core/quartz-build.properties\\E" }]}, "bundles":[] diff --git a/spring/boot-starter/pom.xml b/spring/boot-starter/pom.xml index 7fa77d5704..f685104a77 100644 --- a/spring/boot-starter/pom.xml +++ b/spring/boot-starter/pom.xml @@ -42,6 +42,7 @@ org.springframework.boot spring-boot-starter + true org.springframework.boot diff --git a/test/native/native-image-filter/extra-filter.json b/test/native/native-image-filter/extra-filter.json index 9e706a39d4..fdf91f4da0 100644 --- a/test/native/native-image-filter/extra-filter.json +++ b/test/native/native-image-filter/extra-filter.json @@ -2,13 +2,12 @@ "rules": [ {"includeClasses": "**"}, - {"excludeClasses": "com.google.common.util.concurrent.**"}, - {"excludeClasses": "com.zaxxer.hikari.**"}, + {"excludeClasses": "com.**"}, {"excludeClasses": "java.**"}, {"includeClasses": "java.util.Properties"}, - {"excludeClasses": "org.apache.zookeeper.**"}, - {"excludeClasses": "org.quartz.**"}, - {"excludeClasses": "sun.misc.**"}, + {"excludeClasses": "org.**"}, + {"includeClasses": "org.apache.shardingsphere.elasticjob.**"}, + {"excludeClasses": "sun.**"}, {"excludeClasses": "org.apache.shardingsphere.elasticjob.test.natived.**"} ], diff --git a/test/native/pom.xml b/test/native/pom.xml index 459222a528..f3cca8f28e 100644 --- a/test/native/pom.xml +++ b/test/native/pom.xml @@ -28,12 +28,14 @@ true + 2.0.7 + 1.4.14 org.apache.shardingsphere.elasticjob - elasticjob-bootstrap + elasticjob-spring-boot-starter ${project.version} test @@ -53,6 +55,24 @@ curator-test test + + org.springframework.boot + spring-boot-starter-jdbc + ${spring-boot-dependencies.version} + test + + + org.springframework.boot + spring-boot-starter-web + ${spring-boot-dependencies.version} + test + + + org.springframework.boot + spring-boot-starter-test + ${spring-boot-dependencies.version} + test + @@ -62,6 +82,11 @@ native-maven-plugin ${native-maven-plugin.version} + + org.springframework.boot + spring-boot-maven-plugin + ${spring-boot-dependencies.version} + diff --git a/test/native/src/test/java/org/apache/shardingsphere/elasticjob/test/natived/ElasticJobSpringBootStarterApplication.java b/test/native/src/test/java/org/apache/shardingsphere/elasticjob/test/natived/ElasticJobSpringBootStarterApplication.java new file mode 100644 index 0000000000..e62b3d87b5 --- /dev/null +++ b/test/native/src/test/java/org/apache/shardingsphere/elasticjob/test/natived/ElasticJobSpringBootStarterApplication.java @@ -0,0 +1,31 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.shardingsphere.elasticjob.test.natived; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class ElasticJobSpringBootStarterApplication { + + // CHECKSTYLE:OFF + public static void main(final String[] args) { + // CHECKSTYLE:ON + SpringApplication.run(ElasticJobSpringBootStarterApplication.class, args); + } +} diff --git a/test/native/src/test/java/org/apache/shardingsphere/elasticjob/test/natived/JavaTest.java b/test/native/src/test/java/org/apache/shardingsphere/elasticjob/test/natived/JavaTest.java index 1abcead7ef..8b8212854c 100644 --- a/test/native/src/test/java/org/apache/shardingsphere/elasticjob/test/natived/JavaTest.java +++ b/test/native/src/test/java/org/apache/shardingsphere/elasticjob/test/natived/JavaTest.java @@ -157,7 +157,7 @@ void testScriptJob() { ScheduleJobBootstrap jobBootstrap = new ScheduleJobBootstrap(regCenter, "SCRIPT", JobConfiguration.newBuilder("scriptElasticJob", 3) .cron("0/5 * * * * ?") - .setProperty(ScriptJobProperties.SCRIPT_KEY, Paths.get("src/test/resources/script/demo.sh").toString()) + .setProperty(ScriptJobProperties.SCRIPT_KEY, Paths.get("src/test/resources/test-native/sh/demo.sh").toString()) .addExtraConfigurations(tracingConfig) .build()); assertDoesNotThrow(() -> { diff --git a/test/native/src/test/java/org/apache/shardingsphere/elasticjob/test/natived/SpirngBootTest.java b/test/native/src/test/java/org/apache/shardingsphere/elasticjob/test/natived/SpirngBootTest.java new file mode 100644 index 0000000000..73e6d9752d --- /dev/null +++ b/test/native/src/test/java/org/apache/shardingsphere/elasticjob/test/natived/SpirngBootTest.java @@ -0,0 +1,108 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.shardingsphere.elasticjob.test.natived; + +import org.apache.curator.CuratorZookeeperClient; +import org.apache.curator.retry.ExponentialBackoffRetry; +import org.apache.curator.test.TestingServer; +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.boot.test.context.SpringBootTest; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.DynamicPropertyRegistry; +import org.springframework.test.context.DynamicPropertySource; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultHandlers; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.web.context.WebApplicationContext; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.time.Duration; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; + +@SpringBootTest( + classes = ElasticJobSpringBootStarterApplication.class, + webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +@TestPropertySource(locations = "classpath:application.yml") +@EnabledInNativeImage +public class SpirngBootTest { + + private static TestingServer testingServer; + + private MockMvc mockMvc; + + @BeforeAll + static void beforeAll() throws Exception { + testingServer = new TestingServer(6181); + try ( + CuratorZookeeperClient client = new CuratorZookeeperClient(testingServer.getConnectString(), + 60 * 1000, 500, null, + new ExponentialBackoffRetry(500, 3, 500 * 3))) { + client.start(); + Awaitility.await().atMost(Duration.ofMillis(500 * 60)).until(client::isConnected); + } + } + + @AfterAll + static void afterAll() throws IOException { + testingServer.close(); + } + + @BeforeEach + void setup(final WebApplicationContext webApplicationContext) { + this.mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext) + .defaultResponseCharacterEncoding(StandardCharsets.UTF_8) + .build(); + } + + @DynamicPropertySource + static void elasticjobProperties(final DynamicPropertyRegistry registry) { + registry.add("elasticjob.regCenter.serverLists", () -> testingServer.getConnectString()); + } + + /** + * ElasticJob Spring Boot Starter requires that all Spring Boot Applications be shut down before shutting down Zookeeper Server. + * That's why this unit test uses {@link DirtiesContext}. + * Refer to spring-projects/spring-framework#26196 . + */ + @DirtiesContext + @Test + public void testOneOffJob() throws Exception { + String contentAsString = mockMvc.perform( + MockMvcRequestBuilders.get("/execute/manualScriptJob") + .characterEncoding(StandardCharsets.UTF_8)) + .andDo(MockMvcResultHandlers.print()) + .andExpectAll( + MockMvcResultMatchers.status().isOk(), + MockMvcResultMatchers.content().encoding(StandardCharsets.UTF_8)) + .andReturn() + .getResponse() + .getContentAsString(); + assertThat(contentAsString, is("{\"msg\":\"OK\"}")); + } +} diff --git a/test/native/src/test/java/org/apache/shardingsphere/elasticjob/test/natived/commons/controller/OneOffJobController.java b/test/native/src/test/java/org/apache/shardingsphere/elasticjob/test/natived/commons/controller/OneOffJobController.java new file mode 100644 index 0000000000..873c6fcb94 --- /dev/null +++ b/test/native/src/test/java/org/apache/shardingsphere/elasticjob/test/natived/commons/controller/OneOffJobController.java @@ -0,0 +1,52 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.shardingsphere.elasticjob.test.natived.commons.controller; + +import org.apache.shardingsphere.elasticjob.bootstrap.type.OneOffJobBootstrap; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.context.annotation.Lazy; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class OneOffJobController { + + private static final String RES_TEXT = "{\"msg\":\"OK\"}"; + + /** + * TODO Need to fix apache/shardingsphere-elasticjob#2389 . + */ + @SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection") + @Lazy + @Autowired + @Qualifier("manualScriptJobBean") + private OneOffJobBootstrap manualScriptJob; + + /** + * Execute manual script job. + * + * @return a String + */ + @GetMapping("/execute/manualScriptJob") + public String executeManualScriptJob() { + manualScriptJob.execute(); + manualScriptJob.shutdown(); + return RES_TEXT; + } +} diff --git a/test/native/src/test/java/org/apache/shardingsphere/elasticjob/test/natived/commons/job/dataflow/SpringBootDataflowJob.java b/test/native/src/test/java/org/apache/shardingsphere/elasticjob/test/natived/commons/job/dataflow/SpringBootDataflowJob.java new file mode 100644 index 0000000000..992ca14dca --- /dev/null +++ b/test/native/src/test/java/org/apache/shardingsphere/elasticjob/test/natived/commons/job/dataflow/SpringBootDataflowJob.java @@ -0,0 +1,62 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.shardingsphere.elasticjob.test.natived.commons.job.dataflow; + +import org.apache.shardingsphere.elasticjob.dataflow.job.DataflowJob; +import org.apache.shardingsphere.elasticjob.spi.executor.item.param.ShardingContext; +import org.apache.shardingsphere.elasticjob.test.natived.commons.entity.Foo; +import org.apache.shardingsphere.elasticjob.test.natived.commons.repository.SpringBootFooRepository; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.lang.invoke.MethodHandles; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.List; + +@SuppressWarnings("LoggingSimilarMessage") +@Component +public class SpringBootDataflowJob implements DataflowJob { + + private final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); + + @Autowired + private SpringBootFooRepository springBootFooRepository; + + @Override + public List fetchData(final ShardingContext shardingContext) { + logger.info("Item: {} | Time: {} | Thread: {} | {}", + shardingContext.getShardingItem(), + new SimpleDateFormat("HH:mm:ss").format(new Date()), + Thread.currentThread().getId(), + "DATAFLOW FETCH"); + return springBootFooRepository.findTodoData(shardingContext.getShardingParameter(), 10); + } + + @Override + public void processData(final ShardingContext shardingContext, final List data) { + logger.info("Item: {} | Time: {} | Thread: {} | {}", + shardingContext.getShardingItem(), + new SimpleDateFormat("HH:mm:ss").format(new Date()), + Thread.currentThread().getId(), + "DATAFLOW PROCESS"); + data.forEach(each -> springBootFooRepository.setCompleted(each.getId())); + } +} diff --git a/test/native/src/test/java/org/apache/shardingsphere/elasticjob/test/natived/commons/job/simple/SpringBootSimpleJob.java b/test/native/src/test/java/org/apache/shardingsphere/elasticjob/test/natived/commons/job/simple/SpringBootSimpleJob.java new file mode 100644 index 0000000000..1185636d26 --- /dev/null +++ b/test/native/src/test/java/org/apache/shardingsphere/elasticjob/test/natived/commons/job/simple/SpringBootSimpleJob.java @@ -0,0 +1,51 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.shardingsphere.elasticjob.test.natived.commons.job.simple; + +import org.apache.shardingsphere.elasticjob.simple.job.SimpleJob; +import org.apache.shardingsphere.elasticjob.spi.executor.item.param.ShardingContext; +import org.apache.shardingsphere.elasticjob.test.natived.commons.repository.SpringBootFooRepository; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.lang.invoke.MethodHandles; +import java.text.SimpleDateFormat; +import java.util.Date; + +@Component +public class SpringBootSimpleJob implements SimpleJob { + + private final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); + + @Autowired + private SpringBootFooRepository springBootFooRepository; + + @Override + public void execute(final ShardingContext shardingContext) { + logger.info( + "Item: {} | Time: {} | Thread: {} | {}", + shardingContext.getShardingItem(), + new SimpleDateFormat("HH:mm:ss").format(new Date()), + Thread.currentThread().getId(), + "SIMPLE"); + springBootFooRepository.findTodoData(shardingContext.getShardingParameter(), 10) + .forEach(each -> springBootFooRepository.setCompleted(each.getId())); + } +} diff --git a/test/native/src/test/java/org/apache/shardingsphere/elasticjob/test/natived/commons/repository/SpringBootFooRepository.java b/test/native/src/test/java/org/apache/shardingsphere/elasticjob/test/natived/commons/repository/SpringBootFooRepository.java new file mode 100644 index 0000000000..cafe2bb023 --- /dev/null +++ b/test/native/src/test/java/org/apache/shardingsphere/elasticjob/test/natived/commons/repository/SpringBootFooRepository.java @@ -0,0 +1,74 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.shardingsphere.elasticjob.test.natived.commons.repository; + +import org.apache.shardingsphere.elasticjob.test.natived.commons.entity.Foo; +import org.springframework.stereotype.Repository; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.stream.LongStream; + +@Repository +public class SpringBootFooRepository { + + private final Map data = new ConcurrentHashMap<>(300, 1); + + public SpringBootFooRepository() { + addData(0L, 100L, "Beijing"); + addData(100L, 200L, "Shanghai"); + addData(200L, 300L, "Guangzhou"); + } + + private void addData(final long idFrom, final long idTo, final String location) { + LongStream.range(idFrom, idTo) + .forEachOrdered(i -> data.put(i, new Foo(i, location, Foo.Status.TODO))); + } + + /** + * Find todoData. + * @param location location + * @param limit limit + * @return An ordered collection, where the user has precise control over where in the list each element is inserted. + */ + public List findTodoData(final String location, final int limit) { + List result = new ArrayList<>(limit); + int count = 0; + for (Map.Entry each : data.entrySet()) { + Foo foo = each.getValue(); + if (foo.getLocation().equals(location) && foo.getStatus() == Foo.Status.TODO) { + result.add(foo); + count++; + if (count == limit) { + break; + } + } + } + return result; + } + + /** + * Set completed. + * @param id id + */ + public void setCompleted(final long id) { + data.get(id).setStatus(Foo.Status.COMPLETED); + } +} diff --git a/test/native/src/test/resources/application.yml b/test/native/src/test/resources/application.yml new file mode 100644 index 0000000000..1a99cecae9 --- /dev/null +++ b/test/native/src/test/resources/application.yml @@ -0,0 +1,55 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You 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. +# + +spring: + datasource: + url: jdbc:h2:mem:job_event_storage + driver-class-name: org.h2.Driver + username: sa + password: + +elasticjob: + tracing: + type: RDB + # `elasticjob.regCenter.serverLists` is dynamically defined in `org.apache.shardingsphere.elasticjob.test.natived.SpirngBootTest` + regCenter: + namespace: elasticjob-springboot + jobs: + simpleJob: + elasticJobClass: org.apache.shardingsphere.elasticjob.test.natived.commons.job.simple.SpringBootSimpleJob + cron: 0/5 * * * * ? + shardingTotalCount: 3 + shardingItemParameters: 0=Beijing,1=Shanghai,2=Guangzhou + dataflowJob: + elasticJobClass: org.apache.shardingsphere.elasticjob.test.natived.commons.job.dataflow.SpringBootDataflowJob + cron: 0/5 * * * * ? + shardingTotalCount: 3 + shardingItemParameters: 0=Beijing,1=Shanghai,2=Guangzhou + scriptJob: + elasticJobType: SCRIPT + cron: 0/10 * * * * ? + shardingTotalCount: 3 + props: + script.command.line: "echo SCRIPT Job: " + manualScriptJob: + elasticJobType: SCRIPT + jobBootstrapBeanName: manualScriptJobBean + shardingTotalCount: 9 + props: + script.command.line: "echo Manual SCRIPT Job: " + dump: + port: 9888 diff --git a/test/native/src/test/resources/script/demo.sh b/test/native/src/test/resources/test-native/sh/demo.sh similarity index 100% rename from test/native/src/test/resources/script/demo.sh rename to test/native/src/test/resources/test-native/sh/demo.sh