type parse in service test
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/common/util/Constants.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/common/util/Constants.java
index 6d54b0a..9f5c282 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/common/util/Constants.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/common/util/Constants.java
@@ -24,7 +24,7 @@
 public class Constants {
 
     public static final String REGISTRY_ADDRESS = "dubbo.registry.address";
-    public static final String METADATA_ADDRESS = "dubbo.metadatareport.address";
+    public static final String METADATA_ADDRESS = "dubbo.metadataReport.address";
     public static final String DEFAULT_ROOT = "dubbo";
     public static final String PATH_SEPARATOR = "/";
     public static final String GROUP_KEY = "group";
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/common/util/ServiceTestUtil.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/common/util/ServiceTestUtil.java
new file mode 100644
index 0000000..f469f70
--- /dev/null
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/common/util/ServiceTestUtil.java
@@ -0,0 +1,109 @@
+/*
+ * 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.dubbo.admin.common.util;
+
+import org.apache.dubbo.admin.model.domain.MethodMetadata;
+import org.apache.dubbo.admin.model.dto.MethodDTO;
+import org.apache.dubbo.metadata.definition.model.FullServiceDefinition;
+import org.apache.dubbo.metadata.definition.model.MethodDefinition;
+import org.apache.dubbo.metadata.definition.model.ServiceDefinition;
+import org.apache.dubbo.metadata.definition.model.TypeDefinition;
+
+import java.util.*;
+import java.util.stream.Collectors;
+
+public class ServiceTestUtil {
+
+    public static boolean sameMethod(MethodDefinition m, MethodDTO methodDTO) {
+        return (m.getName().equals(methodDTO.getName())
+                && m.getReturnType().equals(methodDTO.getReturnType())
+                && m.getParameterTypes().equals(methodDTO.getParameterTypes().toArray()));
+    }
+
+    public static MethodMetadata generateMethodMeta(FullServiceDefinition serviceDefinition, MethodDefinition methodDefinition) {
+        MethodMetadata methodMetadata = new MethodMetadata();
+        String[] parameterTypes = methodDefinition.getParameterTypes();
+        String returnType = methodDefinition.getReturnType();
+        String signature = methodDefinition.getName() + "~" + Arrays.stream(parameterTypes).collect(Collectors.joining(";"));
+        methodMetadata.setSignature(signature);
+        methodMetadata.setReturnType(returnType);
+        List parameters = generateParameterTypes(parameterTypes, serviceDefinition);
+        methodMetadata.setParameterTypes(parameters);
+        return methodMetadata;
+    }
+
+    private static boolean isPrimitiveType(String type) {
+        return type.equals("byte") || type.equals("java.lang.Byte") ||
+                type.equals("short") || type.equals("java.lang.Short") ||
+                type.equals("int") || type.equals("java.lang.Integer") ||
+                type.equals("long") || type.equals("java.lang.Long") ||
+                type.equals("float") || type.equals("java.lang.Float") ||
+                type.equals("double") || type.equals("java.lang.Double") ||
+                type.equals("boolean") || type.equals("java.lang.Boolean") ||
+                type.equals("void") || type.equals("java.lang.Void") ||
+                type.equals("java.lang.String") ||
+                type.equals("java.util.Date") ||
+                type.equals("java.lang.Object");
+    }
+
+    private static List generateParameterTypes(String[] parameterTypes, ServiceDefinition serviceDefinition) {
+        List parameters = new ArrayList();
+        for (String type : parameterTypes) {
+            if (isPrimitiveType(type)) {
+                generatePrimitiveType(parameters, type);
+            } else {
+                TypeDefinition typeDefinition = findTypeDefinition(serviceDefinition, type);
+                Map<String, Object> holder = new HashMap<>();
+                generateComplexType(holder, typeDefinition);
+                parameters.add(holder);
+            }
+        }
+        return parameters;
+    }
+
+    private static TypeDefinition findTypeDefinition(ServiceDefinition serviceDefinition, String type) {
+        return serviceDefinition.getTypes().stream()
+                .filter(t -> t.getType().equals(type))
+                .findFirst().orElse(new TypeDefinition(type));
+    }
+
+    private static void generateComplexType(Map<String, Object> holder, TypeDefinition td) {
+        for (Map.Entry<String, TypeDefinition> entry : td.getProperties().entrySet()) {
+            String type = entry.getValue().getType();
+            if (isPrimitiveType(type)) {
+                holder.put(entry.getKey(), type);
+            } else {
+                generateEnclosedType(holder, entry.getKey(), entry.getValue());
+            }
+        }
+    }
+
+    private static void generatePrimitiveType(List parameters, String type) {
+        parameters.add(type);
+    }
+
+    private static void generateEnclosedType(Map<String, Object> holder, String key, TypeDefinition typeDefinition) {
+        if (typeDefinition.getProperties() == null || typeDefinition.getProperties().size() == 0) {
+            holder.put(key, typeDefinition.getType());
+        } else {
+            Map<String, Object> enclosedMap = new HashMap<>();
+            holder.put(key, enclosedMap);
+            generateComplexType(enclosedMap, typeDefinition);
+        }
+    }
+}
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 d080f2e..2944d64 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
@@ -124,10 +124,10 @@
         if (metadata != null) {
             Gson gson = new Gson();
             FullServiceDefinition serviceDefinition = gson.fromJson(metadata, FullServiceDefinition.class);
-            serviceDetailDTO.setConsumers(consumers);
-            serviceDetailDTO.setProviders(providers);
             serviceDetailDTO.setMetadata(serviceDefinition);
         }
+        serviceDetailDTO.setConsumers(consumers);
+        serviceDetailDTO.setProviders(providers);
         return serviceDetailDTO;
     }
 }
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/controller/ServiceTestController.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/controller/ServiceTestController.java
index a91b49e..6b7207c 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/controller/ServiceTestController.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/controller/ServiceTestController.java
@@ -1,10 +1,27 @@
 package org.apache.dubbo.admin.controller;
 
+import com.google.gson.Gson;
+import org.apache.dubbo.admin.common.util.ConvertUtil;
+import org.apache.dubbo.admin.common.util.ServiceTestUtil;
+import org.apache.dubbo.admin.model.domain.MethodMetadata;
+import org.apache.dubbo.admin.model.dto.MethodDTO;
 import org.apache.dubbo.admin.model.dto.ServiceTestDTO;
+import org.apache.dubbo.admin.service.ProviderService;
 import org.apache.dubbo.admin.service.impl.GenericServiceImpl;
+import org.apache.dubbo.common.Constants;
+import org.apache.dubbo.metadata.definition.model.FullServiceDefinition;
+import org.apache.dubbo.metadata.definition.model.MethodDefinition;
+import org.apache.dubbo.metadata.definition.model.TypeDefinition;
+import org.apache.dubbo.metadata.identifier.MetadataIdentifier;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
 @RestController
 @RequestMapping("/api/{env}/test")
 public class ServiceTestController {
@@ -12,9 +29,44 @@
     @Autowired
     private GenericServiceImpl genericService;
 
+    @Autowired
+    private ProviderService providerService;
+
     @RequestMapping(method = RequestMethod.POST)
     public Object test(@PathVariable String env, @RequestBody ServiceTestDTO serviceTestDTO) {
         return genericService.invoke(serviceTestDTO.getService(), serviceTestDTO.getMethod(), serviceTestDTO.getTypes(), serviceTestDTO.getParams());
 //        return null;
     }
+
+    @RequestMapping(value = "/method", method = RequestMethod.GET)
+    public MethodMetadata methodDetail(@PathVariable String env, @RequestBody MethodDTO methodDTO) {
+        String service = methodDTO.getService();
+        String application = methodDTO.getApplication();
+        Map<String, String> info = ConvertUtil.serviceName2Map(service);
+        MetadataIdentifier identifier = new MetadataIdentifier(info.get(Constants.INTERFACE_KEY),
+                info.get(Constants.VERSION_KEY),
+                info.get(Constants.GROUP_KEY), Constants.PROVIDER_SIDE, application);
+        String metadata = providerService.getProviderMetaData(identifier);
+        MethodMetadata methodMetadata = null;
+        if (metadata != null) {
+            Gson gson = new Gson();
+            FullServiceDefinition serviceDefinition = gson.fromJson(metadata, FullServiceDefinition.class);
+            List<MethodDefinition> methods = serviceDefinition.getMethods();
+            if (methods != null) {
+                for (MethodDefinition m : methods) {
+                    if (ServiceTestUtil.sameMethod(m, methodDTO)) {
+                        methodMetadata = ServiceTestUtil.generateMethodMeta(serviceDefinition, m);
+                        break;
+                    }
+                }
+            }
+        }
+        return methodMetadata;
+    }
+
+    public static void main(String[] args) {
+        String[] types = new String[]{"java.lang.String", "java.lang.Map", "com.taobao.alibaba.Demo"};
+        String signature = Arrays.stream(types).collect(Collectors.joining(";"));
+        System.out.println(signature);
+    }
 }
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/domain/MethodMetadata.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/domain/MethodMetadata.java
new file mode 100644
index 0000000..25a98c9
--- /dev/null
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/domain/MethodMetadata.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dubbo.admin.model.domain;
+
+import java.util.List;
+import java.util.Map;
+
+public class MethodMetadata {
+    private String signature;
+    private List parameterTypes;
+    private String returnType;
+
+    public String getSignature() {
+        return signature;
+    }
+
+    public void setSignature(String signature) {
+        this.signature = signature;
+    }
+
+    public List getParameterTypes() {
+        return parameterTypes;
+    }
+
+    public void setParameterTypes(List parameterTypes) {
+        this.parameterTypes = parameterTypes;
+    }
+
+    public String getReturnType() {
+        return returnType;
+    }
+
+    public void setReturnType(String returnType) {
+        this.returnType = returnType;
+    }
+}
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/dto/MethodDTO.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/dto/MethodDTO.java
new file mode 100644
index 0000000..fdd6ffb
--- /dev/null
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/dto/MethodDTO.java
@@ -0,0 +1,70 @@
+/*
+ * 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.dubbo.admin.model.dto;
+
+
+
+import java.util.List;
+
+public class MethodDTO {
+    private String application;
+    private String service;
+    private String name;
+    private List<String> parameterTypes;
+    private String returnType;
+
+    public String getApplication() {
+        return application;
+    }
+
+    public void setApplication(String application) {
+        this.application = application;
+    }
+
+    public String getService() {
+        return service;
+    }
+
+    public void setService(String service) {
+        this.service = service;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public List<String> getParameterTypes() {
+        return parameterTypes;
+    }
+
+    public void setParameterTypes(List<String> parameterTypes) {
+        this.parameterTypes = parameterTypes;
+    }
+
+    public String getReturnType() {
+        return returnType;
+    }
+
+    public void setReturnType(String returnType) {
+        this.returnType = returnType;
+    }
+}
diff --git a/dubbo-admin-frontend/src/components/ServiceTest.vue b/dubbo-admin-frontend/src/components/test/ServiceTest.vue
similarity index 98%
rename from dubbo-admin-frontend/src/components/ServiceTest.vue
rename to dubbo-admin-frontend/src/components/test/ServiceTest.vue
index 64a5a02..5289a4c 100644
--- a/dubbo-admin-frontend/src/components/ServiceTest.vue
+++ b/dubbo-admin-frontend/src/components/test/ServiceTest.vue
@@ -55,6 +55,7 @@
               <json-editor v-model="modal.json" />
             </v-flex>
             <v-flex lg6>
+              <json-editor v-model="modal.json" />
             </v-flex>
           </v-layout>
         </v-container>
diff --git a/dubbo-admin-frontend/src/components/test/TestMethod.vue b/dubbo-admin-frontend/src/components/test/TestMethod.vue
new file mode 100644
index 0000000..5c511a0
--- /dev/null
+++ b/dubbo-admin-frontend/src/components/test/TestMethod.vue
@@ -0,0 +1,107 @@
+<!--
+  - 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.
+  -->
+
+<template>
+  <v-container grid-list-xl fluid>
+    <v-layout row wrap>
+      <v-flex lg12>
+        <v-data-table
+          :items="basic"
+          class="elevation-1"
+          hide-actions
+          hide-headers >
+          <template slot="items" slot-scope="props">
+            <td><h4>{{props.item.name}}</h4></td>
+            <td>{{props.item.value}}</td>
+          </template>
+        </v-data-table>
+      </v-flex>
+      <v-flex lg12>
+        <v-card>
+          <v-toolbar flat color="transparent" class="elevation-0">
+            <v-toolbar-title><h3>Please fill in parameters</h3></v-toolbar-title>
+          </v-toolbar>
+          <v-layout row wrap>
+            <v-flex lg10>
+              <json-editor id="test"/>
+            </v-flex>
+            <v-toolbar flat color="transparent" class="elevation-0">
+              <v-toolbar-title><h3>Test Result</h3></v-toolbar-title>
+            </v-toolbar>
+            <v-flex lg10>
+              <json-editor id="result" v-if="method.showResult"/>
+            </v-flex>
+          </v-layout>
+        </v-card>
+      </v-flex>
+
+    </v-layout>
+
+  </v-container>
+</template>
+
+<script>
+  import JsonEditor from '@/components/public/JsonEditor'
+  export default {
+    name: 'TestMethod',
+    data () {
+      return {
+        basic: [],
+        method: {
+          name: null,
+          types: [],
+          json: [],
+          showResult: false
+        }
+      }
+    },
+
+    mounted: function () {
+      let query = this.$route.query
+      let vm = this
+      Object.keys(query).forEach(function (key) {
+        if (key === 'service') {
+          let item = {}
+          item.name = 'service'
+          item.value = query[key]
+          vm.basic.push(item)
+        }
+        if (key === 'method') {
+          let item = {}
+          item.name = 'method'
+          item.value = query[key]
+          vm.method.name = query[key].split('~')[0]
+          let sig = query[key].split('~')[1]
+          vm.types = sig.split(';')
+          vm.types.forEach(function (item) {
+            vm.json.push(item)
+          })
+
+          vm.basic.push(item)
+        }
+      })
+    },
+    components: {
+      JsonEditor
+    }
+
+  }
+</script>
+
+<style scoped>
+
+</style>
diff --git a/dubbo-admin-frontend/src/router/index.js b/dubbo-admin-frontend/src/router/index.js
index 2fe356e..d2896b5 100644
--- a/dubbo-admin-frontend/src/router/index.js
+++ b/dubbo-admin-frontend/src/router/index.js
@@ -19,7 +19,8 @@
 import Router from 'vue-router'
 import ServiceSearch from '@/components/ServiceSearch'
 import ServiceDetail from '@/components/ServiceDetail'
-import ServiceTest from '@/components/ServiceTest'
+import ServiceTest from '@/components/test/ServiceTest'
+import TestMethod from '@/components/test/TestMethod'
 import RoutingRule from '@/components/governance/RoutingRule'
 import TagRule from '@/components/governance/TagRule'
 import AccessControl from '@/components/governance/AccessControl'
@@ -47,6 +48,11 @@
       component: ServiceTest
     },
     {
+      path: '/testMethod',
+      name: 'TestMethod',
+      component: TestMethod
+    },
+    {
       path: '/governance/routingRule',
       name: 'RoutingRule',
       component: RoutingRule