在实施<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 : 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包.
如有达人不吝指教,不胜感激
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 : 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包.
如有达人不吝指教,不胜感激