梳理解决一个问题的思路

这几天一直在被一个问题纠结:一个stateful session bean的实例变量中保存了一个ResultSet的实例,但是,当这个实例在该bean的一个方法中被创建后,从该方法返回后却发现这个ResultSet实例被关闭了。

这个问题我最初的第一直觉是,一定是什么地方调用了ResultSet的close方法。经过,一次又一次的调试断点可以断定没有调用这个方法。这时候觉得似乎和事务相关,觉得是某次调用抛出了异常,导致事务退出。但是,现在再想想,即使是有异常,也不是根本原因。根本原因还是事务相关。

由于一直没有明确的思路,这个问题就放了几天一直到昨天。这次我决定把之前down掉的调试环境搭建起来。因为我的调用是从另一个虚拟机发起。现在,想想这一步也不是必须的。其实完全可以找到那个方法的调用点,打上断点就可以断定是从哪个分支过来的。

确定了上游调用逻辑后,思路就清晰起来了: stateful session bean中定义的几个方法是业务方法,在一个上游方法中,被依次调用。问题是,第一个方法A创建并保持了一个ResultSet的实例,后续的方法B,C都依赖于这个ResultSet实例。当方法B被调用时,报了一个错:ResultSet already close。

此时,我开始关注这个Bean的事务,它是容器管理的事务。类型是Required。上游调用方法是一个普通类的方法没有事务关联,所以,每次调用方法A就会重新发起一个事务。这时候,我想是不是因为这里的问题?每次方法返回,事务就终结于是在事务中创建的ResultSet实例就close了。

为了验证我的想法我把事务的类型改成了Supports。这样如果调用方没有事务,会话bean的方法A就不会关联到一个事务。改完之后重起application server,运行case结果通过了。看来真是这里的问题。

现在的疑问是这个问题是怎么引入的?联想到系统刚刚升级到了EJB3,很多配置从XML文件一道了类中。于是查看了原来的配置文件,发现原来事务的类型是Bean,但是Bean中并没有用到事务,所以相当于没有事务。现在,升级的时候把它搞错了写成了Container。

重头梳理这个问题的解决思路,其实如果先去看改动历史应该能很快的确定问题所在。我也确实这么做了,但是只看了类文件的改动历史没有看配置文件。还是,问题定位的不准确。

猜你喜欢

转载自messi-18.iteye.com/blog/1678821
今日推荐