diff --git a/dubbo-all/pom.xml b/dubbo-all/pom.xml index cf2609725c..6e464f4b25 100644 --- a/dubbo-all/pom.xml +++ b/dubbo-all/pom.xml @@ -144,7 +144,7 @@ org.apache.dubbo - dubbo-rpc-jsonrpc + dubbo-rpc-http ${project.version} compile true @@ -165,7 +165,7 @@ org.apache.dubbo - dubbo-rpc-http + dubbo-rpc-http-invoker ${project.version} compile true @@ -581,10 +581,10 @@ org.apache.dubbo:dubbo-rpc-api org.apache.dubbo:dubbo-rpc-dubbo org.apache.dubbo:dubbo-rpc-injvm - org.apache.dubbo:dubbo-rpc-jsonrpc + org.apache.dubbo:dubbo-rpc-http org.apache.dubbo:dubbo-rpc-rmi org.apache.dubbo:dubbo-rpc-hessian - org.apache.dubbo:dubbo-rpc-http + org.apache.dubbo:dubbo-rpc-http-invoker org.apache.dubbo:dubbo-rpc-webservice org.apache.dubbo:dubbo-rpc-thrift org.apache.dubbo:dubbo-rpc-memcached diff --git a/dubbo-bom/pom.xml b/dubbo-bom/pom.xml index 5ab6604905..13cac0051a 100644 --- a/dubbo-bom/pom.xml +++ b/dubbo-bom/pom.xml @@ -174,7 +174,7 @@ org.apache.dubbo - dubbo-rpc-jsonrpc + dubbo-rpc-http ${project.version} @@ -189,7 +189,7 @@ org.apache.dubbo - dubbo-rpc-http + dubbo-rpc-http-invoker ${project.version} diff --git a/dubbo-rpc/dubbo-rpc-jsonrpc/pom.xml b/dubbo-rpc/dubbo-rpc-http-invoker/pom.xml similarity index 71% rename from dubbo-rpc/dubbo-rpc-jsonrpc/pom.xml rename to dubbo-rpc/dubbo-rpc-http-invoker/pom.xml index c5b4e89038..f467cc88bb 100644 --- a/dubbo-rpc/dubbo-rpc-jsonrpc/pom.xml +++ b/dubbo-rpc/dubbo-rpc-http-invoker/pom.xml @@ -14,24 +14,20 @@ See the License for the specific language governing permissions and limitations under the License. --> - + + 4.0.0 - dubbo-rpc org.apache.dubbo + dubbo-rpc ${revision} - 4.0.0 - - dubbo-rpc-jsonrpc - - The JSON-RPC module of dubbo project - + dubbo-rpc-http-invoker + jar + ${project.artifactId} + The http rpc module of dubbo project false - org.apache.dubbo @@ -48,14 +44,14 @@ spring-context - com.github.briandilley.jsonrpc4j - jsonrpc4j + org.springframework + spring-web - javax.portlet - portlet-api + org.apache.dubbo + dubbo-serialization-jdk + ${project.parent.version} + test - - \ No newline at end of file diff --git a/dubbo-rpc/dubbo-rpc-http/src/main/java/com/alibaba/dubbo/rpc/protocol/http/HttpRemoteInvocation.java b/dubbo-rpc/dubbo-rpc-http-invoker/src/main/java/com/alibaba/dubbo/rpc/protocol/http/HttpRemoteInvocation.java similarity index 96% rename from dubbo-rpc/dubbo-rpc-http/src/main/java/com/alibaba/dubbo/rpc/protocol/http/HttpRemoteInvocation.java rename to dubbo-rpc/dubbo-rpc-http-invoker/src/main/java/com/alibaba/dubbo/rpc/protocol/http/HttpRemoteInvocation.java index 3e923b67a0..2c7415533a 100644 --- a/dubbo-rpc/dubbo-rpc-http/src/main/java/com/alibaba/dubbo/rpc/protocol/http/HttpRemoteInvocation.java +++ b/dubbo-rpc/dubbo-rpc-http-invoker/src/main/java/com/alibaba/dubbo/rpc/protocol/http/HttpRemoteInvocation.java @@ -19,7 +19,7 @@ package com.alibaba.dubbo.rpc.protocol.http; import org.aopalliance.intercept.MethodInvocation; @Deprecated -public class HttpRemoteInvocation extends org.apache.dubbo.rpc.protocol.http.HttpRemoteInvocation { +public class HttpRemoteInvocation extends org.apache.dubbo.rpc.protocol.httpinvoker.HttpRemoteInvocation { private static final long serialVersionUID = 1L; public HttpRemoteInvocation(MethodInvocation methodInvocation) { diff --git a/dubbo-rpc/dubbo-rpc-http-invoker/src/main/java/org/apache/dubbo/rpc/protocol/httpinvoker/HttpInvokerProtocol.java b/dubbo-rpc/dubbo-rpc-http-invoker/src/main/java/org/apache/dubbo/rpc/protocol/httpinvoker/HttpInvokerProtocol.java new file mode 100644 index 0000000000..31f2be1f9e --- /dev/null +++ b/dubbo-rpc/dubbo-rpc-http-invoker/src/main/java/org/apache/dubbo/rpc/protocol/httpinvoker/HttpInvokerProtocol.java @@ -0,0 +1,225 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.dubbo.rpc.protocol.httpinvoker; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.utils.StringUtils; +import org.apache.dubbo.common.Version; +import org.apache.dubbo.remoting.Constants; +import org.apache.dubbo.remoting.http.HttpBinder; +import org.apache.dubbo.remoting.http.HttpHandler; +import org.apache.dubbo.remoting.http.HttpServer; +import org.apache.dubbo.rpc.RpcContext; +import org.apache.dubbo.rpc.RpcException; +import org.apache.dubbo.rpc.protocol.AbstractProxyProtocol; +import org.apache.dubbo.rpc.service.GenericService; +import org.apache.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; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.net.HttpURLConnection; +import java.net.SocketTimeoutException; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_TIMEOUT; +import static org.apache.dubbo.common.constants.CommonConstants.RELEASE_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.TIMEOUT_KEY; +import static org.apache.dubbo.remoting.Constants.DUBBO_VERSION_KEY; +import static org.apache.dubbo.rpc.Constants.GENERIC_KEY; + +/** + * HttpInvokerProtocol + */ +public class HttpInvokerProtocol extends AbstractProxyProtocol { + + public static final int DEFAULT_PORT = 80; + + private final Map serverMap = new ConcurrentHashMap(); + + private final Map skeletonMap = new ConcurrentHashMap(); + + private HttpBinder httpBinder; + + public HttpInvokerProtocol() { + super(RemoteAccessException.class); + } + + public void setHttpBinder(HttpBinder httpBinder) { + this.httpBinder = httpBinder; + } + + @Override + public int getDefaultPort() { + return DEFAULT_PORT; + } + + @Override + protected Runnable doExport(final T impl, Class type, URL url) throws RpcException { + String addr = getAddr(url); + HttpServer server = serverMap.get(addr); + if (server == null) { + 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 + "/" + GENERIC_KEY; + + skeletonMap.put(genericPath, createExporter(impl, GenericService.class)); + return new Runnable() { + @Override + public void run() { + skeletonMap.remove(path); + skeletonMap.remove(genericPath); + } + }; + } + + private HttpInvokerServiceExporter createExporter(T impl, Class type) { + final HttpInvokerServiceExporter httpServiceExporter = new HttpInvokerServiceExporter(); + httpServiceExporter.setServiceInterface(type); + httpServiceExporter.setService(impl); + try { + httpServiceExporter.afterPropertiesSet(); + } catch (Exception e) { + throw new RpcException(e.getMessage(), e); + } + return httpServiceExporter; + } + + @Override + @SuppressWarnings("unchecked") + protected T doRefer(final Class serviceType, final URL url) throws RpcException { + final String generic = url.getParameter(GENERIC_KEY); + final boolean isGeneric = ProtocolUtils.isGeneric(generic) || serviceType.equals(GenericService.class); + + final HttpInvokerProxyFactoryBean httpProxyFactoryBean = new HttpInvokerProxyFactoryBean(); + httpProxyFactoryBean.setRemoteInvocationFactory(new RemoteInvocationFactory() { + @Override + public RemoteInvocation createRemoteInvocation(MethodInvocation methodInvocation) { + RemoteInvocation invocation; + /* + package was renamed to 'org.apache.dubbo' in v2.7.0, so only provider versions after v2.7.0 can + recognize org.apache.xxx.HttpRemoteInvocation'. + */ + if (Version.isRelease270OrHigher(url.getParameter(RELEASE_KEY))) { + invocation = new HttpRemoteInvocation(methodInvocation); + } else { + /* + The customized 'com.alibaba.dubbo.rpc.protocol.http.HttpRemoteInvocation' was firstly introduced + in v2.6.3. The main purpose is to support transformation of attachments in HttpInvokerProtocol, see + https://github.com/apache/dubbo/pull/1827. To guarantee interoperability with lower + versions, we need to check if the provider is v2.6.3 or higher before sending customized + HttpRemoteInvocation. + */ + if (Version.isRelease263OrHigher(url.getParameter(DUBBO_VERSION_KEY))) { + invocation = new com.alibaba.dubbo.rpc.protocol.http.HttpRemoteInvocation(methodInvocation); + } else { + invocation = new RemoteInvocation(methodInvocation); + } + } + if (isGeneric) { + invocation.addAttribute(GENERIC_KEY, generic); + } + return invocation; + } + }); + + String key = url.toIdentityString(); + if (isGeneric) { + key = key + "/" + GENERIC_KEY; + } + + httpProxyFactoryBean.setServiceUrl(key.replace("http-invoker","http")); + httpProxyFactoryBean.setServiceInterface(serviceType); + String client = url.getParameter(Constants.CLIENT_KEY); + if (StringUtils.isEmpty(client) || "simple".equals(client)) { + SimpleHttpInvokerRequestExecutor httpInvokerRequestExecutor = new SimpleHttpInvokerRequestExecutor() { + @Override + protected void prepareConnection(HttpURLConnection con, + int contentLength) throws IOException { + super.prepareConnection(con, contentLength); + con.setReadTimeout(url.getParameter(TIMEOUT_KEY, DEFAULT_TIMEOUT)); + con.setConnectTimeout(url.getParameter(Constants.CONNECT_TIMEOUT_KEY, Constants.DEFAULT_CONNECT_TIMEOUT)); + } + }; + httpProxyFactoryBean.setHttpInvokerRequestExecutor(httpInvokerRequestExecutor); + } else if ("commons".equals(client)) { + HttpComponentsHttpInvokerRequestExecutor httpInvokerRequestExecutor = new HttpComponentsHttpInvokerRequestExecutor(); + httpInvokerRequestExecutor.setReadTimeout(url.getParameter(TIMEOUT_KEY, 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"); + } + httpProxyFactoryBean.afterPropertiesSet(); + return (T) httpProxyFactoryBean.getObject(); + } + + @Override + protected int getErrorCode(Throwable e) { + if (e instanceof RemoteAccessException) { + e = e.getCause(); + } + if (e != null) { + Class cls = e.getClass(); + if (SocketTimeoutException.class.equals(cls)) { + return RpcException.TIMEOUT_EXCEPTION; + } else if (IOException.class.isAssignableFrom(cls)) { + return RpcException.NETWORK_EXCEPTION; + } else if (ClassNotFoundException.class.isAssignableFrom(cls)) { + return RpcException.SERIALIZATION_EXCEPTION; + } + } + return super.getErrorCode(e); + } + + private class InternalHandler implements HttpHandler { + + @Override + public void handle(HttpServletRequest request, HttpServletResponse response) + throws IOException, ServletException { + String uri = request.getRequestURI(); + HttpInvokerServiceExporter skeleton = skeletonMap.get(uri); + if (!"POST".equalsIgnoreCase(request.getMethod())) { + response.setStatus(500); + } else { + RpcContext.getContext().setRemoteAddress(request.getRemoteAddr(), request.getRemotePort()); + try { + skeleton.handleRequest(request, response); + } catch (Throwable e) { + throw new ServletException(e); + } + } + } + + } + +} diff --git a/dubbo-rpc/dubbo-rpc-http/src/main/java/org/apache/dubbo/rpc/protocol/http/HttpRemoteInvocation.java b/dubbo-rpc/dubbo-rpc-http-invoker/src/main/java/org/apache/dubbo/rpc/protocol/httpinvoker/HttpRemoteInvocation.java similarity index 97% rename from dubbo-rpc/dubbo-rpc-http/src/main/java/org/apache/dubbo/rpc/protocol/http/HttpRemoteInvocation.java rename to dubbo-rpc/dubbo-rpc-http-invoker/src/main/java/org/apache/dubbo/rpc/protocol/httpinvoker/HttpRemoteInvocation.java index 26561728a6..cab3f6ea27 100644 --- a/dubbo-rpc/dubbo-rpc-http/src/main/java/org/apache/dubbo/rpc/protocol/http/HttpRemoteInvocation.java +++ b/dubbo-rpc/dubbo-rpc-http-invoker/src/main/java/org/apache/dubbo/rpc/protocol/httpinvoker/HttpRemoteInvocation.java @@ -15,7 +15,7 @@ * limitations under the License. */ -package org.apache.dubbo.rpc.protocol.http; +package org.apache.dubbo.rpc.protocol.httpinvoker; import org.apache.dubbo.common.utils.StringUtils; import org.apache.dubbo.rpc.RpcContext; diff --git a/dubbo-rpc/dubbo-rpc-http-invoker/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.Protocol b/dubbo-rpc/dubbo-rpc-http-invoker/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.Protocol new file mode 100644 index 0000000000..90763763f6 --- /dev/null +++ b/dubbo-rpc/dubbo-rpc-http-invoker/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.Protocol @@ -0,0 +1 @@ +http-invoker=org.apache.dubbo.rpc.protocol.httpinvoker.HttpInvokerProtocol \ No newline at end of file diff --git a/dubbo-rpc/dubbo-rpc-http-invoker/src/test/java/org/apache/dubbo/rpc/protocol/httpinvoker/HttpInvokerProtocolTest.java b/dubbo-rpc/dubbo-rpc-http-invoker/src/test/java/org/apache/dubbo/rpc/protocol/httpinvoker/HttpInvokerProtocolTest.java new file mode 100644 index 0000000000..046c3b7694 --- /dev/null +++ b/dubbo-rpc/dubbo-rpc-http-invoker/src/test/java/org/apache/dubbo/rpc/protocol/httpinvoker/HttpInvokerProtocolTest.java @@ -0,0 +1,203 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.dubbo.rpc.protocol.httpinvoker; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.beanutil.JavaBeanDescriptor; +import org.apache.dubbo.common.beanutil.JavaBeanSerializeUtil; +import org.apache.dubbo.common.extension.ExtensionLoader; +import org.apache.dubbo.common.serialize.ObjectInput; +import org.apache.dubbo.common.serialize.ObjectOutput; +import org.apache.dubbo.common.serialize.Serialization; +import org.apache.dubbo.common.serialize.nativejava.NativeJavaSerialization; +import org.apache.dubbo.rpc.Exporter; +import org.apache.dubbo.rpc.Invoker; +import org.apache.dubbo.rpc.Protocol; +import org.apache.dubbo.rpc.ProxyFactory; +import org.apache.dubbo.rpc.RpcException; +import org.apache.dubbo.rpc.service.GenericService; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; + +import static org.junit.jupiter.api.Assertions.fail; + +/** + * HttpInvokerProtocolTest + */ +public class HttpInvokerProtocolTest { + + @Test + public void testHttpProtocol() { + HttpServiceImpl server = new HttpServiceImpl(); + Assertions.assertFalse(server.isCalled()); + ProxyFactory proxyFactory = ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension(); + Protocol protocol = ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension(); + URL url = URL.valueOf("http-invoker://127.0.0.1:5342/" + HttpService.class.getName() + "?release=2.7.0"); + Exporter exporter = protocol.export(proxyFactory.getInvoker(server, HttpService.class, url)); + Invoker invoker = protocol.refer(HttpService.class, url); + HttpService client = proxyFactory.getProxy(invoker); + String result = client.sayHello("haha"); + Assertions.assertTrue(server.isCalled()); + Assertions.assertEquals("Hello, haha", result); + invoker.destroy(); + exporter.unexport(); + } + + @Test + public void testGenericInvoke() { + HttpServiceImpl server = new HttpServiceImpl(); + Assertions.assertFalse(server.isCalled()); + ProxyFactory proxyFactory = ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension(); + Protocol protocol = ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension(); + URL url = URL.valueOf("http-invoker://127.0.0.1:5342/" + HttpService.class.getName() + "?release=2.7.0"); + Exporter exporter = protocol.export(proxyFactory.getInvoker(server, HttpService.class, url)); + Invoker invoker = protocol.refer(GenericService.class, url); + GenericService client = proxyFactory.getProxy(invoker, true); + String result = (String) client.$invoke("sayHello", new String[]{"java.lang.String"}, new Object[]{"haha"}); + Assertions.assertTrue(server.isCalled()); + Assertions.assertEquals("Hello, haha", result); + invoker.destroy(); + exporter.unexport(); + } + + @Test + public void testGenericInvokeWithNativeJava() throws IOException, ClassNotFoundException { + HttpServiceImpl server = new HttpServiceImpl(); + Assertions.assertFalse(server.isCalled()); + ProxyFactory proxyFactory = ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension(); + Protocol protocol = ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension(); + URL url = URL.valueOf("http-invoker://127.0.0.1:5342/" + HttpService.class.getName() + "?release=2.7.0&generic=nativejava"); + Exporter exporter = protocol.export(proxyFactory.getInvoker(server, HttpService.class, url)); + Invoker invoker = protocol.refer(GenericService.class, url); + GenericService client = proxyFactory.getProxy(invoker); + + Serialization serialization = new NativeJavaSerialization(); + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + + ObjectOutput objectOutput = serialization.serialize(url, byteArrayOutputStream); + objectOutput.writeObject("haha"); + objectOutput.flushBuffer(); + + Object result = client.$invoke("sayHello", new String[]{"java.lang.String"}, new Object[]{byteArrayOutputStream.toByteArray()}); + ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream((byte[]) result); + ObjectInput objectInput = serialization.deserialize(url, byteArrayInputStream); + Assertions.assertTrue(server.isCalled()); + Assertions.assertEquals("Hello, haha", objectInput.readObject()); + invoker.destroy(); + exporter.unexport(); + } + + @Test + public void testGenericInvokeWithBean() { + HttpServiceImpl server = new HttpServiceImpl(); + Assertions.assertFalse(server.isCalled()); + ProxyFactory proxyFactory = ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension(); + Protocol protocol = ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension(); + URL url = URL.valueOf("http-invoker://127.0.0.1:5342/" + HttpService.class.getName() + "?release=2.7.0&generic=bean"); + Exporter exporter = protocol.export(proxyFactory.getInvoker(server, HttpService.class, url)); + Invoker invoker = protocol.refer(GenericService.class, url); + GenericService client = proxyFactory.getProxy(invoker); + + JavaBeanDescriptor javaBeanDescriptor = JavaBeanSerializeUtil.serialize("haha"); + + Object result = client.$invoke("sayHello", new String[]{"java.lang.String"}, new Object[]{javaBeanDescriptor}); + Assertions.assertTrue(server.isCalled()); + Assertions.assertEquals("Hello, haha", JavaBeanSerializeUtil.deserialize((JavaBeanDescriptor) result)); + invoker.destroy(); + exporter.unexport(); + } + + @Test + public void testOverload() { + HttpServiceImpl server = new HttpServiceImpl(); + Assertions.assertFalse(server.isCalled()); + ProxyFactory proxyFactory = ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension(); + Protocol protocol = ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension(); + URL url = URL.valueOf("http-invoker://127.0.0.1:5342/" + HttpService.class.getName() + "?release=2.7.0&hessian.overload.method=true&hessian2.request=false"); + Exporter exporter = protocol.export(proxyFactory.getInvoker(server, HttpService.class, url)); + Invoker invoker = protocol.refer(HttpService.class, url); + HttpService client = proxyFactory.getProxy(invoker); + String result = client.sayHello("haha"); + Assertions.assertEquals("Hello, haha", result); + result = client.sayHello("haha", 1); + Assertions.assertEquals("Hello, haha. ", result); + invoker.destroy(); + exporter.unexport(); + } + + @Test + public void testSimpleClient() { + HttpServiceImpl server = new HttpServiceImpl(); + Assertions.assertFalse(server.isCalled()); + ProxyFactory proxyFactory = ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension(); + Protocol protocol = ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension(); + URL url = URL.valueOf("http-invoker://127.0.0.1:5342/" + HttpService.class.getName() + "?release=2.7.0&client=simple"); + Exporter exporter = protocol.export(proxyFactory.getInvoker(server, HttpService.class, url)); + Invoker invoker = protocol.refer(HttpService.class, url); + HttpService client = proxyFactory.getProxy(invoker); + String result = client.sayHello("haha"); + Assertions.assertTrue(server.isCalled()); + Assertions.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-invoker://127.0.0.1:5342/" + HttpService.class.getName() + "?release=2.7.0&timeout=10"); + Exporter exporter = protocol.export(proxyFactory.getInvoker(server, HttpService.class, url)); + Invoker invoker = protocol.refer(HttpService.class, url); + HttpService client = proxyFactory.getProxy(invoker); + try { + client.timeOut(6000); + fail(); + } catch (RpcException expected) { + Assertions.assertTrue(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-invoker://127.0.0.1:5342/" + HttpService.class.getName() + "?release=2.7.0"); + Exporter exporter = protocol.export(proxyFactory.getInvoker(server, HttpService.class, url)); + Invoker invoker = protocol.refer(HttpService.class, url); + HttpService client = proxyFactory.getProxy(invoker); + try { + client.customException(); + fail(); + } catch (HttpServiceImpl.MyException expected) { + } + invoker.destroy(); + exporter.unexport(); + } + +} diff --git a/dubbo-rpc/dubbo-rpc-http/src/test/java/org/apache/dubbo/rpc/protocol/http/HttpService.java b/dubbo-rpc/dubbo-rpc-http-invoker/src/test/java/org/apache/dubbo/rpc/protocol/httpinvoker/HttpService.java similarity index 92% rename from dubbo-rpc/dubbo-rpc-http/src/test/java/org/apache/dubbo/rpc/protocol/http/HttpService.java rename to dubbo-rpc/dubbo-rpc-http-invoker/src/test/java/org/apache/dubbo/rpc/protocol/httpinvoker/HttpService.java index d9a0dc0c96..e546c9bff6 100644 --- a/dubbo-rpc/dubbo-rpc-http/src/test/java/org/apache/dubbo/rpc/protocol/http/HttpService.java +++ b/dubbo-rpc/dubbo-rpc-http-invoker/src/test/java/org/apache/dubbo/rpc/protocol/httpinvoker/HttpService.java @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.dubbo.rpc.protocol.http; +package org.apache.dubbo.rpc.protocol.httpinvoker; /** diff --git a/dubbo-rpc/dubbo-rpc-http/src/test/java/org/apache/dubbo/rpc/protocol/http/HttpServiceImpl.java b/dubbo-rpc/dubbo-rpc-http-invoker/src/test/java/org/apache/dubbo/rpc/protocol/httpinvoker/HttpServiceImpl.java similarity index 94% rename from dubbo-rpc/dubbo-rpc-http/src/test/java/org/apache/dubbo/rpc/protocol/http/HttpServiceImpl.java rename to dubbo-rpc/dubbo-rpc-http-invoker/src/test/java/org/apache/dubbo/rpc/protocol/httpinvoker/HttpServiceImpl.java index c3d6e9734a..336ffbfd7d 100644 --- a/dubbo-rpc/dubbo-rpc-http/src/test/java/org/apache/dubbo/rpc/protocol/http/HttpServiceImpl.java +++ b/dubbo-rpc/dubbo-rpc-http-invoker/src/test/java/org/apache/dubbo/rpc/protocol/httpinvoker/HttpServiceImpl.java @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.dubbo.rpc.protocol.http; +package org.apache.dubbo.rpc.protocol.httpinvoker; /** * HttpServiceImpl diff --git a/dubbo-rpc/dubbo-rpc-http/pom.xml b/dubbo-rpc/dubbo-rpc-http/pom.xml index 6681a9a632..8552d7349c 100644 --- a/dubbo-rpc/dubbo-rpc-http/pom.xml +++ b/dubbo-rpc/dubbo-rpc-http/pom.xml @@ -14,20 +14,24 @@ See the License for the specific language governing permissions and limitations under the License. --> - - 4.0.0 + - org.apache.dubbo dubbo-rpc + org.apache.dubbo ${revision} + 4.0.0 + dubbo-rpc-http - jar - ${project.artifactId} - The http rpc module of dubbo project + + The JSON-RPC module of dubbo project + false + org.apache.dubbo @@ -44,14 +48,14 @@ spring-context - org.springframework - spring-web + com.github.briandilley.jsonrpc4j + jsonrpc4j - org.apache.dubbo - dubbo-serialization-jdk - ${project.parent.version} - test + javax.portlet + portlet-api + + \ No newline at end of file diff --git a/dubbo-rpc/dubbo-rpc-http/src/main/java/org/apache/dubbo/rpc/protocol/http/HttpProtocol.java b/dubbo-rpc/dubbo-rpc-http/src/main/java/org/apache/dubbo/rpc/protocol/http/HttpProtocol.java index c8f6e5839c..81072314ef 100644 --- a/dubbo-rpc/dubbo-rpc-http/src/main/java/org/apache/dubbo/rpc/protocol/http/HttpProtocol.java +++ b/dubbo-rpc/dubbo-rpc-http/src/main/java/org/apache/dubbo/rpc/protocol/http/HttpProtocol.java @@ -1,225 +1,163 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.dubbo.rpc.protocol.http; - -import org.apache.dubbo.common.URL; -import org.apache.dubbo.common.utils.StringUtils; -import org.apache.dubbo.common.Version; -import org.apache.dubbo.remoting.Constants; -import org.apache.dubbo.remoting.http.HttpBinder; -import org.apache.dubbo.remoting.http.HttpHandler; -import org.apache.dubbo.remoting.http.HttpServer; -import org.apache.dubbo.rpc.RpcContext; -import org.apache.dubbo.rpc.RpcException; -import org.apache.dubbo.rpc.protocol.AbstractProxyProtocol; -import org.apache.dubbo.rpc.service.GenericService; -import org.apache.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; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.net.HttpURLConnection; -import java.net.SocketTimeoutException; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_TIMEOUT; -import static org.apache.dubbo.common.constants.CommonConstants.RELEASE_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.TIMEOUT_KEY; -import static org.apache.dubbo.remoting.Constants.DUBBO_VERSION_KEY; -import static org.apache.dubbo.rpc.Constants.GENERIC_KEY; - -/** - * HttpProtocol - */ -public class HttpProtocol extends AbstractProxyProtocol { - - public static final int DEFAULT_PORT = 80; - - private final Map serverMap = new ConcurrentHashMap(); - - private final Map skeletonMap = new ConcurrentHashMap(); - - private HttpBinder httpBinder; - - public HttpProtocol() { - super(RemoteAccessException.class); - } - - public void setHttpBinder(HttpBinder httpBinder) { - this.httpBinder = httpBinder; - } - - @Override - public int getDefaultPort() { - return DEFAULT_PORT; - } - - @Override - protected Runnable doExport(final T impl, Class type, URL url) throws RpcException { - String addr = getAddr(url); - HttpServer server = serverMap.get(addr); - if (server == null) { - 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 + "/" + GENERIC_KEY; - - skeletonMap.put(genericPath, createExporter(impl, GenericService.class)); - return new Runnable() { - @Override - public void run() { - skeletonMap.remove(path); - skeletonMap.remove(genericPath); - } - }; - } - - private HttpInvokerServiceExporter createExporter(T impl, Class type) { - final HttpInvokerServiceExporter httpServiceExporter = new HttpInvokerServiceExporter(); - httpServiceExporter.setServiceInterface(type); - httpServiceExporter.setService(impl); - try { - httpServiceExporter.afterPropertiesSet(); - } catch (Exception e) { - throw new RpcException(e.getMessage(), e); - } - return httpServiceExporter; - } - - @Override - @SuppressWarnings("unchecked") - protected T doRefer(final Class serviceType, final URL url) throws RpcException { - final String generic = url.getParameter(GENERIC_KEY); - final boolean isGeneric = ProtocolUtils.isGeneric(generic) || serviceType.equals(GenericService.class); - - final HttpInvokerProxyFactoryBean httpProxyFactoryBean = new HttpInvokerProxyFactoryBean(); - httpProxyFactoryBean.setRemoteInvocationFactory(new RemoteInvocationFactory() { - @Override - public RemoteInvocation createRemoteInvocation(MethodInvocation methodInvocation) { - RemoteInvocation invocation; - /* - package was renamed to 'org.apache.dubbo' in v2.7.0, so only provider versions after v2.7.0 can - recognize org.apache.xxx.HttpRemoteInvocation'. - */ - if (Version.isRelease270OrHigher(url.getParameter(RELEASE_KEY))) { - invocation = new HttpRemoteInvocation(methodInvocation); - } else { - /* - The customized 'com.alibaba.dubbo.rpc.protocol.http.HttpRemoteInvocation' was firstly introduced - in v2.6.3. The main purpose is to support transformation of attachments in HttpProtocol, see - https://github.com/apache/dubbo/pull/1827. To guarantee interoperability with lower - versions, we need to check if the provider is v2.6.3 or higher before sending customized - HttpRemoteInvocation. - */ - if (Version.isRelease263OrHigher(url.getParameter(DUBBO_VERSION_KEY))) { - invocation = new com.alibaba.dubbo.rpc.protocol.http.HttpRemoteInvocation(methodInvocation); - } else { - invocation = new RemoteInvocation(methodInvocation); - } - } - if (isGeneric) { - invocation.addAttribute(GENERIC_KEY, generic); - } - return invocation; - } - }); - - String key = url.toIdentityString(); - if (isGeneric) { - key = key + "/" + GENERIC_KEY; - } - - httpProxyFactoryBean.setServiceUrl(key); - httpProxyFactoryBean.setServiceInterface(serviceType); - String client = url.getParameter(Constants.CLIENT_KEY); - if (StringUtils.isEmpty(client) || "simple".equals(client)) { - SimpleHttpInvokerRequestExecutor httpInvokerRequestExecutor = new SimpleHttpInvokerRequestExecutor() { - @Override - protected void prepareConnection(HttpURLConnection con, - int contentLength) throws IOException { - super.prepareConnection(con, contentLength); - con.setReadTimeout(url.getParameter(TIMEOUT_KEY, DEFAULT_TIMEOUT)); - con.setConnectTimeout(url.getParameter(Constants.CONNECT_TIMEOUT_KEY, Constants.DEFAULT_CONNECT_TIMEOUT)); - } - }; - httpProxyFactoryBean.setHttpInvokerRequestExecutor(httpInvokerRequestExecutor); - } else if ("commons".equals(client)) { - HttpComponentsHttpInvokerRequestExecutor httpInvokerRequestExecutor = new HttpComponentsHttpInvokerRequestExecutor(); - httpInvokerRequestExecutor.setReadTimeout(url.getParameter(TIMEOUT_KEY, 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"); - } - httpProxyFactoryBean.afterPropertiesSet(); - return (T) httpProxyFactoryBean.getObject(); - } - - @Override - protected int getErrorCode(Throwable e) { - if (e instanceof RemoteAccessException) { - e = e.getCause(); - } - if (e != null) { - Class cls = e.getClass(); - if (SocketTimeoutException.class.equals(cls)) { - return RpcException.TIMEOUT_EXCEPTION; - } else if (IOException.class.isAssignableFrom(cls)) { - return RpcException.NETWORK_EXCEPTION; - } else if (ClassNotFoundException.class.isAssignableFrom(cls)) { - return RpcException.SERIALIZATION_EXCEPTION; - } - } - return super.getErrorCode(e); - } - - private class InternalHandler implements HttpHandler { - - @Override - public void handle(HttpServletRequest request, HttpServletResponse response) - throws IOException, ServletException { - String uri = request.getRequestURI(); - HttpInvokerServiceExporter skeleton = skeletonMap.get(uri); - if (!"POST".equalsIgnoreCase(request.getMethod())) { - response.setStatus(500); - } else { - RpcContext.getContext().setRemoteAddress(request.getRemoteAddr(), request.getRemotePort()); - try { - skeleton.handleRequest(request, response); - } catch (Throwable e) { - throw new ServletException(e); - } - } - } - - } - -} +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.dubbo.rpc.protocol.http; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.remoting.http.HttpBinder; +import org.apache.dubbo.remoting.http.HttpHandler; +import org.apache.dubbo.remoting.http.HttpServer; +import org.apache.dubbo.rpc.RpcContext; +import org.apache.dubbo.rpc.RpcException; +import org.apache.dubbo.rpc.protocol.AbstractProxyProtocol; + +import com.googlecode.jsonrpc4j.HttpException; +import com.googlecode.jsonrpc4j.JsonRpcClientException; +import com.googlecode.jsonrpc4j.JsonRpcServer; +import com.googlecode.jsonrpc4j.spring.JsonProxyFactoryBean; +import org.springframework.remoting.RemoteAccessException; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.net.SocketTimeoutException; +import java.util.ArrayList; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +public class HttpProtocol extends AbstractProxyProtocol { + + public static final String ACCESS_CONTROL_ALLOW_ORIGIN_HEADER = "Access-Control-Allow-Origin"; + public static final String ACCESS_CONTROL_ALLOW_METHODS_HEADER = "Access-Control-Allow-Methods"; + public static final String ACCESS_CONTROL_ALLOW_HEADERS_HEADER = "Access-Control-Allow-Headers"; + + private final Map serverMap = new ConcurrentHashMap<>(); + + private final Map skeletonMap = new ConcurrentHashMap<>(); + + private HttpBinder httpBinder; + + public HttpProtocol() { + super(HttpException.class, JsonRpcClientException.class); + } + + public void setHttpBinder(HttpBinder httpBinder) { + this.httpBinder = httpBinder; + } + + @Override + public int getDefaultPort() { + return 80; + } + + private class InternalHandler implements HttpHandler { + + private boolean cors; + + public InternalHandler(boolean cors) { + this.cors = cors; + } + + @Override + public void handle(HttpServletRequest request, HttpServletResponse response) + throws ServletException { + String uri = request.getRequestURI(); + JsonRpcServer skeleton = skeletonMap.get(uri); + if (cors) { + response.setHeader(ACCESS_CONTROL_ALLOW_ORIGIN_HEADER, "*"); + response.setHeader(ACCESS_CONTROL_ALLOW_METHODS_HEADER, "POST"); + response.setHeader(ACCESS_CONTROL_ALLOW_HEADERS_HEADER, "*"); + } + if ("OPTIONS".equalsIgnoreCase(request.getMethod())) { + response.setStatus(200); + } else if ("POST".equalsIgnoreCase(request.getMethod())) { + + RpcContext.getContext().setRemoteAddress(request.getRemoteAddr(), request.getRemotePort()); + try { + skeleton.handle(request.getInputStream(), response.getOutputStream()); + } catch (Throwable e) { + throw new ServletException(e); + } + } else { + response.setStatus(500); + } + } + + } + + @Override + protected Runnable doExport(T impl, Class type, URL url) throws RpcException { + String addr = url.getIp() + ":" + url.getPort(); + HttpServer server = serverMap.get(addr); + if (server == null) { + server = httpBinder.bind(url, new InternalHandler(url.getParameter("cors", false))); + serverMap.put(addr, server); + } + final String path = url.getAbsolutePath(); + JsonRpcServer skeleton = new JsonRpcServer(impl, type); + skeletonMap.put(path, skeleton); + return () -> skeletonMap.remove(path); + } + + @SuppressWarnings("unchecked") + @Override + protected T doRefer(final Class serviceType, URL url) throws RpcException { + JsonProxyFactoryBean jsonProxyFactoryBean = new JsonProxyFactoryBean(); + jsonProxyFactoryBean.setServiceUrl(url.setProtocol("http").toIdentityString()); + jsonProxyFactoryBean.setServiceInterface(serviceType); + + jsonProxyFactoryBean.afterPropertiesSet(); + return (T) jsonProxyFactoryBean.getObject(); + } + + @Override + protected int getErrorCode(Throwable e) { + if (e instanceof RemoteAccessException) { + e = e.getCause(); + } + if (e != null) { + Class cls = e.getClass(); + if (SocketTimeoutException.class.equals(cls)) { + return RpcException.TIMEOUT_EXCEPTION; + } else if (IOException.class.isAssignableFrom(cls)) { + return RpcException.NETWORK_EXCEPTION; + } else if (ClassNotFoundException.class.isAssignableFrom(cls)) { + return RpcException.SERIALIZATION_EXCEPTION; + } + } + return super.getErrorCode(e); + } + + @Override + public void destroy() { + super.destroy(); + for (String key : new ArrayList<>(serverMap.keySet())) { + HttpServer server = serverMap.remove(key); + if (server != null) { + try { + if (logger.isInfoEnabled()) { + logger.info("Close jsonrpc server " + server.getUrl()); + } + server.close(); + } catch (Throwable t) { + logger.warn(t.getMessage(), t); + } + } + } + } + +} \ No newline at end of file diff --git a/dubbo-rpc/dubbo-rpc-http/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.Protocol b/dubbo-rpc/dubbo-rpc-http/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.Protocol index ed1aa52bcb..46f47ba0dd 100644 --- a/dubbo-rpc/dubbo-rpc-http/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.Protocol +++ b/dubbo-rpc/dubbo-rpc-http/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.Protocol @@ -1 +1 @@ -http=org.apache.dubbo.rpc.protocol.http.HttpProtocol +http=org.apache.dubbo.rpc.protocol.http.HttpProtocol \ No newline at end of file diff --git a/dubbo-rpc/dubbo-rpc-http/src/test/java/org/apache/dubbo/rpc/protocol/http/HttpProtocolTest.java b/dubbo-rpc/dubbo-rpc-http/src/test/java/org/apache/dubbo/rpc/protocol/http/HttpProtocolTest.java index 29a4b1c8ae..cee35beabf 100644 --- a/dubbo-rpc/dubbo-rpc-http/src/test/java/org/apache/dubbo/rpc/protocol/http/HttpProtocolTest.java +++ b/dubbo-rpc/dubbo-rpc-http/src/test/java/org/apache/dubbo/rpc/protocol/http/HttpProtocolTest.java @@ -1,203 +1,69 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.dubbo.rpc.protocol.http; - -import org.apache.dubbo.common.URL; -import org.apache.dubbo.common.beanutil.JavaBeanDescriptor; -import org.apache.dubbo.common.beanutil.JavaBeanSerializeUtil; -import org.apache.dubbo.common.extension.ExtensionLoader; -import org.apache.dubbo.common.serialize.ObjectInput; -import org.apache.dubbo.common.serialize.ObjectOutput; -import org.apache.dubbo.common.serialize.Serialization; -import org.apache.dubbo.common.serialize.nativejava.NativeJavaSerialization; -import org.apache.dubbo.rpc.Exporter; -import org.apache.dubbo.rpc.Invoker; -import org.apache.dubbo.rpc.Protocol; -import org.apache.dubbo.rpc.ProxyFactory; -import org.apache.dubbo.rpc.RpcException; -import org.apache.dubbo.rpc.service.GenericService; - -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; - -import static org.junit.jupiter.api.Assertions.fail; - -/** - * HttpProtocolTest - */ -public class HttpProtocolTest { - - @Test - public void testHttpProtocol() { - HttpServiceImpl server = new HttpServiceImpl(); - Assertions.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() + "?release=2.7.0"); - Exporter exporter = protocol.export(proxyFactory.getInvoker(server, HttpService.class, url)); - Invoker invoker = protocol.refer(HttpService.class, url); - HttpService client = proxyFactory.getProxy(invoker); - String result = client.sayHello("haha"); - Assertions.assertTrue(server.isCalled()); - Assertions.assertEquals("Hello, haha", result); - invoker.destroy(); - exporter.unexport(); - } - - @Test - public void testGenericInvoke() { - HttpServiceImpl server = new HttpServiceImpl(); - Assertions.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() + "?release=2.7.0"); - Exporter exporter = protocol.export(proxyFactory.getInvoker(server, HttpService.class, url)); - Invoker invoker = protocol.refer(GenericService.class, url); - GenericService client = proxyFactory.getProxy(invoker, true); - String result = (String) client.$invoke("sayHello", new String[]{"java.lang.String"}, new Object[]{"haha"}); - Assertions.assertTrue(server.isCalled()); - Assertions.assertEquals("Hello, haha", result); - invoker.destroy(); - exporter.unexport(); - } - - @Test - public void testGenericInvokeWithNativeJava() throws IOException, ClassNotFoundException { - HttpServiceImpl server = new HttpServiceImpl(); - Assertions.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() + "?release=2.7.0&generic=nativejava"); - Exporter exporter = protocol.export(proxyFactory.getInvoker(server, HttpService.class, url)); - Invoker invoker = protocol.refer(GenericService.class, url); - GenericService client = proxyFactory.getProxy(invoker); - - Serialization serialization = new NativeJavaSerialization(); - ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); - - ObjectOutput objectOutput = serialization.serialize(url, byteArrayOutputStream); - objectOutput.writeObject("haha"); - objectOutput.flushBuffer(); - - Object result = client.$invoke("sayHello", new String[]{"java.lang.String"}, new Object[]{byteArrayOutputStream.toByteArray()}); - ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream((byte[]) result); - ObjectInput objectInput = serialization.deserialize(url, byteArrayInputStream); - Assertions.assertTrue(server.isCalled()); - Assertions.assertEquals("Hello, haha", objectInput.readObject()); - invoker.destroy(); - exporter.unexport(); - } - - @Test - public void testGenericInvokeWithBean() { - HttpServiceImpl server = new HttpServiceImpl(); - Assertions.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() + "?release=2.7.0&generic=bean"); - Exporter exporter = protocol.export(proxyFactory.getInvoker(server, HttpService.class, url)); - Invoker invoker = protocol.refer(GenericService.class, url); - GenericService client = proxyFactory.getProxy(invoker); - - JavaBeanDescriptor javaBeanDescriptor = JavaBeanSerializeUtil.serialize("haha"); - - Object result = client.$invoke("sayHello", new String[]{"java.lang.String"}, new Object[]{javaBeanDescriptor}); - Assertions.assertTrue(server.isCalled()); - Assertions.assertEquals("Hello, haha", JavaBeanSerializeUtil.deserialize((JavaBeanDescriptor) result)); - invoker.destroy(); - exporter.unexport(); - } - - @Test - public void testOverload() { - HttpServiceImpl server = new HttpServiceImpl(); - Assertions.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() + "?release=2.7.0&hessian.overload.method=true&hessian2.request=false"); - Exporter exporter = protocol.export(proxyFactory.getInvoker(server, HttpService.class, url)); - Invoker invoker = protocol.refer(HttpService.class, url); - HttpService client = proxyFactory.getProxy(invoker); - String result = client.sayHello("haha"); - Assertions.assertEquals("Hello, haha", result); - result = client.sayHello("haha", 1); - Assertions.assertEquals("Hello, haha. ", result); - invoker.destroy(); - exporter.unexport(); - } - - @Test - public void testSimpleClient() { - HttpServiceImpl server = new HttpServiceImpl(); - Assertions.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() + "?release=2.7.0&client=simple"); - Exporter exporter = protocol.export(proxyFactory.getInvoker(server, HttpService.class, url)); - Invoker invoker = protocol.refer(HttpService.class, url); - HttpService client = proxyFactory.getProxy(invoker); - String result = client.sayHello("haha"); - Assertions.assertTrue(server.isCalled()); - Assertions.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() + "?release=2.7.0&timeout=10"); - Exporter exporter = protocol.export(proxyFactory.getInvoker(server, HttpService.class, url)); - Invoker invoker = protocol.refer(HttpService.class, url); - HttpService client = proxyFactory.getProxy(invoker); - try { - client.timeOut(6000); - fail(); - } catch (RpcException expected) { - Assertions.assertTrue(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() + "?release=2.7.0"); - Exporter exporter = protocol.export(proxyFactory.getInvoker(server, HttpService.class, url)); - Invoker invoker = protocol.refer(HttpService.class, url); - HttpService client = proxyFactory.getProxy(invoker); - try { - client.customException(); - fail(); - } catch (HttpServiceImpl.MyException expected) { - } - invoker.destroy(); - exporter.unexport(); - } - -} +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.dubbo.rpc.protocol.http; + + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.extension.ExtensionLoader; +import org.apache.dubbo.rpc.Exporter; +import org.apache.dubbo.rpc.Invoker; +import org.apache.dubbo.rpc.Protocol; +import org.apache.dubbo.rpc.ProxyFactory; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class HttpProtocolTest { + + @Test + public void testJsonrpcProtocol() { + JsonRpcServiceImpl server = new JsonRpcServiceImpl(); + 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/" + JsonRpcService.class.getName() + "?version=1.0.0"); + Exporter exporter = protocol.export(proxyFactory.getInvoker(server, JsonRpcService.class, url)); + Invoker invoker = protocol.refer(JsonRpcService.class, url); + JsonRpcService client = proxyFactory.getProxy(invoker); + String result = client.sayHello("haha"); + assertTrue(server.isCalled()); + assertEquals("Hello, haha", result); + invoker.destroy(); + exporter.unexport(); + } + + @Test + public void testJsonrpcProtocolForServerJetty() { + JsonRpcServiceImpl server = new JsonRpcServiceImpl(); + 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/" + JsonRpcService.class.getName() + "?version=1.0.0&server=jetty"); + Exporter exporter = protocol.export(proxyFactory.getInvoker(server, JsonRpcService.class, url)); + Invoker invoker = protocol.refer(JsonRpcService.class, url); + JsonRpcService client = proxyFactory.getProxy(invoker); + String result = client.sayHello("haha"); + assertTrue(server.isCalled()); + assertEquals("Hello, haha", result); + invoker.destroy(); + exporter.unexport(); + } + +} \ No newline at end of file diff --git a/dubbo-rpc/dubbo-rpc-jsonrpc/src/test/java/org/apache/dubbo/rpc/protocol/jsonrpc/JsonRpcService.java b/dubbo-rpc/dubbo-rpc-http/src/test/java/org/apache/dubbo/rpc/protocol/http/JsonRpcService.java similarity index 95% rename from dubbo-rpc/dubbo-rpc-jsonrpc/src/test/java/org/apache/dubbo/rpc/protocol/jsonrpc/JsonRpcService.java rename to dubbo-rpc/dubbo-rpc-http/src/test/java/org/apache/dubbo/rpc/protocol/http/JsonRpcService.java index 0bcbc8d1ad..e01fc6ea6a 100644 --- a/dubbo-rpc/dubbo-rpc-jsonrpc/src/test/java/org/apache/dubbo/rpc/protocol/jsonrpc/JsonRpcService.java +++ b/dubbo-rpc/dubbo-rpc-http/src/test/java/org/apache/dubbo/rpc/protocol/http/JsonRpcService.java @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.dubbo.rpc.protocol.jsonrpc; +package org.apache.dubbo.rpc.protocol.http; public interface JsonRpcService { String sayHello(String name); diff --git a/dubbo-rpc/dubbo-rpc-jsonrpc/src/test/java/org/apache/dubbo/rpc/protocol/jsonrpc/JsonRpcServiceImpl.java b/dubbo-rpc/dubbo-rpc-http/src/test/java/org/apache/dubbo/rpc/protocol/http/JsonRpcServiceImpl.java similarity index 97% rename from dubbo-rpc/dubbo-rpc-jsonrpc/src/test/java/org/apache/dubbo/rpc/protocol/jsonrpc/JsonRpcServiceImpl.java rename to dubbo-rpc/dubbo-rpc-http/src/test/java/org/apache/dubbo/rpc/protocol/http/JsonRpcServiceImpl.java index 01f32d28ab..4284753c82 100644 --- a/dubbo-rpc/dubbo-rpc-jsonrpc/src/test/java/org/apache/dubbo/rpc/protocol/jsonrpc/JsonRpcServiceImpl.java +++ b/dubbo-rpc/dubbo-rpc-http/src/test/java/org/apache/dubbo/rpc/protocol/http/JsonRpcServiceImpl.java @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.dubbo.rpc.protocol.jsonrpc; +package org.apache.dubbo.rpc.protocol.http; public class JsonRpcServiceImpl implements JsonRpcService { private boolean called; diff --git a/dubbo-rpc/dubbo-rpc-jsonrpc/src/main/java/org/apache/dubbo/rpc/protocol/jsonrpc/JsonRpcProtocol.java b/dubbo-rpc/dubbo-rpc-jsonrpc/src/main/java/org/apache/dubbo/rpc/protocol/jsonrpc/JsonRpcProtocol.java deleted file mode 100644 index 28dc56b67e..0000000000 --- a/dubbo-rpc/dubbo-rpc-jsonrpc/src/main/java/org/apache/dubbo/rpc/protocol/jsonrpc/JsonRpcProtocol.java +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.dubbo.rpc.protocol.jsonrpc; - -import org.apache.dubbo.common.URL; -import org.apache.dubbo.remoting.http.HttpBinder; -import org.apache.dubbo.remoting.http.HttpHandler; -import org.apache.dubbo.remoting.http.HttpServer; -import org.apache.dubbo.rpc.RpcContext; -import org.apache.dubbo.rpc.RpcException; -import org.apache.dubbo.rpc.protocol.AbstractProxyProtocol; - -import com.googlecode.jsonrpc4j.HttpException; -import com.googlecode.jsonrpc4j.JsonRpcClientException; -import com.googlecode.jsonrpc4j.JsonRpcServer; -import com.googlecode.jsonrpc4j.spring.JsonProxyFactoryBean; -import org.springframework.remoting.RemoteAccessException; - -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.net.SocketTimeoutException; -import java.util.ArrayList; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -public class JsonRpcProtocol extends AbstractProxyProtocol { - - public static final String ACCESS_CONTROL_ALLOW_ORIGIN_HEADER = "Access-Control-Allow-Origin"; - public static final String ACCESS_CONTROL_ALLOW_METHODS_HEADER = "Access-Control-Allow-Methods"; - public static final String ACCESS_CONTROL_ALLOW_HEADERS_HEADER = "Access-Control-Allow-Headers"; - - private final Map serverMap = new ConcurrentHashMap<>(); - - private final Map skeletonMap = new ConcurrentHashMap<>(); - - private HttpBinder httpBinder; - - public JsonRpcProtocol() { - super(HttpException.class, JsonRpcClientException.class); - } - - public void setHttpBinder(HttpBinder httpBinder) { - this.httpBinder = httpBinder; - } - - @Override - public int getDefaultPort() { - return 80; - } - - private class InternalHandler implements HttpHandler { - - private boolean cors; - - public InternalHandler(boolean cors) { - this.cors = cors; - } - - @Override - public void handle(HttpServletRequest request, HttpServletResponse response) - throws ServletException { - String uri = request.getRequestURI(); - JsonRpcServer skeleton = skeletonMap.get(uri); - if (cors) { - response.setHeader(ACCESS_CONTROL_ALLOW_ORIGIN_HEADER, "*"); - response.setHeader(ACCESS_CONTROL_ALLOW_METHODS_HEADER, "POST"); - response.setHeader(ACCESS_CONTROL_ALLOW_HEADERS_HEADER, "*"); - } - if ("OPTIONS".equalsIgnoreCase(request.getMethod())) { - response.setStatus(200); - } else if ("POST".equalsIgnoreCase(request.getMethod())) { - - RpcContext.getContext().setRemoteAddress(request.getRemoteAddr(), request.getRemotePort()); - try { - skeleton.handle(request.getInputStream(), response.getOutputStream()); - } catch (Throwable e) { - throw new ServletException(e); - } - } else { - response.setStatus(500); - } - } - - } - - @Override - protected Runnable doExport(T impl, Class type, URL url) throws RpcException { - String addr = url.getIp() + ":" + url.getPort(); - HttpServer server = serverMap.get(addr); - if (server == null) { - server = httpBinder.bind(url, new InternalHandler(url.getParameter("cors", false))); - serverMap.put(addr, server); - } - final String path = url.getAbsolutePath(); - JsonRpcServer skeleton = new JsonRpcServer(impl, type); - skeletonMap.put(path, skeleton); - return () -> skeletonMap.remove(path); - } - - @SuppressWarnings("unchecked") - @Override - protected T doRefer(final Class serviceType, URL url) throws RpcException { - JsonProxyFactoryBean jsonProxyFactoryBean = new JsonProxyFactoryBean(); - jsonProxyFactoryBean.setServiceUrl(url.setProtocol("http").toIdentityString()); - jsonProxyFactoryBean.setServiceInterface(serviceType); - - jsonProxyFactoryBean.afterPropertiesSet(); - return (T) jsonProxyFactoryBean.getObject(); - } - - @Override - protected int getErrorCode(Throwable e) { - if (e instanceof RemoteAccessException) { - e = e.getCause(); - } - if (e != null) { - Class cls = e.getClass(); - if (SocketTimeoutException.class.equals(cls)) { - return RpcException.TIMEOUT_EXCEPTION; - } else if (IOException.class.isAssignableFrom(cls)) { - return RpcException.NETWORK_EXCEPTION; - } else if (ClassNotFoundException.class.isAssignableFrom(cls)) { - return RpcException.SERIALIZATION_EXCEPTION; - } - } - return super.getErrorCode(e); - } - - @Override - public void destroy() { - super.destroy(); - for (String key : new ArrayList<>(serverMap.keySet())) { - HttpServer server = serverMap.remove(key); - if (server != null) { - try { - if (logger.isInfoEnabled()) { - logger.info("Close jsonrpc server " + server.getUrl()); - } - server.close(); - } catch (Throwable t) { - logger.warn(t.getMessage(), t); - } - } - } - } - -} \ No newline at end of file diff --git a/dubbo-rpc/dubbo-rpc-jsonrpc/src/main/resources/META-INF/dubbo/internal/com.alibaba.dubbo.rpc.Protocol b/dubbo-rpc/dubbo-rpc-jsonrpc/src/main/resources/META-INF/dubbo/internal/com.alibaba.dubbo.rpc.Protocol deleted file mode 100644 index 0ce276fc4b..0000000000 --- a/dubbo-rpc/dubbo-rpc-jsonrpc/src/main/resources/META-INF/dubbo/internal/com.alibaba.dubbo.rpc.Protocol +++ /dev/null @@ -1 +0,0 @@ -jsonrpc=org.apache.dubbo.rpc.protocol.jsonrpc.JsonRpcProtocol \ No newline at end of file diff --git a/dubbo-rpc/dubbo-rpc-jsonrpc/src/test/java/org/apache/dubbo/rpc/protocol/jsonrpc/JsonRpcProtocolTest.java b/dubbo-rpc/dubbo-rpc-jsonrpc/src/test/java/org/apache/dubbo/rpc/protocol/jsonrpc/JsonRpcProtocolTest.java deleted file mode 100644 index 5f6e791e9b..0000000000 --- a/dubbo-rpc/dubbo-rpc-jsonrpc/src/test/java/org/apache/dubbo/rpc/protocol/jsonrpc/JsonRpcProtocolTest.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.dubbo.rpc.protocol.jsonrpc; - - -import org.apache.dubbo.common.URL; -import org.apache.dubbo.common.extension.ExtensionLoader; -import org.apache.dubbo.rpc.Exporter; -import org.apache.dubbo.rpc.Invoker; -import org.apache.dubbo.rpc.Protocol; -import org.apache.dubbo.rpc.ProxyFactory; - -import org.junit.jupiter.api.Test; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertTrue; - -public class JsonRpcProtocolTest { - - @Test - public void testJsonrpcProtocol() { - JsonRpcServiceImpl server = new JsonRpcServiceImpl(); - assertFalse(server.isCalled()); - ProxyFactory proxyFactory = ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension(); - Protocol protocol = ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension(); - URL url = URL.valueOf("jsonrpc://127.0.0.1:5342/" + JsonRpcService.class.getName() + "?version=1.0.0"); - Exporter exporter = protocol.export(proxyFactory.getInvoker(server, JsonRpcService.class, url)); - Invoker invoker = protocol.refer(JsonRpcService.class, url); - JsonRpcService client = proxyFactory.getProxy(invoker); - String result = client.sayHello("haha"); - assertTrue(server.isCalled()); - assertEquals("Hello, haha", result); - invoker.destroy(); - exporter.unexport(); - } - - @Test - public void testJsonrpcProtocolForServerJetty9() { - JsonRpcServiceImpl server = new JsonRpcServiceImpl(); - assertFalse(server.isCalled()); - ProxyFactory proxyFactory = ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension(); - Protocol protocol = ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension(); - URL url = URL.valueOf("jsonrpc://127.0.0.1:5342/" + JsonRpcService.class.getName() + "?version=1.0.0&server=jetty9"); - Exporter exporter = protocol.export(proxyFactory.getInvoker(server, JsonRpcService.class, url)); - Invoker invoker = protocol.refer(JsonRpcService.class, url); - JsonRpcService client = proxyFactory.getProxy(invoker); - String result = client.sayHello("haha"); - assertTrue(server.isCalled()); - assertEquals("Hello, haha", result); - invoker.destroy(); - exporter.unexport(); - } - -} \ No newline at end of file diff --git a/dubbo-rpc/pom.xml b/dubbo-rpc/pom.xml index 44b064f697..22e9d840d0 100644 --- a/dubbo-rpc/pom.xml +++ b/dubbo-rpc/pom.xml @@ -32,10 +32,10 @@ dubbo-rpc-api dubbo-rpc-dubbo dubbo-rpc-injvm - dubbo-rpc-jsonrpc + dubbo-rpc-http dubbo-rpc-rmi dubbo-rpc-hessian - dubbo-rpc-http + dubbo-rpc-http-invoker dubbo-rpc-webservice dubbo-rpc-native-thrift dubbo-rpc-thrift