• Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

Spring 2.5 - Rolling back first method, when the second method throws Runtime ex

 
Sam Gehouse
Ranch Hand
Posts: 281
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Trying to rollback the previous write to database using Spring transaction for POC and learning purposes.

There are two functions that are part of the same transaction namely: insert and then update. The insert successfully writes to database using Hibernate 3.2. I throw a Runtime exception from update on purpose to exercise rollback of insert. Even though update throws the Runtime exception, the data inserted by insert method stays committed in database and does not get rolled back.

org.poc.tx.Manager class has insert and update methods.

Following is the XML:

<aop:config>
<aop ointcut
id="myOperation"
expression="execution(* org.poc.tx.Manager.*(..))"
/>
<aop:advisor
pointcut-ref="myOperation"
advice-ref="myTxAdvice"
/>
</aop:config>

<tx:advice id="myTxAdvice" >
<tx:attributes>
<tx:method
name="*"
read-only="true"
propagation="REQUIRED"
isolation="READ_COMMITTED"
timeout="5"
/>
</tx:attributes>
</tx:advice>

My assumption is, the above XML should run both Manager.insert() and Manager.update() within a single transaction will rollback insert(), if update() throws RuntimeException.

I have a main method that calls update and insert as follows:

public static void main(String args[]){
ApplicationContext ctx = new ClassPathXmlApplicationContext("my.xml");
Manager manager = (Manager) ctx.getBean("manager");
manager.insert();
manager.update();
}

The rollback successfully works, if I throw a RunTime exception inside insert method, right after successfully inserting the data as follows:

public void insert(final MyObj myObj){
HibernateCallback callback = new HibernateCallback() {
public Object doInHibernate(Session session)
throws HibernateException,SQLException {
session.insert(myObj);
throw new RuntimeException("ex thrown to rollback");
}
};
hibernateTemplate.execute(callback);
}

But if I want to spread it out to TWO separate methods in Manager class and want both the methods to participate in the same transaction, what should I do?

In a nutshell:

I want both Managaer.insert() and Manager.update() to participate in the same transaction.

I am invoking these two methods as follows in my main method:

manager.insert();
manager.update();

Can I invoke them separately and still make them participate in the same transaction?
 
Ritesh Agrawal
Ranch Hand
Posts: 74
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Did you ever get a response to this question? I am facing the same issue.
 
Mark Spritzler
ranger
Sheriff
Posts: 17278
6
IntelliJ IDE Mac Spring
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Wow, talk about waking the dead, that is almost a year old.

The answer is that he is not in a single transaction there. He has two transactions, one for each method, so the insert call started a transaction, completed and committed the transaction. Then the call to update creates a new transaction.

It is all because a call to manager.method is what is being wrapped by AOP. So if in the insert method it calls the update method directly, then it would all be in one transaction.

Mark
 
kurt hanni
Ranch Hand
Posts: 140
Eclipse IDE Java Mac
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Can I invoke them separately and still make them participate in the same transaction?

No you can't, because the scope of your transaction is in the manager class.

What you can do is make another method in your manager class to do your business logic (insert-then-update), then call this method in your main class
or
you can make your main class (class that calls insert then update) transactional. in this case insert-then-update is called in one method in your main class.

Its better practice to use the first approach.
 
Ritesh Agrawal
Ranch Hand
Posts: 74
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks for the responses.

Well, I tried to resolve the issue in a differnt way using Transactional Annotations. Below is the complete source code along with the application context. I have posted the same quesstion on Spring Forum at
http://forum.springsource.org/showthread.php?p=235791#post235791

Based on your explanation of not being in a single transaction, I had changed the code and put calls to two add methods in one method and made that method Transactional.

Please note that the posted JUnit Test case works fine and the first call to smartBaseBO.add is rolled back when the second call throws exception, but the same code is unable to roll back when used in an application. Thanks for helping me out with this.

Application Environment:

Spring 2.5.6
Hibernate 3.3.1 GA
Oracle 10g
tomcat 6.0.18



 
Ritesh Agrawal
Ranch Hand
Posts: 74
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi folks,

Looks like the above code works fine when the log level for the hibernate package is set to DEBUG. When I set it to INFO, it doesnt work. Its a weird issue and I have no clue why this is working this way. I would be thankful, if someone can provide some insight into this.

Thanks.
 
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic