首页 > 编程语言 >java浅拷贝BeanUtils.copyProperties引发的RPC异常 | 京东物流技术团队

java浅拷贝BeanUtils.copyProperties引发的RPC异常 | 京东物流技术团队

时间:2023-12-27 14:34:06浏览次数:66  
标签:调用 java cargoInfo xxx RPC copyProperties 拷贝 BeanUtils

背景

近期参与了一个攻坚项目,前期因为其他流程原因,测试时间已经耽搁了好几天了,本以为已经解决了卡点,后续流程应该顺顺利利的,没想到 人在地铁上,bug从咚咚来~

没有任何修改的服务接口,抛出异常:

java.lang.ClassCastException: java.util.HashMap cannot be cast to cn.xxx.xxx.xxx.xxx.BatchInfo

排查过程

1、作为资深写bug的老司机,第一感觉是传参的报文格式有问题了,可以通过模拟报文排查。于是乎,在群里圈了服务提供方同学B看下,BG快速的用测试工具+本地debug的方式,验证了下报文格式,发现居然都调用成功了。。。

2、同步服务调用同学L,重点关注:1)、调用方的序列化方式;2)、最近代码改动逻辑是否有问题。L同学确认自己逻辑没有问题后,同步B同学和S同学,看内部是否有什么处理逻辑。。。

3、第二天早上一来,快速写了单测,确认服务端收到的报文格式,的确没有问题。于是乎,开始扒代码。。。发现可疑的代码:

BeanUtils.copyProperties(item,cargoInfo)

private List<CargoInfo> convertToCargoInfo(OutboundEventCallbackRequest outboundEventCallbackRequest) {
        return outboundEventCallbackRequest.getCargos().stream().map(item -> {
            CargoInfo cargoInfo = new CargoInfo();
            BeanUtils.copyProperties(item, cargoInfo);
            return cargoInfo;
    }).collect(Collectors.toList());
}

PS:客户端&服务端类关系

java浅拷贝BeanUtils.copyProperties引发的RPC异常 | 京东物流技术团队_浅拷贝

因为BeanUtils.copyProperties属于浅拷贝,而浅拷贝只是调用子对象的set方法,并没有将所有属性拷贝(引用的一个内存地址)。所以将在进行调用时,JSF会因为反序列化时找不到对应的类,就会将其转换为Map。

直观图如下:

java浅拷贝BeanUtils.copyProperties引发的RPC异常 | 京东物流技术团队_浅拷贝_02

以上,初步定位原因,解决方式也就清晰了。

解决方案

去掉BeanUtils.copyProperties,进行手动赋值。最终解决了这个问题。

后续反思

1、想起王东岳老师的那句话,越原始的越稳定~

2、如果这种转换比较多,建议使用MapStruct

3、谨慎使用BeanUtils.copyProperties,请看:

java浅拷贝BeanUtils.copyProperties引发的RPC异常 | 京东物流技术团队_服务端_03

作者:京东物流 吴义

来源:京东云开发者社区 自猿其说 Tech 转载请注明来源

标签:调用,java,cargoInfo,xxx,RPC,copyProperties,拷贝,BeanUtils
From: https://blog.51cto.com/u_15714439/8999725

相关文章

  • java浅拷贝BeanUtils.copyProperties引发的RPC异常 | 京东物流技术团队
    背景近期参与了一个攻坚项目,前期因为其他流程原因,测试时间已经耽搁了好几天了,本以为已经解决了卡点,后续流程应该顺顺利利的,没想到人在地铁上,bug从咚咚来~没有任何修改的服务接口,抛出异常:java.lang.ClassCastException:java.util.HashMapcannotbecasttocn.xxx.xxx.xxx.xx......
  • 什么是java包冲突
    Java包冲突指的是在Java应用程序中存在多个版本的相同包或类的情况。这可能导致一些问题,比如:1.版本不兼容:不同的库可能提供相同包的不同版本,而这些版本可能具有不同的方法、功能或者API。如果应用程序使用了这些不同版本的库,可能会出现方法不兼容或行为不一致的问题。2.运......
  • Java 简单工厂模式
    需求:Pizza有以下几个方法prepare()准备食材bake()烘焙cut()切割box()装盒现在有两种披萨,第一种是ApplePizza,第二种是CheesePizza。PizzaStore有点单系统Order(pizzaType)根据pizzatype去制作对应的Pizza。Pizza的抽象类publicabstractclassPizza{Strin......
  • 无涯教程-Java加密 - 创建签名
    数字签名使无涯教程可以验证签名的作者,日期和时间,并对邮件内容进行身份验证。它还包括用于其他功能的身份验证功能。创建数字签名现在学习如何创建数字签名。您可以按照以下步骤使用Java创建数字签名。步骤1-创建KeyPairGenerator对象KeyPairGenerator类提供getInstan......
  • Java必知必会系列:机器学习与数据挖掘
    1.背景介绍机器学习和数据挖掘是计算机科学领域的两个重要分支,它们在现实生活中的应用也越来越广泛。机器学习是人工智能的一个分支,它研究如何让计算机自动学习和理解数据,从而实现对未知数据的预测和分类。数据挖掘则是对大量数据进行分析和挖掘,以发现隐藏在数据中的模式和规律,从而......
  • Java应用怎么调优?【转】
    一、Java应用调优的关键指标调优之前首先我们要知道怎样才算是“优”,不能笼统的说我的程序性能很好,所以就需要有一个具体的指标来衡量性能情况,而在JVM里面衡量性能两个指标分别“吞吐量”和“停顿时间”。吞吐量程序运行过程中执行两种任务,分别是执行业务代码和进行垃圾回收,吞......
  • JavaScript事件
    事件JavaScript事件,就是用户或浏览器本身的某种行为,一般是用户对页面的一些动作引起的,比如用户的点击某个链接、在文本框中输入文本等。绑定对应的事件方法一:直接在元素上面添加一个事件属性语法:方法二:在js中找到dom添加事件语法:方法三:使用addEventListener 语法:注意......
  • Java多线程:状态转移详解
    Java中的线程在其生命周期内会经历不同的状态。理解这些状态以及它们之间的转换对于掌握多线程编程至关重要。本文将详细介绍Java线程的状态以及它们之间的转换机制。线程生命周期状态根据Java语言规范和java.lang.Thread.State枚举定义,线程的状态主要分为以下几种:新建(NEW):创建后尚......
  • 【Java核心基础】一文带你了解Java中构造方法的重要作用!
    构造方法是Java中用于初始化对象状态的特殊方法,与类同名且无返回类型,创建对象时自动调用,可重载以提供灵活性;若未定义,编译器提供默认构造方法,它可加访问修饰符,可用super()调用父类构造方法,构造方法不可继承或直接调用,可用于依赖注入。定义在Java中,构造方法专门负责初始化新创......
  • 无涯教程-Java加密 - 获取密钥
    在本章中,无涯教程将学习如何使用Java密码术从密钥库中检索密钥。要从密钥库中检索密钥,请遵循以下步骤。步骤1-创建KeyStore对象java.security包的KeyStore类的getInstance()方法接受一个表示密钥库类型的字符串值,并返回一个KeyStore宾语。如下所示,使用此方法创建KeyS......