問題現象說明
在個別環境下加載規則時出現:rule/trade/hg/Rule_FY_*.java (53:3948) : Duplicate local variable paraMap,出現此問題的環境為:was8.5+linux2.6,問題的關鍵現象也在於:開發環境、客戶相同的部署環境均未發生過類似異常。
問題分析
經過對drools源碼的跟蹤、調試,該問題和中間件無關。根本原因是規則腳本中的全局變量和局部變量重復了,由系統在加載文件時的順序引發此問題:
-
規則腳本中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詞法分析器對規則腳本進行分析,提取出局部變量,將此局部變量和全局變量列表進行匹配,如在全局變量列表中找到了,則將此加入到方法入參,之所以要將此作為入參,是因為在規則體內可能有用到全局變量的場景。
- 規則引擎何時將全局變量作為入參是有條件的,其中的一個必要條件是在解析規則中的局部變量時其全局變量已經先加載了(和規則文件的加載順序有關);當voucher_preprocess.drl腳本比HG-2.0.0.drl先加載時便會觸發此條件,發生問題,當voucher_preprocess.drl后加載時,在解析HG-2.0.0.drl的相關局部變量時因為未發現有相關的全局變量,在生成方法入參時也就不會生成此全局變量了,也就不會有問題。
- 文件的加載順序:讀取規則文件時,用的是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, |
