Merge branch 'develop' into service-test
# Conflicts:
# dubbo-admin-backend/pom.xml
# dubbo-admin-frontend/src/components/test/ServiceTest.vue
diff --git a/dubbo-admin-backend/pom.xml b/dubbo-admin-backend/pom.xml
index 65449cb..671f865 100644
--- a/dubbo-admin-backend/pom.xml
+++ b/dubbo-admin-backend/pom.xml
@@ -87,6 +87,10 @@
</exclusions>
</dependency>
<dependency>
+ <groupId>org.apache.curator</groupId>
+ <artifactId>curator-recipes</artifactId>
+ </dependency>
+ <dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
</dependency>
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
new file mode 100644
index 0000000..6b7207c
--- /dev/null
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/controller/ServiceTestController.java
@@ -0,0 +1,72 @@
+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 {
+
+ @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-backend/src/main/java/org/apache/dubbo/admin/model/dto/ServiceTestDTO.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/dto/ServiceTestDTO.java
new file mode 100644
index 0000000..3979e78
--- /dev/null
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/dto/ServiceTestDTO.java
@@ -0,0 +1,40 @@
+package org.apache.dubbo.admin.model.dto;
+
+public class ServiceTestDTO {
+ private String service;
+ private String method;
+ private String[] types;
+ private Object[] params;
+
+ public String getService() {
+ return service;
+ }
+
+ public void setService(String service) {
+ this.service = service;
+ }
+
+ public String getMethod() {
+ return method;
+ }
+
+ public void setMethod(String method) {
+ this.method = method;
+ }
+
+ public String[] getTypes() {
+ return types;
+ }
+
+ public void setTypes(String[] types) {
+ this.types = types;
+ }
+
+ public Object[] getParams() {
+ return params;
+ }
+
+ public void setParams(Object[] params) {
+ this.params = params;
+ }
+}
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/impl/GenericServiceImpl.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/impl/GenericServiceImpl.java
new file mode 100644
index 0000000..469ec9e
--- /dev/null
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/impl/GenericServiceImpl.java
@@ -0,0 +1,50 @@
+package org.apache.dubbo.admin.service.impl;
+
+import org.apache.dubbo.config.ApplicationConfig;
+import org.apache.dubbo.config.ReferenceConfig;
+import org.apache.dubbo.config.RegistryConfig;
+import org.apache.dubbo.registry.Registry;
+import org.apache.dubbo.rpc.service.GenericService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.PostConstruct;
+
+@Component
+public class GenericServiceImpl {
+
+ private ReferenceConfig<GenericService> reference;
+
+ @Autowired
+ private Registry registry;
+
+ @PostConstruct
+ public void init() {
+ reference = new ReferenceConfig<>();
+ reference.setGeneric(true);
+
+ RegistryConfig registryConfig = new RegistryConfig();
+ registryConfig.setAddress(registry.getUrl().getProtocol() + "://" + registry.getUrl().getAddress());
+
+ ApplicationConfig applicationConfig = new ApplicationConfig();
+ applicationConfig.setName("dubbo-admin");
+ applicationConfig.setRegistry(registryConfig);
+
+ reference.setApplication(applicationConfig);
+ }
+
+ public Object invoke(String service, String method, String[] parameterTypes, Object[] params) {
+
+ reference.setInterface(service);
+ GenericService genericService = reference.get();
+ Object result = genericService.$invoke(method, parameterTypes, params);
+ System.out.println(result);
+ return result;
+ }
+
+ public static void main(String[] args) {
+ GenericServiceImpl genericService = new GenericServiceImpl();
+ genericService.init();
+ genericService.invoke("org.apache.dubbo.demo.api.DemoService", "sayHello", new String[]{"java.lang.String"}, new Object[]{"hello"});
+ }
+}
diff --git a/dubbo-admin-frontend/package.json b/dubbo-admin-frontend/package.json
index e4a3919..26e89c6 100644
--- a/dubbo-admin-frontend/package.json
+++ b/dubbo-admin-frontend/package.json
@@ -15,6 +15,7 @@
"brace": "^0.11.1",
"http-status": "^1.2.0",
"js-yaml": "^3.12.0",
+ "jsoneditor": "^5.26.2",
"vue": "^2.5.2",
"vue-router": "^3.0.1",
"vuetify": "^1.2.2",
diff --git a/dubbo-admin-frontend/src/components/public/Footers.vue b/dubbo-admin-frontend/src/components/public/Footers.vue
index a5bbab6..331bea7 100644
--- a/dubbo-admin-frontend/src/components/public/Footers.vue
+++ b/dubbo-admin-frontend/src/components/public/Footers.vue
@@ -16,7 +16,7 @@
-->
<template>
- <v-footer inset height="auto" class="pa-3 footer-border-top" app>
+ <v-footer inset height="auto" class="pa-3 footer-border-top">
<v-spacer></v-spacer>
<span class="caption mr-1"><strong>Copyright</strong> ©{{ new Date().getFullYear() }} <strong>The Apache Software Foundation.</strong></span>
</v-footer>
diff --git a/dubbo-admin-frontend/src/components/public/JsonEditor.vue b/dubbo-admin-frontend/src/components/public/JsonEditor.vue
new file mode 100644
index 0000000..82e4d35
--- /dev/null
+++ b/dubbo-admin-frontend/src/components/public/JsonEditor.vue
@@ -0,0 +1,84 @@
+<!--
+ - 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>
+ <div class="jsoneditor-vue-container"></div>
+</template>
+
+<script>
+ import JSONEditor from 'jsoneditor'
+ import 'jsoneditor/dist/jsoneditor.css'
+
+ export default {
+ name: 'json-editor',
+ props: {
+ value: Array,
+ mode: {
+ type: String,
+ default: 'tree'
+ },
+ modes: {
+ type: Array,
+ default: () => ['tree', 'code']
+ },
+ templates: Array
+ },
+ data () {
+ return {
+ $jsoneditor: null
+ }
+ },
+ watch: {
+ value (newVal, oldVal) {
+ if (newVal !== oldVal && this.$jsoneditor) {
+ this.$jsoneditor.update(newVal)
+ }
+ }
+ },
+ mounted () {
+ const options = {
+ name: 'Parameters',
+ navigationBar: false,
+ search: false,
+ mode: this.mode,
+ modes: this.modes,
+ onChange: () => {
+ if (this.$jsoneditor) {
+ var json = this.$jsoneditor.get()
+ this.$emit('input', json)
+ }
+ },
+ templates: this.templates
+ }
+ this.$jsoneditor = new JSONEditor(this.$el, options)
+ this.$jsoneditor.set(this.value)
+ this.$jsoneditor.expandAll()
+ },
+ beforeDestroy () {
+ if (this.$jsoneditor) {
+ this.$jsoneditor.destroy()
+ this.$jsoneditor = null
+ }
+ }
+ }
+</script>
+
+<style scoped>
+ .jsoneditor-vue-container {
+ width: 100%;
+ height: 100%;
+ }
+</style>
diff --git a/dubbo-admin-frontend/src/components/test/ServiceTest.vue b/dubbo-admin-frontend/src/components/test/ServiceTest.vue
index a38cca0..5289a4c 100644
--- a/dubbo-admin-frontend/src/components/test/ServiceTest.vue
+++ b/dubbo-admin-frontend/src/components/test/ServiceTest.vue
@@ -14,27 +14,174 @@
- 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-card>
- <v-card-title>
- <h1>Service Test will release in the future</h1>
- </v-card-title>
- </v-card>
+ <v-flex xs12>
+ <search id="serviceSearch" v-model="filter" label="Search by service name" :submit="search"></search>
+ </v-flex>
+ <v-flex xs12>
+ <h3>Methods</h3>
+ </v-flex>
+ <v-flex xs12>
+ <v-data-table :headers="headers" :items="methods" hide-actions class="elevation-1">
+ <template slot="items" slot-scope="props">
+ <td>{{ props.item.name }}</td>
+ <td><v-chip xs v-for="(type, index) in props.item.parameterTypes" :key="index" label>{{ type }}</v-chip></td>
+ <td><v-chip label>{{ props.item.returnType }}</v-chip></td>
+ <td class="text-xs-right">
+ <v-tooltip bottom>
+ <v-icon small
+ class="mr-2"
+ color="blue"
+ slot="activator"
+ @click="toTest(props.item)">input</v-icon>
+ <span>Try it</span>
+ </v-tooltip>
+ </td>
+ </template>
+ </v-data-table>
</v-flex>
</v-layout>
+
+ <v-dialog v-model="modal.enable" width="1000px" persistent>
+ <v-card>
+ <v-card-title>
+ <span class="headline">Test {{ modal.method }}</span>
+ </v-card-title>
+ <v-container grid-list-xl fluid>
+ <v-layout row>
+ <v-flex lg6>
+ <json-editor v-model="modal.json" />
+ </v-flex>
+ <v-flex lg6>
+ <json-editor v-model="modal.json" />
+ </v-flex>
+ </v-layout>
+ </v-container>
+ <v-card-actions>
+ <v-spacer></v-spacer>
+ <v-btn color="darken-1"
+ flat
+ @click="modal.enable = false">Close</v-btn>
+ <v-btn color="primary"
+ depressed
+ @click="test">Execute</v-btn>
+ </v-card-actions>
+ </v-card>
+ </v-dialog>
</v-container>
</template>
<script>
+ import JsonEditor from '@/components/public/JsonEditor'
+ import Search from '@/components/public/Search'
+
export default {
- name: 'ServiceTest'
+ name: 'ServiceTest',
+ data () {
+ return {
+ filter: '',
+ headers: [
+ {
+ text: 'Method Name',
+ value: 'method',
+ sortable: false
+ },
+ {
+ text: 'Parameter List',
+ value: 'parameter',
+ sortable: false
+ },
+ {
+ text: 'Return Type',
+ value: 'returnType',
+ sortable: false
+ },
+ {
+ text: '',
+ value: 'operation',
+ sortable: false
+ }
+ ],
+ service: null,
+ methods: [],
+ modal: {
+ method: null,
+ enable: false,
+ types: null,
+ json: []
+ }
+ }
+ },
+ methods: {
+ search () {
+ if (!this.filter) {
+ this.filter = document.querySelector('#serviceSearch').value.trim()
+ if (!this.filter) {
+ return
+ }
+ }
+ this.$router.push({
+ path: 'test',
+ query: { service: this.filter }
+ })
+ this.$axios.get('/service/' + this.filter).then(response => {
+ this.service = response.data
+ if (this.service.hasOwnProperty('metadata')) {
+ this.methods = this.service.metadata.methods
+ }
+ }).catch(error => {
+ this.showSnackbar('error', error.response.data.message)
+ })
+ },
+ toTest (item) {
+ Object.assign(this.modal, {
+ enable: true,
+ method: item.name
+ })
+ this.modal.json = []
+ this.modal.types = item.parameterTypes
+ item.parameterTypes.forEach((i, index) => {
+ this.modal.json.push(this.getType(i))
+ })
+ },
+ test () {
+ this.$axios.post('/test', {
+ service: this.service.metadata.canonicalName,
+ method: this.modal.method,
+ types: this.modal.types,
+ params: this.modal.json
+ }).then(response => {
+ console.log(response)
+ })
+ },
+ getType (type) {
+ if (type.indexOf('java.util.List') === 0) {
+ return []
+ } else if (type.indexOf('java.util.Map') === 0) {
+ return []
+ } else {
+ return ''
+ }
+ }
+ },
+ mounted: function () {
+ let query = this.$route.query
+ let filter = null
+ Object.keys(query).forEach(function (key) {
+ if (key === 'service') {
+ filter = query[key]
+ }
+ })
+ if (filter !== null) {
+ this.filter = filter
+ this.search()
+ }
+ },
+ components: {
+ JsonEditor,
+ Search
+ }
}
</script>
-
-<style scoped>
-
-</style>
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 d67bd0c..98507b8 100644
--- a/dubbo-admin-frontend/src/router/index.js
+++ b/dubbo-admin-frontend/src/router/index.js
@@ -19,6 +19,8 @@
import Router from 'vue-router'
import ServiceSearch from '@/components/ServiceSearch'
import ServiceDetail from '@/components/ServiceDetail'
+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'
@@ -44,6 +46,16 @@
component: ServiceDetail
},
{
+ path: '/test',
+ name: 'ServiceTest',
+ component: ServiceTest
+ },
+ {
+ path: '/testMethod',
+ name: 'TestMethod',
+ component: TestMethod
+ },
+ {
path: '/governance/routingRule',
name: 'RoutingRule',
component: RoutingRule
diff --git a/pom.xml b/pom.xml
index c8e8b0c..ee4d1b0 100644
--- a/pom.xml
+++ b/pom.xml
@@ -103,6 +103,17 @@
<version>${curator-version}</version>
</dependency>
<dependency>
+ <groupId>org.apache.curator</groupId>
+ <artifactId>curator-recipes</artifactId>
+ <version>${curator-version}</version>
+ <exclusions>
+ <exclusion>
+ <groupId>org.apache.zookeeper</groupId>
+ <artifactId>zookeeper</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>${fastjson-version}</version>