This is an automated email from the ASF dual-hosted git repository. liujun pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/incubator-dubbo.git
The following commit(s) were added to refs/heads/master by this push: new 286fb12 Merge pull request #1827, support generic invoke and attachment for http/hessian protocol. 286fb12 is described below commit 286fb12b011fd878b3d44ff6985e082e2141a164 Author: Jerrick Zhu <diecui1...@gmail.com> AuthorDate: Fri Jun 1 15:02:53 2018 +0800 Merge pull request #1827, support generic invoke and attachment for http/hessian protocol. fixes #1768, #19 --- .../dubbo/config/mock/MockProxyFactory.java | 5 + .../java/com/alibaba/dubbo/rpc/ProxyFactory.java | 9 + .../alibaba/dubbo/rpc/filter/GenericFilter.java | 9 +- .../dubbo/rpc/filter/GenericImplFilter.java | 8 +- .../dubbo/rpc/protocol/AbstractProxyProtocol.java | 6 +- .../dubbo/rpc/proxy/AbstractProxyFactory.java | 15 ++ .../rpc/proxy/wrapper/StubProxyFactoryWrapper.java | 5 + dubbo-rpc/dubbo-rpc-hessian/pom.xml | 6 + ....java => DubboHessianURLConnectionFactory.java} | 87 +++++---- .../rpc/protocol/hessian/HessianProtocol.java | 32 +++- .../hessian/HttpClientConnectionFactory.java | 9 +- .../rpc/protocol/hessian/HessianProtocolTest.java | 93 ++++++++++ .../dubbo/rpc/protocol/hessian/HessianService.java | 2 + .../rpc/protocol/hessian/HessianServiceImpl.java | 6 + dubbo-rpc/dubbo-rpc-http/pom.xml | 6 + .../dubbo/rpc/protocol/http/HttpProtocol.java | 55 ++++-- .../rpc/protocol/http/HttpRemoteInvocation.java | 57 ++++++ .../dubbo/rpc/protocol/http/HttpProtocolTest.java | 198 +++++++++++++++++++++ .../dubbo/rpc/protocol/http/HttpService.java} | 8 +- .../dubbo/rpc/protocol/http/HttpServiceImpl.java} | 8 +- dubbo-rpc/dubbo-rpc-rest/pom.xml | 6 + .../dubbo/rpc/protol/rest/RestProtocolTest.java | 48 +++++ .../dubbo/rpc/protol/rest/RestService.java} | 21 ++- .../dubbo/rpc/protol/rest/RestServiceImpl.java} | 19 +- 24 files changed, 625 insertions(+), 93 deletions(-) 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 3de2e3a..cd78366 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 @@ -28,6 +28,11 @@ public class MockProxyFactory implements ProxyFactory { } @Override + public <T> T getProxy(Invoker<T> invoker, boolean generic) throws RpcException { + return null; + } + + @Override public <T> Invoker<T> getInvoker(T proxy, Class<T> type, URL url) throws RpcException { return null; } 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 6ba7057..fb03d6b 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 @@ -37,6 +37,15 @@ public interface ProxyFactory { <T> T getProxy(Invoker<T> invoker) throws RpcException; /** + * create proxy. + * + * @param invoker + * @return proxy + */ + @Adaptive({Constants.PROXY_KEY}) + <T> T getProxy(Invoker<T> invoker, boolean generic) throws RpcException; + + /** * create invoker. * * @param <T> 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 d393822..8404a99 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.Filter; 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 class GenericFilter implements Filter { 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 class GenericFilter implements Filter { 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 99bced5..6be08fe 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 class GenericImplFilter implements Filter { 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 class GenericImplFilter implements Filter { 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 8136cc0..561520c 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 abstract class AbstractProxyProtocol extends AbstractProtocol { 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<T>(invoker) { @Override public void unexport() { @@ -89,12 +89,12 @@ public abstract class AbstractProxyProtocol extends AbstractProtocol { @Override public <T> Invoker<T> refer(final Class<T> type, final URL url) throws RpcException { - final Invoker<T> tagert = proxyFactory.getInvoker(doRefer(type, url), type, url); + final Invoker<T> target = proxyFactory.getInvoker(doRefer(type, url), type, url); Invoker<T> invoker = new AbstractInvoker<T>(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 21c350d..d27f608 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.Invoker; 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> T getProxy(Invoker<T> invoker) throws RpcException { + return getProxy(invoker, false); + } + + @Override + public <T> T getProxy(Invoker<T> 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 abstract class AbstractProxyFactory implements ProxyFactory { 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 ec3db16..3f3ed3f 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 @@ -55,6 +55,11 @@ public class StubProxyFactoryWrapper implements ProxyFactory { } @Override + public <T> T getProxy(Invoker<T> invoker, boolean generic) throws RpcException { + return proxyFactory.getProxy(invoker, generic); + } + + @Override @SuppressWarnings({"unchecked", "rawtypes"}) public <T> T getProxy(Invoker<T> invoker) throws RpcException { T proxy = proxyFactory.getProxy(invoker); diff --git a/dubbo-rpc/dubbo-rpc-hessian/pom.xml b/dubbo-rpc/dubbo-rpc-hessian/pom.xml index 00ca28c..98ad82d 100644 --- a/dubbo-rpc/dubbo-rpc-hessian/pom.xml +++ b/dubbo-rpc/dubbo-rpc-hessian/pom.xml @@ -48,5 +48,11 @@ <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> </dependency> + <dependency> + <groupId>com.alibaba</groupId> + <artifactId>dubbo-serialization-jdk</artifactId> + <version>${project.parent.version}</version> + <scope>test</scope> + </dependency> </dependencies> </project> \ No newline at end of file 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/DubboHessianURLConnectionFactory.java similarity index 55% copy from dubbo-rpc/dubbo-rpc-hessian/src/main/java/com/alibaba/dubbo/rpc/protocol/hessian/HttpClientConnectionFactory.java copy to dubbo-rpc/dubbo-rpc-hessian/src/main/java/com/alibaba/dubbo/rpc/protocol/hessian/DubboHessianURLConnectionFactory.java index 033277d..8fe2f14 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/DubboHessianURLConnectionFactory.java @@ -1,47 +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.caucho.hessian.client.HessianConnection; -import com.caucho.hessian.client.HessianConnectionFactory; -import com.caucho.hessian.client.HessianProxyFactory; -import org.apache.http.client.HttpClient; -import org.apache.http.impl.client.DefaultHttpClient; -import org.apache.http.params.HttpConnectionParams; - -import java.io.IOException; -import java.net.URL; - -/** - * HttpClientConnectionFactory - */ -public class HttpClientConnectionFactory implements HessianConnectionFactory { - - private final HttpClient httpClient = new DefaultHttpClient(); - - @Override - public void setHessianProxyFactory(HessianProxyFactory factory) { - HttpConnectionParams.setConnectionTimeout(httpClient.getParams(), (int) factory.getConnectTimeout()); - HttpConnectionParams.setSoTimeout(httpClient.getParams(), (int) factory.getReadTimeout()); - } - - @Override - public HessianConnection open(URL url) throws IOException { - return new HttpClientConnection(httpClient, url); - } - -} +/* + * 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 f1eae5c..9733307 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.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 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 javax.servlet.http.HttpServletResponse; 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 @@ public class HessianProtocol extends AbstractProxyProtocol { 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 class HessianProtocol extends AbstractProxyProtocol { @Override @SuppressWarnings("unchecked") protected <T> T doRefer(Class<T> 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 @@ public class HessianProtocol extends AbstractProxyProtocol { 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 class HessianProtocol extends AbstractProxyProtocol { response.setStatus(500); } else { RpcContext.getContext().setRemoteAddress(request.getRemoteAddr(), request.getRemotePort()); + + Enumeration<String> 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 033277d..b19cd27 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 class HttpClientConnectionFactory implements HessianConnectionFactory { @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 877ecd3..bae0333 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; /** @@ -53,6 +65,87 @@ public class HessianProtocolTest { } @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<HessianService> exporter = protocol.export(proxyFactory.getInvoker(server, HessianService.class, url)); + Invoker<GenericService> 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<HessianService> exporter = protocol.export(proxyFactory.getInvoker(server, HessianService.class, url)); + Invoker<GenericService> 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<HessianService> exporter = protocol.export(proxyFactory.getInvoker(server, HessianService.class, url)); + Invoker<GenericService> 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<HessianService> exporter = protocol.export(proxyFactory.getInvoker(server, HessianService.class, url)); + Invoker<GenericService> 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() { HessianServiceImpl server = new HessianServiceImpl(); Assert.assertFalse(server.isCalled()); 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 8629425..9df4524 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 855de0a..68d14b3 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 class HessianServiceImpl implements HessianService { 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 427b70b..93d8a0f 100644 --- a/dubbo-rpc/dubbo-rpc-http/pom.xml +++ b/dubbo-rpc/dubbo-rpc-http/pom.xml @@ -48,5 +48,11 @@ <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> </dependency> + <dependency> + <groupId>com.alibaba</groupId> + <artifactId>dubbo-serialization-jdk</artifactId> + <version>${project.parent.version}</version> + <scope>test</scope> + </dependency> </dependencies> </project> \ 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 27a5913..3fc9087 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.remoting.http.HttpServer; 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 @@ public class HttpProtocol extends AbstractProxyProtocol { 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 <T> HttpInvokerServiceExporter createExporter(T impl, Class<?> type) { final HttpInvokerServiceExporter httpServiceExporter = new HttpInvokerServiceExporter(); httpServiceExporter.setServiceInterface(type); httpServiceExporter.setService(impl); @@ -82,21 +102,33 @@ public class HttpProtocol extends AbstractProxyProtocol { } 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> T doRefer(final Class<T> 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 @@ public class HttpProtocol extends AbstractProxyProtocol { 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 0000000..5054c4f --- /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<String, String>(RpcContext.getContext().getAttachments())); + } + + @Override + public Object invoke(Object targetObject) throws NoSuchMethodException, IllegalAccessException, + InvocationTargetException { + RpcContext context = RpcContext.getContext(); + context.setAttachments((Map<String, String>) 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 0000000..014eed6 --- /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<HttpService> exporter = protocol.export(proxyFactory.getInvoker(server, HttpService.class, url)); + Invoker<HttpService> 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<HttpService> exporter = protocol.export(proxyFactory.getInvoker(server, HttpService.class, url)); + Invoker<GenericService> 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<HttpService> exporter = protocol.export(proxyFactory.getInvoker(server, HttpService.class, url)); + Invoker<GenericService> 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<HttpService> exporter = protocol.export(proxyFactory.getInvoker(server, HttpService.class, url)); + Invoker<GenericService> 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<HttpService> exporter = protocol.export(proxyFactory.getInvoker(server, HttpService.class, url)); + Invoker<HttpService> 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<HttpService> exporter = protocol.export(proxyFactory.getInvoker(server, HttpService.class, url)); + Invoker<HttpService> 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<HttpService> exporter = protocol.export(proxyFactory.getInvoker(server, HttpService.class, url)); + Invoker<HttpService> 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<HttpService> exporter = protocol.export(proxyFactory.getInvoker(server, HttpService.class, url)); + Invoker<HttpService> 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-hessian/src/test/java/com/alibaba/dubbo/rpc/protocol/hessian/HessianService.java b/dubbo-rpc/dubbo-rpc-http/src/test/java/com/alibaba/dubbo/rpc/protocol/http/HttpService.java similarity index 87% copy from dubbo-rpc/dubbo-rpc-hessian/src/test/java/com/alibaba/dubbo/rpc/protocol/hessian/HessianService.java copy to dubbo-rpc/dubbo-rpc-http/src/test/java/com/alibaba/dubbo/rpc/protocol/http/HttpService.java index 8629425..0d0d22c 100644 --- a/dubbo-rpc/dubbo-rpc-hessian/src/test/java/com/alibaba/dubbo/rpc/protocol/hessian/HessianService.java +++ b/dubbo-rpc/dubbo-rpc-http/src/test/java/com/alibaba/dubbo/rpc/protocol/http/HttpService.java @@ -14,16 +14,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.alibaba.dubbo.rpc.protocol.hessian; +package com.alibaba.dubbo.rpc.protocol.http; /** - * HessianService + * HttpService */ -public interface HessianService { +public interface HttpService { String sayHello(String name); - + String sayHello(String name, int times); void timeOut(int millis); diff --git a/dubbo-rpc/dubbo-rpc-hessian/src/test/java/com/alibaba/dubbo/rpc/protocol/hessian/HessianServiceImpl.java b/dubbo-rpc/dubbo-rpc-http/src/test/java/com/alibaba/dubbo/rpc/protocol/http/HttpServiceImpl.java similarity index 90% copy from dubbo-rpc/dubbo-rpc-hessian/src/test/java/com/alibaba/dubbo/rpc/protocol/hessian/HessianServiceImpl.java copy to dubbo-rpc/dubbo-rpc-http/src/test/java/com/alibaba/dubbo/rpc/protocol/http/HttpServiceImpl.java index 855de0a..1c78b3b 100644 --- a/dubbo-rpc/dubbo-rpc-hessian/src/test/java/com/alibaba/dubbo/rpc/protocol/hessian/HessianServiceImpl.java +++ b/dubbo-rpc/dubbo-rpc-http/src/test/java/com/alibaba/dubbo/rpc/protocol/http/HttpServiceImpl.java @@ -14,12 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.alibaba.dubbo.rpc.protocol.hessian; +package com.alibaba.dubbo.rpc.protocol.http; /** - * HessianServiceImpl + * HttpServiceImpl */ -public class HessianServiceImpl implements HessianService { +public class HttpServiceImpl implements HttpService { private boolean called; @@ -27,7 +27,7 @@ public class HessianServiceImpl implements HessianService { called = true; return "Hello, " + name; } - + public String sayHello(String name, int times) { called = true; StringBuilder sb = new StringBuilder(); diff --git a/dubbo-rpc/dubbo-rpc-rest/pom.xml b/dubbo-rpc/dubbo-rpc-rest/pom.xml index 026e2c2..724ae6d 100644 --- a/dubbo-rpc/dubbo-rpc-rest/pom.xml +++ b/dubbo-rpc/dubbo-rpc-rest/pom.xml @@ -105,5 +105,11 @@ <artifactId>netty-all</artifactId> </dependency> + <dependency> + <groupId>com.alibaba</groupId> + <artifactId>dubbo-serialization-jdk</artifactId> + <version>${project.parent.version}</version> + <scope>test</scope> + </dependency> </dependencies> </project> \ 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 0000000..4764cf6 --- /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<RestService> exporter = protocol.export(proxyFactory.getInvoker(server, RestService.class, url)); + Invoker<RestService> 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-hessian/src/test/java/com/alibaba/dubbo/rpc/protocol/hessian/HessianService.java b/dubbo-rpc/dubbo-rpc-rest/src/test/java/com/alibaba/dubbo/rpc/protol/rest/RestService.java similarity index 72% copy from dubbo-rpc/dubbo-rpc-hessian/src/test/java/com/alibaba/dubbo/rpc/protocol/hessian/HessianService.java copy to dubbo-rpc/dubbo-rpc-rest/src/test/java/com/alibaba/dubbo/rpc/protol/rest/RestService.java index 8629425..30441b2 100644 --- a/dubbo-rpc/dubbo-rpc-hessian/src/test/java/com/alibaba/dubbo/rpc/protocol/hessian/HessianService.java +++ b/dubbo-rpc/dubbo-rpc-rest/src/test/java/com/alibaba/dubbo/rpc/protol/rest/RestService.java @@ -14,20 +14,23 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.alibaba.dubbo.rpc.protocol.hessian; +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; + /** - * HessianService + * RestService */ -public interface HessianService { +@Path("/rest") +public interface RestService { + @POST + @Path("/say1") + @Consumes({MediaType.TEXT_PLAIN}) String sayHello(String name); - String sayHello(String name, int times); - - void timeOut(int millis); - - String customException(); - } diff --git a/dubbo-rpc/dubbo-rpc-hessian/src/test/java/com/alibaba/dubbo/rpc/protocol/hessian/HessianService.java b/dubbo-rpc/dubbo-rpc-rest/src/test/java/com/alibaba/dubbo/rpc/protol/rest/RestServiceImpl.java similarity index 70% copy from dubbo-rpc/dubbo-rpc-hessian/src/test/java/com/alibaba/dubbo/rpc/protocol/hessian/HessianService.java copy to dubbo-rpc/dubbo-rpc-rest/src/test/java/com/alibaba/dubbo/rpc/protol/rest/RestServiceImpl.java index 8629425..3de80d2 100644 --- a/dubbo-rpc/dubbo-rpc-hessian/src/test/java/com/alibaba/dubbo/rpc/protocol/hessian/HessianService.java +++ b/dubbo-rpc/dubbo-rpc-rest/src/test/java/com/alibaba/dubbo/rpc/protol/rest/RestServiceImpl.java @@ -14,20 +14,23 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.alibaba.dubbo.rpc.protocol.hessian; - +package com.alibaba.dubbo.rpc.protol.rest; /** - * HessianService + * RestServiceImpl */ -public interface HessianService { - String sayHello(String name); +public class RestServiceImpl implements RestService { - String sayHello(String name, int times); + private boolean called; - void timeOut(int millis); + public String sayHello(String name) { + called = true; + return "Hello, " + name; + } - String customException(); + public boolean isCalled() { + return called; + } } -- To stop receiving notification emails like this one, please contact liu...@apache.org.