diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/tag/TagRouterTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/tag/TagRouterTest.java index 839af44efe9..a3ba0924013 100644 --- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/tag/TagRouterTest.java +++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/tag/TagRouterTest.java @@ -26,8 +26,8 @@ import org.apache.dubbo.rpc.cluster.Router; import org.apache.dubbo.rpc.cluster.RouterFactory; import org.apache.dubbo.rpc.cluster.router.MockInvoker; +import org.junit.After; import org.junit.Assert; -import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; @@ -47,8 +47,9 @@ public class TagRouterTest { public static void setUpBeforeClass() throws Exception { } - @Before - public void setUp() throws Exception { + @After + public void teardown() throws Exception { + RpcContext.getContext().clearAttachments(); } @Test diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/AbstractClusterInvokerTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/AbstractClusterInvokerTest.java index 247a719ad84..11efefe9b2d 100644 --- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/AbstractClusterInvokerTest.java +++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/AbstractClusterInvokerTest.java @@ -34,6 +34,7 @@ import org.apache.dubbo.rpc.cluster.loadbalance.RandomLoadBalance; import org.apache.dubbo.rpc.cluster.loadbalance.RoundRobinLoadBalance; +import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.BeforeClass; @@ -74,6 +75,11 @@ public class AbstractClusterInvokerTest { public static void setUpBeforeClass() throws Exception { } + @After + public void teardown() throws Exception { + RpcContext.getContext().clearAttachments(); + } + @SuppressWarnings({"unchecked"}) @Before public void setUp() throws Exception { diff --git a/dubbo-compatible/src/test/java/org/apache/dubbo/config/MethodConfigTest.java b/dubbo-compatible/src/test/java/org/apache/dubbo/config/MethodConfigTest.java index a7c5e99a03c..e7e0601e2b3 100644 --- a/dubbo-compatible/src/test/java/org/apache/dubbo/config/MethodConfigTest.java +++ b/dubbo-compatible/src/test/java/org/apache/dubbo/config/MethodConfigTest.java @@ -20,6 +20,9 @@ import com.alibaba.dubbo.common.Constants; import com.alibaba.dubbo.config.MethodConfig; import com.alibaba.dubbo.config.ArgumentConfig; + +import org.apache.dubbo.rpc.model.ConsumerMethodModel; +import org.apache.dubbo.service.Person; import org.hamcrest.Matchers; import org.junit.Test; @@ -34,6 +37,7 @@ import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.not; import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; public class MethodConfigTest { @Test @@ -97,12 +101,23 @@ public void testSticky() throws Exception { assertThat(method.getSticky(), is(true)); } + @Test + public void testConverMethodConfig2AsyncInfo() throws Exception{ + org.apache.dubbo.config.MethodConfig methodConfig = new org.apache.dubbo.config.MethodConfig(); + methodConfig.setOninvokeMethod("setName"); + methodConfig.setOninvoke(new Person()); + + ConsumerMethodModel.AsyncMethodInfo methodInfo = org.apache.dubbo.config.MethodConfig.convertMethodConfig2AyncInfo(methodConfig); + + assertTrue(methodInfo.getOninvokeMethod().equals( Person.class.getMethod("setName", String.class))); + } + @Test public void testOnreturn() throws Exception { MethodConfig method = new MethodConfig(); method.setOnreturn("on-return-object"); assertThat(method.getOnreturn(), equalTo((Object) "on-return-object")); - Map attribute = new HashMap(); + Map attribute = new HashMap(); MethodConfig.appendAttributes(attribute, method); assertThat(attribute, hasEntry((Object) Constants.ON_RETURN_INSTANCE_KEY, (Object) "on-return-object")); Map parameters = new HashMap(); @@ -115,7 +130,7 @@ public void testOnreturnMethod() throws Exception { MethodConfig method = new MethodConfig(); method.setOnreturnMethod("on-return-method"); assertThat(method.getOnreturnMethod(), equalTo("on-return-method")); - Map attribute = new HashMap(); + Map attribute = new HashMap(); MethodConfig.appendAttributes(attribute, method); assertThat(attribute, hasEntry((Object) Constants.ON_RETURN_METHOD_KEY, (Object) "on-return-method")); Map parameters = new HashMap(); @@ -128,7 +143,7 @@ public void testOnthrow() throws Exception { MethodConfig method = new MethodConfig(); method.setOnthrow("on-throw-object"); assertThat(method.getOnthrow(), equalTo((Object) "on-throw-object")); - Map attribute = new HashMap(); + Map attribute = new HashMap(); MethodConfig.appendAttributes(attribute, method); assertThat(attribute, hasEntry((Object) Constants.ON_THROW_INSTANCE_KEY, (Object) "on-throw-object")); Map parameters = new HashMap(); @@ -141,7 +156,7 @@ public void testOnthrowMethod() throws Exception { MethodConfig method = new MethodConfig(); method.setOnthrowMethod("on-throw-method"); assertThat(method.getOnthrowMethod(), equalTo("on-throw-method")); - Map attribute = new HashMap(); + Map attribute = new HashMap(); MethodConfig.appendAttributes(attribute, method); assertThat(attribute, hasEntry((Object) Constants.ON_THROW_METHOD_KEY, (Object) "on-throw-method")); Map parameters = new HashMap(); @@ -154,7 +169,7 @@ public void testOninvoke() throws Exception { MethodConfig method = new MethodConfig(); method.setOninvoke("on-invoke-object"); assertThat(method.getOninvoke(), equalTo((Object) "on-invoke-object")); - Map attribute = new HashMap(); + Map attribute = new HashMap(); MethodConfig.appendAttributes(attribute, method); assertThat(attribute, hasEntry((Object) Constants.ON_INVOKE_INSTANCE_KEY, (Object) "on-invoke-object")); Map parameters = new HashMap(); @@ -167,7 +182,7 @@ public void testOninvokeMethod() throws Exception { MethodConfig method = new MethodConfig(); method.setOninvokeMethod("on-invoke-method"); assertThat(method.getOninvokeMethod(), equalTo("on-invoke-method")); - Map attribute = new HashMap(); + Map attribute = new HashMap(); MethodConfig.appendAttributes(attribute, method); assertThat(attribute, hasEntry((Object) Constants.ON_INVOKE_METHOD_KEY, (Object) "on-invoke-method")); Map parameters = new HashMap(); diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractConfig.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractConfig.java index a5a1270ae31..fdaa3b16a1c 100644 --- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractConfig.java +++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractConfig.java @@ -1,487 +1,534 @@ -/* - * 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.config; - -import org.apache.dubbo.common.Constants; -import org.apache.dubbo.common.URL; -import org.apache.dubbo.common.extension.ExtensionLoader; -import org.apache.dubbo.common.logger.Logger; -import org.apache.dubbo.common.logger.LoggerFactory; -import org.apache.dubbo.common.utils.CollectionUtils; -import org.apache.dubbo.common.utils.ConfigUtils; -import org.apache.dubbo.common.utils.ReflectUtils; -import org.apache.dubbo.common.utils.StringUtils; -import org.apache.dubbo.config.support.Parameter; - -import java.io.Serializable; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.util.HashMap; -import java.util.Map; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * Utility methods and public methods for parsing configuration - * - * @export - */ -public abstract class AbstractConfig implements Serializable { - - protected static final Logger logger = LoggerFactory.getLogger(AbstractConfig.class); - private static final long serialVersionUID = 4267533505537413570L; - private static final int MAX_LENGTH = 200; - - private static final int MAX_PATH_LENGTH = 200; - - private static final Pattern PATTERN_NAME = Pattern.compile("[\\-._0-9a-zA-Z]+"); - - private static final Pattern PATTERN_MULTI_NAME = Pattern.compile("[,\\-._0-9a-zA-Z]+"); - - private static final Pattern PATTERN_METHOD_NAME = Pattern.compile("[a-zA-Z][0-9a-zA-Z]*"); - - private static final Pattern PATTERN_PATH = Pattern.compile("[/\\-$._0-9a-zA-Z]+"); - - private static final Pattern PATTERN_NAME_HAS_SYMBOL = Pattern.compile("[:*,/\\-._0-9a-zA-Z]+"); - - private static final Pattern PATTERN_KEY = Pattern.compile("[*,\\-._0-9a-zA-Z]+"); - private static final Map legacyProperties = new HashMap(); - private static final String[] SUFFIXES = new String[]{"Config", "Bean"}; - - static { - legacyProperties.put("dubbo.protocol.name", "dubbo.service.protocol"); - legacyProperties.put("dubbo.protocol.host", "dubbo.service.server.host"); - legacyProperties.put("dubbo.protocol.port", "dubbo.service.server.port"); - legacyProperties.put("dubbo.protocol.threads", "dubbo.service.max.thread.pool.size"); - legacyProperties.put("dubbo.consumer.timeout", "dubbo.service.invoke.timeout"); - legacyProperties.put("dubbo.consumer.retries", "dubbo.service.max.retry.providers"); - legacyProperties.put("dubbo.consumer.check", "dubbo.service.allow.no.provider"); - legacyProperties.put("dubbo.service.url", "dubbo.service.address"); - - // this is only for compatibility - Runtime.getRuntime().addShutdownHook(DubboShutdownHook.getDubboShutdownHook()); - } - - protected String id; - - private static String convertLegacyValue(String key, String value) { - if (value != null && value.length() > 0) { - if ("dubbo.service.max.retry.providers".equals(key)) { - return String.valueOf(Integer.parseInt(value) - 1); - } else if ("dubbo.service.allow.no.provider".equals(key)) { - return String.valueOf(!Boolean.parseBoolean(value)); - } - } - return value; - } - - protected static void appendProperties(AbstractConfig config) { - if (config == null) { - return; - } - String prefix = "dubbo." + getTagName(config.getClass()) + "."; - Method[] methods = config.getClass().getMethods(); - for (Method method : methods) { - try { - String name = method.getName(); - if (name.length() > 3 && name.startsWith("set") && Modifier.isPublic(method.getModifiers()) - && method.getParameterTypes().length == 1 && isPrimitive(method.getParameterTypes()[0])) { - String property = StringUtils.camelToSplitName(name.substring(3, 4).toLowerCase() + name.substring(4), "."); - - String value = null; - if (config.getId() != null && config.getId().length() > 0) { - String pn = prefix + config.getId() + "." + property; - value = System.getProperty(pn); - if (!StringUtils.isBlank(value)) { - logger.info("Use System Property " + pn + " to config dubbo"); - } - } - if (value == null || value.length() == 0) { - String pn = prefix + property; - value = System.getProperty(pn); - if (!StringUtils.isBlank(value)) { - logger.info("Use System Property " + pn + " to config dubbo"); - } - } - if (value == null || value.length() == 0) { - Method getter; - try { - getter = config.getClass().getMethod("get" + name.substring(3)); - } catch (NoSuchMethodException e) { - try { - getter = config.getClass().getMethod("is" + name.substring(3)); - } catch (NoSuchMethodException e2) { - getter = null; - } - } - if (getter != null) { - if (getter.invoke(config) == null) { - if (config.getId() != null && config.getId().length() > 0) { - value = ConfigUtils.getProperty(prefix + config.getId() + "." + property); - } - if (value == null || value.length() == 0) { - value = ConfigUtils.getProperty(prefix + property); - } - if (value == null || value.length() == 0) { - String legacyKey = legacyProperties.get(prefix + property); - if (legacyKey != null && legacyKey.length() > 0) { - value = convertLegacyValue(legacyKey, ConfigUtils.getProperty(legacyKey)); - } - } - - } - } - } - if (value != null && value.length() > 0) { - method.invoke(config, convertPrimitive(method.getParameterTypes()[0], value)); - } - } - } catch (Exception e) { - logger.error(e.getMessage(), e); - } - } - } - - private static String getTagName(Class cls) { - String tag = cls.getSimpleName(); - for (String suffix : SUFFIXES) { - if (tag.endsWith(suffix)) { - tag = tag.substring(0, tag.length() - suffix.length()); - break; - } - } - tag = tag.toLowerCase(); - return tag; - } - - protected static void appendParameters(Map parameters, Object config) { - appendParameters(parameters, config, null); - } - - @SuppressWarnings("unchecked") - protected static void appendParameters(Map parameters, Object config, String prefix) { - if (config == null) { - return; - } - Method[] methods = config.getClass().getMethods(); - for (Method method : methods) { - try { - String name = method.getName(); - if ((name.startsWith("get") || name.startsWith("is")) - && !"getClass".equals(name) - && Modifier.isPublic(method.getModifiers()) - && method.getParameterTypes().length == 0 - && isPrimitive(method.getReturnType())) { - Parameter parameter = method.getAnnotation(Parameter.class); - if (method.getReturnType() == Object.class || parameter != null && parameter.excluded()) { - continue; - } - int i = name.startsWith("get") ? 3 : 2; - String prop = StringUtils.camelToSplitName(name.substring(i, i + 1).toLowerCase() + name.substring(i + 1), "."); - String key; - if (parameter != null && parameter.key().length() > 0) { - key = parameter.key(); - } else { - key = prop; - } - Object value = method.invoke(config); - String str = String.valueOf(value).trim(); - if (value != null && str.length() > 0) { - if (parameter != null && parameter.escaped()) { - str = URL.encode(str); - } - if (parameter != null && parameter.append()) { - String pre = parameters.get(Constants.DEFAULT_KEY + "." + key); - if (pre != null && pre.length() > 0) { - str = pre + "," + str; - } - pre = parameters.get(key); - if (pre != null && pre.length() > 0) { - str = pre + "," + str; - } - } - if (prefix != null && prefix.length() > 0) { - key = prefix + "." + key; - } - parameters.put(key, str); - } else if (parameter != null && parameter.required()) { - throw new IllegalStateException(config.getClass().getSimpleName() + "." + key + " == null"); - } - } else if ("getParameters".equals(name) - && Modifier.isPublic(method.getModifiers()) - && method.getParameterTypes().length == 0 - && method.getReturnType() == Map.class) { - Map map = (Map) method.invoke(config, new Object[0]); - if (map != null && map.size() > 0) { - String pre = (prefix != null && prefix.length() > 0 ? prefix + "." : ""); - for (Map.Entry entry : map.entrySet()) { - parameters.put(pre + entry.getKey().replace('-', '.'), entry.getValue()); - } - } - } - } catch (Exception e) { - throw new IllegalStateException(e.getMessage(), e); - } - } - } - - protected static void appendAttributes(Map parameters, Object config) { - appendAttributes(parameters, config, null); - } - - protected static void appendAttributes(Map parameters, Object config, String prefix) { - if (config == null) { - return; - } - Method[] methods = config.getClass().getMethods(); - for (Method method : methods) { - try { - String name = method.getName(); - if ((name.startsWith("get") || name.startsWith("is")) - && !"getClass".equals(name) - && Modifier.isPublic(method.getModifiers()) - && method.getParameterTypes().length == 0 - && isPrimitive(method.getReturnType())) { - Parameter parameter = method.getAnnotation(Parameter.class); - if (parameter == null || !parameter.attribute()) { - continue; - } - String key; - if (parameter.key().length() > 0) { - key = parameter.key(); - } else { - int i = name.startsWith("get") ? 3 : 2; - key = name.substring(i, i + 1).toLowerCase() + name.substring(i + 1); - } - Object value = method.invoke(config); - if (value != null) { - if (prefix != null && prefix.length() > 0) { - key = prefix + "." + key; - } - parameters.put(key, value); - } - } - } catch (Exception e) { - throw new IllegalStateException(e.getMessage(), e); - } - } - } - - private static boolean isPrimitive(Class type) { - return type.isPrimitive() - || type == String.class - || type == Character.class - || type == Boolean.class - || type == Byte.class - || type == Short.class - || type == Integer.class - || type == Long.class - || type == Float.class - || type == Double.class - || type == Object.class; - } - - private static Object convertPrimitive(Class type, String value) { - if (type == char.class || type == Character.class) { - return value.length() > 0 ? value.charAt(0) : '\0'; - } else if (type == boolean.class || type == Boolean.class) { - return Boolean.valueOf(value); - } else if (type == byte.class || type == Byte.class) { - return Byte.valueOf(value); - } else if (type == short.class || type == Short.class) { - return Short.valueOf(value); - } else if (type == int.class || type == Integer.class) { - return Integer.valueOf(value); - } else if (type == long.class || type == Long.class) { - return Long.valueOf(value); - } else if (type == float.class || type == Float.class) { - return Float.valueOf(value); - } else if (type == double.class || type == Double.class) { - return Double.valueOf(value); - } - return value; - } - - protected static void checkExtension(Class type, String property, String value) { - checkName(property, value); - if (value != null && value.length() > 0 - && !ExtensionLoader.getExtensionLoader(type).hasExtension(value)) { - throw new IllegalStateException("No such extension " + value + " for " + property + "/" + type.getName()); - } - } - - protected static void checkMultiExtension(Class type, String property, String value) { - checkMultiName(property, value); - if (value != null && value.length() > 0) { - String[] values = value.split("\\s*[,]+\\s*"); - for (String v : values) { - if (v.startsWith(Constants.REMOVE_VALUE_PREFIX)) { - v = v.substring(1); - } - if (Constants.DEFAULT_KEY.equals(v)) { - continue; - } - if (!ExtensionLoader.getExtensionLoader(type).hasExtension(v)) { - throw new IllegalStateException("No such extension " + v + " for " + property + "/" + type.getName()); - } - } - } - } - - protected static void checkLength(String property, String value) { - checkProperty(property, value, MAX_LENGTH, null); - } - - protected static void checkPathLength(String property, String value) { - checkProperty(property, value, MAX_PATH_LENGTH, null); - } - - protected static void checkName(String property, String value) { - checkProperty(property, value, MAX_LENGTH, PATTERN_NAME); - } - - protected static void checkNameHasSymbol(String property, String value) { - checkProperty(property, value, MAX_LENGTH, PATTERN_NAME_HAS_SYMBOL); - } - - protected static void checkKey(String property, String value) { - checkProperty(property, value, MAX_LENGTH, PATTERN_KEY); - } - - protected static void checkMultiName(String property, String value) { - checkProperty(property, value, MAX_LENGTH, PATTERN_MULTI_NAME); - } - - protected static void checkPathName(String property, String value) { - checkProperty(property, value, MAX_PATH_LENGTH, PATTERN_PATH); - } - - protected static void checkMethodName(String property, String value) { - checkProperty(property, value, MAX_LENGTH, PATTERN_METHOD_NAME); - } - - protected static void checkParameterName(Map parameters) { - if (parameters == null || parameters.size() == 0) { - return; - } - for (Map.Entry entry : parameters.entrySet()) { - checkNameHasSymbol(entry.getKey(), entry.getValue()); - } - } - - protected static void checkProperty(String property, String value, int maxlength, Pattern pattern) { - if (value == null || value.length() == 0) { - return; - } - if (value.length() > maxlength) { - throw new IllegalStateException("Invalid " + property + "=\"" + value + "\" is longer than " + maxlength); - } - if (pattern != null) { - Matcher matcher = pattern.matcher(value); - if (!matcher.matches()) { - throw new IllegalStateException("Invalid " + property + "=\"" + value + "\" contains illegal " + - "character, only digit, letter, '-', '_' or '.' is legal."); - } - } - } - - @Parameter(excluded = true) - public String getId() { - return id; - } - - public void setId(String id) { - this.id = id; - } - - protected void appendAnnotation(Class annotationClass, Object annotation) { - Method[] methods = annotationClass.getMethods(); - for (Method method : methods) { - if (method.getDeclaringClass() != Object.class - && method.getReturnType() != void.class - && method.getParameterTypes().length == 0 - && Modifier.isPublic(method.getModifiers()) - && !Modifier.isStatic(method.getModifiers())) { - try { - String property = method.getName(); - if ("interfaceClass".equals(property) || "interfaceName".equals(property)) { - property = "interface"; - } - String setter = "set" + property.substring(0, 1).toUpperCase() + property.substring(1); - Object value = method.invoke(annotation); - if (value != null && !value.equals(method.getDefaultValue())) { - Class parameterType = ReflectUtils.getBoxedClass(method.getReturnType()); - if ("filter".equals(property) || "listener".equals(property)) { - parameterType = String.class; - value = StringUtils.join((String[]) value, ","); - } else if ("parameters".equals(property)) { - parameterType = Map.class; - value = CollectionUtils.toStringMap((String[]) value); - } - try { - Method setterMethod = getClass().getMethod(setter, parameterType); - setterMethod.invoke(this, value); - } catch (NoSuchMethodException e) { - // ignore - } - } - } catch (Throwable e) { - logger.error(e.getMessage(), e); - } - } - } - } - - @Override - public String toString() { - try { - StringBuilder buf = new StringBuilder(); - buf.append(""); - return buf.toString(); - } catch (Throwable t) { - logger.warn(t.getMessage(), t); - return super.toString(); - } - } - -} +/* + * 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.config; + +import org.apache.dubbo.common.Constants; +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.extension.ExtensionLoader; +import org.apache.dubbo.common.logger.Logger; +import org.apache.dubbo.common.logger.LoggerFactory; +import org.apache.dubbo.common.utils.CollectionUtils; +import org.apache.dubbo.common.utils.ConfigUtils; +import org.apache.dubbo.common.utils.ReflectUtils; +import org.apache.dubbo.common.utils.StringUtils; +import org.apache.dubbo.config.support.Parameter; +import org.apache.dubbo.rpc.model.ConsumerMethodModel; + +import java.io.Serializable; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.HashMap; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Utility methods and public methods for parsing configuration + * + * @export + */ +public abstract class AbstractConfig implements Serializable { + + protected static final Logger logger = LoggerFactory.getLogger(AbstractConfig.class); + private static final long serialVersionUID = 4267533505537413570L; + private static final int MAX_LENGTH = 200; + + private static final int MAX_PATH_LENGTH = 200; + + private static final Pattern PATTERN_NAME = Pattern.compile("[\\-._0-9a-zA-Z]+"); + + private static final Pattern PATTERN_MULTI_NAME = Pattern.compile("[,\\-._0-9a-zA-Z]+"); + + private static final Pattern PATTERN_METHOD_NAME = Pattern.compile("[a-zA-Z][0-9a-zA-Z]*"); + + private static final Pattern PATTERN_PATH = Pattern.compile("[/\\-$._0-9a-zA-Z]+"); + + private static final Pattern PATTERN_NAME_HAS_SYMBOL = Pattern.compile("[:*,/\\-._0-9a-zA-Z]+"); + + private static final Pattern PATTERN_KEY = Pattern.compile("[*,\\-._0-9a-zA-Z]+"); + private static final Map legacyProperties = new HashMap(); + private static final String[] SUFFIXES = new String[]{"Config", "Bean"}; + + static { + legacyProperties.put("dubbo.protocol.name", "dubbo.service.protocol"); + legacyProperties.put("dubbo.protocol.host", "dubbo.service.server.host"); + legacyProperties.put("dubbo.protocol.port", "dubbo.service.server.port"); + legacyProperties.put("dubbo.protocol.threads", "dubbo.service.max.thread.pool.size"); + legacyProperties.put("dubbo.consumer.timeout", "dubbo.service.invoke.timeout"); + legacyProperties.put("dubbo.consumer.retries", "dubbo.service.max.retry.providers"); + legacyProperties.put("dubbo.consumer.check", "dubbo.service.allow.no.provider"); + legacyProperties.put("dubbo.service.url", "dubbo.service.address"); + + // this is only for compatibility + Runtime.getRuntime().addShutdownHook(DubboShutdownHook.getDubboShutdownHook()); + } + + protected String id; + + private static String convertLegacyValue(String key, String value) { + if (value != null && value.length() > 0) { + if ("dubbo.service.max.retry.providers".equals(key)) { + return String.valueOf(Integer.parseInt(value) - 1); + } else if ("dubbo.service.allow.no.provider".equals(key)) { + return String.valueOf(!Boolean.parseBoolean(value)); + } + } + return value; + } + + protected static void appendProperties(AbstractConfig config) { + if (config == null) { + return; + } + String prefix = "dubbo." + getTagName(config.getClass()) + "."; + Method[] methods = config.getClass().getMethods(); + for (Method method : methods) { + try { + String name = method.getName(); + if (name.length() > 3 && name.startsWith("set") && Modifier.isPublic(method.getModifiers()) + && method.getParameterTypes().length == 1 && isPrimitive(method.getParameterTypes()[0])) { + String property = StringUtils.camelToSplitName(name.substring(3, 4).toLowerCase() + name.substring(4), "."); + + String value = null; + if (config.getId() != null && config.getId().length() > 0) { + String pn = prefix + config.getId() + "." + property; + value = System.getProperty(pn); + if (!StringUtils.isBlank(value)) { + logger.info("Use System Property " + pn + " to config dubbo"); + } + } + if (value == null || value.length() == 0) { + String pn = prefix + property; + value = System.getProperty(pn); + if (!StringUtils.isBlank(value)) { + logger.info("Use System Property " + pn + " to config dubbo"); + } + } + if (value == null || value.length() == 0) { + Method getter; + try { + getter = config.getClass().getMethod("get" + name.substring(3)); + } catch (NoSuchMethodException e) { + try { + getter = config.getClass().getMethod("is" + name.substring(3)); + } catch (NoSuchMethodException e2) { + getter = null; + } + } + if (getter != null) { + if (getter.invoke(config) == null) { + if (config.getId() != null && config.getId().length() > 0) { + value = ConfigUtils.getProperty(prefix + config.getId() + "." + property); + } + if (value == null || value.length() == 0) { + value = ConfigUtils.getProperty(prefix + property); + } + if (value == null || value.length() == 0) { + String legacyKey = legacyProperties.get(prefix + property); + if (legacyKey != null && legacyKey.length() > 0) { + value = convertLegacyValue(legacyKey, ConfigUtils.getProperty(legacyKey)); + } + } + + } + } + } + if (value != null && value.length() > 0) { + method.invoke(config, convertPrimitive(method.getParameterTypes()[0], value)); + } + } + } catch (Exception e) { + logger.error(e.getMessage(), e); + } + } + } + + private static String getTagName(Class cls) { + String tag = cls.getSimpleName(); + for (String suffix : SUFFIXES) { + if (tag.endsWith(suffix)) { + tag = tag.substring(0, tag.length() - suffix.length()); + break; + } + } + tag = tag.toLowerCase(); + return tag; + } + + protected static void appendParameters(Map parameters, Object config) { + appendParameters(parameters, config, null); + } + + @SuppressWarnings("unchecked") + protected static void appendParameters(Map parameters, Object config, String prefix) { + if (config == null) { + return; + } + Method[] methods = config.getClass().getMethods(); + for (Method method : methods) { + try { + String name = method.getName(); + if ((name.startsWith("get") || name.startsWith("is")) + && !"getClass".equals(name) + && Modifier.isPublic(method.getModifiers()) + && method.getParameterTypes().length == 0 + && isPrimitive(method.getReturnType())) { + Parameter parameter = method.getAnnotation(Parameter.class); + if (method.getReturnType() == Object.class || parameter != null && parameter.excluded()) { + continue; + } + int i = name.startsWith("get") ? 3 : 2; + String prop = StringUtils.camelToSplitName(name.substring(i, i + 1).toLowerCase() + name.substring(i + 1), "."); + String key; + if (parameter != null && parameter.key().length() > 0) { + key = parameter.key(); + } else { + key = prop; + } + Object value = method.invoke(config); + String str = String.valueOf(value).trim(); + if (value != null && str.length() > 0) { + if (parameter != null && parameter.escaped()) { + str = URL.encode(str); + } + if (parameter != null && parameter.append()) { + String pre = parameters.get(Constants.DEFAULT_KEY + "." + key); + if (pre != null && pre.length() > 0) { + str = pre + "," + str; + } + pre = parameters.get(key); + if (pre != null && pre.length() > 0) { + str = pre + "," + str; + } + } + if (prefix != null && prefix.length() > 0) { + key = prefix + "." + key; + } + parameters.put(key, str); + } else if (parameter != null && parameter.required()) { + throw new IllegalStateException(config.getClass().getSimpleName() + "." + key + " == null"); + } + } else if ("getParameters".equals(name) + && Modifier.isPublic(method.getModifiers()) + && method.getParameterTypes().length == 0 + && method.getReturnType() == Map.class) { + Map map = (Map) method.invoke(config, new Object[0]); + if (map != null && map.size() > 0) { + String pre = (prefix != null && prefix.length() > 0 ? prefix + "." : ""); + for (Map.Entry entry : map.entrySet()) { + parameters.put(pre + entry.getKey().replace('-', '.'), entry.getValue()); + } + } + } + } catch (Exception e) { + throw new IllegalStateException(e.getMessage(), e); + } + } + } + + protected static void appendAttributes(Map parameters, Object config) { + appendAttributes(parameters, config, null); + } + + protected static void appendAttributes(Map parameters, Object config, String prefix) { + if (config == null) { + return; + } + Method[] methods = config.getClass().getMethods(); + for (Method method : methods) { + try { + Parameter parameter = method.getAnnotation(Parameter.class); + if (parameter == null || !parameter.attribute()) { + continue; + } + String name = method.getName(); + if ((name.startsWith("get") || name.startsWith("is")) + && !"getClass".equals(name) + && Modifier.isPublic(method.getModifiers()) + && method.getParameterTypes().length == 0 + && isPrimitive(method.getReturnType())) { + String key; + if (parameter.key().length() > 0) { + key = parameter.key(); + } else { + int i = name.startsWith("get") ? 3 : 2; + key = name.substring(i, i + 1).toLowerCase() + name.substring(i + 1); + } + Object value = method.invoke(config); + if (value != null) { + if (prefix != null && prefix.length() > 0) { + key = prefix + "." + key; + } + parameters.put(key, value); + } + } + } catch (Exception e) { + throw new IllegalStateException(e.getMessage(), e); + } + } + } + + protected static ConsumerMethodModel.AsyncMethodInfo convertMethodConfig2AyncInfo(MethodConfig methodConfig) { + if (methodConfig == null || (methodConfig.getOninvoke() == null && methodConfig.getOnreturn() == null && methodConfig.getOnthrow() == null)) { + return null; + } + + //check config conflict + if (Boolean.FALSE.equals(methodConfig.isReturn()) && (methodConfig.getOnreturn() != null || methodConfig.getOnthrow() != null)) { + throw new IllegalStateException("method config error : return attribute must be set true when onreturn or onthrow has been set."); + } + + ConsumerMethodModel.AsyncMethodInfo asyncMethodInfo = new ConsumerMethodModel.AsyncMethodInfo(); + + asyncMethodInfo.setOninvokeInstance(methodConfig.getOninvoke()); + asyncMethodInfo.setOnreturnInstance(methodConfig.getOnreturn()); + asyncMethodInfo.setOnthrowInstance(methodConfig.getOnthrow()); + + try { + String oninvokeMethod = methodConfig.getOninvokeMethod(); + if (StringUtils.isNotEmpty(oninvokeMethod)) { + asyncMethodInfo.setOninvokeMethod(getMethodByName(methodConfig.getOninvoke().getClass(), oninvokeMethod)); + } + + String onreturnMethod = methodConfig.getOnreturnMethod(); + if (StringUtils.isNotEmpty(onreturnMethod)) { + asyncMethodInfo.setOnreturnMethod(getMethodByName(methodConfig.getOnreturn().getClass(), onreturnMethod)); + } + + String onthrowMethod = methodConfig.getOnthrowMethod(); + if (StringUtils.isNotEmpty(onthrowMethod)) { + asyncMethodInfo.setOnthrowMethod(getMethodByName(methodConfig.getOnthrow().getClass(), onthrowMethod)); + } + } catch (Exception e) { + throw new IllegalStateException(e.getMessage(), e); + } + + return asyncMethodInfo; + } + + private static Method getMethodByName(Class clazz, String methodName) { + try { + return ReflectUtils.findMethodByMethodName(clazz, methodName); + } catch (Exception e) { + throw new IllegalStateException(e); + } + } + + private static boolean isPrimitive(Class type) { + return type.isPrimitive() + || type == String.class + || type == Character.class + || type == Boolean.class + || type == Byte.class + || type == Short.class + || type == Integer.class + || type == Long.class + || type == Float.class + || type == Double.class + || type == Object.class; + } + + private static Object convertPrimitive(Class type, String value) { + if (type == char.class || type == Character.class) { + return value.length() > 0 ? value.charAt(0) : '\0'; + } else if (type == boolean.class || type == Boolean.class) { + return Boolean.valueOf(value); + } else if (type == byte.class || type == Byte.class) { + return Byte.valueOf(value); + } else if (type == short.class || type == Short.class) { + return Short.valueOf(value); + } else if (type == int.class || type == Integer.class) { + return Integer.valueOf(value); + } else if (type == long.class || type == Long.class) { + return Long.valueOf(value); + } else if (type == float.class || type == Float.class) { + return Float.valueOf(value); + } else if (type == double.class || type == Double.class) { + return Double.valueOf(value); + } + return value; + } + + protected static void checkExtension(Class type, String property, String value) { + checkName(property, value); + if (value != null && value.length() > 0 + && !ExtensionLoader.getExtensionLoader(type).hasExtension(value)) { + throw new IllegalStateException("No such extension " + value + " for " + property + "/" + type.getName()); + } + } + + protected static void checkMultiExtension(Class type, String property, String value) { + checkMultiName(property, value); + if (value != null && value.length() > 0) { + String[] values = value.split("\\s*[,]+\\s*"); + for (String v : values) { + if (v.startsWith(Constants.REMOVE_VALUE_PREFIX)) { + v = v.substring(1); + } + if (Constants.DEFAULT_KEY.equals(v)) { + continue; + } + if (!ExtensionLoader.getExtensionLoader(type).hasExtension(v)) { + throw new IllegalStateException("No such extension " + v + " for " + property + "/" + type.getName()); + } + } + } + } + + protected static void checkLength(String property, String value) { + checkProperty(property, value, MAX_LENGTH, null); + } + + protected static void checkPathLength(String property, String value) { + checkProperty(property, value, MAX_PATH_LENGTH, null); + } + + protected static void checkName(String property, String value) { + checkProperty(property, value, MAX_LENGTH, PATTERN_NAME); + } + + protected static void checkNameHasSymbol(String property, String value) { + checkProperty(property, value, MAX_LENGTH, PATTERN_NAME_HAS_SYMBOL); + } + + protected static void checkKey(String property, String value) { + checkProperty(property, value, MAX_LENGTH, PATTERN_KEY); + } + + protected static void checkMultiName(String property, String value) { + checkProperty(property, value, MAX_LENGTH, PATTERN_MULTI_NAME); + } + + protected static void checkPathName(String property, String value) { + checkProperty(property, value, MAX_PATH_LENGTH, PATTERN_PATH); + } + + protected static void checkMethodName(String property, String value) { + checkProperty(property, value, MAX_LENGTH, PATTERN_METHOD_NAME); + } + + protected static void checkParameterName(Map parameters) { + if (parameters == null || parameters.size() == 0) { + return; + } + for (Map.Entry entry : parameters.entrySet()) { + checkNameHasSymbol(entry.getKey(), entry.getValue()); + } + } + + protected static void checkProperty(String property, String value, int maxlength, Pattern pattern) { + if (value == null || value.length() == 0) { + return; + } + if (value.length() > maxlength) { + throw new IllegalStateException("Invalid " + property + "=\"" + value + "\" is longer than " + maxlength); + } + if (pattern != null) { + Matcher matcher = pattern.matcher(value); + if (!matcher.matches()) { + throw new IllegalStateException("Invalid " + property + "=\"" + value + "\" contains illegal " + + "character, only digit, letter, '-', '_' or '.' is legal."); + } + } + } + + @Parameter(excluded = true) + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + protected void appendAnnotation(Class annotationClass, Object annotation) { + Method[] methods = annotationClass.getMethods(); + for (Method method : methods) { + if (method.getDeclaringClass() != Object.class + && method.getReturnType() != void.class + && method.getParameterTypes().length == 0 + && Modifier.isPublic(method.getModifiers()) + && !Modifier.isStatic(method.getModifiers())) { + try { + String property = method.getName(); + if ("interfaceClass".equals(property) || "interfaceName".equals(property)) { + property = "interface"; + } + String setter = "set" + property.substring(0, 1).toUpperCase() + property.substring(1); + Object value = method.invoke(annotation); + if (value != null && !value.equals(method.getDefaultValue())) { + Class parameterType = ReflectUtils.getBoxedClass(method.getReturnType()); + if ("filter".equals(property) || "listener".equals(property)) { + parameterType = String.class; + value = StringUtils.join((String[]) value, ","); + } else if ("parameters".equals(property)) { + parameterType = Map.class; + value = CollectionUtils.toStringMap((String[]) value); + } + try { + Method setterMethod = getClass().getMethod(setter, parameterType); + setterMethod.invoke(this, value); + } catch (NoSuchMethodException e) { + // ignore + } + } + } catch (Throwable e) { + logger.error(e.getMessage(), e); + } + } + } + } + + @Override + public String toString() { + try { + StringBuilder buf = new StringBuilder(); + buf.append(""); + return buf.toString(); + } catch (Throwable t) { + logger.warn(t.getMessage(), t); + return super.toString(); + } + } + +} diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ReferenceConfig.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ReferenceConfig.java index f568700beae..61ed531e141 100644 --- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ReferenceConfig.java +++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ReferenceConfig.java @@ -24,14 +24,12 @@ import org.apache.dubbo.common.extension.ExtensionLoader; import org.apache.dubbo.common.utils.ConfigUtils; import org.apache.dubbo.common.utils.NetUtils; -import org.apache.dubbo.common.utils.ReflectUtils; import org.apache.dubbo.common.utils.StringUtils; import org.apache.dubbo.config.annotation.Reference; import org.apache.dubbo.config.support.Parameter; import org.apache.dubbo.rpc.Invoker; import org.apache.dubbo.rpc.Protocol; import org.apache.dubbo.rpc.ProxyFactory; -import org.apache.dubbo.rpc.StaticContext; import org.apache.dubbo.rpc.cluster.Cluster; import org.apache.dubbo.rpc.cluster.directory.StaticDirectory; import org.apache.dubbo.rpc.cluster.support.AvailableCluster; @@ -45,7 +43,6 @@ import java.io.File; import java.io.FileInputStream; import java.io.IOException; -import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; @@ -116,39 +113,6 @@ public ReferenceConfig(Reference reference) { appendAnnotation(Reference.class, reference); } - private static void checkAndConvertImplicitConfig(MethodConfig method, Map map, Map attributes) { - //check config conflict - if (Boolean.FALSE.equals(method.isReturn()) && (method.getOnreturn() != null || method.getOnthrow() != null)) { - throw new IllegalStateException("method config error : return attribute must be set true when onreturn or onthrow has been setted."); - } - //convert onreturn methodName to Method - String onReturnMethodKey = StaticContext.getKey(map, method.getName(), Constants.ON_RETURN_METHOD_KEY); - Object onReturnMethod = attributes.get(onReturnMethodKey); - if (onReturnMethod instanceof String) { - attributes.put(onReturnMethodKey, getMethodByName(method.getOnreturn().getClass(), onReturnMethod.toString())); - } - //convert onthrow methodName to Method - String onThrowMethodKey = StaticContext.getKey(map, method.getName(), Constants.ON_THROW_METHOD_KEY); - Object onThrowMethod = attributes.get(onThrowMethodKey); - if (onThrowMethod instanceof String) { - attributes.put(onThrowMethodKey, getMethodByName(method.getOnthrow().getClass(), onThrowMethod.toString())); - } - //convert oninvoke methodName to Method - String onInvokeMethodKey = StaticContext.getKey(map, method.getName(), Constants.ON_INVOKE_METHOD_KEY); - Object onInvokeMethod = attributes.get(onInvokeMethodKey); - if (onInvokeMethod instanceof String) { - attributes.put(onInvokeMethodKey, getMethodByName(method.getOninvoke().getClass(), onInvokeMethod.toString())); - } - } - - private static Method getMethodByName(Class clazz, String methodName) { - try { - return ReflectUtils.findMethodByMethodName(clazz, methodName); - } catch (Exception e) { - throw new IllegalStateException(e); - } - } - public URL toUrl() { return urls.isEmpty() ? null : urls.iterator().next(); } @@ -309,23 +273,20 @@ private void init() { appendParameters(map, module); appendParameters(map, consumer, Constants.DEFAULT_KEY); appendParameters(map, this); - String prefix = StringUtils.getServiceKey(map); + Map attributes = null; if (methods != null && !methods.isEmpty()) { - Map attributes = new HashMap(); - for (MethodConfig method : methods) { - appendParameters(map, method, method.getName()); - String retryKey = method.getName() + ".retry"; + attributes = new HashMap(); + for (MethodConfig methodConfig : methods) { + appendParameters(map, methodConfig, methodConfig.getName()); + String retryKey = methodConfig.getName() + ".retry"; if (map.containsKey(retryKey)) { String retryValue = map.remove(retryKey); if ("false".equals(retryValue)) { - map.put(method.getName() + ".retries", "0"); + map.put(methodConfig.getName() + ".retries", "0"); } } - appendAttributes(attributes, method, prefix + "." + method.getName()); - checkAndConvertImplicitConfig(method, map, attributes); + attributes.put(methodConfig.getName(), convertMethodConfig2AyncInfo(methodConfig)); } - //attributes are stored by system context. - StaticContext.getSystemContext().putAll(attributes); } String hostToRegistry = ConfigUtils.getSystemProperty(Constants.DUBBO_IP_TO_REGISTRY); @@ -337,7 +298,8 @@ private void init() { map.put(Constants.REGISTER_IP_KEY, hostToRegistry); ref = createProxy(map); - ConsumerModel consumerModel = new ConsumerModel(getUniqueServiceName(), ref, interfaceClass.getMethods()); + + ConsumerModel consumerModel = new ConsumerModel(getUniqueServiceName(), ref, interfaceClass.getMethods(), attributes); ApplicationModel.initConsumerModel(getUniqueServiceName(), consumerModel); } diff --git a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/AbstractConfigTest.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/AbstractConfigTest.java index ac231cbad72..ef7354dfd2b 100644 --- a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/AbstractConfigTest.java +++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/AbstractConfigTest.java @@ -141,7 +141,7 @@ public void testAppendParameters4() throws Exception { @Test public void testAppendAttributes1() throws Exception { - Map parameters = new HashMap(); + Map parameters = new HashMap(); AbstractConfig.appendAttributes(parameters, new AttributeConfig('l', true, (byte) 0x01), "prefix"); TestCase.assertEquals('l', parameters.get("prefix.let")); TestCase.assertEquals(true, parameters.get("prefix.activate")); @@ -150,7 +150,7 @@ public void testAppendAttributes1() throws Exception { @Test public void testAppendAttributes2() throws Exception { - Map parameters = new HashMap(); + Map parameters = new HashMap(); AbstractConfig.appendAttributes(parameters, new AttributeConfig('l', true, (byte) 0x01)); TestCase.assertEquals('l', parameters.get("let")); TestCase.assertEquals(true, parameters.get("activate")); diff --git a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/MethodConfigTest.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/MethodConfigTest.java index 2ca7ecc8dfd..8f7e8609ce7 100644 --- a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/MethodConfigTest.java +++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/MethodConfigTest.java @@ -100,7 +100,7 @@ public void testOnreturn() throws Exception { MethodConfig method = new MethodConfig(); method.setOnreturn("on-return-object"); assertThat(method.getOnreturn(), equalTo((Object) "on-return-object")); - Map attribute = new HashMap(); + Map attribute = new HashMap(); MethodConfig.appendAttributes(attribute, method); assertThat(attribute, hasEntry((Object) Constants.ON_RETURN_INSTANCE_KEY, (Object) "on-return-object")); Map parameters = new HashMap(); @@ -113,7 +113,7 @@ public void testOnreturnMethod() throws Exception { MethodConfig method = new MethodConfig(); method.setOnreturnMethod("on-return-method"); assertThat(method.getOnreturnMethod(), equalTo("on-return-method")); - Map attribute = new HashMap(); + Map attribute = new HashMap(); MethodConfig.appendAttributes(attribute, method); assertThat(attribute, hasEntry((Object) Constants.ON_RETURN_METHOD_KEY, (Object) "on-return-method")); Map parameters = new HashMap(); @@ -126,7 +126,7 @@ public void testOnthrow() throws Exception { MethodConfig method = new MethodConfig(); method.setOnthrow("on-throw-object"); assertThat(method.getOnthrow(), equalTo((Object) "on-throw-object")); - Map attribute = new HashMap(); + Map attribute = new HashMap(); MethodConfig.appendAttributes(attribute, method); assertThat(attribute, hasEntry((Object) Constants.ON_THROW_INSTANCE_KEY, (Object) "on-throw-object")); Map parameters = new HashMap(); @@ -139,7 +139,7 @@ public void testOnthrowMethod() throws Exception { MethodConfig method = new MethodConfig(); method.setOnthrowMethod("on-throw-method"); assertThat(method.getOnthrowMethod(), equalTo("on-throw-method")); - Map attribute = new HashMap(); + Map attribute = new HashMap(); MethodConfig.appendAttributes(attribute, method); assertThat(attribute, hasEntry((Object) Constants.ON_THROW_METHOD_KEY, (Object) "on-throw-method")); Map parameters = new HashMap(); @@ -152,7 +152,7 @@ public void testOninvoke() throws Exception { MethodConfig method = new MethodConfig(); method.setOninvoke("on-invoke-object"); assertThat(method.getOninvoke(), equalTo((Object) "on-invoke-object")); - Map attribute = new HashMap(); + Map attribute = new HashMap(); MethodConfig.appendAttributes(attribute, method); assertThat(attribute, hasEntry((Object) Constants.ON_INVOKE_INSTANCE_KEY, (Object) "on-invoke-object")); Map parameters = new HashMap(); @@ -165,7 +165,7 @@ public void testOninvokeMethod() throws Exception { MethodConfig method = new MethodConfig(); method.setOninvokeMethod("on-invoke-method"); assertThat(method.getOninvokeMethod(), equalTo("on-invoke-method")); - Map attribute = new HashMap(); + Map attribute = new HashMap(); MethodConfig.appendAttributes(attribute, method); assertThat(attribute, hasEntry((Object) Constants.ON_INVOKE_METHOD_KEY, (Object) "on-invoke-method")); Map parameters = new HashMap(); diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/StaticContext.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/StaticContext.java deleted file mode 100644 index 30caf571092..00000000000 --- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/StaticContext.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * 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.rpc; - -import org.apache.dubbo.common.URL; -import org.apache.dubbo.common.utils.StringUtils; - -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; - -/** - * System context, for internal use only - */ -public class StaticContext extends ConcurrentHashMap { - private static final long serialVersionUID = 1L; - private static final String SYSTEMNAME = "system"; - private static final ConcurrentMap context_map = new ConcurrentHashMap(); - private String name; - - private StaticContext(String name) { - super(); - this.name = name; - } - - public static StaticContext getSystemContext() { - return getContext(SYSTEMNAME); - } - - public static StaticContext getContext(String name) { - StaticContext appContext = context_map.get(name); - if (appContext == null) { - appContext = context_map.putIfAbsent(name, new StaticContext(name)); - if (appContext == null) { - appContext = context_map.get(name); - } - } - return appContext; - } - - public static StaticContext remove(String name) { - return context_map.remove(name); - } - - public static String getKey(URL url, String methodName, String suffix) { - return getKey(url.getServiceKey(), methodName, suffix); - } - - public static String getKey(Map paras, String methodName, String suffix) { - return getKey(StringUtils.getServiceKey(paras), methodName, suffix); - } - - private static String getKey(String servicekey, String methodName, String suffix) { - StringBuffer sb = new StringBuffer().append(servicekey).append(".").append(methodName).append(".").append(suffix); - return sb.toString(); - } - - public String getName() { - return name; - } -} \ No newline at end of file diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/model/ApplicationModel.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/model/ApplicationModel.java index 456930e5407..74a52d7c4c7 100644 --- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/model/ApplicationModel.java +++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/model/ApplicationModel.java @@ -23,7 +23,15 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; -// adjust project structure in order to fully utilize the methods introduced here. +/** + * Represent a application which is using Dubbo and store basic metadata info for using + * during the processing of RPC invoking. + * + * ApplicationModel includes many ProviderModel which is about published services + * and many Consumer Model which is about subscribed services. + * + * adjust project structure in order to fully utilize the methods introduced here. + */ public class ApplicationModel { protected static final Logger LOGGER = LoggerFactory.getLogger(ApplicationModel.class); diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/model/ConsumerMethodModel.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/model/ConsumerMethodModel.java index 96f55bee4b7..5a871cecc63 100644 --- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/model/ConsumerMethodModel.java +++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/model/ConsumerMethodModel.java @@ -19,6 +19,7 @@ import org.apache.dubbo.common.Constants; import java.lang.reflect.Method; +import java.util.Map; public class ConsumerMethodModel { private final Method method; @@ -30,13 +31,22 @@ public class ConsumerMethodModel { private final String methodName; private final boolean generic; - public ConsumerMethodModel(Method method) { + private final AsyncMethodInfo asyncInfo; + + + public ConsumerMethodModel(Method method, Map attributes) { this.method = method; this.parameterClasses = method.getParameterTypes(); this.returnClass = method.getReturnType(); this.parameterTypes = this.createParamSignature(parameterClasses); this.methodName = method.getName(); this.generic = methodName.equals(Constants.$INVOKE) && parameterTypes != null && parameterTypes.length == 3; + + if (attributes != null) { + asyncInfo = (AsyncMethodInfo) attributes.get(methodName); + } else { + asyncInfo = null; + } } public Method getMethod() { @@ -47,6 +57,9 @@ public Class getReturnClass() { return returnClass; } + public AsyncMethodInfo getAsyncInfo() { + return asyncInfo; + } public String getMethodName() { return methodName; @@ -75,4 +88,73 @@ public boolean isGeneric() { public Class[] getParameterClasses() { return parameterClasses; } + + + public static class AsyncMethodInfo { + // callback instance when async-call is invoked + private Object oninvokeInstance; + + // callback method when async-call is invoked + private Method oninvokeMethod; + + // callback instance when async-call is returned + private Object onreturnInstance; + + // callback method when async-call is returned + private Method onreturnMethod; + + // callback instance when async-call has exception thrown + private Object onthrowInstance; + + // callback method when async-call has exception thrown + private Method onthrowMethod; + + public Object getOninvokeInstance() { + return oninvokeInstance; + } + + public void setOninvokeInstance(Object oninvokeInstance) { + this.oninvokeInstance = oninvokeInstance; + } + + public Method getOninvokeMethod() { + return oninvokeMethod; + } + + public void setOninvokeMethod(Method oninvokeMethod) { + this.oninvokeMethod = oninvokeMethod; + } + + public Object getOnreturnInstance() { + return onreturnInstance; + } + + public void setOnreturnInstance(Object onreturnInstance) { + this.onreturnInstance = onreturnInstance; + } + + public Method getOnreturnMethod() { + return onreturnMethod; + } + + public void setOnreturnMethod(Method onreturnMethod) { + this.onreturnMethod = onreturnMethod; + } + + public Object getOnthrowInstance() { + return onthrowInstance; + } + + public void setOnthrowInstance(Object onthrowInstance) { + this.onthrowInstance = onthrowInstance; + } + + public Method getOnthrowMethod() { + return onthrowMethod; + } + + public void setOnthrowMethod(Method onthrowMethod) { + this.onthrowMethod = onthrowMethod; + } + } } diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/model/ConsumerModel.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/model/ConsumerModel.java index 35ff391e1dd..398bc91bd21 100644 --- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/model/ConsumerModel.java +++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/model/ConsumerModel.java @@ -21,20 +21,24 @@ import java.util.IdentityHashMap; import java.util.List; import java.util.Map; +import java.util.Optional; +/** + * Consumer Model which is about subscribed services. + */ public class ConsumerModel { private final Object proxyObject; private final String serviceName; private final Map methodModels = new IdentityHashMap(); - public ConsumerModel(String serviceName, Object proxyObject, Method[] methods) { + public ConsumerModel(String serviceName, Object proxyObject, Method[] methods, Map attributes) { this.serviceName = serviceName; this.proxyObject = proxyObject; if (proxyObject != null) { for (Method method : methods) { - methodModels.put(method, new ConsumerMethodModel(method)); + methodModels.put(method, new ConsumerMethodModel(method, attributes)); } } } @@ -53,6 +57,17 @@ public ConsumerMethodModel getMethodModel(Method method) { return methodModels.get(method); } + /** + * Return method model for the given method on consumer side + * + * @param method method object + * @return method model + */ + public ConsumerMethodModel getMethodModel(String method) { + Optional> consumerMethodModelEntry = methodModels.entrySet().stream().filter(entry -> entry.getKey().getName().equals(method)).findFirst(); + return consumerMethodModelEntry.map(Map.Entry::getValue).orElse(null); + } + /** * Return all method models for the current service * diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/model/ProviderModel.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/model/ProviderModel.java index 179d300b5e0..6fb9bebd7ea 100644 --- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/model/ProviderModel.java +++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/model/ProviderModel.java @@ -23,6 +23,9 @@ import java.util.List; import java.util.Map; +/** + * ProviderModel which is about published services + */ public class ProviderModel { private final String serviceName; private final Object serviceInstance; diff --git a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/StaticContextTest.java b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/StaticContextTest.java deleted file mode 100644 index 723b1be1e46..00000000000 --- a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/StaticContextTest.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * 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.rpc; - -import org.apache.dubbo.common.Constants; -import org.apache.dubbo.common.URL; -import org.junit.Assert; -import org.junit.Test; - -import java.util.HashMap; -import java.util.Map; - -public class StaticContextTest { - - @Test - public void testGetContext() { - String name = "custom"; - - StaticContext context = StaticContext.getContext(name); - Assert.assertTrue(context != null); - Assert.assertEquals(name, context.getName()); - - StaticContext.remove(name); - - StaticContext sysContext = StaticContext.getSystemContext(); - Assert.assertTrue(sysContext != null); - - } - - @Test - public void testGetKey() { - String interfaceName = "interface"; - String method = "method"; - String group = "group"; - String version = "1.0"; - - String suffix = "suffix"; - - Map para = new HashMap<>(); - para.put(Constants.INTERFACE_KEY, interfaceName); - para.put(Constants.GROUP_KEY, group); - para.put(Constants.VERSION_KEY, version); - - URL url = new URL("dubbo", "localhost", 20880, interfaceName, para); - - Assert.assertEquals(StaticContext.getKey(url, method, suffix), - StaticContext.getKey(para, method, suffix)); - - } -} diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/filter/FutureFilter.java b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/filter/FutureFilter.java index 4547b85f16f..f101ed84277 100644 --- a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/filter/FutureFilter.java +++ b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/filter/FutureFilter.java @@ -26,7 +26,9 @@ import org.apache.dubbo.rpc.PostProcessFilter; import org.apache.dubbo.rpc.Result; import org.apache.dubbo.rpc.RpcException; -import org.apache.dubbo.rpc.StaticContext; +import org.apache.dubbo.rpc.model.ApplicationModel; +import org.apache.dubbo.rpc.model.ConsumerMethodModel; +import org.apache.dubbo.rpc.model.ConsumerModel; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; @@ -79,14 +81,18 @@ private void asyncCallback(final Invoker invoker, final Invocation invocation } private void fireInvokeCallback(final Invoker invoker, final Invocation invocation) { - final Method onInvokeMethod = (Method) StaticContext.getSystemContext().get(StaticContext.getKey(invoker.getUrl(), invocation.getMethodName(), Constants.ON_INVOKE_METHOD_KEY)); - final Object onInvokeInst = StaticContext.getSystemContext().get(StaticContext.getKey(invoker.getUrl(), invocation.getMethodName(), Constants.ON_INVOKE_INSTANCE_KEY)); + final ConsumerMethodModel.AsyncMethodInfo asyncMethodInfo = getAsyncMethodInfo(invoker, invocation); + if (asyncMethodInfo == null) { + return; + } + final Method onInvokeMethod = asyncMethodInfo.getOninvokeMethod(); + final Object onInvokeInst = asyncMethodInfo.getOninvokeInstance(); if (onInvokeMethod == null && onInvokeInst == null) { return; } if (onInvokeMethod == null || onInvokeInst == null) { - throw new IllegalStateException("service:" + invoker.getUrl().getServiceKey() + " has a onreturn callback config , but no such " + (onInvokeMethod == null ? "method" : "instance") + " found. url:" + invoker.getUrl()); + throw new IllegalStateException("service:" + invoker.getUrl().getServiceKey() + " has a oninvoke callback config , but no such " + (onInvokeMethod == null ? "method" : "instance") + " found. url:" + invoker.getUrl()); } if (!onInvokeMethod.isAccessible()) { onInvokeMethod.setAccessible(true); @@ -103,8 +109,13 @@ private void fireInvokeCallback(final Invoker invoker, final Invocation invoc } private void fireReturnCallback(final Invoker invoker, final Invocation invocation, final Object result) { - final Method onReturnMethod = (Method) StaticContext.getSystemContext().get(StaticContext.getKey(invoker.getUrl(), invocation.getMethodName(), Constants.ON_RETURN_METHOD_KEY)); - final Object onReturnInst = StaticContext.getSystemContext().get(StaticContext.getKey(invoker.getUrl(), invocation.getMethodName(), Constants.ON_RETURN_INSTANCE_KEY)); + final ConsumerMethodModel.AsyncMethodInfo asyncMethodInfo = getAsyncMethodInfo(invoker, invocation); + if (asyncMethodInfo == null) { + return; + } + + final Method onReturnMethod = asyncMethodInfo.getOnreturnMethod(); + final Object onReturnInst = asyncMethodInfo.getOnreturnInstance(); //not set onreturn callback if (onReturnMethod == null && onReturnInst == null) { @@ -144,8 +155,13 @@ private void fireReturnCallback(final Invoker invoker, final Invocation invoc } private void fireThrowCallback(final Invoker invoker, final Invocation invocation, final Throwable exception) { - final Method onthrowMethod = (Method) StaticContext.getSystemContext().get(StaticContext.getKey(invoker.getUrl(), invocation.getMethodName(), Constants.ON_THROW_METHOD_KEY)); - final Object onthrowInst = StaticContext.getSystemContext().get(StaticContext.getKey(invoker.getUrl(), invocation.getMethodName(), Constants.ON_THROW_INSTANCE_KEY)); + final ConsumerMethodModel.AsyncMethodInfo asyncMethodInfo = getAsyncMethodInfo(invoker, invocation); + if (asyncMethodInfo == null) { + return; + } + + final Method onthrowMethod = asyncMethodInfo.getOnthrowMethod(); + final Object onthrowInst = asyncMethodInfo.getOnthrowInstance(); //onthrow callback not configured if (onthrowMethod == null && onthrowInst == null) { @@ -184,4 +200,20 @@ private void fireThrowCallback(final Invoker invoker, final Invocation invoca logger.error(invocation.getMethodName() + ".call back method invoke error . callback method :" + onthrowMethod + ", url:" + invoker.getUrl(), exception); } } + + private ConsumerMethodModel.AsyncMethodInfo getAsyncMethodInfo(Invoker invoker, Invocation invocation) { + final ConsumerModel consumerModel = ApplicationModel.getConsumerModel(invoker.getUrl().getServiceKey()); + if (consumerModel == null) { + return null; + } + ConsumerMethodModel methodModel = consumerModel.getMethodModel(invocation.getMethodName()); + if (methodModel == null) { + return null; + } + final ConsumerMethodModel.AsyncMethodInfo asyncMethodInfo = methodModel.getAsyncInfo(); + if (asyncMethodInfo == null) { + return null; + } + return asyncMethodInfo; + } } diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/ImplicitCallBackTest.java b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/ImplicitCallBackTest.java index 773e72f1ead..4c5308caf2e 100644 --- a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/ImplicitCallBackTest.java +++ b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/ImplicitCallBackTest.java @@ -23,7 +23,9 @@ import org.apache.dubbo.rpc.Exporter; import org.apache.dubbo.rpc.Invoker; import org.apache.dubbo.rpc.RpcContext; -import org.apache.dubbo.rpc.StaticContext; +import org.apache.dubbo.rpc.model.ApplicationModel; +import org.apache.dubbo.rpc.model.ConsumerMethodModel; +import org.apache.dubbo.rpc.model.ConsumerModel; import org.apache.dubbo.rpc.protocol.dubbo.support.ProtocolUtils; import org.junit.After; import org.junit.Assert; @@ -72,6 +74,12 @@ public void initOrResetService() { referService(); } + public void initOrResetExService() { + destroyService(); + exportExService(); + referService(); + } + public void destroyService() { demoProxy = null; try { @@ -95,26 +103,36 @@ public void exportExService() { public void initOrResetUrl(boolean isAsync) throws Exception { int port = NetUtils.getAvailablePort(); - consumerUrl = serviceURL = URL.valueOf("dubbo://127.0.0.1:" + port + "/" + IDemoService.class.getName() + "?group=test&async=" + isAsync + "&timeout=100000&reference.filter=future"); - StaticContext.getSystemContext().clear(); + consumerUrl = serviceURL = URL.valueOf("dubbo://127.0.0.1:" + port + "/" + IDemoService.class.getName() + "?group=" + System.nanoTime() + "&async=" + isAsync + "&timeout=100000&reference.filter=future"); } public void initImplicitCallBackURL_onlyOnthrow() throws Exception { - StaticContext.getSystemContext().put(StaticContext.getKey(consumerUrl, "get", Constants.ON_THROW_METHOD_KEY), onThrowMethod); - StaticContext.getSystemContext().put(StaticContext.getKey(consumerUrl, "get", Constants.ON_THROW_INSTANCE_KEY), notify); + Map attitudes = new HashMap<>(); + ConsumerMethodModel.AsyncMethodInfo asyncMethodInfo = new ConsumerMethodModel.AsyncMethodInfo(); + asyncMethodInfo.setOnthrowInstance(notify); + asyncMethodInfo.setOnthrowMethod(onThrowMethod); + attitudes.put("get", asyncMethodInfo); + ApplicationModel.initConsumerModel(consumerUrl.getServiceKey(), new ConsumerModel(consumerUrl.getServiceKey(), demoProxy, IDemoService.class.getMethods(), attitudes)); } //================================================================================================ public void initImplicitCallBackURL_onlyOnreturn() throws Exception { - StaticContext.getSystemContext().put(StaticContext.getKey(consumerUrl, "get", Constants.ON_RETURN_METHOD_KEY), onReturnMethod); - StaticContext.getSystemContext().put(StaticContext.getKey(consumerUrl, "get", Constants.ON_RETURN_INSTANCE_KEY), notify); - + Map attitudes = new HashMap<>(); + ConsumerMethodModel.AsyncMethodInfo asyncMethodInfo = new ConsumerMethodModel.AsyncMethodInfo(); + asyncMethodInfo.setOnreturnInstance(notify); + asyncMethodInfo.setOnreturnMethod(onReturnMethod); + attitudes.put("get", asyncMethodInfo); + ApplicationModel.initConsumerModel(consumerUrl.getServiceKey(), new ConsumerModel(consumerUrl.getServiceKey(), demoProxy, IDemoService.class.getMethods(), attitudes)); } public void initImplicitCallBackURL_onlyOninvoke() throws Exception { - StaticContext.getSystemContext().put(StaticContext.getKey(consumerUrl, "get", Constants.ON_INVOKE_METHOD_KEY), onInvokeMethod); - StaticContext.getSystemContext().put(StaticContext.getKey(consumerUrl, "get", Constants.ON_INVOKE_INSTANCE_KEY), notify); + Map attitudes = new HashMap<>(); + ConsumerMethodModel.AsyncMethodInfo asyncMethodInfo = new ConsumerMethodModel.AsyncMethodInfo(); + asyncMethodInfo.setOninvokeInstance(notify); + asyncMethodInfo.setOninvokeMethod(onInvokeMethod); + attitudes.put("get", asyncMethodInfo); + ApplicationModel.initConsumerModel(consumerUrl.getServiceKey(), new ConsumerModel(consumerUrl.getServiceKey(), demoProxy, IDemoService.class.getMethods(), attitudes)); } @Test @@ -129,8 +147,9 @@ public void test_CloseCallback() throws Exception { @Test public void test_Sync_Onreturn() throws Exception { initOrResetUrl(false); - initImplicitCallBackURL_onlyOnreturn(); initOrResetService(); + initImplicitCallBackURL_onlyOnreturn(); + int requestId = 2; Person ret = demoProxy.get(requestId); Assert.assertEquals(requestId, ret.getId()); @@ -148,11 +167,9 @@ public void test_Sync_Onreturn() throws Exception { @Test public void test_Ex_OnReturn() throws Exception { initOrResetUrl(true); + initOrResetExService(); initImplicitCallBackURL_onlyOnreturn(); - destroyService(); - exportExService(); - referService(); int requestId = 2; Person ret = demoProxy.get(requestId); @@ -171,12 +188,9 @@ public void test_Ex_OnReturn() throws Exception { @Test public void test_Ex_OnInvoke() throws Exception { initOrResetUrl(true); + initOrResetExService(); initImplicitCallBackURL_onlyOninvoke(); - destroyService(); - exportExService(); - referService(); - int requestId = 2; Person ret = demoProxy.get(requestId); Assert.assertEquals(null, ret); @@ -194,12 +208,9 @@ public void test_Ex_OnInvoke() throws Exception { @Test public void test_Ex_Onthrow() throws Exception { initOrResetUrl(true); + initOrResetExService(); initImplicitCallBackURL_onlyOnthrow(); - destroyService(); - exportExService(); - referService(); - int requestId = 2; Person ret = demoProxy.get(requestId); Assert.assertEquals(null, ret); @@ -218,10 +229,8 @@ public void test_Ex_Onthrow() throws Exception { @Test public void test_Sync_NoFuture() throws Exception { initOrResetUrl(false); + initOrResetService(); initImplicitCallBackURL_onlyOnreturn(); - destroyService(); - exportService(); - referService(); int requestId = 2; Person ret = demoProxy.get(requestId); @@ -234,9 +243,7 @@ public void test_Sync_NoFuture() throws Exception { @Test public void test_Async_Future() throws Exception { initOrResetUrl(true); - destroyService(); - exportService(); - referService(); + initOrResetService(); int requestId = 2; Person ret = demoProxy.get(requestId); @@ -250,9 +257,7 @@ public void test_Async_Future() throws Exception { @Test public void test_Async_Future_Multi() throws Exception { initOrResetUrl(true); - destroyService(); - exportService(); - referService(); + initOrResetService(); int requestId1 = 1; Person ret = demoProxy.get(requestId1); @@ -275,9 +280,7 @@ public void test_Async_Future_Multi() throws Exception { public void test_Async_Future_Ex() throws Throwable { try { initOrResetUrl(true); - destroyService(); - exportExService(); - referService(); + initOrResetExService(); int requestId = 2; Person ret = demoProxy.get(requestId); @@ -295,9 +298,7 @@ public void test_Async_Future_Ex() throws Throwable { @Test(expected = RuntimeException.class) public void test_Normal_Ex() throws Exception { initOrResetUrl(false); - destroyService(); - exportExService(); - referService(); + initOrResetExService(); int requestId = 2; Person ret = demoProxy.get(requestId);