Manage rollback on transaction in my managed bean - java

I am using JPA/hibernate, Spring and JSF.
so my application is organized as following:
I have my entities,
My Dao Interface and implementation for each entity where I define basic methods: findById, add, update, remove ...
and then I have my service layer which just use DAO interfaces and where ther is basically the same methods as in my DAO.
My problem is that in my backing bean, I have a method Add_hospital(), which add a hospital and also services in that hospital, so my method looks like
add_hospital(){
add-hospital();
add-services();
add-Hospital-schedule();
}
so this method is a transaction and I want that if some issue happen, the transaction rollback, but I know that the rollback need to be managed in my DAO, will I need to define my method Add_hospital() in my managed bean, and it's in this stage where I have this combination of inserts.
Please how to solve this problem?

Transactions should be managed on the service layer, not data access.
Example from spring:
#Transactional(readOnly = true)
public class DefaultFooService implements FooService {
public Foo getFoo(String fooName) {
// do something
}
// these settings have precedence for this method
#Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW)
public void updateFoo(Foo foo) {
// do something
}
}

Related

What is the use of #Transactional with JPA and Hibernate?

I'm learning about how to create REST API with JPA and Hibernate and a MySQL database and I see this #Transactional annotation. Can someone explain what is the use of this annotation?
For example I have this simple DAO class:
#Repository
public class EmployeeDAOHibernateImpl implements EmployeeDAO {
// define field for entitymanager
private EntityManager entityManager;
// set up constructor injection
#Autowired
public EmployeeDAOHibernateImpl(EntityManager entityManager) {
this.entityManager = entityManager;
}
#Override
#Transactional
public List<Employee> findAll() {
// get the current hibernate session
Session currentSession = entityManager.unwrap(Session.class);
// create a query
Query<Employee> theQuery =
currentSession.createQuery("from Employee", Employee.class);
// execute query and get result list
List<Employee> employees = theQuery.getResultList();
// return the results
return employees;
}
}
You can see the #Transactional used for findAll() method, but if I delete this #Transactional I get the same output... then what is the use of this #Transactional?
#Transactional annotation is used when you want the certain method/class(=all methods inside) to be executed in a transaction.
Let's assume user A wants to transfer 100$ to user B. What happens is:
We decrease A's account by 100$
We add 100$ to B's account
Let's assume the exception is thrown after succeeding 1) and before executing 2). Now we would have some kind of inconsistency because A lost 100$ while B got nothing.
Transactions means all or nothing. If there is an exception thrown somewhere in the method, changes are not persisted in the database. Something called rollback happens.
If you don't specify #Transactional, each DB call will be in a different transaction.
Generally the #Transactional annotation is written at the service level.
It is used to combine more than one writes on a database as a single atomic operation.
When somebody call the method annotated with #Transactional all or none of the writes on the database is executed.
In the case of read operations it is not useful and so it is in case of a single atomic write. You are using it in a single read (select) so adding or removing the #Transactional annotation has no impact.
The class declares #Transactional on itself or its members, Spring creates a proxy that implements the same interface(s) as the class you’re annotating. In other words, Spring wraps the bean in the proxy and the bean itself has no knowledge of it.
A proxy provides a way for Spring to inject behaviors before, after, or around method calls into the object being proxied.
Internally, its the same as using a transaction advice (using AOP), where a proxy is created first and is invoked before/after the target bean’s method.
The generated proxy object is supplied with a TransactionInterceptor, which is created by Spring. So when the #Transactional method is called from client code, the TransactionInterceptor gets invoked first from the proxy object, which begins the transaction and eventually invokes the method on the target bean. When the invocation finishes, the TransactionInterceptor commits/rolls back the transaction accordingly

what is the difference between using #Transactional in dao layer and in service layer?

What is the difference between using #Transactional in dao layer and in service layer?
#Transactional
class UserDAO{}
or
#Transactional
class UserService{}
We can put this annotation in both the layers. So what is the difference?
if you add #Transactional annotation at Service layer and you are performing multiple operations on database, then all these operations will be in a single transaction and with that you can make sure that both the operations are commited, if any of them failed then roll back.
For example: There is a case you want to create an Employee and your business rule says that for every Employee you create, you need to create User in your database. In such case we would use Transactional annotation at service layer
#Service
public class EmployeeService {
....
#Transactional
public int createEmployee(Employee emp) {
//create Employee
employeeDao.createEmployee(emp);
User user = new User();
// some fileds of employee are used to create a User
user.setEmployeeId(emp.getEmployeeId());
....
userDao.createUser(user);
...
}
}
There is no difference at all. But best practice is use it in Service layer. Cause sometimes you need to make transaction through more than one entity. So if you declare transactions in your dao manually. And you call method from service with two methods from your daos you will have two transactions in one call. And that is something what you don't want.

Complete transaction with multiple dao in service class

How do I achieve a complete transaction where a service class requires more than one data access object. Assuming I have the following structure.
Currently, if my dao2 failed, the dao1 still being committed to the database which I do not want it to happen. However, I need my DAO to be reusable.
public class mainService(){
dao1.store(obj1);
dao2.store(obj2);
}
And my dao is written in this way.
Dao 1
private EntityManager entityManager;
#Transactional
public void store(Object obj1){
entityManager.persist(obj1);
}
Dao 2
private EntityManager entityManager;
#Transactional
public void store(Object obj2){
entityManager.persist(obj2);
}
Please help.
Make this happen in one transaction.
#Transactional
public void mainService(..){
dao1.store(obj1);
dao2.store(obj2);
}
Only one transaction will be created, and if dao2 fails, dao1 won't be committed as well. And remove #Transactional from store method. Making DB level methods transactional it's not a good idea. This level might be two low in some cases.
The obvious answer is to use:
private EntityManager entityManager;
#Transactional
public void store(Object obj1, Object obj2){
entityManager.persist(obj1);
entityManager.persist(obj2);
}
What's happened is that you have become hung up on using DAOs. The DAO is dead! If you look at the EntityManager API you will notice that it actually looks very much like a DAO type of interface. So just use it directly where ever you would normally consider using a DAO.
In your case, you should mark mainService() with #Transactional too, For transaction propagation rule is PROPAGATION_REQUIRED by default , and then both dao1.store() and dao2.store() with be under the same transaction.It's OK to keep dao1.store() and dao2.store() #Transactional, they will realize that there is already a transaction and then join the transaction.

Write Less DAOs with Spring Hibernate using Annotations

My Spring+Hibernate configuration files are small and super tight. I use auto scanning to find my model entities/daos.
I don't want to have to write a DAO + DAOImpl for EVERY Entity in my hierarchy.
Some may qualify to have their own, like if they have complex relationships with other entities and require more than basic CRUD functionality. But for the rest...
Is there any way to circumvent the defacto standard?
Say, something like a generic DAO, ex:
http://www.ibm.com/developerworks/java/library/j-genericdao/index.html
Then I can do something like
GenericDao dao = appContext.getBean("genericDao");
dao.save(car);
dao.save(lease);
Is this possible with annotations? I don't want to have to configure anything in xml. If I cannot do above, is it still possible to have one GenericDaoImpl.java with something like:
#Repository("carDao")
#Repository("leaseDao")
class GenericDaoImpl extends CustomHibernateDaoSupport implements GenericDao {
...
}
and then
GenericDao dao = appContext.getBean("carDao");
dao.save(car);
dao = appContext.getBean("leaseDao"); //carDao is garbage coll.
dao.save(lease);
Is this practical at all?
Using generics, you might try something like this:
#Repository
#Transactional
public class GenericDAOImpl<T> implements GenericDAO<T> {
#Autowired
private SessionFactory factory;
public void persist(T entity) {
Session session = factory.getCurrentSession();
session.persist(entity);
}
#SuppressWarnings("unchecked")
public T merge(T entity) {
Session session = factory.getCurrentSession();
return (T) session.merge(entity);
}
public void saveOrUpdate(T entity) {
Session session = factory.getCurrentSession();
session.saveOrUpdate(entity);
}
public void delete(T entity) {
Session session = factory.getCurrentSession();
session.delete(entity);
}
}
The content may be different, but the general idea is applicable.
You should be able to then autowire the DAO in your controller and service classes by using
#Autowired
private GenericDAO<Car> carDao;
You can combine Spring/Hibernate with JPA, which provides the EntityManager for a large amount of basic persistence tasks:
#Service
public class CarService {
#PersistenceContext
private EntityManager em;
public void saveCarAndLease(Car car, Lease lease) {
em.persist(car);
em.persist(lease);
}
}
It will also handle transactions and simple queries without needing to write a DAO. For the more complex operations, you can still write a DAO and fall back to Hibernate's SessionFactory (although JPA is an option here too).
Some tutorials suggest you should still write the DAO for abstraction of the JPA plumbing. However, I have personally found this unnecessary (JPA has a very small integration footprint), and in fact this is also the way Spring Roo deals with the data layer behind the scenes.
Have you tried to use Spring Data. I mean to say Spring JPA where you can use repositories.
You can eliminate writing all stuffs for each entity.

Mixing declarative and programmatic transactions with Spring and JPA listeners

I'm using a JPA EntityListener to do some additional audit work and am injecting a Spring-managed AuditService into my AuditEntryListener using #Configurable. The AuditService generates a collection of AuditEntry objects. The AuditService is itself a Singleton scoped bean, and I'd like to gather all the AuditEntry objects under a common key that can then be accessed by the outermost service layer (the one that invoked the persist call which in turn triggered the EntityListener).
I'm looking at using Spring's TransactionSynchronizationManager to set a specific transaction name (using UID() or some other unique strategy) at the beginning of the transaction, and then using that name as a key within the AuditService that will allow me to group all AuditEntry objects created within that transaction.
Is mixing declarative and programmatic transaction management have the potential for trouble? (Though I'm doing nothing more than setting the transaction name). Is there a better way to associate the generated AuditEntry objects with the current transaction? This solution does work for me, but given that the TransactionSynchronizationManager isn't intended for application use, I'd like to make sure that my use of it won't cause some unforseen problems.
Related Question
Finally, a related, but not immediately pertinent question: I know that the documentation for JPA EntityListeners cautions against using the current EntityManager, but if I did want to use it to diff an object against it's persisted self, would I be safe using an #Transactional(propagation=REQUIRES_NEW) annotation around my preUpdate() method?
Prototype Code:
Service Class
#Transactional
public void create(MyEntity e) {
TransactionSynchronizationManager.setCurrentTransactionName(new UID().toString());
this.em.persist(e);
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
#Override
public void afterCommit() {
Set<AuditEntry> entries = auditService.getAuditEntries(TransactionSynchronizationManager.getCurrentTransactionName());
if(entries != null) {
for(AuditEntry entry : entries) {
//do some stuff....
LOG.info(entry.toString());
}
}
}
});
}
JPA EntityListener
#Configurable
public class AuditEntryListener {
#Autowired
private AuditService service;
#PreUpdate
public void preUpdate(Object entity) {
service.auditUpdate(TransactionSynchronizationManager.getCurrentTransactionName(), entity);
}
public void setService(AuditService service) {
this.service = service;
}
public AuditService getService() {
return service;
}
}
AuditService
#Service
public class AuditService {
private Map<String, Set<AuditEntry>> auditEntryMap = new HashMap<String, Set<AuditEntry>>();
public void auditUpdate(String key, Object entity) {
// do some audit work
// add audit entries to map
this.auditEntryMap.get(key).add(ae);
}
}
#Filip
As far as I understand, your requirement is:
Have an unique token generated within each transaction (database
transaction of course)
Keep this unique token easily accessible across all layers
So naturally you're thinking about the TransactionSynchronizationManager provided by Spring as a facility to store the unique token (in this case, an UID)
Be very carefull with this approach, the TransactionSynchronizationManager is the main storage helper to manage all the #Transactional processing for Spring. Under the #Transactional hood, Spring is creating an appropriate EntityManager, an appropriate Synchronization object and attach them to a thread local using TransactionSynchronizationManager.
In your service class code, inside a #Transactional method your are tampering with the Synchronization object, it can end up with undesirable behavior.
I've done an indept analysis of how #Transactional works here, have a look: http://doanduyhai.wordpress.com/2011/11/20/spring-transactional-explained/
Now back to your needs. What you can do is:
Add a Thread local to the AuditService, containing the unique token when entering the #Transactional method and destroy it when exiting the method. Within this method call, you can access the unique token in any layer. Explanation for ThreadLocal usage can be found here: http://doanduyhai.wordpress.com/2011/12/04/threadlocal-explained/
Create a new annotation, let's say #Auditable(uid="AuditScenario1") to annotate methods that need to be audited and use Spring AOP to intercept these method calls and manage the Thread local processing for you
Example:
Modified AuditService
#Service
public class AuditService {
public uidThreadLocal = new ThreadLocal<String>();
...
...
}
Auditable annotation
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.METHOD)
#Documented
public #interface Auditable
{
String uid();
}
Usage of #Auditable annotation
#Auditable(uid="AuditScenario1")
#Transactional
public void myMethod()
{
// Something
}
Spring AOP part
#Around("execution(public * *(..)) && #annotation(auditableAnnotation))
public Object manageAuditToken(ProceedingJoinPoint jp, Auditable auditableAnnotation)
{
...
...
AuditService.uidThreadLocal.set(auditableAnnotation.uid())...
...
}
Hope this will help.
You can come up with a solution using the TransactionSynchronizationManager. We register a "TransactionInterceptorEntityListener" with JPA as an entity-listener. What we wanted to achieve is the ability to listen to CRUD events such that we can work with a spring managed "listener" that has a lifecycle tied to the current transaction (i.e., spring-managed but instance per transaction). We sub-class the JPATransactionManager and introduce in the prepareSynchronization() method, a hook to setup a "TransactionInterceptorSynchronizer." We also use the same hook for allow code (in programmatic tx) to associate and retrieve arbitrary objects with the current transaction and also register jobs that run before/after transaction commit.
The overall code is complex, but definitely do-able. If you use JPATemplates for programmatic tx, it is tough to achieve this. So we rolled our own template that simply calls the JPA template after taking care of the interceptor work. We plan to open-source our JPA library (written on top of Spring's classes) soon.
You can see a pattern of adding custom transactions and hooks with Spring managed transactions in the following library for Postgresql

Categories

Resources