论坛首页 Java企业应用论坛

使用JTA的事务处理(pro spring ch12范例)问题

浏览 11588 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2007-01-12  
在实施<spring专业开发指南>中12章多事务处理范例遇到问题,当指定由JTA管理的事务执行时,相关代码进入异常抛出部分:
TestControl.java
...
try {
accountManager.insert(account);
} catch (Exception ex) {
failures++;
}
...
每次insert都失败,failures值增加.原代码insert部分如下
public void insert(Account account) {
System.out.println("come on,folks");
doInsert(account);

jmsTemplate.send(queue, new MessageCreator() {

public Message createMessage(Session session) throws JMSException {
return session.createTextMessage("foobar");
}

});

if (random.nextInt(10) > 5) {
System.out.println("Fail now");
throw new IllegalArgumentException("fff");
}
}
将随机函数部分关闭后,所有提交仍无法成功.

配置文件如下:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="urlMap">
<map>
<entry key="*"><ref local="testController"/></entry>
</map>
</property>
</bean>

<bean id="testController" class="com.apress.prospring.ch12.web.TestController">
<property name="accountManager"><ref bean="accountManager"/></property>
</bean>
</beans>

applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">

<beans>

<bean id="accountDao" class="com.apress.prospring.ch12.data.SqlMapClientAccountDao">
<property name="dataSource"><ref bean="dataSource"/></property>
<property name="sqlMapClient"><ref bean="sqlMapClient"/></property>
</bean>

<bean id="historyDao" class="com.apress.prospring.ch12.data.UnreliableSqlMapClientHistoryDao">
<property name="dataSource"><ref bean="dataSource"/></property>
<property name="sqlMapClient"><ref bean="sqlMapClient"/></property>
</bean>

<bean id="accountManager" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager"><ref bean="transactionManager"/></property>
<property name="target"><ref bean="accountManagerJTATarget"/></property>
<property name="transactionAttributes">
<props>
<prop key="insert*">PROPAGATION_REQUIRED, ISOLATION_READ_COMMITTED</prop>
<prop key="transfer*">PROPAGATION_REQUIRED, ISOLATION_SERIALIZABLE</prop>
<prop key="deposit*">PROPAGATION_REQUIRED, ISOLATION_READ_COMMITTED</prop>
</props>
</property>
</bean>
</beans>

已知的范例BUG有spring-xa-ds.xml,修改后如下
<?xml version="1.0" encoding="UTF-8"?>

<datasources>
<xa-datasource>
<jndi-name>XASpringDS</jndi-name>
<track-connection-by-tx/>
<isSameRM-override-value>false</isSameRM-override-value>
<xa-datasource-class>oracle.jdbc.xa.client.OracleXADataSource</xa-datasource-class>
<xa-datasource-property name="URL">jdbc:oracle:oci8:@orcl</xa-datasource-property>
<xa-datasource-property name="User">jboss</xa-datasource-property>
<xa-datasource-property name="Password">password</xa-datasource-property>
<exception-sorter-class-name>org.jboss.resource.adapter.jdbc.vendor.OracleExceptionSorter</exception-sorter-class-name>
<no-tx-separate-pools/>
</xa-datasource>
<mbean
code="org.jboss.resource.adapter.jdbc.vendor.OracleXAExceptionFormatter"
name="jboss.jca:service=OracleXAExceptionFormatter">
<depends optional-attribute-name="TransactionManagerService">
jboss:service=TransactionManager</depends>
</mbean>
</datasources>
(原文中mbean为
<mbean
code="org.jboss.resource.adapter.jdbc.xa.oracle.OracleXAExceptionFormatter"
name="jboss.jca:service=OracleXAExceptionFormatter">
<depends optional-attribute-name="TransactionManagerService">
jboss:service=TransactionManager</depends>
</mbean>
注意code部分类名区别,这是使用手册的bug)

applicationContext-as.xml有人说要将
<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager"/>
改为
<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
<property name="userTransactionName">
<value>UserTransaction</value>
</property>
</bean>
但实施后发现无明显区别.

需另外修改的地方包括源码ibatis目录下将Account-ora.xml和History-ora.xml改名为Account.xml,History.xml

jboss中的debug级日志如下
2007-01-12 00:12:29,930 DEBUG [org.springframework.web.servlet.DispatcherServlet] Testing handler map [org.springframework.web.servlet.handler.SimpleUrlHandlerMapping@130e79e] in DispatcherServlet with name 'spring-ch12'
2007-01-12 00:12:29,930 DEBUG [org.springframework.web.servlet.handler.SimpleUrlHandlerMapping] Looking up handler for [/test.html]
2007-01-12 00:12:29,930 DEBUG [org.springframework.web.servlet.DispatcherServlet] Testing handler adapter [org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter@1b64611]
2007-01-12 00:12:29,930 DEBUG [org.springframework.web.servlet.DispatcherServlet] Last-Modified value for [/spring-ch12/test.html] is [-1]
2007-01-12 00:12:29,930 DEBUG [org.springframework.web.servlet.DispatcherServlet] DispatcherServlet with name 'spring-ch12' received request for [/spring-ch12/test.html]
2007-01-12 00:12:29,930 DEBUG [org.springframework.web.servlet.DispatcherServlet] Testing handler adapter [org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter@1b64611]
2007-01-12 00:12:29,930 DEBUG [org.springframework.jdbc.datasource.DataSourceUtils] Opening JDBC connection
2007-01-12 00:12:31,118 DEBUG [java.sql.Connection] {conn-100006} Connection
2007-01-12 00:12:31,118 DEBUG [java.sql.Connection] {conn-100006} Preparing Statement:    select count(*) from Accounts 
2007-01-12 00:12:31,118 DEBUG [java.sql.PreparedStatement] {pstm-100007} Executing Statement:    select count(*) from Accounts 
2007-01-12 00:12:31,118 DEBUG [java.sql.PreparedStatement] {pstm-100007} Parameters: []
2007-01-12 00:12:31,118 DEBUG [java.sql.PreparedStatement] {pstm-100007} Types: []
2007-01-12 00:12:31,118 DEBUG [java.sql.ResultSet] {rset-100008} ResultSet
2007-01-12 00:12:31,118 DEBUG [java.sql.ResultSet] {rset-100008} Header: [COUNT(*)]
2007-01-12 00:12:31,118 DEBUG [java.sql.ResultSet] {rset-100008} Result: [0]
2007-01-12 00:12:31,118 DEBUG [org.springframework.jdbc.datasource.DataSourceUtils] Closing JDBC connection
2007-01-12 00:12:31,133 DEBUG [org.springframework.transaction.interceptor.TransactionInterceptor] Getting transaction for method 'insert' in class [com.apress.prospring.ch12.business.AccountManager]
2007-01-12 00:12:31,133 DEBUG [org.springframework.transaction.jta.JtaTransactionManager] Using transaction object [org.springframework.transaction.jta.JtaTransactionObject@5ec9da]
2007-01-12 00:12:31,133 DEBUG [org.springframework.transaction.jta.JtaTransactionManager] Creating new transaction
2007-01-12 00:12:31,133 DEBUG [org.springframework.transaction.jta.JtaTransactionManager] Beginning JTA transaction
2007-01-12 00:12:31,133 DEBUG [org.springframework.jdbc.datasource.DataSourceUtils] Opening JDBC connection
2007-01-12 00:12:31,133 DEBUG [java.sql.Connection] {conn-100009} Connection
2007-01-12 00:12:31,133 DEBUG [java.sql.Connection] {conn-100009} Preparing Statement:    select count(*) from Accounts 
2007-01-12 00:12:31,133 DEBUG [java.sql.PreparedStatement] {pstm-100010} Executing Statement:    select count(*) from Accounts 
2007-01-12 00:12:31,133 DEBUG [java.sql.PreparedStatement] {pstm-100010} Parameters: []
2007-01-12 00:12:31,133 DEBUG [java.sql.PreparedStatement] {pstm-100010} Types: []
2007-01-12 00:12:31,133 DEBUG [java.sql.ResultSet] {rset-100011} ResultSet
2007-01-12 00:12:31,133 DEBUG [java.sql.ResultSet] {rset-100011} Header: [COUNT(*)]
2007-01-12 00:12:31,133 DEBUG [java.sql.ResultSet] {rset-100011} Result: [0]
2007-01-12 00:12:31,133 DEBUG [org.springframework.jdbc.datasource.DataSourceUtils] Closing JDBC connection
2007-01-12 00:12:31,133 DEBUG [org.springframework.web.servlet.DispatcherServlet] Null ModelAndView returned to DispatcherServlet with name 'spring-ch12': assuming HandlerAdapter completed request handling
2007-01-12 00:12:31,133 DEBUG [org.springframework.web.servlet.DispatcherServlet] Successfully completed request
2007-01-12 00:12:31,133 DEBUG [org.springframework.web.context.support.XmlWebApplicationContext] Publishing event in context [XmlWebApplicationContext for namespace 'spring-ch12-servlet']: RequestHandledEvent: url=[/spring-ch12/test.html]; time=[1203ms]; client=[127.0.0.1]; method=[GET]; servlet=[spring-ch12]; session=[null]; user=[null]; status=[OK]
2007-01-12 00:12:31,133 DEBUG [org.springframework.web.context.support.XmlWebApplicationContext] Publishing event in context [Root XmlWebApplicationContext]: RequestHandledEvent: url=[/spring-ch12/test.html]; time=[1203ms]; client=[127.0.0.1]; method=[GET]; servlet=[spring-ch12]; session=[null]; user=[null]; status=[OK]
2007-01-12 00:17:52,305 DEBUG [org.jboss.resource.connectionmanager.IdleRemover] run: IdleRemover notifying pools, interval: 450000

JTA事务好象启动了,但却无法进入相关代码,没有挂JTA事务的JDBC操作部分完全正常,调试发现TestController.java中的
int count = accountManager.count();
执行正常,函数被正确解析到了JTAAccountManager.java使用的代码,但使用
accountManager.insert(account);
时,代码没有进入到JTAAccountManager.java部分(标记"come on,folks"未在上述LOG中出现)
也就是说,TestControl.java中AccountManager已可被解析到其代理实现类JTAAccountManager.java,但挂接JTA部分不能正常工作

pro spring的英文电子书下载地址:
ftp://222.214.218.42/20060927/8a0a863e-cc50-401d-b0d2-fb5561322f03.chm
原书中代码下载地址:
http://www.apress.com/ApressCorporate/supplement/1/405/1590594614-2446.zip

JBOSS版本为4.0.5,XA数据源使用书中推荐的ORACLE10g,jboss405\server\default\lib目录下部署的是oracle14.jar包.

如有达人不吝指教,不胜感激
   发表时间:2007-01-12  
忘记说明,使用ant编译原书代码中build.xml配置时,生成的.ear文件有classloader问题,可将.war中的lib下文件全部去掉解决(.ejb下保有应有的lib文件).
我的build.xml使用的lib文件列表为
2004-08-24  21:37           100,776 commons-dbcp.jar
2006-11-22  19:44         1,223,877 xercesImpl.jar
2006-08-07  12:56            79,151 qdox-1.5.jar
2004-11-13  21:50         1,348,814 spring.jar
2006-11-30  17:18           383,531 ibatis-2.3.0.677.jar
2004-08-24  21:37            39,523 commons-pool.jar
2004-08-24  21:37           210,908 pg74.213.jdbc3.jar
2004-09-16  16:57            91,627 servlet-api.jar
2006-12-21  17:58            36,452 commons-attributes-api.jar
2006-12-21  18:46            29,590 commons-attributes-compiler.jar
2006-12-21  18:48             3,199 commons-attributes-plugin.jar
2004-09-16  16:57            12,822 ejb.jar
2004-08-18  20:58             4,467 aopalliance.jar
2004-09-16  16:57            25,998 jms.jar
这并非是最简的,但编译可用
0 请登录后投票
   发表时间:2007-01-12  
楼主 jboss 里怎么配置 JTA 啊?
谢谢了:)
0 请登录后投票
   发表时间:2007-01-12  
yananay 写道
楼主 jboss 里怎么配置 JTA 啊?
谢谢了:)


JBOSS好象有个J2EE的包直接支持JTA,原贴中的spring-xa-ds.xml用于JBOSS下部署一个XA事务的数据源,问的是这个吗?
0 请登录后投票
   发表时间:2007-01-12  
但我用JTA的事务控制时,jboss 出来log 是
not found JTA with JNDI  java:comp/UserTransaction
(大概是这个意思)

这个就应该是 JTA 没配置对吧?
0 请登录后投票
   发表时间:2007-01-12  
yananay 写道
但我用JTA的事务控制时,jboss 出来log 是
not found JTA with JNDI  java:comp/UserTransaction
(大概是这个意思)

这个就应该是 JTA 没配置对吧?


这个问题网上的解释多是classloader的问题,请检查你的.ear包,可参考
http://www.jboss.com/index.html?module=bb&op=viewtopic&t=69587

遵循该页指导,我将.WAR的LIB下清空后问题消除.
spring-ch12.ear
|
|-spring-ch12-web.war
|            |-META-INF
|            |-WEB-INF
|            |     |-class
|            |     |-lib(*.jar清空)
|
|-spring-ch12-ejb.jar
|            |-com
|            |-META-INF
|            |-*.JAR
如上图,ejb.jar中与.war中具有一些相同的JAR包,我去掉的是.war的lib中的,在本例中可行,你的程序可能需要具体尝试

0 请登录后投票
   发表时间:2007-01-12  
wolf_jack 写道
yananay 写道
但我用JTA的事务控制时,jboss 出来log 是
not found JTA with JNDI  java:comp/UserTransaction
(大概是这个意思)

这个就应该是 JTA 没配置对吧?


这个问题网上的解释多是classloader的问题,请检查你的.ear包,可参考
http://www.jboss.com/index.html?module=bb&op=viewtopic&t=69587

遵循该页指导,我将.WAR的LIB下清空后问题消除.
spring-ch12.ear
|
|-spring-ch12-web.war
|            |-META-INF
|            |-WEB-INF
|            |     |-class
|            |     |-lib(*.jar清空)
|
|-spring-ch12-ejb.jar
|            |-com
|            |-META-INF
|            |-*.JAR
如上图,ejb.jar中与.war中具有一些相同的JAR包,我去掉的是.war的lib中的,在本例中可行,你的程序可能需要具体尝试



http://static.springframework.org/spring/docs/2.0.x/api/org/springframework/transaction/jta/JtaTransactionManager.html的说明:
Some well-known JNDI locations are:
"java:comp/UserTransaction" for Resin 2.x, Oracle OC4J (Orion), JOnAS (JOTM), BEA WebLogic
"java:comp/TransactionManager" for Resin 3.x
"java:pm/TransactionManager" for Borland Enterprise Server and Sun Application Server (Sun ONE 7 and later)
"java:/TransactionManager" for JBoss Application Server

当使用2.0版的的spring.jar代替在二楼贴中的1.2.8版spring.jar和aopalliance.jar后(请注意二楼贴中所列文件的大小和时间),部署spring-ch12.ear时,JBOSS的log:
...
2007-01-12 18:45:07,765 DEBUG [org.springframework.transaction.jta.JtaTransactionManager] Retrieving JTA UserTransaction from JNDI location [java:comp/UserTransaction]
2007-01-12 18:45:07,765 DEBUG [org.springframework.jndi.JndiTemplate] Looking up JNDI object with name [java:comp/UserTransaction]
2007-01-12 18:45:07,765 DEBUG [org.springframework.transaction.jta.JtaTransactionManager] Retrieving JTA TransactionManager from JNDI location [java:comp/TransactionManager]
2007-01-12 18:45:07,765 DEBUG [org.springframework.jndi.JndiTemplate] Looking up JNDI object with name [java:comp/TransactionManager]
2007-01-12 18:45:07,765 DEBUG [org.springframework.transaction.jta.JtaTransactionManager] No JTA TransactionManager found at fallback JNDI location [java:comp/TransactionManager]
org.springframework.transaction.TransactionSystemException: JTA TransactionManager is not available at JNDI location [java:comp/TransactionManager]; nested exception is javax.naming.NameNotFoundException: TransactionManager not bound
Caused by:
javax.naming.NameNotFoundException: TransactionManager not bound
...

至于为何2.0的spring.jar会出现这个问题,"Spring2.0及以后的版本中声明式事务的配置与之前的版本有相当大的不同。主要差异在于不再需要配置TransactionProxyFactoryBean了。"
0 请登录后投票
   发表时间:2007-01-13  
楼贴问题基本查出,JTA不能支持代码中的ISOLATION_READ_COMMITTED隔离级别.使用默认级别前述问题消除.

新问题:
1.jms消息发出后,日志:
....
2007-01-13 21:48:49,171 DEBUG [org.jboss.mq.il.uil2.SocketManager] Failed to handle: org.jboss.mq.il.uil2.msgs.CloseMsg22893735[msgType: m_connectionClosing, msgID: -2147483641, error: null]
java.io.IOException: Client is not connected
at org.jboss.mq.il.uil2.SocketManager.internalSendMessage(SocketManager.java:264)
....
很奇怪,因为后面的log显示消息已正确收到并处理.

2.JTA提交报告失败,但在sqlplus中检查,数据已提交
...
2007-01-13 21:48:49,187 DEBUG [org.springframework.transaction.jta.JtaTransactionManager] Committing JTA transaction
2007-01-13 21:48:49,250 ERROR [org.jboss.resource.adapter.jdbc.xa.XAManagedConnectionFactory] End transaction failed for XAResource
oracle.jdbc.xa.OracleXAException
at oracle.jdbc.xa.OracleXAResource.checkError(OracleXAResource.java:962)
at oracle.jdbc.xa.client.OracleXAResource.end(OracleXAResource.java:355)
...

继续等待达人路过.-_-#
0 请登录后投票
   发表时间:2007-03-08  
看看我的那个用Weblogic做的spring的jta事务的测试,是声明式的事务
0 请登录后投票
   发表时间:2007-08-31  
这几天我也把这个例子实现了一下,JMS和JDBC全局事务都回滚成功,没遇到什么问题啊,你有什么问题??
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics