This is an automated email from the ASF dual-hosted git repository.
lzljs3620320 pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/incubator-paimon-webui.git
The following commit(s) were added to refs/heads/main by this push:
new a0c588c Add paimon web api module and fix some issues (#7)
a0c588c is described below
commit a0c588c464c07c7fd0a4c39e347b218242f4a611
Author: s7monk <[email protected]>
AuthorDate: Mon Jul 24 13:57:03 2023 +0800
Add paimon web api module and fix some issues (#7)
---
paimon-web-api/pom.xml | 110 +++++++++++
.../paimon/web/api/catalog/CatalogCreator.java | 46 +++++
.../paimon/web/api/common/CatalogProperties.java | 34 +---
.../paimon/web/api/database/DatabaseManager.java | 40 ++--
.../paimon/web/api/table/ColumnMetadata.java | 50 ++---
.../apache/paimon/web/api/table/TableManager.java | 103 ++++++++++
.../apache/paimon/web/api/table/TableMetadata.java | 185 +++++++++++++++++
.../paimon/web/api/table/TableOptionExtractor.java | 70 +++++++
.../paimon/web/api/catalog/CatalogCreatorTest.java | 39 ++--
.../web/api/database/DatabaseManagerTest.java | 94 +++++++++
.../paimon/web/api/table/TableManagerTest.java | 220 +++++++++++++++++++++
.../apache/paimon/web/common}/enums/Status.java | 2 +-
.../apache/paimon/web/common/result/R.java | 9 +-
paimon-web-server/pom.xml | 14 +-
.../web/server/controller/UserController.java | 4 +-
.../src/main/resources/log4j2-spring.xml | 18 ++
pom.xml | 13 +-
17 files changed, 937 insertions(+), 114 deletions(-)
diff --git a/paimon-web-api/pom.xml b/paimon-web-api/pom.xml
new file mode 100644
index 0000000..6d6886d
--- /dev/null
+++ b/paimon-web-api/pom.xml
@@ -0,0 +1,110 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.apache.paimon</groupId>
+ <artifactId>paimon-webui</artifactId>
+ <version>0.1-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>paimon-web-api</artifactId>
+
+ <properties>
+ <maven.compiler.source>8</maven.compiler.source>
+ <maven.compiler.target>8</maven.compiler.target>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ <paimon.version>0.5-SNAPSHOT</paimon.version>
+ <hadoop.version>2.8.5</hadoop.version>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.paimon</groupId>
+ <artifactId>paimon-bundle</artifactId>
+ <version>${paimon.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.paimon</groupId>
+ <artifactId>paimon-web-common</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.junit.jupiter</groupId>
+ <artifactId>junit-jupiter</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.assertj</groupId>
+ <artifactId>assertj-core</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.hadoop</groupId>
+ <artifactId>hadoop-common</artifactId>
+ <version>${hadoop.version}</version>
+ <scope>test</scope>
+ <exclusions>
+ <exclusion>
+ <groupId>org.apache.avro</groupId>
+ <artifactId>avro</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>log4j</groupId>
+ <artifactId>log4j</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-log4j12</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>jdk.tools</groupId>
+ <artifactId>jdk.tools</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.hadoop</groupId>
+ <artifactId>hadoop-hdfs-client</artifactId>
+ <version>${hadoop.version}</version>
+ <scope>test</scope>
+ <exclusions>
+ <exclusion>
+ <groupId>org.apache.avro</groupId>
+ <artifactId>avro</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>log4j</groupId>
+ <artifactId>log4j</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-log4j12</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ </dependencies>
+</project>
\ No newline at end of file
diff --git
a/paimon-web-api/src/main/java/org/apache/paimon/web/api/catalog/CatalogCreator.java
b/paimon-web-api/src/main/java/org/apache/paimon/web/api/catalog/CatalogCreator.java
new file mode 100644
index 0000000..22514e6
--- /dev/null
+++
b/paimon-web-api/src/main/java/org/apache/paimon/web/api/catalog/CatalogCreator.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.catalog;
+
+import org.apache.paimon.catalog.Catalog;
+import org.apache.paimon.catalog.CatalogContext;
+import org.apache.paimon.catalog.CatalogFactory;
+import org.apache.paimon.fs.Path;
+import org.apache.paimon.options.Options;
+import org.apache.paimon.web.api.common.CatalogProperties;
+
+/** paimon catalog creator. */
+public class CatalogCreator {
+
+ public static Catalog createFilesystemCatalog(String path) {
+ CatalogContext context = CatalogContext.create(new Path(path));
+ return CatalogFactory.createCatalog(context);
+ }
+
+ public static Catalog createHiveCatalog(
+ String warehouse, String metastore, String uri, String
hiveConfDir) {
+ Options options = new Options();
+ options.set(CatalogProperties.WAREHOUSE_LOCATION, warehouse);
+ options.set(CatalogProperties.METASTORE_TYPE, metastore);
+ options.set(CatalogProperties.URI, uri);
+ options.set(CatalogProperties.HIVE_CONF_DIR, hiveConfDir);
+ CatalogContext context = CatalogContext.create(options);
+ return CatalogFactory.createCatalog(context);
+ }
+}
diff --git
a/paimon-web-common/src/main/java/com/apache/paimon/web/common/result/enums/Status.java
b/paimon-web-api/src/main/java/org/apache/paimon/web/api/common/CatalogProperties.java
similarity index 52%
copy from
paimon-web-common/src/main/java/com/apache/paimon/web/common/result/enums/Status.java
copy to
paimon-web-api/src/main/java/org/apache/paimon/web/api/common/CatalogProperties.java
index 0406ba1..c8930fd 100644
---
a/paimon-web-common/src/main/java/com/apache/paimon/web/common/result/enums/Status.java
+++
b/paimon-web-api/src/main/java/org/apache/paimon/web/api/common/CatalogProperties.java
@@ -16,36 +16,16 @@
* limitations under the License.
*/
-package com.apache.paimon.web.common.result.enums;
+package org.apache.paimon.web.api.common;
-/**
- * Status enum.
- *
- * <p><b>NOTE:</b> This enumeration is used to define status codes and
internationalization messages
- * for response data. <br>
- * This is mainly responsible for the internationalization information
returned by the interface
- */
-public enum Status {
- /** response data msg */
- SUCCESS(200, "Successfully"),
- FAILED(400, "Failed"),
-
- USER_NOT_EXIST(10001, "User Not Exist"),
- ;
+/** paimon catalog properties. */
+public class CatalogProperties {
- private final int code;
- private final String msg;
+ public static final String METASTORE_TYPE = "metastore";
- Status(int code, String msg) {
- this.code = code;
- this.msg = msg;
- }
+ public static final String WAREHOUSE_LOCATION = "warehouse";
- public int getCode() {
- return this.code;
- }
+ public static final String URI = "uri";
- public String getMsg() {
- return this.msg;
- }
+ public static final String HIVE_CONF_DIR = "hive-conf-dir";
}
diff --git
a/paimon-web-common/src/main/java/com/apache/paimon/web/common/result/enums/Status.java
b/paimon-web-api/src/main/java/org/apache/paimon/web/api/database/DatabaseManager.java
similarity index 51%
copy from
paimon-web-common/src/main/java/com/apache/paimon/web/common/result/enums/Status.java
copy to
paimon-web-api/src/main/java/org/apache/paimon/web/api/database/DatabaseManager.java
index 0406ba1..c0272bf 100644
---
a/paimon-web-common/src/main/java/com/apache/paimon/web/common/result/enums/Status.java
+++
b/paimon-web-api/src/main/java/org/apache/paimon/web/api/database/DatabaseManager.java
@@ -16,36 +16,30 @@
* limitations under the License.
*/
-package com.apache.paimon.web.common.result.enums;
+package org.apache.paimon.web.api.database;
-/**
- * Status enum.
- *
- * <p><b>NOTE:</b> This enumeration is used to define status codes and
internationalization messages
- * for response data. <br>
- * This is mainly responsible for the internationalization information
returned by the interface
- */
-public enum Status {
- /** response data msg */
- SUCCESS(200, "Successfully"),
- FAILED(400, "Failed"),
+import org.apache.paimon.catalog.Catalog;
- USER_NOT_EXIST(10001, "User Not Exist"),
- ;
+import java.util.List;
- private final int code;
- private final String msg;
+/** paimon database manager. */
+public class DatabaseManager {
+
+ public static void createDatabase(Catalog catalog, String name)
+ throws Catalog.DatabaseAlreadyExistException {
+ catalog.createDatabase(name, false);
+ }
- Status(int code, String msg) {
- this.code = code;
- this.msg = msg;
+ public static boolean databaseExists(Catalog catalog, String name) {
+ return catalog.databaseExists(name);
}
- public int getCode() {
- return this.code;
+ public static List<String> listDatabase(Catalog catalog) {
+ return catalog.listDatabases();
}
- public String getMsg() {
- return this.msg;
+ public static void dropDatabase(Catalog catalog, String name)
+ throws Catalog.DatabaseNotEmptyException,
Catalog.DatabaseNotExistException {
+ catalog.dropDatabase(name, false, true);
}
}
diff --git
a/paimon-web-common/src/main/java/com/apache/paimon/web/common/result/enums/Status.java
b/paimon-web-api/src/main/java/org/apache/paimon/web/api/table/ColumnMetadata.java
similarity index 53%
copy from
paimon-web-common/src/main/java/com/apache/paimon/web/common/result/enums/Status.java
copy to
paimon-web-api/src/main/java/org/apache/paimon/web/api/table/ColumnMetadata.java
index 0406ba1..163f50d 100644
---
a/paimon-web-common/src/main/java/com/apache/paimon/web/common/result/enums/Status.java
+++
b/paimon-web-api/src/main/java/org/apache/paimon/web/api/table/ColumnMetadata.java
@@ -16,36 +16,40 @@
* limitations under the License.
*/
-package com.apache.paimon.web.common.result.enums;
+package org.apache.paimon.web.api.table;
-/**
- * Status enum.
- *
- * <p><b>NOTE:</b> This enumeration is used to define status codes and
internationalization messages
- * for response data. <br>
- * This is mainly responsible for the internationalization information
returned by the interface
- */
-public enum Status {
- /** response data msg */
- SUCCESS(200, "Successfully"),
- FAILED(400, "Failed"),
+import org.apache.paimon.types.DataType;
+
+import javax.annotation.Nullable;
+
+/** table metadata. */
+public class ColumnMetadata {
+
+ private final String name;
- USER_NOT_EXIST(10001, "User Not Exist"),
- ;
+ private final DataType type;
- private final int code;
- private final String msg;
+ private final @Nullable String description;
+
+ public ColumnMetadata(String name, DataType type) {
+ this(name, type, null);
+ }
+
+ public ColumnMetadata(String name, DataType type, String description) {
+ this.name = name;
+ this.type = type;
+ this.description = description;
+ }
- Status(int code, String msg) {
- this.code = code;
- this.msg = msg;
+ public String name() {
+ return this.name;
}
- public int getCode() {
- return this.code;
+ public DataType type() {
+ return this.type;
}
- public String getMsg() {
- return this.msg;
+ public String description() {
+ return this.description;
}
}
diff --git
a/paimon-web-api/src/main/java/org/apache/paimon/web/api/table/TableManager.java
b/paimon-web-api/src/main/java/org/apache/paimon/web/api/table/TableManager.java
new file mode 100644
index 0000000..83188f5
--- /dev/null
+++
b/paimon-web-api/src/main/java/org/apache/paimon/web/api/table/TableManager.java
@@ -0,0 +1,103 @@
+/*
+ * 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.table;
+
+import org.apache.paimon.catalog.Catalog;
+import org.apache.paimon.catalog.Identifier;
+import org.apache.paimon.schema.Schema;
+import org.apache.paimon.table.Table;
+
+import com.google.common.collect.ImmutableList;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/** paimon table manager. */
+public class TableManager {
+
+ public static void createTable(
+ Catalog catalog, String dbName, String tableName, TableMetadata
tableMetadata)
+ throws Catalog.TableAlreadyExistException,
Catalog.DatabaseNotExistException {
+ Schema.Builder schemaBuilder =
+ Schema.newBuilder()
+ .partitionKeys(
+ tableMetadata.primaryKeys() == null
+ ? ImmutableList.of()
+ :
ImmutableList.copyOf(tableMetadata.primaryKeys()))
+ .partitionKeys(
+ tableMetadata.partitionKeys() == null
+ ? ImmutableList.of()
+ :
ImmutableList.copyOf(tableMetadata.partitionKeys()))
+ .comment(tableMetadata.comment() == null ? "" :
tableMetadata.comment())
+ .options(handleOptions(tableMetadata.options()));
+
+ for (ColumnMetadata column : tableMetadata.columns()) {
+ schemaBuilder.column(column.name(), column.type(),
column.description());
+ }
+
+ Schema schema = schemaBuilder.build();
+
+ Identifier identifier = Identifier.create(dbName, tableName);
+
+ catalog.createTable(identifier, schema, false);
+ }
+
+ public static boolean tableExists(Catalog catalog, String dbName, String
tableName) {
+ Identifier identifier = Identifier.create(dbName, tableName);
+ return catalog.tableExists(identifier);
+ }
+
+ public static Table GetTable(Catalog catalog, String dbName, String
tableName)
+ throws Catalog.TableNotExistException {
+ Identifier identifier = Identifier.create(dbName, tableName);
+ return catalog.getTable(identifier);
+ }
+
+ public static List<String> listTables(Catalog catalog, String dbName)
+ throws Catalog.DatabaseNotExistException {
+ return catalog.listTables(dbName);
+ }
+
+ public static void dropTable(Catalog catalog, String dbName, String
tableName)
+ throws Catalog.TableNotExistException {
+ Identifier identifier = Identifier.create(dbName, tableName);
+ catalog.dropTable(identifier, false);
+ }
+
+ public static void renameTable(Catalog catalog, String dbName, String
fromTable, String toTable)
+ throws Catalog.TableAlreadyExistException,
Catalog.TableNotExistException {
+ Identifier fromTableIdentifier = Identifier.create(dbName, fromTable);
+ Identifier toTableIdentifier = Identifier.create(dbName, toTable);
+ catalog.renameTable(fromTableIdentifier, toTableIdentifier, false);
+ }
+
+ private static Map<String, String> handleOptions(Map<String, String>
options) {
+ List<String> keys = TableOptionExtractor.keys();
+ Map<String, String> filteredOptions = new HashMap<>();
+
+ for (String key : options.keySet()) {
+ if (keys.contains(key)) {
+ filteredOptions.put(key, options.get(key));
+ }
+ }
+
+ return filteredOptions;
+ }
+}
diff --git
a/paimon-web-api/src/main/java/org/apache/paimon/web/api/table/TableMetadata.java
b/paimon-web-api/src/main/java/org/apache/paimon/web/api/table/TableMetadata.java
new file mode 100644
index 0000000..67ec73e
--- /dev/null
+++
b/paimon-web-api/src/main/java/org/apache/paimon/web/api/table/TableMetadata.java
@@ -0,0 +1,185 @@
+/*
+ * 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.table;
+
+import com.google.common.base.Preconditions;
+
+import javax.annotation.Nullable;
+
+import java.util.*;
+import java.util.stream.Collectors;
+
+/** table metadata. */
+public class TableMetadata {
+
+ private final List<ColumnMetadata> columns;
+
+ private final List<String> partitionKeys;
+
+ private final List<String> primaryKeys;
+
+ private final Map<String, String> options;
+
+ private final String comment;
+
+ public TableMetadata(
+ List<ColumnMetadata> columns,
+ List<String> partitionKeys,
+ List<String> primaryKeys,
+ Map<String, String> options,
+ String comment) {
+ this.columns = normalizeFields(columns, primaryKeys, partitionKeys);
+ this.partitionKeys = partitionKeys;
+ this.primaryKeys = primaryKeys;
+ this.options = new HashMap<>(options);
+ this.comment = comment;
+ }
+
+ public List<ColumnMetadata> columns() {
+ return columns;
+ }
+
+ public List<String> partitionKeys() {
+ return partitionKeys;
+ }
+
+ public List<String> primaryKeys() {
+ return primaryKeys;
+ }
+
+ public Map<String, String> options() {
+ return options;
+ }
+
+ public String comment() {
+ return comment;
+ }
+
+ private static List<ColumnMetadata> normalizeFields(
+ List<ColumnMetadata> columns, List<String> primaryKeys,
List<String> partitionKeys) {
+ List<String> fieldNames =
+
columns.stream().map(ColumnMetadata::name).collect(Collectors.toList());
+
+ Set<String> duplicateColumns = duplicate(fieldNames);
+ Preconditions.checkState(
+ duplicateColumns.isEmpty(),
+ "Table column %s must not contain duplicate fields. Found: %s",
+ fieldNames,
+ duplicateColumns);
+
+ Set<String> allFields = new HashSet<>(fieldNames);
+
+ duplicateColumns = duplicate(partitionKeys);
+ Preconditions.checkState(
+ duplicateColumns.isEmpty(),
+ "Partition key constraint %s must not contain duplicate
columns. Found: %s",
+ partitionKeys,
+ duplicateColumns);
+ Preconditions.checkState(
+ allFields.containsAll(partitionKeys),
+ "Table column %s should include all partition fields %s",
+ fieldNames,
+ partitionKeys);
+
+ if (primaryKeys.isEmpty()) {
+ return columns;
+ }
+ duplicateColumns = duplicate(primaryKeys);
+ Preconditions.checkState(
+ duplicateColumns.isEmpty(),
+ "Primary key constraint %s must not contain duplicate columns.
Found: %s",
+ primaryKeys,
+ duplicateColumns);
+ Preconditions.checkState(
+ allFields.containsAll(primaryKeys),
+ "Table column %s should include all primary key constraint %s",
+ fieldNames,
+ primaryKeys);
+ Set<String> pkSet = new HashSet<>(primaryKeys);
+ Preconditions.checkState(
+ pkSet.containsAll(partitionKeys),
+ "Primary key constraint %s should include all partition fields
%s",
+ primaryKeys,
+ partitionKeys);
+
+ // primary key should not nullable
+ List<ColumnMetadata> newFields = new ArrayList<>();
+ for (ColumnMetadata field : columns) {
+ if (pkSet.contains(field.name()) && field.type().isNullable()) {
+ newFields.add(
+ new ColumnMetadata(
+ field.name(), field.type().copy(false),
field.description()));
+ } else {
+ newFields.add(field);
+ }
+ }
+ return newFields;
+ }
+
+ private static Set<String> duplicate(List<String> names) {
+ return names.stream()
+ .filter(name -> Collections.frequency(names, name) > 1)
+ .collect(Collectors.toSet());
+ }
+
+ public static TableMetadata.Builder builder() {
+ return new Builder();
+ }
+
+ public static final class Builder {
+ private List<ColumnMetadata> columns = new ArrayList<>();
+
+ private List<String> partitionKeys = new ArrayList<>();
+
+ private List<String> primaryKeys = new ArrayList<>();
+
+ private Map<String, String> options = new HashMap<>();
+
+ @Nullable private String comment;
+
+ public Builder columns(List<ColumnMetadata> columns) {
+ this.columns = new ArrayList<>(columns);
+ return this;
+ }
+
+ public Builder partitionKeys(List<String> partitionKeys) {
+ this.partitionKeys = new ArrayList<>(partitionKeys);
+ return this;
+ }
+
+ public Builder primaryKeys(List<String> primaryKeys) {
+ this.partitionKeys = new ArrayList<>(primaryKeys);
+ return this;
+ }
+
+ public Builder options(Map<String, String> options) {
+ this.options.putAll(options);
+ return this;
+ }
+
+ public Builder comment(String comment) {
+ this.comment = comment;
+ return this;
+ }
+
+ public TableMetadata build() {
+ return new TableMetadata(columns, partitionKeys, primaryKeys,
options, comment);
+ }
+ }
+}
diff --git
a/paimon-web-api/src/main/java/org/apache/paimon/web/api/table/TableOptionExtractor.java
b/paimon-web-api/src/main/java/org/apache/paimon/web/api/table/TableOptionExtractor.java
new file mode 100644
index 0000000..0f19e41
--- /dev/null
+++
b/paimon-web-api/src/main/java/org/apache/paimon/web/api/table/TableOptionExtractor.java
@@ -0,0 +1,70 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.paimon.web.api.table;
+
+import org.apache.paimon.CoreOptions;
+import org.apache.paimon.options.ConfigOption;
+
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.List;
+
+/** table option extractor. */
+public class TableOptionExtractor {
+
+ public static List<String> keys() {
+ List<OptionWithMetaInfo> optionWithMetaInfos =
extractConfigOptions(CoreOptions.class);
+ List<String> keys = new ArrayList<>();
+ for (OptionWithMetaInfo optionWithMetaInfo : optionWithMetaInfos) {
+ keys.add(optionWithMetaInfo.option.key());
+ }
+ return keys;
+ }
+
+ public static List<OptionWithMetaInfo> extractConfigOptions(Class<?>
clazz) {
+ try {
+ List<OptionWithMetaInfo> configOptions = new ArrayList<>(8);
+ Field[] fields = clazz.getFields();
+ for (Field field : fields) {
+ if (isConfigOption(field)) {
+ configOptions.add(
+ new OptionWithMetaInfo((ConfigOption<?>)
field.get(null), field));
+ }
+ }
+ return configOptions;
+ } catch (Exception e) {
+ throw new RuntimeException(
+ "Failed to extract config options from class " + clazz +
'.', e);
+ }
+ }
+
+ private static boolean isConfigOption(Field field) {
+ return field.getType().equals(ConfigOption.class);
+ }
+
+ static class OptionWithMetaInfo {
+ final ConfigOption<?> option;
+ final Field field;
+
+ public OptionWithMetaInfo(ConfigOption<?> option, Field field) {
+ this.option = option;
+ this.field = field;
+ }
+ }
+}
diff --git
a/paimon-web-common/src/main/java/com/apache/paimon/web/common/result/enums/Status.java
b/paimon-web-api/src/test/java/org/apache/paimon/web/api/catalog/CatalogCreatorTest.java
similarity index 53%
copy from
paimon-web-common/src/main/java/com/apache/paimon/web/common/result/enums/Status.java
copy to
paimon-web-api/src/test/java/org/apache/paimon/web/api/catalog/CatalogCreatorTest.java
index 0406ba1..a472ade 100644
---
a/paimon-web-common/src/main/java/com/apache/paimon/web/common/result/enums/Status.java
+++
b/paimon-web-api/src/test/java/org/apache/paimon/web/api/catalog/CatalogCreatorTest.java
@@ -16,36 +16,25 @@
* limitations under the License.
*/
-package com.apache.paimon.web.common.result.enums;
+package org.apache.paimon.web.api.catalog;
-/**
- * Status enum.
- *
- * <p><b>NOTE:</b> This enumeration is used to define status codes and
internationalization messages
- * for response data. <br>
- * This is mainly responsible for the internationalization information
returned by the interface
- */
-public enum Status {
- /** response data msg */
- SUCCESS(200, "Successfully"),
- FAILED(400, "Failed"),
+import org.apache.paimon.catalog.Catalog;
+import org.apache.paimon.catalog.FileSystemCatalog;
- USER_NOT_EXIST(10001, "User Not Exist"),
- ;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
- private final int code;
- private final String msg;
+import static org.assertj.core.api.Assertions.assertThat;
- Status(int code, String msg) {
- this.code = code;
- this.msg = msg;
- }
+/** The test class of catalog creator in {@link CatalogCreator}. */
+public class CatalogCreatorTest {
- public int getCode() {
- return this.code;
- }
+ @TempDir java.nio.file.Path tempFile;
- public String getMsg() {
- return this.msg;
+ @Test
+ public void testCreateFileSystemCatalog() {
+ String warehouse = tempFile.toUri().toString();
+ Catalog catalog = CatalogCreator.createFilesystemCatalog(warehouse);
+ assertThat(catalog).isInstanceOf(FileSystemCatalog.class);
}
}
diff --git
a/paimon-web-api/src/test/java/org/apache/paimon/web/api/database/DatabaseManagerTest.java
b/paimon-web-api/src/test/java/org/apache/paimon/web/api/database/DatabaseManagerTest.java
new file mode 100644
index 0000000..25b71a2
--- /dev/null
+++
b/paimon-web-api/src/test/java/org/apache/paimon/web/api/database/DatabaseManagerTest.java
@@ -0,0 +1,94 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.paimon.web.api.database;
+
+import org.apache.paimon.catalog.Catalog;
+import org.apache.paimon.web.api.catalog.CatalogCreator;
+
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
+
+import java.util.List;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
+
+/** The test class of database manager in {@link DatabaseManager}. */
+public class DatabaseManagerTest {
+
+ @TempDir java.nio.file.Path tempFile;
+ Catalog catalog;
+
+ @BeforeEach
+ public void setUp() {
+ String warehouse = tempFile.toUri().toString();
+ catalog = CatalogCreator.createFilesystemCatalog(warehouse);
+ }
+
+ @AfterEach
+ public void tearDown() throws Exception {
+ if (catalog != null) {
+ catalog.close();
+ }
+ }
+
+ @Test
+ public void testDatabaseExists() throws
Catalog.DatabaseAlreadyExistException {
+ DatabaseManager.createDatabase(catalog, "db_01");
+ boolean exists = DatabaseManager.databaseExists(catalog, "db_01");
+ assertThat(exists).isTrue();
+ }
+
+ @Test
+ public void testCreateDatabase() throws
Catalog.DatabaseAlreadyExistException {
+ DatabaseManager.createDatabase(catalog, "db_01");
+ boolean exists = catalog.databaseExists("db_01");
+ assertThat(exists).isTrue();
+
+ // Create database throws DatabaseAlreadyExistException when database
already exists
+ assertThatExceptionOfType(Catalog.DatabaseAlreadyExistException.class)
+ .isThrownBy(() -> catalog.createDatabase("db_01", false))
+ .withMessage("Database db_01 already exists.");
+ }
+
+ @Test
+ public void testDropDatabase() throws Exception {
+ DatabaseManager.createDatabase(catalog, "db_01");
+ DatabaseManager.dropDatabase(catalog, "db_01");
+ boolean exists = catalog.databaseExists("db_01");
+ assertThat(exists).isFalse();
+
+ // Drop database throws DatabaseNotExistException when database does
not exist
+ assertThatExceptionOfType(Catalog.DatabaseNotExistException.class)
+ .isThrownBy(() -> DatabaseManager.dropDatabase(catalog,
"db_04"))
+ .withMessage("Database db_04 does not exist.");
+ }
+
+ @Test
+ public void testListDatabase() throws
Catalog.DatabaseAlreadyExistException {
+ DatabaseManager.createDatabase(catalog, "db_01");
+ DatabaseManager.createDatabase(catalog, "db_02");
+ DatabaseManager.createDatabase(catalog, "db_03");
+
+ List<String> dbs = DatabaseManager.listDatabase(catalog);
+ assertThat(dbs).contains("db_01", "db_02", "db_03");
+ }
+}
diff --git
a/paimon-web-api/src/test/java/org/apache/paimon/web/api/table/TableManagerTest.java
b/paimon-web-api/src/test/java/org/apache/paimon/web/api/table/TableManagerTest.java
new file mode 100644
index 0000000..8e4db37
--- /dev/null
+++
b/paimon-web-api/src/test/java/org/apache/paimon/web/api/table/TableManagerTest.java
@@ -0,0 +1,220 @@
+/*
+ * 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.table;
+
+import org.apache.paimon.catalog.Catalog;
+import org.apache.paimon.table.Table;
+import org.apache.paimon.types.DataTypes;
+import org.apache.paimon.web.api.catalog.CatalogCreator;
+import org.apache.paimon.web.api.database.DatabaseManager;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Lists;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
+
+/** The test class of table manager in {@link TableManager}. */
+public class TableManagerTest {
+
+ @TempDir java.nio.file.Path tempFile;
+ Catalog catalog;
+ private static final String DB_NAME = "test_db";
+ private static final String TABLE_NAME = "test_table";
+ private static final String DEFAULT_TABLE = "default_table";
+
+ @BeforeEach
+ public void setUp() throws Exception {
+ String warehouse = tempFile.toUri().toString();
+ catalog = CatalogCreator.createFilesystemCatalog(warehouse);
+ DatabaseManager.createDatabase(catalog, DB_NAME);
+ TableManager.createTable(
+ catalog,
+ DB_NAME,
+ DEFAULT_TABLE,
+ new TableMetadata(
+ Lists.newArrayList(new ColumnMetadata("id",
DataTypes.STRING(), "")),
+ ImmutableList.of(),
+ ImmutableList.of(),
+ ImmutableMap.of(),
+ ""));
+ }
+
+ @AfterEach
+ public void tearDown() throws Exception {
+ if (catalog != null) {
+ catalog.close();
+ }
+ }
+
+ @Test
+ public void testTableExists() {
+ boolean exists = TableManager.tableExists(catalog, DB_NAME,
TABLE_NAME);
+ assertThat(exists).isFalse();
+ assertThat(TableManager.tableExists(catalog, DB_NAME,
DEFAULT_TABLE)).isTrue();
+ }
+
+ @Test
+ public void testCreateTable()
+ throws Catalog.TableAlreadyExistException,
Catalog.DatabaseNotExistException {
+ ArrayList<ColumnMetadata> columns =
+ Lists.newArrayList(
+ new ColumnMetadata("id", DataTypes.BIGINT()),
+ new ColumnMetadata("name", DataTypes.STRING()),
+ new ColumnMetadata("age", DataTypes.INT()),
+ new ColumnMetadata("birth", DataTypes.DATE()));
+
+ ArrayList<String> primaryKeys = Lists.newArrayList("id", "birth");
+
+ ArrayList<String> partitionKeys = Lists.newArrayList("birth");
+
+ Map<String, String> options =
+ ImmutableMap.of(
+ "bucket", "4",
+ "changelog-producer", "input");
+
+ TableMetadata tableMetadata =
+ TableMetadata.builder()
+ .columns(columns)
+ .partitionKeys(partitionKeys)
+ .primaryKeys(primaryKeys)
+ .options(options)
+ .build();
+
+ TableManager.createTable(catalog, DB_NAME, TABLE_NAME, tableMetadata);
+ boolean exists = TableManager.tableExists(catalog, DB_NAME,
TABLE_NAME);
+ assertThat(exists).isTrue();
+
+ // Create table throws Exception when table is system table
+ assertThatExceptionOfType(IllegalArgumentException.class)
+ .isThrownBy(
+ () ->
+ TableManager.createTable(
+ catalog, DB_NAME, "$system_table",
tableMetadata))
+ .withMessage(
+ "Cannot 'createTable' for system table
'Identifier{database='test_db', table='$system_table'}', please use data
table.");
+
+ // Create table throws DatabaseNotExistException when database does
not exist
+ assertThatExceptionOfType(Catalog.DatabaseNotExistException.class)
+ .isThrownBy(
+ () -> TableManager.createTable(catalog, "db_01",
TABLE_NAME, tableMetadata))
+ .withMessage("Database db_01 does not exist.");
+
+ // Create table throws TableAlreadyExistException when table already
exists and
+ // ignoreIfExists is false
+ assertThatExceptionOfType(Catalog.TableAlreadyExistException.class)
+ .isThrownBy(
+ () -> TableManager.createTable(catalog, DB_NAME,
TABLE_NAME, tableMetadata))
+ .withMessage("Table test_db.test_table already exists.");
+ }
+
+ @Test
+ public void testGetTable() throws Catalog.TableNotExistException {
+ Table table = TableManager.GetTable(catalog, DB_NAME, DEFAULT_TABLE);
+ assertThat(table).isInstanceOf(Table.class);
+
+ // Get table throws TableNotExistException when table does not exist
+ assertThatExceptionOfType(Catalog.TableNotExistException.class)
+ .isThrownBy(() -> TableManager.GetTable(catalog, DB_NAME,
TABLE_NAME))
+ .withMessage("Table test_db.test_table does not exist.");
+ }
+
+ @Test
+ public void testListTables() throws Catalog.DatabaseNotExistException {
+ List<String> tables = TableManager.listTables(catalog, DB_NAME);
+ assertThat(tables).contains("default_table");
+
+ // List tables throws DatabaseNotExistException when database does not
exist
+ assertThatExceptionOfType(Catalog.DatabaseNotExistException.class)
+ .isThrownBy(() -> TableManager.listTables(catalog, "db_01"))
+ .withMessage("Database db_01 does not exist.");
+ }
+
+ @Test
+ public void testDropTable() throws Exception {
+ TableManager.createTable(
+ catalog,
+ DB_NAME,
+ "tb_01",
+ new TableMetadata(
+ Lists.newArrayList(new ColumnMetadata("id",
DataTypes.STRING(), "")),
+ ImmutableList.of(),
+ ImmutableList.of(),
+ ImmutableMap.of(),
+ ""));
+ assertThat(TableManager.tableExists(catalog, DB_NAME,
"tb_01")).isTrue();
+
+ TableManager.dropTable(catalog, DB_NAME, "tb_01");
+ assertThat(TableManager.tableExists(catalog, DB_NAME,
"tb_01")).isFalse();
+
+ // Drop table throws TableNotExistException when table does not exist
+ assertThatExceptionOfType(Catalog.TableNotExistException.class)
+ .isThrownBy(() -> TableManager.dropTable(catalog, DB_NAME,
"tb_02"))
+ .withMessage("Table test_db.tb_02 does not exist.");
+ }
+
+ @Test
+ public void testRenameTable() throws Exception {
+ TableManager.createTable(
+ catalog,
+ DB_NAME,
+ "tb_01",
+ new TableMetadata(
+ Lists.newArrayList(new ColumnMetadata("id",
DataTypes.STRING(), "")),
+ ImmutableList.of(),
+ ImmutableList.of(),
+ ImmutableMap.of(),
+ ""));
+
+ TableManager.renameTable(catalog, DB_NAME, "tb_01", "tb_02");
+ assertThat(TableManager.tableExists(catalog, DB_NAME,
"tb_01")).isFalse();
+ assertThat(TableManager.tableExists(catalog, DB_NAME,
"tb_02")).isTrue();
+
+ // Rename table throws TableNotExistException when fromTable does not
exist
+ assertThatExceptionOfType(Catalog.TableNotExistException.class)
+ .isThrownBy(() -> TableManager.renameTable(catalog, DB_NAME,
"tb_01", "table_04"))
+ .withMessage("Table test_db.tb_01 does not exist.");
+
+ // Rename table throws TableAlreadyExistException when toTable already
exists
+ TableManager.createTable(
+ catalog,
+ DB_NAME,
+ "tb_03",
+ new TableMetadata(
+ Lists.newArrayList(new ColumnMetadata("id",
DataTypes.STRING(), "")),
+ ImmutableList.of(),
+ ImmutableList.of(),
+ ImmutableMap.of(),
+ ""));
+
+ assertThatExceptionOfType(Catalog.TableAlreadyExistException.class)
+ .isThrownBy(
+ () -> TableManager.renameTable(catalog, DB_NAME,
"tb_03", "default_table"))
+ .withMessage("Table test_db.default_table already exists.");
+ }
+}
diff --git
a/paimon-web-common/src/main/java/com/apache/paimon/web/common/result/enums/Status.java
b/paimon-web-common/src/main/java/org/apache/paimon/web/common/enums/Status.java
similarity index 96%
rename from
paimon-web-common/src/main/java/com/apache/paimon/web/common/result/enums/Status.java
rename to
paimon-web-common/src/main/java/org/apache/paimon/web/common/enums/Status.java
index 0406ba1..cb957d5 100644
---
a/paimon-web-common/src/main/java/com/apache/paimon/web/common/result/enums/Status.java
+++
b/paimon-web-common/src/main/java/org/apache/paimon/web/common/enums/Status.java
@@ -16,7 +16,7 @@
* limitations under the License.
*/
-package com.apache.paimon.web.common.result.enums;
+package org.apache.paimon.web.common.enums;
/**
* Status enum.
diff --git
a/paimon-web-common/src/main/java/com/apache/paimon/web/common/result/R.java
b/paimon-web-common/src/main/java/org/apache/paimon/web/common/result/R.java
similarity index 94%
rename from
paimon-web-common/src/main/java/com/apache/paimon/web/common/result/R.java
rename to
paimon-web-common/src/main/java/org/apache/paimon/web/common/result/R.java
index d4378d6..fa2be30 100644
--- a/paimon-web-common/src/main/java/com/apache/paimon/web/common/result/R.java
+++ b/paimon-web-common/src/main/java/org/apache/paimon/web/common/result/R.java
@@ -16,14 +16,13 @@
* limitations under the License.
*/
-package com.apache.paimon.web.common.result;
+package org.apache.paimon.web.common.result;
+
+import org.apache.paimon.web.common.enums.Status;
-import com.apache.paimon.web.common.result.enums.Status;
import lombok.Data;
-/**
- * result
- */
+/** result */
@Data
public class R<T> {
/** result code */
diff --git a/paimon-web-server/pom.xml b/paimon-web-server/pom.xml
index 87f6d8a..bbbac21 100644
--- a/paimon-web-server/pom.xml
+++ b/paimon-web-server/pom.xml
@@ -34,14 +34,11 @@ under the License.
Paimon Web Server is a server for the [Apache
Paimon](https://paimon.apache.org/) project.
</description>
- <properties>
- </properties>
<dependencies>
-
<dependency>
<groupId>org.apache.paimon</groupId>
<artifactId>paimon-web-common</artifactId>
- <version>${paimon.version}</version>
+ <version>${project.version}</version>
</dependency>
<dependency>
@@ -66,6 +63,7 @@ under the License.
</exclusion>
</exclusions>
</dependency>
+
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
@@ -76,6 +74,7 @@ under the License.
</exclusion>
</exclusions>
</dependency>
+
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
@@ -98,11 +97,13 @@ under the License.
<artifactId>junit-jupiter</artifactId>
<scope>test</scope>
</dependency>
+
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-test</artifactId>
<scope>test</scope>
</dependency>
+
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
@@ -139,6 +140,7 @@ under the License.
</includes>
</resource>
</resources>
+
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
@@ -159,6 +161,7 @@ under the License.
</execution>
</executions>
</plugin>
+
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
@@ -179,6 +182,7 @@ under the License.
</execution>
</executions>
</plugin>
+
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
@@ -202,6 +206,7 @@ under the License.
</execution>
</executions>
</plugin>
+
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
@@ -209,7 +214,6 @@ under the License.
<configuration>
<classesDirectory>target/classes/</classesDirectory>
<excludes>
- <!--注意这玩意默认从编译结果目录开始算目录结构-->
<exclude>/application*.yml</exclude>
<exclude>/mybatis*.xml</exclude>
<exclude>/DinkyFlinkDockerfile</exclude>
diff --git
a/paimon-web-server/src/main/java/org/apache/paimon/web/server/controller/UserController.java
b/paimon-web-server/src/main/java/org/apache/paimon/web/server/controller/UserController.java
index 182563a..737c3e8 100644
---
a/paimon-web-server/src/main/java/org/apache/paimon/web/server/controller/UserController.java
+++
b/paimon-web-server/src/main/java/org/apache/paimon/web/server/controller/UserController.java
@@ -18,10 +18,10 @@
package org.apache.paimon.web.server.controller;
+import org.apache.paimon.web.common.result.R;
import org.apache.paimon.web.server.data.model.User;
import org.apache.paimon.web.server.service.UserService;
-import com.apache.paimon.web.common.result.R;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
@@ -29,7 +29,7 @@ import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
-import static com.apache.paimon.web.common.result.enums.Status.USER_NOT_EXIST;
+import static org.apache.paimon.web.common.enums.Status.USER_NOT_EXIST;
/** User api controller. */
@Slf4j
diff --git a/paimon-web-server/src/main/resources/log4j2-spring.xml
b/paimon-web-server/src/main/resources/log4j2-spring.xml
index e3bc44a..dbf95f7 100644
--- a/paimon-web-server/src/main/resources/log4j2-spring.xml
+++ b/paimon-web-server/src/main/resources/log4j2-spring.xml
@@ -1,4 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
+<!--
+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.
+-->
<configuration status="OFF" monitorInterval="600">
<Properties>
<property name="LOG_PATH">./logs/</property>
diff --git a/pom.xml b/pom.xml
index 4b14536..5f34879 100644
--- a/pom.xml
+++ b/pom.xml
@@ -27,6 +27,7 @@ under the License.
<module>paimon-web-server</module>
<module>paimon-web-common</module>
<module>paimon-web-gateway</module>
+ <module>paimon-web-api</module>
</modules>
<parent>
@@ -61,7 +62,7 @@ under the License.
</scm>
<properties>
- <paimon.version>0.1-SNAPSHOT</paimon.version>
+ <project.version>0.1-SNAPSHOT</project.version>
<java.version>8</java.version>
<maven-dependency-plugin.version>3.5.0</maven-dependency-plugin.version>
<mysql-connector-java.version>8.0.28</mysql-connector-java.version>
@@ -80,6 +81,7 @@ under the License.
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<junit5.version>5.8.1</junit5.version>
+ <assertj.version>3.23.1</assertj.version>
<slf4j.version>1.7.25</slf4j.version>
<log4j.version>2.17.1</log4j.version>
<guava.version>31.1-jre</guava.version>
@@ -125,6 +127,13 @@ under the License.
<version>${junit5.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.assertj</groupId>
+ <artifactId>assertj-core</artifactId>
+ <version>${assertj.version}</version>
+ <scope>test</scope>
+ </dependency>
+
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
@@ -167,7 +176,6 @@ under the License.
<version>${mysql-connector-java.version}</version>
</dependency>
-
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
@@ -185,7 +193,6 @@ under the License.
<build>
<plugins>
-
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>