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>