WebLogic环境下JDBC查询阻塞及事务绑定异常求助
嘿,看你遇到的这个问题——跨服务器调用EJB的Spring Data Repository时卡住,数据库根本没收到请求,还有那俩头疼的异常,咱们一步步拆解来解决:
1. 先啃事务绑定的硬骨头:Error binding to externally managed transaction + setRollbackOnly
这俩异常凑一起,说明Web应用发起的事务上下文传到EJB模块时出了岔子,而且事务早就被标记成回滚了,直接把后续流程堵死。
检查事务传播的兼容性:
要是Web应用自己开了事务(比如加了@Transactional),调用EJB默认会传递这个事务上下文。但如果EJB的事务属性是默认的Required,而Web端的事务已经被标记回滚了(可能之前有隐藏的小错误没抓到),就会触发绑定失败。
临时给Web应用的调用方法改个事务传播属性试试,强制开新事务:@Transactional(propagation = Propagation.REQUIRES_NEW) public void yourWebServiceMethod() { // 这里调用EJB Repository的代码 }另外,别让EJB模块里的
@TransactionAttribute和Spring的@Transactional混用,容易搞出冲突。挖一挖事务被标记回滚的根源:
setRollbackOnly called on transaction说明在调用Repository之前,事务就被判了死刑。你得查查Web应用的调用链里,有没有前置操作偷偷触发了回滚——比如捕获异常后调用了TransactionStatus.setRollbackOnly(),或者某个底层调用抛了异常没处理。
可以加个日志看看事务状态:@Autowired private TransactionManager transactionManager; public void yourWebServiceMethod() { TransactionStatus status = transactionManager.getTransaction(new DefaultTransactionDefinition()); log.info("当前事务是否标记回滚: {}", status.isRollbackOnly()); try { // 调用EJB Repository transactionManager.commit(status); } catch (Exception e) { log.error("调用出错", e); transactionManager.rollback(status); } }再去WebLogic的事务日志(
domain_home/servers/你的服务器名/logs/transaction.log)里翻一翻,说不定能找到更详细的回滚原因。
2. 解决RJVM连接的IllegalArgumentException
这个堆栈指向WebLogic的RJVM连接管理器创建搜索键时参数非法,说白了就是跨服务器调用EJB的连接配置出问题了,这也是请求卡壳的直接原因之一。
检查WebLogic跨服务器的连接配置:
同域的WebLogic服务器之间得配置对集群或者域间信任,不然RJVM连接建不起来。- 确认两台服务器的
weblogic.rjvm.enableSSL配置一致,一台开SSL一台没开肯定连不上。 - 检查服务器的监听地址和端口,Web应用所在服务器能不能ping通EJB服务器的T3/T3s端口(默认7001/7002),用telnet测一下端口通不通。
- 看看WebLogic的
ConnectionManager配置,是不是连接数设得太小或者超时时间太短,导致连接池耗尽或者超时。
- 确认两台服务器的
核对EJB远程调用的客户端配置:
Web应用调用EJB的JNDI配置不能错,不然连都连不上:- JNDI lookup的URL格式要对,比如
t3://ejb服务器IP:7001,如果是集群就用t3://集群地址:端口。 - 检查客户端的
weblogic.jndi.enableDefaultUser配置,要是没正确配用户名密码,也可能导致连接失败。
- JNDI lookup的URL格式要对,比如
3. 确认数据库请求为啥没发出去
既然pgAdmin查表秒出结果,数据库肯定没问题,问题出在应用层的请求传递上。
开Hibernate的SQL日志看看:
在EJB模块的persistence.xml里加这些配置,看看Hibernate有没有生成SQL:<property name="hibernate.show_sql" value="true"/> <property name="hibernate.format_sql" value="true"/> <property name="hibernate.use_sql_comments" value="true"/>如果EJB模块的日志里连SQL都没输出,说明请求根本没走到Hibernate那一步,还是卡在事务或者EJB调用阶段。
看看WebLogic的线程状态:
登WebLogic控制台(console应用),进服务器的「监控」→「线程」,看看阻塞的线程栈到底卡在哪个方法上。要是卡在weblogic.rjvm.ConnectionManager.sendMsg,那就是RJVM连接的问题;要是卡在事务相关方法,就还是事务的锅。
最后总结
先把RJVM连接的异常解决掉,这个是直接导致请求发不出去的元凶;然后再挖事务回滚的根源,调整事务传播配置。这俩问题搞定,数据库请求应该就能正常跑起来了。
内容的提问来源于stack exchange,提问作者László Stahorszki

