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

mikexue pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/eventmesh.git


The following commit(s) were added to refs/heads/master by this push:
     new 62935c4c2 [ISSUE #4494] RESTful API framework for EventMeshAdmin 
(#4498)
62935c4c2 is described below

commit 62935c4c256d019bcf74316452d5bb413e3621b4
Author: Pil0tXia <[email protected]>
AuthorDate: Fri Oct 20 19:07:52 2023 +0800

    [ISSUE #4494] RESTful API framework for EventMeshAdmin (#4498)
    
    * restful response optimize part1
    
    * restful response optimize part2
    
    * restful response optimize part3
    
    * restful response optimize part4
    
    * exception handling
    
    * exception handling part2
    
    * exception handling part3
    
    * exception handling part4
    
    * exception handling part5
    
    * add error type to error displaying
    
    * warp json message response instead of string
---
 .../Constants.java => common/ConfigConst.java}     |  15 ++-
 .../apache/eventmesh/admin/common/NacosConst.java  |  43 ++++++
 .../eventmesh/admin/config/AdminProperties.java    |   6 +-
 .../eventmesh/admin/config/MetaTypeConfig.java     |   4 +-
 .../admin/controller/SubscriptionController.java   |  24 ++--
 .../org/apache/eventmesh/admin/dto/Result.java     | 144 +++++++++++++++++++++
 .../org/apache/eventmesh/admin/enums/Errors.java   |  91 +++++++++++++
 ...{EventMeshException.java => BaseException.java} |  39 ++++--
 .../admin/exception/EventMeshAdminException.java   |  23 ++--
 .../admin/exception/EventMeshException.java        |  22 +---
 .../admin/exception/GlobalExceptionHandler.java    |  61 +++++++++
 .../eventmesh/admin/exception/MetaException.java   |  19 ++-
 .../admin/service/SubscriptionService.java         |   7 +-
 .../service/impl/EtcdSubscriptionService.java      |   7 +-
 .../service/impl/NacosSubscriptionService.java     |  85 ++++++------
 .../ExceptionUtils.java}                           |  41 +++---
 16 files changed, 487 insertions(+), 144 deletions(-)

diff --git 
a/eventmesh-admin/src/main/java/org/apache/eventmesh/admin/config/Constants.java
 
b/eventmesh-admin/src/main/java/org/apache/eventmesh/admin/common/ConfigConst.java
similarity index 82%
rename from 
eventmesh-admin/src/main/java/org/apache/eventmesh/admin/config/Constants.java
rename to 
eventmesh-admin/src/main/java/org/apache/eventmesh/admin/common/ConfigConst.java
index d907c803d..150231672 100644
--- 
a/eventmesh-admin/src/main/java/org/apache/eventmesh/admin/config/Constants.java
+++ 
b/eventmesh-admin/src/main/java/org/apache/eventmesh/admin/common/ConfigConst.java
@@ -15,11 +15,11 @@
  * limitations under the License.
  */
 
-package org.apache.eventmesh.admin.config;
+package org.apache.eventmesh.admin.common;
 
-public class Constants {
+public class ConfigConst {
 
-    // config
+    // yml config
     public static final String ADMIN_PROPS_PREFIX = "eventmesh";
     public static final String META_TYPE_NACOS = "nacos";
     public static final String META_TYPE_ETCD = "etcd";
@@ -28,7 +28,10 @@ public class Constants {
     public static final String HTTP_PREFIX = "http://";;
     public static final String HTTPS_PREFIX = "https://";;
 
-    // Nacos
-    public static final String NACOS_LOGIN_API = "/nacos/v1/auth/login";
-    public static final String NACOS_CONFIGS_API = "/nacos/v1/cs/configs";
+    // common
+    /**
+     * colon with space
+     */
+    public static final String COLON = ": ";
+
 }
diff --git 
a/eventmesh-admin/src/main/java/org/apache/eventmesh/admin/common/NacosConst.java
 
b/eventmesh-admin/src/main/java/org/apache/eventmesh/admin/common/NacosConst.java
new file mode 100644
index 000000000..07e7d9378
--- /dev/null
+++ 
b/eventmesh-admin/src/main/java/org/apache/eventmesh/admin/common/NacosConst.java
@@ -0,0 +1,43 @@
+/*
+ * 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.eventmesh.admin.common;
+
+public class NacosConst {
+
+    public static final String LOGIN_API = "/nacos/v1/auth/login";
+
+    public static final String LOGIN_REQ_USERNAME = "username";
+    public static final String LOGIN_REQ_PASSWORD = "password";
+
+    public static final String LOGIN_RESP_TOKEN = "accessToken";
+
+    public static final String CONFIGS_API = "/nacos/v1/cs/configs";
+
+    public static final String CONFIGS_REQ_PAGE = "pageNo";
+    public static final String CONFIGS_REQ_PAGE_SIZE = "pageSize";
+    public static final String CONFIGS_REQ_DATAID = "dataId";
+    public static final String CONFIGS_REQ_GROUP = "group";
+    public static final String CONFIGS_REQ_SEARCH = "search";
+    public static final String CONFIGS_REQ_TOKEN = "accessToken";
+
+    public static final String CONFIGS_RESP_CONTENT_LIST = "pageItems"; // 
json page data list field
+    public static final String CONFIGS_RESP_CONTENT = "content"; // json page 
data field
+    public static final String CONFIGS_RESP_PAGES = "pagesAvailable"; // json 
total pages field
+    public static final String CONFIGS_RESP_DATAID = "dataId";
+    public static final String CONFIGS_RESP_GROUP = "group";
+}
diff --git 
a/eventmesh-admin/src/main/java/org/apache/eventmesh/admin/config/AdminProperties.java
 
b/eventmesh-admin/src/main/java/org/apache/eventmesh/admin/config/AdminProperties.java
index def5a687f..cce660728 100644
--- 
a/eventmesh-admin/src/main/java/org/apache/eventmesh/admin/config/AdminProperties.java
+++ 
b/eventmesh-admin/src/main/java/org/apache/eventmesh/admin/config/AdminProperties.java
@@ -17,6 +17,8 @@
 
 package org.apache.eventmesh.admin.config;
 
+import org.apache.eventmesh.admin.common.ConfigConst;
+
 import org.springframework.boot.context.properties.ConfigurationProperties;
 import org.springframework.stereotype.Component;
 
@@ -24,7 +26,7 @@ import lombok.Data;
 
 @Data
 @Component
-@ConfigurationProperties(prefix = Constants.ADMIN_PROPS_PREFIX)
+@ConfigurationProperties(prefix = ConfigConst.ADMIN_PROPS_PREFIX)
 public class AdminProperties {
 
     private MetaProperties meta = new MetaProperties();
@@ -34,7 +36,7 @@ public class AdminProperties {
     @Data
     public static class MetaProperties {
 
-        private String type = Constants.META_TYPE_NACOS;
+        private String type = ConfigConst.META_TYPE_NACOS;
 
         private NacosProperties nacos = new NacosProperties();
 
diff --git 
a/eventmesh-admin/src/main/java/org/apache/eventmesh/admin/config/MetaTypeConfig.java
 
b/eventmesh-admin/src/main/java/org/apache/eventmesh/admin/config/MetaTypeConfig.java
index 3b4f19228..4be780159 100644
--- 
a/eventmesh-admin/src/main/java/org/apache/eventmesh/admin/config/MetaTypeConfig.java
+++ 
b/eventmesh-admin/src/main/java/org/apache/eventmesh/admin/config/MetaTypeConfig.java
@@ -17,8 +17,8 @@
 
 package org.apache.eventmesh.admin.config;
 
-import static org.apache.eventmesh.admin.config.Constants.META_TYPE_ETCD;
-import static org.apache.eventmesh.admin.config.Constants.META_TYPE_NACOS;
+import static org.apache.eventmesh.admin.common.ConfigConst.META_TYPE_ETCD;
+import static org.apache.eventmesh.admin.common.ConfigConst.META_TYPE_NACOS;
 
 import org.apache.eventmesh.admin.service.ConnectionService;
 import org.apache.eventmesh.admin.service.SubscriptionService;
diff --git 
a/eventmesh-admin/src/main/java/org/apache/eventmesh/admin/controller/SubscriptionController.java
 
b/eventmesh-admin/src/main/java/org/apache/eventmesh/admin/controller/SubscriptionController.java
index f59523790..0c826731c 100644
--- 
a/eventmesh-admin/src/main/java/org/apache/eventmesh/admin/controller/SubscriptionController.java
+++ 
b/eventmesh-admin/src/main/java/org/apache/eventmesh/admin/controller/SubscriptionController.java
@@ -17,13 +17,13 @@
 
 package org.apache.eventmesh.admin.controller;
 
-import org.apache.eventmesh.admin.dto.SubscriptionResponse;
-import org.apache.eventmesh.admin.exception.EventMeshAdminException;
+import org.apache.eventmesh.admin.dto.Result;
+import org.apache.eventmesh.admin.model.SubscriptionInfo;
 import org.apache.eventmesh.admin.service.SubscriptionService;
 
+import java.util.List;
+
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.http.HttpStatus;
-import org.springframework.http.ResponseEntity;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestParam;
@@ -50,12 +50,8 @@ public class SubscriptionController {
      * @return config content
      */
     @GetMapping("/subscription")
-    public ResponseEntity<String> retrieveSubscription(@RequestParam("dataId") 
String dataId, @RequestParam("group") String group) {
-        try {
-            return 
ResponseEntity.ok(subscriptionService.retrieveConfig(dataId, group));
-        } catch (EventMeshAdminException e) {
-            return 
ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(e.getMessage());
-        }
+    public Result<String> retrieveSubscription(@RequestParam("dataId") String 
dataId, @RequestParam("group") String group) {
+        return Result.success(subscriptionService.retrieveConfig(dataId, 
group));
     }
 
     /**
@@ -68,16 +64,12 @@ public class SubscriptionController {
      * @return config properties and base64 encoded config content
      */
     @GetMapping("/subscriptions")
-    public ResponseEntity<SubscriptionResponse> listSubscriptions(
+    public Result<List<SubscriptionInfo>> listSubscriptions(
         @RequestParam(name = "page", defaultValue = "1") Integer page,
         @RequestParam(name = "size", defaultValue = "10") Integer size,
         @RequestParam(name = "dataId", defaultValue = CLIENT_DATA_ID_PATTERN) 
String dataId,
         @RequestParam(name = "group", defaultValue = "") String group) {
-        try {
-            return ResponseEntity.ok(subscriptionService.retrieveConfigs(page, 
size, dataId, group));
-        } catch (EventMeshAdminException e) {
-            return 
ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(new 
SubscriptionResponse(e.getMessage()));
-        }
+        return Result.success(subscriptionService.retrieveConfigs(page, size, 
dataId, group));
     }
 
 }
diff --git 
a/eventmesh-admin/src/main/java/org/apache/eventmesh/admin/dto/Result.java 
b/eventmesh-admin/src/main/java/org/apache/eventmesh/admin/dto/Result.java
new file mode 100644
index 000000000..15b3dc2f4
--- /dev/null
+++ b/eventmesh-admin/src/main/java/org/apache/eventmesh/admin/dto/Result.java
@@ -0,0 +1,144 @@
+/*
+ * 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.eventmesh.admin.dto;
+
+import static org.apache.eventmesh.admin.enums.Errors.SUCCESS;
+
+import org.apache.eventmesh.admin.enums.Errors;
+import org.apache.eventmesh.admin.exception.BaseException;
+
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * A RESTful response DTO.
+ */
+
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class Result<T> {
+
+    private T data;
+
+    private Integer pages;
+
+    private Message message;
+
+    public Result(Message message) {
+        this.message = message;
+    }
+
+    public Result(T data, Integer pages) {
+        this.data = data;
+        this.pages = pages;
+    }
+
+    /**
+     * The request is valid and the result is wrapped in {@link Result}.
+     */
+    public static <T> Result<T> success() {
+        return new Result<>(new Message(SUCCESS));
+    }
+
+    public static <T> Result<T> success(Result<T> result) {
+        result.setMessage(new Message(SUCCESS));
+        return result;
+    }
+
+    public static <T> Result<T> success(T data) {
+        return new Result<>(data, null, new Message(SUCCESS));
+    }
+
+    /**
+     * The request is valid and the result is returned in {@link 
ResponseEntity}.
+     * Logic issues should use 422 Unprocessable Entity instead of 200 OK.
+     */
+    public static <T> ResponseEntity<Result<T>> ok() {
+        return ResponseEntity.ok(new Result<>(new Message(SUCCESS)));
+    }
+
+    public static <T> ResponseEntity<Result<T>> ok(Result<T> result) {
+        result.setMessage(new Message(SUCCESS));
+        return ResponseEntity.ok(result);
+    }
+
+    /**
+     * The request is invalid.
+     */
+    public static <T> ResponseEntity<Result<T>> badRequest(String message) {
+        return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new 
Result<>(new Message(message)));
+    }
+
+    /**
+     * The request is valid but cannot be processed due to business logic 
issues.
+     */
+    public static <T> ResponseEntity<Result<T>> unprocessable(String message) {
+        return ResponseEntity.status(HttpStatus.UNPROCESSABLE_ENTITY).body(new 
Result<>(new Message(message)));
+    }
+
+    /**
+     * Uncaught exception happened in EventMeshAdmin application.
+     */
+    public static <T> ResponseEntity<Result<T>> internalError(String message) {
+        return 
ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(new Result<>(new 
Message(message)));
+    }
+
+    /**
+     * Upstream service unavailable such as Meta.
+     */
+    public static <T> ResponseEntity<Result<T>> badGateway(String message) {
+        return ResponseEntity.status(HttpStatus.BAD_GATEWAY).body(new 
Result<>(new Message(message)));
+    }
+
+    @Data
+    public static class Message {
+
+        private String name;
+
+        private String type;
+
+        private String desc;
+
+        public Message(BaseException e) {
+            this.name = e.getErrors().name();
+            this.type = e.getErrors().getType().name();
+            this.desc = e.getMessage();
+        }
+
+        /**
+         * Only recommended for returning successful results,
+         * the stack trace cannot be displayed when returning unsuccessful 
results.
+         */
+        public Message(Errors errors) {
+            this.name = errors.name();
+            this.type = errors.getType().name();
+            this.desc = errors.getDesc(); // no stack trace
+        }
+
+        public Message(String desc) {
+            this.desc = desc;
+        }
+    }
+}
diff --git 
a/eventmesh-admin/src/main/java/org/apache/eventmesh/admin/enums/Errors.java 
b/eventmesh-admin/src/main/java/org/apache/eventmesh/admin/enums/Errors.java
new file mode 100644
index 000000000..3854993a4
--- /dev/null
+++ b/eventmesh-admin/src/main/java/org/apache/eventmesh/admin/enums/Errors.java
@@ -0,0 +1,91 @@
+/*
+ * 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.eventmesh.admin.enums;
+
+import static org.apache.eventmesh.admin.common.ConfigConst.COLON;
+
+import org.springframework.http.HttpStatus;
+
+import lombok.Getter;
+
+/**
+ * An enumeration class that conforms to the RESTful specifications and custom 
error reporting requirements.
+ * <ul>
+ *   <li>The 'code' field is used to return the HTTP status code using {@link 
HttpStatus}.</li>
+ *   <li>The 'type' field represents the major category of the error.</li>
+ *   <li>the 'desc' field represents the detailed subcategory and information 
of the error.</li>
+ * </ul>
+ */
+
+@Getter
+public enum Errors {
+
+    SUCCESS(HttpStatus.OK, Types.SUCCESS, "Operation success."),
+
+    NACOS_SDK_CONFIG_ERR(HttpStatus.INTERNAL_SERVER_ERROR, 
Types.SDK_CONFIG_ERR,
+        "Failed to create Nacos ConfigService. Please check EventMeshAdmin 
application configuration."),
+
+    NACOS_GET_CONFIGS_ERR(HttpStatus.BAD_GATEWAY, Types.META_COM_ERR, "Failed 
to retrieve Nacos config(s)."),
+
+    NACOS_EMPTY_RESP_ERR(HttpStatus.BAD_GATEWAY, Types.META_COM_ERR, "No 
result returned by Nacos. Please check Nacos."),
+
+    NACOS_LOGIN_ERR(HttpStatus.UNAUTHORIZED, Types.META_COM_ERR, "Nacos login 
failed."),
+
+    NACOS_LOGIN_EMPTY_RESP_ERR(HttpStatus.BAD_GATEWAY, Types.META_COM_ERR, 
"Nacos didn't return accessToken. Please check Nacos status."),
+    ;
+
+    // error code
+    private final HttpStatus code;
+
+    // error type
+    private final Types type;
+
+    // error message
+    private final String desc;
+
+    Errors(HttpStatus code, Types type, String desc) {
+        this.code = code;
+        this.type = type;
+        this.desc = desc;
+    }
+
+    @Override
+    public String toString() {
+        return name() + " of " + type + COLON + desc;
+    }
+
+    @Getter
+    public enum Types {
+
+        SUCCESS("Successfully received and processed"),
+
+        SDK_CONFIG_ERR("The Meta SDK config in EventMeshAdmin application.yml 
error"),
+
+        META_COM_ERR("Network communication to Meta error"),
+        ;
+
+        /**
+         * Helpful for understanding and not used for now
+         */
+        private final String desc;
+
+        Types(String desc) {
+            this.desc = desc;
+        }
+    }
+}
diff --git 
a/eventmesh-admin/src/main/java/org/apache/eventmesh/admin/exception/EventMeshException.java
 
b/eventmesh-admin/src/main/java/org/apache/eventmesh/admin/exception/BaseException.java
similarity index 52%
copy from 
eventmesh-admin/src/main/java/org/apache/eventmesh/admin/exception/EventMeshException.java
copy to 
eventmesh-admin/src/main/java/org/apache/eventmesh/admin/exception/BaseException.java
index 8405fd76c..db2e3fd50 100644
--- 
a/eventmesh-admin/src/main/java/org/apache/eventmesh/admin/exception/EventMeshException.java
+++ 
b/eventmesh-admin/src/main/java/org/apache/eventmesh/admin/exception/BaseException.java
@@ -17,27 +17,38 @@
 
 package org.apache.eventmesh.admin.exception;
 
-public class EventMeshException extends EventMeshAdminException {
+import static org.apache.eventmesh.admin.common.ConfigConst.COLON;
 
-    private static final long serialVersionUID = 5648256502005456586L;
+import org.apache.eventmesh.admin.enums.Errors;
+import org.apache.eventmesh.admin.utils.ExceptionUtils;
 
-    public EventMeshException(String message) {
-        super(message);
-    }
+import lombok.Getter;
 
-    public EventMeshException(String message, Throwable cause) {
-        super(message, cause);
-    }
+/**
+ * Exceptions in EventMeshAdmin application
+ */
 
-    public EventMeshException(Throwable cause) {
-        super(cause);
+@Getter
+public class BaseException extends RuntimeException {
+
+    private static final long serialVersionUID = 3509261993355721168L;
+
+    private Errors errors;
+
+    public BaseException(String message) {
+        super(message);
     }
 
-    public EventMeshException(String message, Throwable cause, boolean 
enableSuppression, boolean writableStackTrace) {
-        super(message, cause, enableSuppression, writableStackTrace);
+    /**
+     * Customized error reporting using enums and exceptions
+     */
+    public BaseException(Errors errors, Throwable cause) {
+        super(ExceptionUtils.trimDesc(errors.getDesc()) + COLON + 
cause.getMessage(), cause);
+        this.errors = errors;
     }
 
-    public EventMeshException(Integer errCode, String errMsg) {
-        super(String.format("errorCode: %s, errorMessage: %s", errCode, 
errMsg));
+    public BaseException(Errors errors) {
+        super(errors.getDesc());
+        this.errors = errors;
     }
 }
diff --git 
a/eventmesh-admin/src/main/java/org/apache/eventmesh/admin/exception/EventMeshAdminException.java
 
b/eventmesh-admin/src/main/java/org/apache/eventmesh/admin/exception/EventMeshAdminException.java
index 1118a981d..3847f680c 100644
--- 
a/eventmesh-admin/src/main/java/org/apache/eventmesh/admin/exception/EventMeshAdminException.java
+++ 
b/eventmesh-admin/src/main/java/org/apache/eventmesh/admin/exception/EventMeshAdminException.java
@@ -17,7 +17,13 @@
 
 package org.apache.eventmesh.admin.exception;
 
-public class EventMeshAdminException extends RuntimeException {
+import org.apache.eventmesh.admin.enums.Errors;
+
+/**
+ * EventMeshAdmin Application side exception
+ */
+
+public class EventMeshAdminException extends BaseException {
 
     private static final long serialVersionUID = 2002022502005456586L;
 
@@ -25,15 +31,10 @@ public class EventMeshAdminException extends 
RuntimeException {
         super(message);
     }
 
-    public EventMeshAdminException(String message, Throwable cause) {
-        super(message, cause);
-    }
-
-    public EventMeshAdminException(Throwable cause) {
-        super(cause);
-    }
-
-    public EventMeshAdminException(String message, Throwable cause, boolean 
enableSuppression, boolean writableStackTrace) {
-        super(message, cause, enableSuppression, writableStackTrace);
+    /**
+     * Customized error reporting using enums and exceptions
+     */
+    public EventMeshAdminException(Errors errors, Throwable cause) {
+        super(errors, cause);
     }
 }
diff --git 
a/eventmesh-admin/src/main/java/org/apache/eventmesh/admin/exception/EventMeshException.java
 
b/eventmesh-admin/src/main/java/org/apache/eventmesh/admin/exception/EventMeshException.java
index 8405fd76c..224d4e939 100644
--- 
a/eventmesh-admin/src/main/java/org/apache/eventmesh/admin/exception/EventMeshException.java
+++ 
b/eventmesh-admin/src/main/java/org/apache/eventmesh/admin/exception/EventMeshException.java
@@ -17,27 +17,15 @@
 
 package org.apache.eventmesh.admin.exception;
 
-public class EventMeshException extends EventMeshAdminException {
+/**
+ * EventMesh Runtime side exception
+ */
+
+public class EventMeshException extends BaseException {
 
     private static final long serialVersionUID = 5648256502005456586L;
 
     public EventMeshException(String message) {
         super(message);
     }
-
-    public EventMeshException(String message, Throwable cause) {
-        super(message, cause);
-    }
-
-    public EventMeshException(Throwable cause) {
-        super(cause);
-    }
-
-    public EventMeshException(String message, Throwable cause, boolean 
enableSuppression, boolean writableStackTrace) {
-        super(message, cause, enableSuppression, writableStackTrace);
-    }
-
-    public EventMeshException(Integer errCode, String errMsg) {
-        super(String.format("errorCode: %s, errorMessage: %s", errCode, 
errMsg));
-    }
 }
diff --git 
a/eventmesh-admin/src/main/java/org/apache/eventmesh/admin/exception/GlobalExceptionHandler.java
 
b/eventmesh-admin/src/main/java/org/apache/eventmesh/admin/exception/GlobalExceptionHandler.java
new file mode 100644
index 000000000..a54e17a58
--- /dev/null
+++ 
b/eventmesh-admin/src/main/java/org/apache/eventmesh/admin/exception/GlobalExceptionHandler.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.eventmesh.admin.exception;
+
+import org.apache.eventmesh.admin.dto.Result;
+import org.apache.eventmesh.admin.dto.Result.Message;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.RestControllerAdvice;
+
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * This class, in conjunction with {@linkplain 
org.apache.eventmesh.admin.enums.Errors Errors} and {@link BaseException},
+ * collectively implements customized error reporting.
+ */
+
+@Slf4j
+@RestControllerAdvice
+public class GlobalExceptionHandler {
+
+    @ExceptionHandler(BaseException.class)
+    public ResponseEntity<Result<Object>> baseHandler(BaseException e, 
HttpServletRequest request) {
+        String uri = request.getRequestURI();
+        log.error("RESTful API {} service error occurred, name: {}, type: {}", 
uri, e.getErrors().name(), e.getErrors().getType().name(), e);
+        return ResponseEntity.status(e.getErrors().getCode()).body(new 
Result<>(new Message(e)));
+    }
+
+    @ExceptionHandler(RuntimeException.class)
+    public ResponseEntity<Result<Object>> runtimeHandler(RuntimeException e, 
HttpServletRequest request) {
+        String uri = request.getRequestURI();
+        log.error("RESTful API {} runtime error occurred.", uri, e);
+        return Result.internalError(e.getMessage());
+    }
+
+    @ExceptionHandler(Exception.class)
+    public ResponseEntity<Result<Object>> exceptionHandler(Exception e, 
HttpServletRequest request) {
+        String uri = request.getRequestURI();
+        log.error("RESTful API {} unknown error occurred.", uri, e);
+        return Result.internalError(e.getMessage());
+    }
+
+}
diff --git 
a/eventmesh-admin/src/main/java/org/apache/eventmesh/admin/exception/MetaException.java
 
b/eventmesh-admin/src/main/java/org/apache/eventmesh/admin/exception/MetaException.java
index 290bf49f3..930210246 100644
--- 
a/eventmesh-admin/src/main/java/org/apache/eventmesh/admin/exception/MetaException.java
+++ 
b/eventmesh-admin/src/main/java/org/apache/eventmesh/admin/exception/MetaException.java
@@ -17,7 +17,13 @@
 
 package org.apache.eventmesh.admin.exception;
 
-public class MetaException extends EventMeshAdminException {
+import org.apache.eventmesh.admin.enums.Errors;
+
+/**
+ * Meta side exception with EventMeshAdmin Application
+ */
+
+public class MetaException extends BaseException {
 
     private static final long serialVersionUID = 6246145526338359773L;
 
@@ -25,7 +31,14 @@ public class MetaException extends EventMeshAdminException {
         super(message);
     }
 
-    public MetaException(String message, Throwable cause) {
-        super(message, cause);
+    /**
+     * Customized error reporting using enums and exceptions
+     */
+    public MetaException(Errors errors, Throwable cause) {
+        super(errors, cause);
+    }
+
+    public MetaException(Errors errors) {
+        super(errors);
     }
 }
diff --git 
a/eventmesh-admin/src/main/java/org/apache/eventmesh/admin/service/SubscriptionService.java
 
b/eventmesh-admin/src/main/java/org/apache/eventmesh/admin/service/SubscriptionService.java
index 9e06648c1..9eae5c827 100644
--- 
a/eventmesh-admin/src/main/java/org/apache/eventmesh/admin/service/SubscriptionService.java
+++ 
b/eventmesh-admin/src/main/java/org/apache/eventmesh/admin/service/SubscriptionService.java
@@ -17,7 +17,10 @@
 
 package org.apache.eventmesh.admin.service;
 
-import org.apache.eventmesh.admin.dto.SubscriptionResponse;
+import org.apache.eventmesh.admin.dto.Result;
+import org.apache.eventmesh.admin.model.SubscriptionInfo;
+
+import java.util.List;
 
 /**
  * "Subscription" refers to the traditional MQ producer-consumer topic 
subscription relationship,
@@ -28,5 +31,5 @@ public interface SubscriptionService {
 
     String retrieveConfig(String dataId, String group);
 
-    SubscriptionResponse retrieveConfigs(Integer page, Integer size, String 
dataId, String group);
+    Result<List<SubscriptionInfo>> retrieveConfigs(Integer page, Integer size, 
String dataId, String group);
 }
diff --git 
a/eventmesh-admin/src/main/java/org/apache/eventmesh/admin/service/impl/EtcdSubscriptionService.java
 
b/eventmesh-admin/src/main/java/org/apache/eventmesh/admin/service/impl/EtcdSubscriptionService.java
index 9ea72ed35..b05026f99 100644
--- 
a/eventmesh-admin/src/main/java/org/apache/eventmesh/admin/service/impl/EtcdSubscriptionService.java
+++ 
b/eventmesh-admin/src/main/java/org/apache/eventmesh/admin/service/impl/EtcdSubscriptionService.java
@@ -17,9 +17,12 @@
 
 package org.apache.eventmesh.admin.service.impl;
 
-import org.apache.eventmesh.admin.dto.SubscriptionResponse;
+import org.apache.eventmesh.admin.dto.Result;
+import org.apache.eventmesh.admin.model.SubscriptionInfo;
 import org.apache.eventmesh.admin.service.SubscriptionService;
 
+import java.util.List;
+
 import org.springframework.stereotype.Service;
 
 import lombok.extern.slf4j.Slf4j;
@@ -34,7 +37,7 @@ public class EtcdSubscriptionService implements 
SubscriptionService {
     }
 
     @Override
-    public SubscriptionResponse retrieveConfigs(Integer page, Integer size, 
String dataId, String group) {
+    public Result<List<SubscriptionInfo>> retrieveConfigs(Integer page, 
Integer size, String dataId, String group) {
         return null;
     }
 }
diff --git 
a/eventmesh-admin/src/main/java/org/apache/eventmesh/admin/service/impl/NacosSubscriptionService.java
 
b/eventmesh-admin/src/main/java/org/apache/eventmesh/admin/service/impl/NacosSubscriptionService.java
index a7fa509ab..29241d31c 100644
--- 
a/eventmesh-admin/src/main/java/org/apache/eventmesh/admin/service/impl/NacosSubscriptionService.java
+++ 
b/eventmesh-admin/src/main/java/org/apache/eventmesh/admin/service/impl/NacosSubscriptionService.java
@@ -17,12 +17,16 @@
 
 package org.apache.eventmesh.admin.service.impl;
 
-import static org.apache.eventmesh.admin.config.Constants.NACOS_CONFIGS_API;
-import static org.apache.eventmesh.admin.config.Constants.NACOS_LOGIN_API;
-
+import static org.apache.eventmesh.admin.enums.Errors.NACOS_EMPTY_RESP_ERR;
+import static org.apache.eventmesh.admin.enums.Errors.NACOS_GET_CONFIGS_ERR;
+import static 
org.apache.eventmesh.admin.enums.Errors.NACOS_LOGIN_EMPTY_RESP_ERR;
+import static org.apache.eventmesh.admin.enums.Errors.NACOS_LOGIN_ERR;
+import static org.apache.eventmesh.admin.enums.Errors.NACOS_SDK_CONFIG_ERR;
+
+import org.apache.eventmesh.admin.common.ConfigConst;
+import org.apache.eventmesh.admin.common.NacosConst;
 import org.apache.eventmesh.admin.config.AdminProperties;
-import org.apache.eventmesh.admin.config.Constants;
-import org.apache.eventmesh.admin.dto.SubscriptionResponse;
+import org.apache.eventmesh.admin.dto.Result;
 import org.apache.eventmesh.admin.exception.EventMeshAdminException;
 import org.apache.eventmesh.admin.exception.MetaException;
 import org.apache.eventmesh.admin.model.SubscriptionInfo;
@@ -62,7 +66,7 @@ public class NacosSubscriptionService implements 
SubscriptionService {
 
     RestTemplate restTemplate = new RestTemplate();
 
-    private static String HTTP_PREFIX = Constants.HTTP_PREFIX;
+    private static String HTTP_PREFIX = ConfigConst.HTTP_PREFIX;
 
     public NacosSubscriptionService(AdminProperties adminProperties) {
         this.adminProperties = adminProperties;
@@ -84,7 +88,7 @@ public class NacosSubscriptionService implements 
SubscriptionService {
             }
         }
         if 
(adminProperties.getMeta().getNacos().getProtocol().equalsIgnoreCase("https")) {
-            HTTP_PREFIX = Constants.HTTPS_PREFIX;
+            HTTP_PREFIX = ConfigConst.HTTPS_PREFIX;
         }
     }
 
@@ -97,14 +101,14 @@ public class NacosSubscriptionService implements 
SubscriptionService {
         try {
             configService = NacosFactory.createConfigService(nacosProps);
         } catch (Exception e) {
-            log.error("Failed to create Nacos ConfigService", e);
-            throw new EventMeshAdminException("Failed to create Nacos 
ConfigService: " + e.getMessage());
+            log.error(NACOS_SDK_CONFIG_ERR.getDesc(), e);
+            throw new EventMeshAdminException(NACOS_SDK_CONFIG_ERR, e);
         }
         try {
             return configService.getConfig(dataId, group, 
adminProperties.getConfig().getTimeoutMs());
         } catch (Exception e) {
-            log.error("Failed to retrieve Nacos config", e);
-            throw new MetaException("Failed to retrieve Nacos config: " + 
e.getMessage());
+            log.error(NACOS_GET_CONFIGS_ERR.getDesc(), e);
+            throw new MetaException(NACOS_GET_CONFIGS_ERR, e);
         }
     }
 
@@ -112,45 +116,38 @@ public class NacosSubscriptionService implements 
SubscriptionService {
      * Retrieve a list of configs with Nacos OpenAPI, because Nacos SDK 
doesn't support listing and fuzzy matching.
      */
     @Override
-    public SubscriptionResponse retrieveConfigs(Integer page, Integer size, 
String dataId, String group) {
+    public Result<List<SubscriptionInfo>> retrieveConfigs(Integer page, 
Integer size, String dataId, String group) {
         UriComponentsBuilder urlBuilder = UriComponentsBuilder
-            .fromHttpUrl(HTTP_PREFIX + 
nacosProps.getProperty(PropertyKeyConst.SERVER_ADDR) + NACOS_CONFIGS_API)
-            .queryParam("pageNo", page)
-            .queryParam("pageSize", size)
-            .queryParam("dataId", dataId)
-            .queryParam("group", group)
-            .queryParam("search", "blur");
+            .fromHttpUrl(HTTP_PREFIX + 
nacosProps.getProperty(PropertyKeyConst.SERVER_ADDR) + NacosConst.CONFIGS_API)
+            .queryParam(NacosConst.CONFIGS_REQ_PAGE, page)
+            .queryParam(NacosConst.CONFIGS_REQ_PAGE_SIZE, size)
+            .queryParam(NacosConst.CONFIGS_REQ_DATAID, dataId)
+            .queryParam(NacosConst.CONFIGS_REQ_GROUP, group)
+            .queryParam(NacosConst.CONFIGS_REQ_SEARCH, "blur");
 
         if (adminProperties.getMeta().getNacos().isAuthEnabled()) {
-            urlBuilder.queryParam("accessToken", loginGetAccessToken());
+            urlBuilder.queryParam(NacosConst.CONFIGS_REQ_TOKEN, 
loginGetAccessToken());
         }
 
         ResponseEntity<String> response;
         try {
             response = restTemplate.getForEntity(urlBuilder.toUriString(), 
String.class);
         } catch (Exception e) {
-            log.error("Failed to retrieve Nacos config list.", e);
-            throw new MetaException("Failed to retrieve Nacos config list: " + 
e.getMessage());
+            log.error(NACOS_GET_CONFIGS_ERR.getDesc(), e);
+            throw new MetaException(NACOS_GET_CONFIGS_ERR, e);
         }
         if (response.getBody() == null || response.getBody().isEmpty()) {
-            log.error("No result returned by Nacos. Please check Nacos.");
-            throw new MetaException("No result returned by Nacos. Please check 
Nacos.");
+            log.error(NACOS_EMPTY_RESP_ERR.getDesc());
+            throw new MetaException(NACOS_EMPTY_RESP_ERR);
         }
 
-        return toSubscriptionResponse(JSON.parseObject(response.getBody()));
-    }
-
-    private SubscriptionResponse toSubscriptionResponse(JSONObject obj) {
-        return SubscriptionResponse.builder()
-            .subscriptionInfos(toSubscriptionInfos(obj))
-            .pages(obj.getInteger("pagesAvailable"))
-            .message("success")
-            .build();
+        JSONObject obj = JSON.parseObject(response.getBody());
+        return new Result<>(toSubscriptionInfos(obj), 
obj.getInteger(NacosConst.CONFIGS_RESP_PAGES));
     }
 
     private List<SubscriptionInfo> toSubscriptionInfos(JSONObject obj) {
         List<SubscriptionInfo> subscriptionInfos = new ArrayList<>();
-        for (Object pageItem : obj.getJSONArray("pageItems")) {
+        for (Object pageItem : 
obj.getJSONArray(NacosConst.CONFIGS_RESP_CONTENT_LIST)) {
             JSONObject pageItemObj = (JSONObject) pageItem;
             subscriptionInfos.add(toSubscriptionInfo(pageItemObj));
         }
@@ -158,10 +155,10 @@ public class NacosSubscriptionService implements 
SubscriptionService {
     }
 
     private SubscriptionInfo toSubscriptionInfo(JSONObject obj) {
-        String content = obj.getString("content");
+        String content = obj.getString(NacosConst.CONFIGS_RESP_CONTENT);
         return SubscriptionInfo.builder()
-            .clientName(obj.getString("dataId"))
-            .group(obj.getString("group"))
+            .clientName(obj.getString(NacosConst.CONFIGS_RESP_DATAID))
+            .group(obj.getString(NacosConst.CONFIGS_RESP_GROUP))
             // The subscription content of Nacos config should be base64 
encoded to protect special characters.
             
.subscription(Base64.getEncoder().encodeToString(content.getBytes()))
             .build();
@@ -175,22 +172,22 @@ public class NacosSubscriptionService implements 
SubscriptionService {
         headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
 
         MultiValueMap<String, String> bodyParams = new LinkedMultiValueMap<>();
-        bodyParams.put("username", 
Collections.singletonList(nacosProps.getProperty(PropertyKeyConst.USERNAME)));
-        bodyParams.put("password", 
Collections.singletonList(nacosProps.getProperty(PropertyKeyConst.PASSWORD)));
+        bodyParams.put(NacosConst.LOGIN_REQ_USERNAME, 
Collections.singletonList(nacosProps.getProperty(PropertyKeyConst.USERNAME)));
+        bodyParams.put(NacosConst.LOGIN_REQ_PASSWORD, 
Collections.singletonList(nacosProps.getProperty(PropertyKeyConst.PASSWORD)));
 
-        String loginUrl = HTTP_PREFIX + 
nacosProps.getProperty(PropertyKeyConst.SERVER_ADDR) + NACOS_LOGIN_API;
+        String loginUrl = HTTP_PREFIX + 
nacosProps.getProperty(PropertyKeyConst.SERVER_ADDR) + NacosConst.LOGIN_API;
         HttpEntity<MultiValueMap<String, String>> loginRequest = new 
HttpEntity<>(bodyParams, headers);
         ResponseEntity<String> loginResponse;
         try {
             loginResponse = restTemplate.postForEntity(loginUrl, loginRequest, 
String.class);
         } catch (Exception e) {
-            log.error("Nacos login failed.", e);
-            throw new MetaException("Nacos login failed: " + e.getMessage());
+            log.error(NACOS_LOGIN_ERR.getDesc(), e);
+            throw new MetaException(NACOS_LOGIN_ERR, e);
         }
         if (loginResponse.getBody() == null || 
loginResponse.getBody().isEmpty()) {
-            log.error("Nacos didn't return accessToken. Please check Nacos 
status. Status code: {}", loginResponse.getStatusCode());
-            throw new MetaException("Nacos didn't return accessToken. Please 
check Nacos status. Status code: " + loginResponse.getStatusCode());
+            log.error(NACOS_LOGIN_EMPTY_RESP_ERR + " Status code: {}", 
loginResponse.getStatusCode());
+            throw new MetaException(NACOS_LOGIN_EMPTY_RESP_ERR + " Status 
code: " + loginResponse.getStatusCode());
         }
-        return 
JSON.parseObject(loginResponse.getBody()).getString("accessToken");
+        return 
JSON.parseObject(loginResponse.getBody()).getString(NacosConst.LOGIN_RESP_TOKEN);
     }
 }
diff --git 
a/eventmesh-admin/src/main/java/org/apache/eventmesh/admin/dto/SubscriptionResponse.java
 
b/eventmesh-admin/src/main/java/org/apache/eventmesh/admin/utils/ExceptionUtils.java
similarity index 61%
rename from 
eventmesh-admin/src/main/java/org/apache/eventmesh/admin/dto/SubscriptionResponse.java
rename to 
eventmesh-admin/src/main/java/org/apache/eventmesh/admin/utils/ExceptionUtils.java
index 965e71d82..1069e082f 100644
--- 
a/eventmesh-admin/src/main/java/org/apache/eventmesh/admin/dto/SubscriptionResponse.java
+++ 
b/eventmesh-admin/src/main/java/org/apache/eventmesh/admin/utils/ExceptionUtils.java
@@ -15,30 +15,21 @@
  * limitations under the License.
  */
 
-package org.apache.eventmesh.admin.dto;
-
-import org.apache.eventmesh.admin.model.SubscriptionInfo;
-
-import java.util.List;
-
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-@Data
-@Builder
-@NoArgsConstructor
-@AllArgsConstructor
-public class SubscriptionResponse {
-
-    private List<SubscriptionInfo> subscriptionInfos;
-
-    private Integer pages;
-
-    private String message;
-
-    public SubscriptionResponse(String message) {
-        this.message = message;
+package org.apache.eventmesh.admin.utils;
+
+public class ExceptionUtils {
+
+    /**
+     * Remove the last period of exception description.
+     */
+    public static String trimDesc(String desc) {
+        if (desc == null) {
+            return "";
+        }
+        if (desc.charAt(desc.length() - 1) == '.') {
+            return desc.substring(0, desc.length() - 1);
+        }
+        return desc;
     }
+
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]


Reply via email to