From 3e99823b1712935842e6ffa143620fced631a1ae Mon Sep 17 00:00:00 2001 From: Sean Yang Date: Fri, 1 Nov 2024 10:27:26 +0800 Subject: [PATCH 01/19] Support read parameter names from local variable table (#14843) --- .../utils/DefaultParameterNameReader.java | 86 ++++++++++++ .../utils/JavassistParameterNameReader.java | 125 ++++++++++++++++++ .../common/utils/ParameterNameReader.java | 31 +++++ ...che.dubbo.common.utils.ParameterNameReader | 1 + .../JavassistParameterNameReaderTest.java | 66 +++++++++ .../util/SpringParameterNameReader.java | 42 ++++++ ...che.dubbo.common.utils.ParameterNameReader | 1 + dubbo-distribution/dubbo-all-shaded/pom.xml | 3 + dubbo-distribution/dubbo-all/pom.xml | 3 + dubbo-distribution/dubbo-core-spi/pom.xml | 3 + .../support/spring/SpringRestToolKit.java | 10 +- .../tri/rest/util/AbstractRestToolKit.java | 17 +-- 12 files changed, 371 insertions(+), 17 deletions(-) create mode 100644 dubbo-common/src/main/java/org/apache/dubbo/common/utils/DefaultParameterNameReader.java create mode 100644 dubbo-common/src/main/java/org/apache/dubbo/common/utils/JavassistParameterNameReader.java create mode 100644 dubbo-common/src/main/java/org/apache/dubbo/common/utils/ParameterNameReader.java create mode 100644 dubbo-common/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.utils.ParameterNameReader create mode 100644 dubbo-common/src/test/java/org/apache/dubbo/common/utils/JavassistParameterNameReaderTest.java create mode 100644 dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/util/SpringParameterNameReader.java create mode 100644 dubbo-config/dubbo-config-spring/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.utils.ParameterNameReader diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/DefaultParameterNameReader.java b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/DefaultParameterNameReader.java new file mode 100644 index 00000000000..48c7f702584 --- /dev/null +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/DefaultParameterNameReader.java @@ -0,0 +1,86 @@ +/* + * 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.common.utils; + +import org.apache.dubbo.rpc.model.FrameworkModel; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; +import java.lang.reflect.Parameter; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +public final class DefaultParameterNameReader implements ParameterNameReader { + + private final Map> cache = CollectionUtils.newConcurrentHashMap(); + private final List readers; + + public DefaultParameterNameReader(FrameworkModel frameworkModel) { + readers = frameworkModel.getActivateExtensions(ParameterNameReader.class); + } + + @Override + public String[] readParameterNames(Method method) { + return cache.computeIfAbsent(method, k -> { + String[] names = readByReflection(method.getParameters()); + if (names == null) { + for (ParameterNameReader reader : readers) { + names = reader.readParameterNames(method); + if (names != null) { + break; + } + } + } + return Optional.ofNullable(names); + }) + .orElse(null); + } + + @Override + public String[] readParameterNames(Constructor ctor) { + return cache.computeIfAbsent(ctor, k -> { + String[] names = readByReflection(ctor.getParameters()); + if (names == null) { + for (ParameterNameReader reader : readers) { + names = reader.readParameterNames(ctor); + if (names != null) { + break; + } + } + } + return Optional.ofNullable(names); + }) + .orElse(null); + } + + private static String[] readByReflection(Parameter[] parameters) { + int len = parameters.length; + if (len == 0) { + return StringUtils.EMPTY_STRING_ARRAY; + } + String[] names = new String[len]; + for (int i = 0; i < len; i++) { + Parameter param = parameters[i]; + if (!param.isNamePresent()) { + return null; + } + names[i] = param.getName(); + } + return names; + } +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/JavassistParameterNameReader.java b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/JavassistParameterNameReader.java new file mode 100644 index 00000000000..a640754e734 --- /dev/null +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/JavassistParameterNameReader.java @@ -0,0 +1,125 @@ +/* + * 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.common.utils; + +import org.apache.dubbo.common.constants.LoggerCodeConstants; +import org.apache.dubbo.common.extension.Activate; +import org.apache.dubbo.common.logger.ErrorTypeAwareLogger; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.Map; +import javassist.ClassPool; +import javassist.CtBehavior; +import javassist.CtConstructor; +import javassist.CtMethod; +import javassist.LoaderClassPath; +import javassist.bytecode.CodeAttribute; +import javassist.bytecode.Descriptor; +import javassist.bytecode.LocalVariableAttribute; + +import static org.apache.dubbo.common.logger.LoggerFactory.getErrorTypeAwareLogger; + +@Activate(order = 100, onClass = "javassist.ClassPool") +public class JavassistParameterNameReader implements ParameterNameReader { + + private static final ErrorTypeAwareLogger LOG = getErrorTypeAwareLogger(JavassistParameterNameReader.class); + + private final Map classPoolMap = CollectionUtils.newConcurrentHashMap(); + + @Override + public String[] readParameterNames(Method method) { + try { + Class[] paramTypes = method.getParameterTypes(); + if (paramTypes.length == 0) { + return StringUtils.EMPTY_STRING_ARRAY; + } + String descriptor = getDescriptor(paramTypes, method.getReturnType()); + Class clazz = method.getDeclaringClass(); + CtMethod ctMethod = getClassPool(clazz).get(clazz.getName()).getMethod(method.getName(), descriptor); + return read(ctMethod, Modifier.isStatic(method.getModifiers()) ? 0 : 1, paramTypes.length); + } catch (Throwable t) { + LOG.warn(LoggerCodeConstants.INTERNAL_ERROR, "", "", "Read parameter names error", t); + return null; + } + } + + @Override + public String[] readParameterNames(Constructor ctor) { + try { + Class[] paramTypes = ctor.getParameterTypes(); + if (paramTypes.length == 0) { + return StringUtils.EMPTY_STRING_ARRAY; + } + String descriptor = getDescriptor(paramTypes, void.class); + Class clazz = ctor.getDeclaringClass(); + CtConstructor ctCtor = getClassPool(clazz).get(clazz.getName()).getConstructor(descriptor); + return read(ctCtor, 1, paramTypes.length); + } catch (Throwable t) { + LOG.warn(LoggerCodeConstants.INTERNAL_ERROR, "", "", "Read parameter names error", t); + return null; + } + } + + private static String getDescriptor(Class[] parameterTypes, Class returnType) { + StringBuilder descriptor = new StringBuilder(32); + descriptor.append('('); + for (Class type : parameterTypes) { + descriptor.append(toJvmName(type)); + } + descriptor.append(')'); + descriptor.append(toJvmName(returnType)); + return descriptor.toString(); + } + + private static String toJvmName(Class clazz) { + return clazz.isArray() ? Descriptor.toJvmName(clazz.getName()) : Descriptor.of(clazz.getName()); + } + + private ClassPool getClassPool(Class clazz) { + ClassLoader classLoader = ClassUtils.getClassLoader(clazz); + return classPoolMap.computeIfAbsent(System.identityHashCode(classLoader), k -> { + ClassPool pool = new ClassPool(); + pool.appendClassPath(new LoaderClassPath(classLoader)); + return pool; + }); + } + + private static String[] read(CtBehavior behavior, int start, int len) { + if (behavior == null) { + return null; + } + CodeAttribute codeAttr = behavior.getMethodInfo().getCodeAttribute(); + if (codeAttr == null) { + return null; + } + LocalVariableAttribute attr = (LocalVariableAttribute) codeAttr.getAttribute(LocalVariableAttribute.tag); + if (attr == null) { + return null; + } + String[] names = new String[len]; + for (int i = 0, tLen = attr.tableLength(); i < tLen; i++) { + int j = attr.index(i) - start; + if (j >= 0 && j < len) { + names[j] = attr.variableName(i); + } + } + + return names; + } +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/ParameterNameReader.java b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/ParameterNameReader.java new file mode 100644 index 00000000000..7cb1f51fafb --- /dev/null +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/ParameterNameReader.java @@ -0,0 +1,31 @@ +/* + * 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.common.utils; + +import org.apache.dubbo.common.extension.ExtensionScope; +import org.apache.dubbo.common.extension.SPI; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; + +@SPI(scope = ExtensionScope.FRAMEWORK) +public interface ParameterNameReader { + + String[] readParameterNames(Method method); + + String[] readParameterNames(Constructor ctor); +} diff --git a/dubbo-common/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.utils.ParameterNameReader b/dubbo-common/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.utils.ParameterNameReader new file mode 100644 index 00000000000..b6e7ff292a5 --- /dev/null +++ b/dubbo-common/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.utils.ParameterNameReader @@ -0,0 +1 @@ +javassist=org.apache.dubbo.common.utils.JavassistParameterNameReader diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/JavassistParameterNameReaderTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/utils/JavassistParameterNameReaderTest.java new file mode 100644 index 00000000000..1118fdc6d4f --- /dev/null +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/utils/JavassistParameterNameReaderTest.java @@ -0,0 +1,66 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.dubbo.common.utils; + +import org.apache.dubbo.common.URL; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; + +import org.junit.jupiter.api.Test; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.emptyArray; +import static org.hamcrest.Matchers.equalTo; + +class JavassistParameterNameReaderTest { + + private final ParameterNameReader reader = new JavassistParameterNameReader(); + + @Test + void readFromConstructor() { + Class clazz = URL.class; + for (Constructor ctor : clazz.getConstructors()) { + String[] names = reader.readParameterNames(ctor); + // System.out.println(ctor + " -> " + Arrays.toString(names)); + if (names.length == 7) { + assertThat(names[0], equalTo("protocol")); + } + } + } + + @Test + void readFromMethod() { + Class clazz = URL.class; + for (Method method : clazz.getMethods()) { + String[] names = reader.readParameterNames(method); + // System.out.println(method + " -> " + Arrays.toString(names)); + switch (method.getName()) { + case "getAddress": + assertThat(names, emptyArray()); + break; + case "setAddress": + assertThat(names[0], equalTo("address")); + break; + case "buildKey": + assertThat(names[0], equalTo("path")); + break; + default: + } + } + } +} diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/util/SpringParameterNameReader.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/util/SpringParameterNameReader.java new file mode 100644 index 00000000000..f0556576373 --- /dev/null +++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/util/SpringParameterNameReader.java @@ -0,0 +1,42 @@ +/* + * 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.spring.util; + +import org.apache.dubbo.common.extension.Activate; +import org.apache.dubbo.common.utils.ParameterNameReader; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; + +import org.springframework.core.DefaultParameterNameDiscoverer; +import org.springframework.core.ParameterNameDiscoverer; + +@Activate(onClass = "org.springframework.core.DefaultParameterNameDiscoverer") +public class SpringParameterNameReader implements ParameterNameReader { + + private final ParameterNameDiscoverer discoverer = new DefaultParameterNameDiscoverer(); + + @Override + public String[] readParameterNames(Method method) { + return discoverer.getParameterNames(method); + } + + @Override + public String[] readParameterNames(Constructor ctor) { + return discoverer.getParameterNames(ctor); + } +} diff --git a/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.utils.ParameterNameReader b/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.utils.ParameterNameReader new file mode 100644 index 00000000000..ad2dd3afeda --- /dev/null +++ b/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.utils.ParameterNameReader @@ -0,0 +1 @@ +spring=org.apache.dubbo.config.spring.util.SpringParameterNameReader diff --git a/dubbo-distribution/dubbo-all-shaded/pom.xml b/dubbo-distribution/dubbo-all-shaded/pom.xml index eafb65386dd..734d1e11488 100644 --- a/dubbo-distribution/dubbo-all-shaded/pom.xml +++ b/dubbo-distribution/dubbo-all-shaded/pom.xml @@ -599,6 +599,9 @@ META-INF/dubbo/internal/org.apache.dubbo.common.threadpool.manager.ExecutorRepository + + META-INF/dubbo/internal/org.apache.dubbo.common.utils.ParameterNameReader + META-INF/dubbo/internal/org.apache.dubbo.common.url.component.param.DynamicParamSource diff --git a/dubbo-distribution/dubbo-all/pom.xml b/dubbo-distribution/dubbo-all/pom.xml index 2f7828fe80a..02b928d5ed1 100644 --- a/dubbo-distribution/dubbo-all/pom.xml +++ b/dubbo-distribution/dubbo-all/pom.xml @@ -600,6 +600,9 @@ META-INF/dubbo/internal/org.apache.dubbo.common.url.component.param.DynamicParamSource + + META-INF/dubbo/internal/org.apache.dubbo.common.utils.ParameterNameReader + META-INF/dubbo/internal/org.apache.dubbo.config.ConfigInitializer diff --git a/dubbo-distribution/dubbo-core-spi/pom.xml b/dubbo-distribution/dubbo-core-spi/pom.xml index 7592f4e99ad..431959407dc 100644 --- a/dubbo-distribution/dubbo-core-spi/pom.xml +++ b/dubbo-distribution/dubbo-core-spi/pom.xml @@ -223,6 +223,9 @@ META-INF/dubbo/internal/org.apache.dubbo.config.ConfigInitializer + + META-INF/dubbo/internal/org.apache.dubbo.common.utils.ParameterNameReader + META-INF/dubbo/internal/org.apache.dubbo.config.ConfigPostProcessor diff --git a/dubbo-plugin/dubbo-rest-spring/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/support/spring/SpringRestToolKit.java b/dubbo-plugin/dubbo-rest-spring/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/support/spring/SpringRestToolKit.java index eb70a039f29..c040e5914af 100644 --- a/dubbo-plugin/dubbo-rest-spring/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/support/spring/SpringRestToolKit.java +++ b/dubbo-plugin/dubbo-rest-spring/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/support/spring/SpringRestToolKit.java @@ -19,6 +19,8 @@ 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.DefaultParameterNameReader; +import org.apache.dubbo.common.utils.ParameterNameReader; import org.apache.dubbo.config.spring.extension.SpringExtensionInjector; import org.apache.dubbo.remoting.http12.HttpRequest; import org.apache.dubbo.remoting.http12.HttpResponse; @@ -43,9 +45,7 @@ import org.springframework.beans.factory.config.ConfigurableBeanFactory; import org.springframework.context.ApplicationContext; import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.core.DefaultParameterNameDiscoverer; import org.springframework.core.MethodParameter; -import org.springframework.core.ParameterNameDiscoverer; import org.springframework.core.annotation.AnnotatedElementUtils; import org.springframework.core.convert.ConversionService; import org.springframework.core.convert.TypeDescriptor; @@ -63,7 +63,7 @@ final class SpringRestToolKit implements RestToolKit { private final ConversionService conversionService; private final TypeConverter typeConverter; private final BeanArgumentBinder argumentBinder; - private final ParameterNameDiscoverer discoverer; + private final ParameterNameReader parameterNameReader; public SpringRestToolKit(FrameworkModel frameworkModel) { ApplicationModel applicationModel = frameworkModel.defaultApplication(); @@ -84,7 +84,7 @@ public SpringRestToolKit(FrameworkModel frameworkModel) { conversionService = DefaultConversionService.getSharedInstance(); } typeConverter = frameworkModel.getBeanFactory().getOrRegisterBean(GeneralTypeConverter.class); - discoverer = new DefaultParameterNameDiscoverer(); + parameterNameReader = frameworkModel.getBeanFactory().getOrRegisterBean(DefaultParameterNameReader.class); argumentBinder = new BeanArgumentBinder(frameworkModel, conversionService); } @@ -151,7 +151,7 @@ public Object bind(ParameterMeta parameter, HttpRequest request, HttpResponse re @Override public String[] getParameterNames(Method method) { - return discoverer.getParameterNames(method); + return parameterNameReader.readParameterNames(method); } @Override diff --git a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/util/AbstractRestToolKit.java b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/util/AbstractRestToolKit.java index 7ddb719c583..51b36b3cadf 100644 --- a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/util/AbstractRestToolKit.java +++ b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/util/AbstractRestToolKit.java @@ -18,6 +18,8 @@ import org.apache.dubbo.common.config.Environment; import org.apache.dubbo.common.utils.AnnotationUtils; +import org.apache.dubbo.common.utils.DefaultParameterNameReader; +import org.apache.dubbo.common.utils.ParameterNameReader; import org.apache.dubbo.rpc.model.FrameworkModel; import org.apache.dubbo.rpc.protocol.tri.rest.Messages; import org.apache.dubbo.rpc.protocol.tri.rest.RestException; @@ -28,17 +30,18 @@ import java.lang.annotation.Annotation; import java.lang.reflect.AnnotatedElement; import java.lang.reflect.Method; -import java.lang.reflect.Parameter; import java.util.Map; public abstract class AbstractRestToolKit implements RestToolKit { protected final FrameworkModel frameworkModel; protected final TypeConverter typeConverter; + protected final ParameterNameReader parameterNameReader; public AbstractRestToolKit(FrameworkModel frameworkModel) { this.frameworkModel = frameworkModel; typeConverter = frameworkModel.getBeanFactory().getOrRegisterBean(GeneralTypeConverter.class); + parameterNameReader = frameworkModel.getBeanFactory().getOrRegisterBean(DefaultParameterNameReader.class); } @Override @@ -66,17 +69,7 @@ public Object convert(Object value, ParameterMeta parameter) { @Override public String[] getParameterNames(Method method) { - Parameter[] parameters = method.getParameters(); - int len = parameters.length; - String[] names = new String[len]; - for (int i = 0; i < len; i++) { - Parameter param = parameters[i]; - if (!param.isNamePresent()) { - return null; - } - names[i] = param.getName(); - } - return names; + return parameterNameReader.readParameterNames(method); } @Override From 9741de32e54b88d732c865356749661dcb7c4328 Mon Sep 17 00:00:00 2001 From: heliang666s <147408835+heliang666s@users.noreply.github.com> Date: Sun, 3 Nov 2024 13:02:27 +0800 Subject: [PATCH 02/19] =?UTF-8?q?Support=20parsing=20custom=20REST=20paths?= =?UTF-8?q?=20from=20proto=20files=20and=20generating=20@Ma=E2=80=A6=20(#1?= =?UTF-8?q?4796)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dubbo-plugin/dubbo-compiler/pom.xml | 1 - .../apache/dubbo/gen/AbstractGenerator.java | 91 ++++++++++++++++++- .../Dubbo3TripleInterfaceStub.mustache | 54 +++++------ .../main/resources/Dubbo3TripleStub.mustache | 82 ++++------------- .../dubbo/rpc/stub/annotations/GRequest.java | 30 ++++++ .../basic/GRequestArgumentResolver.java | 85 +++++++++++++++++ ...rotocol.tri.rest.argument.ArgumentResolver | 1 + 7 files changed, 248 insertions(+), 96 deletions(-) create mode 100644 dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/stub/annotations/GRequest.java create mode 100644 dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/support/basic/GRequestArgumentResolver.java diff --git a/dubbo-plugin/dubbo-compiler/pom.xml b/dubbo-plugin/dubbo-compiler/pom.xml index adaeb057de4..48c800e7fe4 100644 --- a/dubbo-plugin/dubbo-compiler/pom.xml +++ b/dubbo-plugin/dubbo-compiler/pom.xml @@ -100,5 +100,4 @@ - diff --git a/dubbo-plugin/dubbo-compiler/src/main/java/org/apache/dubbo/gen/AbstractGenerator.java b/dubbo-plugin/dubbo-compiler/src/main/java/org/apache/dubbo/gen/AbstractGenerator.java index c434ec47fcb..7ea75cf5392 100644 --- a/dubbo-plugin/dubbo-compiler/src/main/java/org/apache/dubbo/gen/AbstractGenerator.java +++ b/dubbo-plugin/dubbo-compiler/src/main/java/org/apache/dubbo/gen/AbstractGenerator.java @@ -33,6 +33,9 @@ import com.github.mustachejava.DefaultMustacheFactory; import com.github.mustachejava.Mustache; import com.github.mustachejava.MustacheFactory; +import com.google.api.AnnotationsProto; +import com.google.api.HttpRule; +import com.google.api.HttpRule.PatternCase; import com.google.common.base.Charsets; import com.google.common.base.Preconditions; import com.google.common.base.Strings; @@ -42,6 +45,7 @@ import com.google.protobuf.DescriptorProtos.MethodDescriptorProto; import com.google.protobuf.DescriptorProtos.ServiceDescriptorProto; import com.google.protobuf.DescriptorProtos.SourceCodeInfo.Location; +import com.google.protobuf.ExtensionRegistry; import com.google.protobuf.compiler.PluginProtos; public abstract class AbstractGenerator { @@ -67,24 +71,40 @@ protected String getInterfaceTemplateFileName() { } private String getServiceJavaDocPrefix() { - return " "; + return ""; } private String getMethodJavaDocPrefix() { - return " "; + return " "; } public List generateFiles(PluginProtos.CodeGeneratorRequest request) { - final ProtoTypeMap typeMap = ProtoTypeMap.of(request.getProtoFileList()); + // 1. build ExtensionRegistry and registry + ExtensionRegistry registry = ExtensionRegistry.newInstance(); + AnnotationsProto.registerAllExtensions(registry); + // 2. compile proto file List protosToGenerate = request.getProtoFileList().stream() .filter(protoFile -> request.getFileToGenerateList().contains(protoFile.getName())) + .map(protoFile -> parseWithExtensions(protoFile, registry)) .collect(Collectors.toList()); + // 3. use compiled proto file build ProtoTypeMap + final ProtoTypeMap typeMap = ProtoTypeMap.of(protosToGenerate); + + // 4. find and generate serviceContext List services = findServices(protosToGenerate, typeMap); return generateFiles(services); } + private FileDescriptorProto parseWithExtensions(FileDescriptorProto protoFile, ExtensionRegistry registry) { + try { + return FileDescriptorProto.parseFrom(protoFile.toByteString(), registry); + } catch (Exception e) { + return protoFile; + } + } + private List findServices(List protos, ProtoTypeMap typeMap) { List contexts = new ArrayList<>(); @@ -171,6 +191,40 @@ private MethodContext buildMethodContext( methodContext.isManyOutput = methodProto.getServerStreaming(); methodContext.methodNumber = methodNumber; + // compile google.api.http option + HttpRule httpRule = parseHttpRule(methodProto); + if (httpRule != null) { + PatternCase patternCase = httpRule.getPatternCase(); + String path; + switch (patternCase) { + case GET: + path = httpRule.getGet(); + break; + case PUT: + path = httpRule.getPut(); + break; + case POST: + path = httpRule.getPost(); + break; + case DELETE: + path = httpRule.getDelete(); + break; + case PATCH: + path = httpRule.getPatch(); + break; + default: + path = ""; + break; + } + if (!path.isEmpty()) { + methodContext.httpMethod = patternCase.name(); + methodContext.path = path; + methodContext.body = httpRule.getBody(); + methodContext.hasMapping = true; + methodContext.needRequestAnnotation = !methodContext.body.isEmpty() || path.contains("{"); + } + } + Location methodLocation = locations.stream() .filter(location -> location.getPathCount() == METHOD_NUMBER_OF_PATHS && location.getPath(METHOD_NUMBER_OF_PATHS - 1) == methodNumber) @@ -197,6 +251,17 @@ private MethodContext buildMethodContext( return methodContext; } + private HttpRule parseHttpRule(MethodDescriptorProto methodProto) { + HttpRule rule = null; + // check methodProto have options + if (methodProto.hasOptions()) { + if (methodProto.getOptions().hasExtension(AnnotationsProto.http)) { + rule = methodProto.getOptions().getExtension(AnnotationsProto.http); + } + } + return rule; + } + private String lowerCaseFirst(String s) { return Character.toLowerCase(s.charAt(0)) + s.substring(1); } @@ -360,6 +425,26 @@ private static class MethodContext { public String grpcCallsMethodName; public int methodNumber; public String javaDoc; + /** + * The HTTP request method + */ + public String httpMethod; + /** + * The HTTP request path + */ + public String path; + /** + * The message field that the HTTP request body mapping to + */ + public String body; + /** + * Whether the method has HTTP mapping + */ + public boolean hasMapping; + /** + * Whether the request body parameter need @GRequest annotation + */ + public boolean needRequestAnnotation; // This method mimics the upper-casing method ogf gRPC to ensure compatibility // See https://github.com/grpc/grpc-java/blob/v1.8.0/compiler/src/java_plugin/cpp/java_generator.cpp#L58 diff --git a/dubbo-plugin/dubbo-compiler/src/main/resources/Dubbo3TripleInterfaceStub.mustache b/dubbo-plugin/dubbo-compiler/src/main/resources/Dubbo3TripleInterfaceStub.mustache index d31fed7efbe..559e2b9e5ce 100644 --- a/dubbo-plugin/dubbo-compiler/src/main/resources/Dubbo3TripleInterfaceStub.mustache +++ b/dubbo-plugin/dubbo-compiler/src/main/resources/Dubbo3TripleInterfaceStub.mustache @@ -1,25 +1,28 @@ /* -* 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. -*/ + * 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. + */ {{#packageName}} package {{packageName}}; {{/packageName}} import org.apache.dubbo.common.stream.StreamObserver; +import org.apache.dubbo.remoting.http12.HttpMethods; +import org.apache.dubbo.remoting.http12.rest.Mapping; +import org.apache.dubbo.rpc.stub.annotations.GRequest; import com.google.protobuf.Message; import java.util.HashMap; @@ -28,7 +31,6 @@ import java.util.function.BiConsumer; import java.util.concurrent.CompletableFuture; public interface {{interfaceClassName}} extends org.apache.dubbo.rpc.model.DubboStub { - String JAVA_SERVICE_NAME = "{{packageName}}.{{serviceName}}"; {{#commonPackageName}} String SERVICE_NAME = "{{commonPackageName}}.{{serviceName}}"; @@ -40,34 +42,32 @@ public interface {{interfaceClassName}} extends org.apache.dubbo.rpc.model.Dubbo {{#javaDoc}} {{{javaDoc}}} {{/javaDoc}} - {{outputType}} {{methodName}}({{inputType}} request); - - CompletableFuture<{{outputType}}> {{methodName}}Async({{inputType}} request); - - + {{#hasMapping}} + @Mapping(method = HttpMethods.{{httpMethod}}, path = "{{path}}") + {{/hasMapping}} + {{outputType}} {{methodName}}({{#needRequestAnnotation}}@GRequest{{#body}}("{{body}}"){{/body}} {{/needRequestAnnotation}}{{inputType}} request); + CompletableFuture<{{outputType}}> {{methodName}}Async({{#needRequestAnnotation}}@GRequest {{/needRequestAnnotation}}{{inputType}} request); {{/unaryMethods}} - {{#serverStreamingMethods}} {{#javaDoc}} {{{javaDoc}}} {{/javaDoc}} - void {{methodName}}({{inputType}} request, StreamObserver<{{outputType}}> responseObserver); + {{#hasMapping}} + @Mapping(method = HttpMethods.{{httpMethod}}, path = "{{path}}") + {{/hasMapping}} + void {{methodName}}({{#needRequestAnnotation}}@GRequest{{#body}}("{{body}}"){{/body}} {{/needRequestAnnotation}}{{inputType}} request, StreamObserver<{{outputType}}> responseObserver); {{/serverStreamingMethods}} - {{#biStreamingWithoutClientStreamMethods}} {{#javaDoc}} {{{javaDoc}}} {{/javaDoc}} StreamObserver<{{inputType}}> {{methodName}}(StreamObserver<{{outputType}}> responseObserver); {{/biStreamingWithoutClientStreamMethods}} - - {{#clientStreamingMethods}} {{#javaDoc}} {{{javaDoc}}} {{/javaDoc}} StreamObserver<{{inputType}}> {{methodName}}(StreamObserver<{{outputType}}> responseObserver); {{/clientStreamingMethods}} - } diff --git a/dubbo-plugin/dubbo-compiler/src/main/resources/Dubbo3TripleStub.mustache b/dubbo-plugin/dubbo-compiler/src/main/resources/Dubbo3TripleStub.mustache index 6f19d17fb1c..94572b36e42 100644 --- a/dubbo-plugin/dubbo-compiler/src/main/resources/Dubbo3TripleStub.mustache +++ b/dubbo-plugin/dubbo-compiler/src/main/resources/Dubbo3TripleStub.mustache @@ -1,19 +1,19 @@ /* -* 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. -*/ + * 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. + */ {{#packageName}} package {{packageName}}; @@ -47,7 +47,6 @@ import java.util.function.BiConsumer; import java.util.concurrent.CompletableFuture; public final class {{className}} { - public static final String SERVICE_NAME = {{interfaceClassName}}.SERVICE_NAME; private static final StubServiceDescriptor serviceDescriptor = new StubServiceDescriptor(SERVICE_NAME,{{interfaceClassName}}.class); @@ -64,7 +63,6 @@ public final class {{className}} { public static {{interfaceClassName}} newStub(Invoker invoker) { return new {{interfaceClassName}}Stub((Invoker<{{interfaceClassName}}>)invoker); } - {{#unaryMethods}} {{#javaDoc}} {{{javaDoc}}} @@ -84,7 +82,6 @@ public final class {{className}} { obj -> ((Message) obj).toByteArray(), obj -> ((Message) obj).toByteArray(), {{inputType}}::parseFrom, {{outputType}}::parseFrom); {{/unaryMethods}} - {{#serverStreamingMethods}} {{#javaDoc}} {{{javaDoc}}} @@ -94,7 +91,6 @@ public final class {{className}} { obj -> ((Message) obj).toByteArray(), obj -> ((Message) obj).toByteArray(), {{inputType}}::parseFrom, {{outputType}}::parseFrom); {{/serverStreamingMethods}} - {{#clientStreamingMethods}} {{#javaDoc}} {{{javaDoc}}} @@ -104,7 +100,6 @@ public final class {{className}} { obj -> ((Message) obj).toByteArray(), obj -> ((Message) obj).toByteArray(), {{inputType}}::parseFrom, {{outputType}}::parseFrom); {{/clientStreamingMethods}} - {{#biStreamingWithoutClientStreamMethods}} {{#javaDoc}} {{{javaDoc}}} @@ -142,52 +137,32 @@ public final class {{className}} { public void $destroy() { invoker.destroy(); } - {{#unaryMethods}} - {{#javaDoc}} - {{{javaDoc}}} - {{/javaDoc}} @Override public {{outputType}} {{methodName}}({{inputType}} request){ return StubInvocationUtil.unaryCall(invoker, {{methodName}}Method, request); } - public CompletableFuture<{{outputType}}> {{methodName}}Async({{inputType}} request){ return StubInvocationUtil.unaryCall(invoker, {{methodName}}AsyncMethod, request); } - {{#javaDoc}} - {{{javaDoc}}} - {{/javaDoc}} public void {{methodName}}({{inputType}} request, StreamObserver<{{outputType}}> responseObserver){ StubInvocationUtil.unaryCall(invoker, {{methodName}}Method , request, responseObserver); } {{/unaryMethods}} - {{#serverStreamingMethods}} - {{#javaDoc}} - {{{javaDoc}}} - {{/javaDoc}} @Override public void {{methodName}}({{inputType}} request, StreamObserver<{{outputType}}> responseObserver){ StubInvocationUtil.serverStreamCall(invoker, {{methodName}}Method , request, responseObserver); } {{/serverStreamingMethods}} - {{#biStreamingWithoutClientStreamMethods}} - {{#javaDoc}} - {{{javaDoc}}} - {{/javaDoc}} @Override public StreamObserver<{{inputType}}> {{methodName}}(StreamObserver<{{outputType}}> responseObserver){ return StubInvocationUtil.biOrClientStreamCall(invoker, {{methodName}}Method , responseObserver); } {{/biStreamingWithoutClientStreamMethods}} - {{#clientStreamingMethods}} - {{#javaDoc}} - {{{javaDoc}}} - {{/javaDoc}} @Override public StreamObserver<{{inputType}}> {{methodName}}(StreamObserver<{{outputType}}> responseObserver){ return StubInvocationUtil.biOrClientStreamCall(invoker, {{methodName}}Method , responseObserver); @@ -196,7 +171,6 @@ public final class {{className}} { } public static abstract class {{interfaceClassName}}ImplBase implements {{interfaceClassName}}, ServerService<{{interfaceClassName}}> { - private BiConsumer> syncToAsync(java.util.function.Function syncFun) { return new BiConsumer>() { @Override @@ -211,7 +185,6 @@ public final class {{className}} { } }; } - {{#unaryMethods}} @Override public CompletableFuture<{{outputType}}> {{methodName}}Async({{inputType}} request){ @@ -219,10 +192,8 @@ public final class {{className}} { } {{/unaryMethods}} - /** - * This server stream type unary method is only used for generated stub to support async unary method. - * It will not be called if you are NOT using Dubbo3 generated triple stub and DO NOT implement this method. - */ + // This server stream type unary method is only used for generated stub to support async unary method. + // It will not be called if you are NOT using Dubbo3 generated triple stub and DO NOT implement this method. {{#unaryMethods}} public void {{methodName}}({{inputType}} request, StreamObserver<{{outputType}}> responseObserver){ {{methodName}}Async(request).whenComplete((r, t) -> { @@ -242,68 +213,50 @@ public final class {{className}} { .getExtensionLoader(PathResolver.class) .getDefaultExtension(); Map> handlers = new HashMap<>(); - {{#methods}} pathResolver.addNativeStub( "/" + SERVICE_NAME + "/{{originMethodName}}"); pathResolver.addNativeStub( "/" + SERVICE_NAME + "/{{originMethodName}}Async"); // for compatibility pathResolver.addNativeStub( "/" + JAVA_SERVICE_NAME + "/{{originMethodName}}"); pathResolver.addNativeStub( "/" + JAVA_SERVICE_NAME + "/{{originMethodName}}Async"); - {{/methods}} - {{#unaryMethods}} BiConsumer<{{inputType}}, StreamObserver<{{outputType}}>> {{methodName}}Func = this::{{methodName}}; handlers.put({{methodName}}Method.getMethodName(), new UnaryStubMethodHandler<>({{methodName}}Func)); BiConsumer<{{inputType}}, StreamObserver<{{outputType}}>> {{methodName}}AsyncFunc = syncToAsync(this::{{methodName}}); handlers.put({{methodName}}ProxyAsyncMethod.getMethodName(), new UnaryStubMethodHandler<>({{methodName}}AsyncFunc)); {{/unaryMethods}} - {{#serverStreamingMethods}} handlers.put({{methodName}}Method.getMethodName(), new ServerStreamMethodHandler<>(this::{{methodName}})); {{/serverStreamingMethods}} - {{#clientStreamingMethods}} handlers.put({{methodName}}Method.getMethodName(), new BiStreamMethodHandler<>(this::{{methodName}})); {{/clientStreamingMethods}} - {{#biStreamingWithoutClientStreamMethods}} handlers.put({{methodName}}Method.getMethodName(), new BiStreamMethodHandler<>(this::{{methodName}})); {{/biStreamingWithoutClientStreamMethods}} return new StubInvoker<>(this, url, {{interfaceClassName}}.class, handlers); } - - {{#unaryMethods}} @Override public {{outputType}} {{methodName}}({{inputType}} request){ throw unimplementedMethodException({{methodName}}Method); } - {{/unaryMethods}} - {{#serverStreamingMethods}} - {{#javaDoc}} - {{{javaDoc}}} - {{/javaDoc}} @Override public void {{methodName}}({{inputType}} request, StreamObserver<{{outputType}}> responseObserver){ throw unimplementedMethodException({{methodName}}Method); } {{/serverStreamingMethods}} - {{#biStreamingWithoutClientStreamMethods}} @Override public StreamObserver<{{inputType}}> {{methodName}}(StreamObserver<{{outputType}}> responseObserver){ throw unimplementedMethodException({{methodName}}Method); } {{/biStreamingWithoutClientStreamMethods}} - {{#clientStreamingMethods}} - {{#javaDoc}} - {{{javaDoc}}} - {{/javaDoc}} @Override public StreamObserver<{{inputType}}> {{methodName}}(StreamObserver<{{outputType}}> responseObserver){ throw unimplementedMethodException({{methodName}}Method); @@ -319,5 +272,4 @@ public final class {{className}} { "/" + serviceDescriptor.getInterfaceName() + "/" + methodDescriptor.getMethodName())).asException(); } } - } diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/stub/annotations/GRequest.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/stub/annotations/GRequest.java new file mode 100644 index 00000000000..4e6144f908f --- /dev/null +++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/stub/annotations/GRequest.java @@ -0,0 +1,30 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.dubbo.rpc.stub.annotations; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target(ElementType.PARAMETER) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface GRequest { + String value() default ""; +} diff --git a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/support/basic/GRequestArgumentResolver.java b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/support/basic/GRequestArgumentResolver.java new file mode 100644 index 00000000000..7651892c6b5 --- /dev/null +++ b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/support/basic/GRequestArgumentResolver.java @@ -0,0 +1,85 @@ +/* + * 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.protocol.tri.rest.support.basic; + +import org.apache.dubbo.common.extension.Activate; +import org.apache.dubbo.common.utils.JsonUtils; +import org.apache.dubbo.remoting.http12.HttpRequest; +import org.apache.dubbo.remoting.http12.HttpResponse; +import org.apache.dubbo.remoting.http12.exception.DecodeException; +import org.apache.dubbo.remoting.http12.message.HttpMessageDecoder; +import org.apache.dubbo.rpc.protocol.tri.rest.RestConstants; +import org.apache.dubbo.rpc.protocol.tri.rest.argument.AnnotationBaseArgumentResolver; +import org.apache.dubbo.rpc.protocol.tri.rest.mapping.meta.AnnotationMeta; +import org.apache.dubbo.rpc.protocol.tri.rest.mapping.meta.ParameterMeta; +import org.apache.dubbo.rpc.stub.annotations.GRequest; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.util.HashMap; +import java.util.Map; + +@Activate +public class GRequestArgumentResolver implements AnnotationBaseArgumentResolver { + + @Override + public Class accept() { + return GRequest.class; + } + + @Override + public Object resolve( + ParameterMeta parameter, AnnotationMeta annotation, HttpRequest request, HttpResponse response) { + HttpMessageDecoder decoder = request.attribute(RestConstants.BODY_DECODER_ATTRIBUTE); + if (decoder == null) { + return null; + } + + Map value = new HashMap<>(); + Map variableMap = request.attribute(RestConstants.URI_TEMPLATE_VARIABLES_ATTRIBUTE); + if (variableMap != null) { + value.putAll(variableMap); + } + + InputStream is = request.inputStream(); + try { + int available = is.available(); + if (available > 0) { + Object body = decoder.decode(is, Object.class, request.charsetOrDefault()); + if (body instanceof Map) { + @SuppressWarnings("unchecked") + Map bodyMap = (Map) body; + String key = annotation.getValue(); + if ("*".equals(key) || key.isEmpty()) { + value.putAll(bodyMap); + } else { + value.put(key, bodyMap.get(key)); + } + } + } + } catch (IOException e) { + throw new DecodeException("Error reading input", e); + } + + return decoder.decode( + new ByteArrayInputStream(JsonUtils.toJson(value).getBytes(StandardCharsets.UTF_8)), + parameter.getType(), + StandardCharsets.UTF_8); + } +} diff --git a/dubbo-rpc/dubbo-rpc-triple/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.protocol.tri.rest.argument.ArgumentResolver b/dubbo-rpc/dubbo-rpc-triple/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.protocol.tri.rest.argument.ArgumentResolver index 0486f00884a..829c373182f 100644 --- a/dubbo-rpc/dubbo-rpc-triple/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.protocol.tri.rest.argument.ArgumentResolver +++ b/dubbo-rpc/dubbo-rpc-triple/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.protocol.tri.rest.argument.ArgumentResolver @@ -1,3 +1,4 @@ misc=org.apache.dubbo.rpc.protocol.tri.rest.argument.MiscArgumentResolver basic-param=org.apache.dubbo.rpc.protocol.tri.rest.support.basic.ParamArgumentResolver basic-fallback=org.apache.dubbo.rpc.protocol.tri.rest.support.basic.FallbackArgumentResolver +grpc-request=org.apache.dubbo.rpc.protocol.tri.rest.support.basic.GRequestArgumentResolver From 5239ded0c9794399bc187029c60765c66e67f3c2 Mon Sep 17 00:00:00 2001 From: heliang666s <147408835+heliang666s@users.noreply.github.com> Date: Mon, 4 Nov 2024 20:08:46 +0800 Subject: [PATCH 03/19] optimize dubbo-triple-demo (#14858) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: 何亮 --- .../apache/dubbo/demo/GreeterServiceImpl.java | 9 ++++--- .../dubbo/demo/GreeterWrapperServiceImpl.java | 25 +++++++++++++++--- .../dubbo/demo/consumer/ApiConsumer.java | 5 ++-- .../demo/consumer/ApiWrapperConsumer.java | 9 ++++--- .../dubbo/demo/provider/ApiProvider.java | 3 +-- .../demo/provider/ApiWrapperProvider.java | 2 +- .../src/main/proto/helloworld.proto | 26 ++++++++++++++++--- 7 files changed, 62 insertions(+), 17 deletions(-) diff --git a/dubbo-demo/dubbo-demo-triple/src/main/java/org/apache/dubbo/demo/GreeterServiceImpl.java b/dubbo-demo/dubbo-demo-triple/src/main/java/org/apache/dubbo/demo/GreeterServiceImpl.java index f5919b72a7a..8ec0403c2bc 100644 --- a/dubbo-demo/dubbo-demo-triple/src/main/java/org/apache/dubbo/demo/GreeterServiceImpl.java +++ b/dubbo-demo/dubbo-demo-triple/src/main/java/org/apache/dubbo/demo/GreeterServiceImpl.java @@ -17,6 +17,7 @@ package org.apache.dubbo.demo; import org.apache.dubbo.common.stream.StreamObserver; +import org.apache.dubbo.demo.hello.GreeterService; import org.apache.dubbo.demo.hello.HelloReply; import org.apache.dubbo.demo.hello.HelloRequest; @@ -36,9 +37,11 @@ public HelloReply sayHello(HelloRequest request) { } @Override - public CompletableFuture sayHelloAsync(String name) { - LOGGER.info("Received sayHelloAsync request: {}", name); - return CompletableFuture.supplyAsync(() -> "Hello " + name); + public CompletableFuture sayHelloAsync(HelloRequest request) { + LOGGER.info("Received sayHelloAsync request: {}", request.getName()); + HelloReply.newBuilder().setMessage("Hello " + request.getName()); + return CompletableFuture.supplyAsync(() -> + HelloReply.newBuilder().setMessage("Hello " + request.getName()).build()); } @Override diff --git a/dubbo-demo/dubbo-demo-triple/src/main/java/org/apache/dubbo/demo/GreeterWrapperServiceImpl.java b/dubbo-demo/dubbo-demo-triple/src/main/java/org/apache/dubbo/demo/GreeterWrapperServiceImpl.java index 5fb68739f8d..9af186a2197 100644 --- a/dubbo-demo/dubbo-demo-triple/src/main/java/org/apache/dubbo/demo/GreeterWrapperServiceImpl.java +++ b/dubbo-demo/dubbo-demo-triple/src/main/java/org/apache/dubbo/demo/GreeterWrapperServiceImpl.java @@ -16,14 +16,33 @@ */ package org.apache.dubbo.demo; +import org.apache.dubbo.demo.hello.GreeterWrapperService; +import org.apache.dubbo.demo.hello.HelloReply; +import org.apache.dubbo.demo.hello.HelloRequest; + +import java.util.concurrent.CompletableFuture; + public class GreeterWrapperServiceImpl implements GreeterWrapperService { @Override - public String sayHello(String request) { - StringBuilder responseBuilder = new StringBuilder(request); + public HelloReply sayHello(HelloRequest request) { + StringBuilder responseBuilder = new StringBuilder(request.getName()); for (int i = 0; i < 20; i++) { responseBuilder.append(responseBuilder); } - return responseBuilder.toString(); + return HelloReply.newBuilder().setMessage(responseBuilder.toString()).build(); + } + + @Override + public CompletableFuture sayHelloAsync(HelloRequest request) { + return CompletableFuture.supplyAsync(() -> { + StringBuilder responseBuilder = new StringBuilder(request.getName()); + for (int i = 0; i < 20; i++) { + responseBuilder.append(responseBuilder); + } + return HelloReply.newBuilder() + .setMessage(responseBuilder.toString()) + .build(); + }); } } diff --git a/dubbo-demo/dubbo-demo-triple/src/main/java/org/apache/dubbo/demo/consumer/ApiConsumer.java b/dubbo-demo/dubbo-demo-triple/src/main/java/org/apache/dubbo/demo/consumer/ApiConsumer.java index 6a78b12f379..0ad003b5ceb 100644 --- a/dubbo-demo/dubbo-demo-triple/src/main/java/org/apache/dubbo/demo/consumer/ApiConsumer.java +++ b/dubbo-demo/dubbo-demo-triple/src/main/java/org/apache/dubbo/demo/consumer/ApiConsumer.java @@ -23,7 +23,7 @@ import org.apache.dubbo.config.ReferenceConfig; import org.apache.dubbo.config.RegistryConfig; import org.apache.dubbo.config.bootstrap.DubboBootstrap; -import org.apache.dubbo.demo.GreeterService; +import org.apache.dubbo.demo.hello.GreeterService; import org.apache.dubbo.demo.hello.HelloReply; import org.apache.dubbo.demo.hello.HelloRequest; import org.apache.dubbo.rpc.Constants; @@ -60,7 +60,8 @@ public static void main(String[] args) throws InterruptedException { System.out.println("sayHello reply: " + reply.getMessage()); System.out.println("Call sayHelloAsync"); - CompletableFuture sayHelloAsync = greeterService.sayHelloAsync("triple"); + CompletableFuture sayHelloAsync = greeterService.sayHelloAsync( + HelloRequest.newBuilder().setName("triple").build()); sayHelloAsync.thenAccept(value -> System.out.println("sayHelloAsync reply: " + value)); StreamObserver responseObserver = new StreamObserver() { diff --git a/dubbo-demo/dubbo-demo-triple/src/main/java/org/apache/dubbo/demo/consumer/ApiWrapperConsumer.java b/dubbo-demo/dubbo-demo-triple/src/main/java/org/apache/dubbo/demo/consumer/ApiWrapperConsumer.java index 074dc9d2964..387f5137d1c 100644 --- a/dubbo-demo/dubbo-demo-triple/src/main/java/org/apache/dubbo/demo/consumer/ApiWrapperConsumer.java +++ b/dubbo-demo/dubbo-demo-triple/src/main/java/org/apache/dubbo/demo/consumer/ApiWrapperConsumer.java @@ -22,7 +22,9 @@ import org.apache.dubbo.config.ReferenceConfig; import org.apache.dubbo.config.RegistryConfig; import org.apache.dubbo.config.bootstrap.DubboBootstrap; -import org.apache.dubbo.demo.GreeterWrapperService; +import org.apache.dubbo.demo.hello.GreeterWrapperService; +import org.apache.dubbo.demo.hello.HelloReply; +import org.apache.dubbo.demo.hello.HelloRequest; import org.apache.dubbo.rpc.Constants; import java.io.IOException; @@ -50,9 +52,10 @@ public static void main(String[] args) throws IOException { final GreeterWrapperService greeterWrapperService = referenceConfig.get(); System.out.println("dubbo referenceConfig started"); long st = System.currentTimeMillis(); - String reply = greeterWrapperService.sayHello("haha"); + HelloReply reply = greeterWrapperService.sayHello( + HelloRequest.newBuilder().setName("haha").build()); // 4MB response - System.out.println("Reply length:" + reply.length() + " cost:" + (System.currentTimeMillis() - st)); + System.out.println("Reply Message:" + reply.getMessage() + " cost:" + (System.currentTimeMillis() - st)); System.in.read(); } } diff --git a/dubbo-demo/dubbo-demo-triple/src/main/java/org/apache/dubbo/demo/provider/ApiProvider.java b/dubbo-demo/dubbo-demo-triple/src/main/java/org/apache/dubbo/demo/provider/ApiProvider.java index 91562677023..468319c0883 100644 --- a/dubbo-demo/dubbo-demo-triple/src/main/java/org/apache/dubbo/demo/provider/ApiProvider.java +++ b/dubbo-demo/dubbo-demo-triple/src/main/java/org/apache/dubbo/demo/provider/ApiProvider.java @@ -22,14 +22,13 @@ import org.apache.dubbo.config.RegistryConfig; import org.apache.dubbo.config.ServiceConfig; import org.apache.dubbo.config.bootstrap.DubboBootstrap; -import org.apache.dubbo.demo.GreeterService; import org.apache.dubbo.demo.GreeterServiceImpl; +import org.apache.dubbo.demo.hello.GreeterService; import org.apache.dubbo.rpc.Constants; import java.util.Collections; public class ApiProvider { - public static void main(String[] args) { ServiceConfig serviceConfig = new ServiceConfig<>(); serviceConfig.setInterface(GreeterService.class); diff --git a/dubbo-demo/dubbo-demo-triple/src/main/java/org/apache/dubbo/demo/provider/ApiWrapperProvider.java b/dubbo-demo/dubbo-demo-triple/src/main/java/org/apache/dubbo/demo/provider/ApiWrapperProvider.java index 27cdf25aff3..faeb49c3763 100644 --- a/dubbo-demo/dubbo-demo-triple/src/main/java/org/apache/dubbo/demo/provider/ApiWrapperProvider.java +++ b/dubbo-demo/dubbo-demo-triple/src/main/java/org/apache/dubbo/demo/provider/ApiWrapperProvider.java @@ -22,8 +22,8 @@ import org.apache.dubbo.config.RegistryConfig; import org.apache.dubbo.config.ServiceConfig; import org.apache.dubbo.config.bootstrap.DubboBootstrap; -import org.apache.dubbo.demo.GreeterWrapperService; import org.apache.dubbo.demo.GreeterWrapperServiceImpl; +import org.apache.dubbo.demo.hello.GreeterWrapperService; import org.apache.dubbo.rpc.Constants; import java.io.IOException; diff --git a/dubbo-demo/dubbo-demo-triple/src/main/proto/helloworld.proto b/dubbo-demo/dubbo-demo-triple/src/main/proto/helloworld.proto index f23688817e9..52c3ef756ec 100644 --- a/dubbo-demo/dubbo-demo-triple/src/main/proto/helloworld.proto +++ b/dubbo-demo/dubbo-demo-triple/src/main/proto/helloworld.proto @@ -20,10 +20,30 @@ package helloworld; // The request message containing the user's name. message HelloRequest { - string name = 1; + string name = 1; } -// The response message containing the greetings +// The response message containing the greetings. message HelloReply { - string message = 1; + string message = 1; +} + +// Service definition. +service GreeterService { + // Sends a greeting. + rpc sayHello(HelloRequest) returns (HelloReply); + + /** + * Sends a greeting with server streaming. + */ + rpc sayHelloServerStream(HelloRequest) returns (stream HelloReply); + + /** + * Sends greetings with bi-directional streaming. + */ + rpc sayHelloBiStream(stream HelloRequest) returns (stream HelloReply); +} +service GreeterWrapperService{ + // Sends a greeting. + rpc sayHello(HelloRequest) returns (HelloReply); } From 0ee4e6513e775417a26f44da1e9043f3be2b6afe Mon Sep 17 00:00:00 2001 From: Jermaine Hua Date: Wed, 6 Nov 2024 20:36:21 +0800 Subject: [PATCH 04/19] Upgrade github action version (#14847) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: “JermaineHua” --- .github/workflows/build-and-test-pr.yml | 98 ++++++++++--------- .../build-and-test-scheduled-3.1.yml | 52 +++++----- .../build-and-test-scheduled-3.2.yml | 52 +++++----- .../build-and-test-scheduled-3.3.yml | 52 +++++----- .github/workflows/release-test.yml | 54 +++++----- 5 files changed, 156 insertions(+), 152 deletions(-) diff --git a/.github/workflows/build-and-test-pr.yml b/.github/workflows/build-and-test-pr.yml index 00dfed43dd4..2db3a83be26 100644 --- a/.github/workflows/build-and-test-pr.yml +++ b/.github/workflows/build-and-test-pr.yml @@ -78,13 +78,13 @@ jobs: needs: check-format runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: "Check License" uses: apache/skywalking-eyes@e1a02359b239bd28de3f6d35fdc870250fa513d5 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: "Set up JDK 21" - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: distribution: 'zulu' java-version: 21 @@ -107,11 +107,11 @@ jobs: version: ${{ steps.dubbo-version.outputs.version }} steps: - name: "Checkout code" - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: path: dubbo - name: "Set up JDK" - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: distribution: 'zulu' java-version: 21 @@ -155,7 +155,7 @@ jobs: shopt -s globstar zip ${{ github.workspace }}/class.zip **/target/classes/* -r - name: "Upload class result" - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: "class-file" path: ${{ github.workspace }}/class.zip @@ -163,7 +163,7 @@ jobs: if: failure() run: zip ${{ github.workspace }}/checkstyle.zip *checkstyle* -r - name: "Upload checkstyle file if failure" - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 if: failure() with: name: "checkstyle-file" @@ -221,11 +221,11 @@ jobs: ZOOKEEPER_VERSION: 3.7.2 steps: - name: "Checkout code" - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: fetch-depth: 0 - name: "Set up JDK ${{ matrix.jdk }}" - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: distribution: 'zulu' java-version: 21 @@ -256,7 +256,7 @@ jobs: if: failure() run: cat test_errors.log - name: "Upload coverage result" - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: coverage-result path: "**/target/site/**/jacoco.xml" @@ -267,14 +267,14 @@ jobs: env: JOB_COUNT: 3 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: repository: 'apache/dubbo-samples' ref: master - name: "Prepare test list" run: bash ./test/scripts/prepare-test.sh - name: "Upload test list" - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: samples-test-list path: test/jobs @@ -289,9 +289,9 @@ jobs: strategy: fail-fast: false matrix: - job_id: [1, 2, 3] + job_id: [1,2,3] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: repository: 'apache/dubbo-samples' ref: master @@ -314,12 +314,12 @@ jobs: ${{ runner.os }}-dubbo-snapshot-${{ github.sha }} ${{ runner.os }}-dubbo-snapshot- - name: "Download test list" - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: samples-test-list path: test/jobs/ - name: "Set up JDK 8" - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: distribution: 'zulu' java-version: 8 @@ -335,9 +335,9 @@ jobs: - name: "merge jacoco result" run: cd test/dubbo-test-jacoco-merger && mvn clean compile exec:java -Dexec.mainClass="org.apache.dubbo.test.JacocoMerge" -Dexec.args="${{github.workspace}}" - name: "Upload jacoco" - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: - name: samples-jacoco-result + name: samples-jacoco-result-${{matrix.job_id}} path: target/jacoco*.exec - name: "Upload test result" if: always() @@ -352,7 +352,7 @@ jobs: env: JAVA_VER: 8 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: repository: 'apache/dubbo-samples' ref: master @@ -370,14 +370,14 @@ jobs: env: JOB_COUNT: 3 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: repository: 'apache/dubbo-integration-cases' ref: main - name: "Prepare test list" run: bash ./test/scripts/prepare-test.sh - name: "Upload test list" - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: test-list path: test/jobs @@ -392,9 +392,9 @@ jobs: strategy: fail-fast: false matrix: - job_id: [1, 2, 3] + job_id: [1,2,3] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: repository: 'apache/dubbo-integration-cases' ref: main @@ -417,12 +417,12 @@ jobs: ${{ runner.os }}-dubbo-snapshot-${{ github.sha }} ${{ runner.os }}-dubbo-snapshot- - name: "Download test list" - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: test-list path: test/jobs/ - name: "Set up JDK 8" - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: distribution: 'zulu' java-version: 8 @@ -438,9 +438,9 @@ jobs: - name: "merge jacoco result" run: cd test/dubbo-test-jacoco-merger && mvn clean compile exec:java -Dexec.mainClass="org.apache.dubbo.test.JacocoMerge" -Dexec.args="${{github.workspace}}" - name: "Upload jacoco" - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: - name: jacoco-result + name: jacoco-result-${{matrix.job_id}} path: target/jacoco*.exec - name: "Upload test result" if: always() @@ -455,7 +455,7 @@ jobs: env: JAVA_VER: 8 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: repository: 'apache/dubbo-integration-cases' ref: main @@ -471,56 +471,60 @@ jobs: runs-on: ubuntu-latest needs: [check-format, integration-test-result, samples-test-result, unit-test] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: path: "./dubbo" - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: repository: 'apache/dubbo-samples' path: "./dubbo-samples" - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: repository: 'apache/dubbo-integration-cases' path: "./dubbo-integration-cases" - name: "Set up JDK 21" - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: distribution: 'zulu' java-version: 21 - name: "Restore class result" - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: "class-file" + github-token: ${{ secrets.GITHUB_TOKEN }} path: ${{ github.workspace }} - name: "Unpack class result" run: | cd ${{ github.workspace }}/dubbo unzip -o ${{ github.workspace }}/class.zip - - name: "Restore jacoco exec" - uses: actions/download-artifact@v3 + - name: "Restore samples jacoco exec" + uses: actions/download-artifact@v4 with: - name: samples-jacoco-result + pattern: samples-jacoco-result-* + github-token: ${{ secrets.GITHUB_TOKEN }} path: dubbo-samples/target/ - - name: "Restore integration jacoco exec" - uses: actions/download-artifact@v3 + - name: "Restore integration test jacoco exec" + uses: actions/download-artifact@v4 with: - name: jacoco-result + pattern: jacoco-result-* + github-token: ${{ secrets.GITHUB_TOKEN }} path: dubbo-integration-cases/target/ - - name: "Merge jacoco result" + - name: "Merge samples jacoco result" run: | cd ${{ github.workspace }}/dubbo-samples/test/dubbo-test-jacoco-merger mvn clean compile exec:java -Dexec.mainClass="org.apache.dubbo.test.JacocoReport" -Dexec.args="${{github.workspace}}/dubbo-samples ${{github.workspace}}/dubbo" - - name: "Merge samples jacoco result" + - name: "Merge integration test jacoco result" run: | cd ${{ github.workspace }}/dubbo-integration-cases/test/dubbo-test-jacoco-merger mvn clean compile exec:java -Dexec.mainClass="org.apache.dubbo.test.JacocoReport" -Dexec.args="${{github.workspace}}/dubbo-integration-cases ${{github.workspace}}/dubbo" - name: "Restore coverage result" - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: coverage-result + github-token: ${{ secrets.GITHUB_TOKEN }} path: dubbo/ - name: "Upload coverage to Codecov" - uses: codecov/codecov-action@v3 + uses: codecov/codecov-action@v4 with: verbose: true @@ -528,16 +532,16 @@ jobs: needs: check-format runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: path: "./dubbo" - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: repository: 'apache/dubbo-test-tools' ref: main path: "./dubbo-test-tools" - name: "Set up JDK 21" - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: distribution: 'zulu' java-version: 21 @@ -563,7 +567,7 @@ jobs: - name: "Upload error code inspection result" # always() should not be used here, since we don't need to handle the 'canceled' situation. if: ${{ success() || failure() }} - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: "error-inspection-result" path: ${{ github.workspace }}/dubbo-test-tools/dubbo-error-code-inspector/error-inspection-result.txt @@ -572,7 +576,7 @@ jobs: needs: check-format runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: path: "./dubbo" - name: "Setup GraalVM environment" diff --git a/.github/workflows/build-and-test-scheduled-3.1.yml b/.github/workflows/build-and-test-scheduled-3.1.yml index a96d3663117..4de35db9f45 100644 --- a/.github/workflows/build-and-test-scheduled-3.1.yml +++ b/.github/workflows/build-and-test-scheduled-3.1.yml @@ -24,7 +24,7 @@ jobs: license: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: ref: "3.1" - name: Check License @@ -36,11 +36,11 @@ jobs: outputs: version: ${{ steps.dubbo-version.outputs.version }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: ref: "3.1" path: dubbo - - uses: actions/setup-java@v3 + - uses: actions/setup-java@v4 with: distribution: 'zulu' java-version: 8 @@ -66,7 +66,7 @@ jobs: run: 7z a ${{ github.workspace }}/checkstyle.zip *checkstyle* -r - name: "Upload checkstyle file if failure" if: failure() - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: "checkstyle-file" path: ${{ github.workspace }}/checkstyle.zip @@ -138,7 +138,7 @@ jobs: env: DISABLE_FILE_SYSTEM_TEST: true steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: ref: "3.1" - name: "Set up JDK ${{ matrix.jdk }}" @@ -184,9 +184,9 @@ jobs: DUBBO_DEFAULT_SERIALIZATION: fastjson2 MAVEN_SUREFIRE_ADD_OPENS: true steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: "Set up JDK ${{ matrix.jdk }}" - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: distribution: 'zulu' java-version: ${{ matrix.jdk }} @@ -228,7 +228,7 @@ jobs: env: JOB_COUNT: 5 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: repository: 'apache/dubbo-samples' ref: master @@ -236,7 +236,7 @@ jobs: run: | bash ./test/scripts/prepare-test.sh - name: "Upload test list" - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: samples-test-list path: test/jobs @@ -254,7 +254,7 @@ jobs: jdk: [ 8, 11 ] job_id: [1, 2, 3, 4, 5] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: repository: 'apache/dubbo-samples' ref: master @@ -275,7 +275,7 @@ jobs: ${{ runner.os }}-dubbo-snapshot-${{ github.sha }} ${{ runner.os }}-dubbo-snapshot- - name: "Download test list" - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: samples-test-list path: test/jobs/ @@ -295,7 +295,7 @@ jobs: run: cd test && bash ./run-tests.sh - name: "Upload test result" if: always() - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: samples-test-result-${{matrix.jdk}} path: test/jobs/*-result* @@ -309,12 +309,12 @@ jobs: matrix: jdk: [ 8, 11 ] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: repository: 'apache/dubbo-samples' ref: master - name: "Download test result" - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: samples-test-result-${{matrix.jdk}} path: test/jobs/ @@ -326,7 +326,7 @@ jobs: env: JOB_COUNT: 5 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: repository: 'apache/dubbo-integration-cases' ref: main @@ -334,7 +334,7 @@ jobs: run: | bash ./test/scripts/prepare-test.sh - name: "Upload test list" - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: integration-test-list path: test/jobs @@ -352,7 +352,7 @@ jobs: jdk: [ 8, 11 ] job_id: [1, 2, 3, 4, 5] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: repository: 'apache/dubbo-integration-cases' ref: main @@ -373,7 +373,7 @@ jobs: ${{ runner.os }}-dubbo-snapshot-${{ github.sha }} ${{ runner.os }}-dubbo-snapshot- - name: "Download test list" - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: integration-test-list path: test/jobs/ @@ -393,7 +393,7 @@ jobs: run: cd test && bash ./run-tests.sh - name: "Upload test result" if: always() - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: integration-test-result-${{matrix.jdk}} path: test/jobs/*-result* @@ -407,12 +407,12 @@ jobs: matrix: jdk: [ 8, 11 ] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: repository: 'apache/dubbo-integration-cases' ref: main - name: "Download test result" - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: integration-test-result-${{matrix.jdk}} path: test/jobs/ @@ -422,19 +422,19 @@ jobs: error-code-inspecting: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: ref: "3.1" path: "./dubbo" - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: repository: 'apache/dubbo-test-tools' ref: main path: "./dubbo-test-tools" - name: "Set up JDK 21" - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: distribution: 'zulu' java-version: 21 @@ -453,7 +453,7 @@ jobs: - name: "Upload error code inspection result" # always() should not be used here, since we don't need to handle the 'canceled' situation. if: ${{ success() || failure() }} - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: "error-inspection-result" path: ${{ github.workspace }}/dubbo-test-tools/dubbo-error-code-inspector/error-inspection-result.txt @@ -461,7 +461,7 @@ jobs: native-image-inspecting: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: ref: "3.1" path: "./dubbo" diff --git a/.github/workflows/build-and-test-scheduled-3.2.yml b/.github/workflows/build-and-test-scheduled-3.2.yml index 728fd2a2fcd..c58fd0ac8ad 100644 --- a/.github/workflows/build-and-test-scheduled-3.2.yml +++ b/.github/workflows/build-and-test-scheduled-3.2.yml @@ -24,7 +24,7 @@ jobs: license: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: ref: "3.2" - name: Check License @@ -36,11 +36,11 @@ jobs: outputs: version: ${{ steps.dubbo-version.outputs.version }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: ref: "3.2" path: dubbo - - uses: actions/setup-java@v3 + - uses: actions/setup-java@v4 with: distribution: 'zulu' java-version: 8 @@ -66,7 +66,7 @@ jobs: run: 7z a ${{ github.workspace }}/checkstyle.zip *checkstyle* -r - name: "Upload checkstyle file if failure" if: failure() - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: "checkstyle-file" path: ${{ github.workspace }}/checkstyle.zip @@ -138,7 +138,7 @@ jobs: env: DISABLE_FILE_SYSTEM_TEST: true steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: ref: "3.2" - name: "Set up JDK ${{ matrix.jdk }}" @@ -184,9 +184,9 @@ jobs: DUBBO_DEFAULT_SERIALIZATION: fastjson2 MAVEN_SUREFIRE_ADD_OPENS: true steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: "Set up JDK ${{ matrix.jdk }}" - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: distribution: 'zulu' java-version: ${{ matrix.jdk }} @@ -228,7 +228,7 @@ jobs: env: JOB_COUNT: 5 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: repository: 'apache/dubbo-samples' ref: master @@ -236,7 +236,7 @@ jobs: run: | bash ./test/scripts/prepare-test.sh - name: "Upload test list" - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: samples-test-list path: test/jobs @@ -254,7 +254,7 @@ jobs: jdk: [ 8, 11, 17, 21 ] job_id: [1, 2, 3, 4, 5] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: repository: 'apache/dubbo-samples' ref: master @@ -275,7 +275,7 @@ jobs: ${{ runner.os }}-dubbo-snapshot-${{ github.sha }} ${{ runner.os }}-dubbo-snapshot- - name: "Download test list" - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: samples-test-list path: test/jobs/ @@ -295,7 +295,7 @@ jobs: run: cd test && bash ./run-tests.sh - name: "Upload test result" if: always() - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: samples-test-result-${{matrix.jdk}} path: test/jobs/*-result* @@ -309,12 +309,12 @@ jobs: matrix: jdk: [ 8, 11, 17, 21 ] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: repository: 'apache/dubbo-samples' ref: master - name: "Download test result" - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: samples-test-result-${{matrix.jdk}} path: test/jobs/ @@ -326,7 +326,7 @@ jobs: env: JOB_COUNT: 5 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: repository: 'apache/dubbo-integration-cases' ref: main @@ -334,7 +334,7 @@ jobs: run: | bash ./test/scripts/prepare-test.sh - name: "Upload test list" - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: integration-test-list path: test/jobs @@ -352,7 +352,7 @@ jobs: jdk: [ 8, 11, 17, 21 ] job_id: [1, 2, 3, 4, 5] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: repository: 'apache/dubbo-integration-cases' ref: main @@ -373,7 +373,7 @@ jobs: ${{ runner.os }}-dubbo-snapshot-${{ github.sha }} ${{ runner.os }}-dubbo-snapshot- - name: "Download test list" - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: integration-test-list path: test/jobs/ @@ -393,7 +393,7 @@ jobs: run: cd test && bash ./run-tests.sh - name: "Upload test result" if: always() - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: integration-test-result-${{matrix.jdk}} path: test/jobs/*-result* @@ -407,12 +407,12 @@ jobs: matrix: jdk: [ 8, 11, 17, 21 ] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: repository: 'apache/dubbo-integration-cases' ref: main - name: "Download test result" - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: integration-test-result-${{matrix.jdk}} path: test/jobs/ @@ -422,19 +422,19 @@ jobs: error-code-inspecting: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: ref: "3.2" path: "./dubbo" - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: repository: 'apache/dubbo-test-tools' ref: main path: "./dubbo-test-tools" - name: "Set up JDK 21" - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: distribution: 'zulu' java-version: 21 @@ -453,7 +453,7 @@ jobs: - name: "Upload error code inspection result" # always() should not be used here, since we don't need to handle the 'canceled' situation. if: ${{ success() || failure() }} - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: "error-inspection-result" path: ${{ github.workspace }}/dubbo-test-tools/dubbo-error-code-inspector/error-inspection-result.txt @@ -461,7 +461,7 @@ jobs: native-image-inspecting: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: ref: "3.2" path: "./dubbo" diff --git a/.github/workflows/build-and-test-scheduled-3.3.yml b/.github/workflows/build-and-test-scheduled-3.3.yml index a0938d0a1cd..7bf6a993bbf 100644 --- a/.github/workflows/build-and-test-scheduled-3.3.yml +++ b/.github/workflows/build-and-test-scheduled-3.3.yml @@ -24,7 +24,7 @@ jobs: license: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: ref: "3.3" - name: Check License @@ -36,11 +36,11 @@ jobs: outputs: version: ${{ steps.dubbo-version.outputs.version }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: ref: "3.3" path: dubbo - - uses: actions/setup-java@v3 + - uses: actions/setup-java@v4 with: distribution: 'zulu' java-version: 21 @@ -66,7 +66,7 @@ jobs: run: 7z a ${{ github.workspace }}/checkstyle.zip *checkstyle* -r - name: "Upload checkstyle file if failure" if: failure() - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: "checkstyle-file" path: ${{ github.workspace }}/checkstyle.zip @@ -138,7 +138,7 @@ jobs: env: DISABLE_FILE_SYSTEM_TEST: true steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: ref: "3.3" - name: "Set up JDK ${{ matrix.jdk }}" @@ -184,9 +184,9 @@ jobs: DUBBO_DEFAULT_SERIALIZATION: fastjson2 MAVEN_SUREFIRE_ADD_OPENS: true steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: "Set up JDK ${{ matrix.jdk }}" - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: distribution: 'zulu' java-version: ${{ matrix.jdk }} @@ -228,7 +228,7 @@ jobs: env: JOB_COUNT: 5 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: repository: 'apache/dubbo-samples' ref: master @@ -236,7 +236,7 @@ jobs: run: | bash ./test/scripts/prepare-test.sh - name: "Upload test list" - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: samples-test-list path: test/jobs @@ -254,7 +254,7 @@ jobs: jdk: [ 8, 11, 17, 21 ] job_id: [1, 2, 3, 4, 5] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: repository: 'apache/dubbo-samples' ref: master @@ -275,7 +275,7 @@ jobs: ${{ runner.os }}-dubbo-snapshot-${{ github.sha }} ${{ runner.os }}-dubbo-snapshot- - name: "Download test list" - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: samples-test-list path: test/jobs/ @@ -295,7 +295,7 @@ jobs: run: cd test && bash ./run-tests.sh - name: "Upload test result" if: always() - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: samples-test-result-${{matrix.jdk}} path: test/jobs/*-result* @@ -309,12 +309,12 @@ jobs: matrix: jdk: [ 8, 11, 17, 21 ] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: repository: 'apache/dubbo-samples' ref: master - name: "Download test result" - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: samples-test-result-${{matrix.jdk}} path: test/jobs/ @@ -326,7 +326,7 @@ jobs: env: JOB_COUNT: 5 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: repository: 'apache/dubbo-integration-cases' ref: main @@ -334,7 +334,7 @@ jobs: run: | bash ./test/scripts/prepare-test.sh - name: "Upload test list" - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: integration-test-list path: test/jobs @@ -352,7 +352,7 @@ jobs: jdk: [ 8, 11, 17, 21 ] job_id: [1, 2, 3, 4, 5] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: repository: 'apache/dubbo-integration-cases' ref: main @@ -373,7 +373,7 @@ jobs: ${{ runner.os }}-dubbo-snapshot-${{ github.sha }} ${{ runner.os }}-dubbo-snapshot- - name: "Download test list" - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: integration-test-list path: test/jobs/ @@ -393,7 +393,7 @@ jobs: run: cd test && bash ./run-tests.sh - name: "Upload test result" if: always() - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: integration-test-result-${{matrix.jdk}} path: test/jobs/*-result* @@ -407,12 +407,12 @@ jobs: matrix: jdk: [ 8, 11, 17, 21 ] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: repository: 'apache/dubbo-integration-cases' ref: main - name: "Download test result" - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: integration-test-result-${{matrix.jdk}} path: test/jobs/ @@ -422,19 +422,19 @@ jobs: error-code-inspecting: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: ref: "3.3" path: "./dubbo" - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: repository: 'apache/dubbo-test-tools' ref: main path: "./dubbo-test-tools" - name: "Set up JDK 21" - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: distribution: 'zulu' java-version: 21 @@ -453,7 +453,7 @@ jobs: - name: "Upload error code inspection result" # always() should not be used here, since we don't need to handle the 'canceled' situation. if: ${{ success() || failure() }} - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: "error-inspection-result" path: ${{ github.workspace }}/dubbo-test-tools/dubbo-error-code-inspector/error-inspection-result.txt @@ -461,7 +461,7 @@ jobs: native-image-inspecting: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: ref: "3.3" path: "./dubbo" diff --git a/.github/workflows/release-test.yml b/.github/workflows/release-test.yml index 8e79ba80e3d..17c4b46b98f 100644 --- a/.github/workflows/release-test.yml +++ b/.github/workflows/release-test.yml @@ -25,7 +25,7 @@ jobs: license: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Check License uses: apache/skywalking-eyes@main env: @@ -35,10 +35,10 @@ jobs: outputs: version: ${{ steps.dubbo-version.outputs.version }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: path: dubbo - - uses: actions/setup-java@v3 + - uses: actions/setup-java@v4 with: distribution: 'zulu' java-version: 21 @@ -64,7 +64,7 @@ jobs: run: 7z a ${{ github.workspace }}/checkstyle.zip *checkstyle* -r - name: "Upload checkstyle file if failure" if: failure() - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: "checkstyle-file" path: ${{ github.workspace }}/checkstyle.zip @@ -136,9 +136,9 @@ jobs: env: DISABLE_FILE_SYSTEM_TEST: true steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: "Set up JDK ${{ matrix.jdk }}" - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: java-version: ${{ matrix.jdk }} distribution: 'zulu' @@ -181,9 +181,9 @@ jobs: DUBBO_DEFAULT_SERIALIZATION: fastjson2 MAVEN_SUREFIRE_ADD_OPENS: true steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: "Set up JDK ${{ matrix.jdk }}" - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: distribution: 'zulu' java-version: ${{ matrix.jdk }} @@ -225,7 +225,7 @@ jobs: env: JOB_COUNT: 5 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: repository: 'apache/dubbo-samples' ref: master @@ -233,7 +233,7 @@ jobs: run: | bash ./test/scripts/prepare-test.sh - name: "Upload test list" - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: samples-test-list path: test/jobs @@ -251,7 +251,7 @@ jobs: jdk: [ 8, 11, 17, 21 ] job_id: [1, 2, 3, 4, 5] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: repository: 'apache/dubbo-samples' ref: master @@ -272,7 +272,7 @@ jobs: ${{ runner.os }}-dubbo-snapshot-${{ github.sha }} ${{ runner.os }}-dubbo-snapshot- - name: "Download test list" - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: samples-test-list path: test/jobs/ @@ -292,7 +292,7 @@ jobs: run: cd test && bash ./run-tests.sh - name: "Upload test result" if: always() - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: samples-test-result-${{matrix.jdk}} path: test/jobs/*-result* @@ -306,12 +306,12 @@ jobs: matrix: jdk: [ 8, 11, 17, 21 ] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: repository: 'apache/dubbo-samples' ref: master - name: "Download test result" - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: samples-test-result-${{matrix.jdk}} path: test/jobs/ @@ -323,7 +323,7 @@ jobs: env: JOB_COUNT: 5 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: repository: 'apache/dubbo-integration-cases' ref: main @@ -331,7 +331,7 @@ jobs: run: | bash ./test/scripts/prepare-test.sh - name: "Upload test list" - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: integration-test-list path: test/jobs @@ -349,7 +349,7 @@ jobs: jdk: [ 8, 11, 17, 21 ] job_id: [1, 2, 3, 4, 5] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: repository: 'apache/dubbo-integration-cases' ref: main @@ -370,7 +370,7 @@ jobs: ${{ runner.os }}-dubbo-snapshot-${{ github.sha }} ${{ runner.os }}-dubbo-snapshot- - name: "Download test list" - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: integration-test-list path: test/jobs/ @@ -390,7 +390,7 @@ jobs: run: cd test && bash ./run-tests.sh - name: "Upload test result" if: always() - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: integration-test-result-${{matrix.jdk}} path: test/jobs/*-result* @@ -404,12 +404,12 @@ jobs: matrix: jdk: [ 8, 11, 17, 21 ] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: repository: 'apache/dubbo-integration-cases' ref: main - name: "Download test result" - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: integration-test-result-${{matrix.jdk}} path: test/jobs/ @@ -419,18 +419,18 @@ jobs: error-code-inspecting: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: path: "./dubbo" - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: repository: 'apache/dubbo-test-tools' ref: main path: "./dubbo-test-tools" - name: "Set up JDK 21" - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: java-version: 21 distribution: 'zulu' @@ -449,7 +449,7 @@ jobs: - name: "Upload error code inspection result" # always() should not be used here, since we don't need to handle the 'canceled' situation. if: ${{ success() || failure() }} - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: "error-inspection-result" path: ${{ github.workspace }}/dubbo-test-tools/dubbo-error-code-inspector/error-inspection-result.txt @@ -457,7 +457,7 @@ jobs: native-image-inspecting: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: path: "./dubbo" From a5eb2ee0285bfd8b0b85ddf774b8e046a2c4636e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 6 Nov 2024 20:37:20 +0800 Subject: [PATCH 05/19] Bump byte-buddy_version from 1.15.7 to 1.15.10 (#14856) Bumps `byte-buddy_version` from 1.15.7 to 1.15.10. Updates `net.bytebuddy:byte-buddy` from 1.15.7 to 1.15.10 - [Release notes](https://github.com/raphw/byte-buddy/releases) - [Changelog](https://github.com/raphw/byte-buddy/blob/master/release-notes.md) - [Commits](https://github.com/raphw/byte-buddy/compare/byte-buddy-1.15.7...byte-buddy-1.15.10) Updates `net.bytebuddy:byte-buddy-agent` from 1.15.7 to 1.15.10 - [Release notes](https://github.com/raphw/byte-buddy/releases) - [Changelog](https://github.com/raphw/byte-buddy/blob/master/release-notes.md) - [Commits](https://github.com/raphw/byte-buddy/compare/byte-buddy-1.15.7...byte-buddy-1.15.10) --- updated-dependencies: - dependency-name: net.bytebuddy:byte-buddy dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: net.bytebuddy:byte-buddy-agent dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- dubbo-dependencies-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dubbo-dependencies-bom/pom.xml b/dubbo-dependencies-bom/pom.xml index a9cdc007d06..855e3a5d10e 100644 --- a/dubbo-dependencies-bom/pom.xml +++ b/dubbo-dependencies-bom/pom.xml @@ -92,7 +92,7 @@ 5.3.39 5.8.15 3.30.2-GA - 1.15.7 + 1.15.10 3.2.10.Final 4.1.114.Final 0.0.28.Final From 007665f61bf2b64de11f298c7c9095929d1309a4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 6 Nov 2024 20:37:53 +0800 Subject: [PATCH 06/19] Bump org.apache.maven.plugins:maven-surefire-plugin from 3.5.1 to 3.5.2 (#14855) Bumps [org.apache.maven.plugins:maven-surefire-plugin](https://github.com/apache/maven-surefire) from 3.5.1 to 3.5.2. - [Release notes](https://github.com/apache/maven-surefire/releases) - [Commits](https://github.com/apache/maven-surefire/compare/surefire-3.5.1...surefire-3.5.2) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-surefire-plugin dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 02d93df0521..b592cadc462 100644 --- a/pom.xml +++ b/pom.xml @@ -132,7 +132,7 @@ 3.4.2 - 3.5.1 + 3.5.2 3.5.1 3.1.3 3.13.0 From a3a545052b850f4e828f83b47745aa818ae96cf2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 6 Nov 2024 20:38:36 +0800 Subject: [PATCH 07/19] Bump org.apache.maven.plugins:maven-javadoc-plugin from 3.10.1 to 3.11.1 (#14854) Bumps [org.apache.maven.plugins:maven-javadoc-plugin](https://github.com/apache/maven-javadoc-plugin) from 3.10.1 to 3.11.1. - [Release notes](https://github.com/apache/maven-javadoc-plugin/releases) - [Commits](https://github.com/apache/maven-javadoc-plugin/compare/maven-javadoc-plugin-3.10.1...maven-javadoc-plugin-3.11.1) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-javadoc-plugin dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index b592cadc462..69dd78eb2f4 100644 --- a/pom.xml +++ b/pom.xml @@ -137,7 +137,7 @@ 3.1.3 3.13.0 3.3.1 - 3.10.1 + 3.11.1 9.4.56.v20240826 3.6.0 0.8.12 From 909eb01a54846f4a487d94b9811e8430ca2ff6e3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 6 Nov 2024 21:25:23 +0800 Subject: [PATCH 08/19] Bump jackson_version from 2.18.0 to 2.18.1 (#14852) Bumps `jackson_version` from 2.18.0 to 2.18.1. Updates `com.fasterxml.jackson.core:jackson-core` from 2.18.0 to 2.18.1 - [Commits](https://github.com/FasterXML/jackson-core/compare/jackson-core-2.18.0...jackson-core-2.18.1) Updates `com.fasterxml.jackson.core:jackson-databind` from 2.18.0 to 2.18.1 - [Commits](https://github.com/FasterXML/jackson/commits) Updates `com.fasterxml.jackson.datatype:jackson-datatype-jsr310` from 2.18.0 to 2.18.1 Updates `com.fasterxml.jackson.core:jackson-annotations` from 2.18.0 to 2.18.1 - [Commits](https://github.com/FasterXML/jackson/commits) --- updated-dependencies: - dependency-name: com.fasterxml.jackson.core:jackson-core dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: com.fasterxml.jackson.core:jackson-databind dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: com.fasterxml.jackson.datatype:jackson-datatype-jsr310 dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: com.fasterxml.jackson.core:jackson-annotations dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- dubbo-dependencies-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dubbo-dependencies-bom/pom.xml b/dubbo-dependencies-bom/pom.xml index 855e3a5d10e..7bf5f82a3db 100644 --- a/dubbo-dependencies-bom/pom.xml +++ b/dubbo-dependencies-bom/pom.xml @@ -175,7 +175,7 @@ 5.4.3 2.0.6 2.11.0 - 2.18.0 + 2.18.1 6.1.26 2.0 1.6.0 From 7c7788d8b7cca3bf819a96a1ca3670802fffaf14 Mon Sep 17 00:00:00 2001 From: Ken Liu Date: Thu, 7 Nov 2024 17:12:23 +0800 Subject: [PATCH 09/19] Add preferred protocol support for application service discovery (#14849) * Support preferred protocol first for application service discovery. * Support preferred protocol first for application service discovery. * update comments * format code --- .../dubbo/common/ProtocolServiceKey.java | 2 +- .../ServiceDiscoveryRegistryDirectory.java | 47 ++++++++++++------- 2 files changed, 32 insertions(+), 17 deletions(-) diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/ProtocolServiceKey.java b/dubbo-common/src/main/java/org/apache/dubbo/common/ProtocolServiceKey.java index e4f5862c028..672ee8184a7 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/ProtocolServiceKey.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/ProtocolServiceKey.java @@ -90,7 +90,7 @@ public static boolean isMatch(ProtocolServiceKey rule, ProtocolServiceKey target } // 4.match protocol - // 4.1. if rule group is *, match all + // 4.1. if rule protocol is *, match all if (!CommonConstants.ANY_VALUE.equals(rule.getProtocol())) { // 4.2. if rule protocol is null, match all if (StringUtils.isNotEmpty(rule.getProtocol())) { diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistryDirectory.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistryDirectory.java index 74c35a746d4..d77c72bbc9d 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistryDirectory.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistryDirectory.java @@ -72,6 +72,7 @@ import static org.apache.dubbo.common.constants.CommonConstants.ENABLED_KEY; import static org.apache.dubbo.common.constants.CommonConstants.INSTANCE_REGISTER_MODE; import static org.apache.dubbo.common.constants.CommonConstants.IS_EXTRA; +import static org.apache.dubbo.common.constants.CommonConstants.PREFERRED_PROTOCOL; import static org.apache.dubbo.common.constants.CommonConstants.PROTOCOL_KEY; import static org.apache.dubbo.common.constants.CommonConstants.SIDE_KEY; import static org.apache.dubbo.common.constants.LoggerCodeConstants.PROTOCOL_FAILED_DESTROY_INVOKER; @@ -447,23 +448,12 @@ private Map> toInvokers( } // filter all the service available (version wildcard, group wildcard, protocol wildcard) - int port = instanceAddressURL.getPort(); List matchedProtocolServiceKeys = - instanceAddressURL.getMetadataInfo().getMatchedServiceInfos(consumerProtocolServiceKey).stream() - .filter(serviceInfo -> serviceInfo.getPort() <= 0 || serviceInfo.getPort() == port) - // special filter for extra protocols. - .filter(serviceInfo -> { - if (StringUtils.isNotEmpty( - consumerProtocolServiceKey - .getProtocol())) { // if consumer side protocol is specified, use all - // the protocols we got in hand now directly - return true; - } else { // if consumer side protocol is not specified, remove all extra protocols - return StringUtils.isEmpty(serviceInfo.getParameter(IS_EXTRA)); - } - }) - .map(MetadataInfo.ServiceInfo::getProtocolServiceKey) - .collect(Collectors.toList()); + getMatchedProtocolServiceKeys(instanceAddressURL, true); + if (CollectionUtils.isEmpty(matchedProtocolServiceKeys)) { + // if preferred protocol is not specified, use the default main protocol + matchedProtocolServiceKeys = getMatchedProtocolServiceKeys(instanceAddressURL, false); + } // see org.apache.dubbo.common.ProtocolServiceKey.isSameWith // check if needed to override the consumer url @@ -524,6 +514,31 @@ private Map> toInvokers( return newUrlInvokerMap; } + private List getMatchedProtocolServiceKeys( + InstanceAddressURL instanceAddressURL, boolean needPreferred) { + int port = instanceAddressURL.getPort(); + return instanceAddressURL.getMetadataInfo().getMatchedServiceInfos(consumerProtocolServiceKey).stream() + .filter(serviceInfo -> serviceInfo.getPort() <= 0 || serviceInfo.getPort() == port) + // special filter for extra protocols. + .filter(serviceInfo -> { + if (StringUtils.isNotEmpty( + consumerProtocolServiceKey + .getProtocol())) { // if consumer side protocol is specified, use all + // the protocols we got in hand now directly + return true; + } else { + // if consumer side protocol is not specified, choose the preferred or default main protocol + if (needPreferred) { + return serviceInfo.getProtocol().equals(serviceInfo.getParameter(PREFERRED_PROTOCOL)); + } else { + return StringUtils.isEmpty(serviceInfo.getParameter(IS_EXTRA)); + } + } + }) + .map(MetadataInfo.ServiceInfo::getProtocolServiceKey) + .collect(Collectors.toList()); + } + private boolean urlChanged(Invoker invoker, InstanceAddressURL newURL, ProtocolServiceKey protocolServiceKey) { InstanceAddressURL oldURL = (InstanceAddressURL) invoker.getUrl(); From 218aab1e4a0d7d3fd8ee9680829639f2685b621a Mon Sep 17 00:00:00 2001 From: Ken Liu Date: Thu, 7 Nov 2024 17:12:53 +0800 Subject: [PATCH 10/19] Update initial mapping apps of service discovery MappingListener (#14851) --- .../client/ServiceDiscoveryRegistry.java | 31 +++++++++++++------ 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistry.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistry.java index b2ded478955..f84255abeb7 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistry.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistry.java @@ -211,8 +211,12 @@ public void doSubscribe(URL url, NotifyListener listener) { mappingLock.lock(); mappingByUrl = serviceNameMapping.getMapping(url); try { - MappingListener mappingListener = new DefaultMappingListener(url, mappingByUrl, listener); + DefaultMappingListener mappingListener = new DefaultMappingListener(url, mappingByUrl, listener); mappingByUrl = serviceNameMapping.getAndListen(this.getUrl(), url, mappingListener); + // update the initial mapping apps we started to listen, to make sure it reflects the real value + // used do subscription before any event. + // it's protected by the mapping lock, so it won't override the event value. + mappingListener.updateInitialApps(mappingByUrl); synchronized (mappingListeners) { mappingListeners .computeIfAbsent(url.getProtocolServiceKey(), (k) -> new ConcurrentHashSet<>()) @@ -399,8 +403,8 @@ public Map getServiceListeners() { private class DefaultMappingListener implements MappingListener { private final ErrorTypeAwareLogger logger = LoggerFactory.getErrorTypeAwareLogger(DefaultMappingListener.class); private final URL url; - private Set oldApps; - private NotifyListener listener; + private final NotifyListener listener; + private volatile Set oldApps; private volatile boolean stopped; public DefaultMappingListener(URL subscribedURL, Set serviceNames, NotifyListener listener) { @@ -424,16 +428,15 @@ public synchronized void onEvent(MappingChangedEvent event) { Set newApps = event.getApps(); Set tempOldApps = oldApps; - if (CollectionUtils.isEmpty(newApps) || CollectionUtils.equals(newApps, tempOldApps)) { - return; - } - - logger.info( - "Mapping of service " + event.getServiceKey() + "changed from " + tempOldApps + " to " + newApps); - Lock mappingLock = serviceNameMapping.getMappingLock(event.getServiceKey()); try { mappingLock.lock(); + if (CollectionUtils.isEmpty(newApps) || CollectionUtils.equals(newApps, tempOldApps)) { + return; + } + logger.info("Mapping of service " + event.getServiceKey() + "changed from " + tempOldApps + " to " + + newApps); + if (CollectionUtils.isEmpty(tempOldApps) && !newApps.isEmpty()) { serviceNameMapping.putCachedMapping(ServiceNameMapping.buildMappingKey(url), newApps); subscribeURLs(url, listener, newApps); @@ -478,6 +481,14 @@ protected NotifyListener getListener() { return listener; } + // writing of oldApps is protected by mapping lock to guarantee sequence consistency. + public void updateInitialApps(Set oldApps) { + if (oldApps != null && !CollectionUtils.equals(oldApps, this.oldApps)) { + this.oldApps = oldApps; + logger.info("Update initial mapping apps from " + this.oldApps + " to " + oldApps); + } + } + @Override public void stop() { stopped = true; From f9a1793061399d7076536726c945b2293407fb76 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 7 Nov 2024 17:20:20 +0800 Subject: [PATCH 11/19] Bump org.apache.maven.plugins:maven-failsafe-plugin from 3.5.1 to 3.5.2 (#14857) Bumps [org.apache.maven.plugins:maven-failsafe-plugin](https://github.com/apache/maven-surefire) from 3.5.1 to 3.5.2. - [Release notes](https://github.com/apache/maven-surefire/releases) - [Commits](https://github.com/apache/maven-surefire/compare/surefire-3.5.1...surefire-3.5.2) --- updated-dependencies: - dependency-name: org.apache.maven.plugins:maven-failsafe-plugin dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 69dd78eb2f4..8a766adf335 100644 --- a/pom.xml +++ b/pom.xml @@ -133,7 +133,7 @@ 3.4.2 3.5.2 - 3.5.1 + 3.5.2 3.1.3 3.13.0 3.3.1 From 343a1ab70c5a692e7a0198e1333f01a112a29dc6 Mon Sep 17 00:00:00 2001 From: Sean Yang Date: Fri, 8 Nov 2024 22:26:41 +0800 Subject: [PATCH 12/19] Fix annotation configuration processor dependency missing (#14873) --- .../dubbo-spring-boot-autoconfigure/pom.xml | 7 +++++++ .../dubbo-spring-boot-autoconfigure-compatible/pom.xml | 6 ------ 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/dubbo-spring-boot-project/dubbo-spring-boot-autoconfigure/pom.xml b/dubbo-spring-boot-project/dubbo-spring-boot-autoconfigure/pom.xml index e1a78863fa4..665f791a606 100644 --- a/dubbo-spring-boot-project/dubbo-spring-boot-autoconfigure/pom.xml +++ b/dubbo-spring-boot-project/dubbo-spring-boot-autoconfigure/pom.xml @@ -54,6 +54,13 @@ true + + + org.springframework.boot + spring-boot-configuration-processor + true + + org.apache.dubbo diff --git a/dubbo-spring-boot-project/dubbo-spring-boot-compatible/dubbo-spring-boot-autoconfigure-compatible/pom.xml b/dubbo-spring-boot-project/dubbo-spring-boot-compatible/dubbo-spring-boot-autoconfigure-compatible/pom.xml index 71e34522f99..d45aceca74b 100644 --- a/dubbo-spring-boot-project/dubbo-spring-boot-compatible/dubbo-spring-boot-autoconfigure-compatible/pom.xml +++ b/dubbo-spring-boot-project/dubbo-spring-boot-compatible/dubbo-spring-boot-autoconfigure-compatible/pom.xml @@ -67,12 +67,6 @@ ${project.version} - - org.springframework.boot - spring-boot-configuration-processor - true - - org.apache.dubbo dubbo-spring-boot From 59663c8da5e1be85ca758e4688fc2bdda878dae5 Mon Sep 17 00:00:00 2001 From: TomlongTK Date: Wed, 13 Nov 2024 10:47:07 +0800 Subject: [PATCH 13/19] WebSocket on Triple (#14390) * WebSocket on Triple * Resolve conflict * Fix issues Fix issues * Merge latest code * Change package * Merge latest code * Merge latest code * Use Filter instead of GenericFilter --- .artifacts | 2 + .../dubbo/config/nested/TripleConfig.java | 11 ++ .../dubbo/config/nested/WebSocketConfig.java | 66 ++++++++ dubbo-dependencies-bom/pom.xml | 13 ++ dubbo-distribution/dubbo-all-shaded/pom.xml | 19 +++ dubbo-distribution/dubbo-all/pom.xml | 19 +++ dubbo-distribution/dubbo-bom/pom.xml | 10 ++ dubbo-distribution/dubbo-core-spi/pom.xml | 3 + .../protocol/tri/servlet/TripleFilter.java | 8 +- dubbo-plugin/dubbo-triple-websocket/pom.xml | 140 +++++++++++++++++ .../websocket/TripleBinaryMessageHandler.java | 42 ++++++ .../tri/websocket/TripleEndpoint.java | 93 ++++++++++++ .../websocket/TripleTextMessageHandler.java | 40 +++++ .../tri/websocket/TripleWebSocketFilter.java | 127 ++++++++++++++++ .../tri/websocket/WebSocketConstants.java | 26 ++++ .../tri/websocket/WebSocketStreamChannel.java | 142 ++++++++++++++++++ dubbo-plugin/pom.xml | 1 + .../remoting/http12/HttpHeaderNames.java | 2 + .../http12/LimitedByteArrayOutputStream.java | 61 ++++++++ .../dubbo-remoting-websocket/pom.xml | 41 +++++ .../remoting/websocket/FinalFragment.java | 22 +++ .../FinalFragmentByteArrayInputStream.java | 46 ++++++ .../FinalFragmentByteBufInputStream.java | 55 +++++++ .../FinalFragmentStreamingDecoder.java | 123 +++++++++++++++ .../websocket/WebSocketHeaderNames.java | 31 ++++ ...bSocketServerTransportListenerFactory.java | 29 ++++ .../websocket/WebSocketTransportListener.java | 21 +++ .../netty4/NettyWebSocketChannel.java | 87 +++++++++++ .../websocket/netty4/WebSocketFrameCodec.java | 140 +++++++++++++++++ .../WebSocketProtocolSelectorHandler.java | 71 +++++++++ .../netty4/WebSocketServerUpgradeCodec.java | 64 ++++++++ dubbo-remoting/pom.xml | 1 + .../java/org/apache/dubbo/rpc/Constants.java | 2 + dubbo-rpc/dubbo-rpc-triple/pom.xml | 5 + .../rpc/protocol/tri/TripleConstants.java | 2 + .../rpc/protocol/tri/TripleHttp2Protocol.java | 35 +++++ .../tri/rest/mapping/meta/MethodMeta.java | 2 +- .../basic/FallbackArgumentResolver.java | 4 + ...faultWebSocketServerTransportListener.java | 107 +++++++++++++ ...bSocketServerTransportListenerFactory.java | 35 +++++ .../WebSocketServerChannelObserver.java | 39 +++++ ...et.WebSocketServerTransportListenerFactory | 1 + .../dubbo-spring-boot-3-autoconfigure/pom.xml | 19 +++ .../DubboTriple3AutoConfiguration.java | 35 ++++- .../dubbo-spring-boot-autoconfigure/pom.xml | 19 +++ .../DubboTripleAutoConfiguration.java | 35 ++++- .../pom.xml | 6 + dubbo-test/dubbo-dependencies-all/pom.xml | 10 ++ 48 files changed, 1898 insertions(+), 14 deletions(-) create mode 100644 dubbo-common/src/main/java/org/apache/dubbo/config/nested/WebSocketConfig.java create mode 100644 dubbo-plugin/dubbo-triple-websocket/pom.xml create mode 100644 dubbo-plugin/dubbo-triple-websocket/src/main/java/org/apache/dubbo/rpc/protocol/tri/websocket/TripleBinaryMessageHandler.java create mode 100644 dubbo-plugin/dubbo-triple-websocket/src/main/java/org/apache/dubbo/rpc/protocol/tri/websocket/TripleEndpoint.java create mode 100644 dubbo-plugin/dubbo-triple-websocket/src/main/java/org/apache/dubbo/rpc/protocol/tri/websocket/TripleTextMessageHandler.java create mode 100644 dubbo-plugin/dubbo-triple-websocket/src/main/java/org/apache/dubbo/rpc/protocol/tri/websocket/TripleWebSocketFilter.java create mode 100644 dubbo-plugin/dubbo-triple-websocket/src/main/java/org/apache/dubbo/rpc/protocol/tri/websocket/WebSocketConstants.java create mode 100644 dubbo-plugin/dubbo-triple-websocket/src/main/java/org/apache/dubbo/rpc/protocol/tri/websocket/WebSocketStreamChannel.java create mode 100644 dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/LimitedByteArrayOutputStream.java create mode 100644 dubbo-remoting/dubbo-remoting-websocket/pom.xml create mode 100644 dubbo-remoting/dubbo-remoting-websocket/src/main/java/org/apache/dubbo/remoting/websocket/FinalFragment.java create mode 100644 dubbo-remoting/dubbo-remoting-websocket/src/main/java/org/apache/dubbo/remoting/websocket/FinalFragmentByteArrayInputStream.java create mode 100644 dubbo-remoting/dubbo-remoting-websocket/src/main/java/org/apache/dubbo/remoting/websocket/FinalFragmentByteBufInputStream.java create mode 100644 dubbo-remoting/dubbo-remoting-websocket/src/main/java/org/apache/dubbo/remoting/websocket/FinalFragmentStreamingDecoder.java create mode 100644 dubbo-remoting/dubbo-remoting-websocket/src/main/java/org/apache/dubbo/remoting/websocket/WebSocketHeaderNames.java create mode 100644 dubbo-remoting/dubbo-remoting-websocket/src/main/java/org/apache/dubbo/remoting/websocket/WebSocketServerTransportListenerFactory.java create mode 100644 dubbo-remoting/dubbo-remoting-websocket/src/main/java/org/apache/dubbo/remoting/websocket/WebSocketTransportListener.java create mode 100644 dubbo-remoting/dubbo-remoting-websocket/src/main/java/org/apache/dubbo/remoting/websocket/netty4/NettyWebSocketChannel.java create mode 100644 dubbo-remoting/dubbo-remoting-websocket/src/main/java/org/apache/dubbo/remoting/websocket/netty4/WebSocketFrameCodec.java create mode 100644 dubbo-remoting/dubbo-remoting-websocket/src/main/java/org/apache/dubbo/remoting/websocket/netty4/WebSocketProtocolSelectorHandler.java create mode 100644 dubbo-remoting/dubbo-remoting-websocket/src/main/java/org/apache/dubbo/remoting/websocket/netty4/WebSocketServerUpgradeCodec.java create mode 100644 dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/websocket/DefaultWebSocketServerTransportListener.java create mode 100644 dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/websocket/DefaultWebSocketServerTransportListenerFactory.java create mode 100644 dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/websocket/WebSocketServerChannelObserver.java create mode 100644 dubbo-rpc/dubbo-rpc-triple/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.remoting.websocket.WebSocketServerTransportListenerFactory diff --git a/.artifacts b/.artifacts index ef7445d6111..ef2d5e8ece8 100644 --- a/.artifacts +++ b/.artifacts @@ -75,6 +75,7 @@ dubbo-remoting dubbo-remoting-api dubbo-remoting-http12 dubbo-remoting-http3 +dubbo-remoting-websocket dubbo-remoting-netty dubbo-remoting-netty4 dubbo-remoting-zookeeper-curator5 @@ -116,3 +117,4 @@ dubbo-plugin-loom dubbo-rest-jaxrs dubbo-rest-spring dubbo-triple-servlet +dubbo-triple-websocket diff --git a/dubbo-common/src/main/java/org/apache/dubbo/config/nested/TripleConfig.java b/dubbo-common/src/main/java/org/apache/dubbo/config/nested/TripleConfig.java index 0e81f6f334d..854cb2d0518 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/config/nested/TripleConfig.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/config/nested/TripleConfig.java @@ -152,6 +152,9 @@ public class TripleConfig implements Serializable { @Nested private ServletConfig servlet; + @Nested + private WebSocketConfig websocket; + public Boolean getVerbose() { return verbose; } @@ -370,4 +373,12 @@ public ServletConfig getServlet() { public void setServlet(ServletConfig servlet) { this.servlet = servlet; } + + public WebSocketConfig getWebsocket() { + return websocket; + } + + public void setWebsocket(WebSocketConfig websocket) { + this.websocket = websocket; + } } diff --git a/dubbo-common/src/main/java/org/apache/dubbo/config/nested/WebSocketConfig.java b/dubbo-common/src/main/java/org/apache/dubbo/config/nested/WebSocketConfig.java new file mode 100644 index 00000000000..e2600f775b6 --- /dev/null +++ b/dubbo-common/src/main/java/org/apache/dubbo/config/nested/WebSocketConfig.java @@ -0,0 +1,66 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.dubbo.config.nested; + +import java.io.Serializable; + +public class WebSocketConfig implements Serializable { + + private static final long serialVersionUID = -2504271061733141988L; + + /** + * Whether to enable websocket support, requests are transport through the websocket container + *

The default value is false. + */ + private Boolean enabled; + + /** + * The URL patterns that the websocket filter will be registered for. + *

The default value is '/*'. + */ + private String[] filterUrlPatterns; + + /** + * The order of the websocket filter. + *

The default value is -1000000. + */ + private Integer filterOrder; + + public Boolean getEnabled() { + return enabled; + } + + public void setEnabled(Boolean enabled) { + this.enabled = enabled; + } + + public String[] getFilterUrlPatterns() { + return filterUrlPatterns; + } + + public void setFilterUrlPatterns(String[] filterUrlPatterns) { + this.filterUrlPatterns = filterUrlPatterns; + } + + public Integer getFilterOrder() { + return filterOrder; + } + + public void setFilterOrder(Integer filterOrder) { + this.filterOrder = filterOrder; + } +} diff --git a/dubbo-dependencies-bom/pom.xml b/dubbo-dependencies-bom/pom.xml index 7bf5f82a3db..024759105e8 100644 --- a/dubbo-dependencies-bom/pom.xml +++ b/dubbo-dependencies-bom/pom.xml @@ -108,6 +108,7 @@ 3.25.5 1.3.2 3.1.0 + 2.2.0 6.1.0 9.4.56.v20240826 3.1.0 @@ -462,6 +463,18 @@ ${jakarta_servlet_version} provided + + jakarta.websocket + jakarta.websocket-api + ${jakarta_websocket_version} + provided + + + jakarta.websocket + jakarta.websocket-client-api + ${jakarta_websocket_version} + provided + com.squareup.okhttp3 okhttp diff --git a/dubbo-distribution/dubbo-all-shaded/pom.xml b/dubbo-distribution/dubbo-all-shaded/pom.xml index 734d1e11488..6066525a2a9 100644 --- a/dubbo-distribution/dubbo-all-shaded/pom.xml +++ b/dubbo-distribution/dubbo-all-shaded/pom.xml @@ -283,6 +283,13 @@ compile true + + org.apache.dubbo + dubbo-triple-websocket + ${project.version} + compile + true + @@ -343,6 +350,13 @@ compile true + + org.apache.dubbo + dubbo-remoting-websocket + ${project.version} + compile + true + org.apache.dubbo dubbo-remoting-netty @@ -500,6 +514,7 @@ org.apache.dubbo:dubbo-remoting-api org.apache.dubbo:dubbo-remoting-http12 org.apache.dubbo:dubbo-remoting-http3 + org.apache.dubbo:dubbo-remoting-websocket org.apache.dubbo:dubbo-remoting-netty4 org.apache.dubbo:dubbo-remoting-netty org.apache.dubbo:dubbo-remoting-zookeeper-curator5 @@ -510,6 +525,7 @@ org.apache.dubbo:dubbo-rest-jaxrs org.apache.dubbo:dubbo-rest-spring org.apache.dubbo:dubbo-triple-servlet + org.apache.dubbo:dubbo-triple-websocket org.apache.dubbo:dubbo-serialization-api org.apache.dubbo:dubbo-serialization-hessian2 org.apache.dubbo:dubbo-serialization-fastjson2 @@ -745,6 +761,9 @@ META-INF/dubbo/internal/org.apache.dubbo.remoting.http3.Http3ServerTransportListenerFactory + + META-INF/dubbo/internal/org.apache.dubbo.remoting.websocket.WebSocketServerTransportListenerFactory + META-INF/dubbo/internal/org.apache.dubbo.remoting.telnet.TelnetHandler diff --git a/dubbo-distribution/dubbo-all/pom.xml b/dubbo-distribution/dubbo-all/pom.xml index 02b928d5ed1..7d6b9f81c37 100644 --- a/dubbo-distribution/dubbo-all/pom.xml +++ b/dubbo-distribution/dubbo-all/pom.xml @@ -283,6 +283,13 @@ compile true + + org.apache.dubbo + dubbo-triple-websocket + ${project.version} + compile + true + @@ -343,6 +350,13 @@ compile true + + org.apache.dubbo + dubbo-remoting-websocket + ${project.version} + compile + true + org.apache.dubbo dubbo-remoting-netty @@ -499,6 +513,7 @@ org.apache.dubbo:dubbo-remoting-api org.apache.dubbo:dubbo-remoting-http12 org.apache.dubbo:dubbo-remoting-http3 + org.apache.dubbo:dubbo-remoting-websocket org.apache.dubbo:dubbo-remoting-netty4 org.apache.dubbo:dubbo-remoting-netty org.apache.dubbo:dubbo-remoting-zookeeper-curator5 @@ -509,6 +524,7 @@ org.apache.dubbo:dubbo-rest-jaxrs org.apache.dubbo:dubbo-rest-spring org.apache.dubbo:dubbo-triple-servlet + org.apache.dubbo:dubbo-triple-websocket org.apache.dubbo:dubbo-serialization-api org.apache.dubbo:dubbo-serialization-hessian2 org.apache.dubbo:dubbo-serialization-fastjson2 @@ -743,6 +759,9 @@ META-INF/dubbo/internal/org.apache.dubbo.remoting.http3.Http3ServerTransportListenerFactory + + META-INF/dubbo/internal/org.apache.dubbo.remoting.websocket.WebSocketServerTransportListenerFactory + META-INF/dubbo/internal/org.apache.dubbo.remoting.telnet.TelnetHandler diff --git a/dubbo-distribution/dubbo-bom/pom.xml b/dubbo-distribution/dubbo-bom/pom.xml index 9a93aac9fc0..cf82bbd2ee9 100644 --- a/dubbo-distribution/dubbo-bom/pom.xml +++ b/dubbo-distribution/dubbo-bom/pom.xml @@ -339,6 +339,11 @@ dubbo-triple-servlet ${project.version} + + org.apache.dubbo + dubbo-triple-websocket + ${project.version} + @@ -395,6 +400,11 @@ dubbo-remoting-http3 ${project.version} + + org.apache.dubbo + dubbo-remoting-websocket + ${project.version} + org.apache.dubbo dubbo-remoting-netty diff --git a/dubbo-distribution/dubbo-core-spi/pom.xml b/dubbo-distribution/dubbo-core-spi/pom.xml index 431959407dc..e535005b44a 100644 --- a/dubbo-distribution/dubbo-core-spi/pom.xml +++ b/dubbo-distribution/dubbo-core-spi/pom.xml @@ -363,6 +363,9 @@ META-INF/dubbo/internal/org.apache.dubbo.remoting.http3.Http3ServerTransportListenerFactory + + META-INF/dubbo/internal/org.apache.dubbo.remoting.websocket.WebSocketServerTransportListenerFactory + META-INF/dubbo/internal/org.apache.dubbo.remoting.telnet.TelnetHandler diff --git a/dubbo-plugin/dubbo-triple-servlet/src/main/java/org/apache/dubbo/rpc/protocol/tri/servlet/TripleFilter.java b/dubbo-plugin/dubbo-triple-servlet/src/main/java/org/apache/dubbo/rpc/protocol/tri/servlet/TripleFilter.java index 891cc244409..e93ed1cd09c 100644 --- a/dubbo-plugin/dubbo-triple-servlet/src/main/java/org/apache/dubbo/rpc/protocol/tri/servlet/TripleFilter.java +++ b/dubbo-plugin/dubbo-triple-servlet/src/main/java/org/apache/dubbo/rpc/protocol/tri/servlet/TripleFilter.java @@ -59,6 +59,8 @@ import java.util.Arrays; import java.util.Set; +import static org.apache.dubbo.rpc.protocol.tri.TripleConstants.UPGRADE_HEADER_KEY; + public class TripleFilter implements Filter { private static final Logger LOGGER = LoggerFactory.getLogger(TripleFilter.class); @@ -86,7 +88,7 @@ public void doFilter(ServletRequest servletRequest, ServletResponse servletRespo return; } } else { - if (mappingRegistry.exists(request.getRequestURI(), request.getMethod())) { + if (!isUpgradeRequest(request) && mappingRegistry.exists(request.getRequestURI(), request.getMethod())) { handleHttp1(request, response); return; } @@ -188,6 +190,10 @@ private static int resolveTimeout(HttpServletRequest request, boolean isGrpc) { return 0; } + private boolean isUpgradeRequest(HttpServletRequest request) { + return request.getHeader(UPGRADE_HEADER_KEY) != null; + } + private static final class TripleAsyncListener implements AsyncListener { private final ServletStreamChannel streamChannel; diff --git a/dubbo-plugin/dubbo-triple-websocket/pom.xml b/dubbo-plugin/dubbo-triple-websocket/pom.xml new file mode 100644 index 00000000000..c7f465a66ad --- /dev/null +++ b/dubbo-plugin/dubbo-triple-websocket/pom.xml @@ -0,0 +1,140 @@ + + + + 4.0.0 + + org.apache.dubbo + dubbo-plugin + ${revision} + ../pom.xml + + + dubbo-triple-websocket + + + 4.0.1 + 1.1 + ${project.build.directory}/generated-sources/java/org/apache/dubbo/rpc/protocol/tri + + + + + org.apache.dubbo + dubbo-rpc-triple + ${project.version} + + + javax.servlet + javax.servlet-api + ${servlet4_version} + provided + + + jakarta.servlet + jakarta.servlet-api + provided + + + javax.websocket + javax.websocket-api + ${websocket_version} + provided + + + jakarta.websocket + jakarta.websocket-api + provided + + + jakarta.websocket + jakarta.websocket-client-api + provided + + + org.apache.dubbo + dubbo-remoting-netty4 + ${project.version} + test + + + + + + jdk-version-ge-17 + + [17,) + + + + + org.apache.maven.plugins + maven-antrun-plugin + + + copy-sources + + run + + generate-sources + + + + + + + + + + + + + + + + import org.apache.dubbo.rpc.protocol.tri.ServletExchanger; + + + + + + + + + org.codehaus.mojo + build-helper-maven-plugin + + + add-sources + + add-source + + generate-sources + + + ${project.build.directory}/generated-sources/java + + + + + + + + + + diff --git a/dubbo-plugin/dubbo-triple-websocket/src/main/java/org/apache/dubbo/rpc/protocol/tri/websocket/TripleBinaryMessageHandler.java b/dubbo-plugin/dubbo-triple-websocket/src/main/java/org/apache/dubbo/rpc/protocol/tri/websocket/TripleBinaryMessageHandler.java new file mode 100644 index 00000000000..a507f6f1e42 --- /dev/null +++ b/dubbo-plugin/dubbo-triple-websocket/src/main/java/org/apache/dubbo/rpc/protocol/tri/websocket/TripleBinaryMessageHandler.java @@ -0,0 +1,42 @@ +/* + * 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.protocol.tri.websocket; + +import org.apache.dubbo.remoting.http12.h2.Http2InputMessage; +import org.apache.dubbo.remoting.http12.h2.Http2InputMessageFrame; +import org.apache.dubbo.remoting.websocket.FinalFragmentByteArrayInputStream; +import org.apache.dubbo.remoting.websocket.WebSocketTransportListener; + +import javax.websocket.MessageHandler; + +import java.nio.ByteBuffer; + +public class TripleBinaryMessageHandler implements MessageHandler.Partial { + + private final WebSocketTransportListener webSocketTransportListener; + + public TripleBinaryMessageHandler(WebSocketTransportListener webSocketTransportListener) { + this.webSocketTransportListener = webSocketTransportListener; + } + + @Override + public void onMessage(ByteBuffer messagePart, boolean last) { + Http2InputMessage http2InputMessage = + new Http2InputMessageFrame(new FinalFragmentByteArrayInputStream(messagePart.array(), last), false); + webSocketTransportListener.onData(http2InputMessage); + } +} diff --git a/dubbo-plugin/dubbo-triple-websocket/src/main/java/org/apache/dubbo/rpc/protocol/tri/websocket/TripleEndpoint.java b/dubbo-plugin/dubbo-triple-websocket/src/main/java/org/apache/dubbo/rpc/protocol/tri/websocket/TripleEndpoint.java new file mode 100644 index 00000000000..54eb85fb6be --- /dev/null +++ b/dubbo-plugin/dubbo-triple-websocket/src/main/java/org/apache/dubbo/rpc/protocol/tri/websocket/TripleEndpoint.java @@ -0,0 +1,93 @@ +/* + * 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.protocol.tri.websocket; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.io.StreamUtils; +import org.apache.dubbo.config.context.ConfigManager; +import org.apache.dubbo.config.nested.TripleConfig; +import org.apache.dubbo.remoting.http12.HttpHeaderNames; +import org.apache.dubbo.remoting.http12.HttpHeaders; +import org.apache.dubbo.remoting.http12.HttpMethods; +import org.apache.dubbo.remoting.http12.HttpStatus; +import org.apache.dubbo.remoting.http12.h2.Http2Header; +import org.apache.dubbo.remoting.http12.h2.Http2InputMessage; +import org.apache.dubbo.remoting.http12.h2.Http2InputMessageFrame; +import org.apache.dubbo.remoting.http12.h2.Http2MetadataFrame; +import org.apache.dubbo.remoting.http12.message.DefaultHttpHeaders; +import org.apache.dubbo.remoting.websocket.WebSocketTransportListener; +import org.apache.dubbo.rpc.model.FrameworkModel; +import org.apache.dubbo.rpc.protocol.tri.ServletExchanger; + +import javax.websocket.CloseReason; +import javax.websocket.CloseReason.CloseCodes; +import javax.websocket.Endpoint; +import javax.websocket.EndpointConfig; +import javax.websocket.Session; + +import static org.apache.dubbo.rpc.protocol.tri.websocket.WebSocketConstants.TRIPLE_WEBSOCKET_LISTENER; + +public class TripleEndpoint extends Endpoint { + + @Override + public void onOpen(Session session, EndpointConfig config) { + String path = session.getRequestURI().getPath(); + HttpHeaders httpHeaders = new DefaultHttpHeaders(); + httpHeaders.set(HttpHeaderNames.PATH.getName(), path); + httpHeaders.set(HttpHeaderNames.METHOD.getName(), HttpMethods.POST.name()); + Http2Header http2Header = new Http2MetadataFrame(httpHeaders); + + URL url = ServletExchanger.getUrl(); + TripleConfig tripleConfig = ConfigManager.getProtocolOrDefault(url).getTripleOrDefault(); + + WebSocketStreamChannel webSocketStreamChannel = new WebSocketStreamChannel(session, tripleConfig); + WebSocketTransportListener webSocketTransportListener = + DefaultWebSocketServerTransportListenerFactory.INSTANCE.newInstance( + webSocketStreamChannel, url, FrameworkModel.defaultModel()); + webSocketTransportListener.onMetadata(http2Header); + session.addMessageHandler(new TripleTextMessageHandler(webSocketTransportListener)); + session.addMessageHandler(new TripleBinaryMessageHandler(webSocketTransportListener)); + session.getUserProperties().put(TRIPLE_WEBSOCKET_LISTENER, webSocketTransportListener); + } + + @Override + public void onClose(Session session, CloseReason closeReason) { + super.onClose(session, closeReason); + WebSocketTransportListener webSocketTransportListener = + (WebSocketTransportListener) session.getUserProperties().get(TRIPLE_WEBSOCKET_LISTENER); + if (webSocketTransportListener == null) { + return; + } + if (closeReason.getCloseCode().getCode() == CloseCodes.NORMAL_CLOSURE.getCode()) { + Http2InputMessage http2InputMessage = new Http2InputMessageFrame(StreamUtils.EMPTY, true); + webSocketTransportListener.onData(http2InputMessage); + return; + } + webSocketTransportListener.cancelByRemote(closeReason.getCloseCode().getCode()); + } + + @Override + public void onError(Session session, Throwable thr) { + super.onError(session, thr); + WebSocketTransportListener webSocketTransportListener = + (WebSocketTransportListener) session.getUserProperties().get(TRIPLE_WEBSOCKET_LISTENER); + if (webSocketTransportListener == null) { + return; + } + webSocketTransportListener.cancelByRemote(HttpStatus.INTERNAL_SERVER_ERROR.getCode()); + } +} diff --git a/dubbo-plugin/dubbo-triple-websocket/src/main/java/org/apache/dubbo/rpc/protocol/tri/websocket/TripleTextMessageHandler.java b/dubbo-plugin/dubbo-triple-websocket/src/main/java/org/apache/dubbo/rpc/protocol/tri/websocket/TripleTextMessageHandler.java new file mode 100644 index 00000000000..2aa962d6d18 --- /dev/null +++ b/dubbo-plugin/dubbo-triple-websocket/src/main/java/org/apache/dubbo/rpc/protocol/tri/websocket/TripleTextMessageHandler.java @@ -0,0 +1,40 @@ +/* + * 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.protocol.tri.websocket; + +import org.apache.dubbo.remoting.http12.h2.Http2InputMessage; +import org.apache.dubbo.remoting.http12.h2.Http2InputMessageFrame; +import org.apache.dubbo.remoting.websocket.FinalFragmentByteArrayInputStream; +import org.apache.dubbo.remoting.websocket.WebSocketTransportListener; + +import javax.websocket.MessageHandler; + +public class TripleTextMessageHandler implements MessageHandler.Partial { + + private final WebSocketTransportListener webSocketTransportListener; + + public TripleTextMessageHandler(WebSocketTransportListener webSocketTransportListener) { + this.webSocketTransportListener = webSocketTransportListener; + } + + @Override + public void onMessage(String messagePart, boolean last) { + Http2InputMessage http2InputMessage = + new Http2InputMessageFrame(new FinalFragmentByteArrayInputStream(messagePart.getBytes(), last), false); + webSocketTransportListener.onData(http2InputMessage); + } +} diff --git a/dubbo-plugin/dubbo-triple-websocket/src/main/java/org/apache/dubbo/rpc/protocol/tri/websocket/TripleWebSocketFilter.java b/dubbo-plugin/dubbo-triple-websocket/src/main/java/org/apache/dubbo/rpc/protocol/tri/websocket/TripleWebSocketFilter.java new file mode 100644 index 00000000000..90391a38141 --- /dev/null +++ b/dubbo-plugin/dubbo-triple-websocket/src/main/java/org/apache/dubbo/rpc/protocol/tri/websocket/TripleWebSocketFilter.java @@ -0,0 +1,127 @@ +/* + * 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.protocol.tri.websocket; + +import org.apache.dubbo.common.logger.ErrorTypeAwareLogger; +import org.apache.dubbo.common.logger.LoggerFactory; +import org.apache.dubbo.common.utils.ConcurrentHashSet; +import org.apache.dubbo.remoting.http12.HttpMethods; + +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletRequestWrapper; +import javax.servlet.http.HttpServletResponse; +import javax.websocket.server.ServerContainer; +import javax.websocket.server.ServerEndpointConfig; + +import java.io.IOException; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +import static org.apache.dubbo.common.constants.LoggerCodeConstants.PROTOCOL_FAILED_REQUEST; +import static org.apache.dubbo.rpc.protocol.tri.TripleConstants.UPGRADE_HEADER_KEY; +import static org.apache.dubbo.rpc.protocol.tri.websocket.WebSocketConstants.TRIPLE_WEBSOCKET_REMOTE_ADDRESS; +import static org.apache.dubbo.rpc.protocol.tri.websocket.WebSocketConstants.TRIPLE_WEBSOCKET_UPGRADE_HEADER_VALUE; + +public class TripleWebSocketFilter implements Filter { + + private static final ErrorTypeAwareLogger LOG = LoggerFactory.getErrorTypeAwareLogger(TripleWebSocketFilter.class); + + private transient ServerContainer sc; + + private final Set existed = new ConcurrentHashSet<>(); + + @Override + public void init(FilterConfig filterConfig) { + sc = (ServerContainer) filterConfig.getServletContext().getAttribute(ServerContainer.class.getName()); + } + + @Override + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) + throws IOException, ServletException { + if (!isWebSocketUpgradeRequest(request, response)) { + chain.doFilter(request, response); + return; + } + HttpServletRequest hRequest = (HttpServletRequest) request; + HttpServletResponse hResponse = (HttpServletResponse) response; + String path; + String pathInfo = hRequest.getPathInfo(); + if (pathInfo == null) { + path = hRequest.getServletPath(); + } else { + path = hRequest.getServletPath() + pathInfo; + } + Map copiedMap = new HashMap<>(hRequest.getParameterMap()); + copiedMap.put( + TRIPLE_WEBSOCKET_REMOTE_ADDRESS, + new String[] {hRequest.getRemoteHost(), String.valueOf(hRequest.getRemotePort())}); + HttpServletRequestWrapper wrappedRequest = new HttpServletRequestWrapper(hRequest) { + @Override + public Map getParameterMap() { + return copiedMap; + } + }; + if (existed.contains(path)) { + chain.doFilter(wrappedRequest, hResponse); + return; + } + ServerEndpointConfig serverEndpointConfig = + ServerEndpointConfig.Builder.create(TripleEndpoint.class, path).build(); + try { + sc.addEndpoint(serverEndpointConfig); + existed.add(path); + } catch (Exception e) { + LOG.error(PROTOCOL_FAILED_REQUEST, "", "", "Failed to add endpoint", e); + hResponse.sendError(HttpServletResponse.SC_BAD_REQUEST); + return; + } + chain.doFilter(wrappedRequest, hResponse); + } + + @Override + public void destroy() {} + + public boolean isWebSocketUpgradeRequest(ServletRequest request, ServletResponse response) { + return ((request instanceof HttpServletRequest) + && (response instanceof HttpServletResponse) + && headerContainsToken( + (HttpServletRequest) request, UPGRADE_HEADER_KEY, TRIPLE_WEBSOCKET_UPGRADE_HEADER_VALUE) + && HttpMethods.GET.name().equals(((HttpServletRequest) request).getMethod())); + } + + private boolean headerContainsToken(HttpServletRequest req, String headerName, String target) { + Enumeration headers = req.getHeaders(headerName); + while (headers.hasMoreElements()) { + String header = headers.nextElement(); + String[] tokens = header.split(","); + for (String token : tokens) { + if (target.equalsIgnoreCase(token.trim())) { + return true; + } + } + } + return false; + } +} diff --git a/dubbo-plugin/dubbo-triple-websocket/src/main/java/org/apache/dubbo/rpc/protocol/tri/websocket/WebSocketConstants.java b/dubbo-plugin/dubbo-triple-websocket/src/main/java/org/apache/dubbo/rpc/protocol/tri/websocket/WebSocketConstants.java new file mode 100644 index 00000000000..467e5ae318b --- /dev/null +++ b/dubbo-plugin/dubbo-triple-websocket/src/main/java/org/apache/dubbo/rpc/protocol/tri/websocket/WebSocketConstants.java @@ -0,0 +1,26 @@ +/* + * 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.protocol.tri.websocket; + +public interface WebSocketConstants { + + String TRIPLE_WEBSOCKET_UPGRADE_HEADER_VALUE = "websocket"; + + String TRIPLE_WEBSOCKET_REMOTE_ADDRESS = "tri.websocket.remote.address"; + + String TRIPLE_WEBSOCKET_LISTENER = "tri.websocket.listener"; +} diff --git a/dubbo-plugin/dubbo-triple-websocket/src/main/java/org/apache/dubbo/rpc/protocol/tri/websocket/WebSocketStreamChannel.java b/dubbo-plugin/dubbo-triple-websocket/src/main/java/org/apache/dubbo/rpc/protocol/tri/websocket/WebSocketStreamChannel.java new file mode 100644 index 00000000000..a92235883a6 --- /dev/null +++ b/dubbo-plugin/dubbo-triple-websocket/src/main/java/org/apache/dubbo/rpc/protocol/tri/websocket/WebSocketStreamChannel.java @@ -0,0 +1,142 @@ +/* + * 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.protocol.tri.websocket; + +import org.apache.dubbo.common.utils.CollectionUtils; +import org.apache.dubbo.config.nested.TripleConfig; +import org.apache.dubbo.remoting.http12.HttpHeaderNames; +import org.apache.dubbo.remoting.http12.HttpHeaders; +import org.apache.dubbo.remoting.http12.HttpMetadata; +import org.apache.dubbo.remoting.http12.HttpOutputMessage; +import org.apache.dubbo.remoting.http12.HttpStatus; +import org.apache.dubbo.remoting.http12.LimitedByteArrayOutputStream; +import org.apache.dubbo.remoting.http12.h2.H2StreamChannel; +import org.apache.dubbo.remoting.http12.h2.Http2Header; +import org.apache.dubbo.remoting.http12.h2.Http2OutputMessage; +import org.apache.dubbo.remoting.http12.h2.Http2OutputMessageFrame; +import org.apache.dubbo.remoting.websocket.WebSocketHeaderNames; + +import javax.websocket.CloseReason; +import javax.websocket.Session; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.net.InetSocketAddress; +import java.net.SocketAddress; +import java.nio.ByteBuffer; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CompletableFuture; + +import static org.apache.dubbo.rpc.protocol.tri.websocket.WebSocketConstants.TRIPLE_WEBSOCKET_REMOTE_ADDRESS; + +public class WebSocketStreamChannel implements H2StreamChannel { + + private final Session session; + + private final TripleConfig tripleConfig; + + private final InetSocketAddress remoteAddress; + + private final InetSocketAddress localAddress; + + public WebSocketStreamChannel(Session session, TripleConfig tripleConfig) { + this.session = session; + this.tripleConfig = tripleConfig; + Map> requestParameterMap = session.getRequestParameterMap(); + List remoteAddressData = requestParameterMap.get(TRIPLE_WEBSOCKET_REMOTE_ADDRESS); + this.remoteAddress = InetSocketAddress.createUnresolved( + remoteAddressData.get(0), Integer.parseInt(remoteAddressData.get(1))); + this.localAddress = InetSocketAddress.createUnresolved( + session.getRequestURI().getHost(), session.getRequestURI().getPort()); + } + + @Override + public CompletableFuture writeResetFrame(long errorCode) { + CompletableFuture completableFuture = new CompletableFuture<>(); + try { + session.close(); + completableFuture.complete(null); + } catch (IOException e) { + completableFuture.completeExceptionally(e); + } + return completableFuture; + } + + @Override + public Http2OutputMessage newOutputMessage(boolean endStream) { + return new Http2OutputMessageFrame( + new LimitedByteArrayOutputStream(256, tripleConfig.getMaxResponseBodySizeOrDefault()), endStream); + } + + @Override + public CompletableFuture writeHeader(HttpMetadata httpMetadata) { + Http2Header http2Header = (Http2Header) httpMetadata; + CompletableFuture completableFuture = new CompletableFuture<>(); + if (http2Header.isEndStream()) { + try { + session.close(encodeCloseReason(http2Header)); + completableFuture.complete(null); + } catch (IOException e) { + completableFuture.completeExceptionally(e); + } + } + return completableFuture; + } + + @Override + public CompletableFuture writeMessage(HttpOutputMessage httpOutputMessage) { + ByteArrayOutputStream body = (ByteArrayOutputStream) httpOutputMessage.getBody(); + CompletableFuture completableFuture = new CompletableFuture<>(); + try { + session.getBasicRemote().sendBinary(ByteBuffer.wrap(body.toByteArray())); + completableFuture.complete(null); + } catch (IOException e) { + completableFuture.completeExceptionally(e); + } + return completableFuture; + } + + @Override + public SocketAddress remoteAddress() { + return remoteAddress; + } + + @Override + public SocketAddress localAddress() { + return localAddress; + } + + @Override + public void flush() {} + + private CloseReason encodeCloseReason(Http2Header http2Header) { + HttpHeaders headers = http2Header.headers(); + List statusHeaders = headers.remove(HttpHeaderNames.STATUS.getName()); + CloseReason closeReason; + if (CollectionUtils.isNotEmpty(statusHeaders) + && !HttpStatus.OK.getStatusString().equals(statusHeaders.get(0))) { + List messageHeaders = headers.remove(WebSocketHeaderNames.WEBSOCKET_MESSAGE.getName()); + closeReason = new CloseReason( + CloseReason.CloseCodes.UNEXPECTED_CONDITION, + CollectionUtils.isNotEmpty(messageHeaders) ? messageHeaders.get(0) : "Internal server error"); + } else { + closeReason = new CloseReason(CloseReason.CloseCodes.NORMAL_CLOSURE, "Bye"); + } + return closeReason; + } +} diff --git a/dubbo-plugin/pom.xml b/dubbo-plugin/pom.xml index 1cfb0efb141..8a54f6b958d 100644 --- a/dubbo-plugin/pom.xml +++ b/dubbo-plugin/pom.xml @@ -43,6 +43,7 @@ dubbo-rest-jaxrs dubbo-rest-spring dubbo-triple-servlet + dubbo-triple-websocket false diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/HttpHeaderNames.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/HttpHeaderNames.java index 5272913d3ee..a701870f73d 100644 --- a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/HttpHeaderNames.java +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/HttpHeaderNames.java @@ -24,6 +24,8 @@ public enum HttpHeaderNames { PATH(PseudoHeaderName.PATH.value()), + METHOD(PseudoHeaderName.METHOD.value()), + ACCEPT(io.netty.handler.codec.http.HttpHeaderNames.ACCEPT), CONTENT_TYPE(io.netty.handler.codec.http.HttpHeaderNames.CONTENT_TYPE), diff --git a/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/LimitedByteArrayOutputStream.java b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/LimitedByteArrayOutputStream.java new file mode 100644 index 00000000000..7596f332ded --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/LimitedByteArrayOutputStream.java @@ -0,0 +1,61 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.dubbo.remoting.http12; + +import org.apache.dubbo.remoting.http12.exception.HttpOverPayloadException; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; + +public class LimitedByteArrayOutputStream extends ByteArrayOutputStream { + + private final int capacity; + + public LimitedByteArrayOutputStream(int capacity) { + super(); + this.capacity = capacity == 0 ? Integer.MAX_VALUE : capacity; + } + + public LimitedByteArrayOutputStream(int size, int capacity) { + super(size); + this.capacity = capacity == 0 ? Integer.MAX_VALUE : capacity; + } + + @Override + public void write(int b) { + ensureCapacity(1); + super.write(b); + } + + @Override + public void write(byte[] b) throws IOException { + ensureCapacity(b.length); + super.write(b); + } + + @Override + public void write(byte[] b, int off, int len) { + ensureCapacity(len); + super.write(b, off, len); + } + + private void ensureCapacity(int len) { + if (size() + len > capacity) { + throw new HttpOverPayloadException("Response Entity Too Large"); + } + } +} diff --git a/dubbo-remoting/dubbo-remoting-websocket/pom.xml b/dubbo-remoting/dubbo-remoting-websocket/pom.xml new file mode 100644 index 00000000000..b27869d056a --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-websocket/pom.xml @@ -0,0 +1,41 @@ + + + + 4.0.0 + + org.apache.dubbo + dubbo-remoting + ${revision} + ../pom.xml + + dubbo-remoting-websocket + jar + ${project.artifactId} + The websocket remoting module of dubbo project + + false + + + + + org.apache.dubbo + dubbo-remoting-http12 + ${project.parent.version} + + + diff --git a/dubbo-remoting/dubbo-remoting-websocket/src/main/java/org/apache/dubbo/remoting/websocket/FinalFragment.java b/dubbo-remoting/dubbo-remoting-websocket/src/main/java/org/apache/dubbo/remoting/websocket/FinalFragment.java new file mode 100644 index 00000000000..c3028962df7 --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-websocket/src/main/java/org/apache/dubbo/remoting/websocket/FinalFragment.java @@ -0,0 +1,22 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.dubbo.remoting.websocket; + +public interface FinalFragment { + + boolean isFinalFragment(); +} diff --git a/dubbo-remoting/dubbo-remoting-websocket/src/main/java/org/apache/dubbo/remoting/websocket/FinalFragmentByteArrayInputStream.java b/dubbo-remoting/dubbo-remoting-websocket/src/main/java/org/apache/dubbo/remoting/websocket/FinalFragmentByteArrayInputStream.java new file mode 100644 index 00000000000..0176e352656 --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-websocket/src/main/java/org/apache/dubbo/remoting/websocket/FinalFragmentByteArrayInputStream.java @@ -0,0 +1,46 @@ +/* + * 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.remoting.websocket; + +import java.io.ByteArrayInputStream; + +public class FinalFragmentByteArrayInputStream extends ByteArrayInputStream implements FinalFragment { + + private final boolean finalFragment; + + public FinalFragmentByteArrayInputStream(byte[] buf) { + this(buf, 0, buf.length); + } + + public FinalFragmentByteArrayInputStream(byte[] buf, boolean finalFragment) { + this(buf, 0, buf.length, finalFragment); + } + + public FinalFragmentByteArrayInputStream(byte[] buf, int offset, int length) { + this(buf, offset, length, false); + } + + public FinalFragmentByteArrayInputStream(byte[] buf, int offset, int length, boolean finalFragment) { + super(buf, offset, length); + this.finalFragment = finalFragment; + } + + @Override + public boolean isFinalFragment() { + return finalFragment; + } +} diff --git a/dubbo-remoting/dubbo-remoting-websocket/src/main/java/org/apache/dubbo/remoting/websocket/FinalFragmentByteBufInputStream.java b/dubbo-remoting/dubbo-remoting-websocket/src/main/java/org/apache/dubbo/remoting/websocket/FinalFragmentByteBufInputStream.java new file mode 100644 index 00000000000..5bd5e1fe944 --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-websocket/src/main/java/org/apache/dubbo/remoting/websocket/FinalFragmentByteBufInputStream.java @@ -0,0 +1,55 @@ +/* + * 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.remoting.websocket; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufInputStream; + +public class FinalFragmentByteBufInputStream extends ByteBufInputStream implements FinalFragment { + + private final boolean finalFragment; + + public FinalFragmentByteBufInputStream(ByteBuf buffer) { + this(buffer, buffer.readableBytes()); + } + + public FinalFragmentByteBufInputStream(ByteBuf buffer, int length) { + this(buffer, length, false); + } + + public FinalFragmentByteBufInputStream(ByteBuf buffer, boolean releaseOnClose) { + this(buffer, buffer.readableBytes(), releaseOnClose); + } + + public FinalFragmentByteBufInputStream(ByteBuf buffer, boolean releaseOnClose, boolean finalFragment) { + this(buffer, buffer.readableBytes(), releaseOnClose, finalFragment); + } + + public FinalFragmentByteBufInputStream(ByteBuf buffer, int length, boolean releaseOnClose) { + this(buffer, length, releaseOnClose, false); + } + + public FinalFragmentByteBufInputStream(ByteBuf buffer, int length, boolean releaseOnClose, boolean finalFragment) { + super(buffer, length, releaseOnClose); + this.finalFragment = finalFragment; + } + + @Override + public boolean isFinalFragment() { + return finalFragment; + } +} diff --git a/dubbo-remoting/dubbo-remoting-websocket/src/main/java/org/apache/dubbo/remoting/websocket/FinalFragmentStreamingDecoder.java b/dubbo-remoting/dubbo-remoting-websocket/src/main/java/org/apache/dubbo/remoting/websocket/FinalFragmentStreamingDecoder.java new file mode 100644 index 00000000000..d5530171186 --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-websocket/src/main/java/org/apache/dubbo/remoting/websocket/FinalFragmentStreamingDecoder.java @@ -0,0 +1,123 @@ +/* + * 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.remoting.websocket; + +import org.apache.dubbo.remoting.http12.CompositeInputStream; +import org.apache.dubbo.remoting.http12.exception.DecodeException; +import org.apache.dubbo.remoting.http12.message.StreamingDecoder; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; + +public class FinalFragmentStreamingDecoder implements StreamingDecoder { + + private boolean inDelivery; + + private boolean pendingDelivery; + + private boolean closed; + + private boolean closing; + + protected final CompositeInputStream accumulate = new CompositeInputStream(); + + protected FragmentListener listener; + + @Override + public void request(int numMessages) {} + + @Override + public void decode(InputStream inputStream) throws DecodeException { + if (closing || closed) { + // ignored + return; + } + accumulate.addInputStream(inputStream); + if (inputStream instanceof FinalFragment && ((FinalFragment) inputStream).isFinalFragment()) { + pendingDelivery = true; + deliver(); + } + } + + @Override + public void close() { + closing = true; + deliver(); + } + + @Override + public void onStreamClosed() { + if (closed) { + return; + } + closed = true; + try { + accumulate.close(); + } catch (IOException e) { + throw new DecodeException(e); + } + } + + @Override + public void setFragmentListener(FragmentListener listener) { + this.listener = listener; + } + + private void deliver() { + if (inDelivery) { + return; + } + if (closed) { + return; + } + inDelivery = true; + try { + if (pendingDelivery) { + processBody(); + pendingDelivery = false; + } + if (closing) { + if (!closed) { + closed = true; + accumulate.close(); + listener.onClose(); + } + } + } catch (IOException e) { + throw new DecodeException(e); + } finally { + inDelivery = false; + } + } + + private void processBody() throws IOException { + byte[] rawMessage = readRawMessage(accumulate, accumulate.available()); + InputStream inputStream = new ByteArrayInputStream(rawMessage); + invokeListener(inputStream); + } + + protected void invokeListener(InputStream inputStream) { + this.listener.onFragmentMessage(inputStream); + } + + protected byte[] readRawMessage(InputStream inputStream, int length) throws IOException { + byte[] data = new byte[length]; + inputStream.read(data, 0, length); + return data; + } +} diff --git a/dubbo-remoting/dubbo-remoting-websocket/src/main/java/org/apache/dubbo/remoting/websocket/WebSocketHeaderNames.java b/dubbo-remoting/dubbo-remoting-websocket/src/main/java/org/apache/dubbo/remoting/websocket/WebSocketHeaderNames.java new file mode 100644 index 00000000000..b5a1d87f9a0 --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-websocket/src/main/java/org/apache/dubbo/remoting/websocket/WebSocketHeaderNames.java @@ -0,0 +1,31 @@ +/* + * 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.remoting.websocket; + +public enum WebSocketHeaderNames { + WEBSOCKET_MESSAGE("websocket-message"); + + private final String name; + + WebSocketHeaderNames(String name) { + this.name = name; + } + + public String getName() { + return name; + } +} diff --git a/dubbo-remoting/dubbo-remoting-websocket/src/main/java/org/apache/dubbo/remoting/websocket/WebSocketServerTransportListenerFactory.java b/dubbo-remoting/dubbo-remoting-websocket/src/main/java/org/apache/dubbo/remoting/websocket/WebSocketServerTransportListenerFactory.java new file mode 100644 index 00000000000..94ea29f9a3c --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-websocket/src/main/java/org/apache/dubbo/remoting/websocket/WebSocketServerTransportListenerFactory.java @@ -0,0 +1,29 @@ +/* + * 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.remoting.websocket; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.extension.ExtensionScope; +import org.apache.dubbo.common.extension.SPI; +import org.apache.dubbo.remoting.http12.h2.H2StreamChannel; +import org.apache.dubbo.rpc.model.FrameworkModel; + +@SPI(scope = ExtensionScope.FRAMEWORK) +public interface WebSocketServerTransportListenerFactory { + + WebSocketTransportListener newInstance(H2StreamChannel streamChannel, URL url, FrameworkModel frameworkModel); +} diff --git a/dubbo-remoting/dubbo-remoting-websocket/src/main/java/org/apache/dubbo/remoting/websocket/WebSocketTransportListener.java b/dubbo-remoting/dubbo-remoting-websocket/src/main/java/org/apache/dubbo/remoting/websocket/WebSocketTransportListener.java new file mode 100644 index 00000000000..09fb6ba47cf --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-websocket/src/main/java/org/apache/dubbo/remoting/websocket/WebSocketTransportListener.java @@ -0,0 +1,21 @@ +/* + * 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.remoting.websocket; + +import org.apache.dubbo.remoting.http12.h2.Http2TransportListener; + +public interface WebSocketTransportListener extends Http2TransportListener {} diff --git a/dubbo-remoting/dubbo-remoting-websocket/src/main/java/org/apache/dubbo/remoting/websocket/netty4/NettyWebSocketChannel.java b/dubbo-remoting/dubbo-remoting-websocket/src/main/java/org/apache/dubbo/remoting/websocket/netty4/NettyWebSocketChannel.java new file mode 100644 index 00000000000..261687562c8 --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-websocket/src/main/java/org/apache/dubbo/remoting/websocket/netty4/NettyWebSocketChannel.java @@ -0,0 +1,87 @@ +/* + * 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.remoting.websocket.netty4; + +import org.apache.dubbo.config.nested.TripleConfig; +import org.apache.dubbo.remoting.http12.HttpMetadata; +import org.apache.dubbo.remoting.http12.HttpOutputMessage; +import org.apache.dubbo.remoting.http12.LimitedByteBufOutputStream; +import org.apache.dubbo.remoting.http12.h2.H2StreamChannel; +import org.apache.dubbo.remoting.http12.h2.Http2OutputMessage; +import org.apache.dubbo.remoting.http12.h2.Http2OutputMessageFrame; +import org.apache.dubbo.remoting.http12.netty4.NettyHttpChannelFutureListener; + +import java.net.SocketAddress; +import java.util.concurrent.CompletableFuture; + +import io.netty.channel.Channel; + +public class NettyWebSocketChannel implements H2StreamChannel { + + private final Channel channel; + + private final TripleConfig tripleConfig; + + public NettyWebSocketChannel(Channel channel, TripleConfig tripleConfig) { + this.channel = channel; + this.tripleConfig = tripleConfig; + } + + @Override + public CompletableFuture writeResetFrame(long errorCode) { + NettyHttpChannelFutureListener futureListener = new NettyHttpChannelFutureListener(); + channel.close().addListener(futureListener); + return futureListener; + } + + @Override + public Http2OutputMessage newOutputMessage(boolean endStream) { + return new Http2OutputMessageFrame( + new LimitedByteBufOutputStream( + channel.alloc().buffer(), tripleConfig.getMaxResponseBodySizeOrDefault()), + endStream); + } + + @Override + public CompletableFuture writeHeader(HttpMetadata httpMetadata) { + NettyHttpChannelFutureListener futureListener = new NettyHttpChannelFutureListener(); + channel.write(httpMetadata).addListener(futureListener); + return futureListener; + } + + @Override + public CompletableFuture writeMessage(HttpOutputMessage httpOutputMessage) { + NettyHttpChannelFutureListener futureListener = new NettyHttpChannelFutureListener(); + channel.write(httpOutputMessage).addListener(futureListener); + return futureListener; + } + + @Override + public SocketAddress remoteAddress() { + return channel.remoteAddress(); + } + + @Override + public SocketAddress localAddress() { + return channel.localAddress(); + } + + @Override + public void flush() { + channel.flush(); + } +} diff --git a/dubbo-remoting/dubbo-remoting-websocket/src/main/java/org/apache/dubbo/remoting/websocket/netty4/WebSocketFrameCodec.java b/dubbo-remoting/dubbo-remoting-websocket/src/main/java/org/apache/dubbo/remoting/websocket/netty4/WebSocketFrameCodec.java new file mode 100644 index 00000000000..0bf25d1dac4 --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-websocket/src/main/java/org/apache/dubbo/remoting/websocket/netty4/WebSocketFrameCodec.java @@ -0,0 +1,140 @@ +/* + * 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.remoting.websocket.netty4; + +import org.apache.dubbo.common.io.StreamUtils; +import org.apache.dubbo.common.utils.CollectionUtils; +import org.apache.dubbo.remoting.http12.HttpHeaderNames; +import org.apache.dubbo.remoting.http12.HttpHeaders; +import org.apache.dubbo.remoting.http12.HttpMethods; +import org.apache.dubbo.remoting.http12.HttpStatus; +import org.apache.dubbo.remoting.http12.h2.Http2Header; +import org.apache.dubbo.remoting.http12.h2.Http2InputMessage; +import org.apache.dubbo.remoting.http12.h2.Http2InputMessageFrame; +import org.apache.dubbo.remoting.http12.h2.Http2MetadataFrame; +import org.apache.dubbo.remoting.http12.h2.Http2OutputMessage; +import org.apache.dubbo.remoting.http12.netty4.h1.NettyHttp1HttpHeaders; +import org.apache.dubbo.remoting.websocket.FinalFragmentByteBufInputStream; +import org.apache.dubbo.remoting.websocket.WebSocketHeaderNames; + +import java.io.IOException; +import java.io.OutputStream; +import java.util.List; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufOutputStream; +import io.netty.channel.ChannelDuplexHandler; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelPromise; +import io.netty.handler.codec.http.websocketx.BinaryWebSocketFrame; +import io.netty.handler.codec.http.websocketx.CloseWebSocketFrame; +import io.netty.handler.codec.http.websocketx.TextWebSocketFrame; +import io.netty.handler.codec.http.websocketx.WebSocketCloseStatus; +import io.netty.handler.codec.http.websocketx.WebSocketFrame; +import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler; +import io.netty.handler.codec.http2.DefaultHttp2ResetFrame; + +public class WebSocketFrameCodec extends ChannelDuplexHandler { + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + if (msg instanceof BinaryWebSocketFrame || msg instanceof TextWebSocketFrame) { + Http2InputMessage http2InputMessage = onDataFrame((WebSocketFrame) msg); + super.channelRead(ctx, http2InputMessage); + } else if (msg instanceof CloseWebSocketFrame) { + Object closeMessage = onCloseFrame((CloseWebSocketFrame) msg); + super.channelRead(ctx, closeMessage); + } else { + super.channelRead(ctx, msg); + } + } + + @Override + public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { + if (msg instanceof Http2OutputMessage) { + WebSocketFrame webSocketFrame = encodeWebSocketFrame(ctx, (Http2OutputMessage) msg); + super.write(ctx, webSocketFrame, promise); + } else if (msg instanceof Http2Header) { + Http2Header http2Header = (Http2Header) msg; + if (http2Header.isEndStream()) { + CloseWebSocketFrame closeWebSocketFrame = encodeCloseWebSocketFrame(http2Header); + super.write(ctx, closeWebSocketFrame, promise); + } + } else { + super.write(ctx, msg, promise); + } + } + + @Override + public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { + if (evt instanceof WebSocketServerProtocolHandler.HandshakeComplete) { + Http2Header http2Header = onHandshakeComplete((WebSocketServerProtocolHandler.HandshakeComplete) evt); + super.channelRead(ctx, http2Header); + } else { + super.userEventTriggered(ctx, evt); + } + } + + private Http2Header onHandshakeComplete(WebSocketServerProtocolHandler.HandshakeComplete evt) { + HttpHeaders httpHeaders = new NettyHttp1HttpHeaders(evt.requestHeaders()); + httpHeaders.set(HttpHeaderNames.PATH.getName(), evt.requestUri()); + httpHeaders.set(HttpHeaderNames.METHOD.getName(), HttpMethods.POST.name()); + return new Http2MetadataFrame(httpHeaders); + } + + private Http2InputMessageFrame onDataFrame(WebSocketFrame webSocketFrame) { + ByteBuf data = webSocketFrame.content(); + return new Http2InputMessageFrame( + new FinalFragmentByteBufInputStream(data, true, webSocketFrame.isFinalFragment()), false); + } + + private Object onCloseFrame(CloseWebSocketFrame closeWebSocketFrame) { + if (closeWebSocketFrame.statusCode() != WebSocketCloseStatus.NORMAL_CLOSURE.code()) { + return new DefaultHttp2ResetFrame(closeWebSocketFrame.statusCode()); + } + return new Http2InputMessageFrame(StreamUtils.EMPTY, true); + } + + private CloseWebSocketFrame encodeCloseWebSocketFrame(Http2Header http2Header) { + HttpHeaders headers = http2Header.headers(); + List statusHeaders = headers.remove(HttpHeaderNames.STATUS.getName()); + WebSocketCloseStatus status = WebSocketCloseStatus.NORMAL_CLOSURE; + if (CollectionUtils.isNotEmpty(statusHeaders) + && !HttpStatus.OK.getStatusString().equals(statusHeaders.get(0))) { + List messageHeaders = headers.remove(WebSocketHeaderNames.WEBSOCKET_MESSAGE.getName()); + status = new WebSocketCloseStatus( + WebSocketCloseStatus.INTERNAL_SERVER_ERROR.code(), + CollectionUtils.isNotEmpty(messageHeaders) + ? messageHeaders.get(0) + : WebSocketCloseStatus.INTERNAL_SERVER_ERROR.reasonText()); + } + return new CloseWebSocketFrame(status); + } + + private WebSocketFrame encodeWebSocketFrame(ChannelHandlerContext ctx, Http2OutputMessage outputMessage) + throws IOException { + OutputStream body = outputMessage.getBody(); + if (body == null) { + return new BinaryWebSocketFrame(); + } + if (body instanceof ByteBufOutputStream) { + ByteBuf buffer = ((ByteBufOutputStream) body).buffer(); + return new BinaryWebSocketFrame(buffer); + } + throw new IllegalArgumentException("Http2OutputMessage body must be ByteBufOutputStream"); + } +} diff --git a/dubbo-remoting/dubbo-remoting-websocket/src/main/java/org/apache/dubbo/remoting/websocket/netty4/WebSocketProtocolSelectorHandler.java b/dubbo-remoting/dubbo-remoting-websocket/src/main/java/org/apache/dubbo/remoting/websocket/netty4/WebSocketProtocolSelectorHandler.java new file mode 100644 index 00000000000..1ac8bfbdb98 --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-websocket/src/main/java/org/apache/dubbo/remoting/websocket/netty4/WebSocketProtocolSelectorHandler.java @@ -0,0 +1,71 @@ +/* + * 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.remoting.websocket.netty4; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.config.nested.TripleConfig; +import org.apache.dubbo.remoting.http12.command.HttpWriteQueue; +import org.apache.dubbo.remoting.http12.h2.H2StreamChannel; +import org.apache.dubbo.remoting.http12.h2.command.Http2WriteQueueChannel; +import org.apache.dubbo.remoting.http12.netty4.HttpWriteQueueHandler; +import org.apache.dubbo.remoting.http12.netty4.h2.NettyHttp2FrameHandler; +import org.apache.dubbo.remoting.websocket.WebSocketServerTransportListenerFactory; +import org.apache.dubbo.remoting.websocket.WebSocketTransportListener; +import org.apache.dubbo.rpc.model.FrameworkModel; + +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.SimpleChannelInboundHandler; +import io.netty.handler.codec.http.FullHttpRequest; + +public class WebSocketProtocolSelectorHandler extends SimpleChannelInboundHandler { + + private final URL url; + + private final FrameworkModel frameworkModel; + + private final TripleConfig tripleConfig; + + private final WebSocketServerTransportListenerFactory defaultWebSocketServerTransportListenerFactory; + + public WebSocketProtocolSelectorHandler( + URL url, + FrameworkModel frameworkModel, + TripleConfig tripleConfig, + WebSocketServerTransportListenerFactory defaultWebSocketServerTransportListenerFactory) { + this.url = url; + this.frameworkModel = frameworkModel; + this.tripleConfig = tripleConfig; + this.defaultWebSocketServerTransportListenerFactory = defaultWebSocketServerTransportListenerFactory; + } + + @Override + protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest msg) { + H2StreamChannel streamChannel = new NettyWebSocketChannel(ctx.channel(), tripleConfig); + HttpWriteQueueHandler writeQueueHandler = ctx.channel().pipeline().get(HttpWriteQueueHandler.class); + if (writeQueueHandler != null) { + HttpWriteQueue writeQueue = writeQueueHandler.getWriteQueue(); + streamChannel = new Http2WriteQueueChannel(streamChannel, writeQueue); + } + WebSocketTransportListener webSocketTransportListener = + defaultWebSocketServerTransportListenerFactory.newInstance(streamChannel, url, frameworkModel); + ctx.channel().closeFuture().addListener(future -> webSocketTransportListener.close()); + ctx.pipeline() + .addLast(new NettyHttp2FrameHandler(streamChannel, webSocketTransportListener)) + .remove(this); + ctx.fireChannelRead(msg.retain()); + } +} diff --git a/dubbo-remoting/dubbo-remoting-websocket/src/main/java/org/apache/dubbo/remoting/websocket/netty4/WebSocketServerUpgradeCodec.java b/dubbo-remoting/dubbo-remoting-websocket/src/main/java/org/apache/dubbo/remoting/websocket/netty4/WebSocketServerUpgradeCodec.java new file mode 100644 index 00000000000..1970d2162a3 --- /dev/null +++ b/dubbo-remoting/dubbo-remoting-websocket/src/main/java/org/apache/dubbo/remoting/websocket/netty4/WebSocketServerUpgradeCodec.java @@ -0,0 +1,64 @@ +/* + * 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.remoting.websocket.netty4; + +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.http.FullHttpRequest; +import io.netty.handler.codec.http.HttpHeaders; +import io.netty.handler.codec.http.HttpServerUpgradeHandler; + +public class WebSocketServerUpgradeCodec implements HttpServerUpgradeHandler.UpgradeCodec { + + private final List> shouldRemoveChannelHandlers; + + private final ChannelHandler[] channelHandlers; + + public WebSocketServerUpgradeCodec( + List> shouldRemoveChannelHandlers, ChannelHandler... channelHandlers) { + this.shouldRemoveChannelHandlers = shouldRemoveChannelHandlers; + this.channelHandlers = channelHandlers; + } + + @Override + public Collection requiredUpgradeHeaders() { + return Collections.emptyList(); + } + + @Override + public boolean prepareUpgradeResponse( + ChannelHandlerContext ctx, FullHttpRequest upgradeRequest, HttpHeaders upgradeHeaders) { + if (shouldRemoveChannelHandlers != null) { + for (Class shouldRemoveChannelHandler : shouldRemoveChannelHandlers) { + ctx.pipeline().remove(shouldRemoveChannelHandler); + } + } + if (channelHandlers != null) { + for (ChannelHandler channelHandler : channelHandlers) { + ctx.pipeline().addLast(channelHandler); + } + } + return false; + } + + @Override + public void upgradeTo(ChannelHandlerContext ctx, FullHttpRequest upgradeRequest) {} +} diff --git a/dubbo-remoting/pom.xml b/dubbo-remoting/pom.xml index 2384d0c81ad..2546529bda7 100644 --- a/dubbo-remoting/pom.xml +++ b/dubbo-remoting/pom.xml @@ -34,6 +34,7 @@ dubbo-remoting-netty4 dubbo-remoting-http12 dubbo-remoting-http3 + dubbo-remoting-websocket false diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/Constants.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/Constants.java index d7512eeb88d..59f0235de85 100644 --- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/Constants.java +++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/Constants.java @@ -103,6 +103,8 @@ public interface Constants { String HTTP3_KEY = "http3"; + String TRIPLE_SERVLET_KEY = "triple.servlet"; + String H2_SETTINGS_SUPPORT_NO_LOWER_HEADER_KEY = "dubbo.rpc.tri.support-no-lower-header"; String H2_SETTINGS_IGNORE_1_0_0_KEY = "dubbo.rpc.tri.ignore-1.0.0-version"; String H2_SETTINGS_RESOLVE_FALLBACK_TO_DEFAULT_KEY = "dubbo.rpc.tri.resolve-fallback-to-default"; diff --git a/dubbo-rpc/dubbo-rpc-triple/pom.xml b/dubbo-rpc/dubbo-rpc-triple/pom.xml index 2e7085832f9..929b7944441 100644 --- a/dubbo-rpc/dubbo-rpc-triple/pom.xml +++ b/dubbo-rpc/dubbo-rpc-triple/pom.xml @@ -47,6 +47,11 @@ ${project.parent.version} true + + org.apache.dubbo + dubbo-remoting-websocket + ${project.parent.version} + org.apache.dubbo dubbo-remoting-netty4 diff --git a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/TripleConstants.java b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/TripleConstants.java index 0635bcbef3f..3cf37a4b120 100644 --- a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/TripleConstants.java +++ b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/TripleConstants.java @@ -40,5 +40,7 @@ public final class TripleConstants { public static final String TRIPLE_HANDLER_TYPE_REST = "rest"; public static final String TRIPLE_HANDLER_TYPE_GRPC = "grpc"; + public static final String UPGRADE_HEADER_KEY = "Upgrade"; + private TripleConstants() {} } diff --git a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/TripleHttp2Protocol.java b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/TripleHttp2Protocol.java index a04f4a9d217..bbd53f4ab15 100644 --- a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/TripleHttp2Protocol.java +++ b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/TripleHttp2Protocol.java @@ -32,6 +32,9 @@ import org.apache.dubbo.remoting.http12.netty4.h2.NettyHttp2FrameCodec; import org.apache.dubbo.remoting.http12.netty4.h2.NettyHttp2ProtocolSelectorHandler; import org.apache.dubbo.remoting.utils.UrlUtils; +import org.apache.dubbo.remoting.websocket.netty4.WebSocketFrameCodec; +import org.apache.dubbo.remoting.websocket.netty4.WebSocketProtocolSelectorHandler; +import org.apache.dubbo.remoting.websocket.netty4.WebSocketServerUpgradeCodec; import org.apache.dubbo.rpc.model.FrameworkModel; import org.apache.dubbo.rpc.model.ScopeModelAware; import org.apache.dubbo.rpc.protocol.tri.h12.TripleProtocolDetector; @@ -40,16 +43,23 @@ import org.apache.dubbo.rpc.protocol.tri.transport.TripleGoAwayHandler; import org.apache.dubbo.rpc.protocol.tri.transport.TripleServerConnectionHandler; import org.apache.dubbo.rpc.protocol.tri.transport.TripleTailHandler; +import org.apache.dubbo.rpc.protocol.tri.websocket.DefaultWebSocketServerTransportListenerFactory; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import io.netty.channel.ChannelDuplexHandler; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelPipeline; +import io.netty.handler.codec.http.HttpHeaderValues; import io.netty.handler.codec.http.HttpObjectAggregator; import io.netty.handler.codec.http.HttpServerCodec; import io.netty.handler.codec.http.HttpServerUpgradeHandler; +import io.netty.handler.codec.http.websocketx.WebSocketDecoderConfig; +import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolConfig; +import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler; +import io.netty.handler.codec.http.websocketx.extensions.compression.WebSocketServerCompressionHandler; import io.netty.handler.codec.http2.Http2CodecUtil; import io.netty.handler.codec.http2.Http2FrameCodec; import io.netty.handler.codec.http2.Http2FrameCodecBuilder; @@ -152,6 +162,21 @@ private void configurerHttp1Handlers(URL url, List handlers) { new TripleServerConnectionHandler(), buildHttp2MultiplexHandler(url, tripleConfig), new TripleTailHandler()); + } else if (AsciiString.contentEquals(HttpHeaderValues.WEBSOCKET, protocol)) { + return new WebSocketServerUpgradeCodec( + Arrays.asList( + HttpObjectAggregator.class, + NettyHttp1Codec.class, + NettyHttp1ConnectionHandler.class), + new WebSocketServerCompressionHandler(), + new HttpWriteQueueHandler(), + new WebSocketProtocolSelectorHandler( + url, + frameworkModel, + tripleConfig, + DefaultWebSocketServerTransportListenerFactory.INSTANCE), + buildWebSocketServerProtocolHandler(tripleConfig), + new WebSocketFrameCodec()); } // Not upgrade request return null; @@ -205,4 +230,14 @@ private Http2FrameCodec buildHttp2FrameCodec(TripleConfig tripleConfig) { .validateHeaders(false) .build(); } + + private WebSocketServerProtocolHandler buildWebSocketServerProtocolHandler(TripleConfig tripleConfig) { + return new WebSocketServerProtocolHandler(WebSocketServerProtocolConfig.newBuilder() + .checkStartsWith(true) + .handleCloseFrames(false) + .decoderConfig(WebSocketDecoderConfig.newBuilder() + .maxFramePayloadLength(tripleConfig.getMaxBodySizeOrDefault()) + .build()) + .build()); + } } diff --git a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/mapping/meta/MethodMeta.java b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/mapping/meta/MethodMeta.java index 5e3f7c2eac7..87667690738 100644 --- a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/mapping/meta/MethodMeta.java +++ b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/mapping/meta/MethodMeta.java @@ -153,7 +153,7 @@ public String toShortString() { return MethodUtils.toShortString(method); } - private static final class StreamParameterMeta extends ParameterMeta { + public static final class StreamParameterMeta extends ParameterMeta { private final Class type; private final Type genericType; diff --git a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/support/basic/FallbackArgumentResolver.java b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/support/basic/FallbackArgumentResolver.java index 35c40c881e9..92735f485b0 100644 --- a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/support/basic/FallbackArgumentResolver.java +++ b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/support/basic/FallbackArgumentResolver.java @@ -28,6 +28,7 @@ import org.apache.dubbo.rpc.protocol.tri.rest.argument.AbstractArgumentResolver; import org.apache.dubbo.rpc.protocol.tri.rest.mapping.meta.AnnotationMeta; import org.apache.dubbo.rpc.protocol.tri.rest.mapping.meta.MethodMeta; +import org.apache.dubbo.rpc.protocol.tri.rest.mapping.meta.MethodMeta.StreamParameterMeta; import org.apache.dubbo.rpc.protocol.tri.rest.mapping.meta.MethodParameterMeta; import org.apache.dubbo.rpc.protocol.tri.rest.mapping.meta.NamedValueMeta; import org.apache.dubbo.rpc.protocol.tri.rest.mapping.meta.ParameterMeta; @@ -60,6 +61,9 @@ protected NamedValueMeta createNamedValueMeta(ParameterMeta param) { } } paramCount = methodMeta.getMethodDescriptor().getRpcType() != RpcType.UNARY ? 1 : paramMetas.length; + } else if (param instanceof StreamParameterMeta) { + paramCount = 1; + noBodyParam = false; } return new FallbackNamedValueMeta(param.isAnnotated(Annotations.Nonnull), noBodyParam, paramCount); } diff --git a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/websocket/DefaultWebSocketServerTransportListener.java b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/websocket/DefaultWebSocketServerTransportListener.java new file mode 100644 index 00000000000..e43367d7b79 --- /dev/null +++ b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/websocket/DefaultWebSocketServerTransportListener.java @@ -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. + */ +package org.apache.dubbo.rpc.protocol.tri.websocket; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.remoting.http12.HttpHeaders; +import org.apache.dubbo.remoting.http12.h2.H2StreamChannel; +import org.apache.dubbo.remoting.http12.h2.Http2Header; +import org.apache.dubbo.remoting.http12.h2.Http2InputMessage; +import org.apache.dubbo.remoting.http12.h2.Http2ServerChannelObserver; +import org.apache.dubbo.remoting.http12.message.StreamingDecoder; +import org.apache.dubbo.remoting.websocket.FinalFragmentStreamingDecoder; +import org.apache.dubbo.remoting.websocket.WebSocketHeaderNames; +import org.apache.dubbo.remoting.websocket.WebSocketTransportListener; +import org.apache.dubbo.rpc.model.FrameworkModel; +import org.apache.dubbo.rpc.model.MethodDescriptor.RpcType; +import org.apache.dubbo.rpc.protocol.tri.h12.http2.GenericHttp2ServerTransportListener; + +import java.util.concurrent.Executor; + +public class DefaultWebSocketServerTransportListener extends GenericHttp2ServerTransportListener + implements WebSocketTransportListener { + + private boolean autoClose = false; + + public DefaultWebSocketServerTransportListener( + H2StreamChannel h2StreamChannel, URL url, FrameworkModel frameworkModel) { + super(h2StreamChannel, url, frameworkModel); + } + + @Override + protected void onBeforeMetadata(Http2Header metadata) {} + + @Override + protected Executor initializeExecutor(URL url, Http2Header metadata) { + return getExecutor(url, metadata); + } + + @Override + protected void onPrepareMetadata(Http2Header metadata) { + doRoute(metadata); + } + + @Override + protected StreamingDecoder newStreamingDecoder() { + return new FinalFragmentStreamingDecoder(); + } + + @Override + protected Http2ServerChannelObserver newResponseObserver(H2StreamChannel h2StreamChannel) { + return new WebSocketServerChannelObserver(getFrameworkModel(), h2StreamChannel); + } + + @Override + protected Http2ServerChannelObserver newStreamResponseObserver(H2StreamChannel h2StreamChannel) { + return new WebSocketServerChannelObserver(getFrameworkModel(), h2StreamChannel); + } + + @Override + protected Http2ServerChannelObserver prepareResponseObserver(Http2ServerChannelObserver responseObserver) { + responseObserver.addTrailersCustomizer(this::customizeWebSocketStatus); + return super.prepareResponseObserver(responseObserver); + } + + @Override + protected void prepareUnaryServerCall() { + autoClose = true; + super.prepareUnaryServerCall(); + } + + @Override + protected void prepareStreamServerCall() { + if (getContext().getMethodDescriptor().getRpcType().equals(RpcType.SERVER_STREAM)) { + autoClose = true; + } + super.prepareStreamServerCall(); + } + + @Override + protected void onDataCompletion(Http2InputMessage message) { + if (autoClose) { + getStreamingDecoder().close(); + return; + } + super.onDataCompletion(message); + } + + private void customizeWebSocketStatus(HttpHeaders httpHeaders, Throwable throwable) { + if (throwable != null) { + httpHeaders.set(WebSocketHeaderNames.WEBSOCKET_MESSAGE.getName(), throwable.getMessage()); + } + } +} diff --git a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/websocket/DefaultWebSocketServerTransportListenerFactory.java b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/websocket/DefaultWebSocketServerTransportListenerFactory.java new file mode 100644 index 00000000000..fd5c331f5e6 --- /dev/null +++ b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/websocket/DefaultWebSocketServerTransportListenerFactory.java @@ -0,0 +1,35 @@ +/* + * 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.protocol.tri.websocket; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.remoting.http12.h2.H2StreamChannel; +import org.apache.dubbo.remoting.websocket.WebSocketServerTransportListenerFactory; +import org.apache.dubbo.remoting.websocket.WebSocketTransportListener; +import org.apache.dubbo.rpc.model.FrameworkModel; + +public class DefaultWebSocketServerTransportListenerFactory implements WebSocketServerTransportListenerFactory { + + public static final WebSocketServerTransportListenerFactory INSTANCE = + new DefaultWebSocketServerTransportListenerFactory(); + + @Override + public WebSocketTransportListener newInstance( + H2StreamChannel streamChannel, URL url, FrameworkModel frameworkModel) { + return new DefaultWebSocketServerTransportListener(streamChannel, url, frameworkModel); + } +} diff --git a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/websocket/WebSocketServerChannelObserver.java b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/websocket/WebSocketServerChannelObserver.java new file mode 100644 index 00000000000..3590dbc0269 --- /dev/null +++ b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/websocket/WebSocketServerChannelObserver.java @@ -0,0 +1,39 @@ +/* + * 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.protocol.tri.websocket; + +import org.apache.dubbo.remoting.http12.HttpOutputMessage; +import org.apache.dubbo.remoting.http12.h2.H2StreamChannel; +import org.apache.dubbo.rpc.model.FrameworkModel; +import org.apache.dubbo.rpc.protocol.tri.h12.http2.Http2StreamServerChannelObserver; + +public class WebSocketServerChannelObserver extends Http2StreamServerChannelObserver { + + protected WebSocketServerChannelObserver(FrameworkModel frameworkModel, H2StreamChannel h2StreamChannel) { + super(frameworkModel, h2StreamChannel); + } + + @Override + protected void doOnNext(Object data) throws Throwable { + int statusCode = resolveStatusCode(data); + HttpOutputMessage httpOutputMessage = buildMessage(statusCode, data); + sendMessage(httpOutputMessage); + } + + @Override + protected void doOnError(Throwable throwable) {} +} diff --git a/dubbo-rpc/dubbo-rpc-triple/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.remoting.websocket.WebSocketServerTransportListenerFactory b/dubbo-rpc/dubbo-rpc-triple/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.remoting.websocket.WebSocketServerTransportListenerFactory new file mode 100644 index 00000000000..eb51344a149 --- /dev/null +++ b/dubbo-rpc/dubbo-rpc-triple/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.remoting.websocket.WebSocketServerTransportListenerFactory @@ -0,0 +1 @@ +default=org.apache.dubbo.rpc.protocol.tri.websocket.DefaultWebSocketServerTransportListenerFactory diff --git a/dubbo-spring-boot-project/dubbo-spring-boot-3-autoconfigure/pom.xml b/dubbo-spring-boot-project/dubbo-spring-boot-3-autoconfigure/pom.xml index 07ec5b92a4a..01830da529c 100644 --- a/dubbo-spring-boot-project/dubbo-spring-boot-3-autoconfigure/pom.xml +++ b/dubbo-spring-boot-project/dubbo-spring-boot-3-autoconfigure/pom.xml @@ -67,6 +67,13 @@ true + + org.apache.dubbo + dubbo-triple-websocket + ${project.version} + true + + jakarta.servlet jakarta.servlet-api @@ -77,5 +84,17 @@ tomcat-embed-core provided + + + jakarta.websocket + jakarta.websocket-api + provided + + + + jakarta.websocket + jakarta.websocket-client-api + provided + diff --git a/dubbo-spring-boot-project/dubbo-spring-boot-3-autoconfigure/src/main/java/org/apache/dubbo/spring/boot/autoconfigure/DubboTriple3AutoConfiguration.java b/dubbo-spring-boot-project/dubbo-spring-boot-3-autoconfigure/src/main/java/org/apache/dubbo/spring/boot/autoconfigure/DubboTriple3AutoConfiguration.java index 8caac7a29a7..08ab713a552 100644 --- a/dubbo-spring-boot-project/dubbo-spring-boot-3-autoconfigure/src/main/java/org/apache/dubbo/spring/boot/autoconfigure/DubboTriple3AutoConfiguration.java +++ b/dubbo-spring-boot-project/dubbo-spring-boot-3-autoconfigure/src/main/java/org/apache/dubbo/spring/boot/autoconfigure/DubboTriple3AutoConfiguration.java @@ -18,6 +18,7 @@ import org.apache.dubbo.rpc.protocol.tri.ServletExchanger; import org.apache.dubbo.rpc.protocol.tri.servlet.jakarta.TripleFilter; +import org.apache.dubbo.rpc.protocol.tri.websocket.jakarta.TripleWebSocketFilter; import jakarta.servlet.Filter; import org.apache.coyote.ProtocolHandler; @@ -39,18 +40,20 @@ @Conditional(SpringBoot3Condition.class) public class DubboTriple3AutoConfiguration { - public static final String PREFIX = "dubbo.protocol.triple.servlet"; + public static final String SERVLET_PREFIX = "dubbo.protocol.triple.servlet"; + + public static final String WEBSOCKET_PREFIX = "dubbo.protocol.triple.websocket"; @Configuration(proxyBeanMethods = false) @ConditionalOnClass(Filter.class) @ConditionalOnWebApplication(type = Type.SERVLET) - @ConditionalOnProperty(prefix = PREFIX, name = "enabled", havingValue = "true") + @ConditionalOnProperty(prefix = SERVLET_PREFIX, name = "enabled", havingValue = "true") public static class TripleServletConfiguration { @Bean public FilterRegistrationBean tripleProtocolFilter( - @Value("${" + PREFIX + ".filter-url-patterns:/*}") String[] urlPatterns, - @Value("${" + PREFIX + ".filter-order:-1000000}") int order, + @Value("${" + SERVLET_PREFIX + ".filter-url-patterns:/*}") String[] urlPatterns, + @Value("${" + SERVLET_PREFIX + ".filter-order:-1000000}") int order, @Value("${server.port:8080}") int serverPort) { ServletExchanger.bindServerPort(serverPort); FilterRegistrationBean registrationBean = new FilterRegistrationBean<>(); @@ -62,9 +65,9 @@ public FilterRegistrationBean tripleProtocolFilter( @Bean @ConditionalOnClass(Http2Protocol.class) - @ConditionalOnProperty(prefix = PREFIX, name = "max-concurrent-streams") + @ConditionalOnProperty(prefix = SERVLET_PREFIX, name = "max-concurrent-streams") public WebServerFactoryCustomizer tripleTomcatHttp2Customizer( - @Value("${" + PREFIX + ".max-concurrent-streams}") int maxConcurrentStreams) { + @Value("${" + SERVLET_PREFIX + ".max-concurrent-streams}") int maxConcurrentStreams) { return factory -> factory.addConnectorCustomizers(connector -> { ProtocolHandler handler = connector.getProtocolHandler(); for (UpgradeProtocol upgradeProtocol : handler.findUpgradeProtocols()) { @@ -78,4 +81,24 @@ public WebServerFactoryCustomizer tripleTomc }); } } + + @Configuration(proxyBeanMethods = false) + @ConditionalOnClass(Filter.class) + @ConditionalOnWebApplication(type = Type.SERVLET) + @ConditionalOnProperty(prefix = WEBSOCKET_PREFIX, name = "enabled", havingValue = "true") + public static class TripleWebSocketConfiguration { + + @Bean + public FilterRegistrationBean tripleWebSocketFilter( + @Value("${" + WEBSOCKET_PREFIX + ".filter-url-patterns:/*}") String[] urlPatterns, + @Value("${" + WEBSOCKET_PREFIX + ".filter-order:-1000000}") int order, + @Value("${server.port:8080}") int serverPort) { + ServletExchanger.bindServerPort(serverPort); + FilterRegistrationBean registrationBean = new FilterRegistrationBean<>(); + registrationBean.setFilter(new TripleWebSocketFilter()); + registrationBean.addUrlPatterns(urlPatterns); + registrationBean.setOrder(order); + return registrationBean; + } + } } diff --git a/dubbo-spring-boot-project/dubbo-spring-boot-autoconfigure/pom.xml b/dubbo-spring-boot-project/dubbo-spring-boot-autoconfigure/pom.xml index 665f791a606..d8eeab98f43 100644 --- a/dubbo-spring-boot-project/dubbo-spring-boot-autoconfigure/pom.xml +++ b/dubbo-spring-boot-project/dubbo-spring-boot-autoconfigure/pom.xml @@ -82,6 +82,13 @@ true + + org.apache.dubbo + dubbo-triple-websocket + ${project.version} + true + + javax.servlet javax.servlet-api @@ -93,6 +100,18 @@ provided + + jakarta.websocket + jakarta.websocket-api + provided + + + + jakarta.websocket + jakarta.websocket-client-api + provided + + io.micrometer diff --git a/dubbo-spring-boot-project/dubbo-spring-boot-autoconfigure/src/main/java/org/apache/dubbo/spring/boot/autoconfigure/DubboTripleAutoConfiguration.java b/dubbo-spring-boot-project/dubbo-spring-boot-autoconfigure/src/main/java/org/apache/dubbo/spring/boot/autoconfigure/DubboTripleAutoConfiguration.java index 3dfecdb9529..c238865a0ff 100644 --- a/dubbo-spring-boot-project/dubbo-spring-boot-autoconfigure/src/main/java/org/apache/dubbo/spring/boot/autoconfigure/DubboTripleAutoConfiguration.java +++ b/dubbo-spring-boot-project/dubbo-spring-boot-autoconfigure/src/main/java/org/apache/dubbo/spring/boot/autoconfigure/DubboTripleAutoConfiguration.java @@ -18,6 +18,7 @@ import org.apache.dubbo.rpc.protocol.tri.ServletExchanger; import org.apache.dubbo.rpc.protocol.tri.servlet.TripleFilter; +import org.apache.dubbo.rpc.protocol.tri.websocket.TripleWebSocketFilter; import javax.servlet.Filter; @@ -40,18 +41,20 @@ @Conditional(SpringBoot12Condition.class) public class DubboTripleAutoConfiguration { - public static final String PREFIX = "dubbo.protocol.triple.servlet"; + public static final String SERVLET_PREFIX = "dubbo.protocol.triple.servlet"; + + public static final String WEBSOCKET_PREFIX = "dubbo.protocol.triple.websocket"; @Configuration(proxyBeanMethods = false) @ConditionalOnClass(Filter.class) @ConditionalOnWebApplication(type = Type.SERVLET) - @ConditionalOnProperty(prefix = PREFIX, name = "enabled", havingValue = "true") + @ConditionalOnProperty(prefix = SERVLET_PREFIX, name = "enabled", havingValue = "true") public static class TripleServletConfiguration { @Bean public FilterRegistrationBean tripleProtocolFilter( - @Value("${" + PREFIX + ".filter-url-patterns:/*}") String[] urlPatterns, - @Value("${" + PREFIX + ".filter-order:-1000000}") int order, + @Value("${" + SERVLET_PREFIX + ".filter-url-patterns:/*}") String[] urlPatterns, + @Value("${" + SERVLET_PREFIX + ".filter-order:-1000000}") int order, @Value("${server.port:8080}") int serverPort) { ServletExchanger.bindServerPort(serverPort); FilterRegistrationBean registrationBean = new FilterRegistrationBean<>(); @@ -63,9 +66,9 @@ public FilterRegistrationBean tripleProtocolFilter( @Bean @ConditionalOnClass(Http2Protocol.class) - @ConditionalOnProperty(prefix = PREFIX, name = "max-concurrent-streams") + @ConditionalOnProperty(prefix = SERVLET_PREFIX, name = "max-concurrent-streams") public WebServerFactoryCustomizer tripleTomcatHttp2Customizer( - @Value("${" + PREFIX + ".max-concurrent-streams}") int maxConcurrentStreams) { + @Value("${" + SERVLET_PREFIX + ".max-concurrent-streams}") int maxConcurrentStreams) { return factory -> factory.addConnectorCustomizers(connector -> { ProtocolHandler handler = connector.getProtocolHandler(); for (UpgradeProtocol upgradeProtocol : handler.findUpgradeProtocols()) { @@ -79,4 +82,24 @@ public WebServerFactoryCustomizer tripleTomc }); } } + + @Configuration(proxyBeanMethods = false) + @ConditionalOnClass(Filter.class) + @ConditionalOnWebApplication(type = Type.SERVLET) + @ConditionalOnProperty(prefix = WEBSOCKET_PREFIX, name = "enabled", havingValue = "true") + public static class TripleWebSocketConfiguration { + + @Bean + public FilterRegistrationBean tripleWebSocketFilter( + @Value("${" + WEBSOCKET_PREFIX + ".filter-url-patterns:/*}") String[] urlPatterns, + @Value("${" + WEBSOCKET_PREFIX + ".filter-order:-1000000}") int order, + @Value("${server.port:8080}") int serverPort) { + ServletExchanger.bindServerPort(serverPort); + FilterRegistrationBean registrationBean = new FilterRegistrationBean<>(); + registrationBean.setFilter(new TripleWebSocketFilter()); + registrationBean.addUrlPatterns(urlPatterns); + registrationBean.setOrder(order); + return registrationBean; + } + } } diff --git a/dubbo-spring-boot-project/dubbo-spring-boot-compatible/dubbo-spring-boot-autoconfigure-compatible/pom.xml b/dubbo-spring-boot-project/dubbo-spring-boot-compatible/dubbo-spring-boot-autoconfigure-compatible/pom.xml index d45aceca74b..455533ad504 100644 --- a/dubbo-spring-boot-project/dubbo-spring-boot-compatible/dubbo-spring-boot-autoconfigure-compatible/pom.xml +++ b/dubbo-spring-boot-project/dubbo-spring-boot-compatible/dubbo-spring-boot-autoconfigure-compatible/pom.xml @@ -73,6 +73,12 @@ ${project.version} + + javax.websocket + javax.websocket-api + provided + + org.springframework.boot diff --git a/dubbo-test/dubbo-dependencies-all/pom.xml b/dubbo-test/dubbo-dependencies-all/pom.xml index 83c80c43eb3..ddd9b6b6eb9 100644 --- a/dubbo-test/dubbo-dependencies-all/pom.xml +++ b/dubbo-test/dubbo-dependencies-all/pom.xml @@ -256,6 +256,11 @@ dubbo-triple-servlet ${project.version} + + org.apache.dubbo + dubbo-triple-websocket + ${project.version} + @@ -300,6 +305,11 @@ dubbo-remoting-http3 ${project.version} + + org.apache.dubbo + dubbo-remoting-websocket + ${project.version} + org.apache.dubbo dubbo-remoting-netty From 8bfbb580dff4e07057e930e0f4220a6647c1617e Mon Sep 17 00:00:00 2001 From: Sean Yang Date: Wed, 13 Nov 2024 14:52:33 +0800 Subject: [PATCH 14/19] Spring6 compatibility (#14866) --- dubbo-config/dubbo-config-spring6/pom.xml | 12 +- dubbo-config/pom.xml | 2 - dubbo-dependencies-bom/pom.xml | 6 +- .../tri/rest/support/spring/Helper.java | 32 +++ .../spring/SpringResponseRestFilter.java | 2 +- .../dubbo-spring-boot-3-autoconfigure/pom.xml | 6 +- pom.xml | 205 +++++++++++++++++- 7 files changed, 244 insertions(+), 21 deletions(-) diff --git a/dubbo-config/dubbo-config-spring6/pom.xml b/dubbo-config/dubbo-config-spring6/pom.xml index 673fe767162..520beba17a3 100644 --- a/dubbo-config/dubbo-config-spring6/pom.xml +++ b/dubbo-config/dubbo-config-spring6/pom.xml @@ -28,8 +28,6 @@ 17 17 - 6.1.14 - 3.0.9 @@ -48,22 +46,22 @@ org.springframework spring-beans - ${spring.version} + ${spring-6.version} org.springframework spring-core - ${spring.version} + ${spring-6.version} org.springframework spring-web - ${spring.version} + ${spring-6.version} org.springframework spring-context - ${spring.version} + ${spring-6.version} javax.servlet @@ -74,7 +72,7 @@ org.springframework.boot spring-boot-starter-test - ${spring-boot.version} + ${spring-boot-3.version} test diff --git a/dubbo-config/pom.xml b/dubbo-config/pom.xml index ecfb4322ec3..bc404270a6d 100644 --- a/dubbo-config/pom.xml +++ b/dubbo-config/pom.xml @@ -56,8 +56,6 @@ [17,) - dubbo-config-api - dubbo-config-spring dubbo-config-spring6 diff --git a/dubbo-dependencies-bom/pom.xml b/dubbo-dependencies-bom/pom.xml index 024759105e8..f591d485abb 100644 --- a/dubbo-dependencies-bom/pom.xml +++ b/dubbo-dependencies-bom/pom.xml @@ -90,6 +90,7 @@ 5.3.39 + 2.7.18 5.8.15 3.30.2-GA 1.15.10 @@ -188,7 +189,6 @@ 3.1.9 4.0.2 2.4.0-b180830.0438 - 2.7.18 1.15.1 0.16.0 @@ -260,7 +260,7 @@ org.springframework.boot spring-boot-dependencies - ${spring-boot.version} + ${spring_boot_version} pom import @@ -273,7 +273,7 @@ org.springframework.boot spring-boot-starter-logging - ${spring-boot.version} + ${spring_boot_version} ch.qos.logback diff --git a/dubbo-plugin/dubbo-rest-spring/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/support/spring/Helper.java b/dubbo-plugin/dubbo-rest-spring/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/support/spring/Helper.java index fd818c06770..26d38cbd61e 100644 --- a/dubbo-plugin/dubbo-rest-spring/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/support/spring/Helper.java +++ b/dubbo-plugin/dubbo-rest-spring/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/support/spring/Helper.java @@ -19,13 +19,30 @@ import org.apache.dubbo.rpc.protocol.tri.rest.mapping.meta.AnnotationMeta; import java.lang.annotation.Annotation; +import java.lang.reflect.Method; +import org.springframework.core.SpringVersion; +import org.springframework.http.ResponseEntity; +import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.ValueConstants; final class Helper { + public static boolean IS_SPRING_6; + + private static Method getStatusCode; + private static Method value; + private Helper() {} + static { + try { + String version = SpringVersion.getVersion(); + IS_SPRING_6 = StringUtils.hasLength(version) && version.charAt(0) >= '6'; + } catch (Throwable ignored) { + } + } + public static boolean isRequired(AnnotationMeta annotation) { return annotation.getBoolean("required"); } @@ -41,4 +58,19 @@ public static String defaultValue(AnnotationMeta annotation, String public static String defaultValue(String value) { return ValueConstants.DEFAULT_NONE.equals(value) ? null : value; } + + public static int getStatusCode(ResponseEntity entity) { + if (IS_SPRING_6) { + try { + if (getStatusCode == null) { + getStatusCode = ResponseEntity.class.getMethod("getStatusCode"); + value = getStatusCode.getReturnType().getMethod("value"); + } + return (Integer) value.invoke(getStatusCode.invoke(entity)); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + return entity.getStatusCode().value(); + } } diff --git a/dubbo-plugin/dubbo-rest-spring/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/support/spring/SpringResponseRestFilter.java b/dubbo-plugin/dubbo-rest-spring/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/support/spring/SpringResponseRestFilter.java index 05458703c58..f182551087a 100644 --- a/dubbo-plugin/dubbo-rest-spring/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/support/spring/SpringResponseRestFilter.java +++ b/dubbo-plugin/dubbo-rest-spring/src/main/java/org/apache/dubbo/rpc/protocol/tri/rest/support/spring/SpringResponseRestFilter.java @@ -87,7 +87,7 @@ public void onResponse(Result result, HttpRequest request, HttpResponse response ResponseEntity entity = (ResponseEntity) value; result.setValue(HttpResult.builder() .body(entity.getBody()) - .status(entity.getStatusCode().value()) + .status(Helper.getStatusCode(entity)) .headers(entity.getHeaders()) .build()); return; diff --git a/dubbo-spring-boot-project/dubbo-spring-boot-3-autoconfigure/pom.xml b/dubbo-spring-boot-project/dubbo-spring-boot-3-autoconfigure/pom.xml index 01830da529c..99ea0181322 100644 --- a/dubbo-spring-boot-project/dubbo-spring-boot-3-autoconfigure/pom.xml +++ b/dubbo-spring-boot-project/dubbo-spring-boot-3-autoconfigure/pom.xml @@ -28,16 +28,12 @@ jar Apache Dubbo Spring Boot 3 Auto-Configure - - 3.2.1 - - org.springframework.boot spring-boot-dependencies - ${spring-boot.version} + ${spring-boot-3.version} pom import diff --git a/pom.xml b/pom.xml index 8a766adf335..4597eafeb3e 100644 --- a/pom.xml +++ b/pom.xml @@ -129,6 +129,7 @@ true true true + check 3.4.2 @@ -148,10 +149,13 @@ 0.6.1 3.0.2 + + 6.1.14 + 3.3.5 + 3.22.3 1.54.0 2.43.0 - check 1.0.0 2.38.0 3.3.2-SNAPSHOT @@ -710,8 +714,6 @@ ${log4j2_version} - - none @@ -982,5 +984,202 @@ dubbo-demo + + spring-6 + + + + org.springframework + spring-aop + ${spring-6.version} + + + org.springframework + spring-aspects + ${spring-6.version} + + + org.springframework + spring-beans + ${spring-6.version} + + + org.springframework + spring-context + ${spring-6.version} + + + org.springframework + spring-context-indexer + ${spring-6.version} + + + org.springframework + spring-context-support + ${spring-6.version} + + + org.springframework + spring-core + ${spring-6.version} + + + org.springframework + spring-core-test + ${spring-6.version} + + + org.springframework + spring-expression + ${spring-6.version} + + + org.springframework + spring-instrument + ${spring-6.version} + + + org.springframework + spring-jcl + ${spring-6.version} + + + org.springframework + spring-jdbc + ${spring-6.version} + + + org.springframework + spring-test + ${spring-6.version} + + + org.springframework + spring-tx + ${spring-6.version} + + + org.springframework + spring-web + ${spring-6.version} + + + org.springframework + spring-webmvc + ${spring-6.version} + + + + + + spring-boot-3 + + 10.1.31 + + + + + org.springframework.boot + spring-boot + ${spring-boot-3.version} + + + org.springframework.boot + spring-boot-autoconfigure + ${spring-boot-3.version} + + + org.springframework.boot + spring-boot-starter + ${spring-boot-3.version} + + + org.springframework.boot + spring-boot-test + ${spring-boot-3.version} + + + org.springframework.boot + spring-boot-test-autoconfigure + ${spring-boot-3.version} + + + org.springframework.boot + spring-boot-starter-test + ${spring-boot-3.version} + + + org.springframework.boot + spring-boot-actuator + ${spring-boot-3.version} + + + org.springframework.boot + spring-boot-actuator-autoconfigure + ${spring-boot-3.version} + + + org.springframework.boot + spring-boot-starter-actuator + ${spring-boot-3.version} + + + org.springframework.boot + spring-boot-configuration-processor + ${spring-boot-3.version} + + + org.springframework.boot + spring-boot-starter-aop + ${spring-boot-3.version} + + + org.springframework.boot + spring-boot-starter-json + ${spring-boot-3.version} + + + org.springframework.boot + spring-boot-starter-log4j2 + ${spring-boot-3.version} + + + org.springframework.boot + spring-boot-starter-logging + ${spring-boot-3.version} + + + org.springframework.boot + spring-boot-starter-tomcat + ${spring-boot-3.version} + + + org.springframework.boot + spring-boot-starter-validation + ${spring-boot-3.version} + + + org.springframework.boot + spring-boot-starter-web + ${spring-boot-3.version} + + + org.apache.tomcat.embed + tomcat-embed-core + ${tomcat.version} + + + org.apache.tomcat.embed + tomcat-embed-el + ${tomcat.version} + + + org.apache.tomcat.embed + tomcat-embed-websocket + ${tomcat.version} + + + + From df6c80501c4ff8536cdee047a92e2b204fd2dcf9 Mon Sep 17 00:00:00 2001 From: Jermaine Hua Date: Wed, 13 Nov 2024 14:53:06 +0800 Subject: [PATCH 15/19] Remove zookeeper dependency management (#14869) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: “JermaineHua” --- .artifacts | 3 - .../pom.xml | 214 ------------------ dubbo-dependencies/pom.xml | 127 ----------- dubbo-distribution/dubbo-bom/pom.xml | 25 -- .../pom.xml | 7 - .../pom.xml | 48 ---- .../dubbo-spring-boot-starters/pom.xml | 1 - dubbo-test/dubbo-dependencies-all/pom.xml | 5 - pom.xml | 2 - 9 files changed, 432 deletions(-) delete mode 100644 dubbo-dependencies/dubbo-dependencies-zookeeper-curator5/pom.xml delete mode 100644 dubbo-dependencies/pom.xml delete mode 100644 dubbo-spring-boot-project/dubbo-spring-boot-starters/dubbo-zookeeper-spring-boot-starter/pom.xml diff --git a/.artifacts b/.artifacts index ef2d5e8ece8..1d5f682eb9e 100644 --- a/.artifacts +++ b/.artifacts @@ -35,10 +35,8 @@ dubbo-configcenter-apollo dubbo-configcenter-nacos dubbo-configcenter-zookeeper dubbo-core-spi -dubbo-dependencies dubbo-dependencies-all dubbo-dependencies-bom -dubbo-dependencies-zookeeper-curator5 dubbo-distribution dubbo-filter-cache dubbo-filter-validation @@ -106,7 +104,6 @@ dubbo-spring-boot-starter dubbo-spring-boot-starters dubbo-spring-boot-interceptor dubbo-nacos-spring-boot-starter -dubbo-zookeeper-spring-boot-starter dubbo-zookeeper-curator5-spring-boot-starter dubbo-sentinel-spring-boot-starter dubbo-seata-spring-boot-starter diff --git a/dubbo-dependencies/dubbo-dependencies-zookeeper-curator5/pom.xml b/dubbo-dependencies/dubbo-dependencies-zookeeper-curator5/pom.xml deleted file mode 100644 index 40795e00a34..00000000000 --- a/dubbo-dependencies/dubbo-dependencies-zookeeper-curator5/pom.xml +++ /dev/null @@ -1,214 +0,0 @@ - - - - 4.0.0 - - org.apache - apache - 31 - - - - org.apache.dubbo - dubbo-dependencies-zookeeper-curator5 - ${revision} - pom - - - 1.6.0 - 1.7.36 - 5.1.0 - 3.8.4 - 2.43.0 - check - 1.0.0 - 2.38.0 - - 3.3.2-SNAPSHOT - - - - - org.apache.curator - curator-x-discovery - ${curator5_version} - - - org.apache.zookeeper - zookeeper - - - org.slf4j - slf4j-api - - - com.google.guava - listenablefuture - - - - - org.apache.zookeeper - zookeeper - ${zookeeper_version} - - - ch.qos.logback - logback-classic - - - ch.qos.logback - logback-core - - - org.apache.yetus - audience-annotations - - - io.netty - * - - - org.slf4j - slf4j-api - - - commons-io - commons-io - - - - - org.slf4j - slf4j-api - ${slf4j_version} - - - - - - - org.codehaus.mojo - flatten-maven-plugin - ${maven_flatten_version} - - true - oss - - - - flatten - - flatten - - process-resources - - - flatten.clean - - clean - - clean - - - - - - - - - release - - - - org.apache.maven.plugins - maven-gpg-plugin - - - - sign - - verify - - - - - - - - java11+ - - [11,) - - - - - - com.diffplug.spotless - spotless-maven-plugin - ${spotless-maven-plugin.version} - - - - ${palantirJavaFormat.version} - - - - dubbo-importorder.txt - - - checkstyle-header.txt - - - - - false - true - - - - true - - - - - com.alibaba - dubbo-shared-resources - ${dubbo-shared-resources.version} - - - - - - ${spotless.action} - - process-sources - - - - - - - - skip-spotless - - true - - - - diff --git a/dubbo-dependencies/pom.xml b/dubbo-dependencies/pom.xml deleted file mode 100644 index afc7ab7ab44..00000000000 --- a/dubbo-dependencies/pom.xml +++ /dev/null @@ -1,127 +0,0 @@ - - - - 4.0.0 - - org.apache.dubbo - dubbo-parent - ${revision} - ../pom.xml - - - dubbo-dependencies - pom - - dubbo-dependencies-zookeeper-curator5 - - - - 2.43.0 - check - 1.0.0 - 2.38.0 - - - - - - org.codehaus.mojo - flatten-maven-plugin - ${maven_flatten_version} - - true - bom - - - - flatten - - flatten - - process-resources - - - flatten.clean - - clean - - clean - - - - - - - - - java11+ - - [11,) - - - - - - com.diffplug.spotless - spotless-maven-plugin - ${spotless-maven-plugin.version} - - - - ${palantirJavaFormat.version} - - - - dubbo-importorder.txt - - - checkstyle-header.txt - - - - - false - true - - - - true - - - - - com.alibaba - dubbo-shared-resources - ${dubbo-shared-resources.version} - - - - - - ${spotless.action} - - process-sources - - - - - - - - - diff --git a/dubbo-distribution/dubbo-bom/pom.xml b/dubbo-distribution/dubbo-bom/pom.xml index cf82bbd2ee9..69171eea1a9 100644 --- a/dubbo-distribution/dubbo-bom/pom.xml +++ b/dubbo-distribution/dubbo-bom/pom.xml @@ -112,26 +112,6 @@ dubbo-configcenter-nacos ${project.version} - - - - org.apache.dubbo - dubbo-dependencies - ${project.version} - - - org.apache.dubbo - dubbo-dependencies-zookeeper - ${project.version} - pom - - - org.apache.dubbo - dubbo-dependencies-zookeeper-curator5 - ${project.version} - pom - - org.apache.dubbo @@ -562,11 +542,6 @@ dubbo-nacos-spring-boot-starter ${project.version} - - org.apache.dubbo - dubbo-zookeeper-spring-boot-starter - ${project.version} - org.apache.dubbo dubbo-zookeeper-curator5-spring-boot-starter diff --git a/dubbo-spring-boot-project/dubbo-spring-boot-starters/dubbo-zookeeper-curator5-spring-boot-starter/pom.xml b/dubbo-spring-boot-project/dubbo-spring-boot-starters/dubbo-zookeeper-curator5-spring-boot-starter/pom.xml index f15ce669ee5..0b57007fe87 100644 --- a/dubbo-spring-boot-project/dubbo-spring-boot-starters/dubbo-zookeeper-curator5-spring-boot-starter/pom.xml +++ b/dubbo-spring-boot-project/dubbo-spring-boot-starters/dubbo-zookeeper-curator5-spring-boot-starter/pom.xml @@ -29,21 +29,14 @@ jar Apache Dubbo Zookeeper Curator5 Spring Boot Starter - - 5.1.0 - 3.8.4 - - org.apache.curator curator-x-discovery - ${curator5_version} org.apache.zookeeper zookeeper - ${zookeeper_version} io.netty diff --git a/dubbo-spring-boot-project/dubbo-spring-boot-starters/dubbo-zookeeper-spring-boot-starter/pom.xml b/dubbo-spring-boot-project/dubbo-spring-boot-starters/dubbo-zookeeper-spring-boot-starter/pom.xml deleted file mode 100644 index 7ca946f46be..00000000000 --- a/dubbo-spring-boot-project/dubbo-spring-boot-starters/dubbo-zookeeper-spring-boot-starter/pom.xml +++ /dev/null @@ -1,48 +0,0 @@ - - - - 4.0.0 - - org.apache.dubbo - dubbo-spring-boot-starters - ${revision} - ../pom.xml - - - dubbo-zookeeper-spring-boot-starter - ${revision} - jar - Apache Dubbo Zookeeper Spring Boot Starter - - - 3.8.4 - - - - - org.apache.curator - curator-x-discovery - - - org.apache.zookeeper - zookeeper - ${zookeeper_version} - - - - diff --git a/dubbo-spring-boot-project/dubbo-spring-boot-starters/pom.xml b/dubbo-spring-boot-project/dubbo-spring-boot-starters/pom.xml index de6dd545b2b..d3bcc63bcb0 100644 --- a/dubbo-spring-boot-project/dubbo-spring-boot-starters/pom.xml +++ b/dubbo-spring-boot-project/dubbo-spring-boot-starters/pom.xml @@ -31,7 +31,6 @@ dubbo-nacos-spring-boot-starter - dubbo-zookeeper-spring-boot-starter dubbo-zookeeper-curator5-spring-boot-starter dubbo-sentinel-spring-boot-starter dubbo-seata-spring-boot-starter diff --git a/dubbo-test/dubbo-dependencies-all/pom.xml b/dubbo-test/dubbo-dependencies-all/pom.xml index ddd9b6b6eb9..87f11cb57c8 100644 --- a/dubbo-test/dubbo-dependencies-all/pom.xml +++ b/dubbo-test/dubbo-dependencies-all/pom.xml @@ -433,11 +433,6 @@ dubbo-nacos-spring-boot-starter ${project.version} - - org.apache.dubbo - dubbo-zookeeper-spring-boot-starter - ${project.version} - org.apache.dubbo dubbo-zookeeper-curator5-spring-boot-starter diff --git a/pom.xml b/pom.xml index 4597eafeb3e..5ae7b71a98c 100644 --- a/pom.xml +++ b/pom.xml @@ -85,8 +85,6 @@ dubbo-compatible dubbo-dependencies-bom dubbo-distribution - dubbo-configcenter - dubbo-dependencies dubbo-metadata dubbo-metrics dubbo-test From a20b1acea7f2003b996fe475ed3e8aa7f528772e Mon Sep 17 00:00:00 2001 From: laywin Date: Wed, 13 Nov 2024 15:11:19 +0800 Subject: [PATCH 16/19] optimize repeat registry (#14875) --- .../registry/client/metadata/ServiceInstanceMetadataUtils.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/ServiceInstanceMetadataUtils.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/ServiceInstanceMetadataUtils.java index ac10fd5835f..ba84044c45a 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/ServiceInstanceMetadataUtils.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/ServiceInstanceMetadataUtils.java @@ -218,7 +218,7 @@ public static void registerMetadataAndInstance(ApplicationModel applicationModel applicationModel, Collections.singletonList(getServiceDiscoveryName(serviceDiscovery))), () -> { // register service instance - serviceDiscoveries.forEach(ServiceDiscovery::register); + serviceDiscovery.register(); return null; }); } From aed770dd44927336579fa0919be432e7e36f16b8 Mon Sep 17 00:00:00 2001 From: Albumen Kevin Date: Wed, 13 Nov 2024 14:19:32 +0800 Subject: [PATCH 17/19] Update Codecov Token --- .github/workflows/build-and-test-pr.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/build-and-test-pr.yml b/.github/workflows/build-and-test-pr.yml index 2db3a83be26..f9cfd151fdb 100644 --- a/.github/workflows/build-and-test-pr.yml +++ b/.github/workflows/build-and-test-pr.yml @@ -526,7 +526,12 @@ jobs: - name: "Upload coverage to Codecov" uses: codecov/codecov-action@v4 with: + token: ${{ secrets.CODECOV_TOKEN }} + version: v0.6.0 verbose: true + env: + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} + error-code-inspecting: needs: check-format From 5f7e1d976d94a7d89c633d3f83cb6ab21556bd59 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 14 Nov 2024 15:00:12 +0800 Subject: [PATCH 18/19] Bump org.apache.groovy:groovy from 4.0.23 to 4.0.24 (#14887) Bumps [org.apache.groovy:groovy](https://github.com/apache/groovy) from 4.0.23 to 4.0.24. - [Commits](https://github.com/apache/groovy/commits) --- updated-dependencies: - dependency-name: org.apache.groovy:groovy dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- dubbo-dependencies-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dubbo-dependencies-bom/pom.xml b/dubbo-dependencies-bom/pom.xml index f591d485abb..27625aa8183 100644 --- a/dubbo-dependencies-bom/pom.xml +++ b/dubbo-dependencies-bom/pom.xml @@ -153,7 +153,7 @@ 2.24.1 2.17.0 1.17.1 - 4.0.23 + 4.0.24 5.11.3 From 6509b4a8538385fde503728ad569fc80b48a6967 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 14 Nov 2024 15:00:21 +0800 Subject: [PATCH 19/19] Bump io.opentelemetry:opentelemetry-bom from 1.43.0 to 1.44.1 (#14886) Bumps [io.opentelemetry:opentelemetry-bom](https://github.com/open-telemetry/opentelemetry-java) from 1.43.0 to 1.44.1. - [Release notes](https://github.com/open-telemetry/opentelemetry-java/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-java/blob/main/CHANGELOG.md) - [Commits](https://github.com/open-telemetry/opentelemetry-java/compare/v1.43.0...v1.44.1) --- updated-dependencies: - dependency-name: io.opentelemetry:opentelemetry-bom dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- dubbo-dependencies-bom/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dubbo-dependencies-bom/pom.xml b/dubbo-dependencies-bom/pom.xml index 27625aa8183..60e1f6a1f5a 100644 --- a/dubbo-dependencies-bom/pom.xml +++ b/dubbo-dependencies-bom/pom.xml @@ -123,7 +123,7 @@ 3.17.0 0.1.35 1.13.6 - 1.43.0 + 1.44.1 3.4.2 1.3.5 3.3