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

nicholasjiang pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/paimon-webui.git


The following commit(s) were added to refs/heads/main by this push:
     new f9780b4  [Feature] Introduce Flink CDC service (#143)
f9780b4 is described below

commit f9780b493a431642bdd473722934c6cff88cdd9a
Author: yangyang zhong <[email protected]>
AuthorDate: Tue Apr 23 14:58:42 2024 +0800

    [Feature] Introduce Flink CDC service (#143)
---
 paimon-web-api/pom.xml                             |   4 +
 .../api/action/context/AbstractActionContext.java  |  87 +++++++++++++++
 .../paimon/web/api/action/context/ActionConf.java  |  32 ++++++
 .../web/api/action/context/ActionContext.java      |  31 ++++++
 .../web/api/action/context/ActionContextUtil.java  |  44 ++++++++
 .../api/action/context/ActionExecutionResult.java  |  55 +++++++++
 .../web/api/action/context/FlinkActionContext.java |  40 +++++++
 .../FlinkCdcDatabasesSyncActionContext.java        |  45 ++++++++
 .../context/FlinkCdcTableSyncActionContext.java    |  56 ++++++++++
 .../context/MysqlSyncDatabaseActionContext.java    |  39 +++++++
 .../context/MysqlSyncTableActionContext.java       |  40 +++++++
 .../context/PostgresSyncTableCdcActionContext.java |  38 +++++++
 .../web/api/action/service/ActionService.java      |  31 ++++++
 .../api/action/service/FlinkCdcActionService.java  |  84 ++++++++++++++
 .../apache/paimon/web/api/enums/FlinkJobType.java  |  26 +++++
 .../paimon/web/api/exception/ActionException.java  |  45 ++++++++
 .../apache/paimon/web/api/shell/ShellService.java  |  47 ++++++++
 .../context/FlinkCdcActionContextTestBase.java     |  29 +++++
 .../MysqlSyncDatabaseActionContextTest.java        |  46 ++++++++
 .../context/MysqlSyncTableActionContextTest.java   | 123 +++++++++++++++++++++
 .../PostgresSyncTableActionContextTest.java        |  54 +++++++++
 .../paimon/web/api/shell/ShellServiceTest.java     |  53 +++++++++
 paimon-web-common/pom.xml                          |   5 +
 pom.xml                                            |  18 +++
 24 files changed, 1072 insertions(+)

diff --git a/paimon-web-api/pom.xml b/paimon-web-api/pom.xml
index acea6d1..b023b15 100644
--- a/paimon-web-api/pom.xml
+++ b/paimon-web-api/pom.xml
@@ -120,5 +120,9 @@ under the License.
             <artifactId>paimon-oss</artifactId>
             <version>${paimon.version}</version>
         </dependency>
+        <dependency>
+            <groupId>com.google.auto.service</groupId>
+            <artifactId>auto-service</artifactId>
+        </dependency>
     </dependencies>
 </project>
\ No newline at end of file
diff --git 
a/paimon-web-api/src/main/java/org/apache/paimon/web/api/action/context/AbstractActionContext.java
 
b/paimon-web-api/src/main/java/org/apache/paimon/web/api/action/context/AbstractActionContext.java
new file mode 100644
index 0000000..a721847
--- /dev/null
+++ 
b/paimon-web-api/src/main/java/org/apache/paimon/web/api/action/context/AbstractActionContext.java
@@ -0,0 +1,87 @@
+/*
+ * 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.paimon.web.api.action.context;
+
+import org.apache.paimon.web.api.exception.ActionException;
+
+import lombok.experimental.SuperBuilder;
+
+import javax.annotation.Nullable;
+
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * The AbstractActionContext provides a default implementation for 
getActionArgs. Its concrete
+ * subclasses only need to annotate the parameter fields of the action with 
the {@link ActionConf}
+ * annotation.
+ */
+@SuperBuilder
+public abstract class AbstractActionContext implements ActionContext {
+
+    private String actionPath;
+
+    @Override
+    public List<String> getArguments() {
+        Class<?> clazz = this.getClass();
+        List<String> args = new ArrayList<>();
+        args.add(name());
+        addArgument(args, clazz, this);
+        return args;
+    }
+
+    private void addArgument(List<String> args, Class<?> clazz, Object obj) {
+        if (clazz == null || clazz == Object.class) {
+            return;
+        }
+        addArgument(args, clazz.getSuperclass(), obj);
+        Field[] declaredFields = clazz.getDeclaredFields();
+        for (Field declaredField : declaredFields) {
+            ActionConf actionConf = 
declaredField.getAnnotation(ActionConf.class);
+            if (actionConf == null) {
+                continue;
+            }
+            String confKey = actionConf.value();
+            Object confValue = null;
+            try {
+                declaredField.setAccessible(true);
+                confValue = declaredField.get(obj);
+            } catch (IllegalArgumentException | IllegalAccessException ignore) 
{
+
+            }
+            boolean nullable = declaredField.getAnnotation(Nullable.class) != 
null;
+            if (!nullable && confValue == null) {
+                throw new ActionException(confKey + " can not be null");
+            }
+            if (nullable && confValue == null) {
+                continue;
+            }
+            if (confValue instanceof List) {
+                ActionContextUtil.addConfList(args, confKey, (List<?>) 
confValue);
+            } else {
+                ActionContextUtil.addConf(args, confKey, 
String.valueOf(confValue));
+            }
+        }
+    }
+
+    public String getJarPath() {
+        return actionPath;
+    }
+}
diff --git 
a/paimon-web-api/src/main/java/org/apache/paimon/web/api/action/context/ActionConf.java
 
b/paimon-web-api/src/main/java/org/apache/paimon/web/api/action/context/ActionConf.java
new file mode 100644
index 0000000..43b23f0
--- /dev/null
+++ 
b/paimon-web-api/src/main/java/org/apache/paimon/web/api/action/context/ActionConf.java
@@ -0,0 +1,32 @@
+/*
+ * 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.paimon.web.api.action.context;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/** ActionConf. */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.FIELD)
+public @interface ActionConf {
+
+    String value();
+}
diff --git 
a/paimon-web-api/src/main/java/org/apache/paimon/web/api/action/context/ActionContext.java
 
b/paimon-web-api/src/main/java/org/apache/paimon/web/api/action/context/ActionContext.java
new file mode 100644
index 0000000..95334e2
--- /dev/null
+++ 
b/paimon-web-api/src/main/java/org/apache/paimon/web/api/action/context/ActionContext.java
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.paimon.web.api.action.context;
+
+import java.util.List;
+
+/** The context of action which converts the user-defined action to command 
line. */
+public interface ActionContext {
+    String name();
+
+    /** Converts the user-defined action to command line. */
+    List<String> getArguments();
+
+    String getJarPath();
+}
diff --git 
a/paimon-web-api/src/main/java/org/apache/paimon/web/api/action/context/ActionContextUtil.java
 
b/paimon-web-api/src/main/java/org/apache/paimon/web/api/action/context/ActionContextUtil.java
new file mode 100644
index 0000000..bf06e94
--- /dev/null
+++ 
b/paimon-web-api/src/main/java/org/apache/paimon/web/api/action/context/ActionContextUtil.java
@@ -0,0 +1,44 @@
+/*
+ * 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.paimon.web.api.action.context;
+
+import org.apache.commons.lang3.StringUtils;
+
+import java.util.List;
+
+/** ActionContext Util. */
+public class ActionContextUtil {
+
+    private ActionContextUtil() {}
+
+    public static void addConf(List<String> args, String confName, String 
conf) {
+        if (StringUtils.isNotBlank(conf)) {
+            args.add("--" + confName);
+            args.add(conf);
+        }
+    }
+
+    public static void addConfList(List<String> args, String confName, List<?> 
confList) {
+        if (confList != null && !confList.isEmpty()) {
+            for (Object conf : confList) {
+                addConf(args, confName, String.valueOf(conf));
+            }
+        }
+    }
+}
diff --git 
a/paimon-web-api/src/main/java/org/apache/paimon/web/api/action/context/ActionExecutionResult.java
 
b/paimon-web-api/src/main/java/org/apache/paimon/web/api/action/context/ActionExecutionResult.java
new file mode 100644
index 0000000..13077aa
--- /dev/null
+++ 
b/paimon-web-api/src/main/java/org/apache/paimon/web/api/action/context/ActionExecutionResult.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.paimon.web.api.action.context;
+
+/** ActionExecutionResult. */
+public class ActionExecutionResult {
+
+    private boolean success;
+    private String errorMsg;
+
+    public static ActionExecutionResult success() {
+        ActionExecutionResult actionExecutionResult = new 
ActionExecutionResult();
+        actionExecutionResult.success = true;
+        return actionExecutionResult;
+    }
+
+    public static ActionExecutionResult fail(String errorMsg) {
+        ActionExecutionResult actionExecutionResult = new 
ActionExecutionResult();
+        actionExecutionResult.success = true;
+        actionExecutionResult.errorMsg = errorMsg;
+        return actionExecutionResult;
+    }
+
+    public boolean isSuccess() {
+        return success;
+    }
+
+    public void setSuccess(boolean success) {
+        this.success = success;
+    }
+
+    public String getErrorMsg() {
+        return errorMsg;
+    }
+
+    public void setErrorMsg(String errorMsg) {
+        this.errorMsg = errorMsg;
+    }
+}
diff --git 
a/paimon-web-api/src/main/java/org/apache/paimon/web/api/action/context/FlinkActionContext.java
 
b/paimon-web-api/src/main/java/org/apache/paimon/web/api/action/context/FlinkActionContext.java
new file mode 100644
index 0000000..d823399
--- /dev/null
+++ 
b/paimon-web-api/src/main/java/org/apache/paimon/web/api/action/context/FlinkActionContext.java
@@ -0,0 +1,40 @@
+/*
+ * 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.paimon.web.api.action.context;
+
+import org.apache.paimon.web.api.enums.FlinkJobType;
+
+import lombok.experimental.SuperBuilder;
+
+/** FlinkActionContext. */
+@SuperBuilder
+public abstract class FlinkActionContext extends AbstractActionContext 
implements ActionContext {
+
+    private String sessionUrl;
+
+    private FlinkJobType flinkJobType;
+
+    public String getSessionUrl() {
+        return sessionUrl;
+    }
+
+    public FlinkJobType getFlinkJobType() {
+        return flinkJobType;
+    }
+}
diff --git 
a/paimon-web-api/src/main/java/org/apache/paimon/web/api/action/context/FlinkCdcDatabasesSyncActionContext.java
 
b/paimon-web-api/src/main/java/org/apache/paimon/web/api/action/context/FlinkCdcDatabasesSyncActionContext.java
new file mode 100644
index 0000000..9cc42d6
--- /dev/null
+++ 
b/paimon-web-api/src/main/java/org/apache/paimon/web/api/action/context/FlinkCdcDatabasesSyncActionContext.java
@@ -0,0 +1,45 @@
+/*
+ * 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.paimon.web.api.action.context;
+
+import lombok.experimental.SuperBuilder;
+
+import javax.annotation.Nullable;
+
+import java.util.List;
+
+/** The FlinkCdcDatabasesActionContext for the entire database 
synchronization. */
+@SuperBuilder
+public abstract class FlinkCdcDatabasesSyncActionContext extends 
FlinkActionContext
+        implements ActionContext {
+
+    @ActionConf(value = "warehouse")
+    protected String warehouse;
+
+    @ActionConf(value = "database")
+    protected String database;
+
+    @ActionConf(value = "catalog_conf")
+    @Nullable
+    protected List<String> catalogConfList;
+
+    @ActionConf(value = "table_conf")
+    @Nullable
+    protected List<String> tableConfList;
+}
diff --git 
a/paimon-web-api/src/main/java/org/apache/paimon/web/api/action/context/FlinkCdcTableSyncActionContext.java
 
b/paimon-web-api/src/main/java/org/apache/paimon/web/api/action/context/FlinkCdcTableSyncActionContext.java
new file mode 100644
index 0000000..d2ba655
--- /dev/null
+++ 
b/paimon-web-api/src/main/java/org/apache/paimon/web/api/action/context/FlinkCdcTableSyncActionContext.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.paimon.web.api.action.context;
+
+import lombok.experimental.SuperBuilder;
+
+import javax.annotation.Nullable;
+
+import java.util.List;
+
+/** The FlinkCdcTableSyncActionContext for the table synchronization. */
+@SuperBuilder
+public abstract class FlinkCdcTableSyncActionContext extends FlinkActionContext
+        implements ActionContext {
+
+    @ActionConf(value = "warehouse")
+    protected String warehouse;
+
+    @ActionConf(value = "database")
+    protected String database;
+
+    @ActionConf(value = "table")
+    protected String table;
+
+    @ActionConf("partition_keys")
+    @Nullable
+    protected String partitionKeys;
+
+    @ActionConf("primary_keys")
+    @Nullable
+    protected String primaryKeys;
+
+    @ActionConf(value = "catalog_conf")
+    @Nullable
+    protected List<String> catalogConfList;
+
+    @ActionConf(value = "table_conf")
+    @Nullable
+    protected List<String> tableConfList;
+}
diff --git 
a/paimon-web-api/src/main/java/org/apache/paimon/web/api/action/context/MysqlSyncDatabaseActionContext.java
 
b/paimon-web-api/src/main/java/org/apache/paimon/web/api/action/context/MysqlSyncDatabaseActionContext.java
new file mode 100644
index 0000000..03e5621
--- /dev/null
+++ 
b/paimon-web-api/src/main/java/org/apache/paimon/web/api/action/context/MysqlSyncDatabaseActionContext.java
@@ -0,0 +1,39 @@
+/*
+ * 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.paimon.web.api.action.context;
+
+import lombok.experimental.SuperBuilder;
+
+import javax.annotation.Nullable;
+
+import java.util.List;
+
+/** Mysql sync database action context. */
+@SuperBuilder
+public class MysqlSyncDatabaseActionContext extends 
FlinkCdcDatabasesSyncActionContext
+        implements ActionContext {
+
+    @ActionConf(value = "mysql_conf")
+    @Nullable
+    private final List<String> mysqlConfList;
+
+    public String name() {
+        return "mysql_sync_database";
+    }
+}
diff --git 
a/paimon-web-api/src/main/java/org/apache/paimon/web/api/action/context/MysqlSyncTableActionContext.java
 
b/paimon-web-api/src/main/java/org/apache/paimon/web/api/action/context/MysqlSyncTableActionContext.java
new file mode 100644
index 0000000..5fd8e23
--- /dev/null
+++ 
b/paimon-web-api/src/main/java/org/apache/paimon/web/api/action/context/MysqlSyncTableActionContext.java
@@ -0,0 +1,40 @@
+/*
+ * 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.paimon.web.api.action.context;
+
+import lombok.experimental.SuperBuilder;
+
+import javax.annotation.Nullable;
+
+import java.util.List;
+
+/** Mysql sync table action context. */
+@SuperBuilder
+public class MysqlSyncTableActionContext extends FlinkCdcTableSyncActionContext
+        implements ActionContext {
+
+    @ActionConf(value = "mysql_conf")
+    @Nullable
+    private final List<String> mysqlConfList;
+
+    @Override
+    public String name() {
+        return "mysql_sync_table";
+    }
+}
diff --git 
a/paimon-web-api/src/main/java/org/apache/paimon/web/api/action/context/PostgresSyncTableCdcActionContext.java
 
b/paimon-web-api/src/main/java/org/apache/paimon/web/api/action/context/PostgresSyncTableCdcActionContext.java
new file mode 100644
index 0000000..8cf5dd8
--- /dev/null
+++ 
b/paimon-web-api/src/main/java/org/apache/paimon/web/api/action/context/PostgresSyncTableCdcActionContext.java
@@ -0,0 +1,38 @@
+/*
+ * 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.paimon.web.api.action.context;
+
+import lombok.experimental.SuperBuilder;
+
+import javax.annotation.Nullable;
+
+import java.util.List;
+
+/** Postgres sync table action context. */
+@SuperBuilder
+public class PostgresSyncTableCdcActionContext extends 
FlinkCdcTableSyncActionContext {
+
+    @ActionConf(value = "postgres_conf")
+    @Nullable
+    private final List<String> postgresConfList;
+
+    public String name() {
+        return "postgres_sync_table";
+    }
+}
diff --git 
a/paimon-web-api/src/main/java/org/apache/paimon/web/api/action/service/ActionService.java
 
b/paimon-web-api/src/main/java/org/apache/paimon/web/api/action/service/ActionService.java
new file mode 100644
index 0000000..ea31176
--- /dev/null
+++ 
b/paimon-web-api/src/main/java/org/apache/paimon/web/api/action/service/ActionService.java
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.paimon.web.api.action.service;
+
+import org.apache.paimon.web.api.action.context.ActionContext;
+import org.apache.paimon.web.api.action.context.ActionExecutionResult;
+
+/**
+ * Action service definition. Convert the user-configured CDC job into an 
ActionContext {@link
+ * ActionContext}, and then invoke the execute method to execute the action 
job.
+ */
+public interface ActionService {
+
+    ActionExecutionResult execute(ActionContext actionContext) throws 
Exception;
+}
diff --git 
a/paimon-web-api/src/main/java/org/apache/paimon/web/api/action/service/FlinkCdcActionService.java
 
b/paimon-web-api/src/main/java/org/apache/paimon/web/api/action/service/FlinkCdcActionService.java
new file mode 100644
index 0000000..6020634
--- /dev/null
+++ 
b/paimon-web-api/src/main/java/org/apache/paimon/web/api/action/service/FlinkCdcActionService.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.paimon.web.api.action.service;
+
+import org.apache.paimon.web.api.action.context.ActionContext;
+import org.apache.paimon.web.api.action.context.ActionExecutionResult;
+import org.apache.paimon.web.api.action.context.FlinkActionContext;
+import org.apache.paimon.web.api.enums.FlinkJobType;
+import org.apache.paimon.web.api.exception.ActionException;
+import org.apache.paimon.web.api.shell.ShellService;
+
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/** An abstract Action service that executes actions through the shell. */
+@Slf4j
+public class FlinkCdcActionService implements ActionService {
+
+    private List<String> getCommand(FlinkActionContext actionContext) {
+        List<String> commandList = new ArrayList<>();
+        commandList.add("bin/flink");
+        commandList.add("run");
+        if (actionContext.getFlinkJobType() != FlinkJobType.SESSION) {
+            throw new ActionException("Only support session job now.");
+        }
+        String sessionUrl = actionContext.getSessionUrl();
+        if (StringUtils.isNotBlank(sessionUrl)) {
+            commandList.add("-m");
+            commandList.add(sessionUrl);
+        }
+        commandList.add(actionContext.getJarPath());
+        commandList.addAll(actionContext.getArguments());
+        return commandList;
+    }
+
+    public ActionExecutionResult execute(ActionContext actionContext) throws 
Exception {
+        String flinkHome = getFlinkHome();
+        FlinkActionContext flinkActionContext;
+        if (!(actionContext instanceof FlinkActionContext)) {
+            throw new ActionException("Only support FlinkActionContext. ");
+        }
+        flinkActionContext = (FlinkActionContext) actionContext;
+        ActionExecutionResult result;
+        try {
+            List<String> command = getCommand(flinkActionContext);
+            Process process = new ShellService(flinkHome, command).execute();
+            result = ActionExecutionResult.success();
+        } catch (Exception exception) {
+            log.error(exception.getMessage(), exception);
+            result = ActionExecutionResult.fail(exception.getMessage());
+        }
+        return result;
+    }
+
+    private String getFlinkHome() {
+        String flinkHome = System.getenv("FLINK_HOME");
+        if (StringUtils.isBlank(flinkHome)) {
+            flinkHome = System.getProperty("FLINK_HOME");
+        }
+        if (StringUtils.isBlank(flinkHome)) {
+            throw new ActionException("FLINK_HOME is null");
+        }
+        return flinkHome;
+    }
+}
diff --git 
a/paimon-web-api/src/main/java/org/apache/paimon/web/api/enums/FlinkJobType.java
 
b/paimon-web-api/src/main/java/org/apache/paimon/web/api/enums/FlinkJobType.java
new file mode 100644
index 0000000..bb0808d
--- /dev/null
+++ 
b/paimon-web-api/src/main/java/org/apache/paimon/web/api/enums/FlinkJobType.java
@@ -0,0 +1,26 @@
+/*
+ * 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.paimon.web.api.enums;
+
+/** FlinkJobType. */
+public enum FlinkJobType {
+    SESSION,
+    PER_JOB,
+    APPLICATION
+}
diff --git 
a/paimon-web-api/src/main/java/org/apache/paimon/web/api/exception/ActionException.java
 
b/paimon-web-api/src/main/java/org/apache/paimon/web/api/exception/ActionException.java
new file mode 100644
index 0000000..b01d6df
--- /dev/null
+++ 
b/paimon-web-api/src/main/java/org/apache/paimon/web/api/exception/ActionException.java
@@ -0,0 +1,45 @@
+/*
+ * 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.paimon.web.api.exception;
+
+/** Action exception. */
+public class ActionException extends RuntimeException {
+
+    public ActionException() {}
+
+    public ActionException(String message) {
+        super(message);
+    }
+
+    public ActionException(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+    public ActionException(Throwable cause) {
+        super(cause);
+    }
+
+    public ActionException(
+            String message,
+            Throwable cause,
+            boolean enableSuppression,
+            boolean writableStackTrace) {
+        super(message, cause, enableSuppression, writableStackTrace);
+    }
+}
diff --git 
a/paimon-web-api/src/main/java/org/apache/paimon/web/api/shell/ShellService.java
 
b/paimon-web-api/src/main/java/org/apache/paimon/web/api/shell/ShellService.java
new file mode 100644
index 0000000..8aa08a0
--- /dev/null
+++ 
b/paimon-web-api/src/main/java/org/apache/paimon/web/api/shell/ShellService.java
@@ -0,0 +1,47 @@
+/*
+ * 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.paimon.web.api.shell;
+
+import lombok.extern.slf4j.Slf4j;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.List;
+
+/** Shell service. */
+@Slf4j
+public class ShellService {
+
+    private final String workingDirectory;
+    private final List<String> executeCommand;
+
+    public ShellService(String workingDirectory, List<String> executeCommand) {
+        this.workingDirectory = workingDirectory;
+        this.executeCommand = executeCommand;
+    }
+
+    public Process execute() throws IOException {
+        ProcessBuilder processBuilder = new ProcessBuilder();
+        processBuilder.directory(new File(workingDirectory));
+        processBuilder.redirectErrorStream(true);
+        processBuilder.command(executeCommand);
+        log.info("Executing shell command : {}", String.join(" ", 
executeCommand));
+        return processBuilder.start();
+    }
+}
diff --git 
a/paimon-web-api/src/test/java/org/apache/paimon/web/api/action/context/FlinkCdcActionContextTestBase.java
 
b/paimon-web-api/src/test/java/org/apache/paimon/web/api/action/context/FlinkCdcActionContextTestBase.java
new file mode 100644
index 0000000..0008878
--- /dev/null
+++ 
b/paimon-web-api/src/test/java/org/apache/paimon/web/api/action/context/FlinkCdcActionContextTestBase.java
@@ -0,0 +1,29 @@
+/*
+ * 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.paimon.web.api.action.context;
+
+/** FlinkCdcActionContextTestBase. */
+public class FlinkCdcActionContextTestBase {
+
+    protected static final String WAREHOUSE = "warehouse";
+
+    protected static final String DATABASE = "database";
+
+    protected static final String TABLE = "table";
+}
diff --git 
a/paimon-web-api/src/test/java/org/apache/paimon/web/api/action/context/MysqlSyncDatabaseActionContextTest.java
 
b/paimon-web-api/src/test/java/org/apache/paimon/web/api/action/context/MysqlSyncDatabaseActionContextTest.java
new file mode 100644
index 0000000..f9a6b2b
--- /dev/null
+++ 
b/paimon-web-api/src/test/java/org/apache/paimon/web/api/action/context/MysqlSyncDatabaseActionContextTest.java
@@ -0,0 +1,46 @@
+/*
+ * 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.paimon.web.api.action.context;
+
+import org.junit.jupiter.api.Test;
+
+import java.util.Arrays;
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.assertLinesMatch;
+
+/**
+ * The test class of mysql sync databases action context in {@link 
MysqlSyncDatabaseActionContext}.
+ */
+public class MysqlSyncDatabaseActionContextTest extends 
FlinkCdcActionContextTestBase {
+
+    @Test
+    public void testGetArgs() {
+        List<String> args =
+                MysqlSyncDatabaseActionContext.builder()
+                        .warehouse(WAREHOUSE)
+                        .database(DATABASE)
+                        .build()
+                        .getArguments();
+        List<String> expectedArgs =
+                Arrays.asList(
+                        "mysql_sync_database", "--warehouse", WAREHOUSE, 
"--database", DATABASE);
+        assertLinesMatch(expectedArgs, args);
+    }
+}
diff --git 
a/paimon-web-api/src/test/java/org/apache/paimon/web/api/action/context/MysqlSyncTableActionContextTest.java
 
b/paimon-web-api/src/test/java/org/apache/paimon/web/api/action/context/MysqlSyncTableActionContextTest.java
new file mode 100644
index 0000000..6bdaa9d
--- /dev/null
+++ 
b/paimon-web-api/src/test/java/org/apache/paimon/web/api/action/context/MysqlSyncTableActionContextTest.java
@@ -0,0 +1,123 @@
+/*
+ * 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.paimon.web.api.action.context;
+
+import org.apache.paimon.web.api.exception.ActionException;
+
+import org.junit.jupiter.api.Test;
+
+import java.util.Arrays;
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertLinesMatch;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+/** The test class of mysql sync table action context in {@link 
MysqlSyncTableActionContext}. */
+public class MysqlSyncTableActionContextTest extends 
FlinkCdcActionContextTestBase {
+
+    @Test
+    public void testBuild() {
+        List<String> args =
+                MysqlSyncTableActionContext.builder()
+                        .warehouse(WAREHOUSE)
+                        .database(DATABASE)
+                        .table(TABLE)
+                        .build()
+                        .getArguments();
+        List<String> expectedArgs =
+                Arrays.asList(
+                        "mysql_sync_table",
+                        "--warehouse",
+                        WAREHOUSE,
+                        "--database",
+                        DATABASE,
+                        "--table",
+                        TABLE);
+        assertLinesMatch(expectedArgs, args);
+    }
+
+    @Test
+    public void testBuildConf() {
+        List<String> args =
+                MysqlSyncTableActionContext.builder()
+                        .warehouse(WAREHOUSE)
+                        .database(DATABASE)
+                        .table(TABLE)
+                        .partitionKeys("pt")
+                        .mysqlConfList(
+                                Arrays.asList(
+                                        "table-name='source_table'",
+                                        "database-name='source_db'",
+                                        "password=123456"))
+                        .catalogConfList(
+                                Arrays.asList("metastore=hive", 
"uri=thrift://hive-metastore:9083"))
+                        .tableConfList(Arrays.asList("bucket=4", 
"changelog-producer=input"))
+                        .build()
+                        .getArguments();
+        List<String> expectedCommands =
+                Arrays.asList(
+                        "mysql_sync_table",
+                        "--warehouse",
+                        WAREHOUSE,
+                        "--database",
+                        DATABASE,
+                        "--table",
+                        TABLE,
+                        "--partition_keys",
+                        "pt",
+                        "--catalog_conf",
+                        "metastore=hive",
+                        "--catalog_conf",
+                        "uri=thrift://hive-metastore:9083",
+                        "--table_conf",
+                        "bucket=4",
+                        "--table_conf",
+                        "changelog-producer=input",
+                        "--mysql_conf",
+                        "table-name='source_table'",
+                        "--mysql_conf",
+                        "database-name='source_db'",
+                        "--mysql_conf",
+                        "password=123456");
+        assertLinesMatch(expectedCommands, args);
+    }
+
+    @Test
+    public void testBuildError() {
+        MysqlSyncTableActionContext context =
+                MysqlSyncTableActionContext.builder()
+                        .warehouse(WAREHOUSE)
+                        .database(DATABASE)
+                        .partitionKeys("pt")
+                        .primaryKeys("pt,uid")
+                        .mysqlConfList(
+                                Arrays.asList(
+                                        "table-name='source_table'",
+                                        "database-name='source_db'",
+                                        "password=123456"))
+                        .catalogConfList(
+                                Arrays.asList("metastore=hive", 
"uri=thrift://hive-metastore:9083"))
+                        .tableConfList(Arrays.asList("bucket=4", 
"changelog-producer=input"))
+                        .build();
+        ActionException actionException =
+                assertThrows(ActionException.class, context::getArguments);
+        assertEquals("table can not be null", actionException.getMessage());
+    }
+}
diff --git 
a/paimon-web-api/src/test/java/org/apache/paimon/web/api/action/context/PostgresSyncTableActionContextTest.java
 
b/paimon-web-api/src/test/java/org/apache/paimon/web/api/action/context/PostgresSyncTableActionContextTest.java
new file mode 100644
index 0000000..562e914
--- /dev/null
+++ 
b/paimon-web-api/src/test/java/org/apache/paimon/web/api/action/context/PostgresSyncTableActionContextTest.java
@@ -0,0 +1,54 @@
+/*
+ * 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.paimon.web.api.action.context;
+
+import org.junit.jupiter.api.Test;
+
+import java.util.Arrays;
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.assertLinesMatch;
+
+/**
+ * The test class of postgres sync table action context in {@link
+ * PostgresSyncTableCdcActionContext}.
+ */
+public class PostgresSyncTableActionContextTest extends 
FlinkCdcActionContextTestBase {
+
+    @Test
+    public void testBuild() {
+        List<String> args =
+                PostgresSyncTableCdcActionContext.builder()
+                        .warehouse(WAREHOUSE)
+                        .database(DATABASE)
+                        .table(TABLE)
+                        .build()
+                        .getArguments();
+        List<String> expectedArgs =
+                Arrays.asList(
+                        "postgres_sync_table",
+                        "--warehouse",
+                        WAREHOUSE,
+                        "--database",
+                        DATABASE,
+                        "--table",
+                        TABLE);
+        assertLinesMatch(expectedArgs, args);
+    }
+}
diff --git 
a/paimon-web-api/src/test/java/org/apache/paimon/web/api/shell/ShellServiceTest.java
 
b/paimon-web-api/src/test/java/org/apache/paimon/web/api/shell/ShellServiceTest.java
new file mode 100644
index 0000000..a12e0c0
--- /dev/null
+++ 
b/paimon-web-api/src/test/java/org/apache/paimon/web/api/shell/ShellServiceTest.java
@@ -0,0 +1,53 @@
+/*
+ * 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.paimon.web.api.shell;
+
+import org.apache.commons.io.IOUtils;
+import org.junit.jupiter.api.Test;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Arrays;
+import java.util.List;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/** The test class of shell execution in{@link ShellService}. */
+public class ShellServiceTest {
+
+    @Test
+    public void testExecuteShell() throws IOException {
+        List<String> args = Arrays.asList("/bin/sh", "-c", "echo 1");
+        ShellService shellService = new ShellService("/", args);
+        Process execute = shellService.execute();
+        InputStream is = execute.getInputStream();
+        List<String> lines = IOUtils.readLines(is);
+        assertThat(lines.size() == 1 && "1".equals(lines.get(0))).isTrue();
+    }
+
+    @Test
+    public void testExecuteBash() throws IOException {
+        List<String> args = Arrays.asList("/bin/bash", "-c", "echo 1");
+        ShellService shellService = new ShellService("/", args);
+        Process execute = shellService.execute();
+        InputStream is = execute.getInputStream();
+        List<String> lines = IOUtils.readLines(is);
+        assertThat(lines.size() == 1 && "1".equals(lines.get(0))).isTrue();
+    }
+}
diff --git a/paimon-web-common/pom.xml b/paimon-web-common/pom.xml
index 2f2815e..cbe8946 100644
--- a/paimon-web-common/pom.xml
+++ b/paimon-web-common/pom.xml
@@ -52,6 +52,11 @@ under the License.
             <groupId>org.apache.commons</groupId>
             <artifactId>commons-lang3</artifactId>
         </dependency>
+
+        <dependency>
+            <groupId>commons-io</groupId>
+            <artifactId>commons-io</artifactId>
+        </dependency>
     </dependencies>
 
 </project>
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 7ef3848..79b62c2 100644
--- a/pom.xml
+++ b/pom.xml
@@ -114,8 +114,10 @@ under the License.
         <mybatis-plus.version>3.5.3.1</mybatis-plus.version>
         <sa-token.version>1.35.0.RC</sa-token.version>
         <common-lang3.version>3.12.0</common-lang3.version>
+        <common-io.version>2.4</common-io.version>
         <hutool.version>5.8.11</hutool.version>
         <gson.version>2.10.1</gson.version>
+        <auto-service.version>1.0.1</auto-service.version>
     </properties>
 
     <dependencyManagement>
@@ -224,6 +226,19 @@ under the License.
                 <artifactId>springdoc-openapi-ui</artifactId>
                 <version>${springdoc-openapi-ui.version}</version>
             </dependency>
+
+            <dependency>
+                <groupId>com.google.auto.service</groupId>
+                <artifactId>auto-service</artifactId>
+                <version>${auto-service.version}</version>
+                <scope>provided</scope>
+            </dependency>
+
+            <dependency>
+                <groupId>commons-io</groupId>
+                <artifactId>commons-io</artifactId>
+                <version>${common-io.version}</version>
+            </dependency>
         </dependencies>
     </dependencyManagement>
 
@@ -456,6 +471,9 @@ under the License.
                     <groupId>org.apache.maven.plugins</groupId>
                     <artifactId>maven-surefire-plugin</artifactId>
                     <version>${maven-surefire-plugin.version}</version>
+                    <configuration>
+                        <skip>true</skip>
+                    </configuration>
                 </plugin>
                 <plugin>
                     <groupId>org.apache.maven.plugins</groupId>

Reply via email to