New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Regression in transaction rollback handling [SPR-11406] #16033
Comments
Juergen Hoeller commented I'm not aware of any changes on our side that would cause such a change of behavior. It might be an accidental side effect on our side, of course, but there's also a chance that it is caused by some co-upgraded third-party library such as your persistence provider. So please state the exact combination of project versions where it worked for you before, as well as your current combination of versions where it doesn't work anymore. We'll be researching this ASAP then. Juergen |
Alex commented I'm unable to reproduce the problem with a project from scratch. I'll try to slim down my app up to a point to either understand the problem or upload it here. |
Alex commented Repository pull request: spring-attic/spring-framework-issues#65 I've reduced to absolute minimum the project and the problem still stands, I can't even tell the difference between this one and the one made from scratch from one of your templates, but the behaviour is different. I think the only difference is the initialization code: I use a WebApplicationInitializer while you use the "old" web.xml syntax. You can trigger the problem accessing an url like this: |
Sam Brannen commented Hi Alex, I just took a quick glance at the code you submitted in your pull request (admittedly without having run it), and it looks to me like you should just delete the So try removing the Regards, Sam |
Sam Brannen commented Alex, The project you have submitted unfortunately does not deploy. It fails with the following stack trace.
The MySQL driver cannot be found, but even if it could, the application would still not deploy unless MySQL is installed and running on localhost and configured as on your machine. Thus, in order for us to help you better, please submit an update to your pull request that uses an embedded database instead of a local MySQL instance. For example, you might consider using Spring's Thanks, Sam |
Sam Brannen commented Hi Alex, I got your code working as I assume you expect it to. Here's what you need to change... 1) Add the following to the <dependency>
<groupId>org.hsqldb</groupId>
<artifactId>hsqldb</artifactId>
<version>2.3.1</version>
</dependency> 2) Delete 3) Replace your existing <?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:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xsi:schemaLocation="
http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd
">
<context:annotation-config />
<context:component-scan base-package="it.nibbles.test"/>
<jdbc:embedded-database id="dataSource" />
<bean id="jpaVendorAdapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="false" />
<property name="generateDdl" value="true" />
<property name="database" value="HSQL" />
</bean>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="jpaVendorAdapter" ref="jpaVendorAdapter" />
<property name="packagesToScan" value="it.nibbles.test.objs" />
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
<property name="dataSource" ref="dataSource" />
</bean>
<tx:annotation-driven /> <!-- proxy-target-class="false" / -->
<jpa:repositories base-package="it.nibbles.test.dao"
entity-manager-factory-ref="entityManagerFactory" transaction-manager-ref="transactionManager"/>
</beans> 4) Change the JPA mapping for Once I made these changes and deployed the application to Tomcat 7.0.50, I see the following on the first request to http://localhost:8080/SPR-11406/newUser/alex:
... and the following on all subsequent requests:
This is what you wanted to see -- right? Please let us know if this solves your problem! Thanks, Sam |
Alex commented Hello Sam, Of course this example is as limited as possible to reproduce the issue: in the original one there is more logic on the controller method, so having it marked as transactional is imperative. I've modified the pull request to use the embedded HSQL database, please tell me if you're able to reproduce the problem, thanks! |
Sam Brannen commented Alex, thanks for updating your pull request. I'll take another look and get back to you. |
Sam Brannen commented Just to confirm... When I deploy your updated example application running against Spring Framework
However, this is to be expected, and I'll get to that in more detail later. |
Sam Brannen commented To confirm further, I get the same exception when running the example application against Spring Framework So this is definitely not a regression from 3.2 to 4.0, and I assume that it is also not a regression against previous 3.1 or 3.0 releases. |
Sam Brannen commented Hi Alex, The unexpected behavior encountered in the example application (i.e., the aforementioned The message of the exception, "Transaction marked as rollbackOnly", spells it out rather explicitly.
This behavior is well documented in the Rolling back a declarative transaction section of the reference manual. Here's an excerpt:
And here's another pertinent excerpt:
So you have two options to address your issue. Declare
|
Sam Brannen commented Resolving this issue as "Works as Designed". Please see previous comments for details. |
Alex commented Sam, thanks so much for the detailed information: since I made some other seemingly minor modifications to my code while upgrading to Spring 4 I've probably inputed to the upgrade the regression while probably the method passed from non-transactional to transactional. I thought that unchecked exceptions would have popped out of the call stack and the transaction aborted (rolled back) only when the outer boundary would have been surpassed. Thanks again and sorry for the noise. |
Sam Brannen commented You're welcome, Alex. We're just glad it was not an actual regression. ;-) Cheers, Sam |
Alex opened SPR-11406 and commented
In spring 4, the handling of transaction boundaries between function call has changed considerably and code that worked fine in 3.x now stopped working.
Here is an example where a user function in a service throws an exception when a certain condition is met (in this case when the object is not found in the database).
The caller catches the exception and goes on but the transaction has already been rollback and the subsequent write on the database fails.
A proof of concept follows, where a rest service is called and this method use a service that raises an exception when the requested object is not found.
The repository is just a plain default spring-jpa repository.
Affects: 4.0 GA, 4.0.1
The text was updated successfully, but these errors were encountered: