add provider metadata service & metadata client
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/config/ConfigCenter.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/config/ConfigCenter.java
index 1af2e09..4c03ddf 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/config/ConfigCenter.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/config/ConfigCenter.java
@@ -1,5 +1,6 @@
 package org.apache.dubbo.admin.config;
 
+import org.apache.commons.lang3.StringUtils;
 import org.apache.dubbo.admin.common.util.Constants;
 import org.apache.dubbo.admin.data.config.GovernanceConfiguration;
 import org.apache.dubbo.admin.data.metadata.MetaDataCollector;
@@ -42,7 +43,7 @@
     @Bean("governanceConfiguration")
     GovernanceConfiguration getDynamicConfiguration() {
         if (configCenter != null) {
-            configCenterUrl = formUrl(configCenter);
+            configCenterUrl = formUrl(configCenter, group);
             GovernanceConfiguration dynamicConfiguration = ExtensionLoader.getExtensionLoader(GovernanceConfiguration.class).getExtension(configCenterUrl.getProtocol());
             dynamicConfiguration.setUrl(configCenterUrl);
             dynamicConfiguration.init();
@@ -51,9 +52,9 @@
 
             Arrays.stream(config.split("\n")).forEach( s -> {
                 if(s.startsWith(Constants.REGISTRY_ADDRESS)) {
-                    registryUrl = formUrl(s.split("=")[1].trim());
+                    registryUrl = formUrl(s.split("=")[1].trim(), group);
                 } else if (s.startsWith(Constants.METADATA_ADDRESS)) {
-                    metadataUrl = formUrl(s.split("=")[1].trim());
+                    metadataUrl = formUrl(s.split("=")[1].trim(), group);
                 }
             });
             return dynamicConfiguration;
@@ -88,12 +89,15 @@
         return metaDataCollector;
     }
 
-    private URL formUrl(String config) {
+    private URL formUrl(String config, String group) {
         String protocol = config.split("://")[0];
         String address = config.split("://")[1];
         String port = address.split(":")[1];
         String host = address.split(":")[0];
-        return new URL(protocol, host, Integer.parseInt(port));
+        URL url = new URL(protocol, host, Integer.parseInt(port));
+        if (StringUtils.isNotEmpty(group)) {
+            url.addParameter(org.apache.dubbo.common.Constants.GROUP_KEY, group);
+        }
+        return url;
     }
-
 }
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/controller/ServiceController.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/controller/ServiceController.java
index 0a4e3cb..896baa2 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/controller/ServiceController.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/controller/ServiceController.java
@@ -17,6 +17,8 @@
 
 package org.apache.dubbo.admin.controller;
 
+import com.google.gson.Gson;
+import org.apache.dubbo.admin.common.util.ConvertUtil;
 import org.apache.dubbo.common.Constants;
 import org.apache.dubbo.common.utils.StringUtils;
 import org.apache.dubbo.admin.model.dto.ServiceDTO;
@@ -25,6 +27,8 @@
 import org.apache.dubbo.admin.service.ProviderService;
 import org.apache.dubbo.admin.model.domain.Consumer;
 import org.apache.dubbo.admin.model.domain.Provider;
+import org.apache.dubbo.metadata.definition.model.FullServiceDefinition;
+import org.apache.dubbo.metadata.identifier.ProviderMetadataIdentifier;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 
@@ -107,9 +111,17 @@
 
         List<Consumer> consumers = consumerService.findByService(service);
 
+        Map<String, String> info = ConvertUtil.serviceName2Map(service);
+        ProviderMetadataIdentifier p = new ProviderMetadataIdentifier(info.get(Constants.INTERFACE_KEY),
+                                                                      info.get(Constants.VERSION_KEY),
+                                                                      info.get(Constants.GROUP_KEY));
+        String metadata = providerService.getProviderMetaData(p);
+        Gson gson = new Gson();
+        FullServiceDefinition serviceDefinition = gson.fromJson(metadata, FullServiceDefinition.class);
         ServiceDetailDTO serviceDetailDTO = new ServiceDetailDTO();
         serviceDetailDTO.setConsumers(consumers);
         serviceDetailDTO.setProviders(providers);
+        serviceDetailDTO.setMetadata(serviceDefinition);
         return serviceDetailDTO;
     }
 }
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/data/metadata/MetaDataCollector.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/data/metadata/MetaDataCollector.java
index 77b7041..4be3850 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/data/metadata/MetaDataCollector.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/data/metadata/MetaDataCollector.java
@@ -2,6 +2,8 @@
 
 import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.extension.SPI;
+import org.apache.dubbo.metadata.identifier.ConsumerMetadataIdentifier;
+import org.apache.dubbo.metadata.identifier.ProviderMetadataIdentifier;
 
 @SPI("zookeeper")
 public interface MetaDataCollector {
@@ -11,5 +13,8 @@
     URL getUrl();
 
     void init();
-    String getMetaData(String path);
+
+    String getProviderMetaData(ProviderMetadataIdentifier key);
+
+    String getConsumerMetaData(ConsumerMetadataIdentifier key);
 }
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/data/metadata/impl/RedisMetaDataCollector.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/data/metadata/impl/RedisMetaDataCollector.java
index 82d0e71..82a1536 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/data/metadata/impl/RedisMetaDataCollector.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/data/metadata/impl/RedisMetaDataCollector.java
@@ -3,6 +3,9 @@
 
 import org.apache.dubbo.admin.data.metadata.MetaDataCollector;
 import org.apache.dubbo.common.URL;
+import org.apache.dubbo.metadata.identifier.ConsumerMetadataIdentifier;
+import org.apache.dubbo.metadata.identifier.MetadataIdentifier;
+import org.apache.dubbo.metadata.identifier.ProviderMetadataIdentifier;
 import redis.clients.jedis.Jedis;
 import redis.clients.jedis.JedisPool;
 import redis.clients.jedis.JedisPoolConfig;
@@ -11,6 +14,7 @@
 
     private  URL url;
     private JedisPool pool;
+    private static final String META_DATA_SOTRE_TAG = ".metaData";
     @Override
     public void setUrl(URL url) {
         this.url = url;
@@ -27,8 +31,19 @@
     }
 
     @Override
-    public String getMetaData(String path) {
+    public String getProviderMetaData(ProviderMetadataIdentifier key) {
+        return doGetMetaData(key);
+    }
+
+    @Override
+    public String getConsumerMetaData(ConsumerMetadataIdentifier key) {
+        return doGetMetaData(key);
+    }
+
+    private String doGetMetaData(MetadataIdentifier identifier) {
+        //TODO error handing
         Jedis jedis = pool.getResource();
-        return jedis.get(path);
+        String result = jedis.get(identifier.getUniqueKey(MetadataIdentifier.KeyTypeEnum.UNIQUE_KEY) + META_DATA_SOTRE_TAG);
+        return result;
     }
 }
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/data/metadata/impl/ZookeeperMetaDataCollector.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/data/metadata/impl/ZookeeperMetaDataCollector.java
index d6033f8..2e65aff 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/data/metadata/impl/ZookeeperMetaDataCollector.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/data/metadata/impl/ZookeeperMetaDataCollector.java
@@ -4,13 +4,20 @@
 import org.apache.curator.framework.CuratorFrameworkFactory;
 import org.apache.curator.retry.ExponentialBackoffRetry;
 import org.apache.dubbo.admin.data.metadata.MetaDataCollector;
+import org.apache.dubbo.common.Constants;
 import org.apache.dubbo.common.URL;
+import org.apache.dubbo.metadata.identifier.ConsumerMetadataIdentifier;
+import org.apache.dubbo.metadata.identifier.MetadataIdentifier;
+import org.apache.dubbo.metadata.identifier.ProviderMetadataIdentifier;
 import org.apache.dubbo.remoting.zookeeper.ZookeeperClient;
 
 public class ZookeeperMetaDataCollector implements MetaDataCollector {
 
-    CuratorFramework client;
-    URL url;
+    private CuratorFramework client;
+    private URL url;
+    private String root;
+    private final static String METADATA_NODE_NAME = "service.data";
+    private final static String DEFAULT_ROOT = "dubbo";
 
     @Override
     public void setUrl(URL url) {
@@ -25,12 +32,37 @@
     @Override
     public void init() {
         client = CuratorFrameworkFactory.newClient(url.getAddress(), new ExponentialBackoffRetry(1000, 3));
+        root = url.getParameter(Constants.GROUP_KEY) == null ? DEFAULT_ROOT : url.getParameter(Constants.GROUP_KEY);
         client.start();
     }
 
+
     @Override
-    public String getMetaData(String path) {
+    public String getProviderMetaData(ProviderMetadataIdentifier key) {
+        return doGetMetadata(key);
+    }
+
+    @Override
+    public String getConsumerMetaData(ConsumerMetadataIdentifier key) {
+        return doGetMetadata(key);
+    }
+
+    private String getNodePath(MetadataIdentifier metadataIdentifier) {
+        return toRootDir() + metadataIdentifier.getUniqueKey(MetadataIdentifier.KeyTypeEnum.PATH) +
+                Constants.PATH_SEPARATOR + METADATA_NODE_NAME;
+    }
+
+    private String toRootDir() {
+        if (root.equals(Constants.PATH_SEPARATOR)) {
+            return root;
+        }
+        return root + Constants.PATH_SEPARATOR;
+    }
+
+    private String doGetMetadata(MetadataIdentifier identifier) {
+        //TODO error handing
         try {
+            String path = getNodePath(identifier);
             if (client.checkExists().forPath(path) == null) {
                 return null;
             }
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/dto/ServiceDetailDTO.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/dto/ServiceDetailDTO.java
index a994e48..2a738f5 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/dto/ServiceDetailDTO.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/dto/ServiceDetailDTO.java
@@ -19,6 +19,7 @@
 
 import org.apache.dubbo.admin.model.domain.Consumer;
 import org.apache.dubbo.admin.model.domain.Provider;
+import org.apache.dubbo.metadata.definition.model.FullServiceDefinition;
 
 import java.util.List;
 
@@ -27,6 +28,9 @@
     List<Provider> providers;
     List<Consumer> consumers;
 
+    FullServiceDefinition metadata;
+
+
     public List<Provider> getProviders() {
         return providers;
     }
@@ -42,4 +46,12 @@
     public void setConsumers(List<Consumer> consumers) {
         this.consumers = consumers;
     }
+
+    public FullServiceDefinition getMetadata() {
+        return metadata;
+    }
+
+    public void setMetadata(FullServiceDefinition metadata) {
+        this.metadata = metadata;
+    }
 }
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/ConsumerService.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/ConsumerService.java
index 2b4a860..da518f9 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/ConsumerService.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/ConsumerService.java
@@ -17,6 +17,7 @@
 package org.apache.dubbo.admin.service;
 
 import org.apache.dubbo.admin.model.domain.Consumer;
+import org.apache.dubbo.metadata.identifier.ConsumerMetadataIdentifier;
 
 import java.util.List;
 
@@ -30,6 +31,8 @@
 
     Consumer findConsumer(String id);
 
+    String getConsumerMetadata(ConsumerMetadataIdentifier consumerIdentifier);
+
     List<Consumer> findAll();
 
     /**
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/ProviderService.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/ProviderService.java
index fc7f2a9..5bd69f9 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/ProviderService.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/ProviderService.java
@@ -17,6 +17,7 @@
 package org.apache.dubbo.admin.service;
 
 import org.apache.dubbo.admin.model.domain.Provider;
+import org.apache.dubbo.metadata.identifier.ProviderMetadataIdentifier;
 
 import java.util.List;
 
@@ -42,6 +43,8 @@
 
     Provider findProvider(String id);
 
+    String getProviderMetaData(ProviderMetadataIdentifier providerIdentifier);
+
     List<String> findServices();
 
     List<String> findAddresses();
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/RouteService.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/RouteService.java
index 1b56073..bbb9c16 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/RouteService.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/RouteService.java
@@ -42,6 +42,8 @@
 
     List<Route> findByService(String serviceName);
 
+    List<Route> findByApplication(String application);
+
     List<Route> findByAddress(String address);
 
     List<Route> findByServiceAndAddress(String service, String address);
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/impl/ConsumerServiceImpl.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/impl/ConsumerServiceImpl.java
index 2f70321..56917be 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/impl/ConsumerServiceImpl.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/impl/ConsumerServiceImpl.java
@@ -22,6 +22,7 @@
 import org.apache.dubbo.admin.common.util.Pair;
 import org.apache.dubbo.admin.common.util.SyncUtils;
 import org.apache.dubbo.admin.model.domain.Consumer;
+import org.apache.dubbo.metadata.identifier.ConsumerMetadataIdentifier;
 import org.springframework.stereotype.Component;
 
 import java.util.ArrayList;
@@ -49,6 +50,11 @@
         return SyncUtils.url2ConsumerList(findAllConsumerUrl());
     }
 
+    @Override
+    public String getConsumerMetadata(ConsumerMetadataIdentifier consumerIdentifier) {
+        return metaDataCollector.getConsumerMetaData(consumerIdentifier);
+    }
+
     private Map<String, URL> findAllConsumerUrl() {
         Map<String, String> filter = new HashMap<String, String>();
         filter.put(Constants.CATEGORY_KEY, Constants.CONSUMERS_CATEGORY);
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/impl/ProviderServiceImpl.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/impl/ProviderServiceImpl.java
index faf99dd..3a81d2a 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/impl/ProviderServiceImpl.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/impl/ProviderServiceImpl.java
@@ -26,6 +26,7 @@
 import org.apache.dubbo.admin.model.domain.Override;
 import org.apache.dubbo.admin.model.domain.Provider;
 import org.apache.dubbo.admin.common.util.ParseUtils;
+import org.apache.dubbo.metadata.identifier.ProviderMetadataIdentifier;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 
@@ -88,6 +89,11 @@
         }
     }
 
+    @java.lang.Override
+    public String getProviderMetaData(ProviderMetadataIdentifier providerIdentifier) {
+        return metaDataCollector.getProviderMetaData(providerIdentifier);
+    }
+
     public void disableProvider(String id) {
         if (id == null) {
             throw new IllegalStateException("no provider id");
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/impl/RouteServiceImpl.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/impl/RouteServiceImpl.java
index 7b5bd30..91c5b0d 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/impl/RouteServiceImpl.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/impl/RouteServiceImpl.java
@@ -138,6 +138,11 @@
         return SyncUtils.filterFromCategory(getRegistryCache(), filter);
     }
 
+    @Override
+    public List<Route> findByApplication(String application) {
+        return null;
+    }
+
     public List<Route> findByService(String serviceName) {
         return SyncUtils.url2RouteList(findRouteUrl(serviceName, null, false));
     }