在简书上新开博客,趁着热乎劲,写篇工作心得过过瘾。
这个最佳实践来自于一个defect。准确说是BPM的一些不足带来的一些不方便trouble shooting的问题,加上随意的流程设计,造成了出错的地方和问题暴露的地方相差十万八千里,甚至开始时很难把这两个问题联想到一起。
错误的Log像这样:
[4/28/16 20:52:47:304 CEST] 0002f2c7 wle E CWLLG0326E: The BPD encountered an error.
com.lombardisoftware.core.TeamWorksException: java.lang.Object
at com.lombardisoftware.core.TeamWorksException.asTeamWorksException(TeamWorksException.java:136)
at com.lombardisoftware.client.persistence.common.DAOHelper.serializeObject(DAOHelper.java:166)
at com.lombardisoftware.client.persistence.common.DAOHelper.serializeAndCompressIfNeeded(DAOHelper.java:140)
at com.lombardisoftware.bpd.runtime.engine.BPDInstanceDAO.updateExecutionContext(BPDInstanceDAO.java:416)
at com.lombardisoftware.bpd.runtime.engine.BPDInstanceDAO.save(BPDInstanceDAO.java:338)
[4/28/16 20:52:47:390 CEST] 0002f2c7 wle_scheduler E CWLLG0181E: The following error occurred in the 5,374,817 task: Not a valid char constructor input: in_creation
com.lombardisoftware.core.TeamWorksException: Not a valid char constructor input: in_creation
at com.lombardisoftware.core.TeamWorksException.asTeamWorksException(TeamWorksException.java:136)
at com.lombardisoftware.bpd.runtime.engine.quartz.AbstractBpdTask.execute(AbstractBpdTask.java:137)
at com.lombardisoftware.bpd.runtime.engine.quartz.AbstractBpdTask.execute(AbstractBpdTask.java:55)
at com.lombardisoftware.server.scheduler.Engine.execute(Engine.java:918)
错误的原因看着很简单,串行化失败。当时结合日志上下文,错误地点定位在非本人维护的activity当中,想当然的就transfer出去了。
问题又很快被踢回来了,原因是错误也没有在他们的activity当中。两个activity之间出错,那90%是传递的参数问题。两个activity虽然传递的参数不多,但要debug还挺花时间,费了番功夫之后,神奇的事情出现了。所有参数直接显式赋值确保没有串行化问题之后还是报错。带着绝望的心情,我又费了更大的功夫(妈妈说有5x个,赋值逻辑分散在各个activities里面,调试还没有整套环境T_T)把所有BPD中间定义的所有参数全部隐去,错误消失了!
后面事情就简单了,过滤/定位后发现原来是新人加的一个Any类型的参数,参数的初始化赋值是转化自一个javascript的JSON object,并用Java的map重构。但没有考虑multi-layer,把一个javascript JSON object赋值到了java的object里面。修改逻辑后问题解决。
重新来看这个问题,为什么这个参数为什么之前一直没有暴露问题,而单单到其它activity,还且还是没有任何调用操作的activity出错了?现在事后想想,首先报错的activity是一个existing的BPD,而不是当前BPD下面定义的一个activity。当流程从当前BPD转到报错的activity时,BPM的内在逻辑看来把所有原BPD中的参数都串行化并持久存储起来,然后切换上下文环境来跑下一个由existing BPD生成的activity。但由于初始化的错误,串行化失败,无法持久化,报错了。
这个问题总共花了4天时间debug,中间情节曲折,问题定位艰难,一个是我自身对BPM不熟,第二是当时候BPD设计过分依赖Any参数。Any参数忽略的类型检验,虽然易于编程,但调试却困难重重。所以不是万不得已,不建议在BPD中使用Any类型的参数。