in dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/GenericImplFilter.java [148:243]
public void onResponse(Result appResponse, Invoker<?> invoker, Invocation invocation) {
String generic = invoker.getUrl().getParameter(GENERIC_KEY);
String methodName = invocation.getMethodName();
Class<?>[] parameterTypes = invocation.getParameterTypes();
Object genericImplMarker = invocation.get(GENERIC_IMPL_MARKER);
if (genericImplMarker != null && (boolean) invocation.get(GENERIC_IMPL_MARKER)) {
if (!appResponse.hasException()) {
Object value = appResponse.getValue();
try {
Class<?> invokerInterface = invoker.getInterface();
if (!$INVOKE.equals(methodName)
&& !$INVOKE_ASYNC.equals(methodName)
&& invokerInterface.isAssignableFrom(GenericService.class)) {
try {
// find the real interface from url
String realInterface = invoker.getUrl().getParameter(Constants.INTERFACE);
invokerInterface = ReflectUtils.forName(realInterface);
} catch (Exception e) {
// ignore
}
}
Method method = invokerInterface.getMethod(methodName, parameterTypes);
if (ProtocolUtils.isBeanGenericSerialization(generic)) {
if (value == null) {
appResponse.setValue(value);
} else if (value instanceof JavaBeanDescriptor) {
appResponse.setValue(JavaBeanSerializeUtil.deserialize((JavaBeanDescriptor) value));
} else {
throw new RpcException("The type of result value is "
+ value.getClass().getName() + " other than " + JavaBeanDescriptor.class.getName()
+ ", and the result is " + value);
}
} else {
Type[] types = ReflectUtils.getReturnTypes(method);
appResponse.setValue(PojoUtils.realize(value, (Class<?>) types[0], types[1]));
}
} catch (NoSuchMethodException e) {
throw new RpcException(e.getMessage(), e);
}
} else if (Dubbo2CompactUtils.isEnabled()
&& Dubbo2GenericExceptionUtils.isGenericExceptionClassLoaded()
&& Dubbo2GenericExceptionUtils.getGenericExceptionClass()
.isAssignableFrom(appResponse.getException().getClass())) {
// TODO we should cast if is apache GenericException or not?
org.apache.dubbo.rpc.service.GenericException exception =
(org.apache.dubbo.rpc.service.GenericException) appResponse.getException();
try {
String className = exception.getExceptionClass();
DefaultSerializeClassChecker classChecker = moduleModel
.getApplicationModel()
.getFrameworkModel()
.getBeanFactory()
.getBean(DefaultSerializeClassChecker.class);
Class<?> clazz =
classChecker.loadClass(Thread.currentThread().getContextClassLoader(), className);
Throwable targetException = null;
Throwable lastException = null;
try {
targetException =
(Throwable) clazz.getDeclaredConstructor().newInstance();
} catch (Throwable e) {
lastException = e;
for (Constructor<?> constructor : clazz.getConstructors()) {
try {
targetException = (Throwable)
constructor.newInstance(new Object[constructor.getParameterTypes().length]);
break;
} catch (Throwable e1) {
lastException = e1;
}
}
}
if (targetException != null) {
try {
Field field = Throwable.class.getDeclaredField("detailMessage");
if (!field.isAccessible()) {
field.setAccessible(true);
}
field.set(targetException, exception.getExceptionMessage());
} catch (Throwable e) {
logger.warn(COMMON_REFLECTIVE_OPERATION_FAILED, "", "", e.getMessage(), e);
}
appResponse.setException(targetException);
} else if (lastException != null) {
throw lastException;
}
} catch (Throwable e) {
throw new RpcException(
"Can not deserialize exception " + exception.getExceptionClass() + ", message: "
+ exception.getExceptionMessage(),
e);
}
}
}
}