You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@dubbo.apache.org by li...@apache.org on 2018/06/01 07:02:56 UTC

[incubator-dubbo] branch master updated: Merge pull request #1827, support generic invoke and attachment for http/hessian protocol.

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 <di...@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
liujun@apache.org.