Skip to content

Commit

Permalink
fix RMI protocol doesn't support generic invocation. apache#2779
Browse files Browse the repository at this point in the history
  • Loading branch information
CrazyHZM committed Feb 28, 2019
1 parent e1cb03b commit 4f4b147
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,12 @@
import org.apache.dubbo.common.URL;
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.springframework.remoting.RemoteAccessException;
import org.springframework.remoting.rmi.RmiProxyFactoryBean;
import org.springframework.remoting.rmi.RmiServiceExporter;
import org.springframework.remoting.support.RemoteInvocation;

import java.io.IOException;
import java.net.SocketTimeoutException;
Expand All @@ -50,21 +52,14 @@ public int getDefaultPort() {

@Override
protected <T> Runnable doExport(final T impl, Class<T> type, URL url) throws RpcException {
final RmiServiceExporter rmiServiceExporter = new RmiServiceExporter();
rmiServiceExporter.setRegistryPort(url.getPort());
rmiServiceExporter.setServiceName(url.getPath());
rmiServiceExporter.setServiceInterface(type);
rmiServiceExporter.setService(impl);
try {
rmiServiceExporter.afterPropertiesSet();
} catch (RemoteException e) {
throw new RpcException(e.getMessage(), e);
}
RmiServiceExporter rmiServiceExporter = createExporter(impl, type, url, false);
RmiServiceExporter genericServiceExporter = createExporter(impl, GenericService.class, url, true);
return new Runnable() {
@Override
public void run() {
try {
rmiServiceExporter.destroy();
genericServiceExporter.destroy();
} catch (Throwable e) {
logger.warn(e.getMessage(), e);
}
Expand All @@ -76,6 +71,8 @@ public void run() {
@SuppressWarnings("unchecked")
protected <T> T doRefer(final Class<T> serviceType, final URL url) throws RpcException {
final RmiProxyFactoryBean rmiProxyFactoryBean = new RmiProxyFactoryBean();
final String generic = url.getParameter(Constants.GENERIC_KEY);
final boolean isGeneric = ProtocolUtils.isGeneric(generic) || serviceType.equals(GenericService.class);
/*
RMI needs extra parameter since it uses customized remote invocation object
Expand All @@ -86,11 +83,27 @@ protected <T> T doRefer(final Class<T> serviceType, final URL url) throws RpcExc
3. if the provider version is lower than v2.6.3, does not use customized RemoteInvocation.
*/
if (isRelease270OrHigher(url.getParameter(Constants.RELEASE_KEY))) {
rmiProxyFactoryBean.setRemoteInvocationFactory(RmiRemoteInvocation::new);
rmiProxyFactoryBean.setRemoteInvocationFactory((methodInvocation) -> {
RemoteInvocation invocation = new RmiRemoteInvocation(methodInvocation);
if (invocation != null && isGeneric) {
invocation.addAttribute(Constants.GENERIC_KEY, generic);
}
return invocation;
});
} else if (isRelease263OrHigher(url.getParameter(Constants.DUBBO_VERSION_KEY))) {
rmiProxyFactoryBean.setRemoteInvocationFactory(com.alibaba.dubbo.rpc.protocol.rmi.RmiRemoteInvocation::new);
rmiProxyFactoryBean.setRemoteInvocationFactory((methodInvocation) -> {
RemoteInvocation invocation = new com.alibaba.dubbo.rpc.protocol.rmi.RmiRemoteInvocation(methodInvocation);
if (invocation != null && isGeneric) {
invocation.addAttribute(Constants.GENERIC_KEY, generic);
}
return invocation;
});
}
String serviceUrl = url.toIdentityString();
if (isGeneric) {
serviceUrl = serviceUrl + "/" + Constants.GENERIC_KEY;
}
rmiProxyFactoryBean.setServiceUrl(url.toIdentityString());
rmiProxyFactoryBean.setServiceUrl(serviceUrl);
rmiProxyFactoryBean.setServiceInterface(serviceType);
rmiProxyFactoryBean.setCacheStub(true);
rmiProxyFactoryBean.setLookupStubOnStartup(true);
Expand All @@ -117,4 +130,22 @@ protected int getErrorCode(Throwable e) {
return super.getErrorCode(e);
}

private <T> RmiServiceExporter createExporter(T impl, Class<?> type, URL url, boolean isGeneric) {
final RmiServiceExporter rmiServiceExporter = new RmiServiceExporter();
rmiServiceExporter.setRegistryPort(url.getPort());
if (isGeneric) {
rmiServiceExporter.setServiceName(url.getPath() + "/" + Constants.GENERIC_KEY);
} else {
rmiServiceExporter.setServiceName(url.getPath());
}
rmiServiceExporter.setServiceInterface(type);
rmiServiceExporter.setService(impl);
try {
rmiServiceExporter.afterPropertiesSet();
} catch (RemoteException e) {
throw new RpcException(e.getMessage(), e);
}
return rmiServiceExporter;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
*/
package org.apache.dubbo.rpc.protocol.rmi;

import org.apache.dubbo.common.Constants;
import org.apache.dubbo.common.utils.StringUtils;
import org.apache.dubbo.rpc.RpcContext;

import org.aopalliance.intercept.MethodInvocation;
Expand All @@ -34,7 +36,7 @@ public class RmiRemoteInvocation extends RemoteInvocation {
*/
public RmiRemoteInvocation(MethodInvocation methodInvocation) {
super(methodInvocation);
addAttribute(dubboAttachmentsAttrName, new HashMap<String, String>(RpcContext.getContext().getAttachments()));
addAttribute(dubboAttachmentsAttrName, new HashMap<>(RpcContext.getContext().getAttachments()));
}

/**
Expand All @@ -48,6 +50,10 @@ public Object invoke(Object targetObject) throws NoSuchMethodException, IllegalA
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 {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
public interface DemoService {
void sayHello(String name);

String sayHi(String name);

String echo(String text);

long timestamp();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ public void sayHello(String name) {
System.out.println("hello " + name);
}

public String sayHi(String name) {
return "Hi, " + name;
}

public String echo(String text) {
return text;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,11 @@

import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.extension.ExtensionLoader;
import org.apache.dubbo.rpc.Exporter;
import org.apache.dubbo.rpc.Protocol;
import org.apache.dubbo.rpc.ProxyFactory;
import org.apache.dubbo.rpc.RpcException;
import org.apache.dubbo.rpc.*;
import org.apache.dubbo.rpc.service.EchoService;

import org.apache.dubbo.rpc.service.GenericService;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;

Expand Down Expand Up @@ -115,6 +114,19 @@ public void testRmiProtocol_echoService() throws Exception {
rpcExporter.unexport();
}

@Test
public void testGenericInvoke() {
DemoService service = new DemoServiceImpl();
URL url = URL.valueOf("rmi://127.0.0.1:9003/" + DemoService.class.getName() + "?release=2.7.0");
Exporter<DemoService> exporter = protocol.export(proxy.getInvoker(service, DemoService.class, url));
Invoker<GenericService> invoker = protocol.refer(GenericService.class, url);
GenericService client = proxy.getProxy(invoker, true);
String result = (String) client.$invoke("sayHi", new String[]{"java.lang.String"}, new Object[]{"haha"});
Assertions.assertEquals("Hi, haha", result);
invoker.destroy();
exporter.unexport();
}

public static interface NonStdRmiInterface {
void bark();
}
Expand Down

0 comments on commit 4f4b147

Please sign in to comment.