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
Related
Using the annotation #Transactional spring executes the function past the repository save error to the following lines that shouldn't have been executed!!
Example: Using #Transactional on method
iEmployeeRepository.save(employee); <<-- Error occurs here
System.out.println("Hello"); <<-- This line still gets executed
I know #Transactional behaviour doesn't need a save, it automatically updates the ORM entity, according to this behaviour it looks like its running all the code and executes save repository by itself after all function code has run.
How can make sure #Transactional stop executing code when an error occurs when save repository is called?
save doesn't throw an exception. Due to JPAs write cache SQL statements are moved back as far as possible, which often mean to the end of the transaction, at which time all the collected changes will be flushed to the database. Any exceptions caused by that interaction will be raised at that time only.
This is JPA behaviour and independent of Spring.
You can avoid this by using JpaRepository.saveAndFlush(..)
This will force a flush right after the save and thereby trigger all errors early.
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.
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.
I am using Spring Hibernate integration in my application and DAO classes are extending HibernateDaoSupport.
Suppose I save some object using the code
getHibernateTemplate().save(object);
As Spring Hibernate integration doesn't mandate to write try-catch block, but suppose if any exception is thwron while saving that object.
Then what is the best way to handle it? I means should I catch it in the service layer and wrap it in some user defined excpetions.
Do I need to write try-catch in DAO layer method itself in case I want to log which method in DAO throws exception?
I have never used HibernateDaoSupport or Hibernate Template before so ignorant about exception handling. Please provide me your valuable inputs
The idea behind Spring using RuntimeException is that generally there are different types of exception:
Exceptions that you want to recover from (such as a DuplicateKeyException if a record that you're trying to insert already exists or the more general DataIntegrityViolationException if there was a DB constraint that was violated as a result of user input)
Exceptions that you can't recover from (the database is down)
For the first case, you may well handle the exception (either through a custom business exception, so that the view layer can redirect to the input page and provide a meaningful message)
For the second case, it would be easier to let the exception bubble up and have it handled by a generic exception handler that then displays a generic error page to the user. For this scenario it doesn't make sense to wrap the exception in a custom exception as you won't be able to recover. A blown up DB tends to be fatal.
So what I would do:
try {
getHibernateTemplate().save(object);
} catch (DataIntegrityViolationException dive) {
throw new BusinessValidationException(dive, "You've got the data wrong");
}
Spring exception hierarchy is well documented.
Usually you can't do much if you have a data access exception, because in the working system this may be caused by the shortage of diskspace on the DB server, or network connection problems etc.
Such exceptions are usually need to be logged and investigated as soon as possible.
There some recoverable errors, they can be handled with spring exception hierarchy, but imho most of them should be avoided during the developing phase, so your web server should validate as many things as possible, before it goes to the db.
If you want to set the exception logging see the similar questions:
Exception handler in Spring MVC
Spring MVC Best Practice Handling Unrecoverable Exceptions In Controller
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.