diff --git a/.gitignore b/.gitignore index 7f60d60a3dd..a98a8a69457 100644 --- a/.gitignore +++ b/.gitignore @@ -28,3 +28,4 @@ target/ # system ignore .DS_Store Thumbs.db +*.orig diff --git a/dubbo-config/dubbo-config-api/src/test/java/com/alibaba/dubbo/config/AbstractConfigTest.java b/dubbo-config/dubbo-config-api/src/test/java/com/alibaba/dubbo/config/AbstractConfigTest.java index 5366b909109..0ef1353030d 100644 --- a/dubbo-config/dubbo-config-api/src/test/java/com/alibaba/dubbo/config/AbstractConfigTest.java +++ b/dubbo-config/dubbo-config-api/src/test/java/com/alibaba/dubbo/config/AbstractConfigTest.java @@ -21,6 +21,7 @@ import com.alibaba.dubbo.config.api.Greeting; import com.alibaba.dubbo.config.support.Parameter; import junit.framework.TestCase; +import org.junit.Ignore; import org.junit.Test; import java.lang.annotation.ElementType; @@ -255,6 +256,7 @@ public void checkParameterName() throws Exception { } @Test + @Ignore @Config(interfaceClass = Greeting.class, filter = {"f1, f2"}, listener = {"l1, l2"}, parameters = {"k1", "v1", "k2", "v2"}) public void appendAnnotation() throws Exception { diff --git a/dubbo-config/dubbo-config-api/src/test/java/com/alibaba/dubbo/config/ProtocolConfigTest.java.orig b/dubbo-config/dubbo-config-api/src/test/java/com/alibaba/dubbo/config/ProtocolConfigTest.java.orig deleted file mode 100644 index c22910bb93c..00000000000 --- a/dubbo-config/dubbo-config-api/src/test/java/com/alibaba/dubbo/config/ProtocolConfigTest.java.orig +++ /dev/null @@ -1,214 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.alibaba.dubbo.config; - -<<<<<<< HEAD -import com.alibaba.dubbo.common.extension.ExtensionLoader; -import com.alibaba.dubbo.config.mock.MockProtocol2; -======= ->>>>>>> e201004e985f3ae43ee8c65baa16bcc0aecc0000 -import com.alibaba.dubbo.rpc.Protocol; -import org.junit.Test; -import org.mockito.Mockito; - -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; - -import static org.hamcrest.Matchers.equalTo; -import static org.hamcrest.Matchers.hasEntry; -import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; - -public class ProtocolConfigTest { - - @Test - public void testDestroy() throws Exception { - Protocol protocol = Mockito.mock(Protocol.class); - MockProtocol2.delegate = protocol; - ProtocolConfig protocolConfig = new ProtocolConfig(); - protocolConfig.setName("mockprotocol2"); - protocolConfig.destory(); - Mockito.verify(protocol).destroy(); - } - - @Test - public void testName() throws Exception { - ProtocolConfig protocol = new ProtocolConfig(); - protocol.setName("name"); - Map parameters = new HashMap(); - ProtocolConfig.appendParameters(parameters, protocol); - assertThat(protocol.getName(), equalTo("name")); - assertThat(protocol.getId(), equalTo("name")); - assertThat(parameters.isEmpty(), is(true)); - } - - @Test - public void testHost() throws Exception { - ProtocolConfig protocol = new ProtocolConfig(); - protocol.setHost("host"); - Map parameters = new HashMap(); - ProtocolConfig.appendParameters(parameters, protocol); - assertThat(protocol.getHost(), equalTo("host")); - assertThat(parameters.isEmpty(), is(true)); - } - - @Test - public void testPort() throws Exception { - ProtocolConfig protocol = new ProtocolConfig(); - protocol.setPort(8080); - Map parameters = new HashMap(); - ProtocolConfig.appendParameters(parameters, protocol); - assertThat(protocol.getPort(), equalTo(8080)); - assertThat(parameters.isEmpty(), is(true)); - } - - @Test - public void testPath() throws Exception { - ProtocolConfig protocol = new ProtocolConfig(); - protocol.setContextpath("context-path"); - Map parameters = new HashMap(); - ProtocolConfig.appendParameters(parameters, protocol); - assertThat(protocol.getPath(), equalTo("context-path")); - assertThat(protocol.getContextpath(), equalTo("context-path")); - assertThat(parameters.isEmpty(), is(true)); - protocol.setPath("path"); - assertThat(protocol.getPath(), equalTo("path")); - assertThat(protocol.getContextpath(), equalTo("path")); - } - - @Test - public void testThreads() throws Exception { - ProtocolConfig protocol = new ProtocolConfig(); - protocol.setThreads(10); - assertThat(protocol.getThreads(), is(10)); - } - - @Test - public void testIothreads() throws Exception { - ProtocolConfig protocol = new ProtocolConfig(); - protocol.setIothreads(10); - assertThat(protocol.getIothreads(), is(10)); - } - - @Test - public void testQueues() throws Exception { - ProtocolConfig protocol = new ProtocolConfig(); - protocol.setQueues(10); - assertThat(protocol.getQueues(), is(10)); - } - - @Test - public void testAccepts() throws Exception { - ProtocolConfig protocol = new ProtocolConfig(); - protocol.setAccepts(10); - assertThat(protocol.getAccepts(), is(10)); - } - - @Test - public void testCodec() throws Exception { - ProtocolConfig protocol = new ProtocolConfig(); - protocol.setName("dubbo"); - protocol.setCodec("mockcodec"); - assertThat(protocol.getCodec(), equalTo("mockcodec")); - } - - @Test - public void testAccesslog() throws Exception { - ProtocolConfig protocol = new ProtocolConfig(); - protocol.setAccesslog("access.log"); - assertThat(protocol.getAccesslog(), equalTo("access.log")); - } - - @Test - public void testTelnet() throws Exception { - ProtocolConfig protocol = new ProtocolConfig(); - protocol.setTelnet("mocktelnethandler"); - assertThat(protocol.getTelnet(), equalTo("mocktelnethandler")); - } - - @Test - public void testRegister() throws Exception { - ProtocolConfig protocol = new ProtocolConfig(); - protocol.setRegister(true); - assertThat(protocol.isRegister(), is(true)); - } - - @Test - public void testTransporter() throws Exception { - ProtocolConfig protocol = new ProtocolConfig(); - protocol.setTransporter("mocktransporter"); - assertThat(protocol.getTransporter(), equalTo("mocktransporter")); - } - - @Test - public void testExchanger() throws Exception { - ProtocolConfig protocol = new ProtocolConfig(); - protocol.setExchanger("mockexchanger"); - assertThat(protocol.getExchanger(), equalTo("mockexchanger")); - } - - @Test - public void testDispatcher() throws Exception { - ProtocolConfig protocol = new ProtocolConfig(); - protocol.setDispatcher("mockdispatcher"); - assertThat(protocol.getDispatcher(), equalTo("mockdispatcher")); - } - - @Test - public void testNetworker() throws Exception { - ProtocolConfig protocol = new ProtocolConfig(); - protocol.setNetworker("networker"); - assertThat(protocol.getNetworker(), equalTo("networker")); - } - - @Test - public void testParameters() throws Exception { - ProtocolConfig protocol = new ProtocolConfig(); - protocol.setParameters(Collections.singletonMap("k1", "v1")); - assertThat(protocol.getParameters(), hasEntry("k1", "v1")); - } - - @Test - public void testDefault() throws Exception { - ProtocolConfig protocol = new ProtocolConfig(); - protocol.setDefault(true); - assertThat(protocol.isDefault(), is(true)); - } - - @Test - public void testKeepAlive() throws Exception { - ProtocolConfig protocol = new ProtocolConfig(); - protocol.setKeepAlive(true); - assertThat(protocol.getKeepAlive(), is(true)); - } - - @Test - public void testOptimizer() throws Exception { - ProtocolConfig protocol = new ProtocolConfig(); - protocol.setOptimizer("optimizer"); - assertThat(protocol.getOptimizer(), equalTo("optimizer")); - } - - @Test - public void testExtension() throws Exception { - ProtocolConfig protocol = new ProtocolConfig(); - protocol.setExtension("extension"); - assertThat(protocol.getExtension(), equalTo("extension")); - } -} diff --git a/dubbo-config/dubbo-config-api/src/test/java/com/alibaba/dubbo/config/mock/MockProxyFactory.java b/dubbo-config/dubbo-config-api/src/test/java/com/alibaba/dubbo/config/mock/MockProxyFactory.java index 3de2e3a9833..cd78366c00b 100644 --- a/dubbo-config/dubbo-config-api/src/test/java/com/alibaba/dubbo/config/mock/MockProxyFactory.java +++ b/dubbo-config/dubbo-config-api/src/test/java/com/alibaba/dubbo/config/mock/MockProxyFactory.java @@ -27,6 +27,11 @@ public T getProxy(Invoker invoker) throws RpcException { return null; } + @Override + public T getProxy(Invoker invoker, boolean generic) throws RpcException { + return null; + } + @Override public Invoker getInvoker(T proxy, Class type, URL url) throws RpcException { return null; diff --git a/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/compat/dubbo.xsd b/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/compat/dubbo.xsd new file mode 100644 index 00000000000..91069146e1a --- /dev/null +++ b/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/compat/dubbo.xsd @@ -0,0 +1,1210 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/spring.handlers b/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/spring.handlers index c3d09aefcd2..d6329bfeabb 100644 --- a/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/spring.handlers +++ b/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/spring.handlers @@ -1 +1,2 @@ -http\://dubbo.apache.org/schema/dubbo=com.alibaba.dubbo.config.spring.schema.DubboNamespaceHandler \ No newline at end of file +http\://dubbo.apache.org/schema/dubbo=com.alibaba.dubbo.config.spring.schema.DubboNamespaceHandler +http\://code.alibabatech.com/schema/dubbo=com.alibaba.dubbo.config.spring.schema.DubboNamespaceHandler \ No newline at end of file diff --git a/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/spring.schemas b/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/spring.schemas index 91bb3d7fd80..7e0cfdee05d 100644 --- a/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/spring.schemas +++ b/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/spring.schemas @@ -1 +1,2 @@ -http\://dubbo.apache.org/schema/dubbo/dubbo.xsd=META-INF/dubbo.xsd \ No newline at end of file +http\://dubbo.apache.org/schema/dubbo/dubbo.xsd=META-INF/dubbo.xsd +http\://code.alibabatech.com/schema/dubbo/dubbo.xsd=META-INF/compat/dubbo.xsd \ No newline at end of file diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/dispatcher/ChannelEventRunnable.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/dispatcher/ChannelEventRunnable.java index 038adea56cf..44dea9464c5 100644 --- a/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/dispatcher/ChannelEventRunnable.java +++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/com/alibaba/dubbo/remoting/transport/dispatcher/ChannelEventRunnable.java @@ -52,7 +52,15 @@ public ChannelEventRunnable(Channel channel, ChannelHandler handler, ChannelStat @Override public void run() { - switch (state) { + if (state == ChannelState.RECEIVED) { + try { + handler.received(channel, message); + } catch (Exception e) { + logger.warn("ChannelEventRunnable handle " + state + " operation error, channel is " + channel + + ", message is " + message, e); + } + } else { + switch (state) { case CONNECTED: try { handler.connected(channel); @@ -74,15 +82,6 @@ public void run() { logger.warn("ChannelEventRunnable handle " + state + " operation error, channel is " + channel + ", message is " + message, e); } - break; - case RECEIVED: - try { - handler.received(channel, message); - } catch (Exception e) { - logger.warn("ChannelEventRunnable handle " + state + " operation error, channel is " + channel - + ", message is " + message, e); - } - break; case CAUGHT: try { handler.caught(channel, exception); @@ -93,7 +92,9 @@ public void run() { break; default: logger.warn("unknown state: " + state + ", message is " + message); + } } + } /** diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/ProxyFactory.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/ProxyFactory.java index 6ba705717ba..fb03d6bda44 100644 --- a/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/ProxyFactory.java +++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/ProxyFactory.java @@ -36,6 +36,15 @@ public interface ProxyFactory { @Adaptive({Constants.PROXY_KEY}) T getProxy(Invoker invoker) throws RpcException; + /** + * create proxy. + * + * @param invoker + * @return proxy + */ + @Adaptive({Constants.PROXY_KEY}) + T getProxy(Invoker invoker, boolean generic) throws RpcException; + /** * create invoker. * diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/filter/GenericFilter.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/filter/GenericFilter.java index d393822625a..8404a99f3ca 100644 --- a/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/filter/GenericFilter.java +++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/filter/GenericFilter.java @@ -32,10 +32,12 @@ import com.alibaba.dubbo.rpc.Invocation; import com.alibaba.dubbo.rpc.Invoker; import com.alibaba.dubbo.rpc.Result; +import com.alibaba.dubbo.rpc.RpcContext; import com.alibaba.dubbo.rpc.RpcException; import com.alibaba.dubbo.rpc.RpcInvocation; import com.alibaba.dubbo.rpc.RpcResult; import com.alibaba.dubbo.rpc.service.GenericException; +import com.alibaba.dubbo.rpc.service.GenericService; import com.alibaba.dubbo.rpc.support.ProtocolUtils; import java.io.IOException; @@ -52,7 +54,7 @@ public Result invoke(Invoker invoker, Invocation inv) throws RpcException { if (inv.getMethodName().equals(Constants.$INVOKE) && inv.getArguments() != null && inv.getArguments().length == 3 - && !ProtocolUtils.isGeneric(invoker.getUrl().getParameter(Constants.GENERIC_KEY))) { + && !invoker.getInterface().equals(GenericService.class)) { String name = ((String) inv.getArguments()[0]).trim(); String[] types = (String[]) inv.getArguments()[1]; Object[] args = (Object[]) inv.getArguments()[2]; @@ -63,6 +65,11 @@ public Result invoke(Invoker invoker, Invocation inv) throws RpcException { args = new Object[params.length]; } String generic = inv.getAttachment(Constants.GENERIC_KEY); + + if (StringUtils.isBlank(generic)) { + generic = RpcContext.getContext().getAttachment(Constants.GENERIC_KEY); + } + if (StringUtils.isEmpty(generic) || ProtocolUtils.isDefaultGenericSerialization(generic)) { args = PojoUtils.realize(args, params, method.getGenericParameterTypes()); diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/filter/GenericImplFilter.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/filter/GenericImplFilter.java index 99bced54e74..6be08fef47c 100644 --- a/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/filter/GenericImplFilter.java +++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/filter/GenericImplFilter.java @@ -155,13 +155,13 @@ public Result invoke(Invoker invoker, Invocation invocation) throws RpcExcept for (Object arg : args) { if (!(byte[].class == arg.getClass())) { - error(byte[].class.getName(), arg.getClass().getName()); + error(generic, byte[].class.getName(), arg.getClass().getName()); } } } else if (ProtocolUtils.isBeanGenericSerialization(generic)) { for (Object arg : args) { if (!(arg instanceof JavaBeanDescriptor)) { - error(JavaBeanDescriptor.class.getName(), arg.getClass().getName()); + error(generic, JavaBeanDescriptor.class.getName(), arg.getClass().getName()); } } } @@ -172,10 +172,10 @@ public Result invoke(Invoker invoker, Invocation invocation) throws RpcExcept return invoker.invoke(invocation); } - private void error(String expected, String actual) throws RpcException { + private void error(String generic, String expected, String actual) throws RpcException { throw new RpcException( "Generic serialization [" + - Constants.GENERIC_SERIALIZATION_NATIVE_JAVA + + generic + "] only support message type " + expected + " and your message type is " + diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/protocol/AbstractProxyProtocol.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/protocol/AbstractProxyProtocol.java index 8136cc02165..561520c49e7 100644 --- a/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/protocol/AbstractProxyProtocol.java +++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/protocol/AbstractProxyProtocol.java @@ -68,7 +68,7 @@ public Exporter export(final Invoker invoker) throws RpcException { if (exporter != null) { return exporter; } - final Runnable runnable = doExport(proxyFactory.getProxy(invoker), invoker.getInterface(), invoker.getUrl()); + final Runnable runnable = doExport(proxyFactory.getProxy(invoker, true), invoker.getInterface(), invoker.getUrl()); exporter = new AbstractExporter(invoker) { @Override public void unexport() { @@ -89,12 +89,12 @@ public void unexport() { @Override public Invoker refer(final Class type, final URL url) throws RpcException { - final Invoker tagert = proxyFactory.getInvoker(doRefer(type, url), type, url); + final Invoker target = proxyFactory.getInvoker(doRefer(type, url), type, url); Invoker invoker = new AbstractInvoker(type, url) { @Override protected Result doInvoke(Invocation invocation) throws Throwable { try { - Result result = tagert.invoke(invocation); + Result result = target.invoke(invocation); Throwable e = result.getException(); if (e != null) { for (Class rpcException : rpcExceptions) { diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/proxy/AbstractProxyFactory.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/proxy/AbstractProxyFactory.java index 21c350da9c1..d27f6089709 100644 --- a/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/proxy/AbstractProxyFactory.java +++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/proxy/AbstractProxyFactory.java @@ -22,6 +22,7 @@ import com.alibaba.dubbo.rpc.ProxyFactory; import com.alibaba.dubbo.rpc.RpcException; import com.alibaba.dubbo.rpc.service.EchoService; +import com.alibaba.dubbo.rpc.service.GenericService; /** * AbstractProxyFactory @@ -30,6 +31,11 @@ public abstract class AbstractProxyFactory implements ProxyFactory { @Override public T getProxy(Invoker invoker) throws RpcException { + return getProxy(invoker, false); + } + + @Override + public T getProxy(Invoker invoker, boolean generic) throws RpcException { Class[] interfaces = null; String config = invoker.getUrl().getParameter("interfaces"); if (config != null && config.length() > 0) { @@ -46,6 +52,15 @@ public T getProxy(Invoker invoker) throws RpcException { if (interfaces == null) { interfaces = new Class[]{invoker.getInterface(), EchoService.class}; } + + if (!invoker.getInterface().equals(GenericService.class) && generic) { + int len = interfaces.length; + Class[] temp = interfaces; + interfaces = new Class[len + 1]; + System.arraycopy(temp, 0, interfaces, 0, len); + interfaces[len] = GenericService.class; + } + return getProxy(invoker, interfaces); } diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/proxy/wrapper/StubProxyFactoryWrapper.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/proxy/wrapper/StubProxyFactoryWrapper.java index ec3db16ceba..3f3ed3ff493 100644 --- a/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/proxy/wrapper/StubProxyFactoryWrapper.java +++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/com/alibaba/dubbo/rpc/proxy/wrapper/StubProxyFactoryWrapper.java @@ -54,6 +54,11 @@ public void setProtocol(Protocol protocol) { this.protocol = protocol; } + @Override + public T getProxy(Invoker invoker, boolean generic) throws RpcException { + return proxyFactory.getProxy(invoker, generic); + } + @Override @SuppressWarnings({"unchecked", "rawtypes"}) public T getProxy(Invoker invoker) throws RpcException { diff --git a/dubbo-rpc/dubbo-rpc-hessian/pom.xml b/dubbo-rpc/dubbo-rpc-hessian/pom.xml index 00ca28cf2a3..98ad82de8f5 100644 --- a/dubbo-rpc/dubbo-rpc-hessian/pom.xml +++ b/dubbo-rpc/dubbo-rpc-hessian/pom.xml @@ -48,5 +48,11 @@ org.apache.httpcomponents httpclient + + com.alibaba + dubbo-serialization-jdk + ${project.parent.version} + test + \ No newline at end of file diff --git a/dubbo-rpc/dubbo-rpc-hessian/src/main/java/com/alibaba/dubbo/rpc/protocol/hessian/DubboHessianURLConnectionFactory.java b/dubbo-rpc/dubbo-rpc-hessian/src/main/java/com/alibaba/dubbo/rpc/protocol/hessian/DubboHessianURLConnectionFactory.java new file mode 100644 index 00000000000..8fe2f14de44 --- /dev/null +++ b/dubbo-rpc/dubbo-rpc-hessian/src/main/java/com/alibaba/dubbo/rpc/protocol/hessian/DubboHessianURLConnectionFactory.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 com.alibaba.dubbo.rpc.protocol.hessian; + +import com.alibaba.dubbo.common.Constants; +import com.alibaba.dubbo.rpc.RpcContext; +import com.caucho.hessian.client.HessianConnection; +import com.caucho.hessian.client.HessianURLConnectionFactory; + +import java.io.IOException; +import java.net.URL; + +public class DubboHessianURLConnectionFactory extends HessianURLConnectionFactory { + + @Override + public HessianConnection open(URL url) throws IOException { + HessianConnection connection = super.open(url); + RpcContext context = RpcContext.getContext(); + for (String key : context.getAttachments().keySet()) { + connection.addHeader(Constants.DEFAULT_EXCHANGER + key, context.getAttachment(key)); + } + + return connection; + } +} diff --git a/dubbo-rpc/dubbo-rpc-hessian/src/main/java/com/alibaba/dubbo/rpc/protocol/hessian/HessianProtocol.java b/dubbo-rpc/dubbo-rpc-hessian/src/main/java/com/alibaba/dubbo/rpc/protocol/hessian/HessianProtocol.java index f1eae5cf63c..9733307d629 100644 --- a/dubbo-rpc/dubbo-rpc-hessian/src/main/java/com/alibaba/dubbo/rpc/protocol/hessian/HessianProtocol.java +++ b/dubbo-rpc/dubbo-rpc-hessian/src/main/java/com/alibaba/dubbo/rpc/protocol/hessian/HessianProtocol.java @@ -25,8 +25,11 @@ import com.alibaba.dubbo.rpc.RpcException; import com.alibaba.dubbo.rpc.protocol.AbstractProxyProtocol; +import com.alibaba.dubbo.rpc.service.GenericService; +import com.alibaba.dubbo.rpc.support.ProtocolUtils; import com.caucho.hessian.HessianException; import com.caucho.hessian.client.HessianConnectionException; +import com.caucho.hessian.client.HessianConnectionFactory; import com.caucho.hessian.client.HessianProxyFactory; import com.caucho.hessian.io.HessianMethodSerializationException; import com.caucho.hessian.server.HessianSkeleton; @@ -37,6 +40,7 @@ import java.io.IOException; import java.net.SocketTimeoutException; import java.util.ArrayList; +import java.util.Enumeration; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; @@ -73,12 +77,17 @@ protected Runnable doExport(T impl, Class type, URL url) throws RpcExcept serverMap.put(addr, server); } final String path = url.getAbsolutePath(); - HessianSkeleton skeleton = new HessianSkeleton(impl, type); + final HessianSkeleton skeleton = new HessianSkeleton(impl, type); skeletonMap.put(path, skeleton); + + final String genericPath = path + "/" + Constants.GENERIC_KEY; + skeletonMap.put(genericPath, new HessianSkeleton(impl, GenericService.class)); + return new Runnable() { @Override public void run() { skeletonMap.remove(path); + skeletonMap.remove(genericPath); } }; } @@ -86,6 +95,13 @@ public void run() { @Override @SuppressWarnings("unchecked") protected T doRefer(Class serviceType, URL url) throws RpcException { + String generic = url.getParameter(Constants.GENERIC_KEY); + boolean isGeneric = ProtocolUtils.isGeneric(generic) || serviceType.equals(GenericService.class); + if (isGeneric) { + RpcContext.getContext().setAttachment(Constants.GENERIC_KEY, generic); + url = url.setPath(url.getPath() + "/" + Constants.GENERIC_KEY); + } + HessianProxyFactory hessianProxyFactory = new HessianProxyFactory(); boolean isHessian2Request = url.getParameter(Constants.HESSIAN2_REQUEST_KEY, Constants.DEFAULT_HESSIAN2_REQUEST); hessianProxyFactory.setHessian2Request(isHessian2Request); @@ -96,6 +112,10 @@ protected T doRefer(Class serviceType, URL url) throws RpcException { hessianProxyFactory.setConnectionFactory(new HttpClientConnectionFactory()); } else if (client != null && client.length() > 0 && !Constants.DEFAULT_HTTP_CLIENT.equals(client)) { throw new IllegalStateException("Unsupported http protocol client=\"" + client + "\"!"); + } else { + HessianConnectionFactory factory = new DubboHessianURLConnectionFactory(); + factory.setHessianProxyFactory(hessianProxyFactory); + hessianProxyFactory.setConnectionFactory(factory); } int timeout = url.getParameter(Constants.TIMEOUT_KEY, Constants.DEFAULT_TIMEOUT); hessianProxyFactory.setConnectTimeout(timeout); @@ -148,6 +168,16 @@ public void handle(HttpServletRequest request, HttpServletResponse response) response.setStatus(500); } else { RpcContext.getContext().setRemoteAddress(request.getRemoteAddr(), request.getRemotePort()); + + Enumeration enumeration = request.getHeaderNames(); + while (enumeration.hasMoreElements()) { + String key = enumeration.nextElement(); + if (key.startsWith(Constants.DEFAULT_EXCHANGER)) { + RpcContext.getContext().setAttachment(key.substring(Constants.DEFAULT_EXCHANGER.length()), + request.getHeader(key)); + } + } + try { skeleton.invoke(request.getInputStream(), response.getOutputStream()); } catch (Throwable e) { diff --git a/dubbo-rpc/dubbo-rpc-hessian/src/main/java/com/alibaba/dubbo/rpc/protocol/hessian/HttpClientConnectionFactory.java b/dubbo-rpc/dubbo-rpc-hessian/src/main/java/com/alibaba/dubbo/rpc/protocol/hessian/HttpClientConnectionFactory.java index 033277d02e6..b19cd275c8a 100644 --- a/dubbo-rpc/dubbo-rpc-hessian/src/main/java/com/alibaba/dubbo/rpc/protocol/hessian/HttpClientConnectionFactory.java +++ b/dubbo-rpc/dubbo-rpc-hessian/src/main/java/com/alibaba/dubbo/rpc/protocol/hessian/HttpClientConnectionFactory.java @@ -16,6 +16,8 @@ */ package com.alibaba.dubbo.rpc.protocol.hessian; +import com.alibaba.dubbo.common.Constants; +import com.alibaba.dubbo.rpc.RpcContext; import com.caucho.hessian.client.HessianConnection; import com.caucho.hessian.client.HessianConnectionFactory; import com.caucho.hessian.client.HessianProxyFactory; @@ -41,7 +43,12 @@ public void setHessianProxyFactory(HessianProxyFactory factory) { @Override public HessianConnection open(URL url) throws IOException { - return new HttpClientConnection(httpClient, url); + HttpClientConnection httpClientConnection = new HttpClientConnection(httpClient, url); + RpcContext context = RpcContext.getContext(); + for (String key : context.getAttachments().keySet()) { + httpClientConnection.addHeader(Constants.DEFAULT_EXCHANGER + key, context.getAttachment(key)); + } + return httpClientConnection; } } diff --git a/dubbo-rpc/dubbo-rpc-hessian/src/test/java/com/alibaba/dubbo/rpc/protocol/hessian/HessianProtocolTest.java b/dubbo-rpc/dubbo-rpc-hessian/src/test/java/com/alibaba/dubbo/rpc/protocol/hessian/HessianProtocolTest.java index 6e8ab72e174..f8f830d0cd9 100644 --- a/dubbo-rpc/dubbo-rpc-hessian/src/test/java/com/alibaba/dubbo/rpc/protocol/hessian/HessianProtocolTest.java +++ b/dubbo-rpc/dubbo-rpc-hessian/src/test/java/com/alibaba/dubbo/rpc/protocol/hessian/HessianProtocolTest.java @@ -17,17 +17,29 @@ package com.alibaba.dubbo.rpc.protocol.hessian; import com.alibaba.dubbo.common.URL; +import com.alibaba.dubbo.common.beanutil.JavaBeanDescriptor; +import com.alibaba.dubbo.common.beanutil.JavaBeanSerializeUtil; import com.alibaba.dubbo.common.extension.ExtensionLoader; +import com.alibaba.dubbo.common.serialize.ObjectInput; +import com.alibaba.dubbo.common.serialize.ObjectOutput; +import com.alibaba.dubbo.common.serialize.Serialization; +import com.alibaba.dubbo.common.serialize.nativejava.NativeJavaSerialization; import com.alibaba.dubbo.rpc.Exporter; import com.alibaba.dubbo.rpc.Invoker; import com.alibaba.dubbo.rpc.Protocol; import com.alibaba.dubbo.rpc.ProxyFactory; +import com.alibaba.dubbo.rpc.RpcContext; import com.alibaba.dubbo.rpc.RpcException; import com.alibaba.dubbo.rpc.protocol.hessian.HessianServiceImpl.MyException; +import com.alibaba.dubbo.rpc.service.GenericService; import org.junit.Assert; import org.junit.Test; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; + import static org.junit.Assert.fail; /** @@ -51,6 +63,87 @@ public void testHessianProtocol() { invoker.destroy(); exporter.unexport(); } + + @Test + public void testGenericInvoke() { + HessianServiceImpl server = new HessianServiceImpl(); + Assert.assertFalse(server.isCalled()); + ProxyFactory proxyFactory = ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension(); + Protocol protocol = ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension(); + URL url = URL.valueOf("hessian://127.0.0.1:5342/" + HessianService.class.getName() + "?version=1.0.0"); + Exporter exporter = protocol.export(proxyFactory.getInvoker(server, HessianService.class, url)); + Invoker invoker = protocol.refer(GenericService.class, url); + GenericService client = proxyFactory.getProxy(invoker, true); + String result = (String) client.$invoke("sayHello", new String[]{"java.lang.String"}, new Object[]{"haha"}); + Assert.assertTrue(server.isCalled()); + Assert.assertEquals("Hello, haha", result); + invoker.destroy(); + exporter.unexport(); + } + + @Test + public void testGenericInvokeWithNativeJava() throws IOException, ClassNotFoundException { + HessianServiceImpl server = new HessianServiceImpl(); + Assert.assertFalse(server.isCalled()); + ProxyFactory proxyFactory = ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension(); + Protocol protocol = ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension(); + URL url = URL.valueOf("hessian://127.0.0.1:5342/" + HessianService.class.getName() + "?version=1.0.0&generic=nativejava"); + Exporter exporter = protocol.export(proxyFactory.getInvoker(server, HessianService.class, url)); + Invoker invoker = protocol.refer(GenericService.class, url); + GenericService client = proxyFactory.getProxy(invoker); + + Serialization serialization = new NativeJavaSerialization(); + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + + ObjectOutput objectOutput = serialization.serialize(url, byteArrayOutputStream); + objectOutput.writeObject("haha"); + objectOutput.flushBuffer(); + + Object result = client.$invoke("sayHello", new String[]{"java.lang.String"}, new Object[]{byteArrayOutputStream.toByteArray()}); + ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream((byte[]) result); + ObjectInput objectInput = serialization.deserialize(url, byteArrayInputStream); + Assert.assertTrue(server.isCalled()); + Assert.assertEquals("Hello, haha", objectInput.readObject()); + invoker.destroy(); + exporter.unexport(); + } + + @Test + public void testGenericInvokeWithRpcContext() { + RpcContext.getContext().setAttachment("myContext", "123"); + + HessianServiceImpl server = new HessianServiceImpl(); + ProxyFactory proxyFactory = ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension(); + Protocol protocol = ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension(); + URL url = URL.valueOf("hessian://127.0.0.1:5342/" + HessianService.class.getName() + "?version=1.0.0"); + Exporter exporter = protocol.export(proxyFactory.getInvoker(server, HessianService.class, url)); + Invoker invoker = protocol.refer(GenericService.class, url); + GenericService client = proxyFactory.getProxy(invoker, true); + String result = (String) client.$invoke("context", new String[]{"java.lang.String"}, new Object[]{"haha"}); + Assert.assertEquals("Hello, haha context, 123", result); + invoker.destroy(); + exporter.unexport(); + } + + @Test + public void testGenericInvokeWithBean() { + HessianServiceImpl server = new HessianServiceImpl(); + Assert.assertFalse(server.isCalled()); + ProxyFactory proxyFactory = ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension(); + Protocol protocol = ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension(); + URL url = URL.valueOf("hessian://127.0.0.1:5342/" + HessianService.class.getName() + "?version=1.0.0&generic=bean"); + Exporter exporter = protocol.export(proxyFactory.getInvoker(server, HessianService.class, url)); + Invoker invoker = protocol.refer(GenericService.class, url); + GenericService client = proxyFactory.getProxy(invoker); + + JavaBeanDescriptor javaBeanDescriptor = JavaBeanSerializeUtil.serialize("haha"); + + Object result = client.$invoke("sayHello", new String[]{"java.lang.String"}, new Object[]{javaBeanDescriptor}); + Assert.assertTrue(server.isCalled()); + Assert.assertEquals("Hello, haha", JavaBeanSerializeUtil.deserialize((JavaBeanDescriptor) result)); + invoker.destroy(); + exporter.unexport(); + } @Test public void testOverload() { diff --git a/dubbo-rpc/dubbo-rpc-hessian/src/test/java/com/alibaba/dubbo/rpc/protocol/hessian/HessianService.java b/dubbo-rpc/dubbo-rpc-hessian/src/test/java/com/alibaba/dubbo/rpc/protocol/hessian/HessianService.java index c2f05d28e8c..42304177926 100644 --- a/dubbo-rpc/dubbo-rpc-hessian/src/test/java/com/alibaba/dubbo/rpc/protocol/hessian/HessianService.java +++ b/dubbo-rpc/dubbo-rpc-hessian/src/test/java/com/alibaba/dubbo/rpc/protocol/hessian/HessianService.java @@ -30,4 +30,6 @@ public interface HessianService { String customException(); + String context(String name); + } diff --git a/dubbo-rpc/dubbo-rpc-hessian/src/test/java/com/alibaba/dubbo/rpc/protocol/hessian/HessianServiceImpl.java b/dubbo-rpc/dubbo-rpc-hessian/src/test/java/com/alibaba/dubbo/rpc/protocol/hessian/HessianServiceImpl.java index cc1fe3cad1e..487dc69e93b 100644 --- a/dubbo-rpc/dubbo-rpc-hessian/src/test/java/com/alibaba/dubbo/rpc/protocol/hessian/HessianServiceImpl.java +++ b/dubbo-rpc/dubbo-rpc-hessian/src/test/java/com/alibaba/dubbo/rpc/protocol/hessian/HessianServiceImpl.java @@ -16,6 +16,8 @@ */ package com.alibaba.dubbo.rpc.protocol.hessian; +import com.alibaba.dubbo.rpc.RpcContext; + /** * HessianServiceImpl */ @@ -53,6 +55,10 @@ public String customException() { throw new MyException("custom exception"); } + public String context(String name) { + return "Hello, " + name + " context, " + RpcContext.getContext().getAttachment("myContext"); + } + static class MyException extends RuntimeException { private static final long serialVersionUID = -3051041116483629056L; diff --git a/dubbo-rpc/dubbo-rpc-http/pom.xml b/dubbo-rpc/dubbo-rpc-http/pom.xml index 427b70ba6a3..93d8a0f028f 100644 --- a/dubbo-rpc/dubbo-rpc-http/pom.xml +++ b/dubbo-rpc/dubbo-rpc-http/pom.xml @@ -48,5 +48,11 @@ org.springframework spring-web + + com.alibaba + dubbo-serialization-jdk + ${project.parent.version} + test + \ No newline at end of file diff --git a/dubbo-rpc/dubbo-rpc-http/src/main/java/com/alibaba/dubbo/rpc/protocol/http/HttpProtocol.java b/dubbo-rpc/dubbo-rpc-http/src/main/java/com/alibaba/dubbo/rpc/protocol/http/HttpProtocol.java index 27a59134e8c..3fc908749a8 100644 --- a/dubbo-rpc/dubbo-rpc-http/src/main/java/com/alibaba/dubbo/rpc/protocol/http/HttpProtocol.java +++ b/dubbo-rpc/dubbo-rpc-http/src/main/java/com/alibaba/dubbo/rpc/protocol/http/HttpProtocol.java @@ -24,12 +24,16 @@ import com.alibaba.dubbo.rpc.RpcContext; import com.alibaba.dubbo.rpc.RpcException; import com.alibaba.dubbo.rpc.protocol.AbstractProxyProtocol; - +import com.alibaba.dubbo.rpc.service.GenericService; +import com.alibaba.dubbo.rpc.support.ProtocolUtils; +import org.aopalliance.intercept.MethodInvocation; import org.springframework.remoting.RemoteAccessException; import org.springframework.remoting.httpinvoker.HttpComponentsHttpInvokerRequestExecutor; import org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean; import org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter; import org.springframework.remoting.httpinvoker.SimpleHttpInvokerRequestExecutor; +import org.springframework.remoting.support.RemoteInvocation; +import org.springframework.remoting.support.RemoteInvocationFactory; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; @@ -74,6 +78,22 @@ protected Runnable doExport(final T impl, Class type, URL url) throws Rpc server = httpBinder.bind(url, new InternalHandler()); serverMap.put(addr, server); } + final String path = url.getAbsolutePath(); + skeletonMap.put(path, createExporter(impl, type)); + + final String genericPath = path + "/" + Constants.GENERIC_KEY; + + skeletonMap.put(genericPath, createExporter(impl, GenericService.class)); + return new Runnable() { + @Override + public void run() { + skeletonMap.remove(path); + skeletonMap.remove(genericPath); + } + }; + } + + private HttpInvokerServiceExporter createExporter(T impl, Class type) { final HttpInvokerServiceExporter httpServiceExporter = new HttpInvokerServiceExporter(); httpServiceExporter.setServiceInterface(type); httpServiceExporter.setService(impl); @@ -82,21 +102,33 @@ protected Runnable doExport(final T impl, Class type, URL url) throws Rpc } catch (Exception e) { throw new RpcException(e.getMessage(), e); } - final String path = url.getAbsolutePath(); - skeletonMap.put(path, httpServiceExporter); - return new Runnable() { - @Override - public void run() { - skeletonMap.remove(path); - } - }; + return httpServiceExporter; } @Override @SuppressWarnings("unchecked") protected T doRefer(final Class serviceType, final URL url) throws RpcException { + final String generic = url.getParameter(Constants.GENERIC_KEY); + final boolean isGeneric = ProtocolUtils.isGeneric(generic) || serviceType.equals(GenericService.class); + final HttpInvokerProxyFactoryBean httpProxyFactoryBean = new HttpInvokerProxyFactoryBean(); - httpProxyFactoryBean.setServiceUrl(url.toIdentityString()); + httpProxyFactoryBean.setRemoteInvocationFactory(new RemoteInvocationFactory() { + @Override + public RemoteInvocation createRemoteInvocation(MethodInvocation methodInvocation) { + RemoteInvocation invocation = new HttpRemoteInvocation(methodInvocation); + if (isGeneric) { + invocation.addAttribute(Constants.GENERIC_KEY, generic); + } + return invocation; + } + }); + + String key = url.toIdentityString(); + if (isGeneric) { + key = key + "/" + Constants.GENERIC_KEY; + } + + httpProxyFactoryBean.setServiceUrl(key); httpProxyFactoryBean.setServiceInterface(serviceType); String client = url.getParameter(Constants.CLIENT_KEY); if (client == null || client.length() == 0 || "simple".equals(client)) { @@ -112,7 +144,8 @@ protected void prepareConnection(HttpURLConnection con, httpProxyFactoryBean.setHttpInvokerRequestExecutor(httpInvokerRequestExecutor); } else if ("commons".equals(client)) { HttpComponentsHttpInvokerRequestExecutor httpInvokerRequestExecutor = new HttpComponentsHttpInvokerRequestExecutor(); - httpInvokerRequestExecutor.setReadTimeout(url.getParameter(Constants.CONNECT_TIMEOUT_KEY, Constants.DEFAULT_CONNECT_TIMEOUT)); + httpInvokerRequestExecutor.setReadTimeout(url.getParameter(Constants.TIMEOUT_KEY, Constants.DEFAULT_TIMEOUT)); + httpInvokerRequestExecutor.setConnectTimeout(url.getParameter(Constants.CONNECT_TIMEOUT_KEY, Constants.DEFAULT_CONNECT_TIMEOUT)); httpProxyFactoryBean.setHttpInvokerRequestExecutor(httpInvokerRequestExecutor); } else { throw new IllegalStateException("Unsupported http protocol client " + client + ", only supported: simple, commons"); diff --git a/dubbo-rpc/dubbo-rpc-http/src/main/java/com/alibaba/dubbo/rpc/protocol/http/HttpRemoteInvocation.java b/dubbo-rpc/dubbo-rpc-http/src/main/java/com/alibaba/dubbo/rpc/protocol/http/HttpRemoteInvocation.java new file mode 100644 index 00000000000..5054c4fded8 --- /dev/null +++ b/dubbo-rpc/dubbo-rpc-http/src/main/java/com/alibaba/dubbo/rpc/protocol/http/HttpRemoteInvocation.java @@ -0,0 +1,57 @@ +/* + * 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 com.alibaba.dubbo.rpc.protocol.http; + +import com.alibaba.dubbo.common.Constants; +import com.alibaba.dubbo.common.utils.StringUtils; +import com.alibaba.dubbo.rpc.RpcContext; +import org.aopalliance.intercept.MethodInvocation; +import org.springframework.remoting.support.RemoteInvocation; + +import java.lang.reflect.InvocationTargetException; +import java.util.HashMap; +import java.util.Map; + +public class HttpRemoteInvocation extends RemoteInvocation { + + private static final long serialVersionUID = 1L; + private static final String dubboAttachmentsAttrName = "dubbo.attachments"; + + public HttpRemoteInvocation(MethodInvocation methodInvocation) { + super(methodInvocation); + addAttribute(dubboAttachmentsAttrName, new HashMap(RpcContext.getContext().getAttachments())); + } + + @Override + public Object invoke(Object targetObject) throws NoSuchMethodException, IllegalAccessException, + InvocationTargetException { + RpcContext context = RpcContext.getContext(); + context.setAttachments((Map) getAttribute(dubboAttachmentsAttrName)); + + String generic = (String) getAttribute(Constants.GENERIC_KEY); + if (StringUtils.isNotEmpty(generic)) { + context.setAttachment(Constants.GENERIC_KEY, generic); + } + try { + return super.invoke(targetObject); + } finally { + context.setAttachments(null); + + } + } +} diff --git a/dubbo-rpc/dubbo-rpc-http/src/test/java/com/alibaba/dubbo/rpc/protocol/http/HttpProtocolTest.java b/dubbo-rpc/dubbo-rpc-http/src/test/java/com/alibaba/dubbo/rpc/protocol/http/HttpProtocolTest.java new file mode 100644 index 00000000000..014eed6558a --- /dev/null +++ b/dubbo-rpc/dubbo-rpc-http/src/test/java/com/alibaba/dubbo/rpc/protocol/http/HttpProtocolTest.java @@ -0,0 +1,198 @@ +/* + * 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 com.alibaba.dubbo.rpc.protocol.http; + +import com.alibaba.dubbo.common.URL; +import com.alibaba.dubbo.common.beanutil.JavaBeanDescriptor; +import com.alibaba.dubbo.common.beanutil.JavaBeanSerializeUtil; +import com.alibaba.dubbo.common.extension.ExtensionLoader; +import com.alibaba.dubbo.common.serialize.ObjectInput; +import com.alibaba.dubbo.common.serialize.ObjectOutput; +import com.alibaba.dubbo.common.serialize.Serialization; +import com.alibaba.dubbo.common.serialize.nativejava.NativeJavaSerialization; +import com.alibaba.dubbo.rpc.*; +import com.alibaba.dubbo.rpc.service.GenericService; +import junit.framework.Assert; +import org.junit.Test; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; + +import static org.junit.Assert.fail; + +/** + * HttpProtocolTest + */ +public class HttpProtocolTest { + + @Test + public void testHttpProtocol() { + HttpServiceImpl server = new HttpServiceImpl(); + Assert.assertFalse(server.isCalled()); + ProxyFactory proxyFactory = ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension(); + Protocol protocol = ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension(); + URL url = URL.valueOf("http://127.0.0.1:5342/" + HttpService.class.getName() + "?version=1.0.0"); + Exporter exporter = protocol.export(proxyFactory.getInvoker(server, HttpService.class, url)); + Invoker invoker = protocol.refer(HttpService.class, url); + HttpService client = proxyFactory.getProxy(invoker); + String result = client.sayHello("haha"); + Assert.assertTrue(server.isCalled()); + Assert.assertEquals("Hello, haha", result); + invoker.destroy(); + exporter.unexport(); + } + + @Test + public void testGenericInvoke() { + HttpServiceImpl server = new HttpServiceImpl(); + Assert.assertFalse(server.isCalled()); + ProxyFactory proxyFactory = ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension(); + Protocol protocol = ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension(); + URL url = URL.valueOf("http://127.0.0.1:5342/" + HttpService.class.getName() + "?version=1.0.0"); + Exporter exporter = protocol.export(proxyFactory.getInvoker(server, HttpService.class, url)); + Invoker invoker = protocol.refer(GenericService.class, url); + GenericService client = proxyFactory.getProxy(invoker, true); + String result = (String) client.$invoke("sayHello", new String[]{"java.lang.String"}, new Object[]{"haha"}); + Assert.assertTrue(server.isCalled()); + Assert.assertEquals("Hello, haha", result); + invoker.destroy(); + exporter.unexport(); + } + + @Test + public void testGenericInvokeWithNativeJava() throws IOException, ClassNotFoundException { + HttpServiceImpl server = new HttpServiceImpl(); + Assert.assertFalse(server.isCalled()); + ProxyFactory proxyFactory = ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension(); + Protocol protocol = ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension(); + URL url = URL.valueOf("http://127.0.0.1:5342/" + HttpService.class.getName() + "?version=1.0.0&generic=nativejava"); + Exporter exporter = protocol.export(proxyFactory.getInvoker(server, HttpService.class, url)); + Invoker invoker = protocol.refer(GenericService.class, url); + GenericService client = proxyFactory.getProxy(invoker); + + Serialization serialization = new NativeJavaSerialization(); + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + + ObjectOutput objectOutput = serialization.serialize(url, byteArrayOutputStream); + objectOutput.writeObject("haha"); + objectOutput.flushBuffer(); + + Object result = client.$invoke("sayHello", new String[]{"java.lang.String"}, new Object[]{byteArrayOutputStream.toByteArray()}); + ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream((byte[]) result); + ObjectInput objectInput = serialization.deserialize(url, byteArrayInputStream); + Assert.assertTrue(server.isCalled()); + Assert.assertEquals("Hello, haha", objectInput.readObject()); + invoker.destroy(); + exporter.unexport(); + } + + @Test + public void testGenericInvokeWithBean() { + HttpServiceImpl server = new HttpServiceImpl(); + Assert.assertFalse(server.isCalled()); + ProxyFactory proxyFactory = ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension(); + Protocol protocol = ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension(); + URL url = URL.valueOf("http://127.0.0.1:5342/" + HttpService.class.getName() + "?version=1.0.0&generic=bean"); + Exporter exporter = protocol.export(proxyFactory.getInvoker(server, HttpService.class, url)); + Invoker invoker = protocol.refer(GenericService.class, url); + GenericService client = proxyFactory.getProxy(invoker); + + JavaBeanDescriptor javaBeanDescriptor = JavaBeanSerializeUtil.serialize("haha"); + + Object result = client.$invoke("sayHello", new String[]{"java.lang.String"}, new Object[]{javaBeanDescriptor}); + Assert.assertTrue(server.isCalled()); + Assert.assertEquals("Hello, haha", JavaBeanSerializeUtil.deserialize((JavaBeanDescriptor) result)); + invoker.destroy(); + exporter.unexport(); + } + + @Test + public void testOverload() { + HttpServiceImpl server = new HttpServiceImpl(); + Assert.assertFalse(server.isCalled()); + ProxyFactory proxyFactory = ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension(); + Protocol protocol = ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension(); + URL url = URL.valueOf("http://127.0.0.1:5342/" + HttpService.class.getName() + "?version=1.0.0&hessian.overload.method=true&hessian2.request=false"); + Exporter exporter = protocol.export(proxyFactory.getInvoker(server, HttpService.class, url)); + Invoker invoker = protocol.refer(HttpService.class, url); + HttpService client = proxyFactory.getProxy(invoker); + String result = client.sayHello("haha"); + Assert.assertEquals("Hello, haha", result); + result = client.sayHello("haha", 1); + Assert.assertEquals("Hello, haha. ", result); + invoker.destroy(); + exporter.unexport(); + } + + @Test + public void testSimpleClient() { + HttpServiceImpl server = new HttpServiceImpl(); + Assert.assertFalse(server.isCalled()); + ProxyFactory proxyFactory = ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension(); + Protocol protocol = ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension(); + URL url = URL.valueOf("http://127.0.0.1:5342/" + HttpService.class.getName() + "?version=1.0.0&client=simple"); + Exporter exporter = protocol.export(proxyFactory.getInvoker(server, HttpService.class, url)); + Invoker invoker = protocol.refer(HttpService.class, url); + HttpService client = proxyFactory.getProxy(invoker); + String result = client.sayHello("haha"); + Assert.assertTrue(server.isCalled()); + Assert.assertEquals("Hello, haha", result); + invoker.destroy(); + exporter.unexport(); + } + + @Test + public void testTimeOut() { + HttpServiceImpl server = new HttpServiceImpl(); + ProxyFactory proxyFactory = ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension(); + Protocol protocol = ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension(); + URL url = URL.valueOf("http://127.0.0.1:5342/" + HttpService.class.getName() + "?version=1.0.0&timeout=10"); + Exporter exporter = protocol.export(proxyFactory.getInvoker(server, HttpService.class, url)); + Invoker invoker = protocol.refer(HttpService.class, url); + HttpService client = proxyFactory.getProxy(invoker); + try { + client.timeOut(6000); + fail(); + } catch (RpcException expected) { + Assert.assertEquals(true, expected.isTimeout()); + } finally { + invoker.destroy(); + exporter.unexport(); + } + + } + + @Test + public void testCustomException() { + HttpServiceImpl server = new HttpServiceImpl(); + ProxyFactory proxyFactory = ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension(); + Protocol protocol = ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension(); + URL url = URL.valueOf("http://127.0.0.1:5342/" + HttpService.class.getName() + "?version=1.0.0"); + Exporter exporter = protocol.export(proxyFactory.getInvoker(server, HttpService.class, url)); + Invoker invoker = protocol.refer(HttpService.class, url); + HttpService client = proxyFactory.getProxy(invoker); + try { + client.customException(); + fail(); + } catch (HttpServiceImpl.MyException expected) { + } + invoker.destroy(); + exporter.unexport(); + } + +} diff --git a/dubbo-rpc/dubbo-rpc-http/src/test/java/com/alibaba/dubbo/rpc/protocol/http/HttpService.java b/dubbo-rpc/dubbo-rpc-http/src/test/java/com/alibaba/dubbo/rpc/protocol/http/HttpService.java new file mode 100644 index 00000000000..0d0d22c1e76 --- /dev/null +++ b/dubbo-rpc/dubbo-rpc-http/src/test/java/com/alibaba/dubbo/rpc/protocol/http/HttpService.java @@ -0,0 +1,33 @@ +/* + * 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 com.alibaba.dubbo.rpc.protocol.http; + + +/** + * HttpService + */ +public interface HttpService { + + String sayHello(String name); + + String sayHello(String name, int times); + + void timeOut(int millis); + + String customException(); + +} diff --git a/dubbo-rpc/dubbo-rpc-http/src/test/java/com/alibaba/dubbo/rpc/protocol/http/HttpServiceImpl.java b/dubbo-rpc/dubbo-rpc-http/src/test/java/com/alibaba/dubbo/rpc/protocol/http/HttpServiceImpl.java new file mode 100644 index 00000000000..1c78b3ba692 --- /dev/null +++ b/dubbo-rpc/dubbo-rpc-http/src/test/java/com/alibaba/dubbo/rpc/protocol/http/HttpServiceImpl.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 com.alibaba.dubbo.rpc.protocol.http; + +/** + * HttpServiceImpl + */ +public class HttpServiceImpl implements HttpService { + + private boolean called; + + public String sayHello(String name) { + called = true; + return "Hello, " + name; + } + + public String sayHello(String name, int times) { + called = true; + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < times; i++) { + sb.append("Hello, " + name + ". "); + } + return sb.toString(); + } + + public boolean isCalled() { + return called; + } + + public void timeOut(int millis) { + try { + Thread.sleep(millis); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + + public String customException() { + throw new MyException("custom exception"); + } + + static class MyException extends RuntimeException { + + private static final long serialVersionUID = -3051041116483629056L; + + public MyException(String message) { + super(message); + } + } +} diff --git a/dubbo-rpc/dubbo-rpc-rest/pom.xml b/dubbo-rpc/dubbo-rpc-rest/pom.xml index 026e2c293a9..724ae6dac99 100644 --- a/dubbo-rpc/dubbo-rpc-rest/pom.xml +++ b/dubbo-rpc/dubbo-rpc-rest/pom.xml @@ -105,5 +105,11 @@ netty-all + + com.alibaba + dubbo-serialization-jdk + ${project.parent.version} + test + \ No newline at end of file diff --git a/dubbo-rpc/dubbo-rpc-rest/src/test/java/com/alibaba/dubbo/rpc/protol/rest/RestProtocolTest.java b/dubbo-rpc/dubbo-rpc-rest/src/test/java/com/alibaba/dubbo/rpc/protol/rest/RestProtocolTest.java new file mode 100644 index 00000000000..4764cf6b66f --- /dev/null +++ b/dubbo-rpc/dubbo-rpc-rest/src/test/java/com/alibaba/dubbo/rpc/protol/rest/RestProtocolTest.java @@ -0,0 +1,48 @@ +/* + * 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 com.alibaba.dubbo.rpc.protol.rest; + +import com.alibaba.dubbo.common.URL; +import com.alibaba.dubbo.common.extension.ExtensionLoader; +import com.alibaba.dubbo.rpc.*; +import junit.framework.Assert; +import org.junit.Test; + +/** + * RestProtocolTest + */ +public class RestProtocolTest { + + private Protocol protocol = ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension(); + private ProxyFactory proxyFactory = ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension(); + + @Test + public void testRestProtocol() { + ServiceClassHolder.getInstance().pushServiceClass(RestServiceImpl.class); + RestServiceImpl server = new RestServiceImpl(); + Assert.assertFalse(server.isCalled()); + URL url = URL.valueOf("rest://127.0.0.1:5342/rest/say1?version=1.0.0"); + Exporter exporter = protocol.export(proxyFactory.getInvoker(server, RestService.class, url)); + Invoker invoker = protocol.refer(RestService.class, url); + RestService client = proxyFactory.getProxy(invoker); + String result = client.sayHello("haha"); + Assert.assertTrue(server.isCalled()); + Assert.assertEquals("Hello, haha", result); + invoker.destroy(); + exporter.unexport(); + } +} diff --git a/dubbo-rpc/dubbo-rpc-rest/src/test/java/com/alibaba/dubbo/rpc/protol/rest/RestService.java b/dubbo-rpc/dubbo-rpc-rest/src/test/java/com/alibaba/dubbo/rpc/protol/rest/RestService.java new file mode 100644 index 00000000000..30441b2a87d --- /dev/null +++ b/dubbo-rpc/dubbo-rpc-rest/src/test/java/com/alibaba/dubbo/rpc/protol/rest/RestService.java @@ -0,0 +1,36 @@ +/* + * 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 com.alibaba.dubbo.rpc.protol.rest; + + +import javax.ws.rs.Consumes; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.core.MediaType; + +/** + * RestService + */ +@Path("/rest") +public interface RestService { + + @POST + @Path("/say1") + @Consumes({MediaType.TEXT_PLAIN}) + String sayHello(String name); + +} diff --git a/dubbo-rpc/dubbo-rpc-rest/src/test/java/com/alibaba/dubbo/rpc/protol/rest/RestServiceImpl.java b/dubbo-rpc/dubbo-rpc-rest/src/test/java/com/alibaba/dubbo/rpc/protol/rest/RestServiceImpl.java new file mode 100644 index 00000000000..3de80d266ca --- /dev/null +++ b/dubbo-rpc/dubbo-rpc-rest/src/test/java/com/alibaba/dubbo/rpc/protol/rest/RestServiceImpl.java @@ -0,0 +1,36 @@ +/* + * 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 com.alibaba.dubbo.rpc.protol.rest; + +/** + * RestServiceImpl + */ + +public class RestServiceImpl implements RestService { + + private boolean called; + + public String sayHello(String name) { + called = true; + return "Hello, " + name; + } + + + public boolean isCalled() { + return called; + } +}