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

mxsm 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 b6f9ca581 [ISSUE #4275] Support subscription info management with 
eventmesh-admin module (#4468)
b6f9ca581 is described below

commit b6f9ca5816945ae7cd53cd9f60adc28b201bcf9e
Author: Pil0tXia <[email protected]>
AuthorDate: Fri Oct 6 09:44:38 2023 +0800

    [ISSUE #4275] Support subscription info management with eventmesh-admin 
module (#4468)
    
    * init: Spring Initializr
    
    * init: add basic configurations and dependencies
    
    * init: merge Gradle Groovy DSL to Kotlin DSL
    
    * fix: resolve springdoc compatibility and select kotlin as DSL
    
    * config: use nacos, REVERT BEFORE MERGE
    
    * dep: nacos-client dependency and test endpoint
    
    * config: use rocketmq connector, REVERT BEFORE MERGE
    
    * dep: fix springdoc version
    
    * config: connector namesrv, REVERT BEFORE MERGE
    
    * feat: Realize multi-implements based on config
    
    * feat: get one nacos config by dataId
    
    * feat: get nacos config list with OpenAPI
    
    * chore: fix checkstyle
    
    * feat: config content base64 encode
    
    * feat: use json to output Session toString
    
    * optimize: endpoint support returning error message
    
    * optimize: return an object instead of JSON string
    
    * Revert config changes
    
    * Use Gradle Groovy DSL instead of Kotlin DSL
    
    * feat: support for building and running with docker
---
 .../common/exception/EventMeshException.java       |   2 +-
 .../src/main/resources/source-config.yml           |   2 +-
 eventmesh-console/.gitignore                       |  36 +++
 eventmesh-console/README.md                        |  24 ++
 eventmesh-console/build.gradle                     |  80 +++++++
 .../docker/Dockerfile                              |  28 +--
 eventmesh-console/docs/UserGuide_CN.md             |   1 +
 eventmesh-console/docs/UserGuide_EN.md             |   1 +
 .../gradle/wrapper/gradle-wrapper.jar              | Bin 0 -> 63375 bytes
 .../gradle/wrapper/gradle-wrapper.properties       |  30 +--
 eventmesh-console/gradlew                          | 248 +++++++++++++++++++++
 eventmesh-console/gradlew.bat                      |  92 ++++++++
 .../settings.gradle                                |  27 +--
 .../console/EventMeshAdminApplication.java         |  27 +--
 .../eventmesh/console/config/AdminProperties.java  |  78 +++++++
 .../apache/eventmesh/console/config/Constants.java |  33 +--
 .../eventmesh/console/config/MetaTypeConfig.java   |  68 ++++++
 .../console/controller/ConnectionController.java   |  51 +++++
 .../console/controller/SubscriptionController.java |  83 +++++++
 .../console/dto/SubscriptionResponse.java          |  35 +--
 .../console/exception/EventMeshAdminException.java |  18 +-
 .../console}/exception/EventMeshException.java     |   6 +-
 .../eventmesh/console/exception/MetaException.java |  22 +-
 .../eventmesh/console/model/ConnectionInfo.java    |  25 +--
 .../eventmesh/console/model/SubscriptionInfo.java  |  32 +--
 .../console/service/ConnectionService.java         |  30 +--
 .../console/service/SubscriptionService.java       |  31 +--
 .../service/impl/EtcdConnectionService.java        |  27 +--
 .../service/impl/EtcdSubscriptionService.java      |  31 ++-
 .../service/impl/NacosConnectionService.java       |  43 ++++
 .../service/impl/NacosSubscriptionService.java     | 196 ++++++++++++++++
 .../src/main/resources/application.yml             |  57 +++--
 eventmesh-console/src/main/resources/logback.xml   |  50 +++++
 .../console/EventMeshAdminApplicationTests.java    |  27 +--
 .../core/protocol/tcp/client/session/Session.java  |  33 ++-
 35 files changed, 1225 insertions(+), 349 deletions(-)

diff --git 
a/eventmesh-common/src/main/java/org/apache/eventmesh/common/exception/EventMeshException.java
 
b/eventmesh-common/src/main/java/org/apache/eventmesh/common/exception/EventMeshException.java
index 4adafcb4a..39728b3f9 100644
--- 
a/eventmesh-common/src/main/java/org/apache/eventmesh/common/exception/EventMeshException.java
+++ 
b/eventmesh-common/src/main/java/org/apache/eventmesh/common/exception/EventMeshException.java
@@ -19,7 +19,7 @@ package org.apache.eventmesh.common.exception;
 
 public class EventMeshException extends RuntimeException {
 
-    public static final long serialVersionUID = 5648256502005456586L;
+    private static final long serialVersionUID = 5648256502005456586L;
 
     public EventMeshException(String message) {
         super(message);
diff --git 
a/eventmesh-connectors/eventmesh-connector-rocketmq/src/main/resources/source-config.yml
 
b/eventmesh-connectors/eventmesh-connector-rocketmq/src/main/resources/source-config.yml
index 09c87272a..7a7880b87 100644
--- 
a/eventmesh-connectors/eventmesh-connector-rocketmq/src/main/resources/source-config.yml
+++ 
b/eventmesh-connectors/eventmesh-connector-rocketmq/src/main/resources/source-config.yml
@@ -26,7 +26,7 @@ pubSubConfig:
     passWord: rocketmqPassWord
 connectorConfig:
     connectorName: rocketmqSource
-    nameserver: 127.0.0.1:9877
+    nameserver: 127.0.0.1:9876
     topic: TopicTest
     commitOffsetIntervalMs: 5000
 offsetStorageConfig:
diff --git a/eventmesh-console/.gitignore b/eventmesh-console/.gitignore
new file mode 100644
index 000000000..63d2f1a0c
--- /dev/null
+++ b/eventmesh-console/.gitignore
@@ -0,0 +1,36 @@
+.gradle
+build/
+!gradle/wrapper/gradle-wrapper.jar
+!**/src/main/**/build/
+!**/src/test/**/build/
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+bin/
+!**/src/main/**/bin/
+!**/src/test/**/bin/
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+out/
+!**/src/main/**/out/
+!**/src/test/**/out/
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+
+### VS Code ###
+.vscode/
diff --git a/eventmesh-console/README.md b/eventmesh-console/README.md
new file mode 100644
index 000000000..aadf9b82e
--- /dev/null
+++ b/eventmesh-console/README.md
@@ -0,0 +1,24 @@
+# Getting Started
+
+## Build on source code
+
+```
+cd eventmesh-console
+./gradlew clean bootJar
+```
+
+```
+java -jar build/libs/eventmesh-console-0.0.1-SNAPSHOT.jar
+```
+
+## Build and Run with Docker
+
+```
+cd eventmesh-console
+./gradlew clean bootJar
+docker build -t yourname/eventmesh-console -f docker/Dockerfile .
+```
+
+```
+docker run -d --name eventmesh-console -p 8080:8080 yourname/eventmesh-console
+```
\ No newline at end of file
diff --git a/eventmesh-console/build.gradle b/eventmesh-console/build.gradle
new file mode 100644
index 000000000..42a6fcccb
--- /dev/null
+++ b/eventmesh-console/build.gradle
@@ -0,0 +1,80 @@
+/*
+ * 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.
+ */
+
+plugins {
+    id 'java'
+    id 'idea'
+    id 'org.springframework.boot' version '2.7.15'
+    id 'io.spring.dependency-management' version '1.0.15.RELEASE'
+}
+
+group = 'org.apache.eventmesh'
+version = '0.0.1-SNAPSHOT'
+
+java {
+    sourceCompatibility = '1.8'
+}
+
+configurations {
+    compileOnly {
+        extendsFrom annotationProcessor
+    }
+}
+
+repositories {
+    mavenCentral()
+    maven { url 'https://maven.aliyun.com/repository/public/' }
+}
+
+ext {
+    // utility
+    commonsLang3Version = '3.13.0'
+    guavaVersion = '32.1.2-jre' // not used for now
+    fastjsonVersion = '2.0.40'
+    // swagger
+    springdocVersion = '1.7.0'
+    // unit test
+    mockitoVersion = '5.5.0'
+    // meta
+    nacosVersion = '2.2.4'
+}
+
+dependencies {
+    // versions managed by spring.dependency-management
+    implementation 'org.springframework.boot:spring-boot-starter-web'
+    compileOnly 'org.projectlombok:lombok'
+    developmentOnly 'org.springframework.boot:spring-boot-devtools'
+    annotationProcessor 
'org.springframework.boot:spring-boot-configuration-processor'
+    annotationProcessor 'org.projectlombok:lombok'
+    testImplementation 'org.springframework.boot:spring-boot-starter-test'
+
+    // utility
+    implementation "org.apache.commons:commons-lang3:${commonsLang3Version}"
+    implementation("com.alibaba.fastjson2:fastjson2:${fastjsonVersion}")
+    // swagger
+    implementation "org.springdoc:springdoc-openapi-ui:${springdocVersion}"
+    implementation 
"org.springdoc:springdoc-openapi-javadoc:${springdocVersion}"
+    annotationProcessor 
'com.github.therapi:therapi-runtime-javadoc-scribe:0.15.0'
+    // unit test
+    testImplementation("org.mockito:mockito-core:${mockitoVersion}")
+    // meta
+    implementation("com.alibaba.nacos:nacos-client:${nacosVersion}")
+}
+
+tasks.named('test') {
+    useJUnitPlatform()
+}
diff --git 
a/eventmesh-connectors/eventmesh-connector-rocketmq/src/main/resources/source-config.yml
 b/eventmesh-console/docker/Dockerfile
similarity index 56%
copy from 
eventmesh-connectors/eventmesh-connector-rocketmq/src/main/resources/source-config.yml
copy to eventmesh-console/docker/Dockerfile
index 09c87272a..efa0ccf5c 100644
--- 
a/eventmesh-connectors/eventmesh-connector-rocketmq/src/main/resources/source-config.yml
+++ b/eventmesh-console/docker/Dockerfile
@@ -15,26 +15,8 @@
 # limitations under the License.
 #
 
-pubSubConfig:
-    meshAddress: 127.0.0.1:10000
-    subject: TopicTest
-    idc: FT
-    env: PRD
-    group: rocketmqSource
-    appId: 5032
-    userName: rocketmqSourceUser
-    passWord: rocketmqPassWord
-connectorConfig:
-    connectorName: rocketmqSource
-    nameserver: 127.0.0.1:9877
-    topic: TopicTest
-    commitOffsetIntervalMs: 5000
-offsetStorageConfig:
-    offsetStorageType: nacos
-    offsetStorageAddr: 127.0.0.1:8848
-    extensions: {
-                    #same with topic
-                    dataId: TopicTest,
-                    #same with group
-                    group: rocketmqSource
-    }
+FROM openjdk:8-jre-alpine
+VOLUME /tmp
+COPY build/libs/eventmesh-console-*.jar eventmesh-console.jar
+ENV JAVA_OPTS=""
+ENTRYPOINT ["sh", "-c", "java $JAVA_OPTS -jar /eventmesh-console.jar"]
diff --git a/eventmesh-console/docs/UserGuide_CN.md 
b/eventmesh-console/docs/UserGuide_CN.md
new file mode 100644
index 000000000..0ffdd02fc
--- /dev/null
+++ b/eventmesh-console/docs/UserGuide_CN.md
@@ -0,0 +1 @@
+// TODO
\ No newline at end of file
diff --git a/eventmesh-console/docs/UserGuide_EN.md 
b/eventmesh-console/docs/UserGuide_EN.md
new file mode 100644
index 000000000..0ffdd02fc
--- /dev/null
+++ b/eventmesh-console/docs/UserGuide_EN.md
@@ -0,0 +1 @@
+// TODO
\ No newline at end of file
diff --git a/eventmesh-console/gradle/wrapper/gradle-wrapper.jar 
b/eventmesh-console/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 000000000..033e24c4c
Binary files /dev/null and 
b/eventmesh-console/gradle/wrapper/gradle-wrapper.jar differ
diff --git 
a/eventmesh-connectors/eventmesh-connector-rocketmq/src/main/resources/source-config.yml
 b/eventmesh-console/gradle/wrapper/gradle-wrapper.properties
similarity index 56%
copy from 
eventmesh-connectors/eventmesh-connector-rocketmq/src/main/resources/source-config.yml
copy to eventmesh-console/gradle/wrapper/gradle-wrapper.properties
index 09c87272a..2b303b2bb 100644
--- 
a/eventmesh-connectors/eventmesh-connector-rocketmq/src/main/resources/source-config.yml
+++ b/eventmesh-console/gradle/wrapper/gradle-wrapper.properties
@@ -15,26 +15,10 @@
 # limitations under the License.
 #
 
-pubSubConfig:
-    meshAddress: 127.0.0.1:10000
-    subject: TopicTest
-    idc: FT
-    env: PRD
-    group: rocketmqSource
-    appId: 5032
-    userName: rocketmqSourceUser
-    passWord: rocketmqPassWord
-connectorConfig:
-    connectorName: rocketmqSource
-    nameserver: 127.0.0.1:9877
-    topic: TopicTest
-    commitOffsetIntervalMs: 5000
-offsetStorageConfig:
-    offsetStorageType: nacos
-    offsetStorageAddr: 127.0.0.1:8848
-    extensions: {
-                    #same with topic
-                    dataId: TopicTest,
-                    #same with group
-                    group: rocketmqSource
-    }
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.2.1-bin.zip
+networkTimeout=10000
+validateDistributionUrl=true
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
diff --git a/eventmesh-console/gradlew b/eventmesh-console/gradlew
new file mode 100644
index 000000000..fcb6fca14
--- /dev/null
+++ b/eventmesh-console/gradlew
@@ -0,0 +1,248 @@
+#!/bin/sh
+
+#
+# Copyright © 2015-2021 the original authors.
+#
+# Licensed 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
+#
+#      https://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.
+#
+
+##############################################################################
+#
+#   Gradle start up script for POSIX generated by Gradle.
+#
+#   Important for running:
+#
+#   (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
+#       noncompliant, but you have some other compliant shell such as ksh or
+#       bash, then to run this script, type that shell name before the whole
+#       command line, like:
+#
+#           ksh Gradle
+#
+#       Busybox and similar reduced shells will NOT work, because this script
+#       requires all of these POSIX shell features:
+#         * functions;
+#         * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
+#           «${var#prefix}», «${var%suffix}», and «$( cmd )»;
+#         * compound commands having a testable exit status, especially «case»;
+#         * various built-in commands including «command», «set», and «ulimit».
+#
+#   Important for patching:
+#
+#   (2) This script targets any POSIX shell, so it avoids extensions provided
+#       by Bash, Ksh, etc; in particular arrays are avoided.
+#
+#       The "traditional" practice of packing multiple parameters into a
+#       space-separated string is a well documented source of bugs and security
+#       problems, so this is (mostly) avoided, by progressively accumulating
+#       options in "$@", and eventually passing that to Java.
+#
+#       Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
+#       and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
+#       see the in-line comments for details.
+#
+#       There are tweaks for specific operating systems such as AIX, CygWin,
+#       Darwin, MinGW, and NonStop.
+#
+#   (3) This script is generated from the Groovy template
+#       
https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
+#       within the Gradle project.
+#
+#       You can find Gradle at https://github.com/gradle/gradle/.
+#
+##############################################################################
+
+# Attempt to set APP_HOME
+
+# Resolve links: $0 may be a link
+app_path=$0
+
+# Need this for daisy-chained symlinks.
+while
+    APP_HOME=${app_path%"${app_path##*/}"}  # leaves a trailing /; empty if no 
leading path
+    [ -h "$app_path" ]
+do
+    ls=$( ls -ld "$app_path" )
+    link=${ls#*' -> '}
+    case $link in             #(
+      /*)   app_path=$link ;; #(
+      *)    app_path=$APP_HOME$link ;;
+    esac
+done
+
+# This is normally unused
+# shellcheck disable=SC2034
+APP_BASE_NAME=${0##*/}
+APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD=maximum
+
+warn () {
+    echo "$*"
+} >&2
+
+die () {
+    echo
+    echo "$*"
+    echo
+    exit 1
+} >&2
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "$( uname )" in                #(
+  CYGWIN* )         cygwin=true  ;; #(
+  Darwin* )         darwin=true  ;; #(
+  MSYS* | MINGW* )  msys=true    ;; #(
+  NONSTOP* )        nonstop=true ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+        # IBM's JDK on AIX uses strange locations for the executables
+        JAVACMD=$JAVA_HOME/jre/sh/java
+    else
+        JAVACMD=$JAVA_HOME/bin/java
+    fi
+    if [ ! -x "$JAVACMD" ] ; then
+        die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+    fi
+else
+    JAVACMD=java
+    if ! command -v java >/dev/null 2>&1
+    then
+        die "ERROR: JAVA_HOME is not set and no 'java' command could be found 
in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+    fi
+fi
+
+# Increase the maximum file descriptors if we can.
+if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
+    case $MAX_FD in #(
+      max*)
+        # In POSIX sh, ulimit -H is undefined. That's why the result is 
checked to see if it worked.
+        # shellcheck disable=SC3045
+        MAX_FD=$( ulimit -H -n ) ||
+            warn "Could not query maximum file descriptor limit"
+    esac
+    case $MAX_FD in  #(
+      '' | soft) :;; #(
+      *)
+        # In POSIX sh, ulimit -n is undefined. That's why the result is 
checked to see if it worked.
+        # shellcheck disable=SC3045
+        ulimit -n "$MAX_FD" ||
+            warn "Could not set maximum file descriptor limit to $MAX_FD"
+    esac
+fi
+
+# Collect all arguments for the java command, stacking in reverse order:
+#   * args from the command line
+#   * the main class name
+#   * -classpath
+#   * -D...appname settings
+#   * --module-path (only if needed)
+#   * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
+
+# For Cygwin or MSYS, switch paths to Windows format before running java
+if "$cygwin" || "$msys" ; then
+    APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
+    CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
+
+    JAVACMD=$( cygpath --unix "$JAVACMD" )
+
+    # Now convert the arguments - kludge to limit ourselves to /bin/sh
+    for arg do
+        if
+            case $arg in                                #(
+              -*)   false ;;                            # don't mess with 
options #(
+              /?*)  t=${arg#/} t=/${t%%/*}              # looks like a POSIX 
filepath
+                    [ -e "$t" ] ;;                      #(
+              *)    false ;;
+            esac
+        then
+            arg=$( cygpath --path --ignore --mixed "$arg" )
+        fi
+        # Roll the args list around exactly as many times as the number of
+        # args, so each arg winds up back in the position where it started, but
+        # possibly modified.
+        #
+        # NB: a `for` loop captures its iteration list before it begins, so
+        # changing the positional parameters here affects neither the number of
+        # iterations, nor the values presented in `arg`.
+        shift                   # remove old arg
+        set -- "$@" "$arg"      # push replacement arg
+    done
+fi
+
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to 
pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+
+# Collect all arguments for the java command;
+#   * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
+#     shell script including quotes and variable substitutions, so put them in
+#     double quotes to make sure that they get re-expanded; and
+#   * put everything else in single quotes, so that it's not re-expanded.
+
+set -- \
+        "-Dorg.gradle.appname=$APP_BASE_NAME" \
+        -classpath "$CLASSPATH" \
+        org.gradle.wrapper.GradleWrapperMain \
+        "$@"
+
+# Stop when "xargs" is not available.
+if ! command -v xargs >/dev/null 2>&1
+then
+    die "xargs is not available"
+fi
+
+# Use "xargs" to parse quoted args.
+#
+# With -n1 it outputs one arg per line, with the quotes and backslashes 
removed.
+#
+# In Bash we could simply go:
+#
+#   readarray ARGS < <( xargs -n1 <<<"$var" ) &&
+#   set -- "${ARGS[@]}" "$@"
+#
+# but POSIX shell has neither arrays nor command substitution, so instead we
+# post-process each arg (as a line of input to sed) to backslash-escape any
+# character that might be a shell metacharacter, then use eval to reverse
+# that process (while maintaining the separation between arguments), and wrap
+# the whole thing up as a single "set" statement.
+#
+# This will of course break if any of these variables contains a newline or
+# an unmatched quote.
+#
+
+eval "set -- $(
+        printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
+        xargs -n1 |
+        sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
+        tr '\n' ' '
+    )" '"$@"'
+
+exec "$JAVACMD" "$@"
diff --git a/eventmesh-console/gradlew.bat b/eventmesh-console/gradlew.bat
new file mode 100644
index 000000000..93e3f59f1
--- /dev/null
+++ b/eventmesh-console/gradlew.bat
@@ -0,0 +1,92 @@
+@rem
+@rem Copyright 2015 the original author or authors.
+@rem
+@rem Licensed under the Apache License, Version 2.0 (the "License");
+@rem you may not use this file except in compliance with the License.
+@rem You may obtain a copy of the License at
+@rem
+@rem      https://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing, software
+@rem distributed under the License is distributed on an "AS IS" BASIS,
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem See the License for the specific language governing permissions and
+@rem limitations under the License.
+@rem
+
+@if "%DEBUG%"=="" @echo off
+@rem ##########################################################################
+@rem
+@rem  Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%"=="" set DIRNAME=.
+@rem This is normally unused
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Resolve any "." and ".." in APP_HOME to make it shorter.
+for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS 
to pass JVM options to this script.
+set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if %ERRORLEVEL% equ 0 goto execute
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your 
PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto execute
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% 
"-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" 
org.gradle.wrapper.GradleWrapperMain %*
+
+:end
+@rem End local scope for the variables with windows NT shell
+if %ERRORLEVEL% equ 0 goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code 
instead of
+rem the _cmd.exe /c_ return code!
+set EXIT_CODE=%ERRORLEVEL%
+if %EXIT_CODE% equ 0 set EXIT_CODE=1
+if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
+exit /b %EXIT_CODE%
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git 
a/eventmesh-common/src/main/java/org/apache/eventmesh/common/exception/EventMeshException.java
 b/eventmesh-console/settings.gradle
similarity index 50%
copy from 
eventmesh-common/src/main/java/org/apache/eventmesh/common/exception/EventMeshException.java
copy to eventmesh-console/settings.gradle
index 4adafcb4a..b2966edef 100644
--- 
a/eventmesh-common/src/main/java/org/apache/eventmesh/common/exception/EventMeshException.java
+++ b/eventmesh-console/settings.gradle
@@ -15,29 +15,4 @@
  * limitations under the License.
  */
 
-package org.apache.eventmesh.common.exception;
-
-public class EventMeshException extends RuntimeException {
-
-    public 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));
-    }
-}
+rootProject.name = 'eventmesh-console'
diff --git 
a/eventmesh-common/src/main/java/org/apache/eventmesh/common/exception/EventMeshException.java
 
b/eventmesh-console/src/main/java/org/apache/eventmesh/console/EventMeshAdminApplication.java
similarity index 51%
copy from 
eventmesh-common/src/main/java/org/apache/eventmesh/common/exception/EventMeshException.java
copy to 
eventmesh-console/src/main/java/org/apache/eventmesh/console/EventMeshAdminApplication.java
index 4adafcb4a..2486e783b 100644
--- 
a/eventmesh-common/src/main/java/org/apache/eventmesh/common/exception/EventMeshException.java
+++ 
b/eventmesh-console/src/main/java/org/apache/eventmesh/console/EventMeshAdminApplication.java
@@ -15,29 +15,16 @@
  * limitations under the License.
  */
 
-package org.apache.eventmesh.common.exception;
+package org.apache.eventmesh.console;
 
-public class EventMeshException extends RuntimeException {
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
 
-    public static final long serialVersionUID = 5648256502005456586L;
+@SpringBootApplication
+public class EventMeshAdminApplication {
 
-    public EventMeshException(String message) {
-        super(message);
+    public static void main(String[] args) {
+        SpringApplication.run(EventMeshAdminApplication.class, args);
     }
 
-    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-console/src/main/java/org/apache/eventmesh/console/config/AdminProperties.java
 
b/eventmesh-console/src/main/java/org/apache/eventmesh/console/config/AdminProperties.java
new file mode 100644
index 000000000..9140ae3b1
--- /dev/null
+++ 
b/eventmesh-console/src/main/java/org/apache/eventmesh/console/config/AdminProperties.java
@@ -0,0 +1,78 @@
+/*
+ * 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.console.config;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+import lombok.Data;
+
+@Data
+@Component
+@ConfigurationProperties(prefix = Constants.ADMIN_PROPS_PREFIX)
+public class AdminProperties {
+
+    private MetaProperties meta = new MetaProperties();
+
+    private ConfigProperties config = new ConfigProperties();
+
+    @Data
+    public static class MetaProperties {
+
+        private String type = Constants.META_TYPE_NACOS;
+
+        private NacosProperties nacos = new NacosProperties();
+
+        private EtcdProperties etcd = new EtcdProperties();
+
+        @Data
+        public static class NacosProperties {
+
+            private String addr = "127.0.0.1:8848";
+
+            private String namespace = "";
+
+            private boolean authEnabled = false;
+
+            private String protocol = "http";
+
+            private String username;
+
+            private String password;
+
+            private String accessKey;
+
+            private String secretKey;
+
+        }
+
+        @Data
+        public static class EtcdProperties {
+
+            private String addr;
+
+        }
+    }
+
+    @Data
+    public static class ConfigProperties {
+
+        private int timeoutMs = 5000;
+
+    }
+}
\ No newline at end of file
diff --git 
a/eventmesh-common/src/main/java/org/apache/eventmesh/common/exception/EventMeshException.java
 
b/eventmesh-console/src/main/java/org/apache/eventmesh/console/config/Constants.java
similarity index 50%
copy from 
eventmesh-common/src/main/java/org/apache/eventmesh/common/exception/EventMeshException.java
copy to 
eventmesh-console/src/main/java/org/apache/eventmesh/console/config/Constants.java
index 4adafcb4a..6a9fc86cb 100644
--- 
a/eventmesh-common/src/main/java/org/apache/eventmesh/common/exception/EventMeshException.java
+++ 
b/eventmesh-console/src/main/java/org/apache/eventmesh/console/config/Constants.java
@@ -15,29 +15,20 @@
  * limitations under the License.
  */
 
-package org.apache.eventmesh.common.exception;
+package org.apache.eventmesh.console.config;
 
-public class EventMeshException extends RuntimeException {
+public class Constants {
 
-    public static final long serialVersionUID = 5648256502005456586L;
+    // 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";
 
-    public EventMeshException(String message) {
-        super(message);
-    }
+    // Open-API
+    public static final String HTTP_PREFIX = "http://";;
+    public static final String HTTPS_PREFIX = "https://";;
 
-    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));
-    }
+    // Nacos
+    public static final String NACOS_LOGIN_API = "/nacos/v1/auth/login";
+    public static final String NACOS_CONFIGS_API = "/nacos/v1/cs/configs";
 }
diff --git 
a/eventmesh-console/src/main/java/org/apache/eventmesh/console/config/MetaTypeConfig.java
 
b/eventmesh-console/src/main/java/org/apache/eventmesh/console/config/MetaTypeConfig.java
new file mode 100644
index 000000000..6ec51d0b9
--- /dev/null
+++ 
b/eventmesh-console/src/main/java/org/apache/eventmesh/console/config/MetaTypeConfig.java
@@ -0,0 +1,68 @@
+/*
+ * 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.console.config;
+
+import static org.apache.eventmesh.console.config.Constants.META_TYPE_ETCD;
+import static org.apache.eventmesh.console.config.Constants.META_TYPE_NACOS;
+
+import org.apache.eventmesh.console.service.ConnectionService;
+import org.apache.eventmesh.console.service.SubscriptionService;
+import org.apache.eventmesh.console.service.impl.EtcdConnectionService;
+import org.apache.eventmesh.console.service.impl.EtcdSubscriptionService;
+import org.apache.eventmesh.console.service.impl.NacosConnectionService;
+import org.apache.eventmesh.console.service.impl.NacosSubscriptionService;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * Use different registry SDK depending on the configured meta type
+ */
+@Configuration
+public class MetaTypeConfig {
+
+    private final AdminProperties adminProperties;
+
+    public MetaTypeConfig(AdminProperties adminProperties) {
+        this.adminProperties = adminProperties;
+    }
+
+    @Bean
+    public ConnectionService connectionService() {
+        switch (adminProperties.getMeta().getType()) {
+            case META_TYPE_NACOS:
+                return new NacosConnectionService(adminProperties);
+            case META_TYPE_ETCD:
+                return new EtcdConnectionService();
+            default:
+                throw new IllegalArgumentException("Unsupported eventmesh meta 
type: " + adminProperties.getMeta().getType());
+        }
+    }
+
+    @Bean
+    public SubscriptionService subscriptionService() {
+        switch (adminProperties.getMeta().getType()) {
+            case META_TYPE_NACOS:
+                return new NacosSubscriptionService(adminProperties);
+            case META_TYPE_ETCD:
+                return new EtcdSubscriptionService();
+            default:
+                throw new IllegalArgumentException("Unsupported eventmesh meta 
type: " + adminProperties.getMeta().getType());
+        }
+    }
+}
\ No newline at end of file
diff --git 
a/eventmesh-console/src/main/java/org/apache/eventmesh/console/controller/ConnectionController.java
 
b/eventmesh-console/src/main/java/org/apache/eventmesh/console/controller/ConnectionController.java
new file mode 100644
index 000000000..217418e46
--- /dev/null
+++ 
b/eventmesh-console/src/main/java/org/apache/eventmesh/console/controller/ConnectionController.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.eventmesh.console.controller;
+
+import org.apache.eventmesh.console.service.ConnectionService;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+@RestController
+public class ConnectionController {
+
+    @Autowired
+    public ConnectionService connectionService;
+
+    /**
+     * Query Connection List
+     * <p>
+     * The subscription information of SourceConnector and SinkConnector 
reported by EventMesh Runtime to the meta,
+     * containing the configuration of each connection.
+     *
+     * @param page the page number
+     * @param size the page size
+     * @return A paged list of connection configuration and total number of 
pages
+     */
+    @GetMapping("/connection")
+    public String listConnections(@RequestParam("page") Integer page, 
@RequestParam("size") String size) {
+        return null;
+    }
+
+}
diff --git 
a/eventmesh-console/src/main/java/org/apache/eventmesh/console/controller/SubscriptionController.java
 
b/eventmesh-console/src/main/java/org/apache/eventmesh/console/controller/SubscriptionController.java
new file mode 100644
index 000000000..96459872f
--- /dev/null
+++ 
b/eventmesh-console/src/main/java/org/apache/eventmesh/console/controller/SubscriptionController.java
@@ -0,0 +1,83 @@
+/*
+ * 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.console.controller;
+
+import org.apache.eventmesh.console.dto.SubscriptionResponse;
+import org.apache.eventmesh.console.exception.EventMeshAdminException;
+import org.apache.eventmesh.console.service.SubscriptionService;
+
+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;
+import org.springframework.web.bind.annotation.RestController;
+
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+@RestController
+@RequestMapping("/api/v1")
+public class SubscriptionController {
+
+    @Autowired
+    public SubscriptionService subscriptionService;
+
+    // the subscription dataId naming pattern of EventMesh clients: ip-protocol
+    private static final String CLIENT_DATA_ID_PATTERN = "*.*.*.*-*";
+
+    /**
+     * Retrieve the config content of a specified config.
+     *
+     * @param dataId nacos config data id (Exact Matching)
+     * @param group  config group (Exact Matching)
+     * @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());
+        }
+    }
+
+    /**
+     * Retrieve a list of configs.
+     *
+     * @param page page number
+     * @param size page size
+     * @param dataId nacos config data id (Fuzzy Matching)
+     * @param group config group (Fuzzy Matching)
+     * @return config properties and base64 encoded config content
+     */
+    @GetMapping("/subscriptions")
+    public ResponseEntity<SubscriptionResponse> 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()));
+        }
+    }
+
+}
diff --git 
a/eventmesh-common/src/main/java/org/apache/eventmesh/common/exception/EventMeshException.java
 
b/eventmesh-console/src/main/java/org/apache/eventmesh/console/dto/SubscriptionResponse.java
similarity index 51%
copy from 
eventmesh-common/src/main/java/org/apache/eventmesh/common/exception/EventMeshException.java
copy to 
eventmesh-console/src/main/java/org/apache/eventmesh/console/dto/SubscriptionResponse.java
index 4adafcb4a..49d0e6505 100644
--- 
a/eventmesh-common/src/main/java/org/apache/eventmesh/common/exception/EventMeshException.java
+++ 
b/eventmesh-console/src/main/java/org/apache/eventmesh/console/dto/SubscriptionResponse.java
@@ -15,29 +15,30 @@
  * limitations under the License.
  */
 
-package org.apache.eventmesh.common.exception;
+package org.apache.eventmesh.console.dto;
 
-public class EventMeshException extends RuntimeException {
+import org.apache.eventmesh.console.model.SubscriptionInfo;
 
-    public static final long serialVersionUID = 5648256502005456586L;
+import java.util.List;
 
-    public EventMeshException(String message) {
-        super(message);
-    }
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
 
-    public EventMeshException(String message, Throwable cause) {
-        super(message, cause);
-    }
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class SubscriptionResponse {
 
-    public EventMeshException(Throwable cause) {
-        super(cause);
-    }
+    private List<SubscriptionInfo> subscriptionInfos;
 
-    public EventMeshException(String message, Throwable cause, boolean 
enableSuppression, boolean writableStackTrace) {
-        super(message, cause, enableSuppression, writableStackTrace);
-    }
+    private Integer pages;
+
+    private String message;
 
-    public EventMeshException(Integer errCode, String errMsg) {
-        super(String.format("errorCode: %s, errorMessage: %s", errCode, 
errMsg));
+    public SubscriptionResponse(String message) {
+        this.message = message;
     }
 }
diff --git 
a/eventmesh-common/src/main/java/org/apache/eventmesh/common/exception/EventMeshException.java
 
b/eventmesh-console/src/main/java/org/apache/eventmesh/console/exception/EventMeshAdminException.java
similarity index 61%
copy from 
eventmesh-common/src/main/java/org/apache/eventmesh/common/exception/EventMeshException.java
copy to 
eventmesh-console/src/main/java/org/apache/eventmesh/console/exception/EventMeshAdminException.java
index 4adafcb4a..6261b76bb 100644
--- 
a/eventmesh-common/src/main/java/org/apache/eventmesh/common/exception/EventMeshException.java
+++ 
b/eventmesh-console/src/main/java/org/apache/eventmesh/console/exception/EventMeshAdminException.java
@@ -15,29 +15,25 @@
  * limitations under the License.
  */
 
-package org.apache.eventmesh.common.exception;
+package org.apache.eventmesh.console.exception;
 
-public class EventMeshException extends RuntimeException {
+public class EventMeshAdminException extends RuntimeException {
 
-    public static final long serialVersionUID = 5648256502005456586L;
+    private static final long serialVersionUID = 2002022502005456586L;
 
-    public EventMeshException(String message) {
+    public EventMeshAdminException(String message) {
         super(message);
     }
 
-    public EventMeshException(String message, Throwable cause) {
+    public EventMeshAdminException(String message, Throwable cause) {
         super(message, cause);
     }
 
-    public EventMeshException(Throwable cause) {
+    public EventMeshAdminException(Throwable cause) {
         super(cause);
     }
 
-    public EventMeshException(String message, Throwable cause, boolean 
enableSuppression, boolean writableStackTrace) {
+    public EventMeshAdminException(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-common/src/main/java/org/apache/eventmesh/common/exception/EventMeshException.java
 
b/eventmesh-console/src/main/java/org/apache/eventmesh/console/exception/EventMeshException.java
similarity index 88%
copy from 
eventmesh-common/src/main/java/org/apache/eventmesh/common/exception/EventMeshException.java
copy to 
eventmesh-console/src/main/java/org/apache/eventmesh/console/exception/EventMeshException.java
index 4adafcb4a..5423ac254 100644
--- 
a/eventmesh-common/src/main/java/org/apache/eventmesh/common/exception/EventMeshException.java
+++ 
b/eventmesh-console/src/main/java/org/apache/eventmesh/console/exception/EventMeshException.java
@@ -15,11 +15,11 @@
  * limitations under the License.
  */
 
-package org.apache.eventmesh.common.exception;
+package org.apache.eventmesh.console.exception;
 
-public class EventMeshException extends RuntimeException {
+public class EventMeshException extends EventMeshAdminException {
 
-    public static final long serialVersionUID = 5648256502005456586L;
+    private static final long serialVersionUID = 5648256502005456586L;
 
     public EventMeshException(String message) {
         super(message);
diff --git 
a/eventmesh-common/src/main/java/org/apache/eventmesh/common/exception/EventMeshException.java
 
b/eventmesh-console/src/main/java/org/apache/eventmesh/console/exception/MetaException.java
similarity index 54%
copy from 
eventmesh-common/src/main/java/org/apache/eventmesh/common/exception/EventMeshException.java
copy to 
eventmesh-console/src/main/java/org/apache/eventmesh/console/exception/MetaException.java
index 4adafcb4a..e272b18cf 100644
--- 
a/eventmesh-common/src/main/java/org/apache/eventmesh/common/exception/EventMeshException.java
+++ 
b/eventmesh-console/src/main/java/org/apache/eventmesh/console/exception/MetaException.java
@@ -15,29 +15,17 @@
  * limitations under the License.
  */
 
-package org.apache.eventmesh.common.exception;
+package org.apache.eventmesh.console.exception;
 
-public class EventMeshException extends RuntimeException {
+public class MetaException extends EventMeshAdminException {
 
-    public static final long serialVersionUID = 5648256502005456586L;
+    private static final long serialVersionUID = 6246145526338359773L;
 
-    public EventMeshException(String message) {
+    public MetaException(String message) {
         super(message);
     }
 
-    public EventMeshException(String message, Throwable cause) {
+    public MetaException(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-common/src/main/java/org/apache/eventmesh/common/exception/EventMeshException.java
 
b/eventmesh-console/src/main/java/org/apache/eventmesh/console/model/ConnectionInfo.java
similarity index 50%
copy from 
eventmesh-common/src/main/java/org/apache/eventmesh/common/exception/EventMeshException.java
copy to 
eventmesh-console/src/main/java/org/apache/eventmesh/console/model/ConnectionInfo.java
index 4adafcb4a..ff265c9dd 100644
--- 
a/eventmesh-common/src/main/java/org/apache/eventmesh/common/exception/EventMeshException.java
+++ 
b/eventmesh-console/src/main/java/org/apache/eventmesh/console/model/ConnectionInfo.java
@@ -15,29 +15,8 @@
  * limitations under the License.
  */
 
-package org.apache.eventmesh.common.exception;
+package org.apache.eventmesh.console.model;
 
-public class EventMeshException extends RuntimeException {
+public class ConnectionInfo {
 
-    public 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-common/src/main/java/org/apache/eventmesh/common/exception/EventMeshException.java
 
b/eventmesh-console/src/main/java/org/apache/eventmesh/console/model/SubscriptionInfo.java
similarity index 50%
copy from 
eventmesh-common/src/main/java/org/apache/eventmesh/common/exception/EventMeshException.java
copy to 
eventmesh-console/src/main/java/org/apache/eventmesh/console/model/SubscriptionInfo.java
index 4adafcb4a..86e449734 100644
--- 
a/eventmesh-common/src/main/java/org/apache/eventmesh/common/exception/EventMeshException.java
+++ 
b/eventmesh-console/src/main/java/org/apache/eventmesh/console/model/SubscriptionInfo.java
@@ -15,29 +15,21 @@
  * limitations under the License.
  */
 
-package org.apache.eventmesh.common.exception;
+package org.apache.eventmesh.console.model;
 
-public class EventMeshException extends RuntimeException {
+import lombok.Builder;
+import lombok.Data;
 
-    public static final long serialVersionUID = 5648256502005456586L;
+@Data
+@Builder
+public class SubscriptionInfo {
 
-    public EventMeshException(String message) {
-        super(message);
-    }
+    // client name
+    private String clientName;
 
-    public EventMeshException(String message, Throwable cause) {
-        super(message, cause);
-    }
+    // group name
+    private String group;
 
-    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));
-    }
+    // config content
+    private String subscription;
 }
diff --git 
a/eventmesh-common/src/main/java/org/apache/eventmesh/common/exception/EventMeshException.java
 
b/eventmesh-console/src/main/java/org/apache/eventmesh/console/service/ConnectionService.java
similarity index 50%
copy from 
eventmesh-common/src/main/java/org/apache/eventmesh/common/exception/EventMeshException.java
copy to 
eventmesh-console/src/main/java/org/apache/eventmesh/console/service/ConnectionService.java
index 4adafcb4a..1ebb07304 100644
--- 
a/eventmesh-common/src/main/java/org/apache/eventmesh/common/exception/EventMeshException.java
+++ 
b/eventmesh-console/src/main/java/org/apache/eventmesh/console/service/ConnectionService.java
@@ -15,29 +15,13 @@
  * limitations under the License.
  */
 
-package org.apache.eventmesh.common.exception;
+package org.apache.eventmesh.console.service;
 
-public class EventMeshException extends RuntimeException {
-
-    public 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);
-    }
+/**
+ * "Connection" refers to the subscription relationship between connectors.
+ * It focuses on the configuration deployed on the source and sink connectors 
themselves,
+ * reported by the connector.
+ */
+public interface ConnectionService {
 
-    public EventMeshException(Integer errCode, String errMsg) {
-        super(String.format("errorCode: %s, errorMessage: %s", errCode, 
errMsg));
-    }
 }
diff --git 
a/eventmesh-common/src/main/java/org/apache/eventmesh/common/exception/EventMeshException.java
 
b/eventmesh-console/src/main/java/org/apache/eventmesh/console/service/SubscriptionService.java
similarity index 50%
copy from 
eventmesh-common/src/main/java/org/apache/eventmesh/common/exception/EventMeshException.java
copy to 
eventmesh-console/src/main/java/org/apache/eventmesh/console/service/SubscriptionService.java
index 4adafcb4a..2cab96426 100644
--- 
a/eventmesh-common/src/main/java/org/apache/eventmesh/common/exception/EventMeshException.java
+++ 
b/eventmesh-console/src/main/java/org/apache/eventmesh/console/service/SubscriptionService.java
@@ -15,29 +15,18 @@
  * limitations under the License.
  */
 
-package org.apache.eventmesh.common.exception;
+package org.apache.eventmesh.console.service;
 
-public class EventMeshException extends RuntimeException {
+import org.apache.eventmesh.console.dto.SubscriptionResponse;
 
-    public 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);
-    }
+/**
+ * "Subscription" refers to the traditional MQ producer-consumer topic 
subscription relationship,
+ * emphasizing the subscription relationship between EventMesh clients 
(including SDK and connectors) and topics,
+ * reported by the EventMesh runtime.
+ */
+public interface SubscriptionService {
 
-    public EventMeshException(String message, Throwable cause, boolean 
enableSuppression, boolean writableStackTrace) {
-        super(message, cause, enableSuppression, writableStackTrace);
-    }
+    String retrieveConfig(String dataId, String group);
 
-    public EventMeshException(Integer errCode, String errMsg) {
-        super(String.format("errorCode: %s, errorMessage: %s", errCode, 
errMsg));
-    }
+    SubscriptionResponse retrieveConfigs(Integer page, Integer size, String 
dataId, String group);
 }
diff --git 
a/eventmesh-common/src/main/java/org/apache/eventmesh/common/exception/EventMeshException.java
 
b/eventmesh-console/src/main/java/org/apache/eventmesh/console/service/impl/EtcdConnectionService.java
similarity index 50%
copy from 
eventmesh-common/src/main/java/org/apache/eventmesh/common/exception/EventMeshException.java
copy to 
eventmesh-console/src/main/java/org/apache/eventmesh/console/service/impl/EtcdConnectionService.java
index 4adafcb4a..be589d377 100644
--- 
a/eventmesh-common/src/main/java/org/apache/eventmesh/common/exception/EventMeshException.java
+++ 
b/eventmesh-console/src/main/java/org/apache/eventmesh/console/service/impl/EtcdConnectionService.java
@@ -15,29 +15,16 @@
  * limitations under the License.
  */
 
-package org.apache.eventmesh.common.exception;
+package org.apache.eventmesh.console.service.impl;
 
-public class EventMeshException extends RuntimeException {
+import org.apache.eventmesh.console.service.ConnectionService;
 
-    public static final long serialVersionUID = 5648256502005456586L;
+import org.springframework.stereotype.Service;
 
-    public EventMeshException(String message) {
-        super(message);
-    }
+import lombok.extern.slf4j.Slf4j;
 
-    public EventMeshException(String message, Throwable cause) {
-        super(message, cause);
-    }
+@Slf4j
+@Service
+public class EtcdConnectionService implements ConnectionService {
 
-    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-common/src/main/java/org/apache/eventmesh/common/exception/EventMeshException.java
 
b/eventmesh-console/src/main/java/org/apache/eventmesh/console/service/impl/EtcdSubscriptionService.java
similarity index 51%
copy from 
eventmesh-common/src/main/java/org/apache/eventmesh/common/exception/EventMeshException.java
copy to 
eventmesh-console/src/main/java/org/apache/eventmesh/console/service/impl/EtcdSubscriptionService.java
index 4adafcb4a..1c488edfa 100644
--- 
a/eventmesh-common/src/main/java/org/apache/eventmesh/common/exception/EventMeshException.java
+++ 
b/eventmesh-console/src/main/java/org/apache/eventmesh/console/service/impl/EtcdSubscriptionService.java
@@ -15,29 +15,26 @@
  * limitations under the License.
  */
 
-package org.apache.eventmesh.common.exception;
+package org.apache.eventmesh.console.service.impl;
 
-public class EventMeshException extends RuntimeException {
+import org.apache.eventmesh.console.dto.SubscriptionResponse;
+import org.apache.eventmesh.console.service.SubscriptionService;
 
-    public static final long serialVersionUID = 5648256502005456586L;
+import org.springframework.stereotype.Service;
 
-    public EventMeshException(String message) {
-        super(message);
-    }
-
-    public EventMeshException(String message, Throwable cause) {
-        super(message, cause);
-    }
+import lombok.extern.slf4j.Slf4j;
 
-    public EventMeshException(Throwable cause) {
-        super(cause);
-    }
+@Slf4j
+@Service
+public class EtcdSubscriptionService implements SubscriptionService {
 
-    public EventMeshException(String message, Throwable cause, boolean 
enableSuppression, boolean writableStackTrace) {
-        super(message, cause, enableSuppression, writableStackTrace);
+    @Override
+    public String retrieveConfig(String dataId, String group) {
+        return null;
     }
 
-    public EventMeshException(Integer errCode, String errMsg) {
-        super(String.format("errorCode: %s, errorMessage: %s", errCode, 
errMsg));
+    @Override
+    public SubscriptionResponse retrieveConfigs(Integer page, Integer size, 
String dataId, String group) {
+        return null;
     }
 }
diff --git 
a/eventmesh-console/src/main/java/org/apache/eventmesh/console/service/impl/NacosConnectionService.java
 
b/eventmesh-console/src/main/java/org/apache/eventmesh/console/service/impl/NacosConnectionService.java
new file mode 100644
index 000000000..a01cf13df
--- /dev/null
+++ 
b/eventmesh-console/src/main/java/org/apache/eventmesh/console/service/impl/NacosConnectionService.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.console.service.impl;
+
+import org.apache.eventmesh.console.config.AdminProperties;
+import org.apache.eventmesh.console.service.ConnectionService;
+
+import java.util.Properties;
+
+import org.springframework.stereotype.Service;
+
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+@Service
+public class NacosConnectionService implements ConnectionService {
+
+    Properties properties = new Properties();
+
+    public NacosConnectionService(AdminProperties adminProperties) {
+        properties.setProperty("serverAddr", 
adminProperties.getMeta().getNacos().getAddr());
+        properties.setProperty("username", 
adminProperties.getMeta().getNacos().getUsername());
+        properties.setProperty("password", 
adminProperties.getMeta().getNacos().getPassword());
+        properties.setProperty("namespace", 
adminProperties.getMeta().getNacos().getNamespace());
+        properties.setProperty("timeoutMs", 
String.valueOf(adminProperties.getConfig().getTimeoutMs()));
+    }
+
+}
diff --git 
a/eventmesh-console/src/main/java/org/apache/eventmesh/console/service/impl/NacosSubscriptionService.java
 
b/eventmesh-console/src/main/java/org/apache/eventmesh/console/service/impl/NacosSubscriptionService.java
new file mode 100644
index 000000000..195667581
--- /dev/null
+++ 
b/eventmesh-console/src/main/java/org/apache/eventmesh/console/service/impl/NacosSubscriptionService.java
@@ -0,0 +1,196 @@
+/*
+ * 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.console.service.impl;
+
+import static org.apache.eventmesh.console.config.Constants.NACOS_CONFIGS_API;
+import static org.apache.eventmesh.console.config.Constants.NACOS_LOGIN_API;
+
+import org.apache.eventmesh.console.config.AdminProperties;
+import org.apache.eventmesh.console.config.Constants;
+import org.apache.eventmesh.console.dto.SubscriptionResponse;
+import org.apache.eventmesh.console.exception.EventMeshAdminException;
+import org.apache.eventmesh.console.exception.MetaException;
+import org.apache.eventmesh.console.model.SubscriptionInfo;
+import org.apache.eventmesh.console.service.SubscriptionService;
+
+import java.util.ArrayList;
+import java.util.Base64;
+import java.util.Collections;
+import java.util.List;
+import java.util.Properties;
+
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Service;
+import org.springframework.util.LinkedMultiValueMap;
+import org.springframework.util.MultiValueMap;
+import org.springframework.web.client.RestTemplate;
+import org.springframework.web.util.UriComponentsBuilder;
+
+import com.alibaba.fastjson2.JSON;
+import com.alibaba.fastjson2.JSONObject;
+import com.alibaba.nacos.api.NacosFactory;
+import com.alibaba.nacos.api.PropertyKeyConst;
+import com.alibaba.nacos.api.config.ConfigService;
+
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+@Service
+public class NacosSubscriptionService implements SubscriptionService {
+
+    AdminProperties adminProperties;
+
+    Properties nacosProps = new Properties();
+
+    RestTemplate restTemplate = new RestTemplate();
+
+    private static String HTTP_PREFIX = Constants.HTTP_PREFIX;
+
+    public NacosSubscriptionService(AdminProperties adminProperties) {
+        this.adminProperties = adminProperties;
+
+        nacosProps.setProperty(PropertyKeyConst.SERVER_ADDR, 
adminProperties.getMeta().getNacos().getAddr());
+        nacosProps.setProperty(PropertyKeyConst.NAMESPACE, 
adminProperties.getMeta().getNacos().getNamespace());
+        if (adminProperties.getMeta().getNacos().isAuthEnabled()) {
+            if (!adminProperties.getMeta().getNacos().getUsername().isEmpty()) 
{
+                nacosProps.setProperty(PropertyKeyConst.USERNAME, 
adminProperties.getMeta().getNacos().getUsername());
+            }
+            if (!adminProperties.getMeta().getNacos().getPassword().isEmpty()) 
{
+                nacosProps.setProperty(PropertyKeyConst.PASSWORD, 
adminProperties.getMeta().getNacos().getPassword());
+            }
+            if 
(!adminProperties.getMeta().getNacos().getAccessKey().isEmpty()) {
+                nacosProps.setProperty(PropertyKeyConst.ACCESS_KEY, 
adminProperties.getMeta().getNacos().getAccessKey());
+            }
+            if 
(!adminProperties.getMeta().getNacos().getSecretKey().isEmpty()) {
+                nacosProps.setProperty(PropertyKeyConst.SECRET_KEY, 
adminProperties.getMeta().getNacos().getSecretKey());
+            }
+        }
+        if 
(adminProperties.getMeta().getNacos().getProtocol().equalsIgnoreCase("https")) {
+            HTTP_PREFIX = Constants.HTTPS_PREFIX;
+        }
+    }
+
+    /**
+     * Retrieve a specified config with Nacos SDK.
+     */
+    @Override
+    public String retrieveConfig(String dataId, String group) {
+        ConfigService configService;
+        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());
+        }
+        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());
+        }
+    }
+
+    /**
+     * 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) {
+        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");
+
+        if (adminProperties.getMeta().getNacos().isAuthEnabled()) {
+            urlBuilder.queryParam("accessToken", 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());
+        }
+        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.");
+        }
+
+        return toSubscriptionResponse(JSON.parseObject(response.getBody()));
+    }
+
+    private SubscriptionResponse toSubscriptionResponse(JSONObject obj) {
+        return SubscriptionResponse.builder()
+            .subscriptionInfos(toSubscriptionInfos(obj))
+            .pages(obj.getInteger("pagesAvailable"))
+            .message("success")
+            .build();
+    }
+
+    private List<SubscriptionInfo> toSubscriptionInfos(JSONObject obj) {
+        List<SubscriptionInfo> subscriptionInfos = new ArrayList<>();
+        for (Object pageItem : obj.getJSONArray("pageItems")) {
+            JSONObject pageItemObj = (JSONObject) pageItem;
+            subscriptionInfos.add(toSubscriptionInfo(pageItemObj));
+        }
+        return subscriptionInfos;
+    }
+
+    private SubscriptionInfo toSubscriptionInfo(JSONObject obj) {
+        String content = obj.getString("content");
+        return SubscriptionInfo.builder()
+            .clientName(obj.getString("dataId"))
+            .group(obj.getString("group"))
+            // The subscription content of Nacos config should be base64 
encoded to protect special characters.
+            
.subscription(Base64.getEncoder().encodeToString(content.getBytes()))
+            .build();
+    }
+
+    /**
+     * Login if auth enabled and return accessToken.
+     */
+    private String loginGetAccessToken() {
+        HttpHeaders headers = new HttpHeaders();
+        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)));
+
+        String loginUrl = HTTP_PREFIX + 
nacosProps.getProperty(PropertyKeyConst.SERVER_ADDR) + NACOS_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());
+        }
+        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());
+        }
+        return 
JSON.parseObject(loginResponse.getBody()).getString("accessToken");
+    }
+}
diff --git 
a/eventmesh-connectors/eventmesh-connector-rocketmq/src/main/resources/source-config.yml
 b/eventmesh-console/src/main/resources/application.yml
similarity index 55%
copy from 
eventmesh-connectors/eventmesh-connector-rocketmq/src/main/resources/source-config.yml
copy to eventmesh-console/src/main/resources/application.yml
index 09c87272a..d55a238e7 100644
--- 
a/eventmesh-connectors/eventmesh-connector-rocketmq/src/main/resources/source-config.yml
+++ b/eventmesh-console/src/main/resources/application.yml
@@ -15,26 +15,37 @@
 # limitations under the License.
 #
 
-pubSubConfig:
-    meshAddress: 127.0.0.1:10000
-    subject: TopicTest
-    idc: FT
-    env: PRD
-    group: rocketmqSource
-    appId: 5032
-    userName: rocketmqSourceUser
-    passWord: rocketmqPassWord
-connectorConfig:
-    connectorName: rocketmqSource
-    nameserver: 127.0.0.1:9877
-    topic: TopicTest
-    commitOffsetIntervalMs: 5000
-offsetStorageConfig:
-    offsetStorageType: nacos
-    offsetStorageAddr: 127.0.0.1:8848
-    extensions: {
-                    #same with topic
-                    dataId: TopicTest,
-                    #same with group
-                    group: rocketmqSource
-    }
+spring:
+  application:
+    name: eventmesh-admin
+
+server:
+  port: 8080
+  servlet:
+    encoding:
+      charset: UTF-8
+      enabled: true
+      force: true
+
+logging:
+  config: classpath:logback.xml
+
+eventmesh:
+  meta:
+    # registry type: nacos, etcd
+    type: nacos
+    nacos:
+      addr: 127.0.0.1:8848
+      namespace: # namespace id, empty by default
+      authEnabled: false
+      protocol: http # http or https
+      username:
+      password:
+      # Alibaba Cloud MSE Nacos auth, not nacos.token.secret.key
+      accessKey:
+      secretKey:
+    etcd:
+      addr: # TODO
+  config:
+    # timeout for admin client
+    timeoutMs: 5000
\ No newline at end of file
diff --git a/eventmesh-console/src/main/resources/logback.xml 
b/eventmesh-console/src/main/resources/logback.xml
new file mode 100644
index 000000000..29f868bc1
--- /dev/null
+++ b/eventmesh-console/src/main/resources/logback.xml
@@ -0,0 +1,50 @@
+<?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>
+       <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+               <encoder charset="UTF-8">
+                       <pattern>[%d{yyyy-MM-dd HH:mm:ss.SSS}] %p %t - 
%m%n</pattern>
+               </encoder>
+       </appender>
+
+       <appender name="FILE"
+               class="ch.qos.logback.core.rolling.RollingFileAppender">
+               <file>${user.home}/logs/eventmesh-admin.log</file>
+               <append>true</append>
+               <rollingPolicy 
class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+                       
<fileNamePattern>${user.home}/logs/eventmesh-admin-%d{yyyy-MM-dd}.%i.log
+                       </fileNamePattern>
+                       <timeBasedFileNamingAndTriggeringPolicy
+                               
class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
+                               <maxFileSize>104857600</maxFileSize>
+                       </timeBasedFileNamingAndTriggeringPolicy>
+                       <MaxHistory>10</MaxHistory>
+               </rollingPolicy>
+               <encoder>
+            <pattern>[%d{yyyy-MM-dd HH:mm:ss.SSS}] %p %t - %m%n</pattern>
+                       <charset 
class="java.nio.charset.Charset">UTF-8</charset>
+               </encoder>
+       </appender>
+
+       <root level="INFO">
+               <appender-ref ref="STDOUT" />
+               <appender-ref ref="FILE" />
+       </root>
+
+</configuration> 
\ No newline at end of file
diff --git 
a/eventmesh-common/src/main/java/org/apache/eventmesh/common/exception/EventMeshException.java
 
b/eventmesh-console/src/test/java/org/apache/eventmesh/console/EventMeshAdminApplicationTests.java
similarity index 51%
copy from 
eventmesh-common/src/main/java/org/apache/eventmesh/common/exception/EventMeshException.java
copy to 
eventmesh-console/src/test/java/org/apache/eventmesh/console/EventMeshAdminApplicationTests.java
index 4adafcb4a..81eaea058 100644
--- 
a/eventmesh-common/src/main/java/org/apache/eventmesh/common/exception/EventMeshException.java
+++ 
b/eventmesh-console/src/test/java/org/apache/eventmesh/console/EventMeshAdminApplicationTests.java
@@ -15,29 +15,16 @@
  * limitations under the License.
  */
 
-package org.apache.eventmesh.common.exception;
+package org.apache.eventmesh.console;
 
-public class EventMeshException extends RuntimeException {
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.context.SpringBootTest;
 
-    public static final long serialVersionUID = 5648256502005456586L;
+@SpringBootTest
+class EventMeshAdminApplicationTests {
 
-    public EventMeshException(String message) {
-        super(message);
+    @Test
+    void contextLoads() {
     }
 
-    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-runtime/src/main/java/org/apache/eventmesh/runtime/core/protocol/tcp/client/session/Session.java
 
b/eventmesh-runtime/src/main/java/org/apache/eventmesh/runtime/core/protocol/tcp/client/session/Session.java
index 375c51cba..37c5a1e37 100644
--- 
a/eventmesh-runtime/src/main/java/org/apache/eventmesh/runtime/core/protocol/tcp/client/session/Session.java
+++ 
b/eventmesh-runtime/src/main/java/org/apache/eventmesh/runtime/core/protocol/tcp/client/session/Session.java
@@ -25,6 +25,7 @@ import org.apache.eventmesh.common.protocol.tcp.Header;
 import org.apache.eventmesh.common.protocol.tcp.OPStatus;
 import org.apache.eventmesh.common.protocol.tcp.Package;
 import org.apache.eventmesh.common.protocol.tcp.UserAgent;
+import org.apache.eventmesh.common.utils.JsonUtils;
 import org.apache.eventmesh.runtime.configuration.EventMeshTCPConfiguration;
 import org.apache.eventmesh.runtime.constants.EventMeshConstants;
 import 
org.apache.eventmesh.runtime.core.protocol.tcp.client.group.ClientGroupWrapper;
@@ -39,7 +40,9 @@ import org.apache.commons.lang3.time.DateFormatUtils;
 
 import java.lang.ref.WeakReference;
 import java.net.InetSocketAddress;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.Objects;
 import java.util.UUID;
 import java.util.concurrent.locks.ReentrantLock;
@@ -199,25 +202,17 @@ public class Session {
 
     @Override
     public String toString() {
-        return "Session{"
-            +
-            "sysId=" + 
Objects.requireNonNull(clientGroupWrapper.get()).getSysId()
-            +
-            ",remoteAddr=" + 
RemotingHelper.parseSocketAddressAddr(remoteAddress)
-            +
-            ",client=" + client
-            +
-            ",sessionState=" + sessionState
-            +
-            ",sessionContext=" + sessionContext
-            +
-            ",pusher=" + pusher
-            +
-            ",sender=" + sender
-            +
-            ",createTime=" + DateFormatUtils.format(createTime, 
EventMeshConstants.DATE_FORMAT)
-            +
-            ",lastHeartbeatTime=" + DateFormatUtils.format(lastHeartbeatTime, 
EventMeshConstants.DATE_FORMAT) + '}';
+        Map<String, Object> sessionJson = new HashMap<>();
+        sessionJson.put("sysId", 
Objects.requireNonNull(clientGroupWrapper.get()).getSysId());
+        sessionJson.put("remoteAddr", 
RemotingHelper.parseSocketAddressAddr(remoteAddress));
+        sessionJson.put("client", client);
+        sessionJson.put("sessionState", sessionState);
+        sessionJson.put("sessionContext", sessionContext);
+        sessionJson.put("pusher", pusher);
+        sessionJson.put("sender", sender);
+        sessionJson.put("createTime", DateFormatUtils.format(createTime, 
EventMeshConstants.DATE_FORMAT));
+        sessionJson.put("lastHeartbeatTime", 
DateFormatUtils.format(lastHeartbeatTime, EventMeshConstants.DATE_FORMAT));
+        return JsonUtils.toJSONString(sessionJson);
     }
 
     @Override


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

Reply via email to