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

liubao pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/servicecomb-java-chassis.git


The following commit(s) were added to refs/heads/master by this push:
     new f752056  [SCB-2083]provide client api for config center using blocking 
http client (#1962)
f752056 is described below

commit f7520569da0fb3400d07970e51914311451cff06
Author: bao liu <[email protected]>
AuthorDate: Thu Sep 17 09:32:40 2020 +0800

    [SCB-2083]provide client api for config center using blocking http client 
(#1962)
---
 clients/{ => config-center-client}/pom.xml         |  36 ++++---
 .../config/center/client/AddressManager.java       |  66 ++++++++++++
 .../config/center/client/ConfigCenterClient.java   | 120 +++++++++++++++++++++
 .../config/center/client/ConfigCenterManager.java  |  61 +++++++++++
 .../center/client/ConfigCenterOperation.java       |  32 ++++++
 .../center/client/ConfigurationChangedEvent.java   |  37 +++++++
 .../client/exception/OperationException.java       |  30 ++++++
 .../client/model/QueryConfigurationsRequest.java   |  75 +++++++++++++
 .../client/model/QueryConfigurationsResponse.java  |  56 ++++++++++
 .../servicecomb/http/client/common/HttpUtils.java  |   5 +
 .../http/client/task}/AbstractTask.java            |  14 +--
 .../apache/servicecomb/http/client/task/Task.java  |  22 ++++
 clients/pom.xml                                    |   1 +
 .../center/client/ServiceCenterDiscovery.java      |   2 +
 .../center/client/ServiceCenterRegistration.java   |   2 +
 15 files changed, 538 insertions(+), 21 deletions(-)

diff --git a/clients/pom.xml b/clients/config-center-client/pom.xml
similarity index 62%
copy from clients/pom.xml
copy to clients/config-center-client/pom.xml
index fc17485..f79d9ea 100644
--- a/clients/pom.xml
+++ b/clients/config-center-client/pom.xml
@@ -1,5 +1,4 @@
 <?xml version="1.0" encoding="UTF-8"?>
-
 <!--
   ~ Licensed to the Apache Software Foundation (ASF) under one or more
   ~ contributor license agreements.  See the NOTICE file distributed with
@@ -21,20 +20,33 @@
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
   xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd";>
   <parent>
+    <artifactId>clients</artifactId>
     <groupId>org.apache.servicecomb</groupId>
-    <artifactId>java-chassis-parent</artifactId>
     <version>2.1.2-SNAPSHOT</version>
-    <relativePath>../parents/default</relativePath>
   </parent>
   <modelVersion>4.0.0</modelVersion>
 
-  <artifactId>clients</artifactId>
-  <name>ServiceComb::Client</name>
-  <packaging>pom</packaging>
-  <modules>
-    <module>http-client-common</module>
-    <module>kie-client</module>
-    <module>service-center-client</module>
-  </modules>
+  <artifactId>config-center-client</artifactId>
+  <name>ServiceComb::Clients::Config Center Client</name>
+
+  <dependencies>
+    <!-- Make this client simple and portable to many frameworks.
+       Do not import other dependencies if really need. -->
+    <dependency>
+      <groupId>org.apache.servicecomb</groupId>
+      <artifactId>http-client-common</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <scope>test</scope>
+    </dependency>
 
-</project>
+    <dependency>
+      <groupId>org.mockito</groupId>
+      <artifactId>mockito-core</artifactId>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+</project>
\ No newline at end of file
diff --git 
a/clients/config-center-client/src/main/java/org/apache/servicecomb/config/center/client/AddressManager.java
 
b/clients/config-center-client/src/main/java/org/apache/servicecomb/config/center/client/AddressManager.java
new file mode 100644
index 0000000..fb4e7ef
--- /dev/null
+++ 
b/clients/config-center-client/src/main/java/org/apache/servicecomb/config/center/client/AddressManager.java
@@ -0,0 +1,66 @@
+/*
+ * 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.servicecomb.config.center.client;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.servicecomb.http.client.common.HttpUtils;
+
+public class AddressManager {
+  public static final String DEFAULT_PROJECT = "default";
+
+  private final String projectName;
+
+  private final List<String> addresses;
+
+  private int index;
+
+  public AddressManager(String projectName, List<String> addresses) {
+    this.projectName = StringUtils.isEmpty(projectName) ? DEFAULT_PROJECT : 
projectName;
+    this.addresses = new ArrayList<>(addresses.size());
+    addresses.forEach((address -> this.addresses.add(formatAddress(address))));
+    this.index = new Random().nextInt(addresses.size());
+  }
+
+  private String formatAddress(String address) {
+    try {
+      return address + "/v3/" + HttpUtils.encodeURLParam(this.projectName);
+    } catch (Exception e) {
+      throw new IllegalStateException("not possible");
+    }
+  }
+
+  public String nextAddress() {
+    synchronized (this) {
+      this.index++;
+      if (this.index >= addresses.size()) {
+        this.index = 0;
+      }
+    }
+    return address();
+  }
+
+  public String address() {
+    synchronized (this) {
+      return addresses.get(index);
+    }
+  }
+}
diff --git 
a/clients/config-center-client/src/main/java/org/apache/servicecomb/config/center/client/ConfigCenterClient.java
 
b/clients/config-center-client/src/main/java/org/apache/servicecomb/config/center/client/ConfigCenterClient.java
new file mode 100644
index 0000000..46f3dfb
--- /dev/null
+++ 
b/clients/config-center-client/src/main/java/org/apache/servicecomb/config/center/client/ConfigCenterClient.java
@@ -0,0 +1,120 @@
+/*
+ * 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.servicecomb.config.center.client;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.http.HttpStatus;
+import 
org.apache.servicecomb.config.center.client.exception.OperationException;
+import 
org.apache.servicecomb.config.center.client.model.QueryConfigurationsRequest;
+import 
org.apache.servicecomb.config.center.client.model.QueryConfigurationsResponse;
+import org.apache.servicecomb.http.client.common.HttpRequest;
+import org.apache.servicecomb.http.client.common.HttpResponse;
+import org.apache.servicecomb.http.client.common.HttpTransport;
+import org.apache.servicecomb.http.client.common.HttpUtils;
+
+import com.fasterxml.jackson.core.type.TypeReference;
+
+public class ConfigCenterClient implements ConfigCenterOperation {
+  public static final String DEFAULT_APP_SEPARATOR = "@";
+
+  public static final String DEFAULT_SERVICE_SEPARATOR = "#";
+
+  public static final String REVISION = "revision";
+
+  public static final String APPLICATION_CONFIG = "application";
+
+  private HttpTransport httpTransport;
+
+  private AddressManager addressManager;
+
+  public ConfigCenterClient(AddressManager addressManager, HttpTransport 
httpTransport) {
+    this.addressManager = addressManager;
+    this.httpTransport = httpTransport;
+  }
+
+  @Override
+  public QueryConfigurationsResponse 
queryConfigurations(QueryConfigurationsRequest request) {
+    String dimensionsInfo = buildDimensionsInfo(request);
+    QueryConfigurationsResponse queryConfigurationsResponse = new 
QueryConfigurationsResponse();
+
+    Map<String, Object> configurations = new HashMap<>();
+    try {
+      HttpRequest httpRequest = new HttpRequest(addressManager.address() + 
"/configuration/items?dimensionsInfo="
+          + HttpUtils.encodeURLParam(dimensionsInfo) + "&revision=" + 
request.getRevision(), null, null,
+          HttpRequest.GET);
+
+      HttpResponse httpResponse = httpTransport.doRequest(httpRequest);
+      if (httpResponse.getStatusCode() == HttpStatus.SC_OK) {
+        Map<String, Map<String, Object>> allConfigMap = HttpUtils.deserialize(
+            httpResponse.getContent(),
+            new TypeReference<Map<String, Map<String, Object>>>() {
+            });
+
+        if (allConfigMap.get(REVISION) != null) {
+          queryConfigurationsResponse.setRevision((String) 
allConfigMap.get(REVISION).get("version"));
+        }
+
+        if (allConfigMap.get(APPLICATION_CONFIG) != null) {
+          configurations.putAll(allConfigMap.get(APPLICATION_CONFIG));
+        }
+
+        if (allConfigMap.get(request.getServiceName()) != null) {
+          configurations.putAll(allConfigMap.get(request.getServiceName()));
+        }
+
+        if (allConfigMap.get(dimensionsInfo) != null) {
+          configurations.putAll(allConfigMap.get(dimensionsInfo));
+        }
+        queryConfigurationsResponse.setConfigurations(configurations);
+        queryConfigurationsResponse.setChanged(true);
+        return queryConfigurationsResponse;
+      } else if (httpResponse.getStatusCode() == HttpStatus.SC_NOT_MODIFIED) {
+        queryConfigurationsResponse.setChanged(false);
+        return queryConfigurationsResponse;
+      } else if (httpResponse.getStatusCode() == HttpStatus.SC_BAD_REQUEST) {
+        throw new OperationException("Bad request for query configurations.");
+      } else {
+        throw new OperationException(
+            "read response failed. status:"
+                + httpResponse.getStatusCode()
+                + "; message:"
+                + httpResponse.getMessage()
+                + "; content:"
+                + httpResponse.getContent());
+      }
+    } catch (IOException e) {
+      addressManager.nextAddress();
+      throw new OperationException("", e);
+    }
+  }
+
+  private String buildDimensionsInfo(QueryConfigurationsRequest request) {
+    String result =
+        request.getServiceName() + DEFAULT_APP_SEPARATOR
+            + request.getApplication();
+    if (!StringUtils.isEmpty(request.getVersion())) {
+      result = result + DEFAULT_SERVICE_SEPARATOR + request
+          .getVersion();
+    }
+    return result;
+  }
+}
diff --git 
a/clients/config-center-client/src/main/java/org/apache/servicecomb/config/center/client/ConfigCenterManager.java
 
b/clients/config-center-client/src/main/java/org/apache/servicecomb/config/center/client/ConfigCenterManager.java
new file mode 100644
index 0000000..e328448
--- /dev/null
+++ 
b/clients/config-center-client/src/main/java/org/apache/servicecomb/config/center/client/ConfigCenterManager.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.servicecomb.config.center.client;
+
+import 
org.apache.servicecomb.config.center.client.model.QueryConfigurationsRequest;
+import 
org.apache.servicecomb.config.center.client.model.QueryConfigurationsResponse;
+import org.apache.servicecomb.http.client.task.AbstractTask;
+import org.apache.servicecomb.http.client.task.Task;
+
+import com.google.common.eventbus.EventBus;
+
+public class ConfigCenterManager extends AbstractTask {
+  private static final long POLL_INTERVAL = 15000;
+
+  private ConfigCenterClient configCenterClient;
+
+  private final EventBus eventBus;
+
+  private QueryConfigurationsRequest queryConfigurationsRequest;
+
+  public ConfigCenterManager(ConfigCenterClient configCenterClient, EventBus 
eventBus) {
+    super("config-center-configuration-task");
+    this.configCenterClient = configCenterClient;
+    this.eventBus = eventBus;
+  }
+
+  public void setQueryConfigurationsRequest(QueryConfigurationsRequest 
queryConfigurationsRequest) {
+    this.queryConfigurationsRequest = queryConfigurationsRequest;
+  }
+
+  public void startConfigCenterManager() {
+    this.startTask(new PollConfigurationTask());
+  }
+
+  class PollConfigurationTask implements Task {
+    @Override
+    public void execute() {
+      QueryConfigurationsResponse response = 
configCenterClient.queryConfigurations(queryConfigurationsRequest);
+      if (response.isChanged()) {
+        queryConfigurationsRequest.setRevision(response.getRevision());
+        eventBus.post(new 
ConfigurationChangedEvent(response.getConfigurations()));
+      }
+      startTask(new BackOffSleepTask(POLL_INTERVAL, new 
PollConfigurationTask()));
+    }
+  }
+}
diff --git 
a/clients/config-center-client/src/main/java/org/apache/servicecomb/config/center/client/ConfigCenterOperation.java
 
b/clients/config-center-client/src/main/java/org/apache/servicecomb/config/center/client/ConfigCenterOperation.java
new file mode 100644
index 0000000..6cd726d
--- /dev/null
+++ 
b/clients/config-center-client/src/main/java/org/apache/servicecomb/config/center/client/ConfigCenterOperation.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.servicecomb.config.center.client;
+
+import 
org.apache.servicecomb.config.center.client.exception.OperationException;
+import 
org.apache.servicecomb.config.center.client.model.QueryConfigurationsRequest;
+import 
org.apache.servicecomb.config.center.client.model.QueryConfigurationsResponse;
+
+public interface ConfigCenterOperation {
+  /**
+   * 根据查询条件查询配置项。
+   * @param request 查询的维度(project, application, serviceName, version) 和 
revision 信息。
+   * @return 如果存在配置变更,返回全量的配置项, changed = true。 如果没有变更, 返回 null, changed = 
false,
+   *  @throws OperationException If some problems happened to contact service 
center or non http 200 returned.
+   */
+  QueryConfigurationsResponse queryConfigurations(QueryConfigurationsRequest 
request);
+}
diff --git 
a/clients/config-center-client/src/main/java/org/apache/servicecomb/config/center/client/ConfigurationChangedEvent.java
 
b/clients/config-center-client/src/main/java/org/apache/servicecomb/config/center/client/ConfigurationChangedEvent.java
new file mode 100644
index 0000000..235c6b1
--- /dev/null
+++ 
b/clients/config-center-client/src/main/java/org/apache/servicecomb/config/center/client/ConfigurationChangedEvent.java
@@ -0,0 +1,37 @@
+/*
+ * 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.servicecomb.config.center.client;
+
+import java.util.Map;
+
+public class ConfigurationChangedEvent {
+  private Map<String, Object> configurations;
+
+  public ConfigurationChangedEvent(Map<String, Object> configurations) {
+    this.configurations = configurations;
+  }
+
+  public Map<String, Object> getConfigurations() {
+    return configurations;
+  }
+
+  public ConfigurationChangedEvent setConfigurations(Map<String, Object> 
configurations) {
+    this.configurations = configurations;
+    return this;
+  }
+}
diff --git 
a/clients/config-center-client/src/main/java/org/apache/servicecomb/config/center/client/exception/OperationException.java
 
b/clients/config-center-client/src/main/java/org/apache/servicecomb/config/center/client/exception/OperationException.java
new file mode 100644
index 0000000..c63d1bf
--- /dev/null
+++ 
b/clients/config-center-client/src/main/java/org/apache/servicecomb/config/center/client/exception/OperationException.java
@@ -0,0 +1,30 @@
+/*
+ * 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.servicecomb.config.center.client.exception;
+
+public class OperationException extends RuntimeException {
+  private static final long serialVersionUID = 1L;
+
+  public OperationException(String message) {
+    super(message);
+  }
+
+  public OperationException(String message, Throwable cause) {
+    super(message, cause);
+  }
+}
diff --git 
a/clients/config-center-client/src/main/java/org/apache/servicecomb/config/center/client/model/QueryConfigurationsRequest.java
 
b/clients/config-center-client/src/main/java/org/apache/servicecomb/config/center/client/model/QueryConfigurationsRequest.java
new file mode 100644
index 0000000..34f77a5
--- /dev/null
+++ 
b/clients/config-center-client/src/main/java/org/apache/servicecomb/config/center/client/model/QueryConfigurationsRequest.java
@@ -0,0 +1,75 @@
+/*
+ * 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.servicecomb.config.center.client.model;
+
+public class QueryConfigurationsRequest {
+  private String project;
+
+  private String application;
+
+  private String serviceName;
+
+  private String version;
+
+  private String revision;
+
+  public String getProject() {
+    return project;
+  }
+
+  public QueryConfigurationsRequest setProject(String project) {
+    this.project = project;
+    return this;
+  }
+
+  public String getApplication() {
+    return application;
+  }
+
+  public QueryConfigurationsRequest setApplication(String application) {
+    this.application = application;
+    return this;
+  }
+
+  public String getServiceName() {
+    return serviceName;
+  }
+
+  public QueryConfigurationsRequest setServiceName(String serviceName) {
+    this.serviceName = serviceName;
+    return this;
+  }
+
+  public String getVersion() {
+    return version;
+  }
+
+  public QueryConfigurationsRequest setVersion(String version) {
+    this.version = version;
+    return this;
+  }
+
+  public String getRevision() {
+    return revision;
+  }
+
+  public QueryConfigurationsRequest setRevision(String revision) {
+    this.revision = revision;
+    return this;
+  }
+}
diff --git 
a/clients/config-center-client/src/main/java/org/apache/servicecomb/config/center/client/model/QueryConfigurationsResponse.java
 
b/clients/config-center-client/src/main/java/org/apache/servicecomb/config/center/client/model/QueryConfigurationsResponse.java
new file mode 100644
index 0000000..18b8ac6
--- /dev/null
+++ 
b/clients/config-center-client/src/main/java/org/apache/servicecomb/config/center/client/model/QueryConfigurationsResponse.java
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.servicecomb.config.center.client.model;
+
+import java.util.Map;
+
+public class QueryConfigurationsResponse {
+  private String revision;
+
+  private boolean changed;
+
+  private Map<String, Object> configurations;
+
+  public String getRevision() {
+    return revision;
+  }
+
+  public QueryConfigurationsResponse setRevision(String revision) {
+    this.revision = revision;
+    return this;
+  }
+
+  public boolean isChanged() {
+    return changed;
+  }
+
+  public QueryConfigurationsResponse setChanged(boolean changed) {
+    this.changed = changed;
+    return this;
+  }
+
+  public Map<String, Object> getConfigurations() {
+    return configurations;
+  }
+
+  public QueryConfigurationsResponse setConfigurations(
+      Map<String, Object> configurations) {
+    this.configurations = configurations;
+    return this;
+  }
+}
diff --git 
a/clients/http-client-common/src/main/java/org/apache/servicecomb/http/client/common/HttpUtils.java
 
b/clients/http-client-common/src/main/java/org/apache/servicecomb/http/client/common/HttpUtils.java
index e9c4e1f..37d5c20 100644
--- 
a/clients/http-client-common/src/main/java/org/apache/servicecomb/http/client/common/HttpUtils.java
+++ 
b/clients/http-client-common/src/main/java/org/apache/servicecomb/http/client/common/HttpUtils.java
@@ -26,6 +26,7 @@ import javax.crypto.spec.SecretKeySpec;
 
 import org.apache.commons.codec.binary.Hex;
 
+import com.fasterxml.jackson.core.type.TypeReference;
 import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.ObjectMapper;
 
@@ -38,6 +39,10 @@ public final class HttpUtils {
     return MAPPER.readValue(content, clazz);
   }
 
+  public static <T> T deserialize(String content, TypeReference<T> clazz) 
throws IOException {
+    return MAPPER.readValue(content, clazz);
+  }
+
   public static String serialize(Object value) throws IOException {
     return MAPPER.writeValueAsString(value);
   }
diff --git 
a/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/AbstractTask.java
 
b/clients/http-client-common/src/main/java/org/apache/servicecomb/http/client/task/AbstractTask.java
similarity index 86%
rename from 
clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/AbstractTask.java
rename to 
clients/http-client-common/src/main/java/org/apache/servicecomb/http/client/task/AbstractTask.java
index a8ead0c..097ac45 100644
--- 
a/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/AbstractTask.java
+++ 
b/clients/http-client-common/src/main/java/org/apache/servicecomb/http/client/task/AbstractTask.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.servicecomb.service.center.client;
+package org.apache.servicecomb.http.client.task;
 
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
@@ -25,11 +25,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 public class AbstractTask {
-  interface Task {
-    void execute();
-  }
-
-  class BackOffSleepTask implements Task {
+  public class BackOffSleepTask implements Task {
     final long base = 3000;
 
     final long max = 60000;
@@ -38,12 +34,12 @@ public class AbstractTask {
 
     Task nextTask;
 
-    BackOffSleepTask(int failedCount, Task nextTask) {
+    public BackOffSleepTask(int failedCount, Task nextTask) {
       this.waitTime = failedCount * base;
       this.nextTask = nextTask;
     }
 
-    BackOffSleepTask(long waitTime, Task nextTask) {
+    public BackOffSleepTask(long waitTime, Task nextTask) {
       this.waitTime = waitTime;
       this.nextTask = nextTask;
     }
@@ -60,7 +56,7 @@ public class AbstractTask {
     }
   }
 
-  private static final Logger LOGGER = 
LoggerFactory.getLogger(ServiceCenterRegistration.class);
+  private static final Logger LOGGER = 
LoggerFactory.getLogger(AbstractTask.class);
 
   private final ExecutorService taskPool;
 
diff --git 
a/clients/http-client-common/src/main/java/org/apache/servicecomb/http/client/task/Task.java
 
b/clients/http-client-common/src/main/java/org/apache/servicecomb/http/client/task/Task.java
new file mode 100644
index 0000000..bd00971
--- /dev/null
+++ 
b/clients/http-client-common/src/main/java/org/apache/servicecomb/http/client/task/Task.java
@@ -0,0 +1,22 @@
+/*
+ * 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.servicecomb.http.client.task;
+
+public interface Task {
+  void execute();
+}
diff --git a/clients/pom.xml b/clients/pom.xml
index fc17485..a412d61 100644
--- a/clients/pom.xml
+++ b/clients/pom.xml
@@ -35,6 +35,7 @@
     <module>http-client-common</module>
     <module>kie-client</module>
     <module>service-center-client</module>
+    <module>config-center-client</module>
   </modules>
 
 </project>
diff --git 
a/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/ServiceCenterDiscovery.java
 
b/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/ServiceCenterDiscovery.java
index c6be065..b6d218a 100644
--- 
a/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/ServiceCenterDiscovery.java
+++ 
b/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/ServiceCenterDiscovery.java
@@ -22,6 +22,8 @@ import java.util.Map;
 import java.util.Objects;
 import java.util.concurrent.ConcurrentHashMap;
 
+import org.apache.servicecomb.http.client.task.AbstractTask;
+import org.apache.servicecomb.http.client.task.Task;
 import 
org.apache.servicecomb.service.center.client.DiscoveryEvents.InstanceChangedEvent;
 import 
org.apache.servicecomb.service.center.client.model.FindMicroserviceInstancesResponse;
 import org.apache.servicecomb.service.center.client.model.Microservice;
diff --git 
a/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/ServiceCenterRegistration.java
 
b/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/ServiceCenterRegistration.java
index b83f38e..37c3f80 100644
--- 
a/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/ServiceCenterRegistration.java
+++ 
b/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/ServiceCenterRegistration.java
@@ -20,6 +20,8 @@ package org.apache.servicecomb.service.center.client;
 import java.util.List;
 
 import org.apache.commons.lang3.StringUtils;
+import org.apache.servicecomb.http.client.task.AbstractTask;
+import org.apache.servicecomb.http.client.task.Task;
 import 
org.apache.servicecomb.service.center.client.RegistrationEvents.HeartBeatEvent;
 import 
org.apache.servicecomb.service.center.client.RegistrationEvents.MicroserviceInstanceRegistrationEvent;
 import 
org.apache.servicecomb.service.center.client.RegistrationEvents.MicroserviceRegistrationEvent;

Reply via email to