batchInvokeAction Exception in invoke DispatchService原创
金蝶云社区-Coding
Coding
3人赞赏了该文章 931次浏览 未经作者许可,禁止转载编辑于2022年10月25日 16:19:41

同事发来一张报错截图,问,IDEA出问题了,什么也没动,突然之间工具栏点什么都报错。解决此类问题的四大法则,清除project 缓存(gradle clean),清除浏览器缓存,清除IDEA缓存(invalidate Caches and restart),最后重启。最初的最初,我以为是mservice服务终止或者元数据被重构所导致,四大法则丢出去同事告诉我,还没解决。这下我好奇了,到底是什么样的错,竟然连堆栈信息都不会输出,于是我想起了同事说的,IDEA出问题了,那就从IDEA开始看起。

图片.png


在检查了IDEA的各项配置以及gradle的配置后,我惊讶的发现,并没有任何问题,我尝试点列表数据报错、尝试点工具栏报错,无一例外没有任何堆栈信息的输出。无奈之下只好寄出Debug大法来定位问题,能够抛出这样的异常总有一句代码是导火索,因此要做的是,从浏览器的F12开始,跟踪调试。


首先Debug的流程要致敬几道求索的《苍穹debug流程》,前人搭好的路并做了路引,就应该用来解决当下的问题。


首先我们可以很肯定的获取到,我们当前的操作正好对应到了

kd.bos.web.actions.FormAction#batchInvokeAction

中,通过解读代码,我们发现,这个操作又被转发到了BOS提供的微服务:

kd.bos.mservice.form.FormServiceImpl#batchInvokeAction(java.lang.String, java.lang.String, java.util.Map<java.lang.String,java.lang.Object>)

图片.png


图片.png

接下来就要分析当前方法里面的代码,通过Debug调试以及分析代码,我们不难找出继续分发事件的代码:

results.addAll(this.invokeAction(formView, paramKey, methodName, args, postData, actionParams));

进入到当前类的 invokeAction 的方法,我们再来分析代码

图片.png

这里面的重要的逻辑执行都在if/else中,因为我们的key不为空,所以我将if的代码块折叠起来方便查看,通过Debug我们发现,当我们刚执行完 srv.registerListener()的代码后,就立马进入了finally,敏感的同学已经注意到了,这里虽然没有写catch的部分,但是执行finally必然是在try代码块完成或者执行到异常后捕获处理完成之后,所以说我们最大的问题出来了,就在这句话:

srv.registerListener();


srv即IFormController对象,分别对应了以下几种控制器,当前属于什么页面,就对应什么样的控制器。

图片.png

我们当前对应的是列表界面,因此对应到列表的控制器

图片.png

我们Debug继续执行,发现这里面并没有报错的地方,依然正常执行,我们把断点继续深入,放在了

this.getPluginProxy().fireRegisterListener(new EventObject(this.getView()));

图片.png

这里在做什么,通过方法名,我们不难理解,触发注册的监听,通过传递的参数,我们不难发现其实就是执行了界面上的所有注册插件的指定方法regisetrListener,看到这里,回归到了我们熟悉的领域,插件事件中,我们所有的监听,由regisetrListener方法中添加监听事件,最后在itemClick等方法中实现最后的点击事件。

最后在方法invokeMethod中,消费了我们的监听事件。

图片.png

调试到这里,我们依然没发现问题出现在哪里,为了更好的跟踪,于是决定在

consumer.accept(pl);

上打上断点,看看我们真实的触发情况。

图片.png

第一次Resume之后,我们看到从插件从系统内置的插件替换成我们注册的二开插件,继续Resume,直到所有的注册插件都被触发之后,我惊讶的发现,消息队列var5竟然一直有值一直在while的循环中,也就是说消息队列的所有插件在被消费了之后又重新添加到了消息队列中等待消费,这让我意识到一个问题,这里肯定是同事写的插件出了问题。


经过二开插件和仔细询问同事出问题的经过,我得到了答案,他在插件的"addItemClickListener"方法中写了一句脏代码"this.addItemClickListener("tbmain")",这句话直接导致了消费队列的不断扩容陷入死循环,苍穹检测到这种机制后果断的抛出了异常:

图片.png


但是由于没有确切的堆栈信息,所以让同事不清楚问题的原因到底出现在哪里。当然事后的我也在反思,如果不是先入为主,如果确定菜单、其他页面的相关点击事件都没有问题,那么是不是问题本身就出现在页面相关的插件中呢。

赞 3