Which Aspect/Interceptor handles the #Transactional annotation - java

Does anyone know which class handles the #Transactional annotation? I am searching for the source code that creates the transaction, specifically.

I've done a deep code analysis for the #Transactional stuff here: http://doanduyhai.wordpress.com/2011/11/20/spring-transactional-explained/
Be carefull, this analysis only focus on JPA transaction. I did not consider datasources other than database but I guess the approach is similar

TransactionInterceptor handles the interception logic, but obviously with the assistance of a lot of other infrastructure classes. That's the best place to start, though. The transaction sync stuff is pretty fearsome when you start getting into the source code.
The processing of #Transactional, and its parsing into the neutral transaction descriptor object model, is done by AnnotationTransactionAttributeSource.

Related

Understanding Spring and "No EntityManager with actual transaction available"

I have a Spring Boot application with Hibernate, with a bunch of DAOs annotated with #Repository and Spring's #Transactional. Everything works fine. Then I decide to move common methods (persist, find, merge) to an AbstractDao. Writing operations (persist, merge) start throwing that No EntityManager with actual transaction available for current thread - cannot reliably process 'persist' call exception. I try adding #Transactional to AbstractDao, and contrary to my expectations, it fixes it.
Why is that so? I thought that since, unlike CGLIB, Spring uses interfaces instead of extending classes, it wouldn't work, and I would need to define an interface to declare instead of my DAOs. But I also guess that I'm mixing concepts of how Spring deals with dependency management and with transactions.
Can somebody provide an explanation of why does it work? Is there a better way of dealing with this problem?

Strange Spring Transaction Behavior

I'm having a difficult time understanding Spring Transactions. First off, I am trying to use as little of Spring as possible. Basically, I want to use #Transactional and some of its injection capabilities with JPA/Hibernate. My transactional usage is in my service layer. I try to keep them out of test cases. I use CTW and am spring-configured. I have component scan on the root of my packages right now. I also am using Java configuration for my datasource, JpaTransactionManager, and EntityManagerFactory. My configuration for the JpaTransactionFactory uses:
AnnotationTransactionAspect.aspectOf().setTransactionManager( txnMgr );
I do not use #EnableTransactionManagement.
Unfortunately, I'm having a hard time understanding the rules for #Transactional and can't find an easy page that describes them simply. Especially with regards to Session usage. For example, what if I want to use #Transactional on a class that does not have a default no-arg constructor?
The weirdest problem I'm having is that in some of the POJO service classes Transacitonal works great while in others I can see the transactions being created but operations ultimately fall saying that there is "no session or the session has been closed". I apologize for not having code to reproduce this, I can't get it down to a small set. This is why I am looking for the best resources so I can figure it out myself.
For example, I can have a method that gets a lazily fetched collection of children, iterates through it and puts it into a Set and returns that set. In one class it will work fine while in another class also marked with #Transactional it will fail while trying to iterate through the PersistentSet saying that there is no session (even though there IS a transaction).
Maybe this is because I create both of these service objects in a test case and the first one is somehow hijacking the session?
By the way, I have read through the spring source transaction documents. I'm looking for a clear set of rules and tips for debugging issues like this. Thanks.
Are you sure you loaded your parent entity in the scope of the very transaction where you try to load the lazy children? If it was passed in as parameter for example (that is, loaded from outside your #Transactional method) then it might not be bound to a persistence context anymore...
Note that when no #Transactional context is given, any database-related action may have a short tx to be created, then immediately closed - disabling subsequent lazy-loading calls. It depends on your persistence context and auto-commit configurations.
To put it simply, the behaviour with no transactional context being sometimes unexpected, the ground rule is to always have one. If you access your database, then you give yourself a well-defined tx - period. With spring-tx, it means all your #Repository's and #Services are #Transactional. This way you should avoid most of tx-related issues.

Rollback ORMapper Queries

We're using MyBatis (3.0.5) as our or-mapping tool (and I don't have any say-so over that!).
I've created a Response object that, through MyBatis, mapped to our [responses] database table (we use PostgreSQL).
Actually, the ormapping structure we use is as follows:
ResponseMapper.xml - this is the XML file where the PSQL queries are defined and mapped to the ResponseMapper.java** class and its methods
ReponseMapper.java - An interface used by MyBatis for executing the queries defined in the XML file (above)
ResponseDAO.java - An interface used for DI purposes (we use Spring)
ResponseDAOImpl.java - A concrete implementation of ResponseDAO that actually calls ResponseMapper methods; we use Spring to inject instances of this class into our application
So, to INSERT a new [responses] record into PostgreSQL, the code looks like this from the invoking component:
#Autowired
private ResponseDAO response;
public void doStuff()
{
int action = getAction();
response.setAction(action);
response.insert();
}
This set up works beautifully for us. However I am now trying to write a set of JUnit tests for the ResponseDAOImpl class, and I want to make sure that it is correctly executing queries to our PostgreSQL database.
As far as I can tell, there is no way to "mock" an entire database. So my only option (seemingly) is to have the test method(s) execute a query, check for success, and then roll it back regardless.
MyBatis doesn't seem to support this kind of rollback feature. I found this post off the mybatis-user mailing list on Old Nabble, but the poster was using Guice and his/her question seemed to be more about rolling back transactions through Guice.
If MyBatis doesn't support transactions/rollbacks (does it?!?!), then it seems like my only repireve would be if the PostgreSQL-JDBC driver supports these. I guess I could then try to configure my test methods so that they run the ResponseDAO.insert() method, and then manually try to rollback the transaction directly through the driver (sans MyBatis).
Does SO have any experience with this? Code samples? Tips? Best practices? Thanks in advance!
MyBatis allows rollbacks when working with an "SqlSession", the thing is your using the spring dependency injection piece, which automatically commits your transaction when the method completes.
You have a few options, among them
Inject a Mock of your dependencies. There is some rocking libraries to help with this. Like Mockito, here is a good question on Spring Mockito stuff. This will test your business logic in your java, but not your actual queries.
Commit your queries, and delete your data after the test runs. This is the approach we took, because it tests our database as well. You would obviously need a test instance of your database, which some people don't have.
You could try to provide your own test bindings for the classes that do the automatic commit in the MyBatis Spring Integration and override there behavior so that in the test environment the behavior is to rollback the query instead of committing. A similar approach was use in the Guice integration, and it is described here.
Not sure this is what you need, but org.apache.ibatis.session.SqlSession class has rollback() method which can be used to rollback.
Another approach is to use getConnection() method from the same class which will return javax.sql.Connection javax.sql.Connection class which also has commit() and rollback() methods.
Hope it helps.
Remis B

Rollback transactions in JAX-RS

I have a simple resource class that implements some POST method. How to rollback transaction if there was exceptions in my methods, and commit - if all is ok?
Is there a way to write this code once - not in every resource class that I have?
If you are using Spring, #Transactional will handle your scenario.
http://static.springsource.org/spring/docs/3.0.x/reference/transaction.html
Using a dependency-injection will greatly simplify this. Using #Transactional or similar annotations around the methods where you want to commit/rollback transactions.
If you have to do this manually, you have basically two options:
do it manually for every operation
use the proxy pattern/decorator pattern and proxy/decorate all your classes that require transactions. Then in the proxy/decorator start the transaction, delegate to the target, and commit it after it returns. (this is how DI frameworks do it)

Using and controlling Spring transactions within Struts 2 actions

I have been working for a while on a project with the following components:
Struts2.1.8.1,
Spring 3.0.3
JPA 2.0,
Hibernate 3
I am using Spring's EntityManager magic... But I'm having problems dealing with transactions inside my actions. For instance, I am setting values on my persisted object in several methods within my class, and I want to be able to rollback if the validate method finds a validation error, or commit these changes otherwise. I have already spent quite a long time reading half of the internet for a comprehensive explanation. Unfortunately, no complete examples exist (at least similar to my stack).
I have stumbled with this thread on a mailing list: #Transactional Spring Annotation in a Struts2 Action does not work. The message I'm linking at seems to have a pretty simple and straightforward solution, using a TransactionInterceptor will do the trick it seems... The problem is that I'm not finding useful information regarding this interceptor.
Anyone here has experience with this technology and can spare a tip and a link or two on how to use Spring transactions inside Struts2 actions?
Thanks!
- Edit 1 -
I have set up a test project if you are interested, just download the file and try it out (or inspect it). Thanks!
Generally, controllers/actions/backing beans/etc don't handle transactions. Actions are the web-part of your back-end code - they should only be concerned with gathering request data, and sending response data. The logic itself (including database access) should be done in another layer. E.g. a service layer. So you create another bean, inject it in the action, and make it do the work - userService.register(user). Then configuring transactions on a service layer should be trivial since it is both in the spring documentation and in countless examples:
<tx:annotation-driven /> and #Transactional (btw, make sure you have the <tx:..> now, it might be causing the issue. Even if it works, this does not invalidate my suggestion about the service layer)
I don't like answering my own question, but since I solved this ages ago... I thought I should share the knowledge (or lack of... in this case).
The book I was using to learn about Struts 2 and Spring-JPA-Hibernate, adds the #Transactional annotation right before the declaration of the service class. This is terribly wrong, for all methods (including those that only retrieve stuff from the database) are inside a committable transaction. Long story short everything got committed event if exceptions occurred.
The solution, as Bozho so wisely pointed out, was to look at examples. That is, set your transtactional methods carefully, in my case I set up transactions for the methods that had to write back to the database and everything started to work just fine.
Thanks to Steven and Quaternion too for taking the time to answer my question.
Based on your question, here's what I understand about your problem.
You want to wrap your action invocation in a transaction. If the validate method records validation errors, you want to roll the transaction back. Presumably, you also want to rollback in case of an error.
Solution
Create an interceptor that will:
Start a transaction
Invoke the action inside of a try/catch block
Rollback the transaction if there is an exception or if there are any validation errors on the action (this can be detected using action.hasErrors)
Commit the transaction
You will probably want this interceptor defined pretty early in the stack. I don't know of any pre-built interceptors for this (although there may be some), but it should be fairly easy to assemble.
Update
I don't use Spring, so I can't say how the JPA transaction support works there, but you can handle transactions for your EntityManager like:
try {
entityManager.getTransaction().begin();
// do your thing
entityManager.getTransaction().commit();
} catch (Exception e) {
entityManager.getTransaction().rollback();
throw new PersistenceException(e);
}
This is just a crude example, but it should illustrate the point.

Categories