hyamine 发表于 2013-1-28 23:33:54

hibernate JNDI查询挂死WebSphere

运行环境:
Aix + WebSphere 6.1 + Oracle + Quartz1.65 + Sping2.5.6 +Hibernate 3.3.1
现象:
WebSphere 的Node & Server挂死,JVM堆栈溢出,WebSphere 所在分区被JVM core dump 文件塞满
原因:
Quartz 管理的线程运行在非容器托管状态(不受WebSphere控制),获取不到J2EE context,并且线程中使用到了Hibernete,在试图通过java:comp/UserTransaction查询JTA时throw NamingException,而Hibernete JTATransactionFactory.java 如下代码存在BUG:
protected UserTransaction getUserTransaction() {log.trace( "Attempting to locate UserTransaction via JNDI [{}]", getUserTransactionName() );try {UserTransaction ut = ( UserTransaction ) getInitialContext().lookup( getUserTransactionName() );if ( ut == null ) {throw new TransactionException( "Naming service lookup for UserTransaction returned null [" + getUserTransactionName() +"]" );}log.trace( "Obtained UserTransaction" );return ut;}catch ( NamingException ne ) {throw new TransactionException( "Could not find UserTransaction in JNDI [" + getUserTransaction() + "]", ne );}}
,其中throw new TransactionException( "Could not find UserTransaction in JNDI [" + getUserTransaction() + "]" ,按作者的意思应该是getUserTransactionName() 误写成了getUserTransaction() 导致无限递归调用

解决办法 :
方案1:
重写JTATransactionFactory.java 的getUserTransaction() 方法
代码如下
protected UserTransaction getUserTransaction() {log.trace( "Attempting to locate UserTransaction via JNDI [{}]", getUserTransactionName() );if(uTran != null)return uTran;try {uTran = ( UserTransaction ) getInitialContext().lookup( getUserTransactionName() );if ( uTran == null ) {uTran = ( UserTransaction ) getInitialContext().lookup( CLIENT_USER_TRANSACTION_NAME );if(uTran != null)return uTran;elsethrow new TransactionException( "Naming service lookup for UserTransaction returned null [" + getUserTransactionName() +"]" );}log.trace( "Obtained UserTransaction" );return uTran;}catch ( NamingException ne ) {try {uTran = ( UserTransaction ) getInitialContext().lookup( CLIENT_USER_TRANSACTION_NAME );} catch (NamingException e) {e.printStackTrace();}if(uTran != null)return uTran;elsethrow new TransactionException( "Could not find UserTransaction in JNDI [" + getUserTransactionName() + "]", ne );}}

其中CLIENT_USER_TRANSACTION_NAME= "jta/usertransaction"

方案2:
自定义hibernate.transaction.factory_class类
使用Spring注入usertransaction
重载getUserTransaction
protected UserTransaction getUserTransaction() {    return userTransaction;   }
页: [1]
查看完整版本: hibernate JNDI查询挂死WebSphere