You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@seatunnel.apache.org by ga...@apache.org on 2023/05/23 02:48:08 UTC

[seatunnel-web] branch add_canvas_job_define updated: [Feature][datasource] Add datasource api (#57)

This is an automated email from the ASF dual-hosted git repository.

gaojun2048 pushed a commit to branch add_canvas_job_define
in repository https://gitbox.apache.org/repos/asf/seatunnel-web.git


The following commit(s) were added to refs/heads/add_canvas_job_define by this push:
     new 15a7bdee [Feature][datasource] Add datasource api (#57)
15a7bdee is described below

commit 15a7bdeeddb4ac6db55f9cddefdeb83e9a09bf9f
Author: xiaoqigh <17...@163.com>
AuthorDate: Tue May 23 10:48:03 2023 +0800

    [Feature][datasource] Add datasource api (#57)
---
 pom.xml                                            |  28 +-
 .../datasource/service/DataSourceService.java      |   2 +-
 .../datasource/s3/S3DatasourceChannelTest.java     |   7 +-
 .../datasource/plugin/api/model/TableField.java    |   4 +
 seatunnel-server/seatunnel-app/pom.xml             |  18 +
 .../app/bean/connector/ConnectorCache.java         | 160 ++++
 .../apache/seatunnel/app/common/ConditionType.java |  63 ++
 .../org/apache/seatunnel/app/common/Constants.java | 658 ++++++++++++++++
 .../org/apache/seatunnel/app/common/DataType.java} |  26 +-
 .../org/apache/seatunnel/app/common/DbType.java    |  93 +++
 .../DependResult.java}                             |  12 +-
 .../DependentRelation.java}                        |  10 +-
 .../Direct.java}                                   |  11 +-
 .../EngineType.java}                               |  10 +-
 .../seatunnel/app/common/ExecutionStatus.java      | 250 ++++++
 .../Flag.java}                                     |  28 +-
 .../Priority.java}                                 |  31 +-
 .../ReleaseState.java}                             |  43 +-
 .../ResUploadType.java}                            |  12 +-
 .../ResourceType.java}                             |   9 +-
 .../org/apache/seatunnel/app/common/Status.java    | 854 +++++++++++++++++++++
 .../TaskTimeoutStrategy.java}                      |  43 +-
 .../TimeoutFlag.java}                              |  32 +-
 .../UdfType.java}                                  |  42 +-
 .../config/ConnectorDataSourceMapperConfig.java    | 138 ++++
 .../seatunnel/app/config/YamlSourceFactory.java    |  50 ++
 .../seatunnel/app/controller/BaseController.java   | 255 ++++++
 .../controller/ConnectorDataSourceController.java  | 108 +++
 .../controller/SeatunnelDatasourceController.java  | 425 ++++++++++
 .../app/controller/VirtualTableController.java     | 195 +++++
 .../seatunnel/app/dal/dao/IDatasourceDao.java      |  60 ++
 .../dao/IJobDefinitionDao.java}                    |  29 +-
 .../dao/IJobTaskDao.java}                          |  27 +-
 .../seatunnel/app/dal/dao/IJobVersionDao.java      |  23 +-
 .../org/apache/seatunnel/app/dal/dao/IUserDao.java |   9 +
 .../seatunnel/app/dal/dao/IVirtualTableDao.java    |  51 ++
 .../dao/TaskDefinitionDao.java}                    |  30 +-
 .../app/dal/dao/impl/DatasourceDaoImpl.java        | 139 ++++
 .../app/dal/dao/impl/JobDefinitionDaoImpl.java     |  94 +++
 .../seatunnel/app/dal/dao/impl/JobTaskDaoImpl.java |  90 +++
 .../app/dal/dao/impl/JobVersionDaoImpl.java        |  72 ++
 .../app/dal/dao/impl/TaskDefinitionDaoImpl.java    |  75 ++
 .../seatunnel/app/dal/dao/impl/UserDaoImpl.java    |   5 +
 .../app/dal/dao/impl/VirtualTableDaoImpl.java      | 139 ++++
 .../seatunnel/app/dal/entity/Datasource.java       |  67 ++
 .../entity/DefinitionGroupByUser.java}             |  39 +-
 .../seatunnel/app/dal/entity/JobDefinition.java    |  63 ++
 .../apache/seatunnel/app/dal/entity/JobTask.java   |  84 ++
 .../seatunnel/app/dal/entity/JobVersion.java       |  71 ++
 .../app/dal/entity/ProcessTaskRelation.java        | 107 +++
 .../app/dal/entity/ProcessTaskRelationLog.java     |  85 ++
 .../seatunnel/app/dal/entity/TaskDefinition.java   | 525 +++++++++++++
 .../app/dal/entity/TaskDefinitionExpand.java       |  42 +
 .../app/dal/entity/TaskDefinitionLog.java          |  99 +++
 .../seatunnel/app/dal/entity/TaskMainInfo.java     |  77 ++
 .../seatunnel/app/dal/entity/VirtualTable.java     |  70 ++
 .../{UserMapper.java => DatasourceMapper.java}     |  32 +-
 .../dal/mapper/{UserMapper.java => JobMapper.java} |  34 +-
 .../mapper/JobTaskMapper.java}                     |  10 +-
 .../mapper/JobVersionMapper.java}                  |  10 +-
 .../app/dal/mapper/ProcessTaskRelationMapper.java  | 222 ++++++
 .../dal/mapper/SeatunnalTaskDefinitionMapper.java  |  74 ++
 .../app/dal/mapper/TaskDefinitionMapper.java       | 111 +++
 .../app/dal/mapper/UserLoginLogMapper.java         |   2 +
 .../seatunnel/app/dal/mapper/UserMapper.java       |   4 +
 .../{UserMapper.java => VirtualTableMapper.java}   |  32 +-
 .../domain/dto/datasource/DatabaseTableFields.java |  24 +-
 .../dto/datasource/DatabaseTables.java}            |  18 +-
 .../app/domain/dto/datasource/TableInfo.java       |  26 +-
 .../seatunnel/app/domain/model/DateInterval.java   |  66 ++
 .../DependentItem.java}                            |  39 +-
 .../model/DependentTaskModel.java}                 |  15 +-
 .../seatunnel/app/domain/model/Property.java       | 138 ++++
 .../model/ResourceInfo.java}                       |  16 +-
 .../request/connector/ConnectorStatus.java}        |  10 +-
 .../request/connector/SceneMode.java}              |  10 +-
 .../request/datasource/VirtualTableFieldReq.java   |  60 ++
 .../domain/request/datasource/VirtualTableReq.java |  48 ++
 .../app/domain/request/job/JobConfig.java          |  18 +-
 .../DatasourceRes.java => request/job/JobReq.java} |  30 +-
 .../app/domain/request/job/TableSchemaReq.java     |  27 +-
 .../request/job/transform/ChangeOrder.java}        |  12 +-
 .../request/job/transform/Copy.java}               |  12 +-
 .../job/transform/CopyTransformOptions.java}       |  12 +-
 .../request/job/transform/DeleteField.java}        |  11 +-
 .../transform/FieldMapperTransformOptions.java}    |  14 +-
 .../request/job/transform/RenameField.java}        |  12 +-
 .../request/job/transform/Split.java}              |  16 +-
 .../job/transform/SplitTransformOptions.java}      |  12 +-
 .../request/job/transform/Transform.java}          |  12 +-
 .../request/job/transform/TransformOption.java}    |  10 +-
 .../request/job/transform/TransformOptions.java}   |   8 +-
 .../domain/response/datasource/DatasourceRes.java  |   9 +
 .../app/domain/response/job/JobConfigRes.java      |  18 +-
 .../app/domain/response/job/JobDefinitionRes.java  |  64 ++
 .../app/domain/response/job/JobTaskCheckRes.java   |  24 +-
 .../response/job/SchemaError.java}                 |  18 +-
 .../response/job/SchemaErrorType.java}             |   8 +-
 .../response/job/TableSchemaRes.java}              |  16 +-
 .../app/interceptor/AuthenticationInterceptor.java |   9 +-
 .../app/parameters/AbstractParameters.java         | 202 +++++
 .../DependentParameters.java}                      |  31 +-
 .../seatunnel/app/parameters/IParameters.java      |  38 +
 .../SubProcessParameters.java}                     |  21 +-
 .../resource/AbstractResourceParameters.java}      |  39 +-
 .../parameters/resource/DataSourceParameters.java  |  23 +-
 .../resource/ResourceParametersHelper.java         |  62 ++
 .../app/parameters/resource/UdfFuncParameters.java | 223 ++++++
 .../AvailableResourceRangeService.java}            |   9 +-
 .../AvailableResourceRangeServiceImpl.java         | 102 +++
 .../app/permission/ISeatunnelPermissonService.java |  60 ++
 .../permission/SeatunnelPermissionServiceImpl.java |  61 ++
 .../SeatunnelFuncPermissionKeyConstant.java        |  85 ++
 .../SeatunnelResourcePermissionModuleEnum.java}    |  13 +-
 .../seatunnel/app/service/IConnectorService.java   |  56 ++
 .../seatunnel/app/service/IDatasourceService.java  | 265 +++++++
 .../app/service/IJobDefinitionService.java         |  51 ++
 .../app/service/ISeatunnelBaseService.java         |  24 +-
 .../ITableSchemaService.java}                      |  32 +-
 .../app/service/IVirtualTableService.java          |  53 ++
 .../app/service/impl/ConnectorServiceImpl.java     | 312 ++++++++
 .../app/service/impl/DatasourceServiceImpl.java    | 626 +++++++++++++++
 .../app/service/impl/JobDefinitionServiceImpl.java | 229 ++++++
 .../app/service/impl/SeatunnelBaseServiceImpl.java |  53 ++
 .../app/service/impl/TableSchemaServiceImpl.java   | 202 +++++
 .../app/service/impl/VirtualTableServiceImpl.java  | 376 +++++++++
 .../AbstractDataSourceConfigSwitcher.java          |   6 +-
 .../datasource/DataSourceClientFactory.java        |   3 +-
 .../datasource/DataSourceConfigSwitcher.java       |  27 +-
 .../datasource/DataSourceConfigSwitcherUtils.java  |  44 +-
 .../impl/BaseJdbcDataSourceConfigSwitcher.java     |  15 +-
 .../impl/ClickhouseDataSourceConfigSwitcher.java   |   4 +-
 .../impl/DamengDataSourceConfigSwitcher.java}      |  17 +-
 .../ElasticSearchDataSourceConfigSwitcher.java     |   4 +-
 .../impl/KafkaDataSourceConfigSwitcher.java        |   8 +-
 .../KafkaKingbaseDataSourceConfigSwitcher.java     | 247 ++++++
 .../impl/KingBaseDataSourceConfigSwitcher.java}    |  21 +-
 .../impl/MysqlCDCDataSourceConfigSwitcher.java     |  13 +-
 .../impl/MysqlDatasourceConfigSwitcher.java        |   2 +-
 .../impl/OracleCDCDataSourceConfigSwitcher.java}   |  24 +-
 .../impl/OracleDataSourceConfigSwitcher.java       |   2 +-
 .../impl/PostgresCDCDataSourceConfigSwitcher.java  |  21 +-
 .../impl/PostgresqlDataSourceConfigSwitcher.java   |   8 +-
 .../impl/RedshiftDataSourceConfigSwitcher.java     |   4 +-
 .../impl/S3DataSourceConfigSwitcher.java           |   8 +-
 .../impl/S3RedshiftDataSourceConfigSwitcher.java   |   4 +-
 .../impl/SqlServerCDCDataSourceConfigSwitcher.java |  14 +-
 .../impl/SqlServerDataSourceConfigSwitcher.java    |   4 +-
 .../impl/StarRocksDataSourceConfigSwitcher.java    |   4 +-
 .../impl/TidbDataSourceConfigSwitcher.java         |   2 +-
 .../exceptions/UnSupportWrapperException.java      |   2 +-
 .../framework/FormOptionSort.java                  |   3 +-
 .../framework/PluginDiscoveryUtil.java             |   3 +-
 .../framework/SeaTunnelOptionRuleWrapper.java      |   3 +-
 .../framework/UnSupportWrapperException.java       |   3 +-
 .../transfrom/TransformConfigSwitcher.java         |  36 +
 .../transfrom/TransformConfigSwitcherProvider.java |  44 ++
 .../transfrom/TransformConfigSwitcherUtils.java    |  76 ++
 .../transfrom/impl/CopyTransformSwitcher.java      |  62 ++
 .../impl/FieldMapperTransformSwitcher.java         | 139 ++++
 .../impl/FiledEventTypeTransformSwitcher.java      |  48 ++
 .../transfrom/impl/ReplaceTransformSwitcher.java   |  50 ++
 .../transfrom/impl/SplitTransformSwitcher.java     |  75 ++
 .../app/thridparty/datasource/SchemaGenerator.java |  90 ---
 .../seatunnel/app/utils/CartesianProductUtils.java |  80 ++
 .../org/apache/seatunnel/app/utils/JSONUtils.java  | 396 ++++++++++
 .../apache/seatunnel/app/utils/PropertyUtils.java  | 334 ++++++++
 .../src/main/resources/common.properties           | 126 +++
 .../resources/connector-datasource-mapper.yaml     | 255 ++++++
 .../src/main/resources/i18n_en.config              | 296 +++++++
 .../src/main/resources/i18n_zh.config              | 295 +++++++
 .../seatunnel/app/dal/mapper/DataSourceMapper.xml  |  99 +++
 .../apache/seatunnel/app/dal/mapper/JobMapper.xml  |  76 ++
 .../app/dal/mapper/ProcessTaskRelationMapper.xml   | 212 +++++
 .../dal/mapper/SeatunnalTaskDefinitionMapper.xml   | 109 +++
 .../app/dal/mapper/TaskDefinitionMapper.xml        | 123 +++
 .../apache/seatunnel/app/dal/mapper/UserMapper.xml |   6 +
 .../app/dal/mapper/VirtualTableMapper.xml          |  61 ++
 .../main/resources/script/seatunnel_server_h2.sql  | 223 +++++-
 .../resources/script/seatunnel_server_mysql.sql    | 462 +++++++++--
 .../seatunnel/server/common/CodeGenerateUtils.java |  94 +++
 .../apache/seatunnel/server/common/Constants.java  |   2 +
 .../server/common/SeatunnelErrorEnum.java          |  69 +-
 seatunnel-web-dist/release-docs/LICENSE            |   6 +
 tools/dependencies/known-dependencies.txt          |   7 +
 185 files changed, 14056 insertions(+), 825 deletions(-)

diff --git a/pom.xml b/pom.xml
index fe5fccbb..adde6b03 100644
--- a/pom.xml
+++ b/pom.xml
@@ -61,7 +61,6 @@
         <maven-shade-plugin.version>3.3.0</maven-shade-plugin.version>
         <lombok.version>1.18.0</lombok.version>
         <skipUT>false</skipUT>
-
         <!-- dependency -->
         <commons.logging.version>1.2</commons.logging.version>
         <slf4j.version>1.7.25</slf4j.version>
@@ -98,7 +97,8 @@
         <jwt.version>0.10.7</jwt.version>
         <cron-utils.version>9.1.6</cron-utils.version>
         <commons-io.version>2.11.0</commons-io.version>
-
+        <jsr305.version>3.0.0</jsr305.version>
+        <auto-service-annotation.version>1.0.1</auto-service-annotation.version>
         <hadoop-uber.version>2.3.1</hadoop-uber.version>
         <hadoop-aws.version>3.1.4</hadoop-aws.version>
         <aws-java-sdk-bundle.version>1.11.271</aws-java-sdk-bundle.version>
@@ -500,6 +500,30 @@
                     </exclusion>
                 </exclusions>
             </dependency>
+            <dependency>
+                <groupId>org.apache.seatunnel</groupId>
+                <artifactId>seatunnel-datasource-client</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>com.google.auto.service</groupId>
+                <artifactId>auto-service-annotations</artifactId>
+                <version>${auto-service-annotation.version}</version>
+                <scope>compile</scope>
+            </dependency>
+
+            <dependency>
+                <groupId>org.apache.seatunnel</groupId>
+                <artifactId>datasource-s3</artifactId>
+                <version>${project.version}</version>
+                <scope>provided</scope>
+            </dependency>
+
+            <dependency>
+                <groupId>com.google.code.findbugs</groupId>
+                <artifactId>jsr305</artifactId>
+                <version>${jsr305.version}</version>
+            </dependency>
         </dependencies>
 
     </dependencyManagement>
diff --git a/seatunnel-datasource/seatunnel-datasource-client/src/main/java/org/apache/seatunnel/datasource/service/DataSourceService.java b/seatunnel-datasource/seatunnel-datasource-client/src/main/java/org/apache/seatunnel/datasource/service/DataSourceService.java
index 5e52c077..e777d5e9 100644
--- a/seatunnel-datasource/seatunnel-datasource-client/src/main/java/org/apache/seatunnel/datasource/service/DataSourceService.java
+++ b/seatunnel-datasource/seatunnel-datasource-client/src/main/java/org/apache/seatunnel/datasource/service/DataSourceService.java
@@ -59,7 +59,7 @@ public interface DataSourceService {
     /**
      * we can use this method to check data source connectivity
      *
-     * @param dataSourceParams data source params
+     * @param pluginName source params
      * @return check result
      */
     Boolean checkDataSourceConnectivity(String pluginName, Map<String, String> datasourceParams);
diff --git a/seatunnel-datasource/seatunnel-datasource-client/src/test/java/com/whaleops/datasource/s3/S3DatasourceChannelTest.java b/seatunnel-datasource/seatunnel-datasource-client/src/test/java/com/whaleops/datasource/s3/S3DatasourceChannelTest.java
index 50c3d2d5..ff13771a 100644
--- a/seatunnel-datasource/seatunnel-datasource-client/src/test/java/com/whaleops/datasource/s3/S3DatasourceChannelTest.java
+++ b/seatunnel-datasource/seatunnel-datasource-client/src/test/java/com/whaleops/datasource/s3/S3DatasourceChannelTest.java
@@ -17,8 +17,6 @@
 
 package com.whaleops.datasource.s3;
 
-import org.apache.seatunnel.datasource.plugin.s3.S3DatasourceChannel;
-
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Disabled;
 import org.junit.jupiter.api.Test;
@@ -29,13 +27,14 @@ import java.util.Map;
 
 @Disabled
 class S3DatasourceChannelTest {
-    private static S3DatasourceChannel S3_DATASOURCE_CHANNEL = new S3DatasourceChannel();
+    //    private static S3DatasourceChannel S3_DATASOURCE_CHANNEL = new S3DatasourceChannel();
 
     @Test
     void checkDataSourceConnectivity() {
         Assertions.assertDoesNotThrow(
                 () -> {
-                    S3_DATASOURCE_CHANNEL.checkDataSourceConnectivity("S3", createRequestParams());
+                    //                    S3_DATASOURCE_CHANNEL.checkDataSourceConnectivity("S3",
+                    // createRequestParams());
                 });
     }
 
diff --git a/seatunnel-datasource/seatunnel-datasource-plugins/datasource-plugins-api/src/main/java/org/apache/seatunnel/datasource/plugin/api/model/TableField.java b/seatunnel-datasource/seatunnel-datasource-plugins/datasource-plugins-api/src/main/java/org/apache/seatunnel/datasource/plugin/api/model/TableField.java
index fabcaf47..b9820c60 100644
--- a/seatunnel-datasource/seatunnel-datasource-plugins/datasource-plugins-api/src/main/java/org/apache/seatunnel/datasource/plugin/api/model/TableField.java
+++ b/seatunnel-datasource/seatunnel-datasource-plugins/datasource-plugins-api/src/main/java/org/apache/seatunnel/datasource/plugin/api/model/TableField.java
@@ -37,4 +37,8 @@ public class TableField {
     private Boolean nullable;
 
     private Map<String, String> properties;
+
+    private Boolean unSupport;
+
+    private String outputDataType;
 }
diff --git a/seatunnel-server/seatunnel-app/pom.xml b/seatunnel-server/seatunnel-app/pom.xml
index 6c5da47b..9580bb8a 100644
--- a/seatunnel-server/seatunnel-app/pom.xml
+++ b/seatunnel-server/seatunnel-app/pom.xml
@@ -238,5 +238,23 @@
             <groupId>com.cronutils</groupId>
             <artifactId>cron-utils</artifactId>
         </dependency>
+
+        <dependency>
+            <groupId>commons-io</groupId>
+            <artifactId>commons-io</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>com.google.auto.service</groupId>
+            <artifactId>auto-service-annotations</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.seatunnel</groupId>
+            <artifactId>datasource-s3</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.google.code.findbugs</groupId>
+            <artifactId>jsr305</artifactId>
+        </dependency>
     </dependencies>
 </project>
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/bean/connector/ConnectorCache.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/bean/connector/ConnectorCache.java
new file mode 100644
index 00000000..df0fc5aa
--- /dev/null
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/bean/connector/ConnectorCache.java
@@ -0,0 +1,160 @@
+/*
+ * 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.seatunnel.app.bean.connector;
+
+import org.apache.seatunnel.api.configuration.util.OptionRule;
+import org.apache.seatunnel.app.domain.response.connector.ConnectorFeature;
+import org.apache.seatunnel.app.domain.response.connector.ConnectorInfo;
+import org.apache.seatunnel.app.dynamicforms.FormStructure;
+import org.apache.seatunnel.app.thirdparty.framework.PluginDiscoveryUtil;
+import org.apache.seatunnel.common.config.Common;
+import org.apache.seatunnel.common.config.DeployMode;
+import org.apache.seatunnel.common.constants.PluginType;
+import org.apache.seatunnel.plugin.discovery.PluginIdentifier;
+import org.apache.seatunnel.server.common.SeatunnelErrorEnum;
+import org.apache.seatunnel.server.common.SeatunnelException;
+
+import org.springframework.stereotype.Component;
+
+import lombok.NonNull;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+@Component
+public class ConnectorCache {
+
+    private final ConcurrentMap<PluginType, List<ConnectorInfo>> downloadConnectorCache =
+            new ConcurrentHashMap<>();
+
+    private final ConcurrentMap<PluginType, List<ConnectorInfo>> allConnectorCache =
+            new ConcurrentHashMap<>();
+
+    private final ConcurrentMap<PluginIdentifier, OptionRule> allConnectorOptionRule =
+            new ConcurrentHashMap<>();
+
+    private List<ConnectorInfo> transformCache = new CopyOnWriteArrayList<>();
+
+    private ConcurrentMap<String, FormStructure> sourceFormStructureCache =
+            new ConcurrentHashMap<>();
+
+    private ConcurrentMap<String, FormStructure> sinkFormStructureCache = new ConcurrentHashMap<>();
+
+    private ConcurrentMap<String, FormStructure> transformFormStructureCache =
+            new ConcurrentHashMap<>();
+
+    private Map<PluginIdentifier, ConnectorFeature> featureMap = new HashMap<>();
+
+    public ConnectorCache() throws IOException {
+        refresh();
+    }
+
+    public List<ConnectorInfo> getAllConnectors(PluginType pluginType) {
+        return allConnectorCache.get(pluginType);
+    }
+
+    public List<ConnectorInfo> getTransform() {
+        return transformCache;
+    }
+
+    public List<ConnectorInfo> getDownLoadConnector(PluginType pluginType) {
+        return downloadConnectorCache.get(pluginType);
+    }
+
+    public List<ConnectorInfo> getNotDownLoadConnector(PluginType pluginType) {
+        Map<PluginIdentifier, ConnectorInfo> allConnectors =
+                allConnectorCache.get(pluginType).stream()
+                        .collect(
+                                Collectors.toMap(
+                                        ConnectorInfo::getPluginIdentifier, Function.identity()));
+        downloadConnectorCache
+                .get(pluginType)
+                .forEach(d -> allConnectors.remove(d.getPluginIdentifier()));
+        return new ArrayList<>(allConnectors.values());
+    }
+
+    public ConnectorFeature getConnectorFeature(PluginIdentifier connectorInfo) {
+        return featureMap.get(connectorInfo);
+    }
+
+    public synchronized void refresh() throws IOException {
+        Common.setDeployMode(DeployMode.CLIENT);
+        Map<PluginType, LinkedHashMap<PluginIdentifier, OptionRule>> allConnectors =
+                PluginDiscoveryUtil.getAllConnectors();
+        allConnectorOptionRule.clear();
+        allConnectors.forEach((key, value) -> allConnectorOptionRule.putAll(value));
+
+        downloadConnectorCache.put(
+                PluginType.SOURCE,
+                PluginDiscoveryUtil.getDownloadedConnectors(allConnectors, PluginType.SOURCE));
+        downloadConnectorCache.put(
+                PluginType.SINK,
+                PluginDiscoveryUtil.getDownloadedConnectors(allConnectors, PluginType.SINK));
+        allConnectorCache.put(
+                PluginType.SOURCE,
+                PluginDiscoveryUtil.getAllConnectorsFromPluginMapping(PluginType.SOURCE));
+        allConnectorCache.put(
+                PluginType.SINK,
+                PluginDiscoveryUtil.getAllConnectorsFromPluginMapping(PluginType.SINK));
+        transformCache = PluginDiscoveryUtil.getTransforms(allConnectors);
+
+        sourceFormStructureCache =
+                PluginDiscoveryUtil.getDownloadedConnectorFormStructures(
+                        allConnectors, PluginType.SOURCE);
+        sinkFormStructureCache =
+                PluginDiscoveryUtil.getDownloadedConnectorFormStructures(
+                        allConnectors, PluginType.SINK);
+        transformFormStructureCache = PluginDiscoveryUtil.getTransformFormStructures(allConnectors);
+        syncSourceFeature();
+    }
+
+    private void syncSourceFeature() throws IOException {
+        featureMap = PluginDiscoveryUtil.getConnectorFeatures(PluginType.SOURCE);
+    }
+
+    public FormStructure getFormStructure(
+            @NonNull String pluginType, @NonNull String connectorName) {
+        if (PluginType.SOURCE.getType().equals(pluginType)) {
+            return sourceFormStructureCache.get(connectorName);
+        }
+
+        if (PluginType.TRANSFORM.getType().equals(pluginType)) {
+            return transformFormStructureCache.get(connectorName);
+        }
+
+        if (PluginType.SINK.getType().equals(pluginType)) {
+            return sinkFormStructureCache.get(connectorName);
+        }
+
+        throw new SeatunnelException(SeatunnelErrorEnum.UNSUPPORTED_CONNECTOR_TYPE, pluginType);
+    }
+
+    public OptionRule getOptionRule(@NonNull String pluginType, @NonNull String connectorName) {
+        return allConnectorOptionRule.get(
+                PluginIdentifier.of("seatunnel", pluginType, connectorName));
+    }
+}
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/common/ConditionType.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/common/ConditionType.java
new file mode 100644
index 00000000..63bbe413
--- /dev/null
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/common/ConditionType.java
@@ -0,0 +1,63 @@
+/*
+ * 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.seatunnel.app.common;
+
+import com.baomidou.mybatisplus.annotation.EnumValue;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/** condition type */
+public enum ConditionType {
+
+    /** 0 none 1 judge 2 delay */
+    NONE(0, "none"),
+    JUDGE(1, "judge"),
+    DELAY(2, "delay");
+
+    ConditionType(int code, String desc) {
+        this.code = code;
+        this.desc = desc;
+    }
+
+    @EnumValue private final int code;
+    private final String desc;
+
+    public int getCode() {
+        return code;
+    }
+
+    public String getDesc() {
+        return desc;
+    }
+
+    private static final Map<String, ConditionType> CONDITION_TYPE_MAP = new HashMap<>();
+
+    static {
+        for (ConditionType conditionType : ConditionType.values()) {
+            CONDITION_TYPE_MAP.put(conditionType.desc, conditionType);
+        }
+    }
+
+    public static ConditionType of(String desc) {
+        if (CONDITION_TYPE_MAP.containsKey(desc)) {
+            return CONDITION_TYPE_MAP.get(desc);
+        }
+        throw new IllegalArgumentException("invalid type : " + desc);
+    }
+}
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/common/Constants.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/common/Constants.java
new file mode 100644
index 00000000..b32c48ed
--- /dev/null
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/common/Constants.java
@@ -0,0 +1,658 @@
+/*
+ * 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.seatunnel.app.common;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.SystemUtils;
+
+import java.time.Duration;
+import java.util.regex.Pattern;
+
+public final class Constants {
+
+    private Constants() {
+        throw new UnsupportedOperationException("Construct Constants");
+    }
+
+    /** common properties path */
+    public static final String COMMON_PROPERTIES_PATH = "/common.properties";
+
+    public static final String FORMAT_SS = "%s%s";
+    public static final String FORMAT_S_S = "%s/%s";
+    public static final String FORMAT_S_S_COLON = "%s:%s";
+    public static final String AWS_ACCESS_KEY_ID = "aws.access.key.id";
+    public static final String AWS_SECRET_ACCESS_KEY = "aws.secret.access.key";
+    public static final String AWS_REGION = "aws.region";
+    public static final String FOLDER_SEPARATOR = "/";
+
+    public static final String FOLDER_DOLLOR = "$";
+
+    public static final String RESOURCE_TYPE_FILE = "resources";
+
+    public static final String RESOURCE_TYPE_UDF = "udfs";
+
+    public static final String STORAGE_S3 = "S3";
+
+    public static final String STORAGE_HDFS = "HDFS";
+
+    public static final String EMPTY_STRING = "";
+
+    /** fs.defaultFS */
+    public static final String FS_DEFAULT_FS = "fs.defaultFS";
+
+    /** hadoop configuration */
+    public static final String HADOOP_RM_STATE_ACTIVE = "ACTIVE";
+
+    public static final String HADOOP_RESOURCE_MANAGER_HTTPADDRESS_PORT =
+            "resource.manager.httpaddress.port";
+
+    /** yarn.resourcemanager.ha.rm.ids */
+    public static final String YARN_RESOURCEMANAGER_HA_RM_IDS = "yarn.resourcemanager.ha.rm.ids";
+
+    /** yarn.application.status.address */
+    public static final String YARN_APPLICATION_STATUS_ADDRESS = "yarn.application.status.address";
+
+    /** yarn.job.history.status.address */
+    public static final String YARN_JOB_HISTORY_STATUS_ADDRESS = "yarn.job.history.status.address";
+
+    /** hdfs configuration hdfs.root.user */
+    public static final String HDFS_ROOT_USER = "hdfs.root.user";
+
+    /** hdfs/s3 configuration resource.upload.path */
+    public static final String RESOURCE_UPLOAD_PATH = "resource.upload.path";
+
+    /** data basedir path */
+    public static final String DATA_BASEDIR_PATH = "data.basedir.path";
+
+    /** dolphinscheduler.env.path */
+    public static final String DOLPHINSCHEDULER_ENV_PATH = "dolphinscheduler.env.path";
+
+    /** environment properties default path */
+    public static final String ENV_PATH = "dolphinscheduler_env.sh";
+
+    /** resource.view.suffixs */
+    public static final String RESOURCE_VIEW_SUFFIXES = "resource.view.suffixs";
+
+    public static final String RESOURCE_VIEW_SUFFIXES_DEFAULT_VALUE =
+            "txt,log,sh,bat,conf,cfg,py,java,sql,xml,hql,properties,json,yml,yaml,ini,js";
+
+    /** development.state */
+    public static final String DEVELOPMENT_STATE = "development.state";
+
+    /** sudo enable */
+    public static final String SUDO_ENABLE = "sudo.enable";
+
+    public static final String SET_TENANT_OWNER_ENABLE = "setTenantOwner.enable";
+
+    /** string true */
+    public static final String STRING_TRUE = "true";
+
+    /** resource storage type */
+    public static final String RESOURCE_STORAGE_TYPE = "resource.storage.type";
+
+    public static final String AWS_END_POINT = "aws.endpoint";
+    /** comma , */
+    public static final String COMMA = ",";
+
+    /** COLON : */
+    public static final String COLON = ":";
+
+    /** period . */
+    public static final String PERIOD = ".";
+
+    /** QUESTION ? */
+    public static final String QUESTION = "?";
+
+    /** SPACE " " */
+    public static final String SPACE = " ";
+
+    /** SINGLE_SLASH / */
+    public static final String SINGLE_SLASH = "/";
+
+    /** DOUBLE_SLASH // */
+    public static final String DOUBLE_SLASH = "//";
+
+    /** EQUAL SIGN */
+    public static final String EQUAL_SIGN = "=";
+
+    /** AT SIGN */
+    public static final String AT_SIGN = "@";
+
+    /** date format of yyyy-MM-dd HH:mm:ss */
+    public static final String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";
+
+    /** date format of yyyyMMdd */
+    public static final String YYYYMMDD = "yyyyMMdd";
+
+    /** date format of yyyyMMddHHmmss */
+    public static final String YYYYMMDDHHMMSS = "yyyyMMddHHmmss";
+
+    /** date format of yyyyMMddHHmmssSSS */
+    public static final String YYYYMMDDHHMMSSSSS = "yyyyMMddHHmmssSSS";
+    /** http connect time out */
+    public static final int HTTP_CONNECT_TIMEOUT = 60 * 1000;
+
+    /** http connect request time out */
+    public static final int HTTP_CONNECTION_REQUEST_TIMEOUT = 60 * 1000;
+
+    /** httpclient soceket time out */
+    public static final int SOCKET_TIMEOUT = 60 * 1000;
+
+    /** registry session timeout */
+    public static final int REGISTRY_SESSION_TIMEOUT = 10 * 1000;
+
+    /** http header */
+    public static final String HTTP_HEADER_UNKNOWN = "unKnown";
+
+    /** http X-Forwarded-For */
+    public static final String HTTP_X_FORWARDED_FOR = "X-Forwarded-For";
+
+    /** http X-Real-IP */
+    public static final String HTTP_X_REAL_IP = "X-Real-IP";
+
+    /** UTF-8 */
+    public static final String UTF_8 = "UTF-8";
+
+    /** user name regex */
+    public static final Pattern REGEX_USER_NAME = Pattern.compile("^[a-zA-Z0-9._-]{3,39}$");
+
+    /** read permission */
+    public static final int READ_PERMISSION = 2;
+
+    /** write permission */
+    public static final int WRITE_PERMISSION = 2 * 2;
+
+    /** execute permission */
+    public static final int EXECUTE_PERMISSION = 1;
+
+    /** default admin permission */
+    public static final int DEFAULT_ADMIN_PERMISSION = 7;
+
+    /** default hash map size */
+    public static final int DEFAULT_HASH_MAP_SIZE = 16;
+
+    /** all permissions */
+    public static final int ALL_PERMISSIONS =
+            READ_PERMISSION | WRITE_PERMISSION | EXECUTE_PERMISSION;
+
+    /** max task timeout */
+    public static final int MAX_TASK_TIMEOUT = 24 * 3600;
+
+    /** worker host weight */
+    public static final int DEFAULT_WORKER_HOST_WEIGHT = 100;
+
+    /** time unit secong to minutes */
+    public static final int SEC_2_MINUTES_TIME_UNIT = 60;
+
+    /**
+     * *
+     *
+     * <p>rpc port
+     */
+    public static final String RPC_PORT = "rpc.port";
+
+    /** forbid running task */
+    public static final String FLOWNODE_RUN_FLAG_FORBIDDEN = "FORBIDDEN";
+
+    /** normal running task */
+    public static final String FLOWNODE_RUN_FLAG_NORMAL = "NORMAL";
+
+    public static final String COMMON_TASK_TYPE = "common";
+
+    public static final String DEFAULT = "default";
+    public static final String PASSWORD = "password";
+    public static final String XXXXXX = "******";
+    public static final String NULL = "NULL";
+    public static final String THREAD_NAME_MASTER_SERVER = "Master-Server";
+    public static final String THREAD_NAME_WORKER_SERVER = "Worker-Server";
+    public static final String THREAD_NAME_ALERT_SERVER = "Alert-Server";
+
+    /** command parameter keys */
+    public static final String CMD_PARAM_RECOVER_PROCESS_ID_STRING = "ProcessInstanceId";
+
+    public static final String CMD_PARAM_RECOVERY_START_NODE_STRING = "StartNodeIdList";
+
+    public static final String CMD_PARAM_RECOVERY_WAITING_THREAD = "WaitingThreadInstanceId";
+
+    public static final String CMD_PARAM_SUB_PROCESS = "processInstanceId";
+
+    public static final String CMD_PARAM_EMPTY_SUB_PROCESS = "0";
+
+    public static final String CMD_PARAM_SUB_PROCESS_PARENT_INSTANCE_ID = "parentProcessInstanceId";
+
+    public static final String CMD_PARAM_SUB_PROCESS_DEFINE_CODE = "processDefinitionCode";
+
+    public static final String CMD_PARAM_START_NODES = "StartNodeList";
+
+    public static final String CMD_PARAM_CLEAN_STATE_TASK_INSTANCE_IDS =
+            "CleanStateTaskInstanceIds";
+
+    public static final String CMD_PARAM_DEPENDENT_TASK_TRACK_DATA = "dependentTaskTrackData";
+
+    public static final String CMD_PARAM_SUBPROCESS_TASK_TRACK_DATA = "subProcessTaskTrackData";
+
+    public static final String CMD_PARAM_RECOVERY_PAUSED_ISOLATED_TASK_IDS =
+            "RecoveryPausedIsolationTaskInstanceIds";
+    public static final String CMD_PARAM_RECOVERY_KILLED_ISOLATED_TASK_IDS =
+            "RecoveryKilledIsolationTaskInstanceIds";
+
+    public static final String CMD_PARAM_RECOVERY_PAUSED_BY_CORONATION_TASK_IDS =
+            "RecoveryPausedByCoronationTaskInstanceIds";
+
+    public static final String CMD_PARAM_START_PARAMS = "StartParams";
+
+    public static final String CMD_PARAM_FATHER_PARAMS = "fatherParams";
+
+    /** complement data start date */
+    public static final String CMDPARAM_COMPLEMENT_DATA_START_DATE = "complementStartDate";
+
+    /** complement data end date */
+    public static final String CMDPARAM_COMPLEMENT_DATA_END_DATE = "complementEndDate";
+
+    /** complement data Schedule date */
+    public static final String CMDPARAM_COMPLEMENT_DATA_SCHEDULE_DATE_LIST =
+            "complementScheduleDateList";
+
+    public static final String CMDPARAM_COMPLEMENT_DATA_CALENDAR_TYPE = "complementCalendarType";
+
+    public static final String CMDPARAM_COMPLEMENT_DATA_CALENDAR_CODE = "complementCalendarCode";
+
+    /** complement date default cron string */
+    public static final String DEFAULT_CRON_STRING = "0 0 0 * * ? *";
+
+    /** sleep 1000ms */
+    public static final long SLEEP_TIME_MILLIS = 1_000L;
+
+    /** short sleep 100ms */
+    public static final long SLEEP_TIME_MILLIS_SHORT = 100L;
+
+    public static final Duration SERVER_CLOSE_WAIT_TIME = Duration.ofSeconds(3);
+
+    /** one second mils */
+    public static final long SECOND_TIME_MILLIS = 1_000L;
+
+    /** master task instance cache-database refresh interval */
+    public static final long CACHE_REFRESH_TIME_MILLIS = 20 * 1_000L;
+
+    /** heartbeat for zk info length */
+    public static final int HEARTBEAT_FOR_ZOOKEEPER_INFO_LENGTH = 13;
+
+    /** jar */
+    public static final String JAR = "jar";
+
+    /** hadoop */
+    public static final String HADOOP = "hadoop";
+
+    /** -D <property>=<value> */
+    public static final String D = "-D";
+
+    /** exit code success */
+    public static final int EXIT_CODE_SUCCESS = 0;
+
+    /** exit code failure */
+    public static final int EXIT_CODE_FAILURE = -1;
+
+    /** process or task definition failure */
+    public static final int DEFINITION_FAILURE = -1;
+
+    public static final int OPPOSITE_VALUE = -1;
+
+    /** process or task definition first version */
+    public static final int VERSION_FIRST = 1;
+
+    /** date format of yyyyMMdd */
+    public static final String PARAMETER_FORMAT_DATE = "yyyyMMdd";
+
+    /** date format of yyyyMMddHHmmss */
+    public static final String PARAMETER_FORMAT_TIME = "yyyyMMddHHmmss";
+
+    /** system date(yyyyMMddHHmmss) */
+    public static final String PARAMETER_DATETIME = "system.datetime";
+
+    /** system date(yyyymmdd) today */
+    public static final String PARAMETER_CURRENT_DATE = "system.biz.curdate";
+
+    /** system date(yyyymmdd) yesterday */
+    public static final String PARAMETER_BUSINESS_DATE = "system.biz.date";
+
+    public static final String TASK_TYPE_CONDITIONS = "CONDITIONS";
+
+    public static final String TASK_TYPE_SWITCH = "SWITCH";
+
+    public static final String TASK_TYPE_SUB_PROCESS = "SUB_PROCESS";
+
+    public static final String TASK_TYPE_DEPENDENT = "DEPENDENT";
+
+    public static final String TASK_TYPE_BLOCKING = "BLOCKING";
+
+    public static final String TASK_TYPE_STREAM = "STREAM";
+
+    /** ACCEPTED */
+    public static final String ACCEPTED = "ACCEPTED";
+
+    /** SUCCEEDED */
+    public static final String SUCCEEDED = "SUCCEEDED";
+    /** ENDED */
+    public static final String ENDED = "ENDED";
+    /** NEW */
+    public static final String NEW = "NEW";
+    /** NEW_SAVING */
+    public static final String NEW_SAVING = "NEW_SAVING";
+    /** SUBMITTED */
+    public static final String SUBMITTED = "SUBMITTED";
+    /** FAILED */
+    public static final String FAILED = "FAILED";
+    /** KILLED */
+    public static final String KILLED = "KILLED";
+    /** RUNNING */
+    public static final String RUNNING = "RUNNING";
+    /** underline "_" */
+    public static final String UNDERLINE = "_";
+    /** application regex */
+    public static final String APPLICATION_REGEX = "application_\\d+_\\d+";
+
+    public static final String PID = SystemUtils.IS_OS_WINDOWS ? "handle" : "pid";
+    /** month_begin */
+    public static final String MONTH_BEGIN = "month_begin";
+    /** add_months */
+    public static final String ADD_MONTHS = "add_months";
+    /** month_end */
+    public static final String MONTH_END = "month_end";
+    /** week_begin */
+    public static final String WEEK_BEGIN = "week_begin";
+    /** week_end */
+    public static final String WEEK_END = "week_end";
+    /** timestamp */
+    public static final String TIMESTAMP = "timestamp";
+
+    public static final char SUBTRACT_CHAR = '-';
+    public static final char ADD_CHAR = '+';
+    public static final char MULTIPLY_CHAR = '*';
+    public static final char DIVISION_CHAR = '/';
+    public static final char LEFT_BRACE_CHAR = '(';
+    public static final char RIGHT_BRACE_CHAR = ')';
+    public static final String ADD_STRING = "+";
+    public static final String STAR = "*";
+    public static final String DIVISION_STRING = "/";
+    public static final String LEFT_BRACE_STRING = "(";
+    public static final char P = 'P';
+    public static final char N = 'N';
+    public static final String SUBTRACT_STRING = "-";
+    public static final String GLOBAL_PARAMS = "globalParams";
+    public static final String LOCAL_PARAMS = "localParams";
+    public static final String SUBPROCESS_INSTANCE_ID = "subProcessInstanceId";
+    public static final String PROCESS_INSTANCE_STATE = "processInstanceState";
+    public static final String PARENT_WORKFLOW_INSTANCE = "parentWorkflowInstance";
+    public static final String CONDITION_RESULT = "conditionResult";
+    public static final String SWITCH_RESULT = "switchResult";
+    public static final String WAIT_START_TIMEOUT = "waitStartTimeout";
+    public static final String DEPENDENCE = "dependence";
+    public static final String TASK_LIST = "taskList";
+    public static final String QUEUE = "queue";
+    public static final String QUEUE_NAME = "queueName";
+    public static final int LOG_QUERY_SKIP_LINE_NUMBER = 0;
+    public static final int LOG_QUERY_LIMIT = 4096;
+    public static final String OTHER_PARAMS = "otherParams";
+    public static final String DEPEND_STRATEGY = "dependStrategy";
+    public static final String BLOCKING_CONDITION = "blockingCondition";
+    public static final String ALERT_WHEN_BLOCKING = "alertWhenBlocking";
+
+    /** master/worker server use for zk */
+    public static final String MASTER_TYPE = "master";
+
+    public static final String WORKER_TYPE = "worker";
+    public static final String DELETE_OP = "delete";
+    public static final String ADD_OP = "add";
+    public static final String ALIAS = "alias";
+    public static final String CONTENT = "content";
+
+    public static final String PATH = "path";
+    public static final String DEPENDENT_SPLIT = ":||";
+    public static final long DEPENDENT_ALL_TASK_CODE = 0;
+
+    /** preview schedule execute count */
+    public static final int PREVIEW_SCHEDULE_EXECUTE_COUNT = 5;
+
+    /** kerberos */
+    public static final String KERBEROS = "kerberos";
+
+    /** kerberos expire time */
+    public static final String KERBEROS_EXPIRE_TIME = "kerberos.expire.time";
+
+    /** java.security.krb5.conf */
+    public static final String JAVA_SECURITY_KRB5_CONF = "java.security.krb5.conf";
+
+    /** java.security.krb5.conf.path */
+    public static final String JAVA_SECURITY_KRB5_CONF_PATH = "java.security.krb5.conf.path";
+
+    /** hadoop.security.authentication */
+    public static final String HADOOP_SECURITY_AUTHENTICATION = "hadoop.security.authentication";
+
+    /** hadoop.security.authentication */
+    public static final String HADOOP_SECURITY_AUTHENTICATION_STARTUP_STATE =
+            "hadoop.security.authentication.startup.state";
+
+    /** com.amazonaws.services.s3.enableV4 */
+    public static final String AWS_S3_V4 = "com.amazonaws.services.s3.enableV4";
+
+    /** loginUserFromKeytab user */
+    public static final String LOGIN_USER_KEY_TAB_USERNAME = "login.user.keytab.username";
+
+    /** loginUserFromKeytab path */
+    public static final String LOGIN_USER_KEY_TAB_PATH = "login.user.keytab.path";
+
+    public static final String WORKFLOW_INSTANCE_ID_MDC_KEY = "workflowInstanceId";
+    public static final String TASK_INSTANCE_ID_MDC_KEY = "taskInstanceId";
+
+    /** task log info format */
+    public static final String TASK_LOG_INFO_FORMAT = "TaskLogInfo-%s";
+
+    /** status */
+    public static final String STATUS = "status";
+
+    /** message */
+    public static final String MSG = "msg";
+
+    /** data total */
+    public static final String COUNT = "count";
+
+    /** page size */
+    public static final String PAGE_SIZE = "pageSize";
+
+    /** current page no */
+    public static final String PAGE_NUMBER = "pageNo";
+
+    /** */
+    public static final String DATA_LIST = "data";
+
+    public static final String TOTAL_LIST = "totalList";
+
+    public static final String CURRENT_PAGE = "currentPage";
+
+    public static final String TOTAL_PAGE = "totalPage";
+
+    public static final String TOTAL = "total";
+
+    /** workflow */
+    public static final String WORKFLOW_LIST = "workFlowList";
+
+    public static final String WORKFLOW_RELATION_LIST = "workFlowRelationList";
+
+    /** session user */
+    public static final String SESSION_USER = "session.user";
+
+    public static final String SESSION_ID = "sessionId";
+
+    /** Security authentication types (supported types: PASSWORD,LDAP) */
+    public static final String SECURITY_CONFIG_TYPE = "securityConfigType";
+
+    /** locale */
+    public static final String LOCALE_LANGUAGE = "language";
+
+    /** database type */
+    public static final String MYSQL = "MYSQL";
+
+    public static final String HIVE = "HIVE";
+
+    public static final String ADDRESS = "address";
+    public static final String DATABASE = "database";
+    public static final String OTHER = "other";
+    public static final String USER = "user";
+    public static final String JDBC_URL = "jdbcUrl";
+
+    /** session timeout */
+    public static final int SESSION_TIME_OUT = 7200;
+
+    public static final int MAX_FILE_SIZE = 1024 * 1024 * 1024;
+    public static final String UDF = "UDF";
+    public static final String CLASS = "class";
+
+    /** dataSource sensitive param */
+    public static final String DATASOURCE_PASSWORD_REGEX =
+            "(?<=((?i)password((\":\")|(=')))).*?(?=((\")|(')))";
+
+    /** default worker group */
+    public static final String DEFAULT_WORKER_GROUP = "default";
+    /** authorize writable perm */
+    public static final int AUTHORIZE_WRITABLE_PERM = 7;
+    /** authorize readable perm */
+    public static final int AUTHORIZE_READABLE_PERM = 4;
+
+    public static final int NORMAL_NODE_STATUS = 0;
+    public static final int ABNORMAL_NODE_STATUS = 1;
+    public static final int BUSY_NODE_STATUE = 2;
+
+    public static final String START_TIME = "start time";
+    public static final String END_TIME = "end time";
+    public static final String START_END_DATE = "startDate,endDate";
+
+    /** system line separator */
+    public static final String SYSTEM_LINE_SEPARATOR = System.getProperty("line.separator");
+
+    /** datasource encryption salt */
+    public static final String DATASOURCE_ENCRYPTION_SALT_DEFAULT = "!@#$%^&*";
+
+    public static final String DATASOURCE_ENCRYPTION_ENABLE = "datasource.encryption.enable";
+    public static final String DATASOURCE_ENCRYPTION_SALT = "datasource.encryption.salt";
+
+    /** network interface preferred */
+    public static final String DOLPHIN_SCHEDULER_NETWORK_INTERFACE_PREFERRED =
+            "dolphin.scheduler.network.interface.preferred";
+
+    /** network IP gets priority, default inner outer */
+    public static final String DOLPHIN_SCHEDULER_NETWORK_PRIORITY_STRATEGY =
+            "dolphin.scheduler.network.priority.strategy";
+
+    /** exec shell scripts */
+    public static final String SH = "sh";
+
+    /** pstree, get pud and sub pid */
+    public static final String PSTREE = "pstree";
+
+    public static final boolean KUBERNETES_MODE =
+            !StringUtils.isEmpty(System.getenv("KUBERNETES_SERVICE_HOST"))
+                    && !StringUtils.isEmpty(System.getenv("KUBERNETES_SERVICE_PORT"));
+
+    /** dry run flag */
+    public static final int DRY_RUN_FLAG_NO = 0;
+
+    public static final int DRY_RUN_FLAG_YES = 1;
+
+    /** data.quality.error.output.path */
+    public static final String DATA_QUALITY_ERROR_OUTPUT_PATH = "data-quality.error.output.path";
+
+    public static final String CACHE_KEY_VALUE_ALL = "'all'";
+
+    /** use for k8s */
+    public static final String NAMESPACE = "namespace";
+
+    public static final String K8S = "k8s";
+    public static final String LIMITS_CPU = "limitsCpu";
+    public static final String LIMITS_MEMORY = "limitsMemory";
+
+    public static final String K8S_LOCAL_TEST_CLUSTER = "ds_null_k8s";
+
+    /** schedule timezone */
+    public static final String SCHEDULE_TIMEZONE = "schedule_timezone";
+
+    public static final int RESOURCE_FULL_NAME_MAX_LENGTH = 128;
+
+    /** tenant */
+    public static final int TENANT_FULL_NAME_MAX_LENGTH = 30;
+
+    /** schedule time the amount of date data is too large, affecting the memory, so set 100 */
+    public static final int SCHEDULE_TIME_MAX_LENGTH = 100;
+
+    /** password max and min LENGTH */
+    public static final int USER_PASSWORD_MAX_LENGTH = 20;
+
+    public static final int USER_PASSWORD_MIN_LENGTH = 2;
+
+    public static final String FUNCTION_START_WITH = "$";
+
+    public static final Integer DEFAULT_QUEUE_ID = 1;
+
+    public static final Integer DEFAULT_MAX_RETRY_COUNT = 100;
+
+    public static final String TASK_PRIORITY_QUEUE = "TASK_PRIORITY_QUEUE";
+
+    public static final String TASK_DISPATCH_FAILED_QUEUE = "TASK_DISPATCH_FAILED_QUEUE";
+
+    public static final String TASK_PARSE_RUNNING_LOG_QUEUE = "TASK_PARSE_RUNNING_LOG_QUEUE";
+
+    public static final int DESC_LENGTH_GO_ONLINE = 255;
+
+    public static final int NAME_LENGTH_GO_ONLINE = 100;
+
+    /** Task Types */
+    public static final String TYPE_UNIVERSAL = "Universal";
+
+    public static final String TYPE_DATA_INTEGRATION = "DataIntegration";
+    public static final String TYPE_CLOUD = "Cloud";
+    public static final String TYPE_LOGIC = "Logic";
+    public static final String TYPE_DATA_QUALITY = "DataQuality";
+    public static final String TYPE_OTHER = "Other";
+    public static final String TYPE_MACHINE_LEARNING = "MachineLearning";
+
+    /** file upload verify */
+    public static final String FILE_TYPE_RESTRICTED_LIST = "file.type.restricted.list";
+
+    public static final String FILE_NAME_RESTRICTED_CONTENT = "file.name.restricted.content";
+
+    /** need parse running log task types */
+    public static final String NEED_PARSE_RUNNING_LOG_TASK_TYPES =
+            "need.parse.running.log.task.types";
+
+    public static final String GIT_RESOURCE_BASE_DIR = "git.resource.base.dir";
+
+    public static final String GIT_RESOURCE_FILTER = "git.resource.filter";
+
+    public static final String FILE_TYPE_SUPPORT_LIST = "file.type.support.list";
+
+    public static final String SYSTEM_INTERNAL_PERMISSION_FILTER =
+            "system.internal.permission.filter";
+
+    public static final String WS_SUPPORT_DATASOURCES = "ws.support.datasources";
+
+    public static final String SEATUNNEL_TRANSFORMS_JAR_PATH = "seatunnel.transforms.jar.path";
+
+    /** default alert group id */
+    public static final int DEFAULT_ALERT_GROUP_ID = 1;
+
+    public static final String TASK_ID = "taskId";
+}
diff --git a/seatunnel-server/seatunnel-server-common/src/main/java/org/apache/seatunnel/server/common/Constants.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/common/DataType.java
similarity index 68%
copy from seatunnel-server/seatunnel-server-common/src/main/java/org/apache/seatunnel/server/common/Constants.java
copy to seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/common/DataType.java
index f55aa89d..c398ac27 100644
--- a/seatunnel-server/seatunnel-server-common/src/main/java/org/apache/seatunnel/server/common/Constants.java
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/common/DataType.java
@@ -15,14 +15,22 @@
  * limitations under the License.
  */
 
-package org.apache.seatunnel.server.common;
+package org.apache.seatunnel.app.common;
 
-public class Constants {
-    public static final String BLANK_SPACE = " ";
-    public static final String COMMA = ",";
-    public static final String UNDERLINE = "_";
-    public static final String TOKEN = "token";
-    public static final String USER_ID = "id";
-
-    public static final String OPTIONS = "OPTIONS";
+/** data types in user define parameter */
+public enum DataType {
+    /**
+     * 0 string 1 integer 2 long 3 float 4 double 5 date, "YYYY-MM-DD" 6 time, "HH:MM:SS" 7 time
+     * stamp 8 Boolean 9 list <String>
+     */
+    VARCHAR,
+    INTEGER,
+    LONG,
+    FLOAT,
+    DOUBLE,
+    DATE,
+    TIME,
+    TIMESTAMP,
+    BOOLEAN,
+    LIST
 }
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/common/DbType.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/common/DbType.java
new file mode 100644
index 00000000..b48dc227
--- /dev/null
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/common/DbType.java
@@ -0,0 +1,93 @@
+/*
+ * 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.seatunnel.app.common;
+
+import com.baomidou.mybatisplus.annotation.EnumValue;
+
+import java.util.Arrays;
+import java.util.Map;
+import java.util.NoSuchElementException;
+
+import static java.util.stream.Collectors.toMap;
+
+// todo: implement with SourceType......
+public enum DbType {
+    MYSQL(0, "mysql"),
+    POSTGRESQL(1, "postgresql"),
+    HIVE(2, "hive"),
+    SPARK(3, "spark"),
+    CLICKHOUSE(4, "clickhouse"),
+    ORACLE(5, "oracle"),
+    SQLSERVER(6, "sqlserver"),
+    DB2(7, "db2"),
+    PRESTO(8, "presto"),
+    H2(9, "h2"),
+    REDSHIFT(10, "redshift"),
+    DAMENG(11, "dameng"),
+    STARROCKS(12, "starrocks"),
+    // todo: this is not a db type....
+    SSH(13, "ssh"),
+    PROXY(14, "proxy"),
+    ;
+
+    @EnumValue private final int code;
+    private final String descp;
+
+    DbType(int code, String descp) {
+        this.code = code;
+        this.descp = descp;
+    }
+
+    public int getCode() {
+        return code;
+    }
+
+    public String getDescp() {
+        return descp;
+    }
+
+    private static final Map<Integer, DbType> DB_TYPE_MAP =
+            Arrays.stream(DbType.values()).collect(toMap(DbType::getCode, val -> val));
+
+    public static DbType of(int type) {
+        if (DB_TYPE_MAP.containsKey(type)) {
+            return DB_TYPE_MAP.get(type);
+        }
+        return null;
+    }
+
+    public static DbType ofName(String name) {
+        return Arrays.stream(DbType.values())
+                .filter(e -> e.name().equals(name))
+                .findFirst()
+                .orElseThrow(() -> new NoSuchElementException("no such db type"));
+    }
+
+    public boolean isHive() {
+        return this == DbType.HIVE;
+    }
+
+    /**
+     * support execute multiple segmented statements at a time
+     *
+     * @return
+     */
+    public boolean isSupportMultipleStatement() {
+        return this == DbType.SPARK;
+    }
+}
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/impl/MysqlDatasourceConfigSwitcher.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/common/DependResult.java
similarity index 73%
copy from seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/impl/MysqlDatasourceConfigSwitcher.java
copy to seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/common/DependResult.java
index 7da09161..f4e46d54 100644
--- a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/impl/MysqlDatasourceConfigSwitcher.java
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/common/DependResult.java
@@ -15,10 +15,14 @@
  * limitations under the License.
  */
 
-package org.apache.seatunnel.app.thridparty.datasource.impl;
+package org.apache.seatunnel.app.common;
 
-public class MysqlDatasourceConfigSwitcher extends BaseJdbcDataSourceConfigSwitcher {
-    public static MysqlDatasourceConfigSwitcher INSTANCE = new MysqlDatasourceConfigSwitcher();
+/** depend result */
+public enum DependResult {
 
-    private MysqlDatasourceConfigSwitcher() {}
+    /** 0 success 1 waiting 2 failed 3 non execution */
+    SUCCESS,
+    WAITING,
+    FAILED,
+    NON_EXEC
 }
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/impl/MysqlDatasourceConfigSwitcher.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/common/DependentRelation.java
similarity index 73%
copy from seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/impl/MysqlDatasourceConfigSwitcher.java
copy to seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/common/DependentRelation.java
index 7da09161..c06142e0 100644
--- a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/impl/MysqlDatasourceConfigSwitcher.java
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/common/DependentRelation.java
@@ -15,10 +15,10 @@
  * limitations under the License.
  */
 
-package org.apache.seatunnel.app.thridparty.datasource.impl;
+package org.apache.seatunnel.app.common;
 
-public class MysqlDatasourceConfigSwitcher extends BaseJdbcDataSourceConfigSwitcher {
-    public static MysqlDatasourceConfigSwitcher INSTANCE = new MysqlDatasourceConfigSwitcher();
-
-    private MysqlDatasourceConfigSwitcher() {}
+/** dependent relation: and or */
+public enum DependentRelation {
+    AND,
+    OR;
 }
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/impl/MysqlDatasourceConfigSwitcher.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/common/Direct.java
similarity index 73%
copy from seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/impl/MysqlDatasourceConfigSwitcher.java
copy to seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/common/Direct.java
index 7da09161..9fdea5c1 100644
--- a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/impl/MysqlDatasourceConfigSwitcher.java
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/common/Direct.java
@@ -15,10 +15,11 @@
  * limitations under the License.
  */
 
-package org.apache.seatunnel.app.thridparty.datasource.impl;
+package org.apache.seatunnel.app.common;
 
-public class MysqlDatasourceConfigSwitcher extends BaseJdbcDataSourceConfigSwitcher {
-    public static MysqlDatasourceConfigSwitcher INSTANCE = new MysqlDatasourceConfigSwitcher();
-
-    private MysqlDatasourceConfigSwitcher() {}
+/** parameter of stored procedure */
+public enum Direct {
+    /** 0 in; 1 out; */
+    IN,
+    OUT
 }
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/impl/MysqlDatasourceConfigSwitcher.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/common/EngineType.java
similarity index 73%
copy from seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/impl/MysqlDatasourceConfigSwitcher.java
copy to seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/common/EngineType.java
index 7da09161..096d22bb 100644
--- a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/impl/MysqlDatasourceConfigSwitcher.java
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/common/EngineType.java
@@ -15,10 +15,10 @@
  * limitations under the License.
  */
 
-package org.apache.seatunnel.app.thridparty.datasource.impl;
+package org.apache.seatunnel.app.common;
 
-public class MysqlDatasourceConfigSwitcher extends BaseJdbcDataSourceConfigSwitcher {
-    public static MysqlDatasourceConfigSwitcher INSTANCE = new MysqlDatasourceConfigSwitcher();
-
-    private MysqlDatasourceConfigSwitcher() {}
+public enum EngineType {
+    Spark,
+    Flink,
+    SeaTunnel
 }
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/common/ExecutionStatus.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/common/ExecutionStatus.java
new file mode 100644
index 00000000..62d8e093
--- /dev/null
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/common/ExecutionStatus.java
@@ -0,0 +1,250 @@
+/*
+ * 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.seatunnel.app.common;
+
+import com.baomidou.mybatisplus.annotation.EnumValue;
+
+import java.util.HashMap;
+
+/** running status for workflow and task nodes */
+public enum ExecutionStatus {
+
+    /**
+     * status: 0 submit success 1 running 2 ready pause 3 pause 4 ready stop 5 stop 6 failure 7
+     * success 8 need fault tolerance 9 kill 10 waiting thread 11 waiting depend node complete 12
+     * delay execution 13 forced success 14 serial wait 15 ready block 16 block 17 dispatch
+     */
+    SUBMITTED_SUCCESS(0, "submit success"),
+    RUNNING_EXECUTION(1, "running"),
+    READY_PAUSE(2, "ready pause"),
+    PAUSE(3, "pause"),
+    READY_STOP(4, "ready stop"),
+    STOP(5, "stop"),
+    FAILURE(6, "failure"),
+    SUCCESS(7, "success"),
+    NEED_FAULT_TOLERANCE(8, "need fault tolerance"),
+    KILL(9, "kill"),
+    WAITING_THREAD(10, "waiting thread"),
+    WAITING_DEPEND(11, "waiting depend node complete"),
+    DELAY_EXECUTION(12, "delay execution"),
+    FORCED_SUCCESS(13, "forced success"),
+    SERIAL_WAIT(14, "serial wait"),
+    READY_BLOCK(15, "ready block"),
+    BLOCK(16, "block"),
+    DISPATCH(17, "dispatch"),
+    PAUSE_BY_ISOLATION(18, "paused by isolation"),
+    KILL_BY_ISOLATION(19, "killed by isolation"),
+
+    PAUSE_BY_CORONATION(20, "paused by coronation"),
+    FORBIDDEN_BY_CORONATION(21, "forbidden by coronation"),
+    ;
+
+    ExecutionStatus(int code, String descp) {
+        this.code = code;
+        this.descp = descp;
+    }
+
+    @EnumValue private final int code;
+    private final String descp;
+
+    private static HashMap<Integer, ExecutionStatus> EXECUTION_STATUS_MAP = new HashMap<>();
+
+    private static final int[] NEED_FAILOVER_STATES =
+            new int[] {
+                ExecutionStatus.SUBMITTED_SUCCESS.ordinal(),
+                ExecutionStatus.DISPATCH.ordinal(),
+                ExecutionStatus.RUNNING_EXECUTION.ordinal(),
+                ExecutionStatus.DELAY_EXECUTION.ordinal(),
+                ExecutionStatus.READY_PAUSE.ordinal(),
+                ExecutionStatus.READY_STOP.ordinal()
+            };
+
+    static {
+        for (ExecutionStatus executionStatus : ExecutionStatus.values()) {
+            EXECUTION_STATUS_MAP.put(executionStatus.code, executionStatus);
+        }
+    }
+
+    /**
+     * status is success
+     *
+     * @return status
+     */
+    public boolean typeIsSuccess() {
+        return this == SUCCESS || this == FORCED_SUCCESS || this == FORBIDDEN_BY_CORONATION;
+    }
+
+    /**
+     * status is failure
+     *
+     * @return status
+     */
+    public boolean typeIsFailure() {
+        return this == FAILURE || this == NEED_FAULT_TOLERANCE;
+    }
+
+    /**
+     * status is finished
+     *
+     * @return status
+     */
+    public boolean typeIsFinished() {
+        return typeIsSuccess()
+                || typeIsFailure()
+                || typeIsCancel()
+                || typeIsPause()
+                || typeIsPauseByIsolation()
+                || typeIsStop()
+                || typeIsBlock()
+                || typeIsPauseByCoronation()
+                || typeIsForbiddenByCoronation();
+    }
+
+    public boolean typeIsReady() {
+        return this == READY_PAUSE || this == READY_STOP || this == READY_BLOCK;
+    }
+
+    /**
+     * status is waiting thread
+     *
+     * @return status
+     */
+    public boolean typeIsWaitingThread() {
+        return this == WAITING_THREAD;
+    }
+
+    /**
+     * status is pause
+     *
+     * @return status
+     */
+    public boolean typeIsPause() {
+        return this == PAUSE;
+    }
+
+    public boolean typeIsPauseByIsolation() {
+        return this == PAUSE_BY_ISOLATION;
+    }
+
+    public boolean typeIsPauseByCoronation() {
+        return this == PAUSE_BY_CORONATION;
+    }
+
+    public boolean typeIsForbiddenByCoronation() {
+        return this == FORBIDDEN_BY_CORONATION;
+    }
+
+    public boolean typeIsKilledByIsolation() {
+        return this == KILL_BY_ISOLATION;
+    }
+
+    public boolean typeIsIsolated() {
+        return this == PAUSE_BY_ISOLATION || this == KILL_BY_ISOLATION;
+    }
+
+    /**
+     * status is pause
+     *
+     * @return status
+     */
+    public boolean typeIsStop() {
+        return this == STOP;
+    }
+
+    /**
+     * status is running
+     *
+     * @return status
+     */
+    public boolean typeIsRunning() {
+        return this == RUNNING_EXECUTION || this == WAITING_DEPEND || this == DELAY_EXECUTION;
+    }
+
+    /**
+     * status is block
+     *
+     * @return status
+     */
+    public boolean typeIsBlock() {
+        return this == BLOCK;
+    }
+
+    /**
+     * status is cancel
+     *
+     * @return status
+     */
+    public boolean typeIsCancel() {
+        return this == KILL || this == STOP || this == KILL_BY_ISOLATION;
+    }
+
+    public int getCode() {
+        return code;
+    }
+
+    public String getDescp() {
+        return descp;
+    }
+
+    public static ExecutionStatus of(int status) {
+        if (EXECUTION_STATUS_MAP.containsKey(status)) {
+            return EXECUTION_STATUS_MAP.get(status);
+        }
+        throw new IllegalArgumentException("invalid status : " + status);
+    }
+
+    public static boolean isNeedFailoverWorkflowInstanceState(ExecutionStatus executionStatus) {
+        return ExecutionStatus.SUBMITTED_SUCCESS == executionStatus
+                || ExecutionStatus.DISPATCH == executionStatus
+                || ExecutionStatus.RUNNING_EXECUTION == executionStatus
+                || ExecutionStatus.DELAY_EXECUTION == executionStatus
+                || ExecutionStatus.READY_PAUSE == executionStatus
+                || ExecutionStatus.READY_STOP == executionStatus;
+    }
+
+    public static int[] getNeedFailoverWorkflowInstanceState() {
+        return NEED_FAILOVER_STATES;
+    }
+
+    public static int[] getRunningProcessState() {
+        return new int[] {
+            ExecutionStatus.RUNNING_EXECUTION.getCode(),
+            ExecutionStatus.SUBMITTED_SUCCESS.getCode(),
+            ExecutionStatus.DISPATCH.getCode(),
+            ExecutionStatus.SERIAL_WAIT.getCode()
+        };
+    }
+
+    public static int[] getNotTerminatedStates() {
+        return new int[] {
+            ExecutionStatus.SUBMITTED_SUCCESS.getCode(),
+            ExecutionStatus.DISPATCH.getCode(),
+            ExecutionStatus.RUNNING_EXECUTION.getCode(),
+            ExecutionStatus.DELAY_EXECUTION.getCode(),
+            ExecutionStatus.READY_PAUSE.getCode(),
+            ExecutionStatus.READY_STOP.getCode(),
+            ExecutionStatus.NEED_FAULT_TOLERANCE.getCode(),
+            ExecutionStatus.WAITING_THREAD.getCode(),
+            ExecutionStatus.WAITING_DEPEND.getCode()
+        };
+    }
+
+    public boolean canStop() {
+        return typeIsRunning() || this == READY_PAUSE;
+    }
+}
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/impl/SqlServerDataSourceConfigSwitcher.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/common/Flag.java
similarity index 60%
copy from seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/impl/SqlServerDataSourceConfigSwitcher.java
copy to seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/common/Flag.java
index 3d877f08..3d52d461 100644
--- a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/impl/SqlServerDataSourceConfigSwitcher.java
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/common/Flag.java
@@ -15,18 +15,30 @@
  * limitations under the License.
  */
 
-package org.apache.seatunnel.app.thridparty.datasource.impl;
+package org.apache.seatunnel.app.common;
 
-import org.apache.seatunnel.app.thridparty.datasource.AbstractDataSourceConfigSwitcher;
+import com.baomidou.mybatisplus.annotation.EnumValue;
 
-public class SqlServerDataSourceConfigSwitcher extends AbstractDataSourceConfigSwitcher {
+/** have_script have_file can_retry have_arr_variables have_map_variables have_alert */
+public enum Flag {
 
-    private static final SqlServerDataSourceConfigSwitcher INSTANCE =
-            new SqlServerDataSourceConfigSwitcher();
+    /** 0 no 1 yes */
+    NO(0, "no"),
+    YES(1, "yes");
 
-    public static final SqlServerDataSourceConfigSwitcher getInstance() {
-        return INSTANCE;
+    Flag(int code, String descp) {
+        this.code = code;
+        this.descp = descp;
     }
 
-    private SqlServerDataSourceConfigSwitcher() {}
+    @EnumValue private final int code;
+    private final String descp;
+
+    public int getCode() {
+        return code;
+    }
+
+    public String getDescp() {
+        return descp;
+    }
 }
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/impl/SqlServerDataSourceConfigSwitcher.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/common/Priority.java
similarity index 55%
copy from seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/impl/SqlServerDataSourceConfigSwitcher.java
copy to seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/common/Priority.java
index 3d877f08..20633dcd 100644
--- a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/impl/SqlServerDataSourceConfigSwitcher.java
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/common/Priority.java
@@ -15,18 +15,33 @@
  * limitations under the License.
  */
 
-package org.apache.seatunnel.app.thridparty.datasource.impl;
+package org.apache.seatunnel.app.common;
 
-import org.apache.seatunnel.app.thridparty.datasource.AbstractDataSourceConfigSwitcher;
+import com.baomidou.mybatisplus.annotation.EnumValue;
 
-public class SqlServerDataSourceConfigSwitcher extends AbstractDataSourceConfigSwitcher {
+/** define process and task priority */
+public enum Priority {
 
-    private static final SqlServerDataSourceConfigSwitcher INSTANCE =
-            new SqlServerDataSourceConfigSwitcher();
+    /** 0 highest priority 1 higher priority 2 medium priority 3 lower priority 4 lowest priority */
+    HIGHEST(0, "highest"),
+    HIGH(1, "high"),
+    MEDIUM(2, "medium"),
+    LOW(3, "low"),
+    LOWEST(4, "lowest");
 
-    public static final SqlServerDataSourceConfigSwitcher getInstance() {
-        return INSTANCE;
+    Priority(int code, String descp) {
+        this.code = code;
+        this.descp = descp;
     }
 
-    private SqlServerDataSourceConfigSwitcher() {}
+    @EnumValue private final int code;
+    private final String descp;
+
+    public int getCode() {
+        return code;
+    }
+
+    public String getDescp() {
+        return descp;
+    }
 }
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/DataSourceClientFactory.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/common/ReleaseState.java
similarity index 52%
copy from seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/DataSourceClientFactory.java
copy to seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/common/ReleaseState.java
index 4647e6eb..11a59c97 100644
--- a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/DataSourceClientFactory.java
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/common/ReleaseState.java
@@ -15,25 +15,40 @@
  * limitations under the License.
  */
 
-package org.apache.seatunnel.app.thridparty.datasource;
+package org.apache.seatunnel.app.common;
 
-import org.apache.seatunnel.datasource.DataSourceClient;
+import com.baomidou.mybatisplus.annotation.EnumValue;
 
-public class DataSourceClientFactory {
-    private static DataSourceClient INSTANCE;
+/** process define release state */
+public enum ReleaseState {
 
-    private static final Object LOCK = new Object();
+    /** 0 offline 1 on line */
+    OFFLINE(0, "offline"),
+    ONLINE(1, "online");
 
-    public static DataSourceClient getDataSourceClient() {
-        if (null != INSTANCE) {
-            return INSTANCE;
-        }
-        synchronized (LOCK) {
-            if (null != INSTANCE) {
-                return INSTANCE;
+    ReleaseState(int code, String descp) {
+        this.code = code;
+        this.descp = descp;
+    }
+
+    @EnumValue private final int code;
+    private final String descp;
+
+    public static ReleaseState getEnum(int value) {
+        for (ReleaseState e : ReleaseState.values()) {
+            if (e.ordinal() == value) {
+                return e;
             }
-            INSTANCE = new DataSourceClient();
-            return INSTANCE;
         }
+        // For values out of enum scope
+        return null;
+    }
+
+    public int getCode() {
+        return code;
+    }
+
+    public String getDescp() {
+        return descp;
     }
 }
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/impl/MysqlDatasourceConfigSwitcher.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/common/ResUploadType.java
similarity index 73%
copy from seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/impl/MysqlDatasourceConfigSwitcher.java
copy to seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/common/ResUploadType.java
index 7da09161..5a7e570c 100644
--- a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/impl/MysqlDatasourceConfigSwitcher.java
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/common/ResUploadType.java
@@ -15,10 +15,12 @@
  * limitations under the License.
  */
 
-package org.apache.seatunnel.app.thridparty.datasource.impl;
+package org.apache.seatunnel.app.common;
 
-public class MysqlDatasourceConfigSwitcher extends BaseJdbcDataSourceConfigSwitcher {
-    public static MysqlDatasourceConfigSwitcher INSTANCE = new MysqlDatasourceConfigSwitcher();
-
-    private MysqlDatasourceConfigSwitcher() {}
+/** data base types */
+public enum ResUploadType {
+    /** 0 hdfs 1 s3 2 none */
+    HDFS,
+    S3,
+    NONE
 }
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/impl/MysqlDatasourceConfigSwitcher.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/common/ResourceType.java
similarity index 73%
copy from seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/impl/MysqlDatasourceConfigSwitcher.java
copy to seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/common/ResourceType.java
index 7da09161..c220d8ce 100644
--- a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/impl/MysqlDatasourceConfigSwitcher.java
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/common/ResourceType.java
@@ -15,10 +15,9 @@
  * limitations under the License.
  */
 
-package org.apache.seatunnel.app.thridparty.datasource.impl;
+package org.apache.seatunnel.app.common;
 
-public class MysqlDatasourceConfigSwitcher extends BaseJdbcDataSourceConfigSwitcher {
-    public static MysqlDatasourceConfigSwitcher INSTANCE = new MysqlDatasourceConfigSwitcher();
-
-    private MysqlDatasourceConfigSwitcher() {}
+public enum ResourceType {
+    DATASOURCE,
+    UDF;
 }
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/common/Status.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/common/Status.java
new file mode 100644
index 00000000..39ec64d3
--- /dev/null
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/common/Status.java
@@ -0,0 +1,854 @@
+/*
+ * 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.seatunnel.app.common;
+
+import org.springframework.context.i18n.LocaleContextHolder;
+
+import java.util.Locale;
+import java.util.Optional;
+
+/** status enum // todo #4855 One category one interval */
+public enum Status {
+    SUCCESS(0, "success", "成功"),
+    FAILED(1, "failed", "失败"),
+    INTERNAL_SERVER_ERROR_ARGS(10000, "Internal Server Error: {0}", "服务端异常: {0}"),
+
+    REQUEST_PARAMS_NOT_VALID_ERROR(10001, "request parameter {0} is not valid", "请求参数[{0}]无效"),
+    TASK_TIMEOUT_PARAMS_ERROR(10002, "task timeout parameter is not valid", "任务超时参数无效"),
+    USER_NAME_EXIST(10003, "user name already exists", "用户名已存在"),
+    USER_NAME_NULL(10004, "user name is null", "用户名不能为空"),
+    HDFS_OPERATION_ERROR(10006, "hdfs operation error", "hdfs操作错误"),
+    TASK_INSTANCE_NOT_FOUND(10008, "task instance not found", "任务实例不存在"),
+    OS_TENANT_CODE_EXIST(10009, "os tenant code {0} already exists", "操作系统租户[{0}]已存在"),
+    USER_NOT_EXIST(10010, "user {0} not exists", "用户[{0}]不存在"),
+    ALERT_GROUP_NOT_EXIST(10011, "alarm group not found", "告警组不存在"),
+    ALERT_GROUP_EXIST(10012, "alarm group already exists", "告警组名称已存在"),
+    USER_NAME_PASSWD_ERROR(10013, "user name or password error", "用户名或密码错误"),
+    LOGIN_SESSION_FAILED(10014, "create session failed!", "创建session失败"),
+    DATASOURCE_EXIST(10015, "data source name already exists", "数据源名称已存在"),
+    DATASOURCE_CONNECT_FAILED(10016, "data source connection failed", "建立数据源连接失败"),
+    TENANT_NOT_EXIST(10017, "tenant not exists", "租户不存在"),
+    PROJECT_NOT_FOUND(10018, "project {0} not found ", "项目[{0}]不存在"),
+    PROJECT_ALREADY_EXISTS(10019, "project {0} already exists", "项目名称[{0}]已存在"),
+    TASK_INSTANCE_NOT_EXISTS(10020, "task instance {0} does not exist", "任务实例[{0}]不存在"),
+    TASK_INSTANCE_NOT_SUB_WORKFLOW_INSTANCE(
+            10021, "task instance {0} is not sub process instance", "任务实例[{0}]不是子流程实例"),
+    SCHEDULE_CRON_NOT_EXISTS(10022, "scheduler crontab {0} does not exist", "调度配置定时表达式[{0}]不存在"),
+    SCHEDULE_CRON_ONLINE_FORBID_UPDATE(
+            10023, "online status does not allow update operations", "调度配置上线状态不允许修改"),
+    SCHEDULE_CRON_CHECK_FAILED(
+            10024, "scheduler crontab expression validation failure: {0}", "调度配置定时表达式验证失败: {0}"),
+    MASTER_NOT_EXISTS(10025, "master does not exist", "无可用master节点"),
+    SCHEDULE_STATUS_UNKNOWN(10026, "unknown status: {0}", "未知状态: {0}"),
+    CREATE_ALERT_GROUP_ERROR(10027, "create alert group error", "创建告警组错误"),
+    QUERY_ALL_ALERTGROUP_ERROR(10028, "query all alertgroup error", "查询告警组错误"),
+    LIST_PAGING_ALERT_GROUP_ERROR(10029, "list paging alert group error", "分页查询告警组错误"),
+    UPDATE_ALERT_GROUP_ERROR(10030, "update alert group error", "更新告警组错误"),
+    DELETE_ALERT_GROUP_ERROR(10031, "delete alert group error", "删除告警组错误"),
+    ALERT_GROUP_GRANT_USER_ERROR(10032, "alert group grant user error", "告警组授权用户错误"),
+    CREATE_DATASOURCE_ERROR(10033, "create datasource error", "创建数据源错误"),
+    UPDATE_DATASOURCE_ERROR(10034, "update datasource error", "更新数据源错误"),
+    QUERY_DATASOURCE_ERROR(10035, "query datasource error", "查询数据源错误"),
+    CONNECT_DATASOURCE_FAILURE(10036, "connect datasource failure", "建立数据源连接失败"),
+    CONNECTION_TEST_FAILURE(10037, "connection test failure", "测试数据源连接失败"),
+    DELETE_DATA_SOURCE_FAILURE(10038, "delete data source failure", "删除数据源失败"),
+    VERIFY_DATASOURCE_NAME_FAILURE(10039, "verify datasource name failure", "验证数据源名称失败"),
+    UNAUTHORIZED_DATASOURCE(10040, "unauthorized datasource", "未经授权的数据源"),
+    AUTHORIZED_DATA_SOURCE(10041, "authorized data source", "授权数据源失败"),
+    LOGIN_SUCCESS(10042, "login success", "登录成功"),
+    USER_LOGIN_FAILURE(10043, "user login failure", "用户登录失败"),
+    LIST_WORKERS_ERROR(10044, "list workers error", "查询worker列表错误"),
+    LIST_MASTERS_ERROR(10045, "list masters error", "查询master列表错误"),
+    UPDATE_PROJECT_ERROR(10046, "update project error", "更新项目信息错误"),
+    QUERY_PROJECT_DETAILS_BY_CODE_ERROR(10047, "query project details by code error", "查询项目详细信息错误"),
+    CREATE_PROJECT_ERROR(10048, "create project error", "创建项目错误"),
+    LOGIN_USER_QUERY_PROJECT_LIST_PAGING_ERROR(
+            10049, "login user query project list paging error", "分页查询项目列表错误"),
+    DELETE_PROJECT_ERROR(10050, "delete project error", "删除项目错误"),
+    QUERY_UNAUTHORIZED_PROJECT_ERROR(10051, "query unauthorized project error", "查询未授权项目错误"),
+    QUERY_AUTHORIZED_PROJECT(10052, "query authorized project", "查询授权项目错误"),
+    QUERY_QUEUE_LIST_ERROR(10053, "query queue list error", "查询队列列表错误"),
+    CREATE_RESOURCE_ERROR(10054, "create resource error", "创建资源错误"),
+    UPDATE_RESOURCE_ERROR(10055, "update resource error", "更新资源错误"),
+    QUERY_RESOURCES_LIST_ERROR(10056, "query resources list error", "查询资源列表错误"),
+    QUERY_RESOURCES_LIST_PAGING(10057, "query resources list paging", "分页查询资源列表错误"),
+    DELETE_RESOURCE_ERROR(10058, "delete resource error", "删除资源错误"),
+    VERIFY_RESOURCE_BY_NAME_AND_TYPE_ERROR(
+            10059, "verify resource by name and type error", "资源名称或类型验证错误"),
+    VIEW_RESOURCE_FILE_ON_LINE_ERROR(10060, "view resource file online error", "查看资源文件错误"),
+    CREATE_RESOURCE_FILE_ON_LINE_ERROR(10061, "create resource file online error", "创建资源文件错误"),
+    RESOURCE_FILE_CATNOT_BE_EMPTY(10062, "resource file is empty", "资源文件内容不能为空"),
+    EDIT_RESOURCE_FILE_ON_LINE_ERROR(10063, "edit resource file online error", "更新资源文件错误"),
+    DOWNLOAD_RESOURCE_FILE_ERROR(10064, "download resource file error", "下载资源文件错误"),
+    CREATE_UDF_FUNCTION_ERROR(10065, "create udf function error", "创建UDF函数错误"),
+    VIEW_UDF_FUNCTION_ERROR(10066, "view udf function error", "查询UDF函数错误"),
+    UPDATE_UDF_FUNCTION_ERROR(10067, "update udf function error", "更新UDF函数错误"),
+    QUERY_UDF_FUNCTION_LIST_PAGING_ERROR(
+            10068, "query udf function list paging error", "分页查询UDF函数列表错误"),
+    QUERY_DATASOURCE_BY_TYPE_ERROR(10069, "query datasource by type error", "查询数据源信息错误"),
+    VERIFY_UDF_FUNCTION_NAME_ERROR(10070, "verify udf function name error", "UDF函数名称验证错误"),
+    DELETE_UDF_FUNCTION_ERROR(10071, "delete udf function error", "删除UDF函数错误"),
+    AUTHORIZED_FILE_RESOURCE_ERROR(10072, "authorized file resource error", "授权资源文件错误"),
+    AUTHORIZE_RESOURCE_TREE(10073, "authorize resource tree display error", "授权资源目录树错误"),
+    UNAUTHORIZED_UDF_FUNCTION_ERROR(10074, "unauthorized udf function error", "查询未授权UDF函数错误"),
+    AUTHORIZED_UDF_FUNCTION_ERROR(10075, "authorized udf function error", "授权UDF函数错误"),
+    CREATE_SCHEDULE_ERROR(10076, "create schedule error", "创建调度配置错误"),
+    UPDATE_SCHEDULE_ERROR(10077, "update schedule error", "更新调度配置错误"),
+    PUBLISH_SCHEDULE_ONLINE_ERROR(10078, "publish schedule online error", "上线调度配置错误"),
+    OFFLINE_SCHEDULE_ERROR(10079, "offline schedule error", "下线调度配置错误"),
+    QUERY_SCHEDULE_LIST_PAGING_ERROR(10080, "query schedule list paging error", "分页查询调度配置列表错误"),
+    QUERY_SCHEDULE_LIST_ERROR(10081, "query schedule list error", "查询调度配置列表错误"),
+    QUERY_TASK_LIST_PAGING_ERROR(10082, "query task list paging error", "分页查询任务列表错误"),
+    QUERY_TASK_RECORD_LIST_PAGING_ERROR(10083, "query task record list paging error", "分页查询任务记录错误"),
+    CREATE_TENANT_ERROR(10084, "create tenant error", "创建租户错误"),
+    QUERY_TENANT_LIST_PAGING_ERROR(10085, "query tenant list paging error", "分页查询租户列表错误"),
+    QUERY_TENANT_LIST_ERROR(10086, "query tenant list error", "查询租户列表错误"),
+    UPDATE_TENANT_ERROR(10087, "update tenant error", "更新租户错误"),
+    DELETE_TENANT_BY_ID_ERROR(10088, "delete tenant by id error", "删除租户错误"),
+    VERIFY_OS_TENANT_CODE_ERROR(10089, "verify os tenant code error", "操作系统租户验证错误"),
+    CREATE_USER_ERROR(10090, "create user error", "创建用户错误"),
+    QUERY_USER_LIST_PAGING_ERROR(10091, "query user list paging error", "分页查询用户列表错误"),
+    UPDATE_USER_ERROR(10092, "update user error", "更新用户错误"),
+    DELETE_USER_BY_ID_ERROR(10093, "delete user by id error", "删除用户错误"),
+    GRANT_PROJECT_ERROR(10094, "grant project error", "授权项目错误"),
+    GRANT_RESOURCE_ERROR(10095, "grant resource error", "授权资源错误"),
+    GRANT_UDF_FUNCTION_ERROR(10096, "grant udf function error", "授权UDF函数错误"),
+    GRANT_DATASOURCE_ERROR(10097, "grant datasource error", "授权数据源错误"),
+    GET_USER_INFO_ERROR(10098, "get user info error", "获取用户信息错误"),
+    USER_LIST_ERROR(10099, "user list error", "查询用户列表错误"),
+    VERIFY_USERNAME_ERROR(10100, "verify username error", "用户名验证错误"),
+    UNAUTHORIZED_USER_ERROR(10101, "unauthorized user error", "查询未授权用户错误"),
+    AUTHORIZED_USER_ERROR(10102, "authorized user error", "查询授权用户错误"),
+    QUERY_TASK_INSTANCE_LOG_ERROR(10103, "view task instance log error", "查询任务实例日志错误"),
+    DOWNLOAD_TASK_INSTANCE_LOG_FILE_ERROR(
+            10104, "download task instance log file error", "下载任务日志文件错误"),
+    CREATE_PROCESS_DEFINITION_ERROR(10105, "create process definition error", "创建工作流错误"),
+    VERIFY_PROCESS_DEFINITION_NAME_UNIQUE_ERROR(
+            10106, "verify process definition name unique error", "工作流定义名称验证错误"),
+    UPDATE_PROCESS_DEFINITION_ERROR(10107, "update process definition error", "更新工作流定义错误"),
+    RELEASE_PROCESS_DEFINITION_ERROR(10108, "release process definition error", "上线工作流错误"),
+    QUERY_DETAIL_OF_PROCESS_DEFINITION_ERROR(
+            10109, "query detail of process definition error", "查询工作流详细信息错误"),
+    QUERY_PROCESS_DEFINITION_LIST(10110, "query process definition list", "查询工作流列表错误"),
+    ENCAPSULATION_TREEVIEW_STRUCTURE_ERROR(
+            10111, "encapsulation treeview structure error", "查询工作流树形图数据错误"),
+    GET_TASKS_LIST_BY_PROCESS_DEFINITION_ID_ERROR(
+            10112, "get tasks list by process definition id error", "查询工作流定义节点信息错误"),
+    QUERY_PROCESS_INSTANCE_LIST_PAGING_ERROR(
+            10113, "query process instance list paging error", "分页查询工作流实例列表错误"),
+    QUERY_TASK_LIST_BY_PROCESS_INSTANCE_ID_ERROR(
+            10114, "query task list by process instance id error", "查询任务实例列表错误"),
+    UPDATE_PROCESS_INSTANCE_ERROR(10115, "update process instance error", "更新工作流实例错误"),
+    QUERY_PROCESS_INSTANCE_BY_ID_ERROR(10116, "query process instance by id error", "查询工作流实例错误"),
+    DELETE_PROCESS_INSTANCE_BY_ID_ERROR(10117, "delete process instance by id error", "删除工作流实例错误"),
+    QUERY_SUB_PROCESS_INSTANCE_DETAIL_INFO_BY_TASK_ID_ERROR(
+            10118, "query sub process instance detail info by task id error", "查询子流程任务实例错误"),
+    QUERY_PARENT_PROCESS_INSTANCE_DETAIL_INFO_BY_SUB_PROCESS_INSTANCE_ID_ERROR(
+            10119,
+            "query parent process instance detail info by sub process instance id error",
+            "查询子流程该工作流实例错误"),
+    QUERY_PROCESS_INSTANCE_ALL_VARIABLES_ERROR(
+            10120, "query process instance all variables error", "查询工作流自定义变量信息错误"),
+    ENCAPSULATION_PROCESS_INSTANCE_GANTT_STRUCTURE_ERROR(
+            10121, "encapsulation process instance gantt structure error", "查询工作流实例甘特图数据错误"),
+    QUERY_PROCESS_DEFINITION_LIST_PAGING_ERROR(
+            10122, "query process definition list paging error", "分页查询工作流定义列表错误"),
+    SIGN_OUT_ERROR(10123, "sign out error", "退出错误"),
+    OS_TENANT_CODE_HAS_ALREADY_EXISTS(10124, "os tenant code has already exists", "操作系统租户已存在"),
+    IP_IS_EMPTY(10125, "ip is empty", "IP地址不能为空"),
+    SCHEDULE_CRON_REALEASE_NEED_NOT_CHANGE(
+            10126, "schedule release is already {0}", "调度配置上线错误[{0}]"),
+    CREATE_QUEUE_ERROR(10127, "create queue error", "创建队列错误"),
+    QUEUE_NOT_EXIST(10128, "queue {0} not exists", "队列ID[{0}]不存在"),
+    QUEUE_VALUE_EXIST(10129, "queue value {0} already exists", "队列值[{0}]已存在"),
+    QUEUE_NAME_EXIST(10130, "queue name {0} already exists", "队列名称[{0}]已存在"),
+    UPDATE_QUEUE_ERROR(10131, "update queue error", "更新队列信息错误"),
+    NEED_NOT_UPDATE_QUEUE(10132, "no content changes, no updates are required", "数据未变更,不需要更新队列信息"),
+    VERIFY_QUEUE_ERROR(10133, "verify queue error", "验证队列信息错误"),
+    NAME_NULL(10134, "name must be not null", "名称不能为空"),
+    NAME_EXIST(10135, "name {0} already exists", "名称[{0}]已存在"),
+    SAVE_ERROR(10136, "save error", "保存错误"),
+    DELETE_PROJECT_ERROR_DEFINES_NOT_NULL(
+            10137, "please delete the process definitions in project first!", "请先删除全部工作流定义"),
+    BATCH_DELETE_PROCESS_INSTANCE_BY_IDS_ERROR(
+            10117, "batch delete process instance by ids {0} error", "批量删除工作流实例错误: {0}"),
+    PREVIEW_SCHEDULE_ERROR(10139, "preview schedule error", "预览调度配置错误"),
+    PARSE_TO_CRON_EXPRESSION_ERROR(10140, "parse cron to cron expression error", "解析调度表达式错误"),
+    SCHEDULE_START_TIME_END_TIME_SAME(
+            10141, "The start time must not be the same as the end", "开始时间不能和结束时间一样"),
+    DELETE_TENANT_BY_ID_FAIL(
+            10142,
+            "delete tenant by id fail, for there are {0} process instances in executing using it",
+            "删除租户失败,有[{0}]个运行中的工作流实例正在使用"),
+    DELETE_TENANT_BY_ID_FAIL_DEFINES(
+            10143,
+            "delete tenant by id fail, for there are {0} process definitions using it",
+            "删除租户失败,有[{0}]个工作流定义正在使用"),
+    DELETE_TENANT_BY_ID_FAIL_USERS(
+            10144,
+            "delete tenant by id fail, for there are {0} users using it",
+            "删除租户失败,有[{0}]个用户正在使用"),
+    DELETE_WORKER_GROUP_BY_ID_FAIL(
+            10145,
+            "delete worker group by id fail, for there are {0} process instances in executing using it",
+            "删除Worker分组失败,有[{0}]个运行中的工作流实例正在使用"),
+    QUERY_WORKER_GROUP_FAIL(10146, "query worker group fail ", "查询worker分组失败"),
+    DELETE_WORKER_GROUP_FAIL(10147, "delete worker group fail ", "删除worker分组失败"),
+    USER_DISABLED(10148, "The current user is disabled", "当前用户已停用"),
+    COPY_PROCESS_DEFINITION_ERROR(
+            10149, "copy process definition from {0} to {1} error : {2}", "从{0}复制工作流到{1}错误 : {2}"),
+    MOVE_PROCESS_DEFINITION_ERROR(
+            10150, "move process definition from {0} to {1} error : {2}", "从{0}移动工作流到{1}错误 : {2}"),
+    SWITCH_PROCESS_DEFINITION_VERSION_ERROR(
+            10151, "Switch process definition version error", "切换工作流版本出错"),
+    SWITCH_PROCESS_DEFINITION_VERSION_NOT_EXIST_PROCESS_DEFINITION_ERROR(
+            10152,
+            "Switch process definition version error: not exists process definition, [process definition id {0}]",
+            "切换工作流版本出错:工作流不存在,[工作流id {0}]"),
+    SWITCH_PROCESS_DEFINITION_VERSION_NOT_EXIST_PROCESS_DEFINITION_VERSION_ERROR(
+            10153,
+            "Switch process definition version error: not exists process definition version, [process definition id {0}] [version number {1}]",
+            "切换工作流版本出错:工作流版本信息不存在,[工作流id {0}] [版本号 {1}]"),
+    QUERY_PROCESS_DEFINITION_VERSIONS_ERROR(
+            10154, "query process definition versions error", "查询工作流历史版本信息出错"),
+    DELETE_PROCESS_DEFINITION_VERSION_ERROR(
+            10156, "delete process definition version error", "删除工作流历史版本出错"),
+
+    QUERY_USER_CREATED_PROJECT_ERROR(
+            10157, "query user created project error error", "查询用户创建的项目错误"),
+    PROCESS_DEFINITION_CODES_IS_EMPTY(10158, "process definition codes is empty", "工作流CODES不能为空"),
+    BATCH_COPY_PROCESS_DEFINITION_ERROR(10159, "batch copy process definition error", "复制工作流错误"),
+    BATCH_MOVE_PROCESS_DEFINITION_ERROR(10160, "batch move process definition error", "移动工作流错误"),
+    QUERY_WORKFLOW_LINEAGE_ERROR(10161, "query workflow lineage error", "查询血缘失败"),
+
+    QUERY_WORKFLOW_LEVEL_IN_LINEAGE_ERROR(
+            1016101, "query workflow level in lineage error", "查询血缘中的工作流层级失败"),
+
+    QUERY_WORKFLOW_LINEAGE_ERROR_NOT_EXIST_PROCESS_INSTANCE(
+            1016102,
+            "query workflow lineage error, not exist process instance [{0}]",
+            "查询血缘失败,不存在工作流实例[{0}]"),
+    QUERY_AUTHORIZED_AND_USER_CREATED_PROJECT_ERROR(
+            10162, "query authorized and user created project error error", "查询授权的和用户创建的项目错误"),
+    DELETE_PROCESS_DEFINITION_EXECUTING_FAIL(
+            10163,
+            "delete process definition [{0}] fail, for there are [{1}] process instances in executing using it",
+            "删除工作流定义[{0}]失败,有[{1}]个运行中的工作流实例正在使用"),
+    CHECK_OS_TENANT_CODE_ERROR(
+            10164,
+            "Tenant code invalid, should follow linux's users naming conventions",
+            "非法的租户名,需要遵守 Linux 用户命名规范"),
+    FORCE_TASK_SUCCESS_ERROR(10165, "force task success error", "强制成功任务实例错误"),
+    TASK_INSTANCE_STATE_OPERATION_ERROR(
+            10166,
+            "the status of task instance {0} is {1},Cannot perform force success operation",
+            "任务实例[{0}]的状态是[{1}],无法执行强制成功操作"),
+    DATASOURCE_TYPE_NOT_EXIST(10167, "data source type not exist", "数据源类型不存在"),
+    PROCESS_DEFINITION_NAME_EXIST(
+            10168, "process definition name {0} already exists", "工作流定义名称[{0}]已存在"),
+    DATASOURCE_DB_TYPE_ILLEGAL(10169, "datasource type illegal", "数据源类型参数不合法"),
+    DATASOURCE_PORT_ILLEGAL(10170, "datasource port illegal", "数据源端口参数不合法"),
+    DATASOURCE_OTHER_PARAMS_ILLEGAL(10171, "datasource other params illegal", "数据源其他参数不合法"),
+    DATASOURCE_NAME_ILLEGAL(10172, "datasource name illegal", "数据源名称不合法"),
+    DATASOURCE_HOST_ILLEGAL(10173, "datasource host illegal", "数据源HOST不合法"),
+    DELETE_WORKER_GROUP_NOT_EXIST(10174, "delete worker group not exist ", "删除worker分组不存在"),
+    CREATE_WORKER_GROUP_FORBIDDEN_IN_DOCKER(
+            10175, "create worker group forbidden in docker ", "创建worker分组在docker中禁止"),
+    DELETE_WORKER_GROUP_FORBIDDEN_IN_DOCKER(
+            10176, "delete worker group forbidden in docker ", "删除worker分组在docker中禁止"),
+    WORKER_ADDRESS_INVALID(10177, "worker address {0} invalid", "worker地址[{0}]无效"),
+    QUERY_WORKER_ADDRESS_LIST_FAIL(10178, "query worker address list fail ", "查询worker地址列表失败"),
+    TRANSFORM_PROJECT_OWNERSHIP(
+            10179, "Please transform project ownership [{0}]", "请先转移项目所有权[{0}]"),
+    QUERY_ALERT_GROUP_ERROR(10180, "query alert group error", "查询告警组错误"),
+    CURRENT_LOGIN_USER_TENANT_NOT_EXIST(
+            10181, "the tenant of the currently login user is not specified", "未指定当前登录用户的租户"),
+    REVOKE_PROJECT_ERROR(10182, "revoke project error", "撤销项目授权错误"),
+    QUERY_AUTHORIZED_USER(10183, "query authorized user error", "查询拥有项目权限的用户错误"),
+
+    DATASOURCE_CONNECT_REJECT_KEYWORD(
+            10184,
+            "data source connection does not allow the [{0}] keyword",
+            "数据源连接参数不允许使用[{0}]关键字"),
+    PROJECT_NOT_EXIST(10190, "This project was not found. Please refresh page.", "该项目不存在,请刷新页面"),
+    TASK_INSTANCE_HOST_IS_NULL(10191, "task instance host is null", "任务实例host为空"),
+    QUERY_EXECUTING_WORKFLOW_ERROR(10192, "query executing workflow error", "查询运行的工作流实例错误"),
+    DELETE_PROCESS_DEFINITION_USE_BY_OTHER_FAIL(
+            10193,
+            "delete process definition [{0}] fail, cause used by other tasks: {1}",
+            "删除工作流[{0}]失败,被其他任务引用:{1}"),
+    DELETE_TASK_USE_BY_OTHER_FAIL(
+            10194,
+            "delete task {0} fail, cause used by other tasks: {1}",
+            "删除任务 {0} 失败,被其他任务引用:{1}"),
+    TASK_WITH_DEPENDENT_ERROR(10195, "task used in other tasks", "删除被其他任务引用"),
+    DELETE_PROCESS_DEFINITION_SCHEDULE_CRON_ERROR(
+            10196, "delete workflow [{0}] schedule error", "删除工作流 [{0}] 调度配置错误"),
+    DELETE_PROCESS_DEFINITION_SUCCESS(10197, "delete workflow [{0}] success", "删除工作流 [{0}] 成功"),
+    LIST_TASK_TYPE_ERROR(10200, "list task type error", "查询任务类型列表错误"),
+    DELETE_TASK_TYPE_ERROR(10200, "delete task type error", "删除任务类型错误"),
+    ADD_TASK_TYPE_ERROR(10200, "add task type error", "添加任务类型错误"),
+
+    LIST_ALERT_SERVERS_ERROR(10198, "list AlertServer error", "查询AlertServer列表错误"),
+
+    LIST_API_SERVERS_ERROR(10199, "list ApiServer error", "查询ApiServer列表错误"),
+
+    LISTING_EXECUTING_WORKFLOWS_BY_MASTER_ERROR(
+            10200, "listing executing workflows by master address error", "查询Master中运行的工作流实例信息错误"),
+    LISTING_DISPATCHING_TASK_INSTANCES_BY_MASTER_ERROR(
+            10201,
+            "listing dispatching TaskInstance by master address error",
+            "查询Master中正在分发的任务实例信息错误"),
+    LISTING_EXECUTING_TASK_EXECUTION_CONTEXT_BY_WORKER_ERROR(
+            10202,
+            "listing executing TaskExecutionContext by worker address error",
+            "查询Worker中正在执行的任务上下文信息错误"),
+    QUERY_TASK_EXECUTION_CONTEXT_DETAIL_ERROR(
+            10203, "query task execution context detail error", "查询Worker中的task上下文详情错误"),
+    CLEAN_TASK_INSTANCE_ERROR(10204, "clean task instance state error", "清除任务实例状态错误"),
+    CLEAN_TASK_INSTANCE_ERROR_WORKFLOW_INSTANCE_IS_RUNNING(
+            10205,
+            "clean task instance state error, the related workflow instance is running",
+            "清除任务实例状态错误,对应的工作流实例在运行中"),
+
+    CLEAN_TASK_INSTANCE_ERROR_COMMAND_ALREADY_EXIST(
+            10206,
+            "clean task instance state error, the related workflow instance is already exist a state clean operation, please try later",
+            "清除任务实例状态错误,对应的工作流实例已经有一个清除状态的操作,请稍后再试"),
+    QUERY_EXECUTING_WORKFLOWS_DETAIL_BY_ID(
+            10207, "query executing workflows detail by id error", "查询Master中运行的工作流实例详情错误"),
+
+    CLEAN_TASK_INSTANCE_ERROR_CURRENT_TASK_INSTANCE_IS_IN_ISOLATION_CHAIN(
+            10208,
+            "clean task instance state error, the current task instance is in coronation chain, please cancel the isolation first",
+            "清除任务实例状态错误,当前的任务实例在隔离链,请先解除隔离"),
+
+    CLEAN_TASK_INSTANCE_ERROR_CURRENT_TASK_INSTANCE_IS_IN_PAUSE(
+            10209,
+            "clean task instance state error, the current task instance is in coronation chain or isolation pause, no need to clean, it will be restored automatically when the condition is met",
+            "清除任务实例状态错误,当前的任务实例在加冕或隔离暂停中,无需清除重跑,条件允许后将自动恢复"),
+
+    PROJECT_CODE_NOT_EXIST(
+            10210, "This project {0} was not found. Please refresh page.", "项目{0}不存在,请刷新页面"),
+    CLEAN_TASK_INSTANCE_ERROR_UPSTREAM_WORKFLOW_INSTANCE_IS_RUNNING(
+            10211,
+            "clean task instance state error, the related upstream workflow instance [{0}]is running",
+            "清除任务实例状态错误,对应工作流实例为子工作流,但其引用该工作流的上游工作流[{0}]正在运行中"),
+
+    DEPENDENT_RUN_ERROR(10212, "dependent run error", "依赖链运行操作失败"),
+
+    CREATE_BATCH_RESOURCE_NOTES(10204, "create batch resource error", "创建资源错误"),
+    QUERY_PROJECT_DETAILS_BY_NAME_ERROR(10205, "query project details by name error", "查询项目详细信息错误"),
+    UDF_FUNCTION_NOT_EXIST(20001, "UDF function not found", "UDF函数不存在"),
+    UDF_FUNCTION_EXISTS(20002, "UDF function already exists", "UDF函数已存在"),
+    RESOURCE_NOT_EXIST(20004, "resource not exist", "资源不存在"),
+    RESOURCE_EXIST(20005, "resource already exists", "资源已存在"),
+    RESOURCE_SUFFIX_NOT_SUPPORT_VIEW(
+            20006, "resource suffix do not support online viewing", "资源文件后缀不支持查看"),
+    RESOURCE_SIZE_EXCEED_LIMIT(20007, "upload resource file size exceeds limit", "上传资源文件大小超过限制"),
+    RESOURCE_SUFFIX_FORBID_CHANGE(
+            20008, "resource suffix not allowed to be modified", "资源文件后缀不支持修改"),
+    UDF_RESOURCE_SUFFIX_NOT_JAR(
+            20009, "UDF resource suffix name must be jar", "UDF资源文件后缀名只支持[jar]"),
+    HDFS_COPY_FAIL(20010, "hdfs copy {0} -> {1} fail", "hdfs复制失败:[{0}] -> [{1}]"),
+    RESOURCE_FILE_EXIST(
+            20011,
+            "resource file {0} already exists in hdfs,please delete it or change name!",
+            "资源文件[{0}]在hdfs中已存在,请删除或修改资源名"),
+    RESOURCE_FILE_NOT_EXIST(20012, "resource file {0} not exists !", "资源文件[{0}]不存在"),
+    UDF_RESOURCE_IS_BOUND(
+            20013, "udf resource file is bound by UDF functions:{0}", "udf函数绑定了资源文件[{0}]"),
+    RESOURCE_IS_USED(20014, "resource file is used by process definition", "资源文件被上线的流程定义使用了"),
+    PARENT_RESOURCE_NOT_EXIST(20015, "parent resource not exist", "父资源文件不存在"),
+    RESOURCE_NOT_EXIST_OR_NO_PERMISSION(
+            20016,
+            "resource not exist or no permission,please view the task node and remove error resource",
+            "请检查任务节点并移除无权限或者已删除的资源"),
+    RESOURCE_IS_AUTHORIZED(
+            20017,
+            "resource is authorized to user {0},suffix not allowed to be modified",
+            "资源文件已授权其他用户[{0}],后缀不允许修改"),
+    RESOURCE_HAS_FOLDER(
+            20018, "There are files or folders in the current directory:{0}", "当前目录下有文件或文件夹[{0}]"),
+
+    BATCH_RESOURCE_NAME_REPEAT(20019, "duplicate file names in this batch", "此批处理中存在重复的文件名"),
+    RESOURCE_FILE_IS_EMPTY(20020, "resource file [{0}] is empty", "资源文件 [{0}] 内容不能为空"),
+
+    RESOURCE_OWNER_OR_TENANT_CHANGE_ERROR(
+            20021,
+            "resource[{0}] owner is deleted or the tenant is unbound, the operation is not allowed",
+            "资源[{0}]所属用户被删除或者其租户被解除绑定, 无法进行该操作"),
+
+    RESOURCE_CREATE_ERROR(20022, "resource[{0}] create error", "资源[{0}]创建失败"),
+
+    UPLOAD_FOLDER_WARNING(
+            20023,
+            "upload folder warning, create resource failed[{0}], delete resource failed[{1}], other resources upload success",
+            "文件夹上传警告,以下资源创建失败[{0}], 以下资源覆盖删除失败[{1}], 其余均已上传成功"),
+
+    UPLOAD_FOLDER_CREATE_WARNING(
+            20024,
+            "upload folder warning, create resource failed[{0}], other resources upload success",
+            "文件夹上传警告,以下资源创建失败[{0}], 其余均已上传成功"),
+
+    UPLOAD_FOLDER_DELETE_WARNING(
+            20025,
+            "upload folder warning, delete resource failed[{0}], other resources upload success",
+            "文件夹上传警告, 以下资源覆盖删除失败[{0}], 其余均已上传成功"),
+
+    RESOURCE_LIST_IS_USED(
+            20026, "resource file is used by process definition, [{0}]", "资源文件被上线的流程定义使用了, [{0}]"),
+
+    RESOURCE_IS_USED_BY_PROCESS(
+            20027, "resource file is used by process definition", "资源文件被流程定义使用了"),
+
+    USER_NO_OPERATION_PERM(30001, "user has no operation privilege", "当前用户没有操作权限"),
+    USER_NO_OPERATION_PROJECT_PERM(
+            30002,
+            "User [{0}] does not have this operation permission under the [{1}] project",
+            "用户[{0}]在[{1}]项目下无此操作权限"),
+
+    USER_CAN_NOT_OPERATION(
+            30003, "User [{0}] does not have permission for Project [{1}]", "用户[{0}]在项目[{1}]下无此权限"),
+
+    PROCESS_INSTANCE_NOT_EXIST(50001, "process instance {0} does not exist", "工作流实例[{0}]不存在"),
+    PROCESS_INSTANCE_EXIST(50002, "process instance {0} already exists", "工作流实例[{0}]已存在"),
+    PROCESS_DEFINE_NOT_EXIST(50003, "process definition [{0}] does not exist", "工作流定义[{0}]不存在"),
+    PROCESS_DEFINE_NOT_RELEASE(
+            50004,
+            "process definition {0} process version {1} not on line",
+            "工作流定义[{0}] 工作流版本[{1}]不是上线状态"),
+    SUB_PROCESS_DEFINE_NOT_RELEASE(
+            50004, "exist sub process definition not on line", "存在子工作流定义不是上线状态"),
+    PROCESS_INSTANCE_ALREADY_CHANGED(
+            50005, "the status of process instance {0} is already {1}", "工作流实例[{0}]的状态已经是[{1}]"),
+    PROCESS_INSTANCE_STATE_OPERATION_ERROR(
+            50006,
+            "the status of process instance {0} is {1},Cannot perform {2} operation",
+            "工作流实例[{0}]的状态是[{1}],无法执行[{2}]操作"),
+    SUB_PROCESS_INSTANCE_NOT_EXIST(
+            50007, "the task belong to process instance does not exist", "子工作流实例不存在"),
+    PROCESS_DEFINE_NOT_ALLOWED_EDIT(
+            50008, "process definition {0} does not allow edit", "工作流定义[{0}]不允许修改"),
+    PROCESS_INSTANCE_EXECUTING_COMMAND(
+            50009,
+            "process instance {0} is executing the command, please wait ...",
+            "工作流实例[{0}]正在执行命令,请稍等..."),
+    PROCESS_INSTANCE_NOT_SUB_PROCESS_INSTANCE(
+            50010, "process instance {0} is not sub process instance", "工作流实例[{0}]不是子工作流实例"),
+    TASK_INSTANCE_STATE_COUNT_ERROR(50011, "task instance state count error", "查询各状态任务实例数错误"),
+    COUNT_PROCESS_INSTANCE_STATE_ERROR(50012, "count process instance state error", "查询各状态流程实例数错误"),
+    COUNT_PROCESS_DEFINITION_USER_ERROR(
+            50013, "count process definition user error", "查询各用户流程定义数错误"),
+    START_PROCESS_INSTANCE_ERROR(50014, "start process instance error", "运行工作流实例错误"),
+    BATCH_START_PROCESS_INSTANCE_ERROR(
+            50014, "batch start process instance error: {0}", "批量运行工作流实例错误: {0}"),
+    PROCESS_INSTANCE_ERROR(50014, "process instance delete error: {0}", "工作流实例删除[{0}]错误"),
+    EXECUTE_PROCESS_INSTANCE_ERROR(50015, "execute process instance error", "操作工作流实例错误"),
+    CHECK_PROCESS_DEFINITION_ERROR(50016, "check process definition error", "工作流定义错误"),
+    QUERY_RECIPIENTS_AND_COPYERS_BY_PROCESS_DEFINITION_ERROR(
+            50017, "query recipients and copyers by process definition error", "查询收件人和抄送人错误"),
+    DATA_IS_NOT_VALID(50017, "data {0} not valid", "数据[{0}]无效"),
+    DATA_IS_NULL(50018, "data {0} is null", "数据[{0}]不能为空"),
+    PROCESS_NODE_HAS_CYCLE(50019, "process node has cycle", "流程节点间存在循环依赖"),
+    PROCESS_NODE_S_PARAMETER_INVALID(50020, "process node {0} parameter invalid", "流程节点[{0}]参数无效"),
+    PROCESS_DEFINE_STATE_ONLINE(
+            50021, "process definition [{0}] is already on line", "工作流定义[{0}]已上线"),
+    DELETE_PROCESS_DEFINE_BY_CODE_ERROR(
+            50022, "delete process definition by code error", "删除工作流定义错误"),
+    SCHEDULE_CRON_STATE_ONLINE(
+            50023, "the status of schedule {0} is already on line", "调度配置[{0}]已上线"),
+    DELETE_SCHEDULE_CRON_BY_ID_ERROR(50024, "delete schedule by id error", "删除调度配置错误"),
+    BATCH_DELETE_PROCESS_DEFINE_ERROR(
+            50025, "batch delete process definition error", "批量删除工作流定义错误"),
+    BATCH_DELETE_PROCESS_DEFINE_BY_CODES_ERROR(
+            50026, "batch delete process definition by codes error {0}", "批量删除工作流定义错误 [{0}]"),
+    DELETE_PROCESS_DEFINE_BY_CODES_ERROR(
+            50026, "delete process definition by codes {0} error", "删除工作流定义[{0}]错误"),
+    TENANT_NOT_SUITABLE(
+            50027,
+            "there is not any tenant suitable, please choose a tenant available.",
+            "没有合适的租户,请选择可用的租户"),
+    EXPORT_PROCESS_DEFINE_BY_ID_ERROR(50028, "export process definition by id error", "导出工作流定义错误"),
+    BATCH_EXPORT_PROCESS_DEFINE_BY_IDS_ERROR(
+            50028, "batch export process definition by ids error", "批量导出工作流定义错误"),
+    IMPORT_PROCESS_DEFINE_ERROR(50029, "import process definition error", "导入工作流定义错误"),
+    TASK_DEFINE_NOT_EXIST(50030, "task definition [{0}] does not exist", "任务定义[{0}]不存在"),
+    CREATE_PROCESS_TASK_RELATION_ERROR(50032, "create process task relation error", "创建工作流任务关系错误"),
+    PROCESS_TASK_RELATION_NOT_EXIST(
+            50033, "process task relation [{0}] does not exist", "工作流任务关系[{0}]不存在"),
+    PROCESS_TASK_RELATION_EXIST(
+            50034,
+            "process task relation is already exist, processCode:[{0}]",
+            "工作流任务关系已存在, processCode:[{0}]"),
+    PROCESS_DAG_IS_EMPTY(50035, "process dag is empty", "工作流dag是空"),
+    CHECK_PROCESS_TASK_RELATION_ERROR(50036, "check process task relation error", "工作流任务关系参数错误"),
+    CREATE_TASK_DEFINITION_ERROR(50037, "create task definition error", "创建任务错误"),
+    UPDATE_TASK_DEFINITION_ERROR(50038, "update task definition error", "更新任务定义错误"),
+    QUERY_TASK_DEFINITION_VERSIONS_ERROR(
+            50039, "query task definition versions error", "查询任务历史版本信息出错"),
+    SWITCH_TASK_DEFINITION_VERSION_ERROR(50040, "Switch task definition version error", "切换任务版本出错"),
+    DELETE_TASK_DEFINITION_VERSION_ERROR(
+            50041, "delete task definition version error", "删除任务历史版本出错"),
+    DELETE_TASK_DEFINE_BY_CODE_ERROR(50042, "delete task definition by code error", "删除任务定义错误"),
+    QUERY_DETAIL_OF_TASK_DEFINITION_ERROR(
+            50043, "query detail of task definition error", "查询任务详细信息错误"),
+    QUERY_TASK_DEFINITION_LIST_PAGING_ERROR(
+            50044, "query task definition list paging error", "分页查询任务定义列表错误"),
+    TASK_DEFINITION_NAME_EXISTED(
+            50045, "task definition name [{0}] already exists", "任务定义名称[{0}]已经存在"),
+    RELEASE_TASK_DEFINITION_ERROR(50046, "release task definition error", "上线任务错误"),
+    MOVE_PROCESS_TASK_RELATION_ERROR(50047, "move process task relation error", "移动任务到其他工作流错误"),
+    DELETE_TASK_PROCESS_RELATION_ERROR(50048, "delete process task relation error", "删除工作流任务关系错误"),
+    QUERY_TASK_PROCESS_RELATION_ERROR(50049, "query process task relation error", "查询工作流任务关系错误"),
+    TASK_DEFINE_STATE_ONLINE(50050, "task definition [{0}] is already on line", "任务定义[{0}]已上线"),
+    TASK_HAS_DOWNSTREAM(50051, "Task exists downstream [{0}] dependence", "任务存在下游[{0}]依赖"),
+    TASK_HAS_UPSTREAM(50052, "Task [{0}] exists upstream dependence", "任务[{0}]存在上游依赖"),
+    MAIN_TABLE_USING_VERSION(50053, "the version that the master table is using", "主表正在使用该版本"),
+    PROJECT_PROCESS_NOT_MATCH(50054, "the project and the process is not match", "项目和工作流不匹配"),
+    DELETE_EDGE_ERROR(50055, "delete edge error", "删除工作流任务连接线错误"),
+    NOT_SUPPORT_UPDATE_TASK_DEFINITION(
+            50056, "task state does not support modification", "当前任务不支持修改"),
+    NOT_SUPPORT_COPY_TASK_TYPE(50057, "task type [{0}] does not support copy", "不支持复制的任务类型[{0}]"),
+    BATCH_EXECUTE_PROCESS_INSTANCE_ERROR(
+            50058, "change process instance status error: {0}", "修改工作实例状态错误: {0}"),
+    PROCESS_DEFINE_RELEASE(
+            50059,
+            "process definition {0} process version {1} on line",
+            "工作流定义[{0}] 工作流版本[{1}]是上线状态"),
+    TASK_HAVE_EMPTY_LOCAL_PARAM(50060, "task {0} have empty local parameter", "任务[{0}]存在为空的本地参数"),
+    HDFS_NOT_STARTUP(60001, "hdfs not startup", "hdfs未启用"),
+    STORAGE_NOT_STARTUP(60002, "storage not startup", "存储未启用"),
+    S3_CANNOT_RENAME(60003, "directory cannot be renamed", "S3无法重命名文件夹"),
+
+    /** for monitor */
+    QUERY_DATABASE_STATE_ERROR(70001, "query database state error", "查询数据库状态错误"),
+
+    CREATE_ACCESS_TOKEN_ERROR(70010, "create access token error", "创建访问token错误"),
+    GENERATE_TOKEN_ERROR(70011, "generate token error", "生成token错误"),
+    QUERY_ACCESSTOKEN_LIST_PAGING_ERROR(
+            70012, "query access token list paging error", "分页查询访问token列表错误"),
+    UPDATE_ACCESS_TOKEN_ERROR(70013, "update access token error", "更新访问token错误"),
+    DELETE_ACCESS_TOKEN_ERROR(70014, "delete access token error", "删除访问token错误"),
+    ACCESS_TOKEN_NOT_EXIST(70015, "access token not exist", "访问token不存在"),
+    QUERY_ACCESSTOKEN_BY_USER_ERROR(70016, "query access token by user error", "查询访问指定用户的token错误"),
+
+    COMMAND_STATE_COUNT_ERROR(80001, "task instance state count error", "查询各状态任务实例数错误"),
+    NEGTIVE_SIZE_NUMBER_ERROR(80002, "query size number error", "查询size错误"),
+    START_TIME_BIGGER_THAN_END_TIME_ERROR(
+            80003, "start time bigger than end time error", "开始时间在结束时间之后错误"),
+    QUEUE_COUNT_ERROR(90001, "queue count error", "查询队列数据错误"),
+
+    KERBEROS_STARTUP_STATE(100001, "get kerberos startup state error", "获取kerberos启动状态错误"),
+
+    // audit log
+    QUERY_AUDIT_LOG_LIST_PAGING(10057, "query resources list paging", "分页查询资源列表错误"),
+
+    // plugin
+    PLUGIN_NOT_A_UI_COMPONENT(
+            110001, "query plugin error, this plugin has no UI component", "查询插件错误,此插件无UI组件"),
+    QUERY_PLUGINS_RESULT_IS_NULL(
+            110002,
+            "query alarm plugins result is empty, please check the startup status of the alarm component and confirm that the relevant alarm plugin is successfully registered",
+            "查询告警插件为空, 请检查告警组件启动状态并确认相关告警插件已注册成功"),
+    QUERY_PLUGINS_ERROR(110003, "query plugins error", "查询插件错误"),
+    QUERY_PLUGIN_DETAIL_RESULT_IS_NULL(110004, "query plugin detail result is null", "查询插件详情结果为空"),
+
+    UPDATE_ALERT_PLUGIN_INSTANCE_ERROR(
+            110005, "update alert plugin instance error", "更新告警组和告警组插件实例错误"),
+    DELETE_ALERT_PLUGIN_INSTANCE_ERROR(
+            110006, "delete alert plugin instance error", "删除告警组和告警组插件实例错误"),
+    GET_ALERT_PLUGIN_INSTANCE_ERROR(110007, "get alert plugin instance error", "获取告警组和告警组插件实例错误"),
+    CREATE_ALERT_PLUGIN_INSTANCE_ERROR(
+            110008, "create alert plugin instance error", "创建告警组和告警组插件实例错误"),
+    QUERY_ALL_ALERT_PLUGIN_INSTANCE_ERROR(
+            110009, "query all alert plugin instance error", "查询所有告警实例失败"),
+    PLUGIN_INSTANCE_ALREADY_EXIT(110010, "plugin instance already exit", "该告警插件实例已存在"),
+    LIST_PAGING_ALERT_PLUGIN_INSTANCE_ERROR(
+            110011, "query plugin instance page error", "分页查询告警实例失败"),
+    DELETE_ALERT_PLUGIN_INSTANCE_ERROR_HAS_ALERT_GROUP_ASSOCIATED(
+            110012,
+            "failed to delete the alert instance, there is an alarm group associated with this alert instance",
+            "删除告警实例失败,存在与此告警实例关联的警报组"),
+    PROCESS_DEFINITION_VERSION_IS_USED(
+            110013, "this process definition version is used", "此工作流定义版本被使用"),
+
+    CREATE_ENVIRONMENT_ERROR(120001, "create environment error", "创建环境失败"),
+    ENVIRONMENT_NAME_EXISTS(120002, "this environment name [{0}] already exists", "环境名称[{0}]已经存在"),
+    ENVIRONMENT_NAME_IS_NULL(120003, "this environment name shouldn't be empty.", "环境名称不能为空"),
+    ENVIRONMENT_CONFIG_IS_NULL(120004, "this environment config shouldn't be empty.", "环境配置信息不能为空"),
+    UPDATE_ENVIRONMENT_ERROR(120005, "update environment [{0}] info error", "更新环境[{0}]信息失败"),
+    DELETE_ENVIRONMENT_ERROR(120006, "delete environment error", "删除环境信息失败"),
+    DELETE_ENVIRONMENT_RELATED_TASK_EXISTS(
+            120007,
+            "this environment has been used in tasks,so you can't delete it.",
+            "该环境已经被任务使用,所以不能删除该环境信息"),
+    QUERY_ENVIRONMENT_BY_NAME_ERROR(1200008, "not found environment [{0}] ", "查询环境名称[{0}]信息不存在"),
+    QUERY_ENVIRONMENT_BY_CODE_ERROR(1200009, "not found environment [{0}] ", "查询环境编码[{0}]不存在"),
+    QUERY_ENVIRONMENT_ERROR(1200010, "login user query environment error", "分页查询环境列表错误"),
+    VERIFY_ENVIRONMENT_ERROR(1200011, "verify environment error", "验证环境信息错误"),
+    GET_RULE_FORM_CREATE_JSON_ERROR(
+            1200012, "get rule form create json error", "获取规则 FROM-CREATE-JSON 错误"),
+    QUERY_RULE_LIST_PAGING_ERROR(1200013, "query rule list paging error", "获取规则分页列表错误"),
+    QUERY_RULE_LIST_ERROR(1200014, "query rule list error", "获取规则列表错误"),
+    QUERY_RULE_INPUT_ENTRY_LIST_ERROR(1200015, "query rule list error", "获取规则列表错误"),
+    QUERY_EXECUTE_RESULT_LIST_PAGING_ERROR(
+            1200016, "query execute result list paging error", "获取数据质量任务结果分页错误"),
+    GET_DATASOURCE_OPTIONS_ERROR(1200017, "get datasource options error", "获取数据源Options错误"),
+    GET_DATASOURCE_TABLES_ERROR(1200018, "get datasource tables error", "获取数据源表列表错误"),
+    GET_DATASOURCE_TABLE_COLUMNS_ERROR(1200019, "get datasource table columns error", "获取数据源表列名错误"),
+
+    CREATE_CLUSTER_ERROR(120020, "create cluster error", "创建集群失败"),
+    CLUSTER_NAME_EXISTS(120021, "this cluster name [{0}] already exists", "集群名称[{0}]已经存在"),
+    CLUSTER_NAME_IS_NULL(120022, "this cluster name shouldn't be empty.", "集群名称不能为空"),
+    CLUSTER_CONFIG_IS_NULL(120023, "this cluster config shouldn't be empty.", "集群配置信息不能为空"),
+    UPDATE_CLUSTER_ERROR(120024, "update cluster [{0}] info error", "更新集群[{0}]信息失败"),
+    DELETE_CLUSTER_ERROR(120025, "delete cluster error", "删除集群信息失败"),
+    DELETE_CLUSTER_RELATED_TASK_EXISTS(
+            120026,
+            "this cluster has been used in tasks,so you can't delete it.",
+            "该集群已经被任务使用,所以不能删除该集群信息"),
+    QUERY_CLUSTER_BY_NAME_ERROR(1200027, "not found cluster [{0}] ", "查询集群名称[{0}]信息不存在"),
+    QUERY_CLUSTER_BY_CODE_ERROR(1200028, "not found cluster [{0}] ", "查询集群编码[{0}]不存在"),
+    QUERY_CLUSTER_ERROR(1200029, "login user query cluster error", "分页查询集群列表错误"),
+    VERIFY_CLUSTER_ERROR(1200030, "verify cluster error", "验证集群信息错误"),
+    CLUSTER_PROCESS_DEFINITIONS_IS_INVALID(
+            1200031, "cluster worker groups is invalid format", "集群关联的工作组参数解析错误"),
+    UPDATE_CLUSTER_PROCESS_DEFINITION_RELATION_ERROR(
+            1200032,
+            "You can't modify the process definition, because the process definition [{0}] and this cluster [{1}] already be used in the task [{2}]",
+            "您不能修改集群选项,因为该工作流组 [{0}] 和 该集群 [{1}] 已经被用在任务 [{2}] 中"),
+    CLUSTER_NOT_EXISTS(120033, "this cluster can not found in db.", "集群配置数据库里查询不到为空"),
+    DELETE_CLUSTER_RELATED_NAMESPACE_EXISTS(
+            120034,
+            "this cluster has been used in namespace,so you can't delete it.",
+            "该集群已经被命名空间使用,所以不能删除该集群信息"),
+
+    TASK_GROUP_NAME_EXSIT(
+            130001, "this task group name is repeated in a project", "该任务组名称在一个项目中已经使用"),
+    TASK_GROUP_SIZE_ERROR(130002, "task group size error", "任务组大小应该为大于1的整数"),
+    TASK_GROUP_STATUS_ERROR(130003, "task group status error", "任务组已经被关闭"),
+    TASK_GROUP_FULL(130004, "task group is full", "任务组已经满了"),
+    TASK_GROUP_USED_SIZE_ERROR(
+            130005, "the used size number of task group is dirty", "任务组使用的容量发生了变化"),
+    TASK_GROUP_QUEUE_RELEASE_ERROR(130006, "failed to release task group queue", "任务组资源释放时出现了错误"),
+    TASK_GROUP_QUEUE_AWAKE_ERROR(130007, "awake waiting task failed", "任务组使唤醒等待任务时发生了错误"),
+    CREATE_TASK_GROUP_ERROR(130008, "create task group error", "创建任务组错误"),
+    UPDATE_TASK_GROUP_ERROR(130009, "update task group list error", "更新任务组错误"),
+    QUERY_TASK_GROUP_LIST_ERROR(130010, "query task group list error", "查询任务组列表错误"),
+    CLOSE_TASK_GROUP_ERROR(130011, "close task group error", "关闭任务组错误"),
+    START_TASK_GROUP_ERROR(130012, "start task group error", "启动任务组错误"),
+    QUERY_TASK_GROUP_QUEUE_LIST_ERROR(130013, "query task group queue list error", "查询任务组队列列表错误"),
+    TASK_GROUP_CACHE_START_FAILED(130014, "cache start failed", "任务组相关的缓存启动失败"),
+    ENVIRONMENT_WORKER_GROUPS_IS_INVALID(
+            130015, "environment worker groups is invalid format", "环境关联的工作组参数解析错误"),
+    UPDATE_ENVIRONMENT_WORKER_GROUP_RELATION_ERROR(
+            130016,
+            "You can't modify the worker group, because the worker group [{0}] and this environment [{1}] already be used in the task [{2}]",
+            "您不能修改工作组选项,因为该工作组 [{0}] 和 该环境 [{1}] 已经被用在任务 [{2}] 中"),
+    TASK_GROUP_QUEUE_ALREADY_START(130017, "task group queue already start", "节点已经获取任务组资源"),
+    TASK_GROUP_STATUS_CLOSED(130018, "The task group has been closed.", "任务组已经被关闭"),
+    TASK_GROUP_STATUS_OPENED(130019, "The task group has been opened.", "任务组已经被开启"),
+    NOT_ALLOW_TO_DISABLE_OWN_ACCOUNT(130020, "Not allow to disable your own account", "不能停用自己的账号"),
+    NOT_ALLOW_TO_DELETE_DEFAULT_ALARM_GROUP(
+            130030, "Not allow to delete the default alarm group ", "不能删除默认告警组"),
+    TIME_ZONE_ILLEGAL(130031, "time zone [{0}] is illegal", "时区参数 [{0}] 不合法"),
+
+    TASK_GROUP_USED_SIZE_NOT_EMPTY(
+            130032, "the used size number of task group is not empty", "任务组已使用容量不为空"),
+
+    QUERY_K8S_NAMESPACE_LIST_PAGING_ERROR(
+            1300001, "login user query k8s namespace list paging error", "分页查询k8s名称空间列表错误"),
+    K8S_NAMESPACE_EXIST(1300002, "k8s namespace {0} already exists", "k8s命名空间[{0}]已存在"),
+    CREATE_K8S_NAMESPACE_ERROR(1300003, "create k8s namespace error", "创建k8s命名空间错误"),
+    UPDATE_K8S_NAMESPACE_ERROR(1300004, "update k8s namespace error", "更新k8s命名空间信息错误"),
+    K8S_NAMESPACE_NOT_EXIST(1300005, "k8s namespace {0} not exists", "命名空间ID[{0}]不存在"),
+    K8S_CLIENT_OPS_ERROR(1300006, "k8s error with exception {0}", "k8s操作报错[{0}]"),
+    VERIFY_K8S_NAMESPACE_ERROR(1300007, "verify k8s and namespace error", "验证k8s命名空间信息错误"),
+    DELETE_K8S_NAMESPACE_BY_ID_ERROR(1300008, "delete k8s namespace by id error", "删除命名空间错误"),
+    VERIFY_PARAMETER_NAME_FAILED(1300009, "The file name [{0}] verify failed", "文件命名[{0}]校验失败"),
+    STORE_OPERATE_CREATE_ERROR(1300010, "create the resource failed", "存储操作失败"),
+    GRANT_K8S_NAMESPACE_ERROR(1300011, "grant namespace error", "授权资源错误"),
+    QUERY_UNAUTHORIZED_NAMESPACE_ERROR(
+            1300012, "query unauthorized namespace error", "查询未授权命名空间错误"),
+    QUERY_AUTHORIZED_NAMESPACE_ERROR(1300013, "query authorized namespace error", "查询授权命名空间错误"),
+    QUERY_CAN_USE_K8S_CLUSTER_ERROR(
+            1300014, "login user query can used k8s cluster list error", "查询可用k8s集群错误"),
+    RESOURCE_FULL_NAME_TOO_LONG_ERROR(1300015, "resource's fullname is too long error", "资源文件名过长"),
+    TENANT_FULL_NAME_TOO_LONG_ERROR(1300016, "tenant's fullname is too long error", "租户名过长"),
+    USER_PASSWORD_LENGTH_ERROR(1300017, "user's password length error", "用户密码长度错误"),
+    QUERY_CAN_USE_K8S_NAMESPACE_ERROR(
+            1300018, "login user query can used namespace list error", "查询可用命名空间错误"),
+    FILE_NAME_CONTAIN_RESTRICTIONS(
+            1300019, "The file name [{0}] contain restrictions", "文件命名[{0}]包含限制内容"),
+    FILE_TYPE_IS_RESTRICTIONS(1300020, "The file [{0}] type is restrictions", "文件[{0}]类型为限制类型"),
+
+    NO_CURRENT_OPERATING_PERMISSION(
+            1400001, "The current user does not have this permission.", "当前用户无此权限"),
+    FUNCTION_DISABLED(1400002, "The current feature is disabled.", "当前功能已被禁用"),
+    SCHEDULE_TIME_NUMBER(1400003, "The number of complement dates exceed 100.", "补数日期个数超过100"),
+    DESCRIPTION_TOO_LONG_ERROR(1400004, "description is too long error", "描述过长"),
+    COMPLEMENT_COMMAND_SCHEDULE_TIME_EMPTY(
+            1400005, "complement command schedule time can not be empty", "补数数据日期不可为空"),
+    START_TIME_CAN_NOT_AFTER_END_TIME(1400006, "start time can not after end time", "开始时间不可晚于结束时间"),
+    CONFIG_FILTER_EMPTY(
+            1400007,
+            "complement time is empty after filtering according to the configuration",
+            "当前补数时间根据配置过滤后为空"),
+    PROJECT_NAME_TOO_LONG_ERROR(1400008, "project name is too long error", "项目名称过长"),
+
+    NO_CURRENT_OPERATING_PERMISSION_FOR_RESOURCE(
+            1400009, "[{0}] is exist, current user no [{0}] permission", "[{0}]已存在,当前用户无[{0}]权限"),
+
+    ISOLATION_TASK_NOT_EXIST(1500000, "Isolation task not exist", "隔离任务不存在"),
+
+    ISOLATION_TASK_USER_NO_PERMISSION(
+            1500001,
+            "Current login user does not have isolation view permission",
+            "当前用户不具备当前项目隔离列表查看权限"),
+    ISOLATION_TASK_SUBMIT_ERROR(1500100, "Submit isolation task error", "提交隔离任务异常"),
+    ISOLATION_TASK_SUBMIT_ERROR_WORKFLOW_INSTANCE_NOT_SUPPORT(
+            1500101,
+            "Submit isolation task error, relate workflow instance [{0}] is not support",
+            "提交隔离任务异常, 关联的工作流实例:[{0}]暂不支持该操作"),
+    ISOLATION_TASK_SUBMIT_ERROR_TASK_NOT_EXIST(
+            1500103,
+            "Submit isolation task error, task: [{0}] is not exist",
+            "提交隔离任务异常, 任务不存在:[{0}]"),
+    ISOLATION_TASK_SUBMIT_ERROR_EXIST_SUB_ISOLATION_TASK(
+            1500104,
+            "Submit isolation task error, workflow instance: [{0}] exist an sub isolation task",
+            "提交隔离任务异常, 工作流实例已经存在:[{0}]子隔离任务"),
+    ISOLATION_TASK_SUBMIT_ERROR_SEND_REQUEST_TO_MASTER_ERROR(
+            1500105,
+            "Submit isolation task error, send request to master error",
+            "提交隔离任务异常,发送请求给Master异常"),
+
+    ISOLATION_TASK_SUBMIT_USER_NO_PERMISSION(
+            1500106,
+            "Current login user does not have isolation submit permission for project {0}",
+            "当前用户不具备{0}项目隔离的提交权限"),
+
+    ISOLATION_TASK_ONLINE_ERROR(1500200, "Online isolation task error", "上线隔离任务异常"),
+    ISOLATION_TASK_ONLINE_ERROR_ALREADY_ONLINE(
+            1500201,
+            "Online isolation task error, the isolation task is already online",
+            "上线隔离任务异常,该任务已处于隔离中"),
+    ISOLATION_TASK_ONLINE_ERROR_SEND_REQUEST_TO_MASTER_ERROR(
+            1500202,
+            "Online isolation task error, send request to master error",
+            "上线隔离任务异常,发送隔离请求给Master异常"),
+    ISOLATION_TASK_CANCEL_ERROR(1500300, "Cancel isolation task error", "取消隔离任务异常"),
+    ISOLATION_TASK_CANCEL_ERROR_SEND_REQUEST_TO_MASTER_ERROR(
+            1500301,
+            "Cancel isolation task error, send request to master error",
+            "取消隔离任务异常,发送隔离请求给Master异常"),
+    ISOLATION_TASK_CANCEL_ERROR_THE_ISOLATION_ALREADY_CANCEL(
+            1500302,
+            "Cancel isolation task error, this task isolation is already been cancel",
+            "取消隔离任务异常,该隔离已经下线"),
+    ISOLATION_TASK_CANCEL_USER_NO_PERMISSION(
+            1500304,
+            "Current login user does not have isolation cancel permission",
+            "当前用户不具备当前项目隔离取消权限"),
+    ISOLATION_TASK_LISTING_ERROR(1500400, "Listing isolation task error", "查询隔离任务列表异常"),
+    ISOLATION_TASK_DELETE_ERROR(1500500, "Delete isolation task error", "删除隔离任务异常"),
+    ISOLATION_TASK_DELETE_ERROR_IS_NOT_OFFLINE(
+            1500501,
+            "Delete isolation task error, the task status is not offline",
+            "删除隔离任务异常,该隔离任务尚未下线"),
+
+    CORONATION_TASK_PARSE_ERROR(1600000, "Coronation task parse error", "解析加冕任务异常"),
+    CORONATION_TASK_NOT_EXIST(1600001, "Coronation task not exist", "加冕任务不存在"),
+    CORONATION_TASK_PARSE_ERROR_TASK_NODE_NAME_IS_NOT_VALIDATED(
+            1600002,
+            "Coronation task parse error, taskNode name is not validated",
+            "解析加冕任务异常, 任务名不正确"),
+
+    CORONATION_TASK_PARSE_ERROR_TASK_NODE_ALREADY_EXIST(
+            1600003,
+            "Coronation task parse error, workflowInstance: [{0}] taskNode:[{1}] is already in coronation",
+            "解析加冕任务异常, 工作流实例: [{0}] 任务: [{1}] 已经被加冕"),
+
+    CORONATION_TASK_USER_NO_PERMISSION(
+            1600004,
+            "Current login user does not have coronation view permission",
+            "当前用户不具备当前项目加冕列表查看权限"),
+
+    CORONATION_TASK_SUBMIT_ERROR(1600100, "Coronation task submit error", "提交加冕任务异常"),
+    CORONATION_TASK_SUBMIT_USER_NO_PERMISSION(
+            1600101,
+            "Current login user does not have coronation submit permission",
+            "当前用户不具备当前项目加冕提交权限"),
+    CORONATION_TASK_ONLINE_ERROR(1600200, "Coronation task online error", "上线加冕任务异常"),
+    CORONATION_TASK_CANCEL_ERROR(1600300, "Coronation task cancel error", "取消加冕任务异常"),
+    CORONATION_TASK_CANCEL_USER_NO_PERMISSION(
+            1500301,
+            "Current login user does not have coronation cancel permission",
+            "当前用户不具备当前项目加冕取消权限"),
+    CORONATION_TASK_LISTING_ERROR(1600400, "Coronation task listing error", "查询加冕任务异常"),
+
+    OPERATION_ALREADY_EXIST(1800000, "operation already exist", "操作已存在"),
+
+    DATA_SOURCE_HAD_USED(
+            1600000,
+            "data source already used (projectName - workflowName - taskName):{0}",
+            "数据源正在被使用(项目名 - 工作流名 - 任务名):{0}"),
+
+    COMPLEMENT_CALENDAR_ERROR(1700000, "complement calendar error", "补数日历错误"),
+
+    COMPLEMENT_MISSING_CALENDAR_PARAM(
+            1700001, "complement missing calendar param [{0}]", "补数缺少日历参数 [{0}]"),
+
+    COMPLEMENT_QUERY_DATE_LIST_ERROR(1700002, "complement query date list error", "补数查询日期列表错误"),
+    ;
+
+    private final int code;
+    private final String enMsg;
+    private final String zhMsg;
+
+    Status(int code, String enMsg, String zhMsg) {
+        this.code = code;
+        this.enMsg = enMsg;
+        this.zhMsg = zhMsg;
+    }
+
+    public int getCode() {
+        return this.code;
+    }
+
+    public String getMsg() {
+        if (Locale.SIMPLIFIED_CHINESE
+                .getLanguage()
+                .equals(LocaleContextHolder.getLocale().getLanguage())) {
+            return this.zhMsg;
+        } else {
+            return this.enMsg;
+        }
+    }
+
+    /** Retrieve Status enum entity by status code. */
+    public static Optional<Status> findStatusBy(int code) {
+        for (Status status : Status.values()) {
+            if (code == status.getCode()) {
+                return Optional.of(status);
+            }
+        }
+        return Optional.empty();
+    }
+}
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/DataSourceClientFactory.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/common/TaskTimeoutStrategy.java
similarity index 50%
copy from seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/DataSourceClientFactory.java
copy to seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/common/TaskTimeoutStrategy.java
index 4647e6eb..f304a420 100644
--- a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/DataSourceClientFactory.java
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/common/TaskTimeoutStrategy.java
@@ -15,25 +15,40 @@
  * limitations under the License.
  */
 
-package org.apache.seatunnel.app.thridparty.datasource;
+package org.apache.seatunnel.app.common;
 
-import org.apache.seatunnel.datasource.DataSourceClient;
+import com.baomidou.mybatisplus.annotation.EnumValue;
 
-public class DataSourceClientFactory {
-    private static DataSourceClient INSTANCE;
+/** task timeout strategy */
+public enum TaskTimeoutStrategy {
 
-    private static final Object LOCK = new Object();
+    /** 0 warn 1 failed 2 warn+failed */
+    WARN(0, "warn"),
+    FAILED(1, "failed"),
+    WARNFAILED(2, "warnfailed");
 
-    public static DataSourceClient getDataSourceClient() {
-        if (null != INSTANCE) {
-            return INSTANCE;
-        }
-        synchronized (LOCK) {
-            if (null != INSTANCE) {
-                return INSTANCE;
+    TaskTimeoutStrategy(int code, String descp) {
+        this.code = code;
+        this.descp = descp;
+    }
+
+    @EnumValue private final int code;
+    private final String descp;
+
+    public int getCode() {
+        return code;
+    }
+
+    public String getDescp() {
+        return descp;
+    }
+
+    public static TaskTimeoutStrategy of(int status) {
+        for (TaskTimeoutStrategy es : values()) {
+            if (es.getCode() == status) {
+                return es;
             }
-            INSTANCE = new DataSourceClient();
-            return INSTANCE;
         }
+        throw new IllegalArgumentException("invalid status : " + status);
     }
 }
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/framework/UnSupportWrapperException.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/common/TimeoutFlag.java
similarity index 62%
copy from seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/framework/UnSupportWrapperException.java
copy to seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/common/TimeoutFlag.java
index 8db5be03..5c0e10f9 100644
--- a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/framework/UnSupportWrapperException.java
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/common/TimeoutFlag.java
@@ -15,16 +15,30 @@
  * limitations under the License.
  */
 
-package org.apache.seatunnel.app.thridparty.framework;
+package org.apache.seatunnel.app.common;
 
-import lombok.NonNull;
+import com.baomidou.mybatisplus.annotation.EnumValue;
 
-public class UnSupportWrapperException extends RuntimeException {
-    public UnSupportWrapperException(
-            @NonNull String formName, @NonNull String label, @NonNull String typeName) {
-        super(
-                String.format(
-                        "Form: %s, label: %s, typeName: %s not yet supported",
-                        formName, label, typeName));
+/** timeout flag */
+public enum TimeoutFlag {
+
+    /** 0 close 1 open */
+    CLOSE(0, "close"),
+    OPEN(1, "open");
+
+    TimeoutFlag(int code, String desc) {
+        this.code = code;
+        this.desc = desc;
+    }
+
+    @EnumValue private final int code;
+    private final String desc;
+
+    public int getCode() {
+        return code;
+    }
+
+    public String getDesc() {
+        return desc;
     }
 }
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/DataSourceClientFactory.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/common/UdfType.java
similarity index 54%
copy from seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/DataSourceClientFactory.java
copy to seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/common/UdfType.java
index 4647e6eb..29cd9daa 100644
--- a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/DataSourceClientFactory.java
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/common/UdfType.java
@@ -15,25 +15,39 @@
  * limitations under the License.
  */
 
-package org.apache.seatunnel.app.thridparty.datasource;
+package org.apache.seatunnel.app.common;
 
-import org.apache.seatunnel.datasource.DataSourceClient;
+import com.baomidou.mybatisplus.annotation.EnumValue;
 
-public class DataSourceClientFactory {
-    private static DataSourceClient INSTANCE;
+/** UDF type */
+public enum UdfType {
 
-    private static final Object LOCK = new Object();
+    /** 0 hive; 1 spark */
+    HIVE(0, "hive"),
+    SPARK(1, "spark");
 
-    public static DataSourceClient getDataSourceClient() {
-        if (null != INSTANCE) {
-            return INSTANCE;
-        }
-        synchronized (LOCK) {
-            if (null != INSTANCE) {
-                return INSTANCE;
+    UdfType(int code, String descp) {
+        this.code = code;
+        this.descp = descp;
+    }
+
+    @EnumValue private final int code;
+    private final String descp;
+
+    public int getCode() {
+        return code;
+    }
+
+    public String getDescp() {
+        return descp;
+    }
+
+    public static UdfType of(int type) {
+        for (UdfType ut : values()) {
+            if (ut.getCode() == type) {
+                return ut;
             }
-            INSTANCE = new DataSourceClient();
-            return INSTANCE;
         }
+        throw new IllegalArgumentException("invalid type : " + type);
     }
 }
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/config/ConnectorDataSourceMapperConfig.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/config/ConnectorDataSourceMapperConfig.java
new file mode 100644
index 00000000..fe9c5ca6
--- /dev/null
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/config/ConnectorDataSourceMapperConfig.java
@@ -0,0 +1,138 @@
+/*
+ * 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.seatunnel.app.config;
+
+import org.apache.seatunnel.app.domain.request.connector.BusinessMode;
+import org.apache.seatunnel.app.domain.request.connector.SceneMode;
+import org.apache.seatunnel.app.domain.response.connector.ConnectorInfo;
+import org.apache.seatunnel.app.domain.response.connector.DataSourceInfo;
+import org.apache.seatunnel.common.constants.PluginType;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.PropertySource;
+
+import lombok.Data;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
+@Data
+@Configuration
+@PropertySource(
+        value = "classpath:connector-datasource-mapper.yaml",
+        factory = YamlSourceFactory.class)
+@ConfigurationProperties(prefix = "connector-datasource-mapper")
+public class ConnectorDataSourceMapperConfig {
+    private Map<String, ConnectorMapper> connectorDatasourceMappers;
+    private Map<String, DatasourceFeatures> sourceDatasourceFeatures;
+    private Map<String, DatasourceFeatures> sinkDatasourceFeatures;
+
+    @Data
+    public static class ConnectorMapper {
+        private List<String> dataSources;
+    }
+
+    @Data
+    public static class DatasourceFeatures {
+        private List<String> businessMode;
+        private List<String> sceneMode;
+    }
+
+    public Optional<List<BusinessMode>> supportedBusinessMode(
+            String datasourceName, PluginType pluginType) {
+        if (pluginType.equals(PluginType.SOURCE)) {
+            return Optional.ofNullable(sourceDatasourceFeatures.get(datasourceName))
+                    .map(
+                            cm ->
+                                    cm.getBusinessMode().stream()
+                                            .map(BusinessMode::valueOf)
+                                            .collect(Collectors.toList()));
+        }
+        if (pluginType.equals(PluginType.SINK)) {
+            return Optional.ofNullable(sinkDatasourceFeatures.get(datasourceName))
+                    .map(
+                            cm ->
+                                    cm.getBusinessMode().stream()
+                                            .map(BusinessMode::valueOf)
+                                            .collect(Collectors.toList()));
+        }
+        throw new UnsupportedOperationException(
+                "pluginType : " + pluginType + " not support BusinessMode");
+    }
+
+    public Optional<List<SceneMode>> supportedSceneMode(
+            String datasourceName, PluginType pluginType) {
+        if (pluginType.equals(PluginType.SOURCE)) {
+            return Optional.ofNullable(sourceDatasourceFeatures.get(datasourceName))
+                    .map(
+                            cm ->
+                                    cm.getSceneMode().stream()
+                                            .map(SceneMode::valueOf)
+                                            .collect(Collectors.toList()));
+        }
+        if (pluginType.equals(PluginType.SINK)) {
+            return Optional.ofNullable(sinkDatasourceFeatures.get(datasourceName))
+                    .map(
+                            cm ->
+                                    cm.getSceneMode().stream()
+                                            .map(SceneMode::valueOf)
+                                            .collect(Collectors.toList()));
+        }
+        throw new UnsupportedOperationException(
+                "pluginType : " + pluginType + " not support SceneMode");
+    }
+
+    public Optional<String> findConnectorForDatasourceName(String datasourceName) {
+        return connectorDatasourceMappers.entrySet().stream()
+                .map(
+                        en -> {
+                            return en.getValue().getDataSources().stream()
+                                            .anyMatch(n -> n.equalsIgnoreCase(datasourceName))
+                                    ? en.getKey()
+                                    : null;
+                        })
+                .filter(Objects::nonNull)
+                .findFirst();
+    }
+
+    public List<DataSourceInfo> findDatasourceNameForConnectors(List<ConnectorInfo> connectors) {
+
+        Map<String, ConnectorInfo> connectorMap =
+                connectors.stream()
+                        .collect(
+                                Collectors.toMap(
+                                        connectorInfo ->
+                                                connectorInfo.getPluginIdentifier().getPluginName(),
+                                        connectorInfo -> connectorInfo));
+
+        return connectorDatasourceMappers.entrySet().stream()
+                .filter(en -> connectorMap.containsKey(en.getKey()))
+                .flatMap(
+                        en ->
+                                en.getValue().getDataSources().stream()
+                                        .map(
+                                                name ->
+                                                        new DataSourceInfo(
+                                                                connectorMap.get(en.getKey()),
+                                                                name)))
+                .collect(Collectors.toList());
+    }
+}
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/config/YamlSourceFactory.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/config/YamlSourceFactory.java
new file mode 100644
index 00000000..f84b4060
--- /dev/null
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/config/YamlSourceFactory.java
@@ -0,0 +1,50 @@
+/*
+ * 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.seatunnel.app.config;
+
+import org.springframework.boot.env.YamlPropertySourceLoader;
+import org.springframework.core.env.PropertiesPropertySource;
+import org.springframework.core.env.PropertySource;
+import org.springframework.core.io.Resource;
+import org.springframework.core.io.support.DefaultPropertySourceFactory;
+import org.springframework.core.io.support.EncodedResource;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Properties;
+
+public class YamlSourceFactory extends DefaultPropertySourceFactory {
+    @Override
+    public PropertySource<?> createPropertySource(String name, EncodedResource resource)
+            throws IOException {
+        if (resource == null) {
+            return super.createPropertySource(name, resource);
+        }
+        Resource resourceResource = resource.getResource();
+        if (!resourceResource.exists()) {
+            return new PropertiesPropertySource(null, new Properties());
+        } else if (resourceResource.getFilename().endsWith(".yml")
+                || resourceResource.getFilename().endsWith(".yaml")) {
+            List<PropertySource<?>> sources =
+                    new YamlPropertySourceLoader()
+                            .load(resourceResource.getFilename(), resourceResource);
+            return sources.get(0);
+        }
+        return super.createPropertySource(name, resource);
+    }
+}
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/controller/BaseController.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/controller/BaseController.java
new file mode 100644
index 00000000..c72713db
--- /dev/null
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/controller/BaseController.java
@@ -0,0 +1,255 @@
+/*
+ * 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.seatunnel.app.controller;
+
+import org.apache.seatunnel.app.common.Constants;
+import org.apache.seatunnel.app.common.Result;
+import org.apache.seatunnel.app.common.Status;
+
+import org.apache.commons.lang3.StringUtils;
+
+import javax.servlet.http.HttpServletRequest;
+
+import java.text.MessageFormat;
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.apache.seatunnel.app.common.Constants.COMMA;
+import static org.apache.seatunnel.app.common.Constants.HTTP_HEADER_UNKNOWN;
+import static org.apache.seatunnel.app.common.Constants.HTTP_X_FORWARDED_FOR;
+import static org.apache.seatunnel.app.common.Constants.HTTP_X_REAL_IP;
+
+public abstract class BaseController {
+
+    /**
+     * check params
+     *
+     * @param pageNo page number
+     * @param pageSize page size
+     * @return check result code
+     */
+    public <T> Result<T> checkPageParams(int pageNo, int pageSize) {
+        Result<T> result = Result.success();
+        Status resultEnum = Status.SUCCESS;
+        String msg = Status.SUCCESS.getMsg();
+        if (pageNo <= 0) {
+            resultEnum = Status.REQUEST_PARAMS_NOT_VALID_ERROR;
+            msg =
+                    MessageFormat.format(
+                            Status.REQUEST_PARAMS_NOT_VALID_ERROR.getMsg(), Constants.PAGE_NUMBER);
+        } else if (pageSize <= 0) {
+            resultEnum = Status.REQUEST_PARAMS_NOT_VALID_ERROR;
+            msg =
+                    MessageFormat.format(
+                            Status.REQUEST_PARAMS_NOT_VALID_ERROR.getMsg(), Constants.PAGE_SIZE);
+        }
+        result.setCode(resultEnum.getCode());
+        result.setMsg(msg);
+        return result;
+    }
+
+    /**
+     * get ip address in the http request
+     *
+     * @param request http servlet request
+     * @return client ip address
+     */
+    public static String getClientIpAddress(HttpServletRequest request) {
+        String clientIp = request.getHeader(HTTP_X_FORWARDED_FOR);
+
+        if (StringUtils.isNotEmpty(clientIp) && !clientIp.equalsIgnoreCase(HTTP_HEADER_UNKNOWN)) {
+            int index = clientIp.indexOf(COMMA);
+            if (index != -1) {
+                return clientIp.substring(0, index);
+            } else {
+                return clientIp;
+            }
+        }
+
+        clientIp = request.getHeader(HTTP_X_REAL_IP);
+        if (StringUtils.isNotEmpty(clientIp) && !clientIp.equalsIgnoreCase(HTTP_HEADER_UNKNOWN)) {
+            return clientIp;
+        }
+
+        return request.getRemoteAddr();
+    }
+
+    /**
+     * return data list
+     *
+     * @param result result code
+     * @return result code
+     */
+    public <T> Result<T> returnDataList(Map<String, Object> result) {
+        Status status = (Status) result.get(Constants.STATUS);
+        if (status == Status.SUCCESS) {
+            String msg = Status.SUCCESS.getMsg();
+            Object datalist = result.get(Constants.DATA_LIST);
+            return success(msg, datalist);
+        } else {
+            Integer code = status.getCode();
+            String msg = (String) result.get(Constants.MSG);
+            return error(code, msg);
+        }
+    }
+
+    /**
+     * success
+     *
+     * @return success result code
+     */
+    public Result success() {
+        Result result = Result.success();
+        result.setCode(Status.SUCCESS.getCode());
+        result.setMsg(Status.SUCCESS.getMsg());
+
+        return result;
+    }
+
+    /**
+     * success does not need to return data
+     *
+     * @param msg success message
+     * @return success result code
+     */
+    public Result success(String msg) {
+        Result result = Result.success();
+        result.setCode(Status.SUCCESS.getCode());
+        result.setMsg(msg);
+
+        return result;
+    }
+
+    /**
+     * return data no paging
+     *
+     * @param msg success message
+     * @param list data list
+     * @return success result code
+     */
+    public <T> Result<T> success(String msg, Object list) {
+        return getResult(msg, list);
+    }
+
+    /**
+     * return data no paging
+     *
+     * @param list success
+     * @return success result code
+     */
+    public Result success(Object list) {
+        return getResult(Status.SUCCESS.getMsg(), list);
+    }
+
+    /**
+     * return the data use Map format, for example, passing the value of key, value, passing a value
+     * eg. "/user/add" then return user name: zhangsan
+     *
+     * @param msg message
+     * @param object success object data
+     * @return success result code
+     */
+    public Result success(String msg, Map<String, Object> object) {
+        return getResult(msg, object);
+    }
+
+    /**
+     * return data with paging
+     *
+     * @param totalList success object list
+     * @param currentPage current page
+     * @param total total
+     * @param totalPage total page
+     * @return success result code
+     */
+    public Result success(Object totalList, Integer currentPage, Integer total, Integer totalPage) {
+        Result result = Result.success();
+        result.setCode(Status.SUCCESS.getCode());
+        result.setMsg(Status.SUCCESS.getMsg());
+
+        Map<String, Object> map = new HashMap<>(8);
+        map.put(Constants.TOTAL_LIST, totalList);
+        map.put(Constants.CURRENT_PAGE, currentPage);
+        map.put(Constants.TOTAL_PAGE, totalPage);
+        map.put(Constants.TOTAL, total);
+        result.setData(map);
+        return result;
+    }
+
+    /**
+     * error handle
+     *
+     * @param code result code
+     * @param msg result message
+     * @return error result code
+     */
+    public <T> Result<T> error(Integer code, String msg) {
+        Result<T> result = Result.success();
+        result.setCode(code);
+        result.setMsg(msg);
+        return result;
+    }
+
+    /**
+     * put message to map
+     *
+     * @param result result
+     * @param status status
+     * @param statusParams object messages
+     */
+    protected void putMsg(Map<String, Object> result, Status status, Object... statusParams) {
+        result.put(Constants.STATUS, status);
+        if (statusParams != null && statusParams.length > 0) {
+            result.put(Constants.MSG, MessageFormat.format(status.getMsg(), statusParams));
+        } else {
+            result.put(Constants.MSG, status.getMsg());
+        }
+    }
+
+    /**
+     * put message to result object
+     *
+     * @param result result
+     * @param status status
+     * @param statusParams status parameters
+     */
+    protected void putMsg(Result result, Status status, Object... statusParams) {
+        result.setCode(status.getCode());
+
+        if (statusParams != null && statusParams.length > 0) {
+            result.setMsg(MessageFormat.format(status.getMsg(), statusParams));
+        } else {
+            result.setMsg(status.getMsg());
+        }
+    }
+
+    /**
+     * get result
+     *
+     * @param msg message
+     * @param list object list
+     * @return result code
+     */
+    private Result getResult(String msg, Object list) {
+        Result result = Result.success();
+        result.setCode(Status.SUCCESS.getCode());
+        result.setMsg(msg);
+        result.setData(list);
+        return result;
+    }
+}
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/controller/ConnectorDataSourceController.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/controller/ConnectorDataSourceController.java
new file mode 100644
index 00000000..b59352cd
--- /dev/null
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/controller/ConnectorDataSourceController.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.seatunnel.app.controller;
+
+import org.apache.seatunnel.app.common.Result;
+import org.apache.seatunnel.app.domain.request.connector.ConnectorStatus;
+import org.apache.seatunnel.app.domain.request.connector.SceneMode;
+import org.apache.seatunnel.app.domain.response.connector.ConnectorInfo;
+import org.apache.seatunnel.app.domain.response.connector.DataSourceInstance;
+import org.apache.seatunnel.app.service.IConnectorService;
+import org.apache.seatunnel.common.constants.PluginType;
+import org.apache.seatunnel.common.utils.JsonUtils;
+
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiParam;
+
+import javax.annotation.Resource;
+
+import java.io.IOException;
+import java.util.List;
+
+@RequestMapping("/seatunnel/api/v1/datasource")
+@RestController
+public class ConnectorDataSourceController {
+
+    @Resource private IConnectorService connectorService;
+
+    @GetMapping("/sources")
+    @ApiOperation(value = "Use jobID to list source DataSourceInstance", httpMethod = "GET")
+    public Result<List<DataSourceInstance>> listSource(
+            @ApiParam(value = "jobCode", required = true) @RequestParam Long jobId,
+            @ApiParam(value = "SceneMode", required = true) @RequestParam SceneMode sceneMode,
+            @ApiParam(value = "ConnectorStatus", required = true) @RequestParam
+                    ConnectorStatus status) {
+        return Result.success(
+                connectorService.listSourceDataSourceInstances(jobId, sceneMode, status));
+    }
+
+    @GetMapping("/sinks")
+    @ApiOperation(value = "Use jobID to list sink DataSourceInstance", httpMethod = "GET")
+    public Result<List<DataSourceInstance>> listSink(
+            @ApiParam(value = "jobCode", required = true) @RequestParam Long jobId,
+            @ApiParam(value = "ConnectorStatus", required = true) @RequestParam
+                    ConnectorStatus status) {
+        return Result.success(connectorService.listSinkDataSourcesInstances(jobId, status));
+    }
+
+    @GetMapping("/transforms")
+    @ApiOperation(value = "Use jobID to list  transforms", httpMethod = "GET")
+    public Result<List<ConnectorInfo>> listAllTransform(
+            @ApiParam(value = "jobCode", required = true) @RequestParam Long jobId) {
+        return Result.success(connectorService.listTransformsForJob(jobId));
+    }
+
+    @GetMapping("/sync")
+    @ApiOperation(value = "sync all connector from disk", httpMethod = "GET")
+    public Result<List<ConnectorInfo>> sync() throws IOException {
+        connectorService.sync();
+        return Result.success();
+    }
+
+    @GetMapping("/form")
+    @ApiOperation(value = "get datasource instance form structure", httpMethod = "GET")
+    public Result<String> getDatasourceInstanceFormStructure(
+            @ApiParam(value = "jobCode", required = false)
+                    @RequestParam(required = false, value = "jobCode")
+                    Long jobId,
+            @ApiParam(value = "connector type", required = true)
+                    @RequestParam(required = true, value = "connectorType")
+                    String connectorType,
+            @ApiParam(value = "connector name", required = false)
+                    @RequestParam(required = false, value = "connectorName")
+                    String connectorName,
+            @ApiParam(value = "dataSource instanceId", required = false)
+                    @RequestParam(required = false, value = "dataSourceInstanceId")
+                    Long dataSourceInstanceId) {
+        if (PluginType.TRANSFORM.getType().equals(connectorType)) {
+            return Result.success(
+                    JsonUtils.toJsonString(
+                            connectorService.getTransformFormStructure(
+                                    connectorType, connectorName)));
+        }
+        return Result.success(
+                JsonUtils.toJsonString(
+                        connectorService.getDatasourceFormStructure(
+                                jobId, dataSourceInstanceId, connectorType)));
+    }
+}
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/controller/SeatunnelDatasourceController.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/controller/SeatunnelDatasourceController.java
new file mode 100644
index 00000000..9729c593
--- /dev/null
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/controller/SeatunnelDatasourceController.java
@@ -0,0 +1,425 @@
+/*
+ * 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.seatunnel.app.controller;
+
+import org.apache.seatunnel.app.common.Constants;
+import org.apache.seatunnel.app.common.Result;
+import org.apache.seatunnel.app.dal.dao.IUserDao;
+import org.apache.seatunnel.app.dal.dao.TaskDefinitionDao;
+import org.apache.seatunnel.app.dal.entity.TaskMainInfo;
+import org.apache.seatunnel.app.dal.entity.User;
+import org.apache.seatunnel.app.domain.dto.datasource.DatabaseTableFields;
+import org.apache.seatunnel.app.domain.dto.datasource.DatabaseTables;
+import org.apache.seatunnel.app.domain.dto.datasource.TableInfo;
+import org.apache.seatunnel.app.domain.response.PageInfo;
+import org.apache.seatunnel.app.domain.response.datasource.DatasourceDetailRes;
+import org.apache.seatunnel.app.domain.response.datasource.DatasourceRes;
+import org.apache.seatunnel.app.service.IDatasourceService;
+import org.apache.seatunnel.app.utils.CartesianProductUtils;
+import org.apache.seatunnel.app.utils.JSONUtils;
+import org.apache.seatunnel.app.utils.PropertyUtils;
+import org.apache.seatunnel.datasource.plugin.api.DataSourcePluginInfo;
+import org.apache.seatunnel.datasource.plugin.api.model.TableField;
+import org.apache.seatunnel.server.common.SeatunnelErrorEnum;
+import org.apache.seatunnel.server.common.SeatunnelException;
+
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.collections4.MapUtils;
+import org.apache.commons.lang3.StringUtils;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.RequestAttribute;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import io.swagger.annotations.ApiImplicitParam;
+import io.swagger.annotations.ApiImplicitParams;
+import io.swagger.annotations.ApiOperation;
+import springfox.documentation.annotations.ApiIgnore;
+
+import javax.annotation.Resource;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
+import static org.apache.seatunnel.app.common.Constants.SESSION_USER;
+
+@RestController
+@RequestMapping("/seatunnel/api/v1/datasource")
+public class SeatunnelDatasourceController extends BaseController {
+
+    @Autowired private IDatasourceService datasourceService;
+
+    @Autowired private TaskDefinitionDao taskDefinitionDao;
+
+    @Resource(name = "userDaoImpl")
+    private IUserDao userMapper;
+
+    private static final String DEFAULT_PLUGIN_VERSION = "1.0.0";
+    private static final String WS_SOURCE = "WS";
+
+    private static final List<String> wsSupportDatasources =
+            PropertyUtils.getList(Constants.WS_SUPPORT_DATASOURCES, Constants.COMMA);
+
+    @ApiOperation(value = "create datasource", notes = "create datasource")
+    @ApiImplicitParams({
+        @ApiImplicitParam(
+                name = "datasourceName",
+                value = "datasource name",
+                required = true,
+                dataType = "String",
+                paramType = "query"),
+        @ApiImplicitParam(
+                name = "pluginName",
+                value = "plugin name",
+                required = true,
+                dataType = "String",
+                paramType = "query"),
+        @ApiImplicitParam(
+                name = "description",
+                value = "description",
+                required = false,
+                dataType = "String",
+                paramType = "query"),
+        @ApiImplicitParam(
+                name = "datasourceConfig",
+                value = "datasource config",
+                required = true,
+                dataType = "String",
+                paramType = "query")
+    })
+    @PostMapping("/create")
+    Result<String> createDatasource(
+            @ApiIgnore @RequestAttribute(value = SESSION_USER) User loginUser,
+            @RequestParam("datasourceName") String datasourceName,
+            @RequestParam("pluginName") String pluginName,
+            @RequestParam("description") String description,
+            @RequestParam("datasourceConfig") String datasourceConfig) {
+        Map<String, String> stringStringMap = JSONUtils.toMap(datasourceConfig);
+        return Result.success(
+                datasourceService.createDatasource(
+                        loginUser.getId(),
+                        datasourceName,
+                        pluginName,
+                        DEFAULT_PLUGIN_VERSION,
+                        description,
+                        stringStringMap));
+    }
+
+    @ApiOperation(value = "test datasource connection", notes = "test datasource connection")
+    @ApiImplicitParams({
+        @ApiImplicitParam(
+                name = "pluginName",
+                value = "plugin name",
+                required = true,
+                dataType = "String",
+                paramType = "query"),
+        @ApiImplicitParam(
+                name = "datasourceConfig",
+                value = "datasource config",
+                required = true,
+                dataType = "String",
+                paramType = "query")
+    })
+    @PostMapping("/check/connect")
+    Result<Boolean> testConnect(
+            @ApiIgnore @RequestAttribute(value = SESSION_USER) User loginUser,
+            @RequestParam("pluginName") String pluginName,
+            @RequestParam("datasourceConfig") String datasourceConfig) {
+        Map<String, String> stringStringMap = JSONUtils.toMap(datasourceConfig);
+        return Result.success(
+                datasourceService.testDatasourceConnectionAble(
+                        loginUser.getId(), pluginName, DEFAULT_PLUGIN_VERSION, stringStringMap));
+    }
+
+    @ApiOperation(value = "update datasource", notes = "update datasource")
+    @ApiImplicitParams({
+        @ApiImplicitParam(
+                name = "datasourceName",
+                value = "datasource name",
+                required = false,
+                dataType = "String",
+                paramType = "query"),
+        @ApiImplicitParam(
+                name = "description",
+                value = "description",
+                required = false,
+                dataType = "String",
+                paramType = "query"),
+        @ApiImplicitParam(
+                name = "datasourceConfig",
+                value = "datasource config",
+                required = false,
+                dataType = "String",
+                paramType = "query")
+    })
+    @PutMapping("/{id}")
+    Result<Boolean> updateDatasource(
+            @ApiIgnore @RequestAttribute(value = SESSION_USER) User loginUser,
+            @PathVariable("id") String id,
+            @RequestParam("datasourceName") String datasourceName,
+            @RequestParam("description") String description,
+            @RequestParam("datasourceConfig") String datasourceConfig) {
+        Map<String, String> stringStringMap = JSONUtils.toMap(datasourceConfig);
+        Long datasourceId = Long.parseLong(id);
+        return Result.success(
+                datasourceService.updateDatasource(
+                        loginUser.getId(),
+                        datasourceId,
+                        datasourceName,
+                        description,
+                        stringStringMap));
+    }
+
+    @ApiOperation(value = "delete datasource by id", notes = "delete datasource by id")
+    @DeleteMapping("/{id}")
+    Result<Boolean> deleteDatasource(
+            @ApiIgnore @RequestAttribute(value = SESSION_USER) User loginUser,
+            @PathVariable("id") String id) {
+        Long datasourceId = Long.parseLong(id);
+        List<TaskMainInfo> taskMainInfos = taskDefinitionDao.queryByDataSourceId(datasourceId);
+        if (taskMainInfos.size() > 0) {
+            throw new SeatunnelException(
+                    SeatunnelErrorEnum.DATA_SOURCE_HAD_USED,
+                    taskMainInfos.stream()
+                            .map(
+                                    info ->
+                                            String.format(
+                                                    "%s - %s",
+                                                    info.getProcessDefinitionName(),
+                                                    info.getTaskName()))
+                            .collect(Collectors.toList()));
+        }
+        return Result.success(datasourceService.deleteDatasource(loginUser.getId(), datasourceId));
+    }
+
+    @ApiOperation(value = "get datasource detail", notes = "get datasource detail")
+    @ApiImplicitParams({
+        @ApiImplicitParam(
+                name = "userId",
+                value = "user id",
+                required = true,
+                dataType = "String",
+                paramType = "query"),
+    })
+    @GetMapping("/{id}")
+    Result<DatasourceDetailRes> getDatasource(
+            @ApiIgnore @RequestAttribute(value = SESSION_USER) User loginUser,
+            @PathVariable("id") String id) {
+        return Result.success(datasourceService.queryDatasourceDetailById(loginUser.getId(), id));
+    }
+
+    @ApiOperation(value = "get datasource list", notes = "get datasource list")
+    @ApiImplicitParams({
+        @ApiImplicitParam(
+                name = "searchVal",
+                value = "search value",
+                required = false,
+                dataType = "String",
+                paramType = "query"),
+        @ApiImplicitParam(
+                name = "pluginName",
+                value = "plugin name",
+                required = false,
+                dataType = "String",
+                paramType = "query"),
+        @ApiImplicitParam(
+                name = "pageNo",
+                value = "page no",
+                required = false,
+                dataType = "Integer",
+                paramType = "query"),
+        @ApiImplicitParam(
+                name = "pageSize",
+                value = "page size",
+                required = false,
+                dataType = "Integer",
+                paramType = "query")
+    })
+    @GetMapping("/list")
+    Result<PageInfo<DatasourceRes>> getDatasourceList(
+            @ApiIgnore @RequestAttribute(value = SESSION_USER) User loginUser,
+            @RequestParam("searchVal") String searchVal,
+            @RequestParam("pluginName") String pluginName,
+            @RequestParam("pageNo") Integer pageNo,
+            @RequestParam("pageSize") Integer pageSize) {
+        PageInfo<DatasourceRes> datasourceResPageInfo =
+                datasourceService.queryDatasourceList(
+                        loginUser.getId(), searchVal, pluginName, pageNo, pageSize);
+        if (CollectionUtils.isNotEmpty(datasourceResPageInfo.getData())) {
+            Map<Integer, String> userIdNameMap = userIdNameMap();
+            datasourceResPageInfo
+                    .getData()
+                    .forEach(
+                            datasourceRes -> {
+                                Map<String, String> datasourceConfig =
+                                        datasourceRes.getDatasourceConfig();
+                                Optional.ofNullable(
+                                                MapUtils.getString(
+                                                        datasourceConfig, Constants.PASSWORD))
+                                        .ifPresent(
+                                                password -> {
+                                                    datasourceConfig.put(
+                                                            Constants.PASSWORD,
+                                                            CartesianProductUtils.maskPassword(
+                                                                    password));
+                                                });
+                                datasourceRes.setDatasourceConfig(datasourceConfig);
+                                datasourceRes.setCreateUserName(
+                                        userIdNameMap.getOrDefault(
+                                                datasourceRes.getCreateUserId(), ""));
+                                datasourceRes.setUpdateUserName(
+                                        userIdNameMap.getOrDefault(
+                                                datasourceRes.getUpdateUserId(), ""));
+                            });
+        }
+        return Result.success(datasourceResPageInfo);
+    }
+
+    @ApiOperation(value = "get datasource type list", notes = "get datasource type list")
+    @ApiImplicitParams({
+        @ApiImplicitParam(
+                name = "showVirtualDataSource",
+                value = "show virtual datasource",
+                required = false,
+                defaultValue = "true",
+                dataType = "Boolean",
+                paramType = "query")
+    })
+    @GetMapping("/support-datasources")
+    Result<Map<Integer, List<DataSourcePluginInfo>>> getSupportDatasources(
+            @ApiIgnore @RequestAttribute(value = SESSION_USER) User loginUser,
+            @RequestParam("showVirtualDataSource") Boolean showVirtualDataSource,
+            @RequestParam(value = "source", required = false) String source) {
+        Map<Integer, List<DataSourcePluginInfo>> allDatasources =
+                datasourceService.queryAllDatasourcesGroupByType(showVirtualDataSource);
+        // default source is WS
+        if (StringUtils.isEmpty(source) || source.equals(WS_SOURCE)) {
+            allDatasources.forEach(
+                    (k, typeList) -> {
+                        typeList =
+                                typeList.stream()
+                                        .filter(
+                                                plugin ->
+                                                        wsSupportDatasources.contains(
+                                                                plugin.getName()))
+                                        .collect(Collectors.toList());
+                        allDatasources.put(k, typeList);
+                    });
+        }
+        return Result.success(allDatasources);
+    }
+
+    @GetMapping("/dynamic-form")
+    Result<String> getDynamicForm(
+            @ApiIgnore @RequestAttribute(value = SESSION_USER) User loginUser,
+            @RequestParam("pluginName") String pluginName) {
+        return Result.success(datasourceService.getDynamicForm(pluginName));
+    }
+
+    @GetMapping("/databases")
+    Result<List<String>> getDatabases(
+            @ApiIgnore @RequestAttribute(value = SESSION_USER) User loginUser,
+            @RequestParam("datasourceName") String datasourceName) {
+        return Result.success(datasourceService.queryDatabaseByDatasourceName(datasourceName));
+    }
+
+    @GetMapping("/tables")
+    Result<List<String>> getTableNames(
+            @ApiIgnore @RequestAttribute(value = SESSION_USER) User loginUser,
+            @RequestParam("datasourceName") String datasourceName,
+            @RequestParam("databaseName") String databaseName) {
+        return Result.success(datasourceService.queryTableNames(datasourceName, databaseName));
+    }
+
+    @GetMapping("/schema")
+    Result<List<TableField>> getTableFields(
+            @ApiIgnore @RequestAttribute(value = SESSION_USER) User loginUser,
+            @RequestParam("datasourceId") String datasourceId,
+            @RequestParam(value = "databaseName", required = false) String databaseName,
+            @RequestParam("tableName") String tableName) {
+        DatasourceDetailRes res = datasourceService.queryDatasourceDetailById(datasourceId);
+        if (StringUtils.isEmpty(databaseName)) {
+            throw new SeatunnelException(
+                    SeatunnelErrorEnum.INVALID_DATASOURCE, res.getDatasourceName());
+        }
+        List<TableField> tableFields =
+                datasourceService.queryTableSchema(
+                        res.getDatasourceName(), databaseName, tableName);
+        return Result.success(tableFields);
+    }
+
+    @PostMapping("/schemas")
+    Result<List<DatabaseTableFields>> getMultiTableFields(
+            @ApiIgnore @RequestAttribute(value = SESSION_USER) User loginUser,
+            @RequestParam("datasourceId") String datasourceId,
+            @RequestBody List<DatabaseTables> tableNames) {
+        DatasourceDetailRes res = datasourceService.queryDatasourceDetailById(datasourceId);
+        List<DatabaseTableFields> tableFields = new ArrayList<>();
+        tableNames.forEach(
+                database -> {
+                    List<TableInfo> tableInfos = new ArrayList<>();
+                    database.getTables()
+                            .forEach(
+                                    tableName -> {
+                                        List<TableField> tableField =
+                                                datasourceService.queryTableSchema(
+                                                        res.getDatasourceName(),
+                                                        database.getDatabase(),
+                                                        tableName);
+                                        tableInfos.add(new TableInfo(tableName, tableField));
+                                    });
+                    tableFields.add(new DatabaseTableFields(database.getDatabase(), tableInfos));
+                });
+        return Result.success(tableFields);
+    }
+
+    @GetMapping("/all-tables")
+    Result<List<DatabaseTables>> getTables(
+            @ApiIgnore @RequestAttribute(value = SESSION_USER) User loginUser,
+            @RequestParam("datasourceId") String datasourceId) {
+        DatasourceDetailRes res = datasourceService.queryDatasourceDetailById(datasourceId);
+        List<DatabaseTables> tables = new ArrayList<>();
+        List<String> databases =
+                datasourceService.queryDatabaseByDatasourceName(res.getDatasourceName());
+        databases.forEach(
+                database -> {
+                    tables.add(
+                            new DatabaseTables(
+                                    database,
+                                    datasourceService.queryTableNames(
+                                            res.getDatasourceName(), database)));
+                });
+        return Result.success(tables);
+    }
+
+    public Map<Integer, String> userIdNameMap() {
+        return userMapper.queryEnabledUsers().stream()
+                .collect(Collectors.toMap(User::getId, User::getUsername));
+    }
+}
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/controller/VirtualTableController.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/controller/VirtualTableController.java
new file mode 100644
index 00000000..eeba37d9
--- /dev/null
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/controller/VirtualTableController.java
@@ -0,0 +1,195 @@
+/*
+ * 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.seatunnel.app.controller;
+
+import org.apache.seatunnel.app.common.Result;
+import org.apache.seatunnel.app.dal.dao.IUserDao;
+import org.apache.seatunnel.app.dal.entity.User;
+import org.apache.seatunnel.app.domain.request.datasource.VirtualTableReq;
+import org.apache.seatunnel.app.domain.response.PageInfo;
+import org.apache.seatunnel.app.domain.response.datasource.VirtualTableDetailRes;
+import org.apache.seatunnel.app.domain.response.datasource.VirtualTableRes;
+import org.apache.seatunnel.app.service.IVirtualTableService;
+
+import org.apache.commons.collections4.CollectionUtils;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.RequestAttribute;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import io.swagger.annotations.ApiImplicitParam;
+import io.swagger.annotations.ApiImplicitParams;
+import io.swagger.annotations.ApiOperation;
+import springfox.documentation.annotations.ApiIgnore;
+
+import javax.annotation.Resource;
+
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+import static org.apache.seatunnel.app.common.Constants.SESSION_USER;
+
+@RestController
+@RequestMapping("/seatunnel/api/v1/virtual_table")
+public class VirtualTableController extends BaseController {
+
+    @Autowired private IVirtualTableService virtualTableService;
+
+    @Resource(name = "userDaoImpl")
+    private IUserDao userMapper;
+
+    @ApiOperation(value = "create virtual table", httpMethod = "POST")
+    @ApiImplicitParams({
+        @ApiImplicitParam(
+                name = "tableReq",
+                value = "virtual table request",
+                required = true,
+                dataType = "VirtualTableReq")
+    })
+    @PostMapping("/create")
+    Result<String> createVirtualTable(
+            @ApiIgnore @RequestAttribute(value = SESSION_USER) User loginUser,
+            @RequestBody VirtualTableReq tableReq) {
+        return Result.success(virtualTableService.createVirtualTable(loginUser.getId(), tableReq));
+    }
+
+    @ApiOperation(value = "update virtual table", httpMethod = "PUT")
+    @ApiImplicitParams({
+        @ApiImplicitParam(
+                name = "id",
+                value = "virtual table id",
+                required = true,
+                dataType = "String"),
+        @ApiImplicitParam(
+                name = "tableReq",
+                value = "virtual table request",
+                required = true,
+                dataType = "VirtualTableReq")
+    })
+    @PutMapping("/{id}")
+    Result<Boolean> updateVirtualTable(
+            @ApiIgnore @RequestAttribute(value = SESSION_USER) User loginUser,
+            @PathVariable("id") String id,
+            @RequestBody VirtualTableReq tableReq) {
+        return Result.success(
+                virtualTableService.updateVirtualTable(loginUser.getId(), id, tableReq));
+    }
+
+    @ApiOperation(value = "check virtual table valid", httpMethod = "GET")
+    @ApiImplicitParams({
+        @ApiImplicitParam(
+                name = "virtualTableReq",
+                value = "virtual table request",
+                required = true,
+                dataType = "VirtualTableReq")
+    })
+    @GetMapping("/check/valid")
+    Result<Boolean> checkVirtualTableValid(
+            @ApiIgnore @RequestAttribute(value = SESSION_USER) User loginUser,
+            @RequestBody VirtualTableReq virtualTableReq) {
+        return Result.success(virtualTableService.checkVirtualTableValid(virtualTableReq));
+    }
+
+    @ApiOperation(value = "get support field type", httpMethod = "GET")
+    @GetMapping("/support/field_type")
+    Result<List<String>> getSupportFieldType(@RequestParam("pluginName") String pluginName) {
+        // return Result.success(virtualTableService.queryTableDynamicTable(pluginName));
+        // todo @liuli
+        return null;
+    }
+
+    @ApiOperation(value = "delete virtual table", httpMethod = "DELETE")
+    @ApiImplicitParams({
+        @ApiImplicitParam(
+                name = "id",
+                value = "virtual table id",
+                required = true,
+                dataType = "String")
+    })
+    @DeleteMapping("/{id}")
+    Result<Boolean> deleteVirtualTable(
+            @PathVariable("id") String id,
+            @ApiIgnore @RequestAttribute(value = SESSION_USER) User loginUser) {
+        return Result.success(virtualTableService.deleteVirtualTable(loginUser.getId(), id));
+    }
+
+    @ApiOperation(value = "query virtual table detail by id", httpMethod = "GET")
+    @ApiImplicitParams({
+        @ApiImplicitParam(
+                name = "id",
+                value = "virtual table id",
+                required = true,
+                dataType = "String")
+    })
+    @GetMapping("/{id}")
+    Result<VirtualTableDetailRes> queryVirtualTable(
+            @ApiIgnore @RequestAttribute(value = SESSION_USER) User loginUser,
+            @PathVariable("id") String id) {
+        // rsp add plugin name
+        return Result.success(virtualTableService.queryVirtualTable(id));
+    }
+
+    @GetMapping("/list")
+    Result<PageInfo<VirtualTableRes>> getVirtualTableList(
+            @RequestParam("pluginName") String pluginName,
+            @RequestParam("datasourceName") String datasourceName,
+            @RequestParam("pageNo") Integer pageNo,
+            @RequestParam("pageSize") Integer pageSize) {
+        PageInfo<VirtualTableRes> virtualTableList =
+                virtualTableService.getVirtualTableList(
+                        pluginName, datasourceName, pageNo, pageSize);
+        if (virtualTableList.getTotalCount() == 0
+                || CollectionUtils.isEmpty(virtualTableList.getData())) {
+            return Result.success(virtualTableList);
+        }
+        Map<Integer, String> userIdNameMap = userIdNameMap();
+        virtualTableList
+                .getData()
+                .forEach(
+                        virtualTableRes -> {
+                            virtualTableRes.setCreateUserName(
+                                    userIdNameMap.getOrDefault(
+                                            virtualTableRes.getCreateUserId(), ""));
+                            virtualTableRes.setUpdateUserName(
+                                    userIdNameMap.getOrDefault(
+                                            virtualTableRes.getUpdateUserId(), ""));
+                        });
+        return Result.success(virtualTableList);
+    }
+
+    @GetMapping("/dynamic_config")
+    Result<String> getDynamicConfig(
+            @RequestParam("pluginName") String pluginName,
+            @RequestParam("datasourceName") String datasourceName) {
+        return Result.success(virtualTableService.queryTableDynamicTable(pluginName));
+    }
+
+    public Map<Integer, String> userIdNameMap() {
+        return userMapper.queryEnabledUsers().stream()
+                .collect(Collectors.toMap(User::getId, User::getUsername));
+    }
+}
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/dao/IDatasourceDao.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/dao/IDatasourceDao.java
new file mode 100644
index 00000000..206f63f2
--- /dev/null
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/dao/IDatasourceDao.java
@@ -0,0 +1,60 @@
+/*
+ * 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.seatunnel.app.dal.dao;
+
+import org.apache.seatunnel.app.dal.entity.Datasource;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+
+import java.util.List;
+
+public interface IDatasourceDao {
+
+    boolean insertDatasource(Datasource datasource);
+
+    Datasource selectDatasourceById(Long id);
+
+    boolean deleteDatasourceById(Long id);
+
+    Datasource queryDatasourceByName(String name);
+
+    boolean updateDatasourceById(Datasource datasource);
+
+    boolean checkDatasourceNameUnique(String dataSourceName, Long dataSourceId);
+
+    String queryDatasourceNameById(Long id);
+
+    List<Datasource> selectDatasourceByPluginName(String pluginName, String pluginVersion);
+
+    IPage<Datasource> selectDatasourcePage(Page<Datasource> page);
+
+    IPage<Datasource> selectDatasourceByParam(
+            Page<Datasource> page,
+            List<Long> availableDatasourceIds,
+            String searchVal,
+            String pluginName);
+
+    List<Datasource> selectDatasourceByIds(List<Long> ids);
+
+    List<Datasource> queryAll();
+
+    List<Datasource> selectByIds(List<Long> ids);
+
+    List<Datasource> selectDatasourceByUserId(int userId);
+}
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/exceptions/UnSupportWrapperException.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/dao/IJobDefinitionDao.java
similarity index 57%
copy from seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/exceptions/UnSupportWrapperException.java
copy to seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/dao/IJobDefinitionDao.java
index c761c9db..34b87b57 100644
--- a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/exceptions/UnSupportWrapperException.java
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/dao/IJobDefinitionDao.java
@@ -15,16 +15,27 @@
  * limitations under the License.
  */
 
-package org.apache.seatunnel.app.thridparty.exceptions;
+package org.apache.seatunnel.app.dal.dao;
+
+import org.apache.seatunnel.app.dal.entity.JobDefinition;
+import org.apache.seatunnel.app.domain.response.PageInfo;
 
 import lombok.NonNull;
 
-public class UnSupportWrapperException extends RuntimeException {
-    public UnSupportWrapperException(
-            @NonNull String formName, @NonNull String label, @NonNull String typeName) {
-        super(
-                String.format(
-                        "Form: %s, label: %s, typeName: %s not yet supported",
-                        formName, label, typeName));
-    }
+import java.util.List;
+
+public interface IJobDefinitionDao {
+
+    void add(JobDefinition job);
+
+    JobDefinition getJob(long id);
+
+    void updateJob(JobDefinition jobDefinition);
+
+    PageInfo<JobDefinition> getJob(
+            String name, Integer pageNo, Integer pageSize, List<Long> projectCodes, String jobMode);
+
+    List<JobDefinition> getJob(@NonNull List<Long> projectCodes, @NonNull String name);
+
+    void delete(long id, long projectCode);
 }
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/response/datasource/DatasourceRes.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/dao/IJobTaskDao.java
similarity index 59%
copy from seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/response/datasource/DatasourceRes.java
copy to seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/dao/IJobTaskDao.java
index b702a124..f9ae0a14 100644
--- a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/response/datasource/DatasourceRes.java
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/dao/IJobTaskDao.java
@@ -15,30 +15,27 @@
  * limitations under the License.
  */
 
-package org.apache.seatunnel.app.domain.response.datasource;
+package org.apache.seatunnel.app.dal.dao;
 
-import org.apache.seatunnel.app.domain.response.BaseInfo;
+import org.apache.seatunnel.app.dal.entity.JobTask;
 
-import lombok.Data;
+import java.util.List;
 
-import java.util.Map;
+public interface IJobTaskDao {
 
-@Data
-public class DatasourceRes extends BaseInfo {
+    List<JobTask> getTasksByVersionId(long jobVersionId);
 
-    private String id;
+    void insertTask(JobTask jobTask);
 
-    private String datasourceName;
+    void updateTask(JobTask jobTask);
 
-    private String pluginName;
+    List<JobTask> getJobTaskByDataSourceId(long datasourceId);
 
-    private String pluginVersion;
+    JobTask getTask(long jobVersionId, String pluginId);
 
-    private String description;
+    void updateTasks(List<JobTask> jobTasks);
 
-    private Map<String, String> datasourceConfig;
+    void deleteTasks(List<Long> jobTaskIds);
 
-    private int createUserId;
-
-    private int updateUserId;
+    void deleteTask(long jobVersionId, String pluginId);
 }
diff --git a/seatunnel-datasource/seatunnel-datasource-plugins/datasource-plugins-api/src/main/java/org/apache/seatunnel/datasource/plugin/api/model/TableField.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/dao/IJobVersionDao.java
similarity index 63%
copy from seatunnel-datasource/seatunnel-datasource-plugins/datasource-plugins-api/src/main/java/org/apache/seatunnel/datasource/plugin/api/model/TableField.java
copy to seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/dao/IJobVersionDao.java
index fabcaf47..593dde81 100644
--- a/seatunnel-datasource/seatunnel-datasource-plugins/datasource-plugins-api/src/main/java/org/apache/seatunnel/datasource/plugin/api/model/TableField.java
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/dao/IJobVersionDao.java
@@ -15,26 +15,23 @@
  * limitations under the License.
  */
 
-package org.apache.seatunnel.datasource.plugin.api.model;
+package org.apache.seatunnel.app.dal.dao;
 
-import lombok.Data;
+import org.apache.seatunnel.app.dal.entity.JobVersion;
 
-import java.util.Map;
+import java.util.List;
 
-@Data
-public class TableField {
+public interface IJobVersionDao {
 
-    private String type;
+    void createVersion(JobVersion jobVersion);
 
-    private String name;
+    void updateVersion(JobVersion version);
 
-    private String comment;
+    JobVersion getLatestVersion(long jobId);
 
-    private Boolean primaryKey;
+    List<JobVersion> getLatestVersionByJobIds(List<Long> jobIds);
 
-    private String defaultValue;
+    JobVersion getVersionById(long jobVersionId);
 
-    private Boolean nullable;
-
-    private Map<String, String> properties;
+    List<JobVersion> getVersionsByIds(List<Long> jobVersionIds);
 }
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/dao/IUserDao.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/dao/IUserDao.java
index db2f1662..8adb6442 100644
--- a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/dao/IUserDao.java
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/dao/IUserDao.java
@@ -24,6 +24,8 @@ import org.apache.seatunnel.app.domain.dto.user.UpdateUserDto;
 import org.apache.seatunnel.app.domain.dto.user.UserLoginLogDto;
 import org.apache.seatunnel.server.common.PageData;
 
+import java.util.List;
+
 public interface IUserDao {
     int add(UpdateUserDto dto);
 
@@ -50,4 +52,11 @@ public interface IUserDao {
     void disableToken(int userId);
 
     UserLoginLog getLastLoginLog(Integer userId);
+
+    /**
+     * query enabled users
+     *
+     * @return
+     */
+    List<User> queryEnabledUsers();
 }
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/dao/IVirtualTableDao.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/dao/IVirtualTableDao.java
new file mode 100644
index 00000000..9c4225d2
--- /dev/null
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/dao/IVirtualTableDao.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.seatunnel.app.dal.dao;
+
+import org.apache.seatunnel.app.dal.entity.VirtualTable;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+
+import java.util.List;
+
+public interface IVirtualTableDao {
+
+    boolean insertVirtualTable(VirtualTable virtualTable);
+
+    boolean updateVirtualTable(VirtualTable virtualTable);
+
+    boolean deleteVirtualTable(Long id);
+
+    VirtualTable selectVirtualTableById(Long id);
+
+    VirtualTable selectVirtualTableByTableName(String tableName);
+
+    boolean checkVirtualTableNameUnique(String virtualTableName, String databaseName, Long tableId);
+
+    IPage<VirtualTable> selectVirtualTablePage(
+            Page<VirtualTable> page, String pluginName, String datasourceName);
+
+    IPage<VirtualTable> selectDatasourceByParam(Page<VirtualTable> page, Long datasourceId);
+
+    List<String> getVirtualTableNames(String databaseName, Long datasourceId);
+
+    List<String> getVirtualDatabaseNames(Long datasourceId);
+
+    boolean checkHasVirtualTable(Long datasourceId);
+}
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/response/datasource/DatasourceRes.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/dao/TaskDefinitionDao.java
similarity index 60%
copy from seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/response/datasource/DatasourceRes.java
copy to seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/dao/TaskDefinitionDao.java
index b702a124..7e5ac6e4 100644
--- a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/response/datasource/DatasourceRes.java
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/dao/TaskDefinitionDao.java
@@ -15,30 +15,20 @@
  * limitations under the License.
  */
 
-package org.apache.seatunnel.app.domain.response.datasource;
+package org.apache.seatunnel.app.dal.dao;
 
-import org.apache.seatunnel.app.domain.response.BaseInfo;
+import org.apache.seatunnel.app.dal.entity.TaskDefinition;
+import org.apache.seatunnel.app.dal.entity.TaskMainInfo;
 
-import lombok.Data;
+import java.util.Collection;
+import java.util.List;
 
-import java.util.Map;
+public interface TaskDefinitionDao {
 
-@Data
-public class DatasourceRes extends BaseInfo {
+    List<TaskMainInfo> queryByDataSourceId(Long dataSourceId);
 
-    private String id;
+    List<TaskDefinition> queryTaskDefinitions(Collection<Long> taskCodes);
 
-    private String datasourceName;
-
-    private String pluginName;
-
-    private String pluginVersion;
-
-    private String description;
-
-    private Map<String, String> datasourceConfig;
-
-    private int createUserId;
-
-    private int updateUserId;
+    List<TaskDefinition> queryByWorkflowDefinitionCodeAndVersion(
+            Long workflowDefinitionCode, Integer workflowDefinitionVersion);
 }
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/dao/impl/DatasourceDaoImpl.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/dao/impl/DatasourceDaoImpl.java
new file mode 100644
index 00000000..3e7d273d
--- /dev/null
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/dao/impl/DatasourceDaoImpl.java
@@ -0,0 +1,139 @@
+/*
+ * 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.seatunnel.app.dal.dao.impl;
+
+import org.apache.seatunnel.app.dal.dao.IDatasourceDao;
+import org.apache.seatunnel.app.dal.entity.Datasource;
+import org.apache.seatunnel.app.dal.mapper.DatasourceMapper;
+
+import org.springframework.stereotype.Repository;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+
+import javax.annotation.Resource;
+
+import java.util.List;
+
+@Repository
+public class DatasourceDaoImpl implements IDatasourceDao {
+
+    @Resource private DatasourceMapper datasourceMapper;
+
+    @Override
+    public boolean insertDatasource(Datasource datasource) {
+        return datasourceMapper.insert(datasource) > 0;
+    }
+
+    @Override
+    public Datasource selectDatasourceById(Long id) {
+        return datasourceMapper.selectById(id);
+    }
+
+    @Override
+    public boolean deleteDatasourceById(Long id) {
+        return datasourceMapper.deleteById(id) > 0;
+    }
+
+    @Override
+    public Datasource queryDatasourceByName(String name) {
+        return datasourceMapper.selectOne(
+                new QueryWrapper<Datasource>().eq("datasource_name", name));
+    }
+
+    @Override
+    public boolean updateDatasourceById(Datasource datasource) {
+        return datasourceMapper.updateById(datasource) > 0;
+    }
+
+    @Override
+    public boolean checkDatasourceNameUnique(String dataSourceName, Long dataSourceId) {
+        return datasourceMapper.checkDataSourceNameUnique(dataSourceName, dataSourceId) <= 0;
+    }
+
+    @Override
+    public IPage<Datasource> selectDatasourcePage(Page<Datasource> page) {
+        return datasourceMapper.selectPage(page, new QueryWrapper<Datasource>());
+    }
+
+    @Override
+    public IPage<Datasource> selectDatasourceByParam(
+            Page<Datasource> page,
+            List<Long> availableDatasourceIds,
+            String searchVal,
+            String pluginName) {
+
+        QueryWrapper<Datasource> datasourceQueryWrapper = new QueryWrapper<>();
+        datasourceQueryWrapper.in("id", availableDatasourceIds);
+        if (searchVal != null
+                && !searchVal.isEmpty()
+                && pluginName != null
+                && !pluginName.isEmpty()) {
+            return datasourceMapper.selectPage(
+                    page,
+                    datasourceQueryWrapper
+                            .eq("plugin_name", pluginName)
+                            .like("datasource_name", searchVal));
+        }
+        if (searchVal != null && !searchVal.isEmpty()) {
+            return datasourceMapper.selectPage(
+                    page, datasourceQueryWrapper.like("datasource_name", searchVal));
+        }
+        if (pluginName != null && !pluginName.isEmpty()) {
+            return datasourceMapper.selectPage(
+                    page, datasourceQueryWrapper.eq("plugin_name", pluginName));
+        }
+        return datasourceMapper.selectPage(page, datasourceQueryWrapper);
+    }
+
+    @Override
+    public String queryDatasourceNameById(Long id) {
+        return datasourceMapper.selectById(id).getDatasourceName();
+    }
+
+    @Override
+    public List<Datasource> selectDatasourceByPluginName(String pluginName, String pluginVersion) {
+        return datasourceMapper.selectList(
+                new QueryWrapper<Datasource>()
+                        .eq("plugin_name", pluginName)
+                        .eq("plugin_version", pluginVersion));
+    }
+
+    @Override
+    public List<Datasource> selectDatasourceByIds(List<Long> ids) {
+        return datasourceMapper.selectBatchIds(ids);
+    }
+
+    @Override
+    public List<Datasource> queryAll() {
+        return datasourceMapper.selectList(new QueryWrapper<>());
+    }
+
+    @Override
+    public List<Datasource> selectByIds(List<Long> ids) {
+        return datasourceMapper.selectBatchIds(ids);
+    }
+
+    @Override
+    public List<Datasource> selectDatasourceByUserId(int userId) {
+        QueryWrapper<Datasource> queryWrapper = new QueryWrapper<>();
+        queryWrapper.eq("create_user_id", userId);
+        return datasourceMapper.selectList(queryWrapper);
+    }
+}
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/dao/impl/JobDefinitionDaoImpl.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/dao/impl/JobDefinitionDaoImpl.java
new file mode 100644
index 00000000..b99f8c56
--- /dev/null
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/dao/impl/JobDefinitionDaoImpl.java
@@ -0,0 +1,94 @@
+/*
+ * 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.seatunnel.app.dal.dao.impl;
+
+import org.apache.seatunnel.app.dal.dao.IJobDefinitionDao;
+import org.apache.seatunnel.app.dal.entity.JobDefinition;
+import org.apache.seatunnel.app.dal.mapper.JobMapper;
+import org.apache.seatunnel.app.domain.response.PageInfo;
+
+import org.apache.commons.lang3.StringUtils;
+
+import org.springframework.stereotype.Repository;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import lombok.NonNull;
+
+import javax.annotation.Resource;
+
+import java.util.List;
+
+@Repository
+public class JobDefinitionDaoImpl implements IJobDefinitionDao {
+
+    @Resource private JobMapper jobMapper;
+
+    @Override
+    public void add(JobDefinition job) {
+        jobMapper.insert(job);
+    }
+
+    @Override
+    public JobDefinition getJob(long id) {
+        return jobMapper.selectById(id);
+    }
+
+    @Override
+    public void updateJob(JobDefinition jobDefinition) {
+        jobMapper.updateById(jobDefinition);
+    }
+
+    @Override
+    public PageInfo<JobDefinition> getJob(
+            String searchName,
+            Integer pageNo,
+            Integer pageSize,
+            List<Long> projectCodes,
+            String jobMode) {
+        IPage<JobDefinition> jobDefinitionIPage;
+        if (StringUtils.isEmpty(jobMode)) {
+            jobDefinitionIPage =
+                    jobMapper.queryJobListPaging(
+                            new Page<>(pageNo, pageSize), searchName, projectCodes);
+        } else {
+            jobDefinitionIPage =
+                    jobMapper.queryJobListPagingWithJobMode(
+                            new Page<>(pageNo, pageSize), searchName, projectCodes, jobMode);
+        }
+        PageInfo<JobDefinition> jobs = new PageInfo<>();
+        jobs.setData(jobDefinitionIPage.getRecords());
+        jobs.setPageSize(pageSize);
+        jobs.setPageNo(pageNo);
+        jobs.setTotalCount((int) jobDefinitionIPage.getTotal());
+        return jobs;
+    }
+
+    @Override
+    public List<JobDefinition> getJob(@NonNull List<Long> projectCodes, @NonNull String name) {
+        return jobMapper.queryJobList(name, projectCodes);
+    }
+
+    public void delete(long id, long projectCode) {
+        jobMapper.delete(
+                Wrappers.lambdaQuery(new JobDefinition())
+                        .eq(JobDefinition::getProjectCode, projectCode)
+                        .and(i -> i.eq(JobDefinition::getId, id)));
+    }
+}
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/dao/impl/JobTaskDaoImpl.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/dao/impl/JobTaskDaoImpl.java
new file mode 100644
index 00000000..540e4c72
--- /dev/null
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/dao/impl/JobTaskDaoImpl.java
@@ -0,0 +1,90 @@
+/*
+ * 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.seatunnel.app.dal.dao.impl;
+
+import org.apache.seatunnel.app.dal.dao.IJobTaskDao;
+import org.apache.seatunnel.app.dal.entity.JobTask;
+import org.apache.seatunnel.app.dal.mapper.JobTaskMapper;
+
+import org.springframework.stereotype.Repository;
+
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+
+import javax.annotation.Resource;
+
+import java.util.List;
+
+@Repository
+public class JobTaskDaoImpl implements IJobTaskDao {
+
+    @Resource private JobTaskMapper jobTaskMapper;
+
+    @Override
+    public List<JobTask> getTasksByVersionId(long jobVersionId) {
+        return jobTaskMapper.selectList(
+                Wrappers.lambdaQuery(new JobTask()).eq(JobTask::getVersionId, jobVersionId));
+    }
+
+    @Override
+    public void insertTask(JobTask jobTask) {
+        if (jobTask != null) {
+            jobTaskMapper.insert(jobTask);
+        }
+    }
+
+    @Override
+    public void updateTask(JobTask jobTask) {
+        if (jobTask != null) {
+            jobTaskMapper.updateById(jobTask);
+        }
+    }
+
+    @Override
+    public JobTask getTask(long jobVersionId, String pluginId) {
+        return jobTaskMapper.selectOne(
+                Wrappers.lambdaQuery(new JobTask())
+                        .eq(JobTask::getVersionId, jobVersionId)
+                        .and(i -> i.eq(JobTask::getPluginId, pluginId)));
+    }
+
+    @Override
+    public List<JobTask> getJobTaskByDataSourceId(long datasourceId) {
+        return jobTaskMapper.selectList(
+                Wrappers.lambdaQuery(new JobTask()).eq(JobTask::getDataSourceId, datasourceId));
+    }
+
+    @Override
+    public void updateTasks(List<JobTask> jobTasks) {
+        jobTasks.forEach(jobTaskMapper::updateById);
+    }
+
+    @Override
+    public void deleteTasks(List<Long> jobTaskIds) {
+        if (!jobTaskIds.isEmpty()) {
+            jobTaskMapper.deleteBatchIds(jobTaskIds);
+        }
+    }
+
+    @Override
+    public void deleteTask(long jobVersionId, String pluginId) {
+        jobTaskMapper.delete(
+                Wrappers.lambdaQuery(new JobTask())
+                        .eq(JobTask::getVersionId, jobVersionId)
+                        .and(i -> i.eq(JobTask::getPluginId, pluginId)));
+    }
+}
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/dao/impl/JobVersionDaoImpl.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/dao/impl/JobVersionDaoImpl.java
new file mode 100644
index 00000000..4f6c52d9
--- /dev/null
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/dao/impl/JobVersionDaoImpl.java
@@ -0,0 +1,72 @@
+/*
+ * 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.seatunnel.app.dal.dao.impl;
+
+import org.apache.seatunnel.app.dal.dao.IJobVersionDao;
+import org.apache.seatunnel.app.dal.entity.JobVersion;
+import org.apache.seatunnel.app.dal.mapper.JobVersionMapper;
+
+import org.springframework.stereotype.Repository;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+
+import javax.annotation.Resource;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@Repository
+public class JobVersionDaoImpl implements IJobVersionDao {
+
+    @Resource private JobVersionMapper jobVersionMapper;
+
+    @Override
+    public void createVersion(JobVersion jobVersion) {
+        jobVersionMapper.insert(jobVersion);
+    }
+
+    @Override
+    public void updateVersion(JobVersion version) {
+        jobVersionMapper.updateById(version);
+    }
+
+    @Override
+    public JobVersion getLatestVersion(long jobId) {
+        Map<String, Object> queryMap = new HashMap<>();
+        queryMap.put("job_id", jobId);
+        return jobVersionMapper.selectByMap(queryMap).get(0);
+    }
+
+    @Override
+    public List<JobVersion> getLatestVersionByJobIds(List<Long> jobIds) {
+        QueryWrapper wrapper = new QueryWrapper<JobVersion>();
+        wrapper.in("job_id", jobIds);
+        return jobVersionMapper.selectList(wrapper);
+    }
+
+    @Override
+    public JobVersion getVersionById(long jobVersionId) {
+        return jobVersionMapper.selectById(jobVersionId);
+    }
+
+    @Override
+    public List<JobVersion> getVersionsByIds(List<Long> jobVersionIds) {
+        return jobVersionMapper.selectBatchIds(jobVersionIds);
+    }
+}
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/dao/impl/TaskDefinitionDaoImpl.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/dao/impl/TaskDefinitionDaoImpl.java
new file mode 100644
index 00000000..3da9205f
--- /dev/null
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/dao/impl/TaskDefinitionDaoImpl.java
@@ -0,0 +1,75 @@
+/*
+ * 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.seatunnel.app.dal.dao.impl;
+
+import org.apache.seatunnel.app.dal.dao.TaskDefinitionDao;
+import org.apache.seatunnel.app.dal.entity.ProcessTaskRelation;
+import org.apache.seatunnel.app.dal.entity.TaskDefinition;
+import org.apache.seatunnel.app.dal.entity.TaskMainInfo;
+import org.apache.seatunnel.app.dal.mapper.ProcessTaskRelationMapper;
+import org.apache.seatunnel.app.dal.mapper.TaskDefinitionMapper;
+
+import org.apache.commons.collections4.CollectionUtils;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Repository;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+@Repository
+public class TaskDefinitionDaoImpl implements TaskDefinitionDao {
+
+    @Autowired private TaskDefinitionMapper taskDefinitionMapper;
+
+    @Autowired private ProcessTaskRelationMapper processTaskRelationMapper;
+
+    @Override
+    public List<TaskMainInfo> queryByDataSourceId(Long dataSourceId) {
+        return processTaskRelationMapper.queryByDataSourceId(dataSourceId);
+    }
+
+    @Override
+    public List<TaskDefinition> queryTaskDefinitions(Collection<Long> taskCodes) {
+        if (CollectionUtils.isEmpty(taskCodes)) {
+            return Collections.emptyList();
+        }
+        return taskDefinitionMapper.queryByCodeList(taskCodes);
+    }
+
+    @Override
+    public List<TaskDefinition> queryByWorkflowDefinitionCodeAndVersion(
+            Long workflowDefinitionCode, Integer workflowDefinitionVersion) {
+        List<ProcessTaskRelation> processTaskRelations =
+                processTaskRelationMapper.queryProcessTaskRelationsByProcessDefinitionCode(
+                        workflowDefinitionCode, workflowDefinitionVersion);
+        Set<Long> taskCodes = new HashSet<>();
+        processTaskRelations.forEach(
+                processTaskRelation -> {
+                    taskCodes.add(processTaskRelation.getPreTaskCode());
+                    taskCodes.add(processTaskRelation.getPostTaskCode());
+                });
+        if (CollectionUtils.isEmpty(taskCodes)) {
+            return Collections.emptyList();
+        }
+        return taskDefinitionMapper.queryByCodeList(taskCodes);
+    }
+}
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/dao/impl/UserDaoImpl.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/dao/impl/UserDaoImpl.java
index c2831aa8..0b26991d 100644
--- a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/dao/impl/UserDaoImpl.java
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/dao/impl/UserDaoImpl.java
@@ -138,4 +138,9 @@ public class UserDaoImpl implements IUserDao {
     public UserLoginLog getLastLoginLog(Integer userId) {
         return userLoginLogMapper.checkLastTokenEnable(userId);
     }
+
+    @Override
+    public List<User> queryEnabledUsers() {
+        return userMapper.queryEnabledUsers();
+    }
 }
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/dao/impl/VirtualTableDaoImpl.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/dao/impl/VirtualTableDaoImpl.java
new file mode 100644
index 00000000..854d38eb
--- /dev/null
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/dao/impl/VirtualTableDaoImpl.java
@@ -0,0 +1,139 @@
+/*
+ * 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.seatunnel.app.dal.dao.impl;
+
+import org.apache.seatunnel.app.dal.dao.IVirtualTableDao;
+import org.apache.seatunnel.app.dal.entity.VirtualTable;
+import org.apache.seatunnel.app.dal.mapper.VirtualTableMapper;
+
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.lang3.StringUtils;
+
+import org.springframework.stereotype.Repository;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import lombok.extern.slf4j.Slf4j;
+
+import javax.annotation.Resource;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
+
+@Repository
+@Slf4j
+public class VirtualTableDaoImpl implements IVirtualTableDao {
+
+    @Resource private VirtualTableMapper virtualTableMapper;
+
+    @Override
+    public boolean insertVirtualTable(VirtualTable virtualTable) {
+        return virtualTableMapper.insert(virtualTable) > 0;
+    }
+
+    @Override
+    public boolean updateVirtualTable(VirtualTable virtualTable) {
+        return virtualTableMapper.updateById(virtualTable) > 0;
+    }
+
+    @Override
+    public boolean deleteVirtualTable(Long id) {
+        return virtualTableMapper.deleteById(id) > 0;
+    }
+
+    @Override
+    public VirtualTable selectVirtualTableById(Long id) {
+        return virtualTableMapper.selectById(id);
+    }
+
+    @Override
+    public VirtualTable selectVirtualTableByTableName(String tableName) {
+        return virtualTableMapper.selectOne(
+                new QueryWrapper<VirtualTable>().eq("virtual_table_name", tableName));
+    }
+
+    @Override
+    public boolean checkVirtualTableNameUnique(
+            String virtualTableName, String databaseName, Long tableId) {
+        return virtualTableMapper.checkVirtualTableNameUnique(
+                        tableId, databaseName, virtualTableName)
+                <= 0;
+    }
+
+    @Override
+    public IPage<VirtualTable> selectVirtualTablePage(
+            Page<VirtualTable> page, String pluginName, String datasourceName) {
+        log.debug(
+                "======================pluginName:{}, datasourceName:{}",
+                pluginName,
+                datasourceName);
+        if (StringUtils.isBlank(pluginName) && StringUtils.isBlank(datasourceName)) {
+            return virtualTableMapper.selectPage(
+                    page, new QueryWrapper<VirtualTable>().orderByDesc("create_time"));
+        }
+        return virtualTableMapper.selectVirtualTablePageByParam(page, pluginName, datasourceName);
+    }
+
+    @Override
+    public IPage<VirtualTable> selectDatasourceByParam(Page<VirtualTable> page, Long datasourceId) {
+        return virtualTableMapper.selectPage(
+                page,
+                new QueryWrapper<VirtualTable>()
+                        .eq("datasource_id", datasourceId)
+                        .orderByDesc("create_time"));
+    }
+
+    @Override
+    public List<String> getVirtualTableNames(String databaseName, Long datasourceId) {
+
+        List<VirtualTable> result =
+                virtualTableMapper.selectList(
+                        new QueryWrapper<VirtualTable>()
+                                .select("virtual_table_name")
+                                .eq("datasource_id", datasourceId)
+                                .eq("virtual_database_name", databaseName));
+        if (CollectionUtils.isEmpty(result)) {
+            return new ArrayList<>();
+        }
+        return result.stream().map(VirtualTable::getVirtualTableName).collect(Collectors.toList());
+    }
+
+    @Override
+    public List<String> getVirtualDatabaseNames(Long datasourceId) {
+        List<VirtualTable> result =
+                virtualTableMapper.selectList(
+                        new QueryWrapper<VirtualTable>()
+                                .select("virtual_database_name")
+                                .eq("datasource_id", datasourceId));
+        if (CollectionUtils.isEmpty(result)) {
+            return new ArrayList<>();
+        }
+        return result.stream()
+                .map(VirtualTable::getVirtualDatabaseName)
+                .collect(Collectors.toList());
+    }
+
+    @Override
+    public boolean checkHasVirtualTable(Long datasourceId) {
+        return virtualTableMapper.selectCount(
+                        new QueryWrapper<VirtualTable>().eq("datasource_id", datasourceId))
+                > 0;
+    }
+}
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/entity/Datasource.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/entity/Datasource.java
new file mode 100644
index 00000000..3a526da8
--- /dev/null
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/entity/Datasource.java
@@ -0,0 +1,67 @@
+/*
+ * 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.seatunnel.app.dal.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.Date;
+
+@Data
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+@TableName("t_st_datasource")
+public class Datasource {
+
+    @TableId(value = "id", type = IdType.INPUT)
+    private Long id;
+
+    @TableField("datasource_name")
+    private String datasourceName;
+
+    @TableField("plugin_name")
+    private String pluginName;
+
+    @TableField("plugin_version")
+    private String pluginVersion;
+
+    @TableField("datasource_config")
+    private String datasourceConfig;
+
+    @TableField("description")
+    private String description;
+
+    @TableField("create_user_id")
+    private Integer createUserId;
+
+    @TableField("update_user_id")
+    private Integer updateUserId;
+
+    @TableField("create_time")
+    private Date createTime;
+
+    @TableField("update_time")
+    private Date updateTime;
+}
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/impl/SqlServerDataSourceConfigSwitcher.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/entity/DefinitionGroupByUser.java
similarity index 54%
copy from seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/impl/SqlServerDataSourceConfigSwitcher.java
copy to seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/entity/DefinitionGroupByUser.java
index 3d877f08..c2de7b57 100644
--- a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/impl/SqlServerDataSourceConfigSwitcher.java
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/entity/DefinitionGroupByUser.java
@@ -15,18 +15,41 @@
  * limitations under the License.
  */
 
-package org.apache.seatunnel.app.thridparty.datasource.impl;
+package org.apache.seatunnel.app.dal.entity;
 
-import org.apache.seatunnel.app.thridparty.datasource.AbstractDataSourceConfigSwitcher;
+/** count definition number group by user */
+public class DefinitionGroupByUser {
 
-public class SqlServerDataSourceConfigSwitcher extends AbstractDataSourceConfigSwitcher {
+    /** user name */
+    private String userName;
 
-    private static final SqlServerDataSourceConfigSwitcher INSTANCE =
-            new SqlServerDataSourceConfigSwitcher();
+    /** user id */
+    private Integer userId;
 
-    public static final SqlServerDataSourceConfigSwitcher getInstance() {
-        return INSTANCE;
+    /** count number */
+    private int count;
+
+    public String getUserName() {
+        return userName;
+    }
+
+    public void setUserName(String userName) {
+        this.userName = userName;
+    }
+
+    public int getCount() {
+        return count;
     }
 
-    private SqlServerDataSourceConfigSwitcher() {}
+    public void setCount(int count) {
+        this.count = count;
+    }
+
+    public Integer getUserId() {
+        return userId;
+    }
+
+    public void setUserId(Integer userId) {
+        this.userId = userId;
+    }
 }
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/entity/JobDefinition.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/entity/JobDefinition.java
new file mode 100644
index 00000000..f753fb58
--- /dev/null
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/entity/JobDefinition.java
@@ -0,0 +1,63 @@
+/*
+ * 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.seatunnel.app.dal.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.Date;
+
+@Data
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+@TableName("t_st_job_definition")
+public class JobDefinition {
+
+    @TableId(value = "id", type = IdType.INPUT)
+    private Long id;
+
+    @TableField private String name;
+
+    @TableField private String description;
+
+    /** {@link BusinessMode} string values */
+    @TableField("job_type")
+    private String jobType;
+
+    @TableField("create_user_id")
+    private Integer createUserId;
+
+    @TableField("update_user_id")
+    private Integer updateUserId;
+
+    @TableField("project_code")
+    private Long projectCode;
+
+    @TableField("create_time")
+    private Date createTime;
+
+    @TableField("update_time")
+    private Date updateTime;
+}
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/entity/JobTask.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/entity/JobTask.java
new file mode 100644
index 00000000..417a2015
--- /dev/null
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/entity/JobTask.java
@@ -0,0 +1,84 @@
+/*
+ * 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.seatunnel.app.dal.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.Date;
+
+@Data
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+@TableName("t_st_job_task")
+public class JobTask {
+
+    @TableId(value = "id", type = IdType.INPUT)
+    private Long id;
+
+    @TableField("version_id")
+    private Long versionId;
+
+    @TableField("plugin_id")
+    private String pluginId;
+
+    @TableField("connector_type")
+    private String connectorType;
+
+    @TableField("datasource_id")
+    private Long dataSourceId;
+
+    /** { value */
+    @TableField("datasource_option")
+    private String dataSourceOption;
+
+    /** { value */
+    @TableField("select_table_fields")
+    private String selectTableFields;
+
+    @TableField("scene_mode")
+    private String sceneMode;
+
+    /** value */
+    @TableField("transform_options")
+    private String transformOptions;
+
+    /** {@link java.util.List} value */
+    @TableField("output_schema")
+    private String outputSchema;
+
+    @TableField private String config;
+
+    /** {@link org.apache.seatunnel.common.constants.PluginType} values, lowercase */
+    @TableField private String type;
+
+    @TableField private String name;
+
+    @TableField("create_time")
+    private Date createTime;
+
+    @TableField("update_time")
+    private Date updateTime;
+}
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/entity/JobVersion.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/entity/JobVersion.java
new file mode 100644
index 00000000..3a8abe6e
--- /dev/null
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/entity/JobVersion.java
@@ -0,0 +1,71 @@
+/*
+ * 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.seatunnel.app.dal.entity;
+
+import org.apache.seatunnel.common.constants.JobMode;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.Date;
+
+@Data
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+@TableName("t_st_job_version")
+public class JobVersion {
+
+    @TableId(value = "id", type = IdType.INPUT)
+    private Long id;
+
+    @TableField private String name;
+
+    @TableField("job_id")
+    private Long jobId;
+
+    /** {@link JobMode} value */
+    @TableField("job_mode")
+    private String jobMode;
+
+    @TableField private String env;
+
+    @TableField("engine_name")
+    private String engineName;
+
+    @TableField("engine_version")
+    private String engineVersion;
+
+    @TableField("create_user_id")
+    private Integer createUserId;
+
+    @TableField("update_user_id")
+    private Integer updateUserId;
+
+    @TableField("create_time")
+    private Date createTime;
+
+    @TableField("update_time")
+    private Date updateTime;
+}
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/entity/ProcessTaskRelation.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/entity/ProcessTaskRelation.java
new file mode 100644
index 00000000..32817e7c
--- /dev/null
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/entity/ProcessTaskRelation.java
@@ -0,0 +1,107 @@
+/*
+ * 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.seatunnel.app.dal.entity;
+
+import org.apache.seatunnel.app.common.ConditionType;
+import org.apache.seatunnel.app.utils.JSONUtils;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import lombok.Data;
+
+import java.util.Date;
+
+/** process task relation */
+@Data
+@TableName("t_ds_process_task_relation")
+public class ProcessTaskRelation {
+
+    /** id */
+    @TableId(value = "id", type = IdType.AUTO)
+    private Integer id;
+
+    /** name */
+    private String name;
+
+    /** process version */
+    private int processDefinitionVersion;
+
+    /** project code */
+    private long projectCode;
+
+    /** process code */
+    private long processDefinitionCode;
+
+    /** pre task code */
+    private long preTaskCode;
+
+    /** pre node version */
+    private int preTaskVersion;
+
+    /** post task code */
+    private long postTaskCode;
+
+    /** post node version */
+    private int postTaskVersion;
+
+    /** condition type */
+    private ConditionType conditionType;
+
+    /** condition parameters */
+    @JsonDeserialize(using = JSONUtils.JsonDataDeserializer.class)
+    @JsonSerialize(using = JSONUtils.JsonDataSerializer.class)
+    private String conditionParams;
+
+    /** create time */
+    private Date createTime;
+
+    /** update time */
+    private Date updateTime;
+
+    public ProcessTaskRelation() {}
+
+    public ProcessTaskRelation(
+            String name,
+            int processDefinitionVersion,
+            long projectCode,
+            long processDefinitionCode,
+            long preTaskCode,
+            int preTaskVersion,
+            long postTaskCode,
+            int postTaskVersion,
+            ConditionType conditionType,
+            String conditionParams,
+            Date createTime,
+            Date updateTime) {
+        this.name = name;
+        this.processDefinitionVersion = processDefinitionVersion;
+        this.projectCode = projectCode;
+        this.processDefinitionCode = processDefinitionCode;
+        this.preTaskCode = preTaskCode;
+        this.preTaskVersion = preTaskVersion;
+        this.postTaskCode = postTaskCode;
+        this.postTaskVersion = postTaskVersion;
+        this.conditionType = conditionType;
+        this.conditionParams = conditionParams;
+        this.createTime = createTime;
+        this.updateTime = updateTime;
+    }
+}
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/entity/ProcessTaskRelationLog.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/entity/ProcessTaskRelationLog.java
new file mode 100644
index 00000000..c594b708
--- /dev/null
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/entity/ProcessTaskRelationLog.java
@@ -0,0 +1,85 @@
+/*
+ * 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.seatunnel.app.dal.entity;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+
+import java.util.Date;
+
+/** process task relation log */
+@TableName("t_ds_process_task_relation_log")
+public class ProcessTaskRelationLog extends ProcessTaskRelation {
+
+    /** operator user id */
+    private int operator;
+
+    /** operate time */
+    private Date operateTime;
+
+    public ProcessTaskRelationLog() {
+        super();
+    }
+
+    public ProcessTaskRelationLog(ProcessTaskRelation processTaskRelation) {
+        super();
+        this.setId(processTaskRelation.getId());
+        this.setName(processTaskRelation.getName());
+        this.setProcessDefinitionCode(processTaskRelation.getProcessDefinitionCode());
+        this.setProcessDefinitionVersion(processTaskRelation.getProcessDefinitionVersion());
+        this.setProjectCode(processTaskRelation.getProjectCode());
+        this.setPreTaskCode(processTaskRelation.getPreTaskCode());
+        this.setPreTaskVersion(processTaskRelation.getPreTaskVersion());
+        this.setPostTaskCode(processTaskRelation.getPostTaskCode());
+        this.setPostTaskVersion(processTaskRelation.getPostTaskVersion());
+        this.setConditionType(processTaskRelation.getConditionType());
+        this.setConditionParams(processTaskRelation.getConditionParams());
+        this.setCreateTime(processTaskRelation.getCreateTime());
+        this.setUpdateTime(processTaskRelation.getUpdateTime());
+    }
+
+    public int getOperator() {
+        return operator;
+    }
+
+    public void setOperator(int operator) {
+        this.operator = operator;
+    }
+
+    public Date getOperateTime() {
+        return operateTime;
+    }
+
+    public void setOperateTime(Date operateTime) {
+        this.operateTime = operateTime;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        return super.equals(o);
+    }
+
+    @Override
+    public int hashCode() {
+        return super.hashCode();
+    }
+
+    @Override
+    public String toString() {
+        return super.toString();
+    }
+}
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/entity/TaskDefinition.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/entity/TaskDefinition.java
new file mode 100644
index 00000000..a56b6c6c
--- /dev/null
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/entity/TaskDefinition.java
@@ -0,0 +1,525 @@
+/*
+ * 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.seatunnel.app.dal.entity;
+
+import org.apache.seatunnel.app.common.Constants;
+import org.apache.seatunnel.app.common.Flag;
+import org.apache.seatunnel.app.common.Priority;
+import org.apache.seatunnel.app.common.TaskTimeoutStrategy;
+import org.apache.seatunnel.app.common.TimeoutFlag;
+import org.apache.seatunnel.app.domain.model.Property;
+import org.apache.seatunnel.app.utils.JSONUtils;
+
+import org.apache.commons.collections4.CollectionUtils;
+
+import com.baomidou.mybatisplus.annotation.FieldStrategy;
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.google.common.base.Strings;
+
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+
+/** task definition */
+@TableName("t_ds_task_definition")
+public class TaskDefinition {
+
+    /** id */
+    @TableId(value = "id", type = IdType.AUTO)
+    private Integer id;
+
+    /** code */
+    private long code;
+
+    /** name */
+    private String name;
+
+    /** version */
+    private int version;
+
+    /** description */
+    private String description;
+
+    /** project code */
+    //    private long projectCode;
+
+    /** task user id */
+    private int userId;
+
+    /** task type */
+    private String taskType;
+
+    /** user defined parameters */
+    @JsonDeserialize(using = JSONUtils.JsonDataDeserializer.class)
+    @JsonSerialize(using = JSONUtils.JsonDataSerializer.class)
+    private String taskParams;
+
+    /** user defined parameter list */
+    @TableField(exist = false)
+    private List<Property> taskParamList;
+
+    /** user define parameter map */
+    @TableField(exist = false)
+    private Map<String, String> taskParamMap;
+
+    /** task is valid: yes/no */
+    private Flag flag;
+
+    /** task priority */
+    private Priority taskPriority;
+
+    /** user name */
+    @TableField(exist = false)
+    private String userName;
+
+    /** project name */
+    //    @TableField(exist = false)
+    //    private String projectName;
+
+    /** worker group */
+    private String workerGroup;
+
+    /** environment code */
+    private long environmentCode;
+
+    /** fail retry times */
+    private int failRetryTimes;
+
+    /** fail retry interval */
+    private int failRetryInterval;
+
+    /** timeout flag */
+    private TimeoutFlag timeoutFlag;
+
+    /** timeout notify strategy */
+    @TableField(updateStrategy = FieldStrategy.IGNORED)
+    private TaskTimeoutStrategy timeoutNotifyStrategy;
+
+    /** task warning time out. unit: minute */
+    private int timeout;
+
+    /** delay execution time. */
+    private int delayTime;
+
+    /** resource ids */
+    private String resourceIds;
+
+    /** create time */
+    private Date createTime;
+
+    /** update time */
+    private Date updateTime;
+
+    /** modify user name */
+    @TableField(exist = false)
+    private String modifyBy;
+
+    /** task group id */
+    private int taskGroupId;
+    /** task group id */
+    private int taskGroupPriority;
+
+    public TaskDefinition() {}
+
+    public TaskDefinition(long code, int version) {
+        this.code = code;
+        this.version = version;
+    }
+
+    public int getTaskGroupId() {
+        return taskGroupId;
+    }
+
+    public void setTaskGroupId(int taskGroupId) {
+        this.taskGroupId = taskGroupId;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public Integer getId() {
+        return id;
+    }
+
+    public void setId(Integer id) {
+        this.id = id;
+    }
+
+    public Date getCreateTime() {
+        return createTime;
+    }
+
+    public void setCreateTime(Date createTime) {
+        this.createTime = createTime;
+    }
+
+    public Date getUpdateTime() {
+        return updateTime;
+    }
+
+    public void setUpdateTime(Date updateTime) {
+        this.updateTime = updateTime;
+    }
+
+    public Flag getFlag() {
+        return flag;
+    }
+
+    public void setFlag(Flag flag) {
+        this.flag = flag;
+    }
+
+    public int getUserId() {
+        return userId;
+    }
+
+    public void setUserId(int userId) {
+        this.userId = userId;
+    }
+
+    public String getUserName() {
+        return userName;
+    }
+
+    public void setUserName(String userName) {
+        this.userName = userName;
+    }
+
+    //    public String getProjectName() {
+    //        return projectName;
+    //    }
+
+    //    public void setProjectName(String projectName) {
+    //        this.projectName = projectName;
+    //    }
+
+    public String getTaskParams() {
+        return taskParams;
+    }
+
+    public void setTaskParams(String taskParams) {
+        this.taskParams = taskParams;
+    }
+
+    public List<Property> getTaskParamList() {
+        JsonNode localParams = JSONUtils.parseObject(taskParams).findValue("localParams");
+        if (localParams != null) {
+            taskParamList = JSONUtils.toList(localParams.toString(), Property.class);
+        }
+
+        return taskParamList;
+    }
+
+    public void setTaskParamList(List<Property> taskParamList) {
+        this.taskParamList = taskParamList;
+    }
+
+    public void setTaskParamMap(Map<String, String> taskParamMap) {
+        this.taskParamMap = taskParamMap;
+    }
+
+    public Map<String, String> getTaskParamMap() {
+        if (taskParamMap == null && !Strings.isNullOrEmpty(taskParams)) {
+            JsonNode localParams = JSONUtils.parseObject(taskParams).findValue("localParams");
+
+            // If a jsonNode is null, not only use !=null, but also it should use the isNull method
+            // to be estimated.
+            if (localParams != null && !localParams.isNull()) {
+                List<Property> propList = JSONUtils.toList(localParams.toString(), Property.class);
+
+                if (CollectionUtils.isNotEmpty(propList)) {
+                    taskParamMap = new HashMap<>();
+                    for (Property property : propList) {
+                        taskParamMap.put(property.getProp(), property.getValue());
+                    }
+                }
+            }
+        }
+        return taskParamMap;
+    }
+
+    public int getTimeout() {
+        return timeout;
+    }
+
+    public void setTimeout(int timeout) {
+        this.timeout = timeout;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    public void setDescription(String description) {
+        this.description = description;
+    }
+
+    public long getCode() {
+        return code;
+    }
+
+    public void setCode(long code) {
+        this.code = code;
+    }
+
+    public int getVersion() {
+        return version;
+    }
+
+    public void setVersion(int version) {
+        this.version = version;
+    }
+
+    //    public long getProjectCode() {
+    //        return projectCode;
+    //    }
+
+    //    public void setProjectCode(long projectCode) {
+    //        this.projectCode = projectCode;
+    //    }
+
+    public String getTaskType() {
+        return taskType;
+    }
+
+    public void setTaskType(String taskType) {
+        this.taskType = taskType;
+    }
+
+    public Priority getTaskPriority() {
+        return taskPriority;
+    }
+
+    public void setTaskPriority(Priority taskPriority) {
+        this.taskPriority = taskPriority;
+    }
+
+    public String getWorkerGroup() {
+        return workerGroup;
+    }
+
+    public void setWorkerGroup(String workerGroup) {
+        this.workerGroup = workerGroup;
+    }
+
+    public int getFailRetryTimes() {
+        return failRetryTimes;
+    }
+
+    public void setFailRetryTimes(int failRetryTimes) {
+        this.failRetryTimes = failRetryTimes;
+    }
+
+    public int getFailRetryInterval() {
+        return failRetryInterval;
+    }
+
+    public void setFailRetryInterval(int failRetryInterval) {
+        this.failRetryInterval = failRetryInterval;
+    }
+
+    public TaskTimeoutStrategy getTimeoutNotifyStrategy() {
+        return timeoutNotifyStrategy;
+    }
+
+    public void setTimeoutNotifyStrategy(TaskTimeoutStrategy timeoutNotifyStrategy) {
+        this.timeoutNotifyStrategy = timeoutNotifyStrategy;
+    }
+
+    public TimeoutFlag getTimeoutFlag() {
+        return timeoutFlag;
+    }
+
+    public void setTimeoutFlag(TimeoutFlag timeoutFlag) {
+        this.timeoutFlag = timeoutFlag;
+    }
+
+    public String getResourceIds() {
+        return resourceIds;
+    }
+
+    public void setResourceIds(String resourceIds) {
+        this.resourceIds = resourceIds;
+    }
+
+    public int getDelayTime() {
+        return delayTime;
+    }
+
+    public void setDelayTime(int delayTime) {
+        this.delayTime = delayTime;
+    }
+
+    public String getDependence() {
+        return JSONUtils.getNodeString(this.taskParams, Constants.DEPENDENCE);
+    }
+
+    public String getModifyBy() {
+        return modifyBy;
+    }
+
+    public void setModifyBy(String modifyBy) {
+        this.modifyBy = modifyBy;
+    }
+
+    public long getEnvironmentCode() {
+        return this.environmentCode;
+    }
+
+    public void setEnvironmentCode(long environmentCode) {
+        this.environmentCode = environmentCode;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (o == null) {
+            return false;
+        }
+        TaskDefinition that = (TaskDefinition) o;
+        return failRetryTimes == that.failRetryTimes
+                && failRetryInterval == that.failRetryInterval
+                && timeout == that.timeout
+                && delayTime == that.delayTime
+                && Objects.equals(name, that.name)
+                && Objects.equals(description, that.description)
+                && Objects.equals(taskType, that.taskType)
+                && Objects.equals(taskParams, that.taskParams)
+                && flag == that.flag
+                && taskPriority == that.taskPriority
+                && Objects.equals(workerGroup, that.workerGroup)
+                && timeoutFlag == that.timeoutFlag
+                && timeoutNotifyStrategy == that.timeoutNotifyStrategy
+                && (Objects.equals(resourceIds, that.resourceIds)
+                        || ("".equals(resourceIds) && that.resourceIds == null)
+                        || ("".equals(that.resourceIds) && resourceIds == null))
+                && environmentCode == that.environmentCode
+                && taskGroupId == that.taskGroupId
+                && taskGroupPriority == that.taskGroupPriority;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(
+                code,
+                version,
+                name,
+                description,
+                taskType,
+                taskParams,
+                flag,
+                taskPriority,
+                workerGroup,
+                failRetryTimes,
+                failRetryInterval,
+                timeout,
+                timeoutFlag,
+                timeoutNotifyStrategy,
+                resourceIds,
+                delayTime,
+                environmentCode,
+                taskGroupId,
+                taskGroupPriority);
+    }
+
+    @Override
+    public String toString() {
+        return "TaskDefinition{"
+                + "id="
+                + id
+                + ", code="
+                + code
+                + ", name='"
+                + name
+                + '\''
+                + ", version="
+                + version
+                + ", description='"
+                + description
+                + ", userId="
+                + userId
+                + ", taskType="
+                + taskType
+                + ", taskParams='"
+                + taskParams
+                + '\''
+                + ", taskParamList="
+                + taskParamList
+                + ", taskParamMap="
+                + taskParamMap
+                + ", flag="
+                + flag
+                + ", taskPriority="
+                + taskPriority
+                + ", userName='"
+                + userName
+                + '\''
+                + ", workerGroup='"
+                + workerGroup
+                + '\''
+                + ", failRetryTimes="
+                + failRetryTimes
+                + ", environmentCode='"
+                + environmentCode
+                + '\''
+                + ", taskGroupId='"
+                + taskGroupId
+                + '\''
+                + ", taskGroupPriority='"
+                + taskGroupPriority
+                + '\''
+                + ", failRetryInterval="
+                + failRetryInterval
+                + ", timeoutFlag="
+                + timeoutFlag
+                + ", timeoutNotifyStrategy="
+                + timeoutNotifyStrategy
+                + ", timeout="
+                + timeout
+                + ", delayTime="
+                + delayTime
+                + ", resourceIds='"
+                + resourceIds
+                + '\''
+                + ", createTime="
+                + createTime
+                + ", updateTime="
+                + updateTime
+                + '}';
+    }
+
+    public int getTaskGroupPriority() {
+        return taskGroupPriority;
+    }
+
+    public void setTaskGroupPriority(int taskGroupPriority) {
+        this.taskGroupPriority = taskGroupPriority;
+    }
+}
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/entity/TaskDefinitionExpand.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/entity/TaskDefinitionExpand.java
new file mode 100644
index 00000000..a7041df1
--- /dev/null
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/entity/TaskDefinitionExpand.java
@@ -0,0 +1,42 @@
+/*
+ * 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.seatunnel.app.dal.entity;
+
+import org.apache.seatunnel.app.parameters.DependentParameters;
+import org.apache.seatunnel.app.parameters.SubProcessParameters;
+import org.apache.seatunnel.app.utils.JSONUtils;
+
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+import static org.apache.seatunnel.app.common.Constants.CMD_PARAM_SUB_PROCESS_DEFINE_CODE;
+
+public class TaskDefinitionExpand extends TaskDefinition {
+
+    public SubProcessParameters getSubProcessParameters() {
+        String parameter = super.getTaskParams();
+        ObjectNode parameterJson = JSONUtils.parseObject(parameter);
+        if (parameterJson.get(CMD_PARAM_SUB_PROCESS_DEFINE_CODE) != null) {
+            return JSONUtils.parseObject(parameter, SubProcessParameters.class);
+        }
+        return null;
+    }
+
+    public DependentParameters getDependentParameters() {
+        return JSONUtils.parseObject(super.getDependence(), DependentParameters.class);
+    }
+}
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/entity/TaskDefinitionLog.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/entity/TaskDefinitionLog.java
new file mode 100644
index 00000000..097266b0
--- /dev/null
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/entity/TaskDefinitionLog.java
@@ -0,0 +1,99 @@
+/*
+ * 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.seatunnel.app.dal.entity;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+
+import java.util.Date;
+
+/** task definition log */
+@TableName("t_ds_task_definition_log")
+public class TaskDefinitionLog extends TaskDefinition {
+
+    /** operator user id */
+    private int operator;
+
+    /** operate time */
+    private Date operateTime;
+
+    public TaskDefinitionLog() {
+        super();
+    }
+
+    public TaskDefinitionLog(TaskDefinition taskDefinition) {
+        super();
+        this.setId(taskDefinition.getId());
+        this.setCode(taskDefinition.getCode());
+        this.setVersion(taskDefinition.getVersion());
+        this.setName(taskDefinition.getName());
+        this.setDescription(taskDefinition.getDescription());
+        this.setUserId(taskDefinition.getUserId());
+        this.setUserName(taskDefinition.getUserName());
+        this.setWorkerGroup(taskDefinition.getWorkerGroup());
+        this.setEnvironmentCode(taskDefinition.getEnvironmentCode());
+        //        this.setProjectCode(taskDefinition.getProjectCode());
+        //        this.setProjectName(taskDefinition.getProjectName());
+        this.setResourceIds(taskDefinition.getResourceIds());
+        this.setTaskParams(taskDefinition.getTaskParams());
+        this.setTaskParamList(taskDefinition.getTaskParamList());
+        this.setTaskParamMap(taskDefinition.getTaskParamMap());
+        this.setTaskPriority(taskDefinition.getTaskPriority());
+        this.setTimeoutNotifyStrategy(taskDefinition.getTimeoutNotifyStrategy());
+        this.setTaskType(taskDefinition.getTaskType());
+        this.setTimeout(taskDefinition.getTimeout());
+        this.setDelayTime(taskDefinition.getDelayTime());
+        this.setTimeoutFlag(taskDefinition.getTimeoutFlag());
+        this.setUpdateTime(taskDefinition.getUpdateTime());
+        this.setCreateTime(taskDefinition.getCreateTime());
+        this.setFailRetryInterval(taskDefinition.getFailRetryInterval());
+        this.setFailRetryTimes(taskDefinition.getFailRetryTimes());
+        this.setFlag(taskDefinition.getFlag());
+        this.setModifyBy(taskDefinition.getModifyBy());
+    }
+
+    public int getOperator() {
+        return operator;
+    }
+
+    public void setOperator(int operator) {
+        this.operator = operator;
+    }
+
+    public Date getOperateTime() {
+        return operateTime;
+    }
+
+    public void setOperateTime(Date operateTime) {
+        this.operateTime = operateTime;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        return super.equals(o);
+    }
+
+    @Override
+    public int hashCode() {
+        return super.hashCode();
+    }
+
+    @Override
+    public String toString() {
+        return super.toString();
+    }
+}
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/entity/TaskMainInfo.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/entity/TaskMainInfo.java
new file mode 100644
index 00000000..de99dbae
--- /dev/null
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/entity/TaskMainInfo.java
@@ -0,0 +1,77 @@
+/*
+ * 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.seatunnel.app.dal.entity;
+
+import org.apache.seatunnel.app.common.ReleaseState;
+
+import lombok.Data;
+
+import java.util.Date;
+import java.util.Map;
+
+/** task main info */
+@Data
+public class TaskMainInfo {
+
+    private long id;
+
+    /** project code */
+    //    private long projectCode;
+
+    /** project name */
+    //    private String projectName;
+
+    /** task name */
+    private String taskName;
+
+    /** task code */
+    private long taskCode;
+
+    /** task version */
+    private int taskVersion;
+
+    /** task type */
+    private String taskType;
+
+    /** create time */
+    private Date taskCreateTime;
+
+    /** update time */
+    private Date taskUpdateTime;
+
+    /** processDefinitionCode */
+    private long processDefinitionCode;
+
+    /** processDefinitionVersion */
+    private int processDefinitionVersion;
+
+    /** processDefinitionName */
+    private String processDefinitionName;
+
+    /** processReleaseState */
+    private ReleaseState processReleaseState;
+
+    /** upstreamTaskMap(k:code,v:name) */
+    private Map<Long, String> upstreamTaskMap;
+
+    /** upstreamTaskCode */
+    private long upstreamTaskCode;
+
+    /** upstreamTaskName */
+    private String upstreamTaskName;
+}
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/entity/VirtualTable.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/entity/VirtualTable.java
new file mode 100644
index 00000000..7afcf725
--- /dev/null
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/entity/VirtualTable.java
@@ -0,0 +1,70 @@
+/*
+ * 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.seatunnel.app.dal.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.Date;
+
+@Data
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+@TableName("t_st_virtual_table")
+public class VirtualTable {
+
+    @TableId(value = "id", type = IdType.INPUT)
+    private Long id;
+
+    @TableField("datasource_id")
+    private Long datasourceId;
+
+    @TableField("virtual_database_name")
+    private String virtualDatabaseName;
+
+    @TableField("virtual_table_name")
+    private String virtualTableName;
+
+    @TableField("table_fields")
+    private String tableFields;
+
+    @TableField("description")
+    private String description;
+
+    @TableField("virtual_table_config")
+    private String virtualTableConfig;
+
+    @TableField("create_user_id")
+    private Integer createUserId;
+
+    @TableField("update_user_id")
+    private Integer updateUserId;
+
+    @TableField("create_time")
+    private Date createTime;
+
+    @TableField("update_time")
+    private Date updateTime;
+}
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/mapper/UserMapper.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/mapper/DatasourceMapper.java
similarity index 54%
copy from seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/mapper/UserMapper.java
copy to seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/mapper/DatasourceMapper.java
index e270ade0..48e9894e 100644
--- a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/mapper/UserMapper.java
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/mapper/DatasourceMapper.java
@@ -17,30 +17,28 @@
 
 package org.apache.seatunnel.app.dal.mapper;
 
-import org.apache.seatunnel.app.dal.entity.User;
+import org.apache.seatunnel.app.dal.entity.Datasource;
 
 import org.apache.ibatis.annotations.Param;
 
-import java.util.List;
-
-public interface UserMapper {
-    User selectByPrimaryKey(@Param("id") Integer id);
-
-    void insert(User user);
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
 
-    int updateByPrimaryKey(User user);
-
-    void deleteByPrimaryKey(@Param("id") int id);
+import java.util.List;
 
-    List<User> selectBySelectiveAndPage(
-            @Param("user") User user, @Param("start") int start, @Param("offset") int offset);
+public interface DatasourceMapper extends BaseMapper<Datasource> {
 
-    void updateStatus(@Param("id") int id, @Param("status") byte status);
+    IPage<Datasource> selectDatasourceByParam(
+            IPage<Datasource> page,
+            @Param("pluginName") String pluginName,
+            @Param("pluginVersion") String pluginVersion,
+            @Param("datasource_id") Long datasourceId);
 
-    User selectByName(@Param("username") String username);
+    List<Datasource> selectByPluginName(@Param("pluginName") String pluginName);
 
-    int countBySelective(@Param("user") User user);
+    int checkDataSourceNameUnique(
+            @Param("datasourceName") String datasourceName,
+            @Param("datasourceId") Long datasourceId);
 
-    User selectByNameAndPasswd(
-            @Param("username") String username, @Param("password") String password);
+    List<Datasource> selectByUserId(@Param("userId") int userId);
 }
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/mapper/UserMapper.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/mapper/JobMapper.java
similarity index 52%
copy from seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/mapper/UserMapper.java
copy to seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/mapper/JobMapper.java
index e270ade0..52cfdc94 100644
--- a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/mapper/UserMapper.java
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/mapper/JobMapper.java
@@ -17,30 +17,28 @@
 
 package org.apache.seatunnel.app.dal.mapper;
 
-import org.apache.seatunnel.app.dal.entity.User;
+import org.apache.seatunnel.app.dal.entity.JobDefinition;
 
 import org.apache.ibatis.annotations.Param;
 
-import java.util.List;
-
-public interface UserMapper {
-    User selectByPrimaryKey(@Param("id") Integer id);
-
-    void insert(User user);
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
 
-    int updateByPrimaryKey(User user);
-
-    void deleteByPrimaryKey(@Param("id") int id);
-
-    List<User> selectBySelectiveAndPage(
-            @Param("user") User user, @Param("start") int start, @Param("offset") int offset);
+import java.util.List;
 
-    void updateStatus(@Param("id") int id, @Param("status") byte status);
+public interface JobMapper extends BaseMapper<JobDefinition> {
 
-    User selectByName(@Param("username") String username);
+    IPage<JobDefinition> queryJobListPaging(
+            IPage<JobDefinition> page,
+            @Param("searchName") String searchName,
+            @Param("projectCodes") List<Long> projectCodes);
 
-    int countBySelective(@Param("user") User user);
+    IPage<JobDefinition> queryJobListPagingWithJobMode(
+            IPage<JobDefinition> page,
+            @Param("searchName") String searchName,
+            @Param("projectCodes") List<Long> projectCodes,
+            @Param("jobMode") String jobMode);
 
-    User selectByNameAndPasswd(
-            @Param("username") String username, @Param("password") String password);
+    List<JobDefinition> queryJobList(
+            @Param("searchName") String searchName, @Param("projectCodes") List<Long> projectCodes);
 }
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/impl/MysqlDatasourceConfigSwitcher.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/mapper/JobTaskMapper.java
similarity index 73%
copy from seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/impl/MysqlDatasourceConfigSwitcher.java
copy to seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/mapper/JobTaskMapper.java
index 7da09161..58f4b4fa 100644
--- a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/impl/MysqlDatasourceConfigSwitcher.java
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/mapper/JobTaskMapper.java
@@ -15,10 +15,10 @@
  * limitations under the License.
  */
 
-package org.apache.seatunnel.app.thridparty.datasource.impl;
+package org.apache.seatunnel.app.dal.mapper;
 
-public class MysqlDatasourceConfigSwitcher extends BaseJdbcDataSourceConfigSwitcher {
-    public static MysqlDatasourceConfigSwitcher INSTANCE = new MysqlDatasourceConfigSwitcher();
+import org.apache.seatunnel.app.dal.entity.JobTask;
 
-    private MysqlDatasourceConfigSwitcher() {}
-}
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+public interface JobTaskMapper extends BaseMapper<JobTask> {}
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/impl/MysqlDatasourceConfigSwitcher.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/mapper/JobVersionMapper.java
similarity index 73%
copy from seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/impl/MysqlDatasourceConfigSwitcher.java
copy to seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/mapper/JobVersionMapper.java
index 7da09161..b7173846 100644
--- a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/impl/MysqlDatasourceConfigSwitcher.java
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/mapper/JobVersionMapper.java
@@ -15,10 +15,10 @@
  * limitations under the License.
  */
 
-package org.apache.seatunnel.app.thridparty.datasource.impl;
+package org.apache.seatunnel.app.dal.mapper;
 
-public class MysqlDatasourceConfigSwitcher extends BaseJdbcDataSourceConfigSwitcher {
-    public static MysqlDatasourceConfigSwitcher INSTANCE = new MysqlDatasourceConfigSwitcher();
+import org.apache.seatunnel.app.dal.entity.JobVersion;
 
-    private MysqlDatasourceConfigSwitcher() {}
-}
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+public interface JobVersionMapper extends BaseMapper<JobVersion> {}
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/mapper/ProcessTaskRelationMapper.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/mapper/ProcessTaskRelationMapper.java
new file mode 100644
index 00000000..2a7d4b02
--- /dev/null
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/mapper/ProcessTaskRelationMapper.java
@@ -0,0 +1,222 @@
+/*
+ * 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.seatunnel.app.dal.mapper;
+
+import org.apache.seatunnel.app.dal.entity.ProcessTaskRelation;
+import org.apache.seatunnel.app.dal.entity.ProcessTaskRelationLog;
+import org.apache.seatunnel.app.dal.entity.TaskMainInfo;
+
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+import org.springframework.cache.annotation.CacheConfig;
+import org.springframework.cache.annotation.CacheEvict;
+import org.springframework.cache.annotation.Cacheable;
+
+import java.util.List;
+import java.util.Map;
+
+/** process task relation mapper interface */
+@CacheConfig(cacheNames = "processTaskRelation", keyGenerator = "cacheKeyGenerator")
+@Mapper
+public interface ProcessTaskRelationMapper {
+
+    /**
+     * process task relation by projectCode and processCode
+     *
+     * @param projectCode projectCode
+     * @param processCode processCode
+     * @return ProcessTaskRelation list
+     */
+    @Cacheable(unless = "#result == null || #result.size() == 0")
+    List<ProcessTaskRelation> queryByProcessCode(
+            @Param("projectCode") long projectCode, @Param("processCode") long processCode);
+
+    /** update */
+    @CacheEvict(key = "#p0.projectCode + '_' + #p0.processDefinitionCode")
+    int updateById(@Param("et") ProcessTaskRelation processTaskRelation);
+
+    /**
+     * delete process task relation by processCode
+     *
+     * @param projectCode projectCode
+     * @param processCode processCode
+     * @return int
+     */
+    @CacheEvict
+    int deleteByCode(
+            @Param("projectCode") long projectCode, @Param("processCode") long processCode);
+
+    /**
+     * process task relation by taskCode
+     *
+     * @param taskCodes taskCode list
+     * @return ProcessTaskRelation
+     */
+    List<ProcessTaskRelation> queryByTaskCodes(@Param("taskCodes") Long[] taskCodes);
+
+    /**
+     * process task relation by taskCode
+     *
+     * @param taskCode taskCode
+     * @return ProcessTaskRelation
+     */
+    List<ProcessTaskRelation> queryByTaskCode(@Param("taskCode") long taskCode);
+
+    /**
+     * batch insert process task relation
+     *
+     * @param taskRelationList taskRelationList
+     * @return int
+     */
+    int batchInsert(@Param("taskRelationList") List<ProcessTaskRelationLog> taskRelationList);
+
+    /**
+     * query downstream process task relation by taskCode
+     *
+     * @param taskCode taskCode
+     * @return ProcessTaskRelation
+     */
+    List<ProcessTaskRelation> queryDownstreamByTaskCode(@Param("taskCode") long taskCode);
+
+    /**
+     * query upstream process task relation by taskCode
+     *
+     * @param projectCode projectCode
+     * @param taskCode taskCode
+     * @return ProcessTaskRelation
+     */
+    List<ProcessTaskRelation> queryUpstreamByCode(
+            @Param("projectCode") long projectCode, @Param("taskCode") long taskCode);
+
+    /**
+     * query downstream process task relation by taskCode
+     *
+     * @param projectCode projectCode
+     * @param taskCode taskCode
+     * @return ProcessTaskRelation
+     */
+    List<ProcessTaskRelation> queryDownstreamByCode(
+            @Param("projectCode") long projectCode, @Param("taskCode") long taskCode);
+
+    /**
+     * query task relation by codes
+     *
+     * @param projectCode projectCode
+     * @param taskCode taskCode
+     * @param preTaskCodes preTaskCode list
+     * @return ProcessTaskRelation
+     */
+    List<ProcessTaskRelation> queryUpstreamByCodes(
+            @Param("projectCode") long projectCode,
+            @Param("taskCode") long taskCode,
+            @Param("preTaskCodes") Long[] preTaskCodes);
+
+    /**
+     * query process task relation by process definition code
+     *
+     * @param processDefinitionCode process definition code
+     * @param processDefinitionVersion process definition version
+     * @return ProcessTaskRelation
+     */
+    List<ProcessTaskRelation> queryProcessTaskRelationsByProcessDefinitionCode(
+            @Param("processDefinitionCode") long processDefinitionCode,
+            @Param("processDefinitionVersion") Integer processDefinitionVersion);
+
+    //    List<ProcessTaskRelation>
+    // queryProcessTaskRelationsByProcessDefinitionCode(@Param("processDefinitionCode") long
+    // processDefinitionCode);
+
+    /**
+     * count upstream by codes
+     *
+     * @param projectCode projectCode
+     * @param taskCode taskCode
+     * @param processDefinitionCodes processDefinitionCodes
+     * @return upstream count list group by process definition code
+     */
+    List<Map<String, Long>> countUpstreamByCodeGroupByProcessDefinitionCode(
+            @Param("projectCode") long projectCode,
+            @Param("processDefinitionCodes") Long[] processDefinitionCodes,
+            @Param("taskCode") long taskCode);
+
+    /**
+     * batch update process task relation pre task
+     *
+     * @param processTaskRelationList process task relation list
+     * @return update num
+     */
+    int batchUpdateProcessTaskRelationPreTask(
+            @Param("processTaskRelationList") List<ProcessTaskRelation> processTaskRelationList);
+
+    /**
+     * query by code
+     *
+     * @param projectCode projectCode
+     * @param processDefinitionCode processDefinitionCode
+     * @param preTaskCode preTaskCode
+     * @param postTaskCode postTaskCode
+     * @return ProcessTaskRelation
+     */
+    List<ProcessTaskRelation> queryByCode(
+            @Param("projectCode") long projectCode,
+            @Param("processDefinitionCode") long processDefinitionCode,
+            @Param("preTaskCode") long preTaskCode,
+            @Param("postTaskCode") long postTaskCode);
+
+    /**
+     * delete process task relation
+     *
+     * @param processTaskRelationLog processTaskRelationLog
+     * @return int
+     */
+    int deleteRelation(
+            @Param("processTaskRelationLog") ProcessTaskRelationLog processTaskRelationLog);
+
+    /**
+     * count by code
+     *
+     * @param projectCode projectCode
+     * @param processDefinitionCode processDefinitionCode
+     * @param preTaskCode preTaskCode
+     * @param postTaskCode postTaskCode
+     * @return ProcessTaskRelation
+     */
+    int countByCode(
+            @Param("projectCode") long projectCode,
+            @Param("processDefinitionCode") long processDefinitionCode,
+            @Param("preTaskCode") long preTaskCode,
+            @Param("postTaskCode") long postTaskCode);
+
+    /**
+     * query downstream process task relation by processDefinitionCode
+     *
+     * @param processDefinitionCode
+     * @return ProcessTaskRelation
+     */
+    List<ProcessTaskRelation> queryDownstreamByProcessDefinitionCode(
+            @Param("processDefinitionCode") long processDefinitionCode);
+
+    /**
+     * query by datasourceId
+     *
+     * @param dataSourceId
+     * @return
+     */
+    List<TaskMainInfo> queryByDataSourceId(@Param("dataSourceId") Long dataSourceId);
+}
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/mapper/SeatunnalTaskDefinitionMapper.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/mapper/SeatunnalTaskDefinitionMapper.java
new file mode 100644
index 00000000..d3d44b39
--- /dev/null
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/mapper/SeatunnalTaskDefinitionMapper.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.seatunnel.app.dal.mapper;
+
+import org.apache.seatunnel.app.dal.entity.TaskDefinition;
+import org.apache.seatunnel.app.dal.entity.TaskDefinitionExpand;
+import org.apache.seatunnel.app.dal.entity.TaskMainInfo;
+
+import org.apache.ibatis.annotations.Param;
+
+import org.springframework.context.annotation.Primary;
+
+import java.util.List;
+import java.util.Set;
+
+@Primary
+public interface SeatunnalTaskDefinitionMapper extends TaskDefinitionMapper {
+
+    /**
+     * Query all specific task type from single process definition
+     *
+     * @param processCode process definition code
+     * @param taskType Task type of this process definition code
+     * @return List of ProcessTaskRelationMapper
+     */
+    List<TaskDefinitionExpand> queryProcessTaskType(
+            @Param("processCode") Long processCode, @Param("taskType") String taskType);
+
+    /**
+     * query all task definition list
+     *
+     * @param taskCodesList taskCodesList
+     * @return task definition list
+     */
+    List<TaskDefinition> queryAllTaskProcessDefinition(
+            @Param("taskCodesList") List<Long> taskCodesList);
+
+    /**
+     * query task definition by project codes and task types
+     *
+     * @param projectCodes
+     * @param definitionCodes
+     * @param taskTypes
+     * @return
+     */
+    List<TaskDefinition> queryTaskDefinitionByProjectCodesAndTaskTypes(
+            @Param("projectCodes") Set<Long> projectCodes,
+            @Param("definitionCodes") Set<Long> definitionCodes,
+            @Param("taskTypes") List<String> taskTypes);
+
+    List<TaskMainInfo> queryTaskDefinitionBySubprocessTask(
+            @Param("processDefinitionCode") Long processDefinitionCode);
+
+    List<TaskMainInfo> queryTaskDefinitionByDependentTaskWithTaskCode(
+            @Param("taskCode") Long taskCode);
+
+    List<TaskMainInfo> queryTaskDefinitionByDependentTaskWithProcessCode(
+            @Param("processDefinitionCode") Long processDefinitionCode);
+}
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/mapper/TaskDefinitionMapper.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/mapper/TaskDefinitionMapper.java
new file mode 100644
index 00000000..248353ad
--- /dev/null
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/mapper/TaskDefinitionMapper.java
@@ -0,0 +1,111 @@
+/*
+ * 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.seatunnel.app.dal.mapper;
+
+import org.apache.seatunnel.app.dal.entity.TaskDefinition;
+import org.apache.seatunnel.app.dal.entity.TaskDefinitionLog;
+import org.apache.seatunnel.app.dal.entity.TaskMainInfo;
+
+import org.apache.ibatis.annotations.MapKey;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+/** task definition mapper interface */
+@Mapper
+public interface TaskDefinitionMapper extends BaseMapper<TaskDefinition> {
+
+    /**
+     * query task definition by code
+     *
+     * @param code taskDefinitionCode
+     * @return task definition
+     */
+    TaskDefinition queryByCode(@Param("code") long code);
+
+    /**
+     * query all task definition list
+     *
+     * @return task definition list
+     */
+    List<TaskDefinition> queryAllDefinitionList();
+
+    /**
+     * list all resource ids
+     *
+     * @return task ids list
+     */
+    @MapKey("id")
+    List<Map<String, Object>> listResources();
+
+    /**
+     * list all resource ids by user id
+     *
+     * @return resource ids list
+     */
+    @MapKey("id")
+    List<Map<String, Object>> listResourcesByUser(@Param("userId") Integer userId);
+
+    /**
+     * delete task definition by code
+     *
+     * @param code code
+     * @return int
+     */
+    int deleteByCode(@Param("code") long code);
+
+    /**
+     * batch insert task definitions
+     *
+     * @param taskDefinitions taskDefinitions
+     * @return int
+     */
+    int batchInsert(@Param("taskDefinitions") List<TaskDefinitionLog> taskDefinitions);
+
+    /**
+     * task main info page
+     *
+     * @param page page // * @param projectCodes projectCodes
+     * @param searchWorkflowName searchWorkflowName
+     * @param searchTaskName searchTaskName
+     * @param taskType taskType
+     * @return task main info IPage
+     */
+    IPage<TaskMainInfo> queryDefineListPaging(
+            IPage<TaskMainInfo> page,
+            //            @Param("projectCodes") List<Long> projectCodes,
+            @Param("searchWorkflowName") String searchWorkflowName,
+            @Param("searchTaskName") String searchTaskName,
+            @Param("taskType") String taskType);
+
+    /**
+     * query task definition by code list
+     *
+     * @param codes taskDefinitionCode list
+     * @return task definition list
+     */
+    List<TaskDefinition> queryByCodeList(@Param("codes") Collection<Long> codes);
+
+    int deleteByCodes(@Param("taskDefinitionCodes") List<Long> taskDefinitionCodes);
+}
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/mapper/UserLoginLogMapper.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/mapper/UserLoginLogMapper.java
index b5850ab0..1641f3d2 100644
--- a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/mapper/UserLoginLogMapper.java
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/mapper/UserLoginLogMapper.java
@@ -19,8 +19,10 @@ package org.apache.seatunnel.app.dal.mapper;
 
 import org.apache.seatunnel.app.dal.entity.UserLoginLog;
 
+import org.apache.ibatis.annotations.Mapper;
 import org.apache.ibatis.annotations.Param;
 
+@Mapper
 public interface UserLoginLogMapper {
     int insert(UserLoginLog userLoginLog);
 
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/mapper/UserMapper.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/mapper/UserMapper.java
index e270ade0..5d13b976 100644
--- a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/mapper/UserMapper.java
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/mapper/UserMapper.java
@@ -19,10 +19,12 @@ package org.apache.seatunnel.app.dal.mapper;
 
 import org.apache.seatunnel.app.dal.entity.User;
 
+import org.apache.ibatis.annotations.Mapper;
 import org.apache.ibatis.annotations.Param;
 
 import java.util.List;
 
+@Mapper
 public interface UserMapper {
     User selectByPrimaryKey(@Param("id") Integer id);
 
@@ -43,4 +45,6 @@ public interface UserMapper {
 
     User selectByNameAndPasswd(
             @Param("username") String username, @Param("password") String password);
+
+    List<User> queryEnabledUsers();
 }
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/mapper/UserMapper.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/mapper/VirtualTableMapper.java
similarity index 55%
copy from seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/mapper/UserMapper.java
copy to seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/mapper/VirtualTableMapper.java
index e270ade0..5111bc3e 100644
--- a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/mapper/UserMapper.java
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/dal/mapper/VirtualTableMapper.java
@@ -17,30 +17,24 @@
 
 package org.apache.seatunnel.app.dal.mapper;
 
-import org.apache.seatunnel.app.dal.entity.User;
+import org.apache.seatunnel.app.dal.entity.VirtualTable;
 
 import org.apache.ibatis.annotations.Param;
 
-import java.util.List;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
 
-public interface UserMapper {
-    User selectByPrimaryKey(@Param("id") Integer id);
+public interface VirtualTableMapper extends BaseMapper<VirtualTable> {
 
-    void insert(User user);
+    IPage<VirtualTable> selectPage(IPage<VirtualTable> page);
 
-    int updateByPrimaryKey(User user);
+    IPage<VirtualTable> selectVirtualTablePageByParam(
+            IPage<VirtualTable> page,
+            @Param("pluginName") String pluginName,
+            @Param("datasourceName") String datasourceName);
 
-    void deleteByPrimaryKey(@Param("id") int id);
-
-    List<User> selectBySelectiveAndPage(
-            @Param("user") User user, @Param("start") int start, @Param("offset") int offset);
-
-    void updateStatus(@Param("id") int id, @Param("status") byte status);
-
-    User selectByName(@Param("username") String username);
-
-    int countBySelective(@Param("user") User user);
-
-    User selectByNameAndPasswd(
-            @Param("username") String username, @Param("password") String password);
+    int checkVirtualTableNameUnique(
+            @Param("tableId") Long tableId,
+            @Param("virtualDatabaseName") String databaseName,
+            @Param("virtualTableName") String virtualTableName);
 }
diff --git a/seatunnel-datasource/seatunnel-datasource-plugins/datasource-plugins-api/src/main/java/org/apache/seatunnel/datasource/plugin/api/model/TableField.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/dto/datasource/DatabaseTableFields.java
similarity index 71%
copy from seatunnel-datasource/seatunnel-datasource-plugins/datasource-plugins-api/src/main/java/org/apache/seatunnel/datasource/plugin/api/model/TableField.java
copy to seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/dto/datasource/DatabaseTableFields.java
index fabcaf47..9a2a7015 100644
--- a/seatunnel-datasource/seatunnel-datasource-plugins/datasource-plugins-api/src/main/java/org/apache/seatunnel/datasource/plugin/api/model/TableField.java
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/dto/datasource/DatabaseTableFields.java
@@ -15,26 +15,20 @@
  * limitations under the License.
  */
 
-package org.apache.seatunnel.datasource.plugin.api.model;
+package org.apache.seatunnel.app.domain.dto.datasource;
 
+import lombok.AllArgsConstructor;
 import lombok.Data;
+import lombok.NoArgsConstructor;
 
-import java.util.Map;
+import java.util.List;
 
 @Data
-public class TableField {
+@NoArgsConstructor
+@AllArgsConstructor
+public class DatabaseTableFields {
 
-    private String type;
+    private String database;
 
-    private String name;
-
-    private String comment;
-
-    private Boolean primaryKey;
-
-    private String defaultValue;
-
-    private Boolean nullable;
-
-    private Map<String, String> properties;
+    private List<TableInfo> tableInfos;
 }
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/impl/MysqlDatasourceConfigSwitcher.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/dto/datasource/DatabaseTables.java
similarity index 72%
copy from seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/impl/MysqlDatasourceConfigSwitcher.java
copy to seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/dto/datasource/DatabaseTables.java
index 7da09161..40488238 100644
--- a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/impl/MysqlDatasourceConfigSwitcher.java
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/dto/datasource/DatabaseTables.java
@@ -15,10 +15,20 @@
  * limitations under the License.
  */
 
-package org.apache.seatunnel.app.thridparty.datasource.impl;
+package org.apache.seatunnel.app.domain.dto.datasource;
 
-public class MysqlDatasourceConfigSwitcher extends BaseJdbcDataSourceConfigSwitcher {
-    public static MysqlDatasourceConfigSwitcher INSTANCE = new MysqlDatasourceConfigSwitcher();
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
 
-    private MysqlDatasourceConfigSwitcher() {}
+import java.util.List;
+
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class DatabaseTables {
+
+    private String database;
+
+    private List<String> tables;
 }
diff --git a/seatunnel-datasource/seatunnel-datasource-plugins/datasource-plugins-api/src/main/java/org/apache/seatunnel/datasource/plugin/api/model/TableField.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/dto/datasource/TableInfo.java
similarity index 70%
copy from seatunnel-datasource/seatunnel-datasource-plugins/datasource-plugins-api/src/main/java/org/apache/seatunnel/datasource/plugin/api/model/TableField.java
copy to seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/dto/datasource/TableInfo.java
index fabcaf47..7314ce01 100644
--- a/seatunnel-datasource/seatunnel-datasource-plugins/datasource-plugins-api/src/main/java/org/apache/seatunnel/datasource/plugin/api/model/TableField.java
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/dto/datasource/TableInfo.java
@@ -15,26 +15,22 @@
  * limitations under the License.
  */
 
-package org.apache.seatunnel.datasource.plugin.api.model;
+package org.apache.seatunnel.app.domain.dto.datasource;
 
+import org.apache.seatunnel.datasource.plugin.api.model.TableField;
+
+import lombok.AllArgsConstructor;
 import lombok.Data;
+import lombok.NoArgsConstructor;
 
-import java.util.Map;
+import java.util.List;
 
 @Data
-public class TableField {
-
-    private String type;
-
-    private String name;
-
-    private String comment;
-
-    private Boolean primaryKey;
-
-    private String defaultValue;
+@NoArgsConstructor
+@AllArgsConstructor
+public class TableInfo {
 
-    private Boolean nullable;
+    private String tableName;
 
-    private Map<String, String> properties;
+    private List<TableField> fields;
 }
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/model/DateInterval.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/model/DateInterval.java
new file mode 100644
index 00000000..752197ad
--- /dev/null
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/model/DateInterval.java
@@ -0,0 +1,66 @@
+/*
+ * 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.seatunnel.app.domain.model;
+
+import java.util.Date;
+import java.util.Objects;
+
+/** date interval class */
+public class DateInterval {
+
+    private Date startTime;
+    private Date endTime;
+
+    public DateInterval(Date beginTime, Date endTime) {
+        this.startTime = beginTime;
+        this.endTime = endTime;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj == null || getClass() != obj.getClass()) {
+            return false;
+        } else if (this == obj) {
+            return true;
+        } else {
+            DateInterval that = (DateInterval) obj;
+            return startTime.equals(that.startTime) && endTime.equals(that.endTime);
+        }
+    }
+
+    public Date getStartTime() {
+        return startTime;
+    }
+
+    public void setStartTime(Date startTime) {
+        this.startTime = startTime;
+    }
+
+    public Date getEndTime() {
+        return endTime;
+    }
+
+    public void setEndTime(Date endTime) {
+        this.endTime = endTime;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(startTime, endTime);
+    }
+}
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/response/datasource/DatasourceRes.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/model/DependentItem.java
similarity index 58%
copy from seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/response/datasource/DatasourceRes.java
copy to seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/model/DependentItem.java
index b702a124..f9b2738e 100644
--- a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/response/datasource/DatasourceRes.java
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/model/DependentItem.java
@@ -15,30 +15,27 @@
  * limitations under the License.
  */
 
-package org.apache.seatunnel.app.domain.response.datasource;
+package org.apache.seatunnel.app.domain.model;
 
-import org.apache.seatunnel.app.domain.response.BaseInfo;
+import org.apache.seatunnel.app.common.DependResult;
+import org.apache.seatunnel.app.common.ExecutionStatus;
 
 import lombok.Data;
 
-import java.util.Map;
-
 @Data
-public class DatasourceRes extends BaseInfo {
-
-    private String id;
-
-    private String datasourceName;
-
-    private String pluginName;
-
-    private String pluginVersion;
-
-    private String description;
-
-    private Map<String, String> datasourceConfig;
-
-    private int createUserId;
-
-    private int updateUserId;
+public class DependentItem {
+
+    private long projectCode;
+    private long definitionCode;
+    private long depTaskCode;
+    private String timeType;
+    private String cycle;
+    private String dateValue;
+    private DependResult dependResult;
+    private ExecutionStatus status;
+
+    public String getKey() {
+        return String.format(
+                "%d-%d-%s-%s", getDefinitionCode(), getDepTaskCode(), getCycle(), getDateValue());
+    }
 }
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/impl/MysqlDatasourceConfigSwitcher.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/model/DependentTaskModel.java
similarity index 73%
copy from seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/impl/MysqlDatasourceConfigSwitcher.java
copy to seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/model/DependentTaskModel.java
index 7da09161..1d962097 100644
--- a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/impl/MysqlDatasourceConfigSwitcher.java
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/model/DependentTaskModel.java
@@ -15,10 +15,17 @@
  * limitations under the License.
  */
 
-package org.apache.seatunnel.app.thridparty.datasource.impl;
+package org.apache.seatunnel.app.domain.model;
 
-public class MysqlDatasourceConfigSwitcher extends BaseJdbcDataSourceConfigSwitcher {
-    public static MysqlDatasourceConfigSwitcher INSTANCE = new MysqlDatasourceConfigSwitcher();
+import org.apache.seatunnel.app.common.DependentRelation;
 
-    private MysqlDatasourceConfigSwitcher() {}
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class DependentTaskModel {
+
+    private List<DependentItem> dependItemList;
+    private DependentRelation relation;
 }
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/model/Property.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/model/Property.java
new file mode 100644
index 00000000..ed8f3ffa
--- /dev/null
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/model/Property.java
@@ -0,0 +1,138 @@
+/*
+ * 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.seatunnel.app.domain.model;
+
+import org.apache.seatunnel.app.common.DataType;
+import org.apache.seatunnel.app.common.Direct;
+
+import java.io.Serializable;
+import java.util.Objects;
+
+public class Property implements Serializable {
+
+    private static final long serialVersionUID = -4045513703397452451L;
+    /** key */
+    private String prop;
+
+    /** input/output */
+    private Direct direct;
+
+    /** data type */
+    private DataType type;
+
+    /** value */
+    private String value;
+
+    public Property() {}
+
+    public Property(String prop, Direct direct, DataType type, String value) {
+        this.prop = prop;
+        this.direct = direct;
+        this.type = type;
+        this.value = value;
+    }
+
+    /**
+     * getter method
+     *
+     * @return the prop
+     * @see Property#prop
+     */
+    public String getProp() {
+        return prop;
+    }
+
+    /**
+     * setter method
+     *
+     * @param prop the prop to set
+     * @see Property#prop
+     */
+    public void setProp(String prop) {
+        this.prop = prop;
+    }
+
+    /**
+     * getter method
+     *
+     * @return the value
+     * @see Property#value
+     */
+    public String getValue() {
+        return value;
+    }
+
+    /**
+     * setter method
+     *
+     * @param value the value to set
+     * @see Property#value
+     */
+    public void setValue(String value) {
+        this.value = value;
+    }
+
+    public Direct getDirect() {
+        return direct;
+    }
+
+    public void setDirect(Direct direct) {
+        this.direct = direct;
+    }
+
+    public DataType getType() {
+        return type;
+    }
+
+    public void setType(DataType type) {
+        this.type = type;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+        Property property = (Property) o;
+        return Objects.equals(prop, property.prop) && Objects.equals(value, property.value);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(prop, value);
+    }
+
+    @Override
+    public String toString() {
+        return "Property{"
+                + "prop='"
+                + prop
+                + '\''
+                + ", direct="
+                + direct
+                + ", type="
+                + type
+                + ", value='"
+                + value
+                + '\''
+                + '}';
+    }
+}
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/impl/MysqlDatasourceConfigSwitcher.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/model/ResourceInfo.java
similarity index 73%
copy from seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/impl/MysqlDatasourceConfigSwitcher.java
copy to seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/model/ResourceInfo.java
index 7da09161..13aa349f 100644
--- a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/impl/MysqlDatasourceConfigSwitcher.java
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/model/ResourceInfo.java
@@ -15,10 +15,18 @@
  * limitations under the License.
  */
 
-package org.apache.seatunnel.app.thridparty.datasource.impl;
+package org.apache.seatunnel.app.domain.model;
 
-public class MysqlDatasourceConfigSwitcher extends BaseJdbcDataSourceConfigSwitcher {
-    public static MysqlDatasourceConfigSwitcher INSTANCE = new MysqlDatasourceConfigSwitcher();
+import lombok.Data;
 
-    private MysqlDatasourceConfigSwitcher() {}
+@Data
+public class ResourceInfo {
+
+    /** res the name of the resource that was uploaded */
+    private int id;
+
+    /** full name of the resource that was uploaded */
+    private String resourceName;
+
+    private String res;
 }
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/impl/MysqlDatasourceConfigSwitcher.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/request/connector/ConnectorStatus.java
similarity index 73%
copy from seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/impl/MysqlDatasourceConfigSwitcher.java
copy to seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/request/connector/ConnectorStatus.java
index 7da09161..3fb95bc7 100644
--- a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/impl/MysqlDatasourceConfigSwitcher.java
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/request/connector/ConnectorStatus.java
@@ -15,10 +15,10 @@
  * limitations under the License.
  */
 
-package org.apache.seatunnel.app.thridparty.datasource.impl;
+package org.apache.seatunnel.app.domain.request.connector;
 
-public class MysqlDatasourceConfigSwitcher extends BaseJdbcDataSourceConfigSwitcher {
-    public static MysqlDatasourceConfigSwitcher INSTANCE = new MysqlDatasourceConfigSwitcher();
-
-    private MysqlDatasourceConfigSwitcher() {}
+public enum ConnectorStatus {
+    DOWNLOADED,
+    NOT_DOWNLOAD,
+    ALL
 }
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/impl/MysqlDatasourceConfigSwitcher.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/request/connector/SceneMode.java
similarity index 73%
copy from seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/impl/MysqlDatasourceConfigSwitcher.java
copy to seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/request/connector/SceneMode.java
index 7da09161..7673664c 100644
--- a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/impl/MysqlDatasourceConfigSwitcher.java
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/request/connector/SceneMode.java
@@ -15,10 +15,12 @@
  * limitations under the License.
  */
 
-package org.apache.seatunnel.app.thridparty.datasource.impl;
+package org.apache.seatunnel.app.domain.request.connector;
 
-public class MysqlDatasourceConfigSwitcher extends BaseJdbcDataSourceConfigSwitcher {
-    public static MysqlDatasourceConfigSwitcher INSTANCE = new MysqlDatasourceConfigSwitcher();
+public enum SceneMode {
+    SINGLE_TABLE,
 
-    private MysqlDatasourceConfigSwitcher() {}
+    MULTIPLE_TABLE,
+
+    SPLIT_TABLE;
 }
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/request/datasource/VirtualTableFieldReq.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/request/datasource/VirtualTableFieldReq.java
new file mode 100644
index 00000000..028ad802
--- /dev/null
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/request/datasource/VirtualTableFieldReq.java
@@ -0,0 +1,60 @@
+/*
+ * 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.seatunnel.app.domain.request.datasource;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+@Data
+@ApiModel(value = "Virtual Table Field Request", description = "create ")
+public class VirtualTableFieldReq {
+
+    @ApiModelProperty(value = "field name", required = true, dataType = "String")
+    private String fieldName;
+
+    @ApiModelProperty(
+            value = "field type",
+            required = true,
+            dataType = "String",
+            example = "varchar")
+    private String fieldType;
+
+    @ApiModelProperty(
+            value = "field length",
+            dataType = "Boolean",
+            example = "true",
+            notes = "default false")
+    private Boolean nullable;
+
+    @ApiModelProperty(value = "field default value", dataType = "String", example = "10")
+    private String defaultValue;
+
+    @ApiModelProperty(
+            value = "primary key",
+            dataType = "Boolean",
+            example = "true",
+            notes = "default false, only one field can be primary key")
+    private Boolean primaryKey;
+
+    @ApiModelProperty(value = "field comment", dataType = "String", example = "this is a comment")
+    private String fieldComment;
+
+    @ApiModelProperty(value = "field extra", dataType = "String", example = "this is a extra")
+    private String fieldExtra;
+}
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/request/datasource/VirtualTableReq.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/request/datasource/VirtualTableReq.java
new file mode 100644
index 00000000..79a937fe
--- /dev/null
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/request/datasource/VirtualTableReq.java
@@ -0,0 +1,48 @@
+/*
+ * 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.seatunnel.app.domain.request.datasource;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.util.List;
+import java.util.Map;
+
+@Data
+@ApiModel(value = "VirtualTable Request", description = "virtual table info")
+public class VirtualTableReq {
+
+    @ApiModelProperty(value = "datasource id", required = true, dataType = "String")
+    private String datasourceId;
+
+    @ApiModelProperty(value = "database name", required = true, dataType = "String")
+    private String databaseName;
+
+    @ApiModelProperty(value = "table name", required = true, dataType = "String")
+    private String tableName;
+
+    @ApiModelProperty(value = "table description", dataType = "String")
+    private String description;
+
+    @ApiModelProperty(value = "table properties", dataType = "Map")
+    private Map<String, String> databaseProperties;
+
+    @ApiModelProperty(value = "table fields", dataType = "List")
+    private List<VirtualTableFieldReq> tableFields;
+}
diff --git a/seatunnel-datasource/seatunnel-datasource-plugins/datasource-plugins-api/src/main/java/org/apache/seatunnel/datasource/plugin/api/model/TableField.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/request/job/JobConfig.java
similarity index 76%
copy from seatunnel-datasource/seatunnel-datasource-plugins/datasource-plugins-api/src/main/java/org/apache/seatunnel/datasource/plugin/api/model/TableField.java
copy to seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/request/job/JobConfig.java
index fabcaf47..62e81196 100644
--- a/seatunnel-datasource/seatunnel-datasource-plugins/datasource-plugins-api/src/main/java/org/apache/seatunnel/datasource/plugin/api/model/TableField.java
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/request/job/JobConfig.java
@@ -15,26 +15,22 @@
  * limitations under the License.
  */
 
-package org.apache.seatunnel.datasource.plugin.api.model;
+package org.apache.seatunnel.app.domain.request.job;
+
+import org.apache.seatunnel.app.common.EngineType;
 
 import lombok.Data;
 
 import java.util.Map;
 
 @Data
-public class TableField {
-
-    private String type;
+public class JobConfig {
 
     private String name;
 
-    private String comment;
-
-    private Boolean primaryKey;
-
-    private String defaultValue;
+    private String description;
 
-    private Boolean nullable;
+    private Map<String, Object> env;
 
-    private Map<String, String> properties;
+    private EngineType engine;
 }
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/response/datasource/DatasourceRes.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/request/job/JobReq.java
similarity index 56%
copy from seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/response/datasource/DatasourceRes.java
copy to seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/request/job/JobReq.java
index b702a124..b6bbe5ce 100644
--- a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/response/datasource/DatasourceRes.java
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/request/job/JobReq.java
@@ -15,30 +15,26 @@
  * limitations under the License.
  */
 
-package org.apache.seatunnel.app.domain.response.datasource;
+package org.apache.seatunnel.app.domain.request.job;
 
-import org.apache.seatunnel.app.domain.response.BaseInfo;
+import org.apache.seatunnel.app.domain.request.connector.BusinessMode;
 
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 
-import java.util.Map;
-
 @Data
-public class DatasourceRes extends BaseInfo {
-
-    private String id;
-
-    private String datasourceName;
-
-    private String pluginName;
-
-    private String pluginVersion;
+@ApiModel(value = "JobDefinition Request", description = "job info")
+public class JobReq {
+    @ApiModelProperty(value = "job name", required = true, dataType = "String")
+    private String name;
 
+    @ApiModelProperty(value = "job description", dataType = "String")
     private String description;
 
-    private Map<String, String> datasourceConfig;
-
-    private int createUserId;
+    @ApiModelProperty(value = "job type", dataType = "String")
+    private BusinessMode jobType;
 
-    private int updateUserId;
+    @ApiModelProperty(value = "project code", dataType = "Long")
+    private Long projectCode;
 }
diff --git a/seatunnel-datasource/seatunnel-datasource-plugins/datasource-plugins-api/src/main/java/org/apache/seatunnel/datasource/plugin/api/model/TableField.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/request/job/TableSchemaReq.java
similarity index 70%
copy from seatunnel-datasource/seatunnel-datasource-plugins/datasource-plugins-api/src/main/java/org/apache/seatunnel/datasource/plugin/api/model/TableField.java
copy to seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/request/job/TableSchemaReq.java
index fabcaf47..f33d79d5 100644
--- a/seatunnel-datasource/seatunnel-datasource-plugins/datasource-plugins-api/src/main/java/org/apache/seatunnel/datasource/plugin/api/model/TableField.java
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/request/job/TableSchemaReq.java
@@ -15,26 +15,21 @@
  * limitations under the License.
  */
 
-package org.apache.seatunnel.datasource.plugin.api.model;
+package org.apache.seatunnel.app.domain.request.job;
 
+import org.apache.seatunnel.datasource.plugin.api.model.TableField;
+
+import lombok.AllArgsConstructor;
 import lombok.Data;
+import lombok.NoArgsConstructor;
 
-import java.util.Map;
+import java.util.List;
 
 @Data
-public class TableField {
-
-    private String type;
-
-    private String name;
-
-    private String comment;
-
-    private Boolean primaryKey;
-
-    private String defaultValue;
-
-    private Boolean nullable;
+@AllArgsConstructor
+@NoArgsConstructor
+public class TableSchemaReq {
 
-    private Map<String, String> properties;
+    private String tableName;
+    private List<TableField> fields;
 }
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/impl/MysqlDatasourceConfigSwitcher.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/request/job/transform/ChangeOrder.java
similarity index 73%
copy from seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/impl/MysqlDatasourceConfigSwitcher.java
copy to seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/request/job/transform/ChangeOrder.java
index 7da09161..d0bf19bd 100644
--- a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/impl/MysqlDatasourceConfigSwitcher.java
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/request/job/transform/ChangeOrder.java
@@ -15,10 +15,14 @@
  * limitations under the License.
  */
 
-package org.apache.seatunnel.app.thridparty.datasource.impl;
+package org.apache.seatunnel.app.domain.request.job.transform;
 
-public class MysqlDatasourceConfigSwitcher extends BaseJdbcDataSourceConfigSwitcher {
-    public static MysqlDatasourceConfigSwitcher INSTANCE = new MysqlDatasourceConfigSwitcher();
+import lombok.Data;
+import lombok.EqualsAndHashCode;
 
-    private MysqlDatasourceConfigSwitcher() {}
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class ChangeOrder extends TransformOption {
+
+    private int index;
 }
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/impl/MysqlDatasourceConfigSwitcher.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/request/job/transform/Copy.java
similarity index 73%
copy from seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/impl/MysqlDatasourceConfigSwitcher.java
copy to seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/request/job/transform/Copy.java
index 7da09161..75a95229 100644
--- a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/impl/MysqlDatasourceConfigSwitcher.java
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/request/job/transform/Copy.java
@@ -15,10 +15,14 @@
  * limitations under the License.
  */
 
-package org.apache.seatunnel.app.thridparty.datasource.impl;
+package org.apache.seatunnel.app.domain.request.job.transform;
 
-public class MysqlDatasourceConfigSwitcher extends BaseJdbcDataSourceConfigSwitcher {
-    public static MysqlDatasourceConfigSwitcher INSTANCE = new MysqlDatasourceConfigSwitcher();
+import lombok.Data;
+import lombok.EqualsAndHashCode;
 
-    private MysqlDatasourceConfigSwitcher() {}
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class Copy extends TransformOption {
+
+    private String targetFieldName;
 }
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/impl/MysqlDatasourceConfigSwitcher.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/request/job/transform/CopyTransformOptions.java
similarity index 73%
copy from seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/impl/MysqlDatasourceConfigSwitcher.java
copy to seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/request/job/transform/CopyTransformOptions.java
index 7da09161..20c03baf 100644
--- a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/impl/MysqlDatasourceConfigSwitcher.java
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/request/job/transform/CopyTransformOptions.java
@@ -15,10 +15,14 @@
  * limitations under the License.
  */
 
-package org.apache.seatunnel.app.thridparty.datasource.impl;
+package org.apache.seatunnel.app.domain.request.job.transform;
 
-public class MysqlDatasourceConfigSwitcher extends BaseJdbcDataSourceConfigSwitcher {
-    public static MysqlDatasourceConfigSwitcher INSTANCE = new MysqlDatasourceConfigSwitcher();
+import lombok.Data;
 
-    private MysqlDatasourceConfigSwitcher() {}
+import java.util.List;
+
+@Data
+public class CopyTransformOptions implements TransformOptions {
+
+    private List<Copy> copyList;
 }
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/impl/MysqlDatasourceConfigSwitcher.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/request/job/transform/DeleteField.java
similarity index 73%
copy from seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/impl/MysqlDatasourceConfigSwitcher.java
copy to seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/request/job/transform/DeleteField.java
index 7da09161..cdc1db5d 100644
--- a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/impl/MysqlDatasourceConfigSwitcher.java
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/request/job/transform/DeleteField.java
@@ -15,10 +15,11 @@
  * limitations under the License.
  */
 
-package org.apache.seatunnel.app.thridparty.datasource.impl;
+package org.apache.seatunnel.app.domain.request.job.transform;
 
-public class MysqlDatasourceConfigSwitcher extends BaseJdbcDataSourceConfigSwitcher {
-    public static MysqlDatasourceConfigSwitcher INSTANCE = new MysqlDatasourceConfigSwitcher();
+import lombok.Data;
+import lombok.EqualsAndHashCode;
 
-    private MysqlDatasourceConfigSwitcher() {}
-}
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class DeleteField extends TransformOption {}
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/impl/MysqlDatasourceConfigSwitcher.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/request/job/transform/FieldMapperTransformOptions.java
similarity index 73%
copy from seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/impl/MysqlDatasourceConfigSwitcher.java
copy to seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/request/job/transform/FieldMapperTransformOptions.java
index 7da09161..a5462fd0 100644
--- a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/impl/MysqlDatasourceConfigSwitcher.java
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/request/job/transform/FieldMapperTransformOptions.java
@@ -15,10 +15,16 @@
  * limitations under the License.
  */
 
-package org.apache.seatunnel.app.thridparty.datasource.impl;
+package org.apache.seatunnel.app.domain.request.job.transform;
 
-public class MysqlDatasourceConfigSwitcher extends BaseJdbcDataSourceConfigSwitcher {
-    public static MysqlDatasourceConfigSwitcher INSTANCE = new MysqlDatasourceConfigSwitcher();
+import lombok.Data;
 
-    private MysqlDatasourceConfigSwitcher() {}
+import java.util.List;
+
+@Data
+public class FieldMapperTransformOptions implements TransformOptions {
+
+    List<ChangeOrder> changeOrders;
+    List<RenameField> renameFields;
+    List<DeleteField> deleteFields;
 }
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/impl/MysqlDatasourceConfigSwitcher.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/request/job/transform/RenameField.java
similarity index 73%
copy from seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/impl/MysqlDatasourceConfigSwitcher.java
copy to seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/request/job/transform/RenameField.java
index 7da09161..650ccf7e 100644
--- a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/impl/MysqlDatasourceConfigSwitcher.java
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/request/job/transform/RenameField.java
@@ -15,10 +15,14 @@
  * limitations under the License.
  */
 
-package org.apache.seatunnel.app.thridparty.datasource.impl;
+package org.apache.seatunnel.app.domain.request.job.transform;
 
-public class MysqlDatasourceConfigSwitcher extends BaseJdbcDataSourceConfigSwitcher {
-    public static MysqlDatasourceConfigSwitcher INSTANCE = new MysqlDatasourceConfigSwitcher();
+import lombok.Data;
+import lombok.EqualsAndHashCode;
 
-    private MysqlDatasourceConfigSwitcher() {}
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class RenameField extends TransformOption {
+
+    private String targetName;
 }
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/impl/MysqlDatasourceConfigSwitcher.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/request/job/transform/Split.java
similarity index 72%
copy from seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/impl/MysqlDatasourceConfigSwitcher.java
copy to seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/request/job/transform/Split.java
index 7da09161..41ebf96e 100644
--- a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/impl/MysqlDatasourceConfigSwitcher.java
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/request/job/transform/Split.java
@@ -15,10 +15,18 @@
  * limitations under the License.
  */
 
-package org.apache.seatunnel.app.thridparty.datasource.impl;
+package org.apache.seatunnel.app.domain.request.job.transform;
 
-public class MysqlDatasourceConfigSwitcher extends BaseJdbcDataSourceConfigSwitcher {
-    public static MysqlDatasourceConfigSwitcher INSTANCE = new MysqlDatasourceConfigSwitcher();
+import lombok.Data;
+import lombok.EqualsAndHashCode;
 
-    private MysqlDatasourceConfigSwitcher() {}
+import java.util.List;
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class Split extends TransformOption {
+
+    private String separator;
+
+    private List<String> outputFields;
 }
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/impl/MysqlDatasourceConfigSwitcher.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/request/job/transform/SplitTransformOptions.java
similarity index 73%
copy from seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/impl/MysqlDatasourceConfigSwitcher.java
copy to seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/request/job/transform/SplitTransformOptions.java
index 7da09161..c345f866 100644
--- a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/impl/MysqlDatasourceConfigSwitcher.java
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/request/job/transform/SplitTransformOptions.java
@@ -15,10 +15,14 @@
  * limitations under the License.
  */
 
-package org.apache.seatunnel.app.thridparty.datasource.impl;
+package org.apache.seatunnel.app.domain.request.job.transform;
 
-public class MysqlDatasourceConfigSwitcher extends BaseJdbcDataSourceConfigSwitcher {
-    public static MysqlDatasourceConfigSwitcher INSTANCE = new MysqlDatasourceConfigSwitcher();
+import lombok.Data;
 
-    private MysqlDatasourceConfigSwitcher() {}
+import java.util.List;
+
+@Data
+public class SplitTransformOptions implements TransformOptions {
+
+    List<Split> splits;
 }
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/impl/MysqlDatasourceConfigSwitcher.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/request/job/transform/Transform.java
similarity index 73%
copy from seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/impl/MysqlDatasourceConfigSwitcher.java
copy to seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/request/job/transform/Transform.java
index 7da09161..769387c2 100644
--- a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/impl/MysqlDatasourceConfigSwitcher.java
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/request/job/transform/Transform.java
@@ -15,10 +15,12 @@
  * limitations under the License.
  */
 
-package org.apache.seatunnel.app.thridparty.datasource.impl;
+package org.apache.seatunnel.app.domain.request.job.transform;
 
-public class MysqlDatasourceConfigSwitcher extends BaseJdbcDataSourceConfigSwitcher {
-    public static MysqlDatasourceConfigSwitcher INSTANCE = new MysqlDatasourceConfigSwitcher();
-
-    private MysqlDatasourceConfigSwitcher() {}
+public enum Transform {
+    REPLACE,
+    COPY,
+    SPLIT,
+    FIELDMAPPER,
+    FILTERROWKIND
 }
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/impl/MysqlDatasourceConfigSwitcher.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/request/job/transform/TransformOption.java
similarity index 73%
copy from seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/impl/MysqlDatasourceConfigSwitcher.java
copy to seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/request/job/transform/TransformOption.java
index 7da09161..07c0d98c 100644
--- a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/impl/MysqlDatasourceConfigSwitcher.java
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/request/job/transform/TransformOption.java
@@ -15,10 +15,12 @@
  * limitations under the License.
  */
 
-package org.apache.seatunnel.app.thridparty.datasource.impl;
+package org.apache.seatunnel.app.domain.request.job.transform;
 
-public class MysqlDatasourceConfigSwitcher extends BaseJdbcDataSourceConfigSwitcher {
-    public static MysqlDatasourceConfigSwitcher INSTANCE = new MysqlDatasourceConfigSwitcher();
+import lombok.Data;
 
-    private MysqlDatasourceConfigSwitcher() {}
+@Data
+public abstract class TransformOption {
+
+    private String sourceFieldName;
 }
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/impl/MysqlDatasourceConfigSwitcher.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/request/job/transform/TransformOptions.java
similarity index 73%
copy from seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/impl/MysqlDatasourceConfigSwitcher.java
copy to seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/request/job/transform/TransformOptions.java
index 7da09161..c167a302 100644
--- a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/impl/MysqlDatasourceConfigSwitcher.java
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/request/job/transform/TransformOptions.java
@@ -15,10 +15,6 @@
  * limitations under the License.
  */
 
-package org.apache.seatunnel.app.thridparty.datasource.impl;
+package org.apache.seatunnel.app.domain.request.job.transform;
 
-public class MysqlDatasourceConfigSwitcher extends BaseJdbcDataSourceConfigSwitcher {
-    public static MysqlDatasourceConfigSwitcher INSTANCE = new MysqlDatasourceConfigSwitcher();
-
-    private MysqlDatasourceConfigSwitcher() {}
-}
+public interface TransformOptions {}
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/response/datasource/DatasourceRes.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/response/datasource/DatasourceRes.java
index b702a124..f0c2ee74 100644
--- a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/response/datasource/DatasourceRes.java
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/response/datasource/DatasourceRes.java
@@ -21,6 +21,7 @@ import org.apache.seatunnel.app.domain.response.BaseInfo;
 
 import lombok.Data;
 
+import java.util.Date;
 import java.util.Map;
 
 @Data
@@ -36,9 +37,17 @@ public class DatasourceRes extends BaseInfo {
 
     private String description;
 
+    private String createUserName;
+
+    private String updateUserName;
+
     private Map<String, String> datasourceConfig;
 
     private int createUserId;
 
     private int updateUserId;
+
+    private Date createTime;
+
+    private Date updateTime;
 }
diff --git a/seatunnel-datasource/seatunnel-datasource-plugins/datasource-plugins-api/src/main/java/org/apache/seatunnel/datasource/plugin/api/model/TableField.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/response/job/JobConfigRes.java
similarity index 76%
copy from seatunnel-datasource/seatunnel-datasource-plugins/datasource-plugins-api/src/main/java/org/apache/seatunnel/datasource/plugin/api/model/TableField.java
copy to seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/response/job/JobConfigRes.java
index fabcaf47..896bb31f 100644
--- a/seatunnel-datasource/seatunnel-datasource-plugins/datasource-plugins-api/src/main/java/org/apache/seatunnel/datasource/plugin/api/model/TableField.java
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/response/job/JobConfigRes.java
@@ -15,26 +15,24 @@
  * limitations under the License.
  */
 
-package org.apache.seatunnel.datasource.plugin.api.model;
+package org.apache.seatunnel.app.domain.response.job;
+
+import org.apache.seatunnel.app.common.EngineType;
 
 import lombok.Data;
 
 import java.util.Map;
 
 @Data
-public class TableField {
+public class JobConfigRes {
 
-    private String type;
+    private long id;
 
     private String name;
 
-    private String comment;
-
-    private Boolean primaryKey;
-
-    private String defaultValue;
+    private String description;
 
-    private Boolean nullable;
+    private Map<String, Object> env;
 
-    private Map<String, String> properties;
+    private EngineType engine;
 }
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/response/job/JobDefinitionRes.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/response/job/JobDefinitionRes.java
new file mode 100644
index 00000000..a8013432
--- /dev/null
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/response/job/JobDefinitionRes.java
@@ -0,0 +1,64 @@
+/*
+ * 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.seatunnel.app.domain.response.job;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.util.Date;
+
+@ApiModel(value = "jobDefinitionResponse", description = "job definition response")
+@Data
+public class JobDefinitionRes {
+    @ApiModelProperty(value = "job definition id", dataType = "Long")
+    private long id;
+
+    @ApiModelProperty(value = "job name", dataType = "String")
+    private String name;
+
+    @ApiModelProperty(value = "job description", dataType = "String")
+    private String description;
+
+    @ApiModelProperty(value = "job type", dataType = "String")
+    private String jobType;
+
+    @ApiModelProperty(value = "create user id", dataType = "Integer")
+    private int createUserId;
+
+    @ApiModelProperty(value = "update user id", dataType = "Integer")
+    private int updateUserId;
+
+    @ApiModelProperty(value = "create user name", dataType = "String")
+    private String createUserName;
+
+    @ApiModelProperty(value = "update user name", dataType = "String")
+    private String updateUserName;
+
+    @ApiModelProperty(value = "job create time", dataType = "String")
+    private Date createTime;
+
+    @ApiModelProperty(value = "job update time", dataType = "String")
+    private Date updateTime;
+
+    @ApiModelProperty(value = "project code", dataType = "Long")
+    private long projectCode;
+
+    @ApiModelProperty(value = "project name", dataType = "String")
+    private String projectName;
+}
diff --git a/seatunnel-datasource/seatunnel-datasource-plugins/datasource-plugins-api/src/main/java/org/apache/seatunnel/datasource/plugin/api/model/TableField.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/response/job/JobTaskCheckRes.java
similarity index 71%
copy from seatunnel-datasource/seatunnel-datasource-plugins/datasource-plugins-api/src/main/java/org/apache/seatunnel/datasource/plugin/api/model/TableField.java
copy to seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/response/job/JobTaskCheckRes.java
index fabcaf47..6030e685 100644
--- a/seatunnel-datasource/seatunnel-datasource-plugins/datasource-plugins-api/src/main/java/org/apache/seatunnel/datasource/plugin/api/model/TableField.java
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/response/job/JobTaskCheckRes.java
@@ -15,26 +15,22 @@
  * limitations under the License.
  */
 
-package org.apache.seatunnel.datasource.plugin.api.model;
+package org.apache.seatunnel.app.domain.response.job;
 
+import lombok.AllArgsConstructor;
 import lombok.Data;
-
-import java.util.Map;
+import lombok.NoArgsConstructor;
 
 @Data
-public class TableField {
-
-    private String type;
-
-    private String name;
-
-    private String comment;
+@AllArgsConstructor
+@NoArgsConstructor
+public class JobTaskCheckRes {
 
-    private Boolean primaryKey;
+    private boolean global;
 
-    private String defaultValue;
+    private String pluginId;
 
-    private Boolean nullable;
+    private SchemaError schemaError;
 
-    private Map<String, String> properties;
+    private String normalError;
 }
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/impl/MysqlDatasourceConfigSwitcher.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/response/job/SchemaError.java
similarity index 73%
copy from seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/impl/MysqlDatasourceConfigSwitcher.java
copy to seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/response/job/SchemaError.java
index 7da09161..69485687 100644
--- a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/impl/MysqlDatasourceConfigSwitcher.java
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/response/job/SchemaError.java
@@ -15,10 +15,20 @@
  * limitations under the License.
  */
 
-package org.apache.seatunnel.app.thridparty.datasource.impl;
+package org.apache.seatunnel.app.domain.response.job;
 
-public class MysqlDatasourceConfigSwitcher extends BaseJdbcDataSourceConfigSwitcher {
-    public static MysqlDatasourceConfigSwitcher INSTANCE = new MysqlDatasourceConfigSwitcher();
+import lombok.AllArgsConstructor;
+import lombok.Data;
 
-    private MysqlDatasourceConfigSwitcher() {}
+@Data
+@AllArgsConstructor
+public class SchemaError {
+
+    private String database;
+
+    private String tableName;
+
+    private String fieldName;
+
+    private SchemaErrorType errorType;
 }
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/impl/MysqlDatasourceConfigSwitcher.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/response/job/SchemaErrorType.java
similarity index 73%
copy from seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/impl/MysqlDatasourceConfigSwitcher.java
copy to seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/response/job/SchemaErrorType.java
index 7da09161..c901daab 100644
--- a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/impl/MysqlDatasourceConfigSwitcher.java
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/response/job/SchemaErrorType.java
@@ -15,10 +15,8 @@
  * limitations under the License.
  */
 
-package org.apache.seatunnel.app.thridparty.datasource.impl;
+package org.apache.seatunnel.app.domain.response.job;
 
-public class MysqlDatasourceConfigSwitcher extends BaseJdbcDataSourceConfigSwitcher {
-    public static MysqlDatasourceConfigSwitcher INSTANCE = new MysqlDatasourceConfigSwitcher();
-
-    private MysqlDatasourceConfigSwitcher() {}
+public enum SchemaErrorType {
+    MISS_FIELD;
 }
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/impl/MysqlDatasourceConfigSwitcher.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/response/job/TableSchemaRes.java
similarity index 72%
copy from seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/impl/MysqlDatasourceConfigSwitcher.java
copy to seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/response/job/TableSchemaRes.java
index 7da09161..dbaca0ae 100644
--- a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/impl/MysqlDatasourceConfigSwitcher.java
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/response/job/TableSchemaRes.java
@@ -15,10 +15,18 @@
  * limitations under the License.
  */
 
-package org.apache.seatunnel.app.thridparty.datasource.impl;
+package org.apache.seatunnel.app.domain.response.job;
 
-public class MysqlDatasourceConfigSwitcher extends BaseJdbcDataSourceConfigSwitcher {
-    public static MysqlDatasourceConfigSwitcher INSTANCE = new MysqlDatasourceConfigSwitcher();
+import org.apache.seatunnel.datasource.plugin.api.model.TableField;
 
-    private MysqlDatasourceConfigSwitcher() {}
+import lombok.Data;
+import lombok.RequiredArgsConstructor;
+
+import java.util.List;
+
+@Data
+@RequiredArgsConstructor
+public class TableSchemaRes {
+
+    private List<TableField> fields;
 }
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/interceptor/AuthenticationInterceptor.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/interceptor/AuthenticationInterceptor.java
index b76de658..23948a95 100644
--- a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/interceptor/AuthenticationInterceptor.java
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/interceptor/AuthenticationInterceptor.java
@@ -17,7 +17,9 @@
 
 package org.apache.seatunnel.app.interceptor;
 
+import org.apache.seatunnel.app.common.Constants;
 import org.apache.seatunnel.app.dal.dao.IUserDao;
+import org.apache.seatunnel.app.dal.entity.User;
 import org.apache.seatunnel.app.dal.entity.UserLoginLog;
 import org.apache.seatunnel.app.security.JwtUtils;
 
@@ -91,7 +93,12 @@ public class AuthenticationInterceptor implements HandlerInterceptor {
         }
 
         map.forEach(request::setAttribute);
-
+        User user = new User();
+        user.setUsername((String) map.get("name"));
+        user.setId((Integer) map.get("id"));
+        //        user.setStatus((Byte) map.get("status"));
+        //        user.setType((Byte) map.get("type"));
+        request.setAttribute(Constants.SESSION_USER, user);
         return true;
     }
 
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/parameters/AbstractParameters.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/parameters/AbstractParameters.java
new file mode 100644
index 00000000..a76e06ba
--- /dev/null
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/parameters/AbstractParameters.java
@@ -0,0 +1,202 @@
+/*
+ * 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.seatunnel.app.parameters;
+
+import org.apache.seatunnel.app.common.Direct;
+import org.apache.seatunnel.app.domain.model.Property;
+import org.apache.seatunnel.app.domain.model.ResourceInfo;
+import org.apache.seatunnel.app.parameters.resource.ResourceParametersHelper;
+import org.apache.seatunnel.app.utils.JSONUtils;
+
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.lang3.StringUtils;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+
+/** job params related class */
+public abstract class AbstractParameters implements IParameters {
+
+    @Override
+    public abstract boolean checkParameters();
+
+    @Override
+    public List<ResourceInfo> getResourceFilesList() {
+        return new ArrayList<>();
+    }
+
+    /** local parameters */
+    public List<Property> localParams;
+
+    /** var pool */
+    public List<Property> varPool;
+
+    /**
+     * get local parameters list
+     *
+     * @return Property list
+     */
+    public List<Property> getLocalParams() {
+        return localParams;
+    }
+
+    public void setLocalParams(List<Property> localParams) {
+        this.localParams = localParams;
+    }
+
+    /**
+     * get local parameters map
+     *
+     * @return parameters map
+     */
+    public Map<String, Property> getLocalParametersMap() {
+        Map<String, Property> localParametersMaps = new LinkedHashMap<>();
+        if (localParams != null) {
+            for (Property property : localParams) {
+                localParametersMaps.put(property.getProp(), property);
+            }
+        }
+        return localParametersMaps;
+    }
+
+    /**
+     * get input local parameters map if the param direct is IN
+     *
+     * @return parameters map
+     */
+    public Map<String, Property> getInputLocalParametersMap() {
+        Map<String, Property> localParametersMaps = new LinkedHashMap<>();
+        if (localParams != null) {
+            for (Property property : localParams) {
+                if (Objects.equals(Direct.IN, property.getDirect())) {
+                    localParametersMaps.put(property.getProp(), property);
+                }
+            }
+        }
+        return localParametersMaps;
+    }
+
+    /**
+     * get varPool map
+     *
+     * @return parameters map
+     */
+    public Map<String, Property> getVarPoolMap() {
+        Map<String, Property> varPoolMap = new LinkedHashMap<>();
+        if (varPool != null) {
+            for (Property property : varPool) {
+                varPoolMap.put(property.getProp(), property);
+            }
+        }
+        return varPoolMap;
+    }
+
+    public List<Property> getVarPool() {
+        return varPool;
+    }
+
+    public void setVarPool(String varPool) {
+        if (StringUtils.isEmpty(varPool)) {
+            this.varPool = new ArrayList<>();
+        } else {
+            this.varPool = JSONUtils.toList(varPool, Property.class);
+        }
+    }
+
+    public void dealOutParam(String result) {
+        if (CollectionUtils.isEmpty(localParams)) {
+            return;
+        }
+        List<Property> outProperty = getOutProperty(localParams);
+        if (CollectionUtils.isEmpty(outProperty)) {
+            return;
+        }
+        if (StringUtils.isEmpty(result)) {
+            varPool.addAll(outProperty);
+            return;
+        }
+        Map<String, String> taskResult = getMapByString(result);
+        if (taskResult.size() == 0) {
+            return;
+        }
+        for (Property info : outProperty) {
+            String propValue = taskResult.get(info.getProp());
+            if (StringUtils.isNotEmpty(propValue)) {
+                info.setValue(propValue);
+                addPropertyToValPool(info);
+            }
+        }
+    }
+
+    public List<Property> getOutProperty(List<Property> params) {
+        if (CollectionUtils.isEmpty(params)) {
+            return new ArrayList<>();
+        }
+        List<Property> result = new ArrayList<>();
+        for (Property info : params) {
+            if (info.getDirect() == Direct.OUT) {
+                result.add(info);
+            }
+        }
+        return result;
+    }
+
+    public List<Map<String, String>> getListMapByString(String json) {
+        List<Map<String, String>> allParams = new ArrayList<>();
+        ArrayNode paramsByJson = JSONUtils.parseArray(json);
+        for (JsonNode jsonNode : paramsByJson) {
+            Map<String, String> param = JSONUtils.toMap(jsonNode.toString());
+            allParams.add(param);
+        }
+        return allParams;
+    }
+
+    /**
+     * shell's result format is key=value$VarPool$key=value$VarPool$
+     *
+     * @param result
+     * @return
+     */
+    public static Map<String, String> getMapByString(String result) {
+        String[] formatResult = result.split("\\$VarPool\\$");
+        Map<String, String> format = new HashMap<>();
+        for (String info : formatResult) {
+            if (StringUtils.isNotEmpty(info) && info.contains("=")) {
+                String[] keyValue = info.split("=");
+                format.put(keyValue[0], keyValue[1]);
+            }
+        }
+        return format;
+    }
+
+    public ResourceParametersHelper getResources() {
+        return new ResourceParametersHelper();
+    }
+
+    public void addPropertyToValPool(Property property) {
+        varPool.removeIf(p -> p.getProp().equals(property.getProp()));
+        varPool.add(property);
+    }
+}
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/response/datasource/DatasourceRes.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/parameters/DependentParameters.java
similarity index 61%
copy from seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/response/datasource/DatasourceRes.java
copy to seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/parameters/DependentParameters.java
index b702a124..bf780327 100644
--- a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/response/datasource/DatasourceRes.java
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/parameters/DependentParameters.java
@@ -15,30 +15,27 @@
  * limitations under the License.
  */
 
-package org.apache.seatunnel.app.domain.response.datasource;
+package org.apache.seatunnel.app.parameters;
 
-import org.apache.seatunnel.app.domain.response.BaseInfo;
+import org.apache.seatunnel.app.common.DependentRelation;
+import org.apache.seatunnel.app.domain.model.DependentTaskModel;
 
 import lombok.Data;
+import lombok.EqualsAndHashCode;
 
+import java.util.List;
 import java.util.Map;
 
 @Data
-public class DatasourceRes extends BaseInfo {
+@EqualsAndHashCode(callSuper = true)
+public class DependentParameters extends AbstractParameters {
 
-    private String id;
+    private List<DependentTaskModel> dependTaskList;
+    private DependentRelation relation;
+    private Map<String, Object> otherParams;
 
-    private String datasourceName;
-
-    private String pluginName;
-
-    private String pluginVersion;
-
-    private String description;
-
-    private Map<String, String> datasourceConfig;
-
-    private int createUserId;
-
-    private int updateUserId;
+    @Override
+    public boolean checkParameters() {
+        return true;
+    }
 }
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/parameters/IParameters.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/parameters/IParameters.java
new file mode 100644
index 00000000..d6b07f84
--- /dev/null
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/parameters/IParameters.java
@@ -0,0 +1,38 @@
+package org.apache.seatunnel.app.parameters; /*
+                                              * 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.
+                                              */
+
+import org.apache.seatunnel.app.domain.model.ResourceInfo;
+
+import java.util.List;
+
+/** job params interface */
+public interface IParameters {
+
+    /**
+     * check parameters is valid
+     *
+     * @return result
+     */
+    boolean checkParameters();
+
+    /**
+     * get project resource files list
+     *
+     * @return resource files list
+     */
+    List<ResourceInfo> getResourceFilesList();
+}
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/impl/SqlServerDataSourceConfigSwitcher.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/parameters/SubProcessParameters.java
similarity index 61%
copy from seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/impl/SqlServerDataSourceConfigSwitcher.java
copy to seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/parameters/SubProcessParameters.java
index 3d877f08..649e6221 100644
--- a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/impl/SqlServerDataSourceConfigSwitcher.java
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/parameters/SubProcessParameters.java
@@ -15,18 +15,23 @@
  * limitations under the License.
  */
 
-package org.apache.seatunnel.app.thridparty.datasource.impl;
+package org.apache.seatunnel.app.parameters;
 
-import org.apache.seatunnel.app.thridparty.datasource.AbstractDataSourceConfigSwitcher;
+public class SubProcessParameters extends AbstractParameters {
 
-public class SqlServerDataSourceConfigSwitcher extends AbstractDataSourceConfigSwitcher {
+    /** process definition id */
+    private long processDefinitionCode;
 
-    private static final SqlServerDataSourceConfigSwitcher INSTANCE =
-            new SqlServerDataSourceConfigSwitcher();
+    public void setProcessDefinitionCode(long processDefinitionCode) {
+        this.processDefinitionCode = processDefinitionCode;
+    }
 
-    public static final SqlServerDataSourceConfigSwitcher getInstance() {
-        return INSTANCE;
+    public long getProcessDefinitionCode() {
+        return this.processDefinitionCode;
     }
 
-    private SqlServerDataSourceConfigSwitcher() {}
+    @Override
+    public boolean checkParameters() {
+        return this.processDefinitionCode != 0;
+    }
 }
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/response/datasource/DatasourceRes.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/parameters/resource/AbstractResourceParameters.java
similarity index 61%
copy from seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/response/datasource/DatasourceRes.java
copy to seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/parameters/resource/AbstractResourceParameters.java
index b702a124..54bfa60a 100644
--- a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/domain/response/datasource/DatasourceRes.java
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/parameters/resource/AbstractResourceParameters.java
@@ -15,30 +15,15 @@
  * limitations under the License.
  */
 
-package org.apache.seatunnel.app.domain.response.datasource;
-
-import org.apache.seatunnel.app.domain.response.BaseInfo;
-
-import lombok.Data;
-
-import java.util.Map;
-
-@Data
-public class DatasourceRes extends BaseInfo {
-
-    private String id;
-
-    private String datasourceName;
-
-    private String pluginName;
-
-    private String pluginVersion;
-
-    private String description;
-
-    private Map<String, String> datasourceConfig;
-
-    private int createUserId;
-
-    private int updateUserId;
-}
+package org.apache.seatunnel.app.parameters.resource;
+
+import com.fasterxml.jackson.annotation.JsonSubTypes;
+import com.fasterxml.jackson.annotation.JsonSubTypes.Type;
+import com.fasterxml.jackson.annotation.JsonTypeInfo;
+
+@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, visible = true, property = "resourceType")
+@JsonSubTypes({
+    @Type(value = DataSourceParameters.class, name = "DATASOURCE"),
+    @Type(value = UdfFuncParameters.class, name = "UDF")
+})
+public abstract class AbstractResourceParameters {}
diff --git a/seatunnel-datasource/seatunnel-datasource-plugins/datasource-plugins-api/src/main/java/org/apache/seatunnel/datasource/plugin/api/model/TableField.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/parameters/resource/DataSourceParameters.java
similarity index 70%
copy from seatunnel-datasource/seatunnel-datasource-plugins/datasource-plugins-api/src/main/java/org/apache/seatunnel/datasource/plugin/api/model/TableField.java
copy to seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/parameters/resource/DataSourceParameters.java
index fabcaf47..85a0ff47 100644
--- a/seatunnel-datasource/seatunnel-datasource-plugins/datasource-plugins-api/src/main/java/org/apache/seatunnel/datasource/plugin/api/model/TableField.java
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/parameters/resource/DataSourceParameters.java
@@ -15,26 +15,21 @@
  * limitations under the License.
  */
 
-package org.apache.seatunnel.datasource.plugin.api.model;
+package org.apache.seatunnel.app.parameters.resource;
 
-import lombok.Data;
+import org.apache.seatunnel.app.common.DbType;
 
-import java.util.Map;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
 
 @Data
-public class TableField {
-
-    private String type;
+public class DataSourceParameters extends AbstractResourceParameters {
 
     private String name;
+    private DbType type;
 
-    private String comment;
-
-    private Boolean primaryKey;
-
-    private String defaultValue;
-
-    private Boolean nullable;
+    @JsonProperty(value = "DATASOURCE")
+    private String resourceType;
 
-    private Map<String, String> properties;
+    private String connectionParams;
 }
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/parameters/resource/ResourceParametersHelper.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/parameters/resource/ResourceParametersHelper.java
new file mode 100644
index 00000000..cbf93531
--- /dev/null
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/parameters/resource/ResourceParametersHelper.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.seatunnel.app.parameters.resource;
+
+import org.apache.seatunnel.app.common.ResourceType;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+
+public class ResourceParametersHelper {
+
+    private Map<ResourceType, Map<String, AbstractResourceParameters>> resourceMap =
+            new HashMap<>();
+
+    public void put(ResourceType resourceType, String id) {
+        put(resourceType, id, null);
+    }
+
+    public void put(ResourceType resourceType, String id, AbstractResourceParameters parameters) {
+        Map<String, AbstractResourceParameters> resourceParametersMap =
+                resourceMap.get(resourceType);
+        if (Objects.isNull(resourceParametersMap)) {
+            resourceParametersMap = new HashMap<>();
+            resourceMap.put(resourceType, resourceParametersMap);
+        }
+        resourceParametersMap.put(id, parameters);
+    }
+
+    public void setResourceMap(
+            Map<ResourceType, Map<String, AbstractResourceParameters>> resourceMap) {
+        this.resourceMap = resourceMap;
+    }
+
+    public Map<ResourceType, Map<String, AbstractResourceParameters>> getResourceMap() {
+        return resourceMap;
+    }
+
+    public Map<String, AbstractResourceParameters> getResourceMap(ResourceType resourceType) {
+        return this.getResourceMap().get(resourceType);
+    }
+
+    public AbstractResourceParameters getResourceParameters(
+            ResourceType resourceType, String code) {
+        return this.getResourceMap(resourceType).get(code);
+    }
+}
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/parameters/resource/UdfFuncParameters.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/parameters/resource/UdfFuncParameters.java
new file mode 100644
index 00000000..638d5a32
--- /dev/null
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/parameters/resource/UdfFuncParameters.java
@@ -0,0 +1,223 @@
+/*
+ * 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.seatunnel.app.parameters.resource;
+
+import org.apache.seatunnel.app.common.UdfType;
+import org.apache.seatunnel.app.utils.JSONUtils;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+import java.util.Date;
+
+/** udf function */
+public class UdfFuncParameters extends AbstractResourceParameters {
+
+    /** id */
+    private int id;
+
+    public String getResourceType() {
+        return resourceType;
+    }
+
+    public void setResourceType(String resourceType) {
+        this.resourceType = resourceType;
+    }
+
+    @JsonProperty(value = "UDF")
+    private String resourceType;
+
+    /** user id */
+    private int userId;
+
+    /** udf function name */
+    private String funcName;
+
+    /** udf class name */
+    private String className;
+
+    /** udf argument types */
+    private String argTypes;
+
+    /** udf data base */
+    private String database;
+
+    /** udf description */
+    private String description;
+
+    /** resource id */
+    private int resourceId;
+
+    /** resource name */
+    private String resourceName;
+
+    /** udf function type: hive / spark */
+    private UdfType type;
+
+    private String tenantCode;
+
+    private String defaultFS;
+
+    /** create time */
+    private Date createTime;
+
+    /** update time */
+    private Date updateTime;
+
+    public int getId() {
+        return id;
+    }
+
+    public void setId(int id) {
+        this.id = id;
+    }
+
+    public int getUserId() {
+        return userId;
+    }
+
+    public void setUserId(int userId) {
+        this.userId = userId;
+    }
+
+    public String getFuncName() {
+        return funcName;
+    }
+
+    public void setFuncName(String funcName) {
+        this.funcName = funcName;
+    }
+
+    public String getClassName() {
+        return className;
+    }
+
+    public void setClassName(String className) {
+        this.className = className;
+    }
+
+    public String getArgTypes() {
+        return argTypes;
+    }
+
+    public void setArgTypes(String argTypes) {
+        this.argTypes = argTypes;
+    }
+
+    public String getDatabase() {
+        return database;
+    }
+
+    public void setDatabase(String database) {
+        this.database = database;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    public void setDescription(String description) {
+        this.description = description;
+    }
+
+    public int getResourceId() {
+        return resourceId;
+    }
+
+    public void setResourceId(int resourceId) {
+        this.resourceId = resourceId;
+    }
+
+    public String getResourceName() {
+        return resourceName;
+    }
+
+    public void setResourceName(String resourceName) {
+        this.resourceName = resourceName;
+    }
+
+    public UdfType getType() {
+        return type;
+    }
+
+    public void setType(UdfType type) {
+        this.type = type;
+    }
+
+    public Date getCreateTime() {
+        return createTime;
+    }
+
+    public void setCreateTime(Date createTime) {
+        this.createTime = createTime;
+    }
+
+    public Date getUpdateTime() {
+        return updateTime;
+    }
+
+    public void setUpdateTime(Date updateTime) {
+        this.updateTime = updateTime;
+    }
+
+    public String getTenantCode() {
+        return tenantCode;
+    }
+
+    public void setTenantCode(String tenantCode) {
+        this.tenantCode = tenantCode;
+    }
+
+    public String getDefaultFS() {
+        return defaultFS;
+    }
+
+    public void setDefaultFS(String defaultFS) {
+        this.defaultFS = defaultFS;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+
+        UdfFuncParameters udfFuncRequest = (UdfFuncParameters) o;
+
+        if (id != udfFuncRequest.id) {
+            return false;
+        }
+        return !(funcName != null
+                ? !funcName.equals(udfFuncRequest.funcName)
+                : udfFuncRequest.funcName != null);
+    }
+
+    @Override
+    public int hashCode() {
+        int result = id;
+        result = 31 * result + (funcName != null ? funcName.hashCode() : 0);
+        return result;
+    }
+
+    @Override
+    public String toString() {
+        return JSONUtils.toJsonString(this);
+    }
+}
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/impl/MysqlDatasourceConfigSwitcher.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/permission/AvailableResourceRangeService.java
similarity index 73%
copy from seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/impl/MysqlDatasourceConfigSwitcher.java
copy to seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/permission/AvailableResourceRangeService.java
index 7da09161..6879744a 100644
--- a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/impl/MysqlDatasourceConfigSwitcher.java
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/permission/AvailableResourceRangeService.java
@@ -15,10 +15,11 @@
  * limitations under the License.
  */
 
-package org.apache.seatunnel.app.thridparty.datasource.impl;
+package org.apache.seatunnel.app.permission;
 
-public class MysqlDatasourceConfigSwitcher extends BaseJdbcDataSourceConfigSwitcher {
-    public static MysqlDatasourceConfigSwitcher INSTANCE = new MysqlDatasourceConfigSwitcher();
+import java.util.List;
 
-    private MysqlDatasourceConfigSwitcher() {}
+public interface AvailableResourceRangeService {
+
+    List<Object> queryAvailableResourceRangeBySourceType(String sourceType, int userId);
 }
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/permission/AvailableResourceRangeServiceImpl.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/permission/AvailableResourceRangeServiceImpl.java
new file mode 100644
index 00000000..19ec509b
--- /dev/null
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/permission/AvailableResourceRangeServiceImpl.java
@@ -0,0 +1,102 @@
+/*
+ * 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.seatunnel.app.permission;
+
+import org.apache.seatunnel.app.dal.dao.IDatasourceDao;
+import org.apache.seatunnel.app.dal.entity.Datasource;
+import org.apache.seatunnel.app.permission.enums.SeatunnelResourcePermissionModuleEnum;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+import org.springframework.stereotype.Component;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+@Component
+public class AvailableResourceRangeServiceImpl
+        implements AvailableResourceRangeService, ApplicationContextAware {
+
+    private static final Logger LOGGER =
+            LoggerFactory.getLogger(AvailableResourceRangeServiceImpl.class);
+
+    private final Map<String, ResourcePermissionQuery> resourceQueryMap = new HashMap<>();
+
+    @Override
+    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
+        Map<String, ResourcePermissionQuery> beansOfType =
+                applicationContext.getBeansOfType(ResourcePermissionQuery.class);
+        beansOfType.forEach(
+                (key, value) -> {
+                    List typeList = value.accessTypes();
+                    if (typeList == null || typeList.isEmpty()) {
+                        return;
+                    }
+                    typeList.forEach(
+                            accessType -> resourceQueryMap.put(String.valueOf(accessType), value));
+                });
+    }
+
+    @Override
+    public List queryAvailableResourceRangeBySourceType(String resourceType, int userId) {
+        ResourcePermissionQuery resourcePermissionQuery = resourceQueryMap.get(resourceType);
+        if (resourcePermissionQuery == null) {
+            LOGGER.warn("resource type {} query handle not init", resourceType);
+            return Collections.emptyList();
+        }
+        return resourcePermissionQuery.queryByResourceType(userId);
+    }
+
+    @Component
+    public static class DataSourceQuery implements ResourcePermissionQuery<Long> {
+
+        @Autowired
+        @Qualifier("datasourceDaoImpl") private IDatasourceDao iDatasourceDao;
+
+        @Override
+        public List<String> accessTypes() {
+            return Collections.singletonList(
+                    SeatunnelResourcePermissionModuleEnum.DATASOURCE.name());
+        }
+
+        @Override
+        public List<Long> queryByResourceType(int userId) {
+            List<Datasource> datasourceList = iDatasourceDao.selectDatasourceByUserId(userId);
+            return datasourceList == null || datasourceList.isEmpty()
+                    ? Collections.emptyList()
+                    : datasourceList.stream().map(Datasource::getId).collect(Collectors.toList());
+        }
+    }
+
+    interface ResourcePermissionQuery<T> {
+
+        /** resource type */
+        List<String> accessTypes();
+
+        /** query by resource type */
+        List<T> queryByResourceType(int userId);
+    }
+}
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/permission/ISeatunnelPermissonService.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/permission/ISeatunnelPermissonService.java
new file mode 100644
index 00000000..11d1eae0
--- /dev/null
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/permission/ISeatunnelPermissonService.java
@@ -0,0 +1,60 @@
+/*
+ * 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.seatunnel.app.permission;
+
+import java.util.List;
+
+public interface ISeatunnelPermissonService {
+
+    /**
+     * func permission check
+     *
+     * @param permissionKey permissionKey
+     * @param userId userId
+     */
+    void funcPermissionCheck(String permissionKey, int userId);
+
+    /**
+     * func permission and resource permission check
+     *
+     * @param permissionKey permissionKey
+     * @param resourceType resourceType
+     * @param resourceCodes resourceCodes
+     * @param userId userId
+     */
+    void funcAndResourcePermissionCheck(
+            String permissionKey, String resourceType, List<Object> resourceCodes, int userId);
+
+    /**
+     * resource post handle
+     *
+     * @param resourceType resourceType
+     * @param resourceCodes resourceCodes
+     * @param userId userId
+     */
+    void resourcePostHandle(String resourceType, List<Object> resourceCodes, int userId);
+
+    /**
+     * available resource range
+     *
+     * @param resourceType resourceType
+     * @param userId userId
+     * @return list
+     */
+    List<Object> availableResourceRange(String resourceType, int userId);
+}
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/permission/SeatunnelPermissionServiceImpl.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/permission/SeatunnelPermissionServiceImpl.java
new file mode 100644
index 00000000..b49ecc28
--- /dev/null
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/permission/SeatunnelPermissionServiceImpl.java
@@ -0,0 +1,61 @@
+/*
+ * 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.seatunnel.app.permission;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+
+@Component
+public class SeatunnelPermissionServiceImpl implements ISeatunnelPermissonService {
+
+    private static final Logger LOGGER =
+            LoggerFactory.getLogger(SeatunnelPermissionServiceImpl.class);
+
+    @Autowired private AvailableResourceRangeService availableResourceRangeService;
+
+    @Override
+    public void funcPermissionCheck(String permissionKey, int userId) {
+        // user id will be replaced by shiro in ws when user id == 0
+        LOGGER.warn("func permission check in whaletunnel");
+    }
+
+    @Override
+    public void funcAndResourcePermissionCheck(
+            String permissionKey, String sourceType, List<Object> sourceCodes, int userId) {
+        // user id will be replaced by shiro in ws when user id == 0
+        LOGGER.warn("func and resource permission check in whaletunnel");
+    }
+
+    @Override
+    public void resourcePostHandle(String sourceType, List<Object> sourceCodes, int userId) {
+        // user id will be replaced by shiro in ws when user id == 0
+        LOGGER.warn("resource post handle in whaletunnel");
+    }
+
+    @Override
+    public List<Object> availableResourceRange(String sourceType, int userId) {
+        // user id will be replaced by shiro in ws when user id == 0
+        LOGGER.warn("query available resource range in whaletunnel");
+        return availableResourceRangeService.queryAvailableResourceRangeBySourceType(
+                sourceType, userId);
+    }
+}
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/permission/constants/SeatunnelFuncPermissionKeyConstant.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/permission/constants/SeatunnelFuncPermissionKeyConstant.java
new file mode 100644
index 00000000..2ea22a3d
--- /dev/null
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/permission/constants/SeatunnelFuncPermissionKeyConstant.java
@@ -0,0 +1,85 @@
+/*
+ * 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.seatunnel.app.permission.constants;
+
+public class SeatunnelFuncPermissionKeyConstant {
+
+    /** cluster */
+    public static final String CLUSTER_METRICS_VIEW = "monitor:cluster:view";
+
+    /** sync task definition */
+    public static final String CONNECTOR_SOURCES = "project:seatunnel-task:sources";
+
+    public static final String CONNECTOR_TRANSFORMS = "project:seatunnel-task:transforms";
+    public static final String CONNECTOR_SINKS = "project:seatunnel-task:sinks";
+    public static final String CONNECTOR_SYNC = "project:seatunnel-task:sync";
+    public static final String CONNECTOR_FORM = "project:seatunnel-task:form";
+    public static final String CONNECTOR_DATASOURCE_SOURCES =
+            "project:seatunnel-task:datasource-sources";
+    public static final String CONNECTOR_DATASOURCE_TRANSFORMS =
+            "project:seatunnel-task:datasource-transforms";
+    public static final String CONNECTOR_DATASOURCE_SINKS =
+            "project:seatunnel-task:datasource-sinks";
+    public static final String CONNECTOR_DATASOURCE_FORM = "project:seatunnel-task:datasource-form";
+    public static final String ENGIN_LIST = "project:seatunnel-task:engin-list";
+    public static final String ENGIN_TYPE = "project:seatunnel-task:engin-type";
+    public static final String ENV_VIEW = "project:seatunnel-task:env";
+    public static final String JOB_CONFIG_UPDATE = "project:seatunnel-task:job-config-update";
+    public static final String JOB_CONFIG_DETAIL = "project:seatunnel-task:job-config-detail";
+    public static final String JOB_DEFINITION_VIEW = "project:seatunnel-task:view";
+    public static final String JOB_DEFINITION_CREATE = "project:seatunnel-task:create";
+    public static final String JOB_DEFINITION_DETAIL = "project:seatunnel-task:detail";
+    public static final String JOB_DEFINITION_DELETE = "project:seatunnel-task:delete";
+    public static final String JOB_TASK_DAG_CREATE = "project:seatunnel-task:job-dag-create";
+    public static final String JOB_TASK_DETAIL = "project:seatunnel-task:job-detail";
+    public static final String SINGLE_TASK_CREATE = "project:seatunnel-task:task-create";
+    public static final String SINGLE_TASK_DETAIL = "project:seatunnel-task:task-detail";
+    public static final String SINGLE_TASK_DELETE = "project:seatunnel-task:task-delete";
+    public static final String JOB_TABLE_SCHEMA = "project:seatunnel-task:table-schema";
+    public static final String JOB_TABLE_COLUMN_PROJECTION =
+            "project:seatunnel-task:column-projection";
+    public static final String JOB_EXECUTOR_RESOURCE = "project:seatunnel-task:job-exec-resource";
+    public static final String JOB_EXECUTOR_INSTANCE = "project:seatunnel-task:job-exec-instance";
+    public static final String JOB_EXECUTOR_COMPLETE = "project:seatunnel-task:job-exec-complete";
+
+    /** sync task instance */
+    public static final String JOB_METRICS_SUMMARY = "project:seatunnel-task-instance:summary";
+
+    public static final String JOB_DETAIL = "project:seatunnel-task-instance:detail";
+    public static final String JOB_DAG = "project:seatunnel-task-instance:dag";
+
+    /** datasource */
+    public static final String DATASOURCE_LIST = "datasource:list";
+
+    public static final String DATASOURCE_CREATE = "datasource:create";
+    public static final String DATASOURCE_UPDATE = "datasource:update";
+    public static final String DATASOURCE_DELETE = "datasource:delete";
+    public static final String DATASOURCE_TEST_CONNECT = "datasource:test-connect";
+    public static final String DATASOURCE_DYNAMIC = "datasource:dynamic";
+    public static final String DATASOURCE_DATABASES = "datasource:databases";
+    public static final String DATASOURCE_TABLE = "datasource:table";
+    public static final String DATASOURCE_TABLE_SCHEMA = "datasource:table-schema";
+    public static final String DATASOURCE_QUERY_ALL = "datasource:query-all";
+    public static final String DATASOURCE_DETAIL_LIST = "datasource:detail-list";
+    public static final String DATASOURCE_DETAIL = "datasource:detail";
+    public static final String VIRTUAL_TABLE_CREATE = "datasource:virtual-table-create";
+    public static final String VIRTUAL_TABLE_UPDATE = "datasource:virtual-table-update";
+    public static final String VIRTUAL_TABLE_DELETE = "datasource:virtual-table-delete";
+    public static final String VIRTUAL_TABLE_VIEW = "datasource:virtual-table-view";
+    public static final String VIRTUAL_TABLE_DETAIL = "datasource:virtual-table-detail";
+}
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/impl/MysqlDatasourceConfigSwitcher.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/permission/enums/SeatunnelResourcePermissionModuleEnum.java
similarity index 73%
copy from seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/impl/MysqlDatasourceConfigSwitcher.java
copy to seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/permission/enums/SeatunnelResourcePermissionModuleEnum.java
index 7da09161..3b157213 100644
--- a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/thridparty/datasource/impl/MysqlDatasourceConfigSwitcher.java
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/permission/enums/SeatunnelResourcePermissionModuleEnum.java
@@ -15,10 +15,15 @@
  * limitations under the License.
  */
 
-package org.apache.seatunnel.app.thridparty.datasource.impl;
+package org.apache.seatunnel.app.permission.enums;
 
-public class MysqlDatasourceConfigSwitcher extends BaseJdbcDataSourceConfigSwitcher {
-    public static MysqlDatasourceConfigSwitcher INSTANCE = new MysqlDatasourceConfigSwitcher();
+import lombok.AllArgsConstructor;
+import lombok.Getter;
 
-    private MysqlDatasourceConfigSwitcher() {}
+@Getter
+@AllArgsConstructor
+public enum SeatunnelResourcePermissionModuleEnum {
+    DATASOURCE,
+    SYNC_DEFINITION,
+    ;
 }
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/IConnectorService.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/IConnectorService.java
new file mode 100644
index 00000000..0ddd283c
--- /dev/null
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/IConnectorService.java
@@ -0,0 +1,56 @@
+/*
+ * 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.seatunnel.app.service;
+
+import org.apache.seatunnel.app.domain.request.connector.ConnectorStatus;
+import org.apache.seatunnel.app.domain.request.connector.SceneMode;
+import org.apache.seatunnel.app.domain.response.connector.ConnectorInfo;
+import org.apache.seatunnel.app.domain.response.connector.DataSourceInstance;
+import org.apache.seatunnel.app.dynamicforms.FormStructure;
+
+import lombok.NonNull;
+
+import java.io.IOException;
+import java.util.List;
+
+public interface IConnectorService {
+
+    List<ConnectorInfo> listSources(ConnectorStatus status);
+
+    List<DataSourceInstance> listSourceDataSourceInstances(
+            Long jobId, SceneMode sceneMode, ConnectorStatus status);
+
+    List<ConnectorInfo> listTransforms();
+
+    List<ConnectorInfo> listTransformsForJob(Long jobId);
+
+    List<ConnectorInfo> listSinks(ConnectorStatus status);
+
+    List<DataSourceInstance> listSinkDataSourcesInstances(Long jobId, ConnectorStatus status);
+
+    void sync() throws IOException;
+
+    FormStructure getConnectorFormStructure(
+            @NonNull String pluginType, @NonNull String connectorName);
+
+    FormStructure getTransformFormStructure(
+            @NonNull String pluginType, @NonNull String connectorName);
+
+    FormStructure getDatasourceFormStructure(
+            @NonNull Long jobId, @NonNull Long dataSourceId, @NonNull String pluginType);
+}
diff --git a/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/IDatasourceService.java b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/IDatasourceService.java
new file mode 100644
index 00000000..d1e911dc
--- /dev/null
+++ b/seatunnel-server/seatunnel-app/src/main/java/org/apache/seatunnel/app/service/IDatasourceService.java
@@ -0,0 +1,265 @@
+/*
+ * 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.seatunnel.app.service;
+
+import org.apache.seatunnel.api.configuration.util.OptionRule;
+import org.apache.seatunnel.app.domain.response.PageInfo;
+import org.apache.seatunnel.app.domain.response.datasource.DatasourceDetailRes;
+import org.apache.seatunnel.app.domain.response.datasource.DatasourceRes;
+import org.apache.seatunnel.datasource.plugin.api.DataSourcePluginInfo;
+import org.apache.seatunnel.datasource.plugin.api.model.TableField;
+import org.apache.seatunnel.server.common.CodeGenerateUtils;
+
+import java.util.List;
+import java.util.Map;
+
+public interface IDatasourceService {
+    /**
+     * create datasource
+     *
+     * @param userId userid
+     * @param datasourceName is required //todo datasourceName global is required
+     * @param pluginName is required
+     * @param pluginVersion is required
+     * @param description is optional
+     * @param datasourceConfig is required
+     * @return datasourceId
+     */
+    String createDatasource(
+            Integer userId,
+            String datasourceName,
+            String pluginName,
+            String pluginVersion,
+            String description,
+            Map<String, String> datasourceConfig)
+            throws CodeGenerateUtils.CodeGenerateException;
+
+    /**
+     * update datasource
+     *
+     * @param userId userid
+     * @param datasourceId datasource id
+     * @param datasourceName datasourceName
+     * @param description description
+     * @param datasourceConfig datasourceConfig
+     * @return boolean
+     */
+    boolean updateDatasource(
+            Integer userId,
+            Long datasourceId,
+            String datasourceName,
+            String description,
+            Map<String, String> datasourceConfig);
+
+    /**
+     * delete datasource
+     *
+     * @param userId userId
+     * @param datasourceId datasourceId
+     * @return boolean
+     */
+    boolean deleteDatasource(Integer userId, Long datasourceId);
+
+    /**
+     * test datasource is used
+     *
+     * @param userId userId
+     * @param pluginName pluginName
+     * @param pluginVersion pluginVersion default is 1.0.0
+     * @param datasourceConfig datasourceConfig
+     * @return boolean
+     */
+    boolean testDatasourceConnectionAble(
+            Integer userId,
+            String pluginName,
+            String pluginVersion,
+            Map<String, String> datasourceConfig);
+
+    /**
+     * test datasource is used
+     *
+     * @param userId userId
+     * @param datasourceId datasourceId
+     * @return boolean
+     */
+    boolean testDatasourceConnectionAble(Integer userId, Long datasourceId);
+
+    /**
+     * checkDatasourceNameUnique
+     *
+     * @param userId userId
+     * @param datasourceName datasourceName
+     * @param dataSourceId dataSourceId
+     * @return boolean
+     */
+    boolean checkDatasourceNameUnique(Integer userId, String datasourceName, Long dataSourceId);
+
+    /**
+     * queryDatasourceList
+     *
+     * @param userId userId
+     * @param pluginName pluginName
+     * @param pageNo pageNo
+     * @param pageSize pageSize
+     * @return PageInfo DatasourceRes
+     */
+    PageInfo<DatasourceRes> queryDatasourceList(
+            Integer userId, String searchVal, String pluginName, Integer pageNo, Integer pageSize);
+
+    /**
+     * datasourceId query detail
+     *
+     * @param userId userId
+     * @param datasourceId datasourceId
+     * @return DatasourceDetailRes
+     */
+    DatasourceDetailRes queryDatasourceDetailById(Integer userId, String datasourceId);
+
+    /**
+     * datasourceId query detail
+     *
+     * @param datasourceId datasourceId
+     * @return DatasourceDetailRes
+     */
+    DatasourceDetailRes queryDatasourceDetailById(String datasourceId);
+
+    /**
+     * datasourceName query detail
+     *
+     * @param datasourceName datasourceName
+     * @return DatasourceDetailRes
+     */
+    DatasourceDetailRes queryDatasourceDetailByDatasourceName(String datasourceName);
+
+    /**
+     * datasourceIds
+     *
+     * @param datasourceIds datasourceIds
+     * @return List DatasourceDetailRes
+     */
+    List<DatasourceDetailRes> queryDatasourceDetailListByDatasourceIds(List<String> datasourceIds);
+
+    /**
+     * Note: This interface is only used for exporting data, please evaluate it in advance for other
+     * scenarios!!! Querying all data source instances is limited to exporting data for use, please
+     * evaluate in advance for other scenarios!!!
+     *
+     * @return all datasource instance
+     */
+    @Deprecated
+    List<DatasourceDetailRes> queryAllDatasourcesInstance();
+
+    /**
+     * datasourceName query config
+     *
+     * @param datasourceId datasourceId
+     * @return Map
+     */
+    Map<String, String> queryDatasourceConfigById(String datasourceId);
+
+    /**
+     * plugin name datasourceName and id @liuli
+     *
+     * @param pluginName pluginName
+     * @return List String key: datasourceId value: datasourceName
+     */
+    Map<String, String> queryDatasourceNameByPluginName(String pluginName);
+
+    /**
+     * plugin name query config
+     *
+     * @param pluginName pluginName
+     * @return OptionRule @liuli
+     */
+    OptionRule queryOptionRuleByPluginName(String pluginName);
+
+    /**
+     * plugin name OptionRule
+     *
+     * @param pluginName pluginName
+     * @return OptionRule
+     */
+    OptionRule queryVirtualTableOptionRuleByPluginName(String pluginName);
+
+    /**
+     * query all datasource
+     *
+     * @return list
+     */
+    List<DataSourcePluginInfo> queryAllDatasources();
+
+    /**
+     * query all datasource by type
+     *
+     * @param type @see com.whaleops.datasource.plugin.api.DatasourcePluginTypeEnum
+     * @return List DataSourcePluginInfo
+     */
+    List<DataSourcePluginInfo> queryAllDatasourcesByType(Integer type);
+
+    /**
+     * all datasource
+     *
+     * @param onlyShowVirtualDataSource onlyShowVirtualDataSource
+     * @return key: type, value: List DataSourcePluginInfo
+     */
+    Map<Integer, List<DataSourcePluginInfo>> queryAllDatasourcesGroupByType(
+            Boolean onlyShowVirtualDataSource);
+
+    /**
+     * query by id
+     *
+     * @param datasourceId datasourceId
+     * @return name
+     */
+    String queryDatasourceNameById(String datasourceId);
+
+    /**
+     * query dynamic form by pluginName
+     *
+     * @param pluginName pluginName
+     * @return String json
+     */
+    String getDynamicForm(String pluginName);
+
+    /**
+     * queryDatabaseByDatasourceName
+     *
+     * @param datasourceName datasourceName
+     * @return List String databaseName
+     */
+    List<String> queryDatabaseByDatasourceName(String datasourceName);
+
... 7548 lines suppressed ...