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

jin pushed a commit to branch master
in repository 
https://gitbox.apache.org/repos/asf/incubator-hugegraph-commons.git


The following commit(s) were added to refs/heads/master by this push:
     new 5ad55fb  feat(common): replace jersey dependencies with OkHttp 
(Breaking Change) (#133)
5ad55fb is described below

commit 5ad55fb82f1e8720778aa1a337f5cd2d0535c8b6
Author: 小宇 <[email protected]>
AuthorDate: Wed Nov 22 09:37:02 2023 +0800

    feat(common): replace jersey dependencies with OkHttp (Breaking Change) 
(#133)
    
    * remove jersey
    
    * Update ci.yml
    
    * refact: replace params okhttp3.Headers to internal RestHeaders
    
    * fix: licence dependency
    
    * fix: test error
    
    * fix: code format issue
    
    * fix: unit test error
    
    
    ---------
    
    Co-authored-by: imbajin <[email protected]>
---
 .github/workflows/ci.yml                           |   1 +
 .github/workflows/license-checker.yml              |   1 +
 hugegraph-common/pom.xml                           | 107 +--
 .../apache/hugegraph/rest/AbstractRestClient.java  | 719 ++++++++-------------
 .../hugegraph/rest/OkHttpBasicAuthInterceptor.java |  47 ++
 .../hugegraph/rest/OkHttpTokenInterceptor.java     |  50 ++
 .../java/org/apache/hugegraph/rest/RestClient.java |  11 +-
 .../apache/hugegraph/rest/RestClientConfig.java    |  27 +-
 .../org/apache/hugegraph/rest/RestHeaders.java     |  90 +++
 .../java/org/apache/hugegraph/rest/RestResult.java |  46 +-
 .../java/org/apache/hugegraph/util/JsonUtil.java   |  62 ++
 .../apache/hugegraph/version/CommonVersion.java    |   2 +-
 .../apache/hugegraph/unit/rest/RestClientTest.java | 507 ++++++---------
 .../apache/hugegraph/unit/rest/RestResultTest.java |  61 +-
 .../hugegraph/unit/util/ReflectionUtilTest.java    |   4 +-
 .../org.mockito.plugins.MockMaker                  |  17 +
 .../scripts/dependency/known-dependencies.txt      |  29 +-
 .../org/apache/hugegraph/version/RpcVersion.java   |   2 +-
 pom.xml                                            |   2 +-
 19 files changed, 866 insertions(+), 919 deletions(-)

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 0616bf8..cc0cd1a 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -1,6 +1,7 @@
 name: "hugegraph-commons ci"
 
 on:
+  workflow_dispatch:
   push:
     branches:
       - master
diff --git a/.github/workflows/license-checker.yml 
b/.github/workflows/license-checker.yml
index 9c74ed0..0485bd1 100644
--- a/.github/workflows/license-checker.yml
+++ b/.github/workflows/license-checker.yml
@@ -1,6 +1,7 @@
 name: "license checker"
 
 on:
+  workflow_dispatch:
   push:
     branches:
       - master
diff --git a/hugegraph-common/pom.xml b/hugegraph-common/pom.xml
index 01bf29b..2010869 100644
--- a/hugegraph-common/pom.xml
+++ b/hugegraph-common/pom.xml
@@ -15,8 +15,8 @@
   See the License for the specific language governing permissions and
   limitations under the License.
   -->
-<project xmlns="http://maven.apache.org/POM/4.0.0";
-         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+         xmlns="http://maven.apache.org/POM/4.0.0";
          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd";>
     <modelVersion>4.0.0</modelVersion>
     <parent>
@@ -32,11 +32,14 @@
     <description>
         hugegraph-common is a common module for HugeGraph and its peripheral 
components.
         hugegraph-common encapsulates locks, configurations, events, 
iterators, rest and some
-        numeric or collection util classes to simplify the development of 
HugeGraph and its components.
+        numeric or collection util classes to simplify the development of 
HugeGraph and its
+        components.
     </description>
 
     <properties>
         <!-- Use parent params -->
+        <lombok.version>1.18.8</lombok.version>
+        <okhttp.version>4.10.0</okhttp.version>
     </properties>
 
     <dependencies>
@@ -196,76 +199,6 @@
             <version>${jackson.version}</version>
         </dependency>
 
-        <!-- jersey -->
-        <dependency>
-            <groupId>org.glassfish.jersey.core</groupId>
-            <artifactId>jersey-client</artifactId>
-            <version>${jersey.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>org.glassfish.jersey.media</groupId>
-            <artifactId>jersey-media-json-jackson</artifactId>
-            <version>${jersey.version}</version>
-            <exclusions>
-                <exclusion>
-                    <groupId>com.fasterxml.jackson.jaxrs</groupId>
-                    <artifactId>jackson-jaxrs-base</artifactId>
-                </exclusion>
-                <exclusion>
-                    <groupId>com.fasterxml.jackson.jaxrs</groupId>
-                    <artifactId>jackson-jaxrs-json-provider</artifactId>
-                </exclusion>
-                <exclusion>
-                    <artifactId>jackson-annotations</artifactId>
-                    <groupId>com.fasterxml.jackson.core</groupId>
-                </exclusion>
-                <exclusion>
-                    <artifactId>jackson-databind</artifactId>
-                    <groupId>com.fasterxml.jackson.core</groupId>
-                </exclusion>
-                <exclusion>
-                    <artifactId>jackson-module-jaxb-annotations</artifactId>
-                    <groupId>com.fasterxml.jackson.module</groupId>
-                </exclusion>
-            </exclusions>
-        </dependency>
-        <dependency>
-            <groupId>org.glassfish.jersey.connectors</groupId>
-            <artifactId>jersey-apache-connector</artifactId>
-            <version>${jersey.version}</version>
-            <exclusions>
-                <exclusion>
-                    <artifactId>commons-codec</artifactId>
-                    <groupId>commons-codec</groupId>
-                </exclusion>
-                <exclusion>
-                    <artifactId>commons-logging</artifactId>
-                    <groupId>commons-logging</groupId>
-                </exclusion>
-            </exclusions>
-        </dependency>
-        <dependency>
-            <groupId>org.glassfish.jersey.inject</groupId>
-            <artifactId>jersey-hk2</artifactId>
-            <version>${jersey.hk2.version}</version>
-            <exclusions>
-                <exclusion>
-                    <artifactId>javassist</artifactId>
-                    <groupId>org.javassist</groupId>
-                </exclusion>
-            </exclusions>
-        </dependency>
-        <dependency>
-            <groupId>jakarta.xml.bind</groupId>
-            <artifactId>jakarta.xml.bind-api</artifactId>
-            <version>${jakarta.xml.version}</version>
-            <exclusions>
-                <exclusion>
-                    <artifactId>jakarta.activation-api</artifactId>
-                    <groupId>jakarta.activation</groupId>
-                </exclusion>
-            </exclusions>
-        </dependency>
         <dependency>
             <groupId>com.sun.xml.bind</groupId>
             <artifactId>jaxb-impl</artifactId>
@@ -278,8 +211,36 @@
                 </exclusion>
             </exclusions>
         </dependency>
+
+        <dependency>
+            <groupId>com.squareup.okhttp3</groupId>
+            <artifactId>okhttp</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.squareup.okhttp3</groupId>
+            <artifactId>logging-interceptor</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+            <version>${lombok.version}</version>
+            <optional>true</optional>
+        </dependency>
     </dependencies>
 
+    <dependencyManagement>
+        <dependencies>
+            <dependency>
+                <groupId>com.squareup.okhttp3</groupId>
+                <artifactId>okhttp-bom</artifactId>
+                <version>${okhttp.version}</version>
+                <type>pom</type>
+                <scope>import</scope>
+            </dependency>
+        </dependencies>
+    </dependencyManagement>
+
     <build>
         <plugins>
             <plugin>
diff --git 
a/hugegraph-common/src/main/java/org/apache/hugegraph/rest/AbstractRestClient.java
 
b/hugegraph-common/src/main/java/org/apache/hugegraph/rest/AbstractRestClient.java
index ea7e923..27d9add 100644
--- 
a/hugegraph-common/src/main/java/org/apache/hugegraph/rest/AbstractRestClient.java
+++ 
b/hugegraph-common/src/main/java/org/apache/hugegraph/rest/AbstractRestClient.java
@@ -17,188 +17,219 @@
 
 package org.apache.hugegraph.rest;
 
+import java.io.FileInputStream;
+import java.io.IOException;
 import java.net.URI;
-import java.security.KeyManagementException;
-import java.security.SecureRandom;
-import java.security.cert.CertificateException;
-import java.security.cert.X509Certificate;
+import java.security.KeyStore;
+import java.util.Arrays;
 import java.util.Collection;
-import java.util.List;
 import java.util.Map;
-import java.util.concurrent.Callable;
-import java.util.concurrent.ScheduledExecutorService;
+import java.util.Objects;
 import java.util.concurrent.TimeUnit;
 
 import javax.net.ssl.HostnameVerifier;
 import javax.net.ssl.HttpsURLConnection;
 import javax.net.ssl.SSLContext;
 import javax.net.ssl.SSLSession;
+import javax.net.ssl.SSLSocketFactory;
 import javax.net.ssl.TrustManager;
+import javax.net.ssl.TrustManagerFactory;
 import javax.net.ssl.X509TrustManager;
 
-import org.apache.commons.collections.MapUtils;
-import org.apache.commons.lang.StringUtils;
-import org.apache.commons.lang3.tuple.Pair;
-import org.apache.http.HttpHeaders;
-import org.apache.http.config.Registry;
-import org.apache.http.config.RegistryBuilder;
-import org.apache.http.conn.socket.ConnectionSocketFactory;
-import org.apache.http.conn.socket.PlainConnectionSocketFactory;
-import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
-import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
-import org.apache.http.pool.PoolStats;
-import org.apache.hugegraph.util.E;
-import org.apache.hugegraph.util.ExecutorUtil;
-import org.glassfish.jersey.SslConfigurator;
-import org.glassfish.jersey.apache.connector.ApacheClientProperties;
-import org.glassfish.jersey.apache.connector.ApacheConnectorProvider;
-import org.glassfish.jersey.client.ClientConfig;
-import org.glassfish.jersey.client.ClientProperties;
-import org.glassfish.jersey.client.JerseyClientBuilder;
-import org.glassfish.jersey.client.authentication.HttpAuthenticationFeature;
-import org.glassfish.jersey.internal.util.collection.Ref;
-import org.glassfish.jersey.internal.util.collection.Refs;
-import org.glassfish.jersey.message.GZipEncoder;
-import org.glassfish.jersey.uri.UriComponent;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.hugegraph.util.JsonUtil;
+import org.jetbrains.annotations.NotNull;
 
 import com.google.common.collect.ImmutableMap;
 
-import jakarta.ws.rs.client.Client;
-import jakarta.ws.rs.client.ClientRequestContext;
-import jakarta.ws.rs.client.ClientRequestFilter;
-import jakarta.ws.rs.client.Entity;
-import jakarta.ws.rs.client.Invocation.Builder;
-import jakarta.ws.rs.client.WebTarget;
-import jakarta.ws.rs.core.MediaType;
-import jakarta.ws.rs.core.MultivaluedMap;
-import jakarta.ws.rs.core.Response;
-import jakarta.ws.rs.core.Variant;
-
+import lombok.SneakyThrows;
+import okhttp3.ConnectionPool;
+import okhttp3.HttpUrl;
+import okhttp3.MediaType;
+import okhttp3.OkHttpClient;
+import okhttp3.Request;
+import okhttp3.RequestBody;
+import okhttp3.Response;
+import okio.BufferedSink;
+import okio.GzipSink;
+import okio.Okio;
+
+/**
+ * This class provides an abstract implementation of the RestClient interface.
+ * It provides methods for making HTTP requests (GET, POST, PUT, DELETE) to a 
REST API.
+ * Note: It uses the OkHttp library to make these requests for now.
+ */
 public abstract class AbstractRestClient implements RestClient {
 
-    // Time unit: hours
-    private static final long TTL = 24L;
-    // Time unit: ms
-    private static final long IDLE_TIME = 40L * 1000L;
-
-    private static final String TOKEN_KEY = "tokenKey";
+    private final ThreadLocal<String> authContext;
 
-    private final Client client;
-    private final WebTarget target;
+    private final OkHttpClient client;
 
-    private PoolingHttpClientConnectionManager pool;
-    private ScheduledExecutorService cleanExecutor;
+    private final String baseUrl;
 
     public AbstractRestClient(String url, int timeout) {
-        this(url, new ConfigBuilder().configTimeout(timeout).build());
-    }
-
-    public AbstractRestClient(String url, String user, String password,
-                              int timeout) {
-        this(url, new ConfigBuilder().configTimeout(timeout)
-                                     .configUser(user, password)
-                                     .build());
+        this(url, RestClientConfig.builder().timeout(timeout).build());
     }
 
-    public AbstractRestClient(String url, int timeout,
-                              int maxTotal, int maxPerRoute) {
-        this(url, new ConfigBuilder().configTimeout(timeout)
-                                     .configPool(maxTotal, maxPerRoute)
-                                     .build());
+    public AbstractRestClient(String url, String user, String password, int 
timeout) {
+        this(url, RestClientConfig.builder()
+                                  .user(user)
+                                  .password(password)
+                                  .timeout(timeout)
+                                  .build());
     }
 
     public AbstractRestClient(String url, int timeout, int idleTime,
-                              int maxTotal, int maxPerRoute) {
-        this(url, new ConfigBuilder().configTimeout(timeout)
-                                     .configIdleTime(idleTime)
-                                     .configPool(maxTotal, maxPerRoute)
-                                     .build());
+                              int maxConns, int maxConnsPerRoute) {
+        this(url, RestClientConfig.builder()
+                                  .idleTime(idleTime)
+                                  .timeout(timeout)
+                                  .maxConns(maxConns)
+                                  .maxConnsPerRoute(maxConnsPerRoute)
+                                  .build());
+    }
+
+    public AbstractRestClient(String url, String user, String password, int 
timeout,
+                              int maxConns, int maxConnsPerRoute,
+                              String trustStoreFile, String 
trustStorePassword) {
+        this(url, RestClientConfig.builder()
+                                  .user(user).password(password)
+                                  .timeout(timeout)
+                                  .maxConns(maxConns)
+                                  .maxConnsPerRoute(maxConnsPerRoute)
+                                  .trustStoreFile(trustStoreFile)
+                                  .trustStorePassword(trustStorePassword)
+                                  .build());
     }
 
-    public AbstractRestClient(String url, String user, String password,
-                              int timeout, int maxTotal, int maxPerRoute) {
-        this(url, new ConfigBuilder().configTimeout(timeout)
-                                     .configUser(user, password)
-                                     .configPool(maxTotal, maxPerRoute)
-                                     .build());
-    }
+    public AbstractRestClient(String url, String token, int timeout,
+                              int maxConns, int maxConnsPerRoute,
+                              String trustStoreFile, String 
trustStorePassword) {
+        this(url, RestClientConfig.builder()
+                                  .token(token)
+                                  .timeout(timeout)
+                                  .maxConns(maxConns)
+                                  .maxConnsPerRoute(maxConnsPerRoute)
+                                  .trustStoreFile(trustStoreFile)
+                                  .trustStorePassword(trustStorePassword)
+                                  .build());
+    }
+
+    public AbstractRestClient(String url, RestClientConfig config) {
+        this.baseUrl = url;
+        this.client = buildOkHttpClient(config);
+        this.authContext = new InheritableThreadLocal<>();
+    }
+
+    private static RequestBody buildRequestBody(Object body, RestHeaders 
headers) {
+        String contentType = parseContentType(headers);
+        String bodyContent;
+        if (RestHeaders.APPLICATION_JSON.equals(contentType)) {
+            if (body == null) {
+                bodyContent = "{}";
+            } else {
+                bodyContent = JsonUtil.toJson(body);
+            }
+        } else {
+            bodyContent = String.valueOf(body);
+        }
+        RequestBody requestBody = RequestBody.create(bodyContent.getBytes(),
+                                                     
MediaType.parse(contentType));
 
-    public AbstractRestClient(String url, String user, String password,
-                              int timeout, int maxTotal, int maxPerRoute,
-                              String trustStoreFile,
-                              String trustStorePassword) {
-        this(url, new ConfigBuilder().configTimeout(timeout)
-                                     .configUser(user, password)
-                                     .configPool(maxTotal, maxPerRoute)
-                                     .configSSL(trustStoreFile,
-                                                trustStorePassword)
-                                     .build());
+        if (headers != null &&
+            "gzip".equals(headers.get(RestHeaders.CONTENT_ENCODING))) {
+            requestBody = gzipBody(requestBody);
+        }
+        return requestBody;
     }
 
-    public AbstractRestClient(String url, String token, int timeout) {
-        this(url, new ConfigBuilder().configTimeout(timeout)
-                                     .configToken(token)
-                                     .build());
-    }
+    private static RequestBody gzipBody(final RequestBody body) {
+        return new RequestBody() {
+            @Override
+            public MediaType contentType() {
+                return body.contentType();
+            }
 
-    public AbstractRestClient(String url, String token, int timeout,
-                              int maxTotal, int maxPerRoute) {
-        this(url, new ConfigBuilder().configTimeout(timeout)
-                                     .configToken(token)
-                                     .configPool(maxTotal, maxPerRoute)
-                                     .build());
+            @Override
+            public long contentLength() {
+                return -1; // We don't know the compressed length in advance!
+            }
+
+            @Override
+            public void writeTo(@NotNull BufferedSink sink) throws IOException 
{
+                BufferedSink gzipSink = Okio.buffer(new GzipSink(sink));
+                body.writeTo(gzipSink);
+                gzipSink.close();
+            }
+        };
     }
 
-    public AbstractRestClient(String url, String token, int timeout,
-                              int maxTotal, int maxPerRoute,
-                              String trustStoreFile,
-                              String trustStorePassword) {
-        this(url, new ConfigBuilder().configTimeout(timeout)
-                                     .configToken(token)
-                                     .configPool(maxTotal, maxPerRoute)
-                                     .configSSL(trustStoreFile,
-                                                trustStorePassword)
-                                     .build());
-    }
-
-    public AbstractRestClient(String url, ClientConfig config) {
-        configConnectionManager(url, config);
-
-        this.client = JerseyClientBuilder.newClient(config);
-        this.client.register(GZipEncoder.class);
-        this.target = this.client.target(url);
-        this.pool = (PoolingHttpClientConnectionManager) config.getProperty(
-                    ApacheClientProperties.CONNECTION_MANAGER);
-        if (this.pool != null) {
-            this.cleanExecutor = ExecutorUtil.newScheduledThreadPool(
-                                              "conn-clean-worker-%d");
-            Number idleTimeProp = (Number) config.getProperty("idleTime");
-            final long idleTime = idleTimeProp == null ?
-                                  IDLE_TIME : idleTimeProp.longValue();
-            final long checkPeriod = idleTime / 2L;
-            this.cleanExecutor.scheduleWithFixedDelay(() -> {
-                PoolStats stats = this.pool.getTotalStats();
-                int using = stats.getLeased() + stats.getPending();
-                if (using > 0) {
-                    // Do clean only when all connections are idle
-                    return;
-                }
-                // Release connections when all clients are inactive
-                this.pool.closeIdleConnections(idleTime, 
TimeUnit.MILLISECONDS);
-                this.pool.closeExpiredConnections();
-            }, checkPeriod, checkPeriod, TimeUnit.MILLISECONDS);
+    private static String parseContentType(RestHeaders headers) {
+        if (headers != null) {
+            String contentType = headers.get(RestHeaders.CONTENT_TYPE);
+            if (contentType != null) {
+                return contentType;
+            }
         }
+        return RestHeaders.APPLICATION_JSON;
     }
 
-    protected abstract void checkStatus(Response response,
-                                        Response.Status... statuses);
+    private OkHttpClient buildOkHttpClient(RestClientConfig config) {
+        OkHttpClient.Builder builder = new OkHttpClient.Builder();
+
+        if (config.getTimeout() != null) {
+            builder.connectTimeout(config.getTimeout(), TimeUnit.MILLISECONDS)
+                   .readTimeout(config.getTimeout(), TimeUnit.MILLISECONDS);
+        }
+
+        if (config.getMaxIdleConns() != null || config.getIdleTime() != null) {
+            ConnectionPool connectionPool = new 
ConnectionPool(config.getMaxIdleConns(),
+                                                               
config.getIdleTime(),
+                                                               
TimeUnit.SECONDS);
+            builder.connectionPool(connectionPool);
+        }
+
+        // auth header interceptor
+        if (StringUtils.isNotBlank(config.getUser()) &&
+            StringUtils.isNotBlank(config.getPassword())) {
+            builder.addInterceptor(new 
OkHttpBasicAuthInterceptor(config.getUser(),
+                                                                  
config.getPassword()));
+        }
+        if (StringUtils.isNotBlank(config.getToken())) {
+            builder.addInterceptor(new 
OkHttpTokenInterceptor(config.getToken()));
+        }
+
+        // ssl
+        configSsl(builder, this.baseUrl, config.getTrustStoreFile(),
+                  config.getTrustStorePassword());
+
+        OkHttpClient okHttpClient = builder.build();
+
+        if (config.getMaxConns() != null) {
+            okHttpClient.dispatcher().setMaxRequests(config.getMaxConns());
+        }
+
+        if (config.getMaxConnsPerRoute() != null) {
+            
okHttpClient.dispatcher().setMaxRequestsPerHost(config.getMaxConnsPerRoute());
+        }
+
+        return okHttpClient;
+    }
 
-    protected Response request(Callable<Response> method) {
-        try {
-            return method.call();
-        } catch (Exception e) {
-            throw new ClientException("Failed to do request", e);
+    @SneakyThrows
+    private void configSsl(OkHttpClient.Builder builder, String url, String 
trustStoreFile,
+                           String trustStorePass) {
+        if (StringUtils.isBlank(trustStoreFile) || 
StringUtils.isBlank(trustStorePass)) {
+            return;
         }
+
+        X509TrustManager trustManager = 
trustManagerForCertificates(trustStoreFile, trustStorePass);
+        SSLContext sslContext = SSLContext.getInstance("TLS");
+        sslContext.init(null, new TrustManager[]{trustManager}, null);
+        SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
+
+        builder.sslSocketFactory(sslSocketFactory, trustManager)
+               .hostnameVerifier(new HostNameVerifier(url));
     }
 
     @Override
@@ -207,31 +238,69 @@ public abstract class AbstractRestClient implements 
RestClient {
     }
 
     @Override
-    public RestResult post(String path, Object object,
-                           MultivaluedMap<String, Object> headers) {
+    public RestResult post(String path, Object object, RestHeaders headers) {
         return this.post(path, object, headers, null);
     }
 
     @Override
-    public RestResult post(String path, Object object,
-                           Map<String, Object> params) {
+    public RestResult post(String path, Object object, Map<String, Object> 
params) {
         return this.post(path, object, null, params);
     }
 
+    private Request.Builder genRequestBuilder(String path, String id, 
RestHeaders headers,
+                                              Map<String, Object> params) {
+        HttpUrl.Builder urlBuilder = 
Objects.requireNonNull(HttpUrl.parse(this.baseUrl))
+                                            .newBuilder()
+                                            .addPathSegments(path);
+        if (id != null) {
+            urlBuilder.addPathSegment(id);
+        }
+
+        if (params != null) {
+            params.forEach((name, value) -> {
+                if (value == null) {
+                    return;
+                }
+
+                if (value instanceof Collection) {
+                    for (Object i : (Collection<?>) value) {
+                        urlBuilder.addQueryParameter(name, String.valueOf(i));
+                    }
+                } else {
+                    urlBuilder.addQueryParameter(name, String.valueOf(value));
+                }
+            });
+        }
+
+        Request.Builder builder = newRequestBuilder().url(urlBuilder.build());
+
+        if (headers != null) {
+            builder.headers(headers.toOkHttpHeader());
+        }
+
+        this.attachAuthToRequest(builder);
+
+        return builder;
+    }
+
+    /**
+     * In order to provide subclasses with overloading opportunities
+     */
+    protected Request.Builder newRequestBuilder() {
+        return new Request.Builder();
+    }
+
+    @SneakyThrows
     @Override
-    public RestResult post(String path, Object object,
-                           MultivaluedMap<String, Object> headers,
+    public RestResult post(String path, Object object, RestHeaders headers,
                            Map<String, Object> params) {
-        Pair<Builder, Entity<?>> pair = this.buildRequest(path, null, object,
-                                                          headers, params);
-        Response response = this.request(() -> {
-            // pair.getLeft() is builder, pair.getRight() is entity (http body)
-            return pair.getLeft().post(pair.getRight());
-        });
-        // If check status failed, throw client exception.
-        checkStatus(response, Response.Status.CREATED,
-                    Response.Status.OK, Response.Status.ACCEPTED);
-        return new RestResult(response);
+        Request.Builder requestBuilder = genRequestBuilder(path, null, 
headers, params);
+        requestBuilder.post(buildRequestBody(object, headers));
+
+        try (Response response = request(requestBuilder)) {
+            checkStatus(response, 200, 201, 202);
+            return new RestResult(response);
+        }
     }
 
     @Override
@@ -240,30 +309,27 @@ public abstract class AbstractRestClient implements 
RestClient {
     }
 
     @Override
-    public RestResult put(String path, String id, Object object,
-                          MultivaluedMap<String, Object> headers) {
+    public RestResult put(String path, String id, Object object, RestHeaders 
headers) {
         return this.put(path, id, object, headers, null);
     }
 
     @Override
-    public RestResult put(String path, String id, Object object,
-                          Map<String, Object> params) {
+    public RestResult put(String path, String id, Object object, Map<String, 
Object> params) {
         return this.put(path, id, object, null, params);
     }
 
+    @SneakyThrows
     @Override
     public RestResult put(String path, String id, Object object,
-                          MultivaluedMap<String, Object> headers,
+                          RestHeaders headers,
                           Map<String, Object> params) {
-        Pair<Builder, Entity<?>> pair = this.buildRequest(path, id, object,
-                                                          headers, params);
-        Response response = this.request(() -> {
-            // pair.getLeft() is builder, pair.getRight() is entity (http body)
-            return pair.getLeft().put(pair.getRight());
-        });
-        // If check status failed, throw client exception.
-        checkStatus(response, Response.Status.OK, Response.Status.ACCEPTED);
-        return new RestResult(response);
+        Request.Builder requestBuilder = genRequestBuilder(path, id, headers, 
params);
+        requestBuilder.put(buildRequestBody(object, headers));
+
+        try (Response response = request(requestBuilder)) {
+            checkStatus(response, 200, 202);
+            return new RestResult(response);
+        }
     }
 
     @Override
@@ -281,29 +347,14 @@ public abstract class AbstractRestClient implements 
RestClient {
         return this.get(path, id, ImmutableMap.of());
     }
 
+    @SneakyThrows
     private RestResult get(String path, String id, Map<String, Object> params) 
{
-        Ref<WebTarget> target = Refs.of(this.target);
-        for (String key : params.keySet()) {
-            Object value = params.get(key);
-            if (value instanceof Collection) {
-                for (Object i : (Collection<?>) value) {
-                    target.set(target.get().queryParam(key, i));
-                }
-            } else {
-                target.set(target.get().queryParam(key, value));
-            }
-        }
+        Request.Builder requestBuilder = genRequestBuilder(path, id, null, 
params);
 
-        Response response = this.request(() -> {
-            WebTarget webTarget = target.get();
-            Builder builder = id == null ? webTarget.path(path).request() :
-                              webTarget.path(path).path(encode(id)).request();
-            this.attachAuthToRequest(builder);
-            return builder.get();
-        });
-
-        checkStatus(response, Response.Status.OK);
-        return new RestResult(response);
+        try (Response response = request(requestBuilder)) {
+            checkStatus(response, 200);
+            return new RestResult(response);
+        }
     }
 
     @Override
@@ -316,40 +367,35 @@ public abstract class AbstractRestClient implements 
RestClient {
         return this.delete(path, id, ImmutableMap.of());
     }
 
+    @SneakyThrows
     private RestResult delete(String path, String id,
                               Map<String, Object> params) {
-        Ref<WebTarget> target = Refs.of(this.target);
-        for (String key : params.keySet()) {
-            target.set(target.get().queryParam(key, params.get(key)));
+        Request.Builder requestBuilder = genRequestBuilder(path, id, null, 
params);
+        requestBuilder.delete();
+
+        try (Response response = request(requestBuilder)) {
+            checkStatus(response, 204, 202);
+            return new RestResult(response);
         }
+    }
 
-        Response response = this.request(() -> {
-            WebTarget webTarget = target.get();
-            Builder builder = id == null ? webTarget.path(path).request() :
-                              webTarget.path(path).path(encode(id)).request();
-            this.attachAuthToRequest(builder);
-            return builder.delete();
-        });
+    protected abstract void checkStatus(Response response, int... statuses);
 
-        checkStatus(response, Response.Status.NO_CONTENT,
-                    Response.Status.ACCEPTED);
-        return new RestResult(response);
+    @SneakyThrows
+    protected Response request(Request.Builder requestBuilder) {
+        return this.client.newCall(requestBuilder.build()).execute();
     }
 
+    @SneakyThrows
     @Override
     public void close() {
-        if (this.pool != null) {
-            this.pool.close();
-            this.cleanExecutor.shutdownNow();
+        if (this.client != null) {
+            this.client.dispatcher().executorService().shutdown();
+            this.client.connectionPool().evictAll();
+            if (this.client.cache() != null) {
+                this.client.cache().close();
+            }
         }
-        this.client.close();
-    }
-
-    private final ThreadLocal<String> authContext =
-                                      new InheritableThreadLocal<>();
-
-    public void setAuthContext(String auth) {
-        this.authContext.set(auth);
     }
 
     public void resetAuthContext() {
@@ -360,132 +406,39 @@ public abstract class AbstractRestClient implements 
RestClient {
         return this.authContext.get();
     }
 
-    private void attachAuthToRequest(Builder builder) {
+    public void setAuthContext(String auth) {
+        this.authContext.set(auth);
+    }
+
+    private void attachAuthToRequest(Request.Builder builder) {
         // Add auth header
         String auth = this.getAuthContext();
         if (StringUtils.isNotEmpty(auth)) {
-            builder.header(HttpHeaders.AUTHORIZATION, auth);
+            builder.addHeader(RestHeaders.AUTHORIZATION, auth);
         }
     }
 
-    private Pair<Builder, Entity<?>> buildRequest(
-                                     String path, String id, Object object,
-                                     MultivaluedMap<String, Object> headers,
-                                     Map<String, Object> params) {
-        WebTarget target = this.target;
-        if (params != null && !params.isEmpty()) {
-            for (Map.Entry<String, Object> param : params.entrySet()) {
-                target = target.queryParam(param.getKey(), param.getValue());
-            }
-        }
-
-        Builder builder = id == null ? target.path(path).request() :
-                          target.path(path).path(encode(id)).request();
-
-        String encoding = null;
-        if (headers != null && !headers.isEmpty()) {
-            // Add headers
-            builder = builder.headers(headers);
-            encoding = (String) headers.getFirst("Content-Encoding");
-        }
-        // Add auth header
-        this.attachAuthToRequest(builder);
-
-        /*
-         * We should specify the encoding of the entity object manually,
-         * because Entity.json() method will reset "content encoding =
-         * null" that has been set up by headers before.
-         */
-        MediaType customContentType = parseCustomContentType(headers);
-        Entity<?> entity;
-        if (encoding == null) {
-            entity = Entity.entity(object, customContentType);
-        } else {
-            Variant variant = new Variant(customContentType,
-                                          (String) null, encoding);
-            entity = Entity.entity(object, variant);
-        }
-        return Pair.of(builder, entity);
-    }
+    @SneakyThrows
+    private X509TrustManager trustManagerForCertificates(String trustStoreFile,
+                                                         String 
trustStorePass) {
+        char[] password = trustStorePass.toCharArray();
 
-    /**
-     * parse user custom content-type, returns MediaType.APPLICATION_JSON_TYPE 
default.
-     * @param headers custom http header
-     */
-    private static MediaType parseCustomContentType(MultivaluedMap<String, 
Object> headers) {
-        String customContentType = null;
-        if (MapUtils.isNotEmpty(headers) && headers.get("Content-Type") != 
null) {
-            List<?> contentTypeObj = headers.get("Content-Type");
-            if (contentTypeObj != null && !contentTypeObj.isEmpty()) {
-                customContentType = contentTypeObj.get(0).toString();
-            }
-            return MediaType.valueOf(customContentType);
-        }
-        return MediaType.APPLICATION_JSON_TYPE;
-    }
-
-    private static void configConnectionManager(String url, ClientConfig conf) 
{
-        /*
-         * Using httpclient with connection pooling, and configuring the
-         * jersey connector. But the jersey that has been released in the 
maven central
-         * repository seems to have a bug: 
https://github.com/jersey/jersey/pull/3752
-         */
-        PoolingHttpClientConnectionManager pool = connectionManager(url, conf);
-        Object maxTotal = conf.getProperty("maxTotal");
-        Object maxPerRoute = conf.getProperty("maxPerRoute");
-        if (maxTotal != null) {
-            pool.setMaxTotal((int) maxTotal);
+        // load keyStore
+        KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
+        try (FileInputStream in = new FileInputStream(trustStoreFile)) {
+            keyStore.load(in, password);
         }
-        if (maxPerRoute != null) {
-            pool.setDefaultMaxPerRoute((int) maxPerRoute);
-        }
-        conf.property(ApacheClientProperties.CONNECTION_MANAGER, pool);
-        conf.connectorProvider(new ApacheConnectorProvider());
-    }
 
-    private static PoolingHttpClientConnectionManager connectionManager(
-                                                      String url,
-                                                      ClientConfig conf) {
-        String protocol = (String) conf.getProperty("protocol");
-        if (protocol == null || "http".equals(protocol)) {
-            return new PoolingHttpClientConnectionManager(TTL, TimeUnit.HOURS);
-        }
+        TrustManagerFactory trustManagerFactory =
+                
TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
+        trustManagerFactory.init(keyStore);
 
-        assert "https".equals(protocol);
-        String trustStoreFile = (String) conf.getProperty("trustStoreFile");
-        E.checkArgument(trustStoreFile != null && !trustStoreFile.isEmpty(),
-                        "The trust store file must be set when use https");
-        String trustStorePass = (String) 
conf.getProperty("trustStorePassword");
-        E.checkArgument(trustStorePass != null,
-                        "The trust store password must be set when use https");
-        SSLContext context = SslConfigurator.newInstance()
-                                            .trustStoreFile(trustStoreFile)
-                                            .trustStorePassword(trustStorePass)
-                                            .securityProtocol("SSL")
-                                            .createSSLContext();
-        TrustManager[] trustAllManager = NoCheckTrustManager.create();
-        try {
-            context.init(null, trustAllManager, new SecureRandom());
-        } catch (KeyManagementException e) {
-            throw new ClientException("Failed to init security management", e);
+        TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
+        if (trustManagers.length != 1 || !(trustManagers[0] instanceof 
X509TrustManager)) {
+            throw new IllegalStateException("Unexpected default trust 
managers:" +
+                                            Arrays.toString(trustManagers));
         }
-
-        HostnameVerifier verifier = new HostNameVerifier(url);
-        ConnectionSocketFactory httpSocketFactory, httpsSocketFactory;
-        httpSocketFactory = PlainConnectionSocketFactory.getSocketFactory();
-        httpsSocketFactory = new SSLConnectionSocketFactory(context, verifier);
-        Registry<ConnectionSocketFactory> registry =
-                RegistryBuilder.<ConnectionSocketFactory>create()
-                .register("http", httpSocketFactory)
-                .register("https", httpsSocketFactory)
-                .build();
-        return new PoolingHttpClientConnectionManager(registry, null,
-                                                      null, null, TTL,
-                                                      TimeUnit.HOURS);
-    }
-
-    public static String encode(String raw) {
-        return UriComponent.encode(raw, UriComponent.Type.PATH_SEGMENT);
+        return (X509TrustManager) trustManagers[0];
     }
 
     public static class HostNameVerifier implements HostnameVerifier {
@@ -505,107 +458,9 @@ public abstract class AbstractRestClient implements 
RestClient {
             if (!this.url.isEmpty() && this.url.endsWith(hostname)) {
                 return true;
             } else {
-                HostnameVerifier verifier = HttpsURLConnection
-                                            .getDefaultHostnameVerifier();
+                HostnameVerifier verifier = 
HttpsURLConnection.getDefaultHostnameVerifier();
                 return verifier.verify(hostname, session);
             }
         }
     }
-
-    private static class NoCheckTrustManager implements X509TrustManager {
-
-        @Override
-        public void checkClientTrusted(X509Certificate[] chain, String 
authType)
-                                       throws CertificateException {
-        }
-
-        @Override
-        public void checkServerTrusted(X509Certificate[] chain, String 
authType)
-                                       throws CertificateException {
-        }
-
-        @Override
-        public X509Certificate[] getAcceptedIssuers() {
-            return null;
-        }
-
-        public static TrustManager[] create() {
-            return new TrustManager[]{new NoCheckTrustManager()};
-        }
-    }
-
-    private static class ConfigBuilder {
-
-        private final ClientConfig config;
-
-        ConfigBuilder() {
-            this.config = new ClientConfig();
-        }
-
-        public ConfigBuilder configTimeout(int timeout) {
-            this.config.property(ClientProperties.CONNECT_TIMEOUT, timeout);
-            this.config.property(ClientProperties.READ_TIMEOUT, timeout);
-            return this;
-        }
-
-        public ConfigBuilder configUser(String username, String password) {
-            /*
-             * NOTE: don't use non-preemptive mode
-             * In non-preemptive mode the authentication information is added
-             * only when server refuses the request with 401 status code and
-             * then the request is repeated.
-             * Non-preemptive has negative impact on the performance. The
-             * advantage is it doesn't send credentials when they are not 
needed
-             * 
https://jersey.github.io/documentation/latest/client.html#d0e5461
-             */
-            this.config.register(HttpAuthenticationFeature.basic(username,
-                                                                 password));
-            return this;
-        }
-
-        public ConfigBuilder configToken(String token) {
-            this.config.property(TOKEN_KEY, token);
-            this.config.register(BearerRequestFilter.class);
-            return this;
-        }
-
-        public ConfigBuilder configPool(int maxTotal, int maxPerRoute) {
-            this.config.property("maxTotal", maxTotal);
-            this.config.property("maxPerRoute", maxPerRoute);
-            return this;
-        }
-
-        public ConfigBuilder configIdleTime(int idleTime) {
-            this.config.property("idleTime", idleTime);
-            return this;
-        }
-
-        public ConfigBuilder configSSL(String trustStoreFile,
-                                       String trustStorePassword) {
-            if (trustStoreFile == null || trustStoreFile.isEmpty() ||
-                trustStorePassword == null) {
-                this.config.property("protocol", "http");
-            } else {
-                this.config.property("protocol", "https");
-            }
-            this.config.property("trustStoreFile", trustStoreFile);
-            this.config.property("trustStorePassword", trustStorePassword);
-            return this;
-        }
-
-        public ClientConfig build() {
-            return this.config;
-        }
-    }
-
-    public static class BearerRequestFilter implements ClientRequestFilter {
-
-        @Override
-        public void filter(ClientRequestContext context) {
-            String token = context.getClient().getConfiguration()
-                                  .getProperty(TOKEN_KEY).toString();
-            context.getHeaders().add(HttpHeaders.AUTHORIZATION,
-                                     "Bearer " + token);
-        }
-    }
 }
diff --git 
a/hugegraph-common/src/main/java/org/apache/hugegraph/rest/OkHttpBasicAuthInterceptor.java
 
b/hugegraph-common/src/main/java/org/apache/hugegraph/rest/OkHttpBasicAuthInterceptor.java
new file mode 100644
index 0000000..f7b1509
--- /dev/null
+++ 
b/hugegraph-common/src/main/java/org/apache/hugegraph/rest/OkHttpBasicAuthInterceptor.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.hugegraph.rest;
+
+import java.io.IOException;
+
+import okhttp3.Credentials;
+import okhttp3.Interceptor;
+import okhttp3.Request;
+import okhttp3.Response;
+
+public class OkHttpBasicAuthInterceptor implements Interceptor {
+
+    private final String credentials;
+
+    public OkHttpBasicAuthInterceptor(String user, String password) {
+        this.credentials = Credentials.basic(user, password);
+    }
+
+    @Override
+    public Response intercept(Chain chain) throws IOException {
+        Request request = chain.request();
+        if (request.header(RestHeaders.AUTHORIZATION) == null) {
+            Request authenticatedRequest = request.newBuilder()
+                                                  
.header(RestHeaders.AUTHORIZATION,
+                                                          this.credentials)
+                                                  .build();
+            return chain.proceed(authenticatedRequest);
+        }
+        return chain.proceed(request);
+    }
+}
diff --git 
a/hugegraph-common/src/main/java/org/apache/hugegraph/rest/OkHttpTokenInterceptor.java
 
b/hugegraph-common/src/main/java/org/apache/hugegraph/rest/OkHttpTokenInterceptor.java
new file mode 100644
index 0000000..f564033
--- /dev/null
+++ 
b/hugegraph-common/src/main/java/org/apache/hugegraph/rest/OkHttpTokenInterceptor.java
@@ -0,0 +1,50 @@
+/*
+ * 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.hugegraph.rest;
+
+import static org.apache.hugegraph.rest.RestHeaders.AUTHORIZATION;
+import static org.apache.hugegraph.rest.RestHeaders.BEARER_PREFIX;
+
+import java.io.IOException;
+
+import okhttp3.Interceptor;
+import okhttp3.Request;
+import okhttp3.Response;
+
+
+public class OkHttpTokenInterceptor implements Interceptor {
+
+    private final String token;
+
+    public OkHttpTokenInterceptor(String token) {
+        this.token = token;
+    }
+
+    @Override
+    public Response intercept(Chain chain) throws IOException {
+        Request request = chain.request();
+        if (request.header(AUTHORIZATION) == null) {
+            Request authenticatedRequest = request.newBuilder()
+                                                  .header(AUTHORIZATION,
+                                                          BEARER_PREFIX + 
this.token)
+                                                  .build();
+            return chain.proceed(authenticatedRequest);
+        }
+        return chain.proceed(request);
+    }
+}
diff --git 
a/hugegraph-common/src/main/java/org/apache/hugegraph/rest/RestClient.java 
b/hugegraph-common/src/main/java/org/apache/hugegraph/rest/RestClient.java
index dc3b7b7..d5b58d9 100644
--- a/hugegraph-common/src/main/java/org/apache/hugegraph/rest/RestClient.java
+++ b/hugegraph-common/src/main/java/org/apache/hugegraph/rest/RestClient.java
@@ -19,31 +19,28 @@ package org.apache.hugegraph.rest;
 
 import java.util.Map;
 
-import jakarta.ws.rs.core.MultivaluedMap;
-
 public interface RestClient {
     /**
      * Post method
      */
     RestResult post(String path, Object object);
 
-    RestResult post(String path, Object object, MultivaluedMap<String, Object> 
headers);
+    RestResult post(String path, Object object, RestHeaders headers);
 
     RestResult post(String path, Object object, Map<String, Object> params);
 
-    RestResult post(String path, Object object, MultivaluedMap<String, Object> 
headers,
-                    Map<String, Object> params);
+    RestResult post(String path, Object object, RestHeaders headers, 
Map<String, Object> params);
 
     /**
      * Put method
      */
     RestResult put(String path, String id, Object object);
 
-    RestResult put(String path, String id, Object object, 
MultivaluedMap<String, Object> headers);
+    RestResult put(String path, String id, Object object, RestHeaders headers);
 
     RestResult put(String path, String id, Object object, Map<String, Object> 
params);
 
-    RestResult put(String path, String id, Object object, 
MultivaluedMap<String, Object> headers,
+    RestResult put(String path, String id, Object object, RestHeaders headers,
                    Map<String, Object> params);
 
     /**
diff --git 
a/hugegraph-rpc/src/main/java/org/apache/hugegraph/version/RpcVersion.java 
b/hugegraph-common/src/main/java/org/apache/hugegraph/rest/RestClientConfig.java
similarity index 60%
copy from 
hugegraph-rpc/src/main/java/org/apache/hugegraph/version/RpcVersion.java
copy to 
hugegraph-common/src/main/java/org/apache/hugegraph/rest/RestClientConfig.java
index f3cf926..ef3e9b0 100644
--- a/hugegraph-rpc/src/main/java/org/apache/hugegraph/version/RpcVersion.java
+++ 
b/hugegraph-common/src/main/java/org/apache/hugegraph/rest/RestClientConfig.java
@@ -15,14 +15,27 @@
  * under the License.
  */
 
-package org.apache.hugegraph.version;
+package org.apache.hugegraph.rest;
 
-import org.apache.hugegraph.util.VersionUtil.Version;
+import lombok.Builder;
+import lombok.Getter;
+import lombok.Setter;
 
-public class RpcVersion {
+@Builder
+@Getter
+@Setter
+public class RestClientConfig {
 
-    public static final String NAME = "hugegraph-rpc";
-
-    // The second parameter of Version.of() is for all-in-one JAR
-    public static final Version VERSION = Version.of(RpcVersion.class, 
"1.0.1");
+    private String user;
+    private String password;
+    private String token;
+    // unit in milliseconds
+    private Integer timeout;
+    private Integer maxConns;
+    private Integer maxConnsPerRoute;
+    // unit in seconds
+    private Integer idleTime = 30;
+    private Integer maxIdleConns = 5;
+    private String trustStoreFile;
+    private String trustStorePassword;
 }
diff --git 
a/hugegraph-common/src/main/java/org/apache/hugegraph/rest/RestHeaders.java 
b/hugegraph-common/src/main/java/org/apache/hugegraph/rest/RestHeaders.java
new file mode 100644
index 0000000..03c082e
--- /dev/null
+++ b/hugegraph-common/src/main/java/org/apache/hugegraph/rest/RestHeaders.java
@@ -0,0 +1,90 @@
+/*
+ * 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.hugegraph.rest;
+
+import java.util.Date;
+import java.util.Iterator;
+
+import kotlin.Pair;
+
+public class RestHeaders {
+
+    public static final String CONTENT_TYPE = "Content-Type";
+
+    public static final String CONTENT_ENCODING = "Content-Encoding";
+
+    public static final String AUTHORIZATION = "Authorization";
+
+    public static final String APPLICATION_JSON = "application/json";
+
+    public static final String BEARER_PREFIX = "Bearer ";
+
+    private final okhttp3.Headers.Builder headersBuilder;
+
+    public RestHeaders() {
+        this.headersBuilder = new okhttp3.Headers.Builder();
+    }
+
+    public static RestHeaders convertToRestHeaders(okhttp3.Headers headers) {
+        RestHeaders restHeaders = new RestHeaders();
+
+        if (headers != null) {
+            Iterator<Pair<String, String>> iter = headers.iterator();
+            while (iter.hasNext()) {
+                Pair<String, String> pair = iter.next();
+                restHeaders.add(pair.getFirst(), pair.getSecond());
+            }
+        }
+        return restHeaders;
+    }
+
+    public String get(String key) {
+        return this.headersBuilder.get(key);
+    }
+
+    public Date getDate(String key) {
+        return this.headersBuilder.build().getDate(key);
+    }
+
+    public RestHeaders add(String key, String value) {
+        this.headersBuilder.add(key, value);
+        return this;
+    }
+
+    public RestHeaders add(String key, Date value) {
+        this.headersBuilder.add(key, value);
+        return this;
+    }
+
+    @Override
+    public int hashCode() {
+        return this.toOkHttpHeader().hashCode();
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj instanceof RestHeaders) {
+            return this.toOkHttpHeader().equals(((RestHeaders) 
obj).toOkHttpHeader());
+        }
+        return false;
+    }
+
+    public okhttp3.Headers toOkHttpHeader() {
+        return this.headersBuilder.build();
+    }
+}
diff --git 
a/hugegraph-common/src/main/java/org/apache/hugegraph/rest/RestResult.java 
b/hugegraph-common/src/main/java/org/apache/hugegraph/rest/RestResult.java
index 82b7f39..0aa482b 100644
--- a/hugegraph-common/src/main/java/org/apache/hugegraph/rest/RestResult.java
+++ b/hugegraph-common/src/main/java/org/apache/hugegraph/rest/RestResult.java
@@ -21,39 +21,47 @@ import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
 
-import jakarta.ws.rs.core.MultivaluedMap;
-import jakarta.ws.rs.core.Response;
-
 import com.fasterxml.jackson.databind.JavaType;
 import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.Module;
 import com.fasterxml.jackson.databind.ObjectMapper;
 
+import lombok.SneakyThrows;
+import okhttp3.Response;
+
 public class RestResult {
 
     private static final ObjectMapper MAPPER = new ObjectMapper();
 
     private final int status;
-    private final MultivaluedMap<String, Object> headers;
+    private final RestHeaders headers;
     private final String content;
 
     public RestResult(Response response) {
-        this(response.getStatus(), response.readEntity(String.class),
-             response.getHeaders());
+        this(response.code(), getResponseContent(response),
+             RestHeaders.convertToRestHeaders(response.headers()));
     }
 
-    public RestResult(int status, String content,
-                      MultivaluedMap<String, Object> headers) {
+    public RestResult(int status, String content, RestHeaders headers) {
         this.status = status;
         this.headers = headers;
         this.content = content;
     }
 
+    @SneakyThrows
+    private static String getResponseContent(Response response) {
+        return response.body().string();
+    }
+
+    public static void registerModule(Module module) {
+        MAPPER.registerModule(module);
+    }
+
     public int status() {
         return this.status;
     }
 
-    public MultivaluedMap<String, Object> headers() {
+    public RestHeaders headers() {
         return this.headers;
     }
 
@@ -65,8 +73,7 @@ public class RestResult {
         try {
             return MAPPER.readValue(this.content, clazz);
         } catch (Exception e) {
-            throw new SerializeException(
-                      "Failed to deserialize: %s", e, this.content);
+            throw new SerializeException("Failed to deserialize: %s", e, 
this.content);
         }
     }
 
@@ -76,16 +83,14 @@ public class RestResult {
             JsonNode root = MAPPER.readTree(this.content);
             JsonNode element = root.get(key);
             if (element == null) {
-                throw new SerializeException(
-                          "Can't find value of the key: %s in json.", key);
+                throw new SerializeException("Can't find value of the key: %s 
in json.", key);
             }
             JavaType type = MAPPER.getTypeFactory()
                                   .constructParametrizedType(ArrayList.class,
                                                              List.class, 
clazz);
             return MAPPER.convertValue(element, type);
         } catch (IOException e) {
-            throw new SerializeException(
-                      "Failed to deserialize %s", e, this.content);
+            throw new SerializeException("Failed to deserialize %s", e, 
this.content);
         }
     }
 
@@ -97,18 +102,13 @@ public class RestResult {
         try {
             return MAPPER.readValue(this.content, type);
         } catch (IOException e) {
-            throw new SerializeException(
-                      "Failed to deserialize %s", e, this.content);
+            throw new SerializeException("Failed to deserialize %s", e, 
this.content);
         }
     }
 
     @Override
     public String toString() {
-        return String.format("{status=%s, headers=%s, content=%s}",
-                             this.status, this.headers, this.content);
-    }
-
-    public static void registerModule(Module module) {
-        MAPPER.registerModule(module);
+        return String.format("{status=%s, headers=%s, content=%s}", 
this.status, this.headers,
+                             this.content);
     }
 }
diff --git 
a/hugegraph-common/src/main/java/org/apache/hugegraph/util/JsonUtil.java 
b/hugegraph-common/src/main/java/org/apache/hugegraph/util/JsonUtil.java
new file mode 100644
index 0000000..fc9586b
--- /dev/null
+++ b/hugegraph-common/src/main/java/org/apache/hugegraph/util/JsonUtil.java
@@ -0,0 +1,62 @@
+/*
+ * 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.hugegraph.util;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.Module;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.apache.hugegraph.rest.SerializeException;
+
+import java.io.IOException;
+
+public final class JsonUtil {
+
+    private static final ObjectMapper MAPPER = new ObjectMapper();
+
+    public static void registerModule(Module module) {
+        MAPPER.registerModule(module);
+    }
+
+    public static String toJson(Object object) {
+        try {
+            return MAPPER.writeValueAsString(object);
+        } catch (JsonProcessingException e) {
+            throw new SerializeException("Failed to serialize object '%s'",
+                                         e, object);
+        }
+    }
+
+    public static <T> T fromJson(String json, Class<T> clazz) {
+        try {
+            return MAPPER.readValue(json, clazz);
+        } catch (IOException e) {
+            throw new SerializeException("Failed to deserialize json '%s'",
+                                         e, json);
+        }
+    }
+
+    public static <T> T convertValue(JsonNode node, Class<T> clazz) {
+        try {
+            return MAPPER.convertValue(node, clazz);
+        } catch (IllegalArgumentException e) {
+            throw new SerializeException("Failed to deserialize json node 
'%s'",
+                                         e, node);
+        }
+    }
+}
diff --git 
a/hugegraph-common/src/main/java/org/apache/hugegraph/version/CommonVersion.java
 
b/hugegraph-common/src/main/java/org/apache/hugegraph/version/CommonVersion.java
index bcdad92..a049ff4 100644
--- 
a/hugegraph-common/src/main/java/org/apache/hugegraph/version/CommonVersion.java
+++ 
b/hugegraph-common/src/main/java/org/apache/hugegraph/version/CommonVersion.java
@@ -24,5 +24,5 @@ public class CommonVersion {
     public static final String NAME = "hugegraph-common";
 
     // The second parameter of Version.of() is for all-in-one JAR
-    public static final Version VERSION = Version.of(CommonVersion.class, 
"1.0.1");
+    public static final Version VERSION = Version.of(CommonVersion.class, 
"1.2.0");
 }
diff --git 
a/hugegraph-common/src/test/java/org/apache/hugegraph/unit/rest/RestClientTest.java
 
b/hugegraph-common/src/test/java/org/apache/hugegraph/unit/rest/RestClientTest.java
index eb9c7c2..f7b998d 100644
--- 
a/hugegraph-common/src/test/java/org/apache/hugegraph/unit/rest/RestClientTest.java
+++ 
b/hugegraph-common/src/test/java/org/apache/hugegraph/unit/rest/RestClientTest.java
@@ -21,249 +21,90 @@ import java.security.NoSuchAlgorithmException;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.UUID;
-import java.util.concurrent.Callable;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.function.BiFunction;
 
 import javax.net.ssl.SSLContext;
 import javax.net.ssl.SSLSession;
 import javax.net.ssl.SSLSessionContext;
 
-import jakarta.ws.rs.client.Invocation.Builder;
-import jakarta.ws.rs.client.WebTarget;
-import jakarta.ws.rs.core.MultivaluedHashMap;
-import jakarta.ws.rs.core.MultivaluedMap;
-import jakarta.ws.rs.core.Response;
-
-import org.apache.hugegraph.unit.BaseUnitTest;
-import org.junit.Test;
-import org.mockito.Mockito;
-
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-import org.glassfish.jersey.internal.util.collection.ImmutableMultivaluedMap;
-
-import org.apache.http.HttpClientConnection;
-import org.apache.http.HttpHeaders;
-import org.apache.http.HttpHost;
-import org.apache.http.conn.routing.HttpRoute;
-import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
-import org.apache.http.pool.PoolStats;
-
 import org.apache.hugegraph.rest.AbstractRestClient;
 import org.apache.hugegraph.rest.ClientException;
 import org.apache.hugegraph.rest.RestClient;
+import org.apache.hugegraph.rest.RestClientConfig;
+import org.apache.hugegraph.rest.RestHeaders;
 import org.apache.hugegraph.rest.RestResult;
 import org.apache.hugegraph.testutil.Assert;
 import org.apache.hugegraph.testutil.Whitebox;
+import org.apache.hugegraph.unit.BaseUnitTest;
+import org.junit.Test;
+import org.mockito.Mockito;
 
-public class RestClientTest {
-
-    private static class RestClientImpl extends AbstractRestClient {
-
-        private final int status;
-        private final MultivaluedMap<String, Object> headers;
-        private final String content;
-
-        public RestClientImpl(String url, int timeout, int idleTime,
-                              int maxTotal, int maxPerRoute, int status) {
-            super(url, timeout, idleTime, maxTotal, maxPerRoute);
-            this.status = status;
-            this.headers = ImmutableMultivaluedMap.empty();
-            this.content = "";
-        }
-
-        public RestClientImpl(String url, int timeout,
-                              int maxTotal, int maxPerRoute, int status) {
-            super(url, timeout, maxTotal, maxPerRoute);
-            this.status = status;
-            this.headers = ImmutableMultivaluedMap.empty();
-            this.content = "";
-        }
-
-        public RestClientImpl(String url, String user, String password,
-                              int timeout, int status) {
-            super(url, user, password, timeout);
-            this.status = status;
-            this.headers = ImmutableMultivaluedMap.empty();
-            this.content = "";
-        }
-
-        public RestClientImpl(String url, String user, String password,
-                              int timeout, int maxTotal, int maxPerRoute,
-                              int status) {
-            super(url, user, password, timeout, maxTotal, maxPerRoute);
-            this.status = status;
-            this.headers = ImmutableMultivaluedMap.empty();
-            this.content = "";
-        }
-
-        public RestClientImpl(String url, String user, String password,
-                              int timeout, int maxTotal, int maxPerRoute,
-                              String trustStoreFile, String trustStorePassword,
-                              int status) {
-            super(url, user, password, timeout, maxTotal, maxPerRoute,
-                  trustStoreFile, trustStorePassword);
-            this.status = status;
-            this.headers = ImmutableMultivaluedMap.empty();
-            this.content = "";
-        }
-
-        public RestClientImpl(String url, String token,
-                              int timeout, int status) {
-            super(url, token, timeout);
-            this.status = status;
-            this.headers = ImmutableMultivaluedMap.empty();
-            this.content = "";
-        }
-
-        public RestClientImpl(String url, String token, int timeout,
-                              int maxTotal, int maxPerRoute, int status) {
-            super(url, token, timeout, maxTotal, maxPerRoute);
-            this.status = status;
-            this.headers = ImmutableMultivaluedMap.empty();
-            this.content = "";
-        }
-
-        public RestClientImpl(String url, String token, int timeout,
-                              int maxTotal, int maxPerRoute,
-                              String trustStoreFile,
-                              String trustStorePassword, int status) {
-            super(url, token, timeout, maxTotal, maxPerRoute,
-                  trustStoreFile, trustStorePassword);
-            this.status = status;
-            this.headers = ImmutableMultivaluedMap.empty();
-            this.content = "";
-        }
-
-        public RestClientImpl(String url, int timeout, int status) {
-            this(url, timeout, status, ImmutableMultivaluedMap.empty(), "");
-        }
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.net.HttpHeaders;
 
-        public RestClientImpl(String url, int timeout, int status,
-                              MultivaluedMap<String, Object> headers,
-                              String content) {
-            super(url, timeout);
-            this.status = status;
-            this.headers = headers;
-            this.content = content;
-        }
+import lombok.SneakyThrows;
+import okhttp3.HttpUrl;
+import okhttp3.OkHttpClient;
+import okhttp3.Request;
+import okhttp3.Response;
 
-        @Override
-        protected Response request(Callable<Response> method) {
-            Response response = Mockito.mock(Response.class);
-            Mockito.when(response.getStatus()).thenReturn(this.status);
-            Mockito.when(response.getHeaders()).thenReturn(this.headers);
-            Mockito.when(response.readEntity(String.class))
-                   .thenReturn(this.content);
-            return response;
-        }
+public class RestClientTest {
 
-        @Override
-        protected void checkStatus(Response response,
-                                   Response.Status... statuses) {
-            boolean match = false;
-            for (Response.Status status : statuses) {
-                if (status.getStatusCode() == response.getStatus()) {
-                    match = true;
-                    break;
-                }
-            }
-            if (!match) {
-                throw new ClientException("Invalid response '%s'", response);
-            }
-        }
-    }
+    private static final String TEST_URL = "http://localhost:8080";;
 
     @Test
     public void testPost() {
-        RestClient client = new RestClientImpl("/test", 1000, 200);
+        RestClientConfig restClientConfig = 
RestClientConfig.builder().timeout(1000).build();
+        RestClient client = new RestClientImpl(TEST_URL, restClientConfig, 
200);
         RestResult restResult = client.post("path", "body");
         Assert.assertEquals(200, restResult.status());
     }
 
     @Test
     // TODO: How to verify it?
-    public void testPostWithMaxTotalAndPerRoute() {
-        RestClient client = new RestClientImpl("/test", 1000, 10, 5, 200);
+    public void testPostWithMaxConnsAndPerRoute() {
+        RestClientConfig restClientConfig =
+                
RestClientConfig.builder().timeout(1000).maxConns(10).maxConnsPerRoute(5).build();
+        RestClient client = new RestClientImpl(TEST_URL, restClientConfig, 
200);
         RestResult restResult = client.post("path", "body");
         Assert.assertEquals(200, restResult.status());
     }
 
-    @Test
-    public void testCleanExecutor() throws Exception {
-        // Modify IDLE_TIME 100ms to speed test
-        int newIdleTime = 100;
-        int newCheckPeriod = newIdleTime + 20;
-
-        RestClient client = new RestClientImpl("/test", 1000, newIdleTime,
-                                               10, 5, 200);
-
-        PoolingHttpClientConnectionManager pool;
-        pool = Whitebox.getInternalState(client, "pool");
-        pool = Mockito.spy(pool);
-        Whitebox.setInternalState(client, "pool", pool);
-        HttpRoute route = new HttpRoute(HttpHost.create(
-                                        "http://127.0.0.1:8080";));
-        // Create a connection manually, it will be put into leased list
-        HttpClientConnection conn = pool.requestConnection(route, null)
-                                        .get(1L, TimeUnit.SECONDS);
-        PoolStats stats = pool.getTotalStats();
-        int usingConns = stats.getLeased() + stats.getPending();
-        Assert.assertGte(1, usingConns);
-
-        // Sleep more than two check periods for busy connection
-        Thread.sleep(newCheckPeriod);
-        Mockito.verify(pool, Mockito.never()).closeExpiredConnections();
-        stats = pool.getTotalStats();
-        usingConns = stats.getLeased() + stats.getPending();
-        Assert.assertGte(1, usingConns);
-
-        // The connection will be put into available list
-        pool.releaseConnection(conn, null, 0, TimeUnit.SECONDS);
-
-        stats = pool.getTotalStats();
-        usingConns = stats.getLeased() + stats.getPending();
-        Assert.assertEquals(0, usingConns);
-        /*
-         * Sleep more than two check periods for free connection,
-         * ensure connection has been closed
-         */
-        Thread.sleep(newCheckPeriod);
-        Mockito.verify(pool, Mockito.atLeastOnce())
-               .closeExpiredConnections();
-        Mockito.verify(pool, Mockito.atLeastOnce())
-               .closeIdleConnections(newIdleTime, TimeUnit.MILLISECONDS);
-    }
-
     @Test
     public void testPostWithUserAndPassword() {
-        RestClient client = new RestClientImpl("/test", "user", "", 1000, 200);
+        RestClientConfig restClientConfig =
+                
RestClientConfig.builder().user("user").password("").timeout(1000).build();
+        RestClient client = new RestClientImpl(TEST_URL, restClientConfig, 
200);
         RestResult restResult = client.post("path", "body");
         Assert.assertEquals(200, restResult.status());
     }
 
     @Test
     public void testPostWithToken() {
-        RestClient client = new RestClientImpl("/test", "token", 1000, 200);
+        RestClientConfig restClientConfig =
+                
RestClientConfig.builder().token("token").timeout(1000).build();
+        RestClient client = new RestClientImpl(TEST_URL, restClientConfig, 
200);
         RestResult restResult = client.post("path", "body");
         Assert.assertEquals(200, restResult.status());
     }
 
     @Test
     public void testPostWithAllParams() {
-        RestClient client = new RestClientImpl("/test", "user", "", 1000,
-                                               10, 5, 200);
+        RestClientConfig restClientConfig =
+                
RestClientConfig.builder().user("user").password("").timeout(1000).maxConns(10)
+                                .maxConnsPerRoute(5).build();
+        RestClient client = new RestClientImpl(TEST_URL, restClientConfig, 
200);
         RestResult restResult = client.post("path", "body");
         Assert.assertEquals(200, restResult.status());
     }
 
     @Test
     public void testPostWithTokenAndAllParams() {
-        RestClient client = new RestClientImpl("/test", "token", 1000,
-                                               10, 5, 200);
+        RestClientConfig restClientConfig =
+                
RestClientConfig.builder().token("token").timeout(1000).maxConns(10)
+                                .maxConnsPerRoute(5).build();
+        RestClient client = new RestClientImpl(TEST_URL, restClientConfig, 
200);
         RestResult restResult = client.post("path", "body");
         Assert.assertEquals(200, restResult.status());
     }
@@ -276,9 +117,11 @@ public class RestClientTest {
         BaseUnitTest.downloadFileByUrl(url, trustStoreFile);
 
         String trustStorePassword = "changeit";
-        RestClient client = new RestClientImpl("/test", "user", "", 1000,
-                                               10, 5, trustStoreFile,
-                                               trustStorePassword, 200);
+        RestClientConfig restClientConfig =
+                
RestClientConfig.builder().user("user").password("").timeout(1000).maxConns(10)
+                                
.maxConnsPerRoute(5).trustStoreFile(trustStoreFile)
+                                
.trustStorePassword(trustStorePassword).build();
+        RestClient client = new RestClientImpl(TEST_URL, restClientConfig, 
200);
         RestResult restResult = client.post("path", "body");
         Assert.assertEquals(200, restResult.status());
     }
@@ -291,9 +134,11 @@ public class RestClientTest {
         BaseUnitTest.downloadFileByUrl(url, trustStoreFile);
 
         String trustStorePassword = "changeit";
-        RestClient client = new RestClientImpl("/test", "token", 1000,
-                                               10, 5, trustStoreFile,
-                                               trustStorePassword, 200);
+        RestClientConfig restClientConfig =
+                
RestClientConfig.builder().token("token").timeout(1000).maxConns(10)
+                                
.maxConnsPerRoute(5).trustStoreFile(trustStoreFile)
+                                
.trustStorePassword(trustStorePassword).build();
+        RestClient client = new RestClientImpl(TEST_URL, restClientConfig, 
200);
         RestResult restResult = client.post("path", "body");
         Assert.assertEquals(200, restResult.status());
     }
@@ -327,13 +172,12 @@ public class RestClientTest {
 
     @Test
     public void testPostWithHeaderAndContent() {
-        MultivaluedMap<String, Object> headers = new MultivaluedHashMap<>();
-        headers.add("key1", "value1-1");
-        headers.add("key1", "value1-2");
-        headers.add("Content-Encoding", "gzip");
+        RestHeaders headers = new RestHeaders().add("key1", "value1-1")
+                                               .add("key1", "value1-2")
+                                               .add("Content-Encoding", 
"gzip");
         String content = "{\"names\": [\"marko\", \"josh\", \"lop\"]}";
-        RestClient client = new RestClientImpl("/test", 1000, 200,
-                                               headers, content);
+        RestClientConfig restClientConfig = 
RestClientConfig.builder().timeout(1000).build();
+        RestClient client = new RestClientImpl(TEST_URL, restClientConfig, 
200, headers, content);
         RestResult restResult = client.post("path", "body");
         Assert.assertEquals(200, restResult.status());
         Assert.assertEquals(headers, restResult.headers());
@@ -344,7 +188,8 @@ public class RestClientTest {
 
     @Test
     public void testPostWithException() {
-        RestClient client = new RestClientImpl("/test", 1000, 400);
+        RestClientConfig restClientConfig = 
RestClientConfig.builder().timeout(1000).build();
+        RestClient client = new RestClientImpl(TEST_URL, restClientConfig, 
400);
         Assert.assertThrows(ClientException.class, () -> {
             client.post("path", "body");
         });
@@ -352,8 +197,10 @@ public class RestClientTest {
 
     @Test
     public void testPostWithParams() {
-        RestClient client = new RestClientImpl("/test", 1000, 200);
-        MultivaluedMap<String, Object> headers = 
ImmutableMultivaluedMap.empty();
+        RestClientConfig restClientConfig = 
RestClientConfig.builder().timeout(1000).build();
+        RestClient client = new RestClientImpl(TEST_URL, restClientConfig, 
200);
+        RestHeaders headers = new RestHeaders();
+
         Map<String, Object> params = ImmutableMap.of("param1", "value1");
         RestResult restResult = client.post("path", "body", headers,
                                             params);
@@ -362,25 +209,27 @@ public class RestClientTest {
 
     @Test
     public void testPut() {
-        RestClient client = new RestClientImpl("/test", 1000, 200);
+        RestClientConfig restClientConfig = 
RestClientConfig.builder().timeout(1000).build();
+        RestClient client = new RestClientImpl(TEST_URL, restClientConfig, 
200);
         RestResult restResult = client.put("path", "id1", "body");
         Assert.assertEquals(200, restResult.status());
     }
 
     @Test
     public void testPutWithHeaders() {
-        RestClient client = new RestClientImpl("/test", 1000, 200);
-        MultivaluedMap<String, Object> headers = new MultivaluedHashMap<>();
-        headers.add("key1", "value1-1");
-        headers.add("key1", "value1-2");
-        headers.add("Content-Encoding", "gzip");
+        RestClientConfig restClientConfig = 
RestClientConfig.builder().timeout(1000).build();
+        RestClient client = new RestClientImpl(TEST_URL, restClientConfig, 
200);
+        RestHeaders headers = new RestHeaders().add("key1", "value1-1")
+                                               .add("key2", "value1-2")
+                                               .add("Content-Encoding", 
"gzip");
         RestResult restResult = client.put("path", "id1", "body", headers);
         Assert.assertEquals(200, restResult.status());
     }
 
     @Test
     public void testPutWithParams() {
-        RestClient client = new RestClientImpl("/test", 1000, 200);
+        RestClientConfig restClientConfig = 
RestClientConfig.builder().timeout(1000).build();
+        RestClient client = new RestClientImpl(TEST_URL, restClientConfig, 
200);
         Map<String, Object> params = ImmutableMap.of("param1", "value1");
         RestResult restResult = client.put("path", "id1", "body", params);
         Assert.assertEquals(200, restResult.status());
@@ -388,7 +237,8 @@ public class RestClientTest {
 
     @Test
     public void testPutWithException() {
-        RestClient client = new RestClientImpl("/test", 1000, 400);
+        RestClientConfig restClientConfig = 
RestClientConfig.builder().timeout(1000).build();
+        RestClient client = new RestClientImpl(TEST_URL, restClientConfig, 
400);
         Assert.assertThrows(ClientException.class, () -> {
             client.put("path", "id1", "body");
         });
@@ -396,21 +246,24 @@ public class RestClientTest {
 
     @Test
     public void testGet() {
-        RestClient client = new RestClientImpl("/test", 1000, 200);
+        RestClientConfig restClientConfig = 
RestClientConfig.builder().timeout(1000).build();
+        RestClient client = new RestClientImpl(TEST_URL, restClientConfig, 
200);
         RestResult restResult = client.get("path");
         Assert.assertEquals(200, restResult.status());
     }
 
     @Test
     public void testGetWithId() {
-        RestClient client = new RestClientImpl("/test", 1000, 200);
+        RestClientConfig restClientConfig = 
RestClientConfig.builder().timeout(1000).build();
+        RestClient client = new RestClientImpl(TEST_URL, restClientConfig, 
200);
         RestResult restResult = client.get("path", "id1");
         Assert.assertEquals(200, restResult.status());
     }
 
     @Test
     public void testGetWithParams() {
-        RestClient client = new RestClientImpl("/test", 1000, 200);
+        RestClientConfig restClientConfig = 
RestClientConfig.builder().timeout(1000).build();
+        RestClient client = new RestClientImpl(TEST_URL, restClientConfig, 
200);
         Map<String, Object> params = new HashMap<>();
         params.put("key1", ImmutableList.of("value1-1", "value1-2"));
         params.put("key2", "value2");
@@ -420,7 +273,8 @@ public class RestClientTest {
 
     @Test
     public void testGetWithException() {
-        RestClient client = new RestClientImpl("/test", 1000, 400);
+        RestClientConfig restClientConfig = 
RestClientConfig.builder().timeout(1000).build();
+        RestClient client = new RestClientImpl(TEST_URL, restClientConfig, 
400);
         Assert.assertThrows(ClientException.class, () -> {
             client.get("path", "id1");
         });
@@ -428,14 +282,16 @@ public class RestClientTest {
 
     @Test
     public void testDeleteWithId() {
-        RestClient client = new RestClientImpl("/test", 1000, 204);
+        RestClientConfig restClientConfig = 
RestClientConfig.builder().timeout(1000).build();
+        RestClient client = new RestClientImpl(TEST_URL, restClientConfig, 
204);
         RestResult restResult = client.delete("path", "id1");
         Assert.assertEquals(204, restResult.status());
     }
 
     @Test
     public void testDeleteWithParams() {
-        RestClient client = new RestClientImpl("/test", 1000, 204);
+        RestClientConfig restClientConfig = 
RestClientConfig.builder().timeout(1000).build();
+        RestClient client = new RestClientImpl(TEST_URL, restClientConfig, 
204);
         Map<String, Object> params = ImmutableMap.of("param1", "value1");
         RestResult restResult = client.delete("path", params);
         Assert.assertEquals(204, restResult.status());
@@ -443,38 +299,17 @@ public class RestClientTest {
 
     @Test
     public void testDeleteWithException() {
-        RestClient client = new RestClientImpl("/test", 1000, 400);
+        RestClientConfig restClientConfig = 
RestClientConfig.builder().timeout(1000).build();
+        RestClient client = new RestClientImpl(TEST_URL, restClientConfig, 
400);
         Assert.assertThrows(ClientException.class, () -> {
             client.delete("path", "id1");
         });
     }
 
-    @Test
-    public void testClose() {
-        RestClient client = new RestClientImpl("/test", 1000, 10, 5, 200);
-        RestResult restResult = client.post("path", "body");
-        Assert.assertEquals(200, restResult.status());
-
-        client.close();
-        Assert.assertThrows(IllegalStateException.class, () -> {
-            client.post("path", "body");
-        });
-
-        PoolingHttpClientConnectionManager pool;
-        pool = Whitebox.getInternalState(client, "pool");
-        Assert.assertNotNull(pool);
-        AtomicBoolean isShutDown = Whitebox.getInternalState(pool, 
"isShutDown");
-        Assert.assertTrue(isShutDown.get());
-
-        ScheduledExecutorService cleanExecutor;
-        cleanExecutor = Whitebox.getInternalState(client, "cleanExecutor");
-        Assert.assertNotNull(cleanExecutor);
-        Assert.assertTrue(cleanExecutor.isShutdown());
-    }
-
     @Test
     public void testAuthContext() {
-        RestClientImpl client = new RestClientImpl("/test", 1000, 10, 5, 200);
+        RestClientConfig restClientConfig = 
RestClientConfig.builder().timeout(1000).build();
+        RestClientImpl client = new RestClientImpl(TEST_URL, restClientConfig, 
200);
         Assert.assertNull(client.getAuthContext());
 
         String token = UUID.randomUUID().toString();
@@ -485,48 +320,33 @@ public class RestClientTest {
         Assert.assertNull(client.getAuthContext());
     }
 
-    private static class MockRestClientImpl extends AbstractRestClient {
-
-        public MockRestClientImpl(String url, int timeout) {
-            super(url, timeout);
-        }
-
-        @Override
-        protected void checkStatus(Response response,
-                                   Response.Status... statuses) {
-            // pass
-        }
-    }
-
+    @SneakyThrows
     @Test
     public void testRequest() {
-        MockRestClientImpl client = new MockRestClientImpl("test", 1000);
-
-        WebTarget target = Mockito.mock(WebTarget.class);
-        Builder builder = Mockito.mock(Builder.class);
-
-        Mockito.when(target.path("test")).thenReturn(target);
-        Mockito.when(target.path("test")
-                           .path(AbstractRestClient.encode("id")))
-               .thenReturn(target);
-        Mockito.when(target.path("test").request()).thenReturn(builder);
-        Mockito.when(target.path("test")
-                           .path(AbstractRestClient.encode("id"))
-                           .request())
-               .thenReturn(builder);
-
-        Response response = Mockito.mock(Response.class);
-        Mockito.when(response.getStatus()).thenReturn(200);
-        Mockito.when(response.getHeaders())
-               .thenReturn(new MultivaluedHashMap<>());
-        Mockito.when(response.readEntity(String.class)).thenReturn("content");
-
-        Mockito.when(builder.delete()).thenReturn(response);
-        Mockito.when(builder.get()).thenReturn(response);
-        Mockito.when(builder.put(Mockito.any())).thenReturn(response);
-        Mockito.when(builder.post(Mockito.any())).thenReturn(response);
-
-        Whitebox.setInternalState(client, "target", target);
+        Response response = Mockito.mock(Response.class, 
Mockito.RETURNS_DEEP_STUBS);
+        Mockito.when(response.code()).thenReturn(200);
+        Mockito.when(response.headers())
+               .thenReturn(new RestHeaders().toOkHttpHeader());
+        Mockito.when(response.body().string()).thenReturn("content");
+
+        Request.Builder requestBuilder = Mockito.mock(Request.Builder.class,
+                                                      
Mockito.RETURNS_DEEP_STUBS);
+        Mockito.when(requestBuilder.delete()).thenReturn(requestBuilder);
+        Mockito.when(requestBuilder.get()).thenReturn(requestBuilder);
+        
Mockito.when(requestBuilder.put(Mockito.any())).thenReturn(requestBuilder);
+        
Mockito.when(requestBuilder.post(Mockito.any())).thenReturn(requestBuilder);
+        Mockito.when(requestBuilder.url((HttpUrl) 
Mockito.any())).thenReturn(requestBuilder);
+        MockRestClientImpl client = new MockRestClientImpl(TEST_URL, 1000) {
+            @Override
+            protected Request.Builder newRequestBuilder() {
+                return requestBuilder;
+            }
+        };
+
+        OkHttpClient okHttpClient = Mockito.mock(OkHttpClient.class, 
Mockito.RETURNS_DEEP_STUBS);
+        
Mockito.when(okHttpClient.newCall(Mockito.any()).execute()).thenReturn(response);
+
+        Whitebox.setInternalState(client, "client", okHttpClient);
 
         RestResult result;
 
@@ -534,97 +354,140 @@ public class RestClientTest {
         client.setAuthContext("token1");
         result = client.delete("test", ImmutableMap.of());
         Assert.assertEquals(200, result.status());
-        Mockito.verify(builder).header(HttpHeaders.AUTHORIZATION,
-                                       "token1");
+        Mockito.verify(requestBuilder).addHeader(RestHeaders.AUTHORIZATION, 
"token1");
+
         client.resetAuthContext();
 
         client.setAuthContext("token2");
         result = client.delete("test", "id");
         Assert.assertEquals(200, result.status());
-        Mockito.verify(builder).header(HttpHeaders.AUTHORIZATION,
-                                       "token2");
+        Mockito.verify(requestBuilder).addHeader(HttpHeaders.AUTHORIZATION, 
"token2");
         client.resetAuthContext();
 
         // Test get
         client.setAuthContext("token3");
         result = client.get("test");
         Assert.assertEquals(200, result.status());
-        Mockito.verify(builder).header(HttpHeaders.AUTHORIZATION,
-                                       "token3");
+        Mockito.verify(requestBuilder).addHeader(HttpHeaders.AUTHORIZATION, 
"token3");
         client.resetAuthContext();
 
         client.setAuthContext("token4");
         result = client.get("test", ImmutableMap.of());
         Assert.assertEquals(200, result.status());
-        Mockito.verify(builder).header(HttpHeaders.AUTHORIZATION,
-                                       "token4");
+        Mockito.verify(requestBuilder).addHeader(HttpHeaders.AUTHORIZATION, 
"token4");
         client.resetAuthContext();
 
         client.setAuthContext("token5");
         result = client.get("test", "id");
         Assert.assertEquals(200, result.status());
-        Mockito.verify(builder).header(HttpHeaders.AUTHORIZATION,
-                                       "token5");
+        Mockito.verify(requestBuilder).addHeader(HttpHeaders.AUTHORIZATION, 
"token5");
         client.resetAuthContext();
 
         // Test put
         client.setAuthContext("token6");
-        result = client.post("test", new Object());
+        result = client.post("test", null);
         Assert.assertEquals(200, result.status());
-        Mockito.verify(builder).header(HttpHeaders.AUTHORIZATION,
-                                       "token6");
+        Mockito.verify(requestBuilder).addHeader(HttpHeaders.AUTHORIZATION, 
"token6");
         client.resetAuthContext();
 
         client.setAuthContext("token7");
-        result = client.post("test", new Object(), new MultivaluedHashMap<>());
+        result = client.post("test", null, new RestHeaders());
         Assert.assertEquals(200, result.status());
-        Mockito.verify(builder).header(HttpHeaders.AUTHORIZATION,
-                                       "token7");
+        Mockito.verify(requestBuilder).addHeader(HttpHeaders.AUTHORIZATION, 
"token7");
         client.resetAuthContext();
 
         client.setAuthContext("token8");
-        result = client.post("test", new Object(), ImmutableMap.of());
+        result = client.post("test", null, ImmutableMap.of());
         Assert.assertEquals(200, result.status());
-        Mockito.verify(builder).header(HttpHeaders.AUTHORIZATION,
-                                       "token8");
+        Mockito.verify(requestBuilder).addHeader(HttpHeaders.AUTHORIZATION, 
"token8");
         client.resetAuthContext();
 
         client.setAuthContext("token9");
-        result = client.post("test", new Object(), new MultivaluedHashMap<>(),
+        result = client.post("test", null, new RestHeaders(),
                              ImmutableMap.of());
         Assert.assertEquals(200, result.status());
-        Mockito.verify(builder).header(HttpHeaders.AUTHORIZATION,
-                                       "token9");
+        Mockito.verify(requestBuilder).addHeader(HttpHeaders.AUTHORIZATION, 
"token9");
         client.resetAuthContext();
 
         // Test post
         client.setAuthContext("token10");
-        result = client.post("test", new Object());
+        result = client.post("test", null);
         Assert.assertEquals(200, result.status());
-        Mockito.verify(builder).header(HttpHeaders.AUTHORIZATION,
-                                       "token10");
+        Mockito.verify(requestBuilder).addHeader(HttpHeaders.AUTHORIZATION, 
"token10");
         client.resetAuthContext();
 
         client.setAuthContext("token11");
-        result = client.post("test", new Object(), new MultivaluedHashMap<>());
+        result = client.post("test", null, new RestHeaders());
         Assert.assertEquals(200, result.status());
-        Mockito.verify(builder).header(HttpHeaders.AUTHORIZATION,
-                                       "token11");
+        Mockito.verify(requestBuilder).addHeader(HttpHeaders.AUTHORIZATION, 
"token11");
         client.resetAuthContext();
 
         client.setAuthContext("token12");
-        result = client.post("test", new Object(), ImmutableMap.of());
+        result = client.post("test", null, ImmutableMap.of());
         Assert.assertEquals(200, result.status());
-        Mockito.verify(builder).header(HttpHeaders.AUTHORIZATION,
-                                       "token12");
+        Mockito.verify(requestBuilder).addHeader(HttpHeaders.AUTHORIZATION, 
"token12");
         client.resetAuthContext();
 
         client.setAuthContext("token13");
-        result = client.post("test", new Object(), new MultivaluedHashMap<>(),
+        result = client.post("test", null, new RestHeaders(),
                              ImmutableMap.of());
         Assert.assertEquals(200, result.status());
-        Mockito.verify(builder).header(HttpHeaders.AUTHORIZATION,
-                                       "token13");
+        Mockito.verify(requestBuilder).addHeader(HttpHeaders.AUTHORIZATION, 
"token13");
         client.resetAuthContext();
     }
+
+    private static class RestClientImpl extends AbstractRestClient {
+
+        private final int status;
+        private final RestHeaders headers;
+        private final String content;
+
+        public RestClientImpl(String url, RestClientConfig config, int status) 
{
+            this(url, config, status, new RestHeaders(), "");
+        }
+
+        public RestClientImpl(String url, RestClientConfig config, int status, 
RestHeaders headers,
+                              String content) {
+            super(url, config);
+            this.status = status;
+            this.headers = headers;
+            this.content = content;
+        }
+
+        @SneakyThrows
+        @Override
+        protected Response request(Request.Builder requestBuilder) {
+            Response response = Mockito.mock(Response.class, 
Mockito.RETURNS_DEEP_STUBS);
+            Mockito.when(response.code()).thenReturn(this.status);
+            
Mockito.when(response.headers()).thenReturn(this.headers.toOkHttpHeader());
+            Mockito.when(response.body().string()).thenReturn(this.content);
+            return response;
+        }
+
+        @Override
+        protected void checkStatus(Response response, int... statuses) {
+            boolean match = false;
+            for (int status : statuses) {
+                if (status == response.code()) {
+                    match = true;
+                    break;
+                }
+            }
+            if (!match) {
+                throw new ClientException("Invalid response '%s'", response);
+            }
+        }
+    }
+
+    private static class MockRestClientImpl extends AbstractRestClient {
+
+        public MockRestClientImpl(String url, int timeout) {
+            super(url, timeout);
+        }
+
+        @Override
+        protected void checkStatus(Response response, int... statuses) {
+            // pass
+        }
+    }
 }
diff --git 
a/hugegraph-common/src/test/java/org/apache/hugegraph/unit/rest/RestResultTest.java
 
b/hugegraph-common/src/test/java/org/apache/hugegraph/unit/rest/RestResultTest.java
index 2ae9a4e..06eb03a 100644
--- 
a/hugegraph-common/src/test/java/org/apache/hugegraph/unit/rest/RestResultTest.java
+++ 
b/hugegraph-common/src/test/java/org/apache/hugegraph/unit/rest/RestResultTest.java
@@ -19,22 +19,44 @@ package org.apache.hugegraph.unit.rest;
 
 import java.util.Map;
 
-import jakarta.ws.rs.core.MultivaluedHashMap;
-import jakarta.ws.rs.core.MultivaluedMap;
-import jakarta.ws.rs.core.Response;
-import org.glassfish.jersey.internal.util.collection.ImmutableMultivaluedMap;
+import org.apache.hugegraph.rest.RestHeaders;
+import org.apache.hugegraph.rest.RestResult;
+import org.apache.hugegraph.rest.SerializeException;
+import org.apache.hugegraph.testutil.Assert;
 import org.junit.Test;
 import org.mockito.Mockito;
 
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 
-import org.apache.hugegraph.rest.RestResult;
-import org.apache.hugegraph.rest.SerializeException;
-import org.apache.hugegraph.testutil.Assert;
+import lombok.SneakyThrows;
+import okhttp3.Response;
 
 public class RestResultTest {
 
+    private static RestResult newRestResult(int status) {
+        return newRestResult(status, "", new RestHeaders());
+    }
+
+    private static RestResult newRestResult(int status, String content) {
+        return newRestResult(status, content, new RestHeaders());
+    }
+
+    private static RestResult newRestResult(int status, RestHeaders headers) {
+        return newRestResult(status, "", headers);
+    }
+
+    @SneakyThrows
+    private static RestResult newRestResult(int status, String content,
+                                            RestHeaders headers) {
+        Response response = Mockito.mock(Response.class, 
Mockito.RETURNS_DEEP_STUBS);
+        Mockito.when(response.code()).thenReturn(status);
+        Mockito.when(response.headers()).thenReturn(headers.toOkHttpHeader());
+        Mockito.when(response.body().string())
+               .thenReturn(content);
+        return new RestResult(response);
+    }
+
     @Test
     public void testStatus() {
         RestResult result = newRestResult(200);
@@ -43,7 +65,7 @@ public class RestResultTest {
 
     @Test
     public void testHeaders() {
-        MultivaluedMap<String, Object> headers = new MultivaluedHashMap<>();
+        RestHeaders headers = new RestHeaders();
         headers.add("key1", "value1-1");
         headers.add("key1", "value1-2");
         headers.add("key2", "value2");
@@ -116,27 +138,4 @@ public class RestResultTest {
             result3.readList(String.class);
         });
     }
-
-    private static RestResult newRestResult(int status) {
-        return newRestResult(status, "", ImmutableMultivaluedMap.empty());
-    }
-
-    private static RestResult newRestResult(int status, String content) {
-        return newRestResult(status, content, ImmutableMultivaluedMap.empty());
-    }
-
-    private static RestResult newRestResult(int status,
-                                            MultivaluedMap<String, Object> h) {
-        return newRestResult(status, "", h);
-    }
-
-    private static RestResult newRestResult(int status, String content,
-                                            MultivaluedMap<String, Object> h) {
-        Response response = Mockito.mock(Response.class);
-        Mockito.when(response.getStatus()).thenReturn(status);
-        Mockito.when(response.getHeaders()).thenReturn(h);
-        Mockito.when(response.readEntity(String.class))
-               .thenReturn(content);
-        return new RestResult(response);
-    }
 }
diff --git 
a/hugegraph-common/src/test/java/org/apache/hugegraph/unit/util/ReflectionUtilTest.java
 
b/hugegraph-common/src/test/java/org/apache/hugegraph/unit/util/ReflectionUtilTest.java
index 510d145..c83b2ad 100644
--- 
a/hugegraph-common/src/test/java/org/apache/hugegraph/unit/util/ReflectionUtilTest.java
+++ 
b/hugegraph-common/src/test/java/org/apache/hugegraph/unit/util/ReflectionUtilTest.java
@@ -94,7 +94,7 @@ public class ReflectionUtilTest extends BaseUnitTest {
         @SuppressWarnings("unchecked")
         List<ClassInfo> classes = IteratorUtils.toList(ReflectionUtil.classes(
                                   "org.apache.hugegraph.util"));
-        Assert.assertEquals(17, classes.size());
+        Assert.assertEquals(18, classes.size());
         classes.sort(Comparator.comparing(ClassInfo::getName));
         Assert.assertEquals("org.apache.hugegraph.util.Bytes",
                             classes.get(0).getName());
@@ -103,7 +103,7 @@ public class ReflectionUtilTest extends BaseUnitTest {
         Assert.assertEquals("org.apache.hugegraph.util.CollectionUtil",
                             classes.get(2).getName());
         Assert.assertEquals("org.apache.hugegraph.util.VersionUtil",
-                            classes.get(16).getName());
+                            classes.get(17).getName());
     }
 
     @Test
diff --git 
a/hugegraph-common/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker
 
b/hugegraph-common/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker
new file mode 100644
index 0000000..a76010b
--- /dev/null
+++ 
b/hugegraph-common/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker
@@ -0,0 +1,17 @@
+#
+# 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.
+#
+mock-maker-inline
diff --git a/hugegraph-dist/scripts/dependency/known-dependencies.txt 
b/hugegraph-dist/scripts/dependency/known-dependencies.txt
index c6de269..53b4567 100644
--- a/hugegraph-dist/scripts/dependency/known-dependencies.txt
+++ b/hugegraph-dist/scripts/dependency/known-dependencies.txt
@@ -1,6 +1,6 @@
 animal-sniffer-annotations-1.18.jar
 annotations-4.1.1.4.jar
-aopalliance-repackaged-3.0.1.jar
+annotations-13.0.jar
 bolt-1.6.2.jar
 checker-qual-3.5.0.jar
 commons-beanutils-1.9.4.jar
@@ -27,11 +27,6 @@ gson-2.8.6.jar
 guava-30.0-jre.jar
 hamcrest-core-1.3.jar
 hessian-3.3.7.jar
-hk2-api-3.0.1.jar
-hk2-locator-3.0.1.jar
-hk2-utils-3.0.1.jar
-httpclient-4.5.13.jar
-httpcore-4.4.13.jar
 j2objc-annotations-1.3.jar
 jackson-annotations-2.14.0-rc1.jar
 jackson-core-2.14.0-rc1.jar
@@ -42,22 +37,10 @@ jackson-jaxrs-json-provider-2.14.0-rc1.jar
 jackson-module-jaxb-annotations-2.14.0-rc1.jar
 jakarta.activation-2.0.1.jar
 jakarta.activation-api-1.2.2.jar
-jakarta.annotation-api-2.0.0.jar
-jakarta.inject-api-2.0.0.jar
-jakarta.ws.rs-api-3.0.0.jar
-jakarta.xml.bind-api-4.0.0-RC2.jar
 javassist-3.28.0-GA.jar
-javax.activation-api-1.2.0.jar
 javax.json-1.0.jar
-jaxb-api-2.3.1.jar
 jaxb-core-3.0.2.jar
 jaxb-impl-3.0.2.jar
-jersey-apache-connector-3.0.3.jar
-jersey-client-3.0.3.jar
-jersey-common-3.0.3.jar
-jersey-entity-filtering-3.0.3.jar
-jersey-hk2-3.0.3.jar
-jersey-media-json-jackson-3.0.3.jar
 joda-time-2.10.8.jar
 jsr305-3.0.1.jar
 junit-4.13.1.jar
@@ -71,7 +54,6 @@ opentracing-api-0.22.0.jar
 opentracing-mock-0.22.0.jar
 opentracing-noop-0.22.0.jar
 opentracing-util-0.22.0.jar
-osgi-resource-locator-1.0.3.jar
 perfmark-api-0.19.0.jar
 proto-google-common-protos-1.17.0.jar
 protobuf-java-3.11.0.jar
@@ -84,3 +66,12 @@ swagger-core-1.5.18.jar
 swagger-models-1.5.18.jar
 tracer-core-3.0.8.jar
 validation-api-1.1.0.Final.jar
+kotlin-stdlib-1.6.20.jar
+kotlin-stdlib-common-1.5.31.jar
+kotlin-stdlib-jdk7-1.6.10.jar
+kotlin-stdlib-jdk8-1.6.10.jar
+logging-interceptor-4.10.0.jar
+lombok-1.18.8.jar
+okhttp-4.10.0.jar
+okio-jvm-3.0.0.jar
+
diff --git 
a/hugegraph-rpc/src/main/java/org/apache/hugegraph/version/RpcVersion.java 
b/hugegraph-rpc/src/main/java/org/apache/hugegraph/version/RpcVersion.java
index f3cf926..c7ab405 100644
--- a/hugegraph-rpc/src/main/java/org/apache/hugegraph/version/RpcVersion.java
+++ b/hugegraph-rpc/src/main/java/org/apache/hugegraph/version/RpcVersion.java
@@ -24,5 +24,5 @@ public class RpcVersion {
     public static final String NAME = "hugegraph-rpc";
 
     // The second parameter of Version.of() is for all-in-one JAR
-    public static final Version VERSION = Version.of(RpcVersion.class, 
"1.0.1");
+    public static final Version VERSION = Version.of(RpcVersion.class, 
"1.2.0");
 }
diff --git a/pom.xml b/pom.xml
index 8f2e39b..2b8a486 100644
--- a/pom.xml
+++ b/pom.xml
@@ -90,7 +90,7 @@
 
     <properties>
         <!-- Note: We need also update the version in CommonVersion.java & 
RpcVersion.java now -->
-        <revision>1.0.1</revision>
+        <revision>1.2.0</revision>
         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
         <top.level.dir>${project.basedir}/..</top.level.dir>
         <compiler.source>1.8</compiler.source>

Reply via email to