问题现象说明

  在个别环境下加载规则时出现:rule/trade/hg/Rule_FY_*.java (53:3948) : Duplicate local variable paraMap,出现此问题的环境为:was8.5+linux2.6,问题的关键现象也在于:开发环境、客户相同的部署环境均未发生过类似异常。

问题分析

经过对drools源码的跟踪、调试,该问题和中间件无关。根本原因是规则脚本中的全局变量和局部变量重复了,由系统在加载文件时的顺序引发此问题:

  1. 规则脚本中voucher_preprocess.drl中定义了一个全局变量(paraMap),HG-2.0.0.drl等脚本中也定义了paraMap的局部变量,当规则引擎将全局变量作为本规则方法的入参时就会发生冲突。调试出rule/trade/hg/Rule_FY_*.java的源代码,相关代码为:

public class Rule_FY_e9cd732bdbd54e998f137a2f40468216 {

public static void defaultConsequence(org.drools.spi.KnowledgeHelper drools,**,java.util.Map paraMap ) throws Exception {

org.drools.runtime.rule.RuleContext kcontext = drools;

Map<String, List<CNSecurityFlow>> originalMap = map.getGroupMap();

******

Map<String, String> paraMap = new HashMap<String, String>();

******

}

}

}

paraMap变量的冲突点为方法入参和本方法的局部定义变量发生重复定义,其中入参paraMap是规则引擎根据规则的上下文信息自动生成的,其生成的原理为:采用antlr词法分析器对规则脚本进行分析,提取出局部变量,将此局部变量和全局变量列表进行匹配,如在全局变量列表中找到了,则将此加入到方法入参,之所以要将此作为入参,是因为在规则体内可能有用到全局变量的场景。

  1. 规则引擎何时将全局变量作为入参是有条件的,其中的一个必要条件是在解析规则中的局部变量时其全局变量已经先加载了(和规则文件的加载顺序有关);当voucher_preprocess.drl脚本比HG-2.0.0.drl先加载时便会触发此条件,发生问题,当voucher_preprocess.drl后加载时,在解析HG-2.0.0.drl的相关局部变量时因为未发现有相关的全局变量,在生成方法入参时也就不会生成此全局变量了,也就不会有问题。
  2. 文件的加载顺序:读取规则文件时,用的是java.io.File.listFiles(),而该方法java官方的说明是:"不保证数组中的字符以特定顺序出现,特别是不保证按字母顺序排序"(绝大部分情况是按字母顺序排序的),原始注释:

/**

* ****

* <p> There is no guarantee that the name strings in the resulting array

* will appear in any specific order; they are not, in particular,

* guaranteed to appear in alphabetical order.

*/

public File[] listFiles() {

结论

对于规则脚本的编写,也应该遵循java的编码规范,比如全局变量的命名以g开头,避免局部变量和全局变量出现同名现象。

可删除voucher_preprocess.drl中的全局变量或对相关规则中的局部变量paraMap进行重命名均可解决此问题。

重现条件

在未报出此问题的环境中,将voucher_preprocess.drl的文件名前添加a(avoucher_preprocess.drl),使其先于HG-2.0.0.drl加载。

附:调试日志

有问题环境规则文件加载顺序(无规则):

/home/sofa_home/rules/SJSJG-2.0.0.drl,

/home/sofa_home/rules/voucher_qyfhpx.drl,

/home/sofa_home/rules/STOCKBUYBACK-2.0.0.drl,

/home/sofa_home/rules/voucher_xg.drl,

/home/sofa_home/rules/voucher_qygxsf.drl,

/home/sofa_home/rules/voucher_etfjj_bp.drl,

/home/sofa_home/rules/voucher_zqzh.drl,

/home/sofa_home/rules/BJSMX_BFJ-2.0.0.drl,

/home/sofa_home/rules/voucher_gpjys.drl,

/home/sofa_home/rules/voucher_trade.drl,

/home/sofa_home/rules/voucher_xdhgjx.drl,

/home/sofa_home/rules/TAJZ-2.0.0.drl,

/home/sofa_home/rules/voucher_preprocess.drl,

/home/sofa_home/rules/DETAILTOSUMMARY_SH-2.0.0.drl,

无问题环境规则文件加载顺序(按字母排序):

C:\test\sofa_home\rules\BJSJG-2.0.0.drl,

C:\test\sofa_home\rules\BJSMX-2.0.0.drl,

C:\test\sofa_home\rules\BJSMX_BFJ-2.0.0.drl,

C:\test\sofa_home\rules\COMMAND-2.0.0.drl,

C:\test\sofa_home\rules\DEALCPQSQFCASH_BJ-2.0.0.drl,

C:\test\sofa_home\rules\DEALCPQSQFCASH_GGT_SH-2.0.0.drl,

C:\test\sofa_home\rules\DEALCPQSQFCASH_SH-2.0.0.drl,

C:\test\sofa_home\rules\DEALCPQSQFCASH_SZ-2.0.0.drl,

C:\test\sofa_home\rules\DEALYJQSQFCASH_BJ-2.0.0.drl,

C:\test\sofa_home\rules\DEALYJQSQFCASH_GGT_SH-2.0.0.drl,

C:\test\sofa_home\rules\DEALYJQSQFCASH_SH-2.0.0.drl,

C:\test\sofa_home\rules\DEALYJQSQFCASH_SZ-2.0.0.drl,

C:\test\sofa_home\rules\DETAILTOSUMMARY_BJ-2.0.0.drl,

C:\test\sofa_home\rules\DETAILTOSUMMARY_GGT_SH-2.0.0.drl,

C:\test\sofa_home\rules\DETAILTOSUMMARY_SH-2.0.0.drl,

C:\test\sofa_home\rules\DETAILTOSUMMARY_SZ-2.0.0.drl,

C:\test\sofa_home\rules\ETFJJCASHSUMMARY-2.0.0.drl,

C:\test\sofa_home\rules\FUTURES-2.0.0.drl,

C:\test\sofa_home\rules\GP-2.0.0.drl,

Drools规则加载变量冲突问题分析的更多相关文章

  1. Spring加载流程源码分析03【refresh】

      前面两篇文章分析了super(this)和setConfigLocations(configLocations)的源代码,本文来分析下refresh的源码, Spring加载流程源码分析01[su ...

  2. Springboot学习04-默认错误页面加载机制源码分析

    Springboot学习04-默认错误页面加载机制源码分析 前沿 希望通过本文的学习,对错误页面的加载机制有这更神的理解 正文 1-Springboot错误页面展示 2-Springboot默认错误处 ...

  3. Springboot 加载配置文件源码分析

    Springboot 加载配置文件源码分析 本文的分析是基于springboot 2.2.0.RELEASE. 本篇文章的相关源码位置:https://github.com/wbo112/blogde ...

  4. Android艺术——Bitmap高效加载和缓存代码分析(2)

    Bitmap的加载与缓存代码分析: 图片的压缩 比如有一张1024*768像素的图像要被载入内存,然而最终你要用到的图片大小其实只有128*96,那么我们会浪费很大一部分内存,这显然是没有必要的,下面 ...

  5. ElasticSearch 启动时加载 Analyzer 源码分析

    ElasticSearch 启动时加载 Analyzer 源码分析 本文介绍 ElasticSearch启动时如何创建.加载Analyzer,主要的参考资料是Lucene中关于Analyzer官方文档 ...

  6. jQuery实现DOM加载方法源码分析

    传统的判断dom加载的方法 使用 dom0级 onload事件来进行触发所有浏览器都支持在最初是很流行的写法 我们都熟悉这种写法: window.onload=function(){ ... }  但 ...

  7. JVM加载类冲突,导致Mybatis查数据库返回NULL的一个小问题

    今天碰到个bug,虽然小,但是有点意思 背景是SpringMVC + Mybatis的一个项目,mapper文件里写了一条sql 大概相当于 select a from tableA where b ...

  8. Linker加载so失败问题分析

    WeTest 导读 近期测试反馈一个问题,在旧版本微视基础上覆盖安装新版本的微视APP,首次打开拍摄页录制视频合成时高概率出现crash. 那么我们直奔主题,看看日志: 另外复现的日志中还出现如下信息 ...

  9. spring启动加载过程源码分析

    我们知道启动spring容器两常见的两种方式(其实都是加载spring容器的xml配置文件时启动的): 1.在应用程序下加载 ApplicationContext ctx = new ClassPat ...

随机推荐

  1. jQuery.prop() 使用详解

    prop()函数用于设置或返回当前jQuery对象所匹配的元素的属性值. 该函数属于jQuery对象(实例).如果需要删除DOM元素的属性,请使用removeProp()函数. 语法 jQuery 1 ...

  2. 【PHP】金额数字转换成大写形式

    <?php /*将数字金额转成大写*/ function num_to_upper($num) { $d = array('零','壹','贰','叁','肆','伍','陆','柒','捌', ...

  3. MySQL连接语法

    http://www.cnblogs.com/hanzhaoxin/p/3590642.html 内连接:INNER  JOIN 内连接为 两个表中必须都同时满足条件 内连接,即最常见的等值连接自然连 ...

  4. SQLite开发工具

    Sqlite 管理工具 SQLiteDeveloper及破解 功能特点 表结构设计,数据维护,ddl生成,加密数据库支持,sqlite2,3支持 唯一缺憾,收费,有试用期 下载地址: http://w ...

  5. 认识php钩子-转白俊遥的博客

    认识php钩子-转载白俊遥的博客 我们先来回顾下原本的开发流程:产品汪搞出了一堆需求:当用户注册成功后需要发送短信.发送邮件等等:然后聪明机智勇敢的程序猿们就一扑而上:把这些需求转换成代码扔在 用户注 ...

  6. 了解Unix进程(1)

    今天瞎看 看到一本了解Unix进程 -- 理解UNIX进程 的书 不错,可以看看,使用的ruby语言,第一章讲的是一些基础的知识 1.输出进程号和父进程号: puts Process.pid # 得到 ...

  7. C++判断五位以内的对称素数

    题目内容:判断一个数是否为对称且不大于五位数的素数. 输入描述:输入数据含有不多于50个的正整数n(0<n<232). 输出描述:对于每个n,如果该数是不大于五位数的对称素数,则输出“Ye ...

  8. 多层级Spinner列表选项实时更新树形层级(选择城市)

    package com.example.spinnerdemo; import android.os.Bundle; import android.app.Activity; import andro ...

  9. HOOK API 在多线程时应该注意的问题点

    在使用INLINE HOOK API实现对系统API的拦截时,正常情况下并没有太大问题,但一旦涉及到多线程,不管是修改IAT还是JMP,2种方法均会出现不可预料的问题,特别是在HOOK一些复杂的大型系 ...

  10. Maven学习随记

    慕课网视频教程:http://www.imooc.com/learn/443 ====Maven是什么 Maven是基于项目对象模型(POM),可以通过一小段描述信息来管理项目的构建.报告和文档的软件 ...