dubbo 协议层源码解析 数据转换序列化失败
2019-07-22 本文已影响0人
语落心生
今天遇到了一个业务异常,实体类中的属性无法被反序列化成需要的相应的对象
2019-07-22 17:58:29,394 WARN [DecodeableRpcInvocation.java:112] : [DUBBO] Decode argument failed: com.zoe.base.healthservice.api.po.healthmanager.CfgDoctorWorkTimePO.startTime: java.sql.Time cannot be assigned from null, dubbo version: 2.5.3, current host: 172.16.36.42
com.alibaba.com.caucho.hessian.io.HessianFieldException: com.zoe.base.healthservice.api.po.healthmanager.CfgDoctorWorkTimePO.startTime: java.sql.Time cannot be assigned from null
at com.alibaba.com.caucho.hessian.io.JavaDeserializer.logDeserializeError(JavaDeserializer.java:677)
at com.alibaba.com.caucho.hessian.io.JavaDeserializer$SqlTimeFieldDeserializer.deserialize(JavaDeserializer.java:656)
at com.alibaba.com.caucho.hessian.io.JavaDeserializer.readObject(JavaDeserializer.java:233)
at com.alibaba.com.caucho.hessian.io.JavaDeserializer.readObject(JavaDeserializer.java:157)
at com.alibaba.com.caucho.hessian.io.Hessian2Input.readObjectInstance(Hessian2Input.java:2067)
at com.alibaba.com.caucho.hessian.io.Hessian2Input.readObject(Hessian2Input.java:1592)
at com.alibaba.com.caucho.hessian.io.Hessian2Input.readObject(Hessian2Input.java:1576)
at com.alibaba.dubbo.common.serialize.support.hessian.Hessian2ObjectInput.readObject(Hessian2ObjectInput.java:94)
at com.alibaba.dubbo.rpc.protocol.dubbo.DecodeableRpcInvocation.decode(DecodeableRpcInvocation.java:109)
at com.alibaba.dubbo.rpc.protocol.dubbo.DecodeableRpcInvocation.decode(DecodeableRpcInvocation.java:71)
at com.alibaba.dubbo.rpc.protocol.dubbo.DubboCodec.decodeBody(DubboCodec.java:137)
at com.alibaba.dubbo.remoting.exchange.codec.ExchangeCodec.decode(ExchangeCodec.java:126)
at com.alibaba.dubbo.remoting.exchange.codec.ExchangeCodec.decode(ExchangeCodec.java:87)
at com.alibaba.dubbo.rpc.protocol.dubbo.DubboCountCodec.decode(DubboCountCodec.java:46)
at com.alibaba.dubbo.remoting.transport.netty.NettyCodecAdapter$InternalDecoder.messageReceived(NettyCodecAdapter.java:134)
at org.jboss.netty.channel.SimpleChannelUpstreamHandler.handleUpstream(SimpleChannelUpstreamHandler.java:80)
at org.jboss.netty.channel.DefaultChannelPipeline.sendUpstream(DefaultChannelPipeline.java:564)
at org.jboss.netty.channel.DefaultChannelPipeline.sendUpstream(DefaultChannelPipeline.java:559)
at org.jboss.netty.channel.Channels.fireMessageReceived(Channels.java:274)
at org.jboss.netty.channel.Channels.fireMessageReceived(Channels.java:261)
at org.jboss.netty.channel.socket.nio.NioWorker.read(NioWorker.java:349)
at org.jboss.netty.channel.socket.nio.NioWorker.processSelectedKeys(NioWorker.java:280)
at org.jboss.netty.channel.socket.nio.NioWorker.run(NioWorker.java:200)
at org.jboss.netty.util.ThreadRenamingRunnable.run(ThreadRenamingRunnable.java:108)
at org.jboss.netty.util.internal.DeadLockProofWorker$1.run(DeadLockProofWorker.java:44)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.NullPointerException
at com.alibaba.com.caucho.hessian.io.JavaDeserializer$SqlTimeFieldDeserializer.deserialize(JavaDeserializer.java:652)
... 26 more
事故现场还原
A模块调B模块的方法
first.pngpackage com.zoe.base.healthservice.api.po.healthmanager;
import java.sql.Time;
import java.util.*;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
import org.hibernate.annotations.GenericGenerator;
import com.zoe.common.entity.BaseEntity;
/**
* @date 2019/02/27
*/
@Entity
@Table(name = "cfg_doctor_work_time")
public class CfgDoctorWorkTimePO extends BaseEntity<CfgDoctorWorkTimePO>{
/**
*主键id
*/
@Id
@GeneratedValue(generator = "system-uuid")
@GenericGenerator(name = "system-uuid", strategy = "uuid")
@Column(name = "id")
private String id;
/**
*医生id
*/
@Column(name = "doctor_id")
private String doctorId;
/**
*业务类型(胎心:fetal_heart)
*/
@Column(name = "business_type")
private String businessType;
/**
*开始时间
*/
@Column(name = "start_time")
private Time startTime;
/**
*结束时间
*/
@Column(name = "end_time")
private Time endTime;
/**
*创建时间
*/
@Column(name = "create_time")
private Date createTime;
/**
*
*/
@Column(name = "create_user")
private String createUser;
/**
*更新时间
*/
@Column(name = "update_time")
private Date updateTime;
/**
*更新人
*/
@Column(name = "update_user")
private String updateUser;
/**
*
*/
@Column(name = "valid_flag")
private Integer validFlag;
@Override
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getDoctorId() {
return doctorId;
}
public void setDoctorId(String doctorId) {
this.doctorId = doctorId;
}
public String getBusinessType() {
return businessType;
}
public void setBusinessType(String businessType) {
this.businessType = businessType;
}
public Time getStartTime() {
return startTime;
}
public void setStartTime(Time startTime) {
this.startTime = startTime;
}
public Time getEndTime() {
return endTime;
}
public void setEndTime(Time endTime) {
this.endTime = endTime;
}
public String getStartTimeStr(){
Time startTime = this.getStartTime();
return startTime.toString();
}
public String getEndTimeStr(){
Time endTime = this.getEndTime();
return endTime.toString();
}
public Date getCreateTime() {
return createTime;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
public String getCreateUser() {
return createUser;
}
public void setCreateUser(String createUser) {
this.createUser = createUser;
}
public Date getUpdateTime() {
return updateTime;
}
public void setUpdateTime(Date updateTime) {
this.updateTime = updateTime;
}
public String getUpdateUser() {
return updateUser;
}
public void setUpdateUser(String updateUser) {
this.updateUser = updateUser;
}
public Integer getValidFlag() {
return validFlag;
}
public void setValidFlag(Integer validFlag) {
this.validFlag = validFlag;
}
}
- 实体类继承Serilize示意图
调用B模块后的执行结果
paramVo.png为什么会出现这样的结果
根据异常我们定位到dubbo的源码
mark1.png当我们反序列化之后,使用的是Hessian协议,且当反序列化的值为null的时候抛出异常
进一步回溯堆栈,看之前的报错
mark2.png这是一个反序列化时间的类
static class SqlTimeFieldDeserializer extends JavaDeserializer.FieldDeserializer {
private final Field _field;
SqlTimeFieldDeserializer(Field field) {
this._field = field;
}
void deserialize(AbstractHessianInput in, Object obj) throws IOException {
Time value = null;
try {
java.util.Date date = (java.util.Date)in.readObject();
value = new Time(date.getTime());
this._field.set(obj, value);
} catch (Exception var5) {
JavaDeserializer.logDeserializeError(this._field, obj, value, var5);
}
}
}
他会将所有hessin协议传进来的Time对象都转成Date对象处理,所以传进来之前我们要对其进行初始化处理