Java与Scala混合编程带来的问题

虽然都是运行在JVM之上的语言,看起来在字节码层面上一样,不过混合编程有时候还是有...

问题描述

项目升级改造,部署时遇到下面问题。

1 发现已经下发了命令,但是设备没有动作。

发现项目1.0版本与2.0版本的设备id不一样。

2 临时添加设备id的映射关系,旧的id转换为新的设备id即可

发现一直报错,表达式解析错误,命令无法下达到底层应用。使用了QLExpression规则引擎,可以动态的执行规则脚本。

线上无法直接调试,框架内错误信息提示不明显。

干扰因素

  • 本人对日常环境的所有流程比较清晰,可能出现的问题也知道。比如在日常环境云端处理规则,可能无法下发到本地。测试不知情,我让测试帮我更新一下日常的规则,导致日常不是最新的规则
    • 日常不是最新的规则,日常环境就与线上不一致,问题无法再现
  • 出现问题时,不够冷静,在问题出现没多久,通过模拟勉强达到了与线上差不多的数据。但是没有完全执行规则,比如线上规则有5句话,日常只测试了4句话,都是成功的,就以为规则是成功的,实际规则问题是在第5句。规则不仅仅是5句话而已,而是一句话被包装了5次,这种情况最容易出现各种各样的问题

定位问题

早上来到公司,没人的情况下头脑清晰,开始处理问题。

1 处理日常环境,试日常环境与线上环境保持一致。以便再现问题

2 关键部分加上断点

3 调试问题

问题点

以下是出现问题的规则:

setPoint(_states_,deviceIds.get(queryBoxRight.data.data.get(0)),"Lock_control","true")

拆解:

queryBoxRight.data.data.get(0) ==> 执行成功

deviceIds.get(queryBoxRight.data.data.get(0)) ==> 执行成功

setPoint(states,deviceIds.get(queryBoxRight.data.data.get(0)),"Lock_control","true") ==> 执行失败

报错信息:ClassCastException

疑问

为什么会报ClassCastException?

查看:deviceIds.get(queryBoxRight.data.data.get(0)) ==> scala.Some

查看:setPoint(states: States,deviceId: String, code: String, value: String): Unit

原因

scala.Some != java.lang.String,无法强制转换。

多次Scala语法尝试

// scala获取String的方法
deviceIds.get(queryBoxRight.data.data.get(0)).getOrElse()
// 结果:报错,无法调用getOrElse()方法。

// scala获取Some中的值,报错
deviceIds.get(queryBoxRight.data.data.get(0)).value

// scala获取Some值的方法,报错
deviceIds.get(queryBoxRight.data.data.get(0)).get

尝试Scala Decompile之后的class文件语法尝试

//成功
deviceIds.get(queryBoxRight.data.data.get(0)).value()
deviceIds.get(queryBoxRight.data.data.get(0)).get()

结论

QLExpression执行规则语句,只支持java语法,或者decompile为Java文件的语法。不要直接用Scala的语法写规则。

反思

1 遇到问题仍然要保持冷静,不能嫌麻烦,仍然需要一步一步来,越偷工减料,越找不到问题真正原因

2 不要有侥幸心理,当以为都试过了,其实还差一步没有试的时候,问题出现在了最后一步。尽可能还原真实场景,尽可能追求一模一样

你可能感兴趣的:(Java与Scala混合编程带来的问题)