Transaction commit just does not work.
mader Feb 3, 2011 8:34 AMI have these classes:
@Name("someService")
@Scope(ScopeType.APPLICATION)
@AutoCreate
public class SomeService implements Serializable
{
@In(create = true)
private InterfaceToSomeBean someBean;
@In
private EntityManager entityManager;
@Asynchronous
@Transactional // yes, already must be here because of "some doing here"
public synchronized QuartzTriggerHandle execute(@Expiration Date when, @IntervalDuration long interval)
{
// ...some doing here...
someBean.callOne();
// ...some doing here...
someBean.callTwo();
// ...some doing here...
}
}
@Name("someBean")
@Scope(ScopeType.SESSION)
public class SomeBean implements InterfaceToSomeBean, Serializable
{
@In
private EntityManager entityManager;
// BOTH of these does NOT work
//@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
//@Transactional
public void callOne()
{
// do some long updates/inserts/other horrible, horrible things to data
}
// BOTH of these does NOT work
//@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
//@Transactional
public void callTwo()
{
// do another series of long updates/whatever
}
}
public interface InterfaceToSomeBean
{
public void callOne();
public void callTwo();
}
I tried both @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) and @Transactional for callOne() and callTwo(). Does not work. AFAIK there is no way to enforce commit in middle of method (flush() does something else). Nice design decisions you have there.
What I wanted to achieve: after calling callOne() there is end of transaction and all data commits (and are readable for rest of system). Same with callTwo().
What I get in reality: unfortunately, everything is commited AFTER end of service execute() call. Until then service happily prevents half of system from reading (just READING) data.
I do not know if removing "@Transactional" from execute() would help, but it would be very inconvenient due to some other code in this service (throws javax.persistence.TransactionRequiredException because of entityManager.flush() call).
@Name("someService")
@Scope(ScopeType.APPLICATION)
@AutoCreate
public class SomeService implements Serializable
{
@In(create = true)
private InterfaceToSomeBean someBean;
@In
private EntityManager entityManager;
@Asynchronous
@Transactional // yes, already must be here because of "some doing here"
public synchronized QuartzTriggerHandle execute(@Expiration Date when, @IntervalDuration long interval)
{
// ...some doing here...
someBean.callOne();
// ...some doing here...
someBean.callTwo();
// ...some doing here...
}
}
@Name("someBean")
@Scope(ScopeType.SESSION)
public class SomeBean implements InterfaceToSomeBean, Serializable
{
@In
private EntityManager entityManager;
// BOTH of these does NOT work
//@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
//@Transactional
public void callOne()
{
// do some long updates/inserts/other horrible, horrible things to data
}
// BOTH of these does NOT work
//@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
//@Transactional
public void callTwo()
{
// do another series of long updates/whatever
}
}
public interface InterfaceToSomeBean
{
public void callOne();
public void callTwo();
}
I tried both @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) and @Transactional for callOne() and callTwo(). Does not work. AFAIK there is no way to enforce commit in middle of method (flush() does something else). Nice design decisions you have there.
What I wanted to achieve: after calling callOne() there is end of transaction and all data commits (and are readable for rest of system). Same with callTwo().
What I get in reality: unfortunately, everything is commited AFTER end of service execute() call. Until then service happily prevents half of system from reading (just READING) data.
I do not know if removing "@Transactional" from execute() would help, but it would be very inconvenient due to some other code in this service (throws javax.persistence.TransactionRequiredException because of entityManager.flush() call).