Reputation: 5133
I have a similar piece of code inside a @Service
:
@Autowired
private MyDAO myDAO;
@Transactional
@Override
public void m(...) {
Integer i = null; // this is just to simulate a NPE
myDAO.saveX(...);
i.toString(); // throws NullPointerException
myDAO.saveY(...);
}
This piece of code throws a NPE which is not catched by Spring and so my code is not rolled back. Any idea why is this happening?
I have the same configuration as in other places in my app and in those places it works as expected.
<jee:jndi-lookup id="dataSource" jndi-name="jdbc/MyDataSource"/>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
Upvotes: 1
Views: 2951
Reputation: 22516
Possible reasons:
Your bean is not managed by Spring, a.k.a created with new
instead of taken from the application context.
you're calling the m()
method in another method of the same class/bean. By default Spring uses proxies to manage declarative transactions and internal calls are not supported.
you're throwing checked exception and not using @Repository
on the dao. Declarative transactions work only for runtime exceptions. @Reposiotry "fixes" that by wrapping all exceptions in a DataAccessException
. (probably not the case since NPE is runtime)
Upvotes: 4
Reputation: 5133
I found the solution here. I have multiple contexts and some of them didn't have <tx:annotation-driven />
.
Upvotes: 1
Reputation: 140
Try adding rollbackFor
parameter to @Transactional
annotation
@Transactional(rollbackFor=NullPointerException.class)
Upvotes: 1