Skip to content

Commit

Permalink
DUBBO-627 使用 JavaBeanSerializationUtil 实现泛化调用或泛化实现
Browse files Browse the repository at this point in the history
  • Loading branch information
kimi committed Dec 26, 2012
1 parent 0e3b007 commit 645152a
Show file tree
Hide file tree
Showing 6 changed files with 197 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -577,6 +577,8 @@ public class Constants {

public static final String GENERIC_SERIALIZATION_DEFAULT = "true";

public static final String GENERIC_SERIALIZATION_BEAN = "bean";

/*
* private Constants(){ }
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,12 +61,14 @@ public final class JavaBeanDescriptor implements Serializable, Iterable<Map.Entr
*/
private static final int TYPE_MIN = TYPE_CLASS;

private final String className;
private String className;

private final int type;
private int type;

private Map<Object, Object> properties = new LinkedHashMap<Object, Object>();

public JavaBeanDescriptor() {}

public JavaBeanDescriptor(String className, int type) {
notEmpty(className, "class name is empty");
if (!isValidType(type)) {
Expand All @@ -79,6 +81,14 @@ public JavaBeanDescriptor(String className, int type) {
this.type = type;
}

public void setClassName(String className) {
this.className = className;
}

public void setType(int type) {
this.type = type;
}

public boolean isClassType() {
return TYPE_CLASS == type;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,18 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;

import org.junit.Assert;
import org.junit.Test;

import com.alibaba.dubbo.common.Constants;
import com.alibaba.dubbo.common.beanutil.JavaBeanAccessor;
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.Serialization;
import com.alibaba.dubbo.common.utils.ReflectUtils;
import com.alibaba.dubbo.config.api.DemoException;
import com.alibaba.dubbo.config.api.DemoService;
import com.alibaba.dubbo.config.api.User;
Expand All @@ -37,11 +42,11 @@

/**
* GenericServiceTest
*
*
* @author william.liangf
*/
public class GenericServiceTest {

@Test
public void testGenericServiceException() {
ServiceConfig<GenericService> service = new ServiceConfig<GenericService>();
Expand All @@ -50,8 +55,9 @@ public void testGenericServiceException() {
service.setProtocol(new ProtocolConfig("dubbo", 29581));
service.setInterface(DemoService.class.getName());
service.setRef(new GenericService() {

public Object $invoke(String method, String[] parameterTypes, Object[] args)
throws GenericException {
throws GenericException {
if ("sayName".equals(method)) {
return "Generic " + args[0];
}
Expand Down Expand Up @@ -117,7 +123,7 @@ public void testGenericReferenceException() {
user.put("class", "com.alibaba.dubbo.config.api.User");
user.put("name", "actual.provider");
users.add(user);
users = (List<Map<String, Object>>) genericService.$invoke("getUsers", new String[] {List.class.getName()}, new Object[] {users});
users = (List<Map<String, Object>>) genericService.$invoke("getUsers", new String[]{List.class.getName()}, new Object[]{users});
Assert.assertEquals(1, users.size());
Assert.assertEquals("actual.provider", users.get(0).get("name"));
} finally {
Expand Down Expand Up @@ -196,4 +202,111 @@ public void testGenericSerializationJava() throws Exception {
}
}

@Test
public void testGenericInvokeWithBeanSerialization() throws Exception {
ServiceConfig<DemoService> service = new ServiceConfig<DemoService>();
service.setApplication(new ApplicationConfig("bean-provider"));
service.setInterface(DemoService.class);
service.setRegistry(new RegistryConfig("N/A"));
DemoServiceImpl impl = new DemoServiceImpl();
service.setRef(impl);
service.setProtocol(new ProtocolConfig("dubbo", 29581));
service.export();
ReferenceConfig<GenericService> reference = null;
try {
reference = new ReferenceConfig<GenericService>();
reference.setApplication(new ApplicationConfig("bean-consumer"));
reference.setInterface(DemoService.class);
reference.setUrl("dubbo://127.0.0.1:29581?scope=remote");
reference.setGeneric(Constants.GENERIC_SERIALIZATION_BEAN);
GenericService genericService = reference.get();
User user = new User();
user.setName("zhangsan");
List<User> users = new ArrayList<User>();
users.add(user);
Object result = genericService.$invoke("getUsers", new String[]{ReflectUtils.getName(List.class)}, new Object[]{JavaBeanSerializeUtil.serialize(users, JavaBeanAccessor.METHOD)});
Assert.assertTrue(result instanceof JavaBeanDescriptor);
JavaBeanDescriptor descriptor = (JavaBeanDescriptor) result;
Assert.assertTrue(descriptor.isCollectionType());
Assert.assertEquals(1, descriptor.propertySize());
descriptor = (JavaBeanDescriptor) descriptor.getProperty(0);
Assert.assertTrue(descriptor.isBeanType());
Assert.assertEquals(user.getName(), ((JavaBeanDescriptor) descriptor.getProperty("name")).getPrimitiveProperty());
} finally {
if (reference != null) {
reference.destroy();
}
service.unexport();
}
}

protected static class GenericParameter {

String method;

String[] parameterTypes;

Object[] arguments;
}

@Test
public void testGenericImplementationWithBeanSerialization() throws Exception {
final AtomicReference reference = new AtomicReference();
ServiceConfig<GenericService> service = new ServiceConfig<GenericService>();
service.setApplication(new ApplicationConfig("bean-provider"));
service.setRegistry(new RegistryConfig("N/A"));
service.setProtocol(new ProtocolConfig("dubbo", 29581));
service.setInterface(DemoService.class.getName());
service.setRef(new GenericService() {

public Object $invoke(String method, String[] parameterTypes, Object[] args) throws GenericException {
if ("getUsers".equals(method)) {
GenericParameter arg = new GenericParameter();
arg.method = method;
arg.parameterTypes = parameterTypes;
arg.arguments = args;
reference.set(arg);
return args[0];
}
return args;
}
});
service.export();
ReferenceConfig<DemoService> ref = null;
try {
ref = new ReferenceConfig<DemoService>();
ref.setApplication(new ApplicationConfig("bean-consumer"));
ref.setInterface(DemoService.class);
ref.setUrl("dubbo://127.0.0.1:29581?scope=remote&generic=bean");
DemoService demoService = ref.get();
User user = new User();
user.setName("zhangsan");
List<User> users = new ArrayList<User>();
users.add(user);
List<User> result = demoService.getUsers(users);
Assert.assertEquals(users.size(), result.size());
Assert.assertEquals(user.getName(), result.get(0).getName());

GenericParameter gp = (GenericParameter)reference.get();
Assert.assertEquals("getUsers", gp.method);
Assert.assertEquals(1, gp.parameterTypes.length);
Assert.assertEquals(ReflectUtils.getName(List.class), gp.parameterTypes[0]);
Assert.assertEquals(1, gp.arguments.length);
Assert.assertTrue(gp.arguments[0] instanceof JavaBeanDescriptor);
JavaBeanDescriptor descriptor = (JavaBeanDescriptor)gp.arguments[0];
Assert.assertTrue(descriptor.isCollectionType());
Assert.assertEquals(ArrayList.class.getName(), descriptor.getClassName());
Assert.assertEquals(1, descriptor.propertySize());
descriptor = (JavaBeanDescriptor)descriptor.getProperty(0);
Assert.assertTrue(descriptor.isBeanType());
Assert.assertEquals(User.class.getName(), descriptor.getClassName());
Assert.assertEquals(user.getName(), ((JavaBeanDescriptor)descriptor.getProperty("name")).getPrimitiveProperty());
} finally {
if (ref != null) {
ref.destroy();
}
service.unexport();
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@
import java.lang.reflect.Method;

import com.alibaba.dubbo.common.Constants;
import com.alibaba.dubbo.common.beanutil.JavaBeanAccessor;
import com.alibaba.dubbo.common.beanutil.JavaBeanDescriptor;
import com.alibaba.dubbo.common.beanutil.JavaBeanSerializeUtil;
import com.alibaba.dubbo.common.extension.Activate;
import com.alibaba.dubbo.common.extension.ExtensionLoader;
import com.alibaba.dubbo.common.io.UnsafeByteArrayInputStream;
Expand Down Expand Up @@ -84,6 +87,21 @@ public Result invoke(Invoker<?> invoker, Invocation inv) throws RpcException {
.append(args[i].getClass()).toString());
}
}
} else if (ProtocolUtils.isBeanGenericSerialization(generic)) {
for(int i = 0; i < args.length; i++) {
if (args[i] instanceof JavaBeanDescriptor) {
args[i] = JavaBeanSerializeUtil.deserialize((JavaBeanDescriptor)args[i]);
} else {
throw new RpcException(
new StringBuilder(32)
.append("Generic serialization [")
.append(Constants.GENERIC_SERIALIZATION_BEAN)
.append("] only support message type ")
.append(JavaBeanDescriptor.class.getName())
.append(" and your message type is ")
.append(args[i].getClass().getName()).toString());
}
}
}
Result result = invoker.invoke(new RpcInvocation(method, args, inv.getAttachments()));
if (result.hasException()
Expand All @@ -100,6 +118,8 @@ public Result invoke(Invoker<?> invoker, Invocation inv) throws RpcException {
} catch (IOException e) {
throw new RpcException("Serialize result failed.", e);
}
} else if (ProtocolUtils.isBeanGenericSerialization(generic)) {
return new RpcResult(JavaBeanSerializeUtil.serialize(result.getValue(), JavaBeanAccessor.METHOD));
} else {
return new RpcResult(PojoUtils.generalize(result.getValue()));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@
import java.lang.reflect.Method;

import com.alibaba.dubbo.common.Constants;
import com.alibaba.dubbo.common.beanutil.JavaBeanAccessor;
import com.alibaba.dubbo.common.beanutil.JavaBeanDescriptor;
import com.alibaba.dubbo.common.beanutil.JavaBeanSerializeUtil;
import com.alibaba.dubbo.common.extension.Activate;
import com.alibaba.dubbo.common.logger.Logger;
import com.alibaba.dubbo.common.logger.LoggerFactory;
Expand Down Expand Up @@ -61,7 +64,16 @@ public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcExcept
for (int i = 0; i < parameterTypes.length; i ++) {
types[i] = ReflectUtils.getName(parameterTypes[i]);
}
Object[] args = PojoUtils.generalize(arguments);

Object[] args;
if (ProtocolUtils.isBeanGenericSerialization(generic)) {
args = new Object[arguments.length];
for(int i = 0; i < arguments.length; i++) {
args[i] = JavaBeanSerializeUtil.serialize(arguments[i], JavaBeanAccessor.METHOD);
}
} else {
args = PojoUtils.generalize(arguments);
}

invocation2.setMethodName(Constants.$INVOKE);
invocation2.setParameterTypes(GENERIC_PARAMETER_TYPES);
Expand All @@ -72,7 +84,22 @@ public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcExcept
Object value = result.getValue();
try {
Method method = invoker.getInterface().getMethod(methodName, parameterTypes);
return new RpcResult(PojoUtils.realize(value, method.getReturnType(), method.getGenericReturnType()));
if (ProtocolUtils.isBeanGenericSerialization(generic)) {
if (value instanceof JavaBeanDescriptor) {
return new RpcResult(JavaBeanSerializeUtil.deserialize((JavaBeanDescriptor)value));
} else {
throw new RpcException(
new StringBuilder(64)
.append("The type of result value is ")
.append(value.getClass().getName())
.append(" other than ")
.append(JavaBeanDescriptor.class.getName())
.append(", and the result is ")
.append(value).toString());
}
} else {
return new RpcResult(PojoUtils.realize(value, method.getReturnType(), method.getGenericReturnType()));
}
} catch (NoSuchMethodException e) {
throw new RpcException(e.getMessage(), e);
}
Expand Down Expand Up @@ -122,12 +149,18 @@ public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcExcept
&& invocation.getArguments().length == 3
&& ProtocolUtils.isGeneric(generic)) {

Object[] args = (Object[]) invocation.getArguments()[2];
if (ProtocolUtils.isJavaGenericSerialization(generic)) {
Object[] args = (Object[]) invocation.getArguments()[2];

for (Object arg : args) {
if (!(byte[].class == arg.getClass())) {
error(arg.getClass().getName());
error(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());
}
}
}
Expand All @@ -138,15 +171,15 @@ public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcExcept
return invoker.invoke(invocation);
}

private void error(String type) throws RpcException {
private void error(String expected, String actual) throws RpcException {
throw new RpcException(
new StringBuilder(32)
.append("Generic serialization [")
.append(Constants.GENERIC_SERIALIZATION_NATIVE_JAVA)
.append("] only support message type ")
.append(byte[].class)
.append(expected)
.append(" and your message type is ")
.append(type).toString());
.append(actual).toString());
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ public static boolean isGeneric(String generic) {
return generic != null
&& !"".equals(generic)
&& (Constants.GENERIC_SERIALIZATION_DEFAULT.equalsIgnoreCase(generic) /* 正常的泛化调用 */
|| Constants.GENERIC_SERIALIZATION_NATIVE_JAVA.equalsIgnoreCase(generic)); /* 支持java序列化的流式泛化调用 */
|| Constants.GENERIC_SERIALIZATION_NATIVE_JAVA.equalsIgnoreCase(generic) /* 支持java序列化的流式泛化调用 */
|| Constants.GENERIC_SERIALIZATION_BEAN.equalsIgnoreCase(generic));
}

public static boolean isDefaultGenericSerialization(String generic) {
Expand All @@ -48,4 +49,8 @@ public static boolean isJavaGenericSerialization(String generic) {
return isGeneric(generic)
&& Constants.GENERIC_SERIALIZATION_NATIVE_JAVA.equalsIgnoreCase(generic);
}

public static boolean isBeanGenericSerialization(String generic) {
return isGeneric(generic) && Constants.GENERIC_SERIALIZATION_BEAN.equals(generic);
}
}

0 comments on commit 645152a

Please sign in to comment.