I tried setting up declarative transaction management in my Spring-based web application and it refuses to work with me.
I have two main problems:
- Setting defaultAutoCommit to false on our data source (what we need for our application) causes all requests to be rolled back, with or without transactions.
- Transactions are generated, as well as proxy classes, as well as transactional methods, but transactions are not used.
The first problem is rather perplexing, since each individual request is returned to the database. This also includes SELECT statements. What can lead to rollback of each request in a database?
Regarding the second issue, my transaction management configuration is described below:
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://springframework.org/schema/context" xmlns:util="http://www.springframework.org/schema/util" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/spring-context-3.0.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd" default-autowire="byName"> <tx:advice id="txAdvice" transaction-manager="txManager"> <tx:attributes> <tx:method name="*" rollback-for="Exception" /> </tx:attributes> </tx:advice> <aop:config> <aop:pointcut id="serviceOperations" expression="execution(* foo.bar.service.*.*(..))"/> <aop:advisor advice-ref="txAdvice" pointcut-ref="serviceOperations"/> </aop:config> <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean> <bean id="dataSource" destroy-method="close" class="org.apache.commons.dbcp.BasicDataSource"> <property name="driverClassName" value="${jdbc.driverClassName}" /> <property name="url" value="${jdbc.url}" /> <property name="username" value="${jdbc.username}" /> <property name="password" value="${jdbc.password}" /> <property name="defaultAutoCommit" value="false" /> </bean> <bean id="fooService" class="foo.bar.service.FooService" /> <bean id="barService" class="foo.bar.service.BarService" /> <bean id="zapService" class="foo.bar.service.ZapService" /> </beans>
Of all the training programs and forums that I visited in an attempt to solve this problem, I believe that my configuration should be correct. However, I do not fully understand aop and spring transactions, so I might have something important.
As mentioned above, I can track my logs and view proxies as well as transactional methods created for my classes of service. However, when I actually launch the application and trace through the logs, I do not see any statements related to the DataSourceTransactionManager or generated transactions, executed, canceled, etc.
It seems to me that nothing really starts up, and I'm terribly confused, since I followed a lot of different textbooks and tried it in different ways, but it always ends with this situation.
I am also sure that my log4j properties are correctly configured to receive messages from the DataSourceTransactionManager, but I provide them below to make sure that this is not just a registration error on my side.
My log4j is configured with the following loggers to try and track transactions:
log4j.logger.org.springframework=INFO, file log4j.logger.org.springframework.jdbc.datasource=DEBUG, file log4j.logger.org.springframework.transaction=DEBUG, file
Note. At some point, I started the upper logger on DEBUG, and it was there that I checked that service proxies were being created.
Does anyone have an idea of ββwhat might happen? Iβm pretty stuck at the moment, because I see some parts related to the transactions being created, but I donβt see any signs of any transactions that would be used at all.
Edit
Further information on request from JB Nizet.
My entire application is annotated, so my beans service is annotated using @Service and injected into my controllers through auto-negotiation by name.
The following is an example of one of my service classes (the names have been changed but will be displayed in my context.xml application).
@Service("zapService") public class ZapService { private ZapDAO zapDAO; public void processNewZap(Zap zap) { zapDAO.processNewZap(zap); } }
As you can see, my service classes are just proxies between controller classes and dao classes. DAO is where I actually handle database connections.
I believe that I read somewhere that providing services to transactional rather than dao classes was the preferred practice when dealing with transactions. Please correct me if I am wrong.
The ZapDAO class is described below.
@Repository("zapDAO") public class ZapDAO { Logger logger = Logger.getLogger(ZapDAO.class); private JdbcTemplate jdbcTemplate; public void processNewZap(Zap zap) { ... query constructing logic ... this.jdbcTemplate.update(INSERT_ZAP_QUERY_SQL); } public void setDataSource(DataSource dataSource) { Assert.notNull(dataSource, "You must supply a valid data source"); this.jdbcTemplate = new JdbcTemplate(dataSource); } }
I use jdbcTemplate to handle my connections and requests.