Exception "Unable to commit: transaction marked for rollback" when using camel-jpa and JTA Transactions - osgi

I am currently working on a Tutorial to show camel-jpa on Karaf together with JTA Transactions. I use the following route:
from("jpa://net.lr.tutorial.karaf.camel.jpa2jms.model.Person").id("jpa2jms")
.transacted()
.marshal(df)
.bean(new ExceptionDecider())
.to("jms:person");
So I checked if the transactions work by throwing an exception in ExceptionDecider. When I do this I get the following Exception:
https://gist.github.com/3150591
Any ideas what I do wrong? I suspect it might be the way I setup the transaction manager.
You can find my whole project on github:
https://github.com/cschneider/Karaf-Tutorial/tree/master/cameljpa/jpa2jms

This happens when the transaction is marked inside an exception handler but the exception is swallowed. Normally such exceptions should bubble up and cause the whole transaction to rollback.
If the exception is swallowed instead then camel tries to commit at the end which results in the above exception.

Related

Spring Transaction - Do not rollback for error under specific method

I have a Spring Boot application in which a service is responsible to create a Business Entity. For simplicity, let's consider:
create(Object toCreate) {
validationService.validate(toCreate);
Object created = repository.save(toCreate);
notificationService.notify(created);
}
Business has changed and now I would like the creation to not fail if notification fails.
I therefore wrapped the notify() method in a try-catch block that only logs the error (which is a RuntimeException).
However when tested, a transaction rollback error was thrown, saying the connection was closed. I do not want any rollback, especially since the NotificationService does not modify the database.
How can I tell Spring that any exception happening in the NotificationService is fine and does not require a rollback? I tried annotating the class/method with #Transactional(propagation=NEVER) but got existing transaction found for transaction marked with propagation 'never'
Perhaps refactoring your code would help better than the introduction of more complex transaction handling.
Assuming your #Transactional is on the create() method, we can see that you have:
Pre-persistence business logic
Persistence logic
Post-persistence business logic
It depends on your use-case, but I would not expect pts. 1 & 3 to contain persistence logic. If that is the case, you could extract your persistence logic in its own service that would itself be a transaction, not the parent.
If you have the need for a transaction in those steps, you could also extract them in their own transaction.
Other leads might be:
The default rollback behavior is for runtime unchecked exceptions. You could use checked exceptions to avoid the rollback.
If your notification is separate from persistence and you do not care about the transaction, you could make it an asynchronous call (e.g. with #Async). It would be scheduled outside of the transaction in its own context.
You can use the option norollbackfor of #Transactional so you have to specify an exception class not the service and when an error occurs in notifications try to throw a specifc error which would not cause a rollback.

Spring Data Mongo : Rollback if exception occurs

I'm working on a project using Spring Data and MongoDB.
I'm wondering if there is some kind of solution to rollback when some exception (standard or custom) occurs.
I tried this solution but unfortunately it didn't work :
#Transactional(rollbackFor = SomeException.class)
For the moment I'm doing the rollback manually by saving what's already deleted and vis-versa.
NOTE: The exception may occur when contacting a foreign micro-service using http.
NOTE2 : I'm using an Exception handler, I removed it and still not working.

spring #transactional noRollbackFor unexpectedly rollsback...any clue?

I have following problem :
Servers runs on WL 12.
The main code is in a EAR, in methods with #Transactional explicitly written as NoRollbackFor=RuntimeException.class
When the exception occurs inside the EAR code, the noRollbackFor is correctly taken into account.
However, when the error occurs in a remote call to another WAR, the transaction is flagged as setRollbackOnly, and subsequent calls to the dabatase (read operations) fail (even if the exception is trapped in the calling code).
Any idea as to why this happens / how to avoid this ?
Thanks !
Make sure that your exception is of type RuntimeException, which triggers a rollback, but checked exception does not

How to track JTA transactions

We have JTA transactions(Atomikos) configured using Spring annotations across different places in our application. I need to get trace logs whenever a transaction started and completed.
For example, whenever the below method invoked within a new transaction,
#Transactional
void createAgent() { ... }
I need to log a message saying
Transaction started on AgentFactory::createAgent() ...
Transaction ended on AgentFactory::createAgent() ...
Can you please provide if there is any way to enable trace logging on transactions?
If you set loglevel to DEBUG or TRACE for org.springframework.transaction
you get the log entries you want. May be not in the exact format, but the information is provided.

Transaction not rolling back

I have mybatis 3.0.4 with mybatis-spring integration 1.0.1 deployed within Fuse (OSGi). I've created a basic database within SQLServer 2008. In Spring I've configured a TransactionAwareDataSourceProxy data source and a DataSourceTransactionManager transaction manager.
Now I've created my own bundle to be deployed within Fuse which inserts some rows into the database. I've told the bundle to use the configured data source and transaction manager. The method which carries out the logic looks like this:
#Transactional(propagation=Propagation.REQUIRED)
public void go(RecsCashContext context) throws ActionException {
When this method throws an exception I can follow Spring through seeing the expected behaviour triggered. This leads me to Springs JtaTransactionManager and doRollBack(..).
So everything looks promising, except that when I look at the database, sure enough it's in an unstable state as previous inserts have not been roll back.
I'm at a loss on this one and I'm struggling to find any information online. Any thoughts?
What kind of exception is being thrown? Unless you tell Spring to explicitly rollback when a particular exception is thrown, it will proceed. By default, Spring's transaction handling only rolls back when an unchecked exception (e.g. RuntimeException) is thrown. In your case, if you're expecting the rollback to occur when ActionException occurs, you're out of luck unless you make the following modification:
#Transactional(rollbackFor={ActionException.class})
public void go(RecsCashContext context) throws ActionException {
More details are in here, specifically in section 10.5.6.1, #Transactional settings
As it turns out Fuse (servicemix) already exposes a transaction manager via an OSGi service within bundle org.apache.aries.transaction.manager_0.2.0.incubating [49]. As a result when I was looking up the transaction manager service, the one exposed by bundle 49 got picked up first.
This was resolved by clearly specifying the transaction manager I was interested in. At the moment I am doing this using the bean-name propery:
<osgi:reference id="transactionManager" bean-name="transactionManager" interface="org.springframework.transaction.PlatformTransactionManager" />
Though this could also be done by using a filter, but preferably we'll just make use of the transaction manager service that's already being expose as opposed to providing our own.

Resources