[2.7.16] dubbo协议反序列化mongo-java-driver 4.2.0以上版本ObjectId失败
- Dominant language
- Java
- Stars
- 41.6k
- Forks
- 26.4k
- Avg merge
- 15h 13m
- Merged PRs (30d)
- 4
Description
- [x] I have searched the [issues](https://github.com/apache/dubbo/issues) of this repository and believe that this is not a duplicate.
### Environment
* Dubbo version: 2.7.16
* Operating System version: windows 11
* Java version: 1.8
### Steps to reproduce this issue
在mongo-java-driver 4.2.0+版本中,ObjectId序列化方式发生变化
https://github.com/mongodb/mongo-java-driver/commit/57a20d675e0cdd1ae378b1b9ce969612953546a6
通过Hessian2Output写出到provider端时,Hessian2Input解析到的类型是org.bson.types.ObjectId.SerializationProxy
在调用com.alibaba.com.caucho.hessian.io.JavaDeserializer#readObject(com.alibaba.com.caucho.hessian.io.AbstractHessianInput, java.lang.String[])方法时,会试图利用反射构造其实例,调用构造方法org.bson.types.ObjectId.SerializationProxy#SerializationProxy时会报空指针
```
SerializationProxy(final ObjectId objectId) {
bytes = objectId.toByteArray();
}
```
类似的的可定义类
```
@ToString
public class TimeRecord implements Serializable {
private static final long serialVersionUID = 1L;
private final String timestamp;
public TimeRecord() {
this(System.currentTimeMillis());
}
public TimeRecord(final long timestamp) {
this.timestamp = String.valueOf(timestamp);
}
private long toLong() {
return Long.parseLong(timestamp);
}
private Object writeReplace() {
return new SerializationProxy(this);
}
private void readObject(final ObjectInputStream stream) throws InvalidObjectException {
throw new InvalidObjectException("Proxy required");
}
public static class SerializationProxy implements Serializable {
private static final long serialVersionUID = 1L;
private final long number;
SerializationProxy(final TimeRecord o) {
number = o.toLong();
}
private Object readResolve() {
return new TimeRecord(number);
}
}
}
```
在consumer端任意service方法调用前附加隐式参数`RpcContext.getClientAttachment().setObjectAttachment("haha", new TimeRecord());`即可复现问题
### Expected Behavior
希望能正确反序列化ObjectId,以便兼容更高版本的mongodb server;
或者是否可提供扩展接口,方便用户自定义特殊类型的bean的序列化方式
另外 Exception的message组织是否有问题,好多重复信息
### Actual Behavior
exception trace:
```
org.apache.dubbo.rpc.RpcException: Failed to invoke the method sayHello in the service com.example.api.DemoService. Tried 3 times of the providers [192.168.199.1:30880] (1/1) from the registry 127.0.0.1:2181 on the consumer 192.168.199.1 using the dubbo version 3.0.6. Last error is: Failed to invoke remote method: sayHello, provider: dubbo://192.168.199.1:30880/com.example.api.DemoService?application=provider&background=false&category=providers,configurators,routers&check=false&deprecated=false&dubbo=2.0.2&interface=com.example.api.DemoService&metadata-type=remote&pid=24752&qos.enable=false&release=3.0.6&side=consumer&sticky=false, cause: org.apache.dubbo.remoting.RemotingException: Fail to decode request due to: com.alibaba.com.caucho.hessian.io.HessianProtocolException: 'com.example.Application$TimeRecord$SerializationProxy' could not be instantiated
com.alibaba.com.caucho.hessian.io.HessianProtocolException: 'com.example.Application$TimeRecord$SerializationProxy' could not be instantiated
at com.alibaba.com.caucho.hessian.io.JavaDeserializer.instantiate(JavaDeserializer.java:317)
at com.alibaba.com.caucho.hessian.io.JavaDeserializer.readObject(JavaDeserializer.java:202)
at com.alibaba.com.caucho.hessian.io.SerializerFactory.readObject(SerializerFactory.java:548)
at com.alibaba.com.caucho.hessian.io.Hessian2Input.readObjectInstance(Hessian2Input.java:2850)
at com.alibaba.com.caucho.hessian.io.Hessian2Input.readObject(Hessian2Input.java:2773)
at com.alibaba.com.caucho.hessian.io.Hessian2Input.readObject(Hessian2Input.java:2308)
at com.alibaba.com.caucho.hessian.io.Hessian2Input.readObject(Hessian2Input.java:2747)
at com.alibaba.com.caucho.hessian.io.Hessian2Input.readObject(Hessian2Input.java:2308)
at com.alibaba.com.caucho.hessian.io.MapDeserializer.doReadMap(MapDeserializer.java:146)
at com.alibaba.com.caucho.hessian.io.MapDeserializer.readMap(MapDeserializer.java:126)
at com.alibaba.com.caucho.hessian.io.Hessian2Input.readObject(Hessian2Input.java:2123)
at com.alibaba.com.caucho.hessian.io.Hessian2Input.readObject(Hessian2Input.java:2104)
at org.apache.dubbo.common.serialize.hessian2.Hessian2ObjectInput.readObject(Hessian2ObjectInput.java:102)
at org.apache.dubbo.common.serialize.ObjectInput.readAttachments(ObjectInput.java:87)
at org.apache.dubbo.rpc.protocol.dubbo.DecodeableRpcInvocation.decode(DecodeableRpcInvocation.java:224)
at org.apache.dubbo.rpc.protocol.dubbo.DecodeableRpcInvocation.decode(DecodeableRpcInvocation.java:93)
at org.apache.dubbo.remoting.transport.DecodeHandler.decode(DecodeHandler.java:57)
at org.apache.dubbo.remoting.transport.DecodeHandler.received(DecodeHandler.java:44)
at org.apache.dubbo.remoting.transport.dispatcher.ChannelEventRunnable.run(ChannelEventRunnable.java:57)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at org.apache.dubbo.common.threadlocal.InternalRunnable.run(InternalRunnable.java:41)
at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.reflect.InvocationTargetException
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at com.alibaba.com.caucho.hessian.io.JavaDeserializer.instantiate(JavaDeserializer.java:313)
... 22 more
Caused by: java.lang.NullPointerException
at com.example.Application$TimeRecord.access$000(Application.java:55)
at com.example.Application$TimeRecord$SerializationProxy.(Application.java:87)
... 27 more
at org.apache.dubbo.rpc.cluster.support.FailoverClusterInvoker.doInvoke(FailoverClusterInvoker.java:114)
at org.apache.dubbo.rpc.cluster.support.AbstractClusterInvoker.invoke(AbstractClusterInvoker.java:340)
at org.apache.dubbo.rpc.cluster.router.RouterSnapshotFilter.invoke(RouterSnapshotFilter.java:46)
at org.apache.dubbo.rpc.cluster.filter.FilterChainBuilder$CopyOfFilterChainNode.invoke(FilterChainBuilder.java:321)
at org.apache.dubbo.monitor.support.MonitorFilter.invoke(MonitorFilter.java:99)
at org.apache.dubbo.rpc.cluster.filter.FilterChainBuilder$CopyOfFilterChainNode.invoke(FilterChainBuilder.java:321)
at org.apache.dubbo.rpc.protocol.dubbo.filter.FutureFilter.invoke(FutureFilter.java:51)
at org.apache.dubbo.rpc.cluster.filter.FilterChainBuilder$CopyOfFilterChainNode.invoke(FilterChainBuilder.java:321)
at org.apache.dubbo.rpc.cluster.filter.support.ConsumerContextFilter.invoke(ConsumerContextFilter.java:108)
at org.apache.dubbo.rpc.cluster.filter.FilterChainBuilder$CopyOfFilterChainNode.invoke(FilterChainBuilder.java:321)
at org.apache.dubbo.rpc.cluster.filter.FilterChainBuilder$CallbackRegistrationInvoker.invoke(FilterChainBuilder.java:193)
at org.apache.dubbo.rpc.cluster.support.wrapper.AbstractCluster$ClusterFilterInvoker.invoke(AbstractCluster.java:92)
at org.apache.dubbo.rpc.cluster.support.wrapper.MockClusterInvoker.invoke(MockClusterInvoker.java:97)
at org.apache.dubbo.registry.client.migration.MigrationInvoker.invoke(MigrationInvoker.java:280)
at org.apache.dubbo.rpc.proxy.InvokerInvocationHandler.invoke(InvokerInvocationHandler.java:97)
at com.example.api.DemoServiceDubboProxy0.sayHello(DemoServiceDubboProxy0.java)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:208)
at com.sun.proxy.$Proxy56.sayHello(Unknown Source)
at com.example.Application.main(Application.java:47)
Caused by: java.util.concurrent.ExecutionException: org.apache.dubbo.remoting.RemotingException: Fail to decode request due to: com.alibaba.com.caucho.hessian.io.HessianProtocolException: 'com.example.Application$TimeRecord$SerializationProxy' could not be instantiated
com.alibaba.com.caucho.hessian.io.HessianProtocolException: 'com.example.Application$TimeRecord$SerializationProxy' could not be instantiated
at com.alibaba.com.caucho.hessian.io.JavaDeserializer.instantiate(JavaDeserializer.java:317)
at com.alibaba.com.caucho.hessian.io.JavaDeserializer.readObject(JavaDeserializer.java:202)
at com.alibaba.com.caucho.hessian.io.SerializerFactory.readObject(SerializerFactory.java:548)
at com.alibaba.com.caucho.hessian.io.Hessian2Input.readObjectInstance(Hessian2Input.java:2850)
at com.alibaba.com.caucho.hessian.io.Hessian2Input.readObject(Hessian2Input.java:2773)
at com.alibaba.com.caucho.hessian.io.Hessian2Input.readObject(Hessian2Input.java:2308)
at com.alibaba.com.caucho.hessian.io.Hessian2Input.readObject(Hessian2Input.java:2747)
at com.alibaba.com.caucho.hessian.io.Hessian2Input.readObject(Hessian2Input.java:2308)
at com.alibaba.com.caucho.hessian.io.MapDeserializer.doReadMap(MapDeserializer.java:146)
at com.alibaba.com.caucho.hessian.io.MapDeserializer.readMap(MapDeserializer.java:126)
at com.alibaba.com.caucho.hessian.io.Hessian2Input.readObject(Hessian2Input.java:2123)
at com.alibaba.com.caucho.hessian.io.Hessian2Input.readObject(Hessian2Input.java:2104)
at org.apache.dubbo.common.serialize.hessian2.Hessian2ObjectInput.readObject(Hessian2ObjectInput.java:102)
at org.apache.dubbo.common.serialize.ObjectInput.readAttachments(ObjectInput.java:87)
at org.apache.dubbo.rpc.protocol.dubbo.DecodeableRpcInvocation.decode(DecodeableRpcInvocation.java:224)
at org.apache.dubbo.rpc.protocol.dubbo.DecodeableRpcInvocation.decode(DecodeableRpcInvocation.java:93)
at org.apache.dubbo.remoting.transport.DecodeHandler.decode(DecodeHandler.java:57)
at org.apache.dubbo.remoting.transport.DecodeHandler.received(DecodeHandler.java:44)
at org.apache.dubbo.remoting.transport.dispatcher.ChannelEventRunnable.run(ChannelEventRunnable.java:57)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at org.apache.dubbo.common.threadlocal.InternalRunnable.run(InternalRunnable.java:41)
at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.reflect.InvocationTargetException
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at com.alibaba.com.caucho.hessian.io.JavaDeserializer.instantiate(JavaDeserializer.java:313)
... 22 more
Caused by: java.lang.NullPointerException
at com.example.Application$TimeRecord.access$000(Application.java:55)
at com.example.Application$TimeRecord$SerializationProxy.(Application.java:87)
... 27 more
at java.util.concurrent.CompletableFuture.reportGet(CompletableFuture.java:357)
at java.util.concurrent.CompletableFuture.get(CompletableFuture.java:1915)
at org.apache.dubbo.rpc.AsyncRpcResult.get(AsyncRpcResult.java:195)
at org.apache.dubbo.rpc.protocol.AbstractInvoker.waitForResultIfSync(AbstractInvoker.java:264)
at org.apache.dubbo.rpc.protocol.AbstractInvoker.invoke(AbstractInvoker.java:185)
at org.apache.dubbo.rpc.listener.ListenerInvokerWrapper.invoke(ListenerInvokerWrapper.java:78)
at org.apache.dubbo.rpc.cluster.support.AbstractClusterInvoker.invokeWithContext(AbstractClusterInvoker.java:378)
at org.apache.dubbo.rpc.cluster.support.FailoverClusterInvoker.doInvoke(FailoverClusterInvoker.java:80)
... 23 more
Caused by: org.apache.dubbo.remoting.RemotingException: Fail to decode request due to: com.alibaba.com.caucho.hessian.io.HessianProtocolException: 'com.example.Application$TimeRecord$SerializationProxy' could not be instantiated
com.alibaba.com.caucho.hessian.io.HessianProtocolException: 'com.example.Application$TimeRecord$SerializationProxy' could not be instantiated
at com.alibaba.com.caucho.hessian.io.JavaDeserializer.instantiate(JavaDeserializer.java:317)
at com.alibaba.com.caucho.hessian.io.JavaDeserializer.readObject(JavaDeserializer.java:202)
at com.alibaba.com.caucho.hessian.io.SerializerFactory.readObject(SerializerFactory.java:548)
at com.alibaba.com.caucho.hessian.io.Hessian2Input.readObjectInstance(Hessian2Input.java:2850)
at com.alibaba.com.caucho.hessian.io.Hessian2Input.readObject(Hessian2Input.java:2773)
at com.alibaba.com.caucho.hessian.io.Hessian2Input.readObject(Hessian2Input.java:2308)
at com.alibaba.com.caucho.hessian.io.Hessian2Input.readObject(Hessian2Input.java:2747)
at com.alibaba.com.caucho.hessian.io.Hessian2Input.readObject(Hessian2Input.java:2308)
at com.alibaba.com.caucho.hessian.io.MapDeserializer.doReadMap(MapDeserializer.java:146)
at com.alibaba.com.caucho.hessian.io.MapDeserializer.readMap(MapDeserializer.java:126)
at com.alibaba.com.caucho.hessian.io.Hessian2Input.readObject(Hessian2Input.java:2123)
at com.alibaba.com.caucho.hessian.io.Hessian2Input.readObject(Hessian2Input.java:2104)
at org.apache.dubbo.common.serialize.hessian2.Hessian2ObjectInput.readObject(Hessian2ObjectInput.java:102)
at org.apache.dubbo.common.serialize.ObjectInput.readAttachments(ObjectInput.java:87)
at org.apache.dubbo.rpc.protocol.dubbo.DecodeableRpcInvocation.decode(DecodeableRpcInvocation.java:224)
at org.apache.dubbo.rpc.protocol.dubbo.DecodeableRpcInvocation.decode(DecodeableRpcInvocation.java:93)
at org.apache.dubbo.remoting.transport.DecodeHandler.decode(DecodeHandler.java:57)
at org.apache.dubbo.remoting.transport.DecodeHandler.received(DecodeHandler.java:44)
at org.apache.dubbo.remoting.transport.dispatcher.ChannelEventRunnable.run(ChannelEventRunnable.java:57)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at org.apache.dubbo.common.threadlocal.InternalRunnable.run(InternalRunnable.java:41)
at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.reflect.InvocationTargetException
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at com.alibaba.com.caucho.hessian.io.JavaDeserializer.instantiate(JavaDeserializer.java:313)
... 22 more
Caused by: java.lang.NullPointerException
at com.example.Application$TimeRecord.access$000(Application.java:55)
at com.example.Application$TimeRecord$SerializationProxy.(Application.java:87)
... 27 more
at org.apache.dubbo.remoting.exchange.support.DefaultFuture.doReceived(DefaultFuture.java:214)
at org.apache.dubbo.remoting.exchange.support.DefaultFuture.received(DefaultFuture.java:176)
at org.apache.dubbo.remoting.exchange.support.DefaultFuture.received(DefaultFuture.java:164)
at org.apache.dubbo.remoting.exchange.support.header.HeaderExchangeHandler.handleResponse(HeaderExchangeHandler.java:60)
at org.apache.dubbo.remoting.exchange.support.header.HeaderExchangeHandler.received(HeaderExchangeHandler.java:181)
at org.apache.dubbo.remoting.transport.DecodeHandler.received(DecodeHandler.java:51)
at org.apache.dubbo.remoting.transport.dispatcher.ChannelEventRunnable.run(ChannelEventRunnable.java:57)
at org.apache.dubbo.common.threadpool.ThreadlessExecutor$RunnableWrapper.run(ThreadlessExecutor.java:184)
at org.apache.dubbo.common.threadpool.ThreadlessExecutor.waitAndDrain(ThreadlessExecutor.java:103)
at org.apache.dubbo.rpc.AsyncRpcResult.get(AsyncRpcResult.java:193)
... 28 more
```
Contributor guide
Research direction
Start with the reported Dubbo Hessian2 path in Hessian2ObjectInput.readObject, ObjectInput.readAttachments, and DecodeableRpcInvocation.decode, then compare behavior with mongo-java-driver 4.2.0+ ObjectId.SerializationProxy. Reproduce using the described RpcContext client attachment and the TimeRecord proxy example. Done means ObjectId and equivalent serialization-proxy objects deserialize correctly, or a documented extension point is provided.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java, mongodb
- Domain
- distributed-systems
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100