1

I have a web app using Hibernate, and I am attempting to persist some data, but it is failing to persist within a Transaction despite using the @Transactional annotation.

My service class is as follows:

@Service("profileService")
public class ProfileService {
    private EntityManager entityManager;

    @Autowired
    private AccountService accountService;

    @Autowired
    private ProfileDAOImpl profileDao;

    @PersistenceContext
    public void setEntityManager(EntityManager em) {
        this.entityManager = em;
    }

    @Transactional
    public void addConnectionToAccount(SocialConnection sc) {
        entityManager.persist(sc);
    }

}

The addConnectionToAccount() method is being called from another Spring bean in a normal method, and the ProfileService class is currently being injected there:

public class HibernateConnectionRepository implements ConnectionRepository {

    @Inject
    private ProfileService profileService;

    @Override
    @Transactional
    public void addConnection(SocialConnection sc) {
        try {
            profileService.addConnectionToAccount(accountId, sc);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

I tried putting the @Transactional annotation on the calling method in the vain hope that it might make a difference but nothing.

Previously I have experienced problems like this its been because the object being persisted does not satisfy table restrictions (such as non-nullable columns as null) or because the method is being called from within the same class and the calling method is not Transactional, but neither of those are the case here..

Any ideas? it just fails silently, the logs are as follows:

2012-03-26 22:25:04,702 [http-bio-8085-exec-9] DEBUG com.mchange.v2.resourcepool.BasicResourcePool - trace com.mchange.v2.resourcepool.BasicResourcePool@1bc25c8 [managed: 3, unused: 2, excluded: 0] (e.g. com.mchange.v2.c3p0.impl.NewPooledConnection@e5b006)
2012-03-26 22:25:04,710 [http-bio-8085-exec-9] DEBUG org.hibernate.SQL - select SEQ_COUNT from SEQUENCE where SEQ_NAME = 'PO_SEQ' for update
2012-03-26 22:25:04,711 [http-bio-8085-exec-9] DEBUG org.hibernate.SQL - update SEQUENCE set SEQ_COUNT = ? where SEQ_COUNT = ? and SEQ_NAME = 'PO_SEQ'
2012-03-26 22:25:04,723 [http-bio-8085-exec-9] DEBUG com.mchange.v2.resourcepool.BasicResourcePool - trace com.mchange.v2.resourcepool.BasicResourcePool@1bc25c8 [managed: 3, unused: 2, excluded: 0] (e.g. com.mchange.v2.c3p0.impl.NewPooledConnection@e5b006)
2012-03-26 22:25:04,723 [http-bio-8085-exec-9] DEBUG org.hibernate.event.internal.AbstractSaveEventListener - Generated identifier: 2200, using strategy: org.hibernate.id.MultipleHiLoPerTableGenerator

UPDATE

Also wanted to mention that the HibernateConnectionRepository bean is not annotated and is actually being configured in an @Configuration class (if this makes any difference? not used @Configuration classes much).

The method to create the bean is as follows:

@Bean
@Scope(value = "request", proxyMode = ScopedProxyMode.INTERFACES)
public ConnectionRepository connectionRepository() {
    Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
    if (authentication == null) {
        throw new IllegalStateException("Unable to get a ConnectionRepository: no user signed in");
    }
    ApplicationUser user = (ApplicationUser) authentication.getPrincipal();
    return usersConnectionRepository().createConnectionRepository(String.valueOf(user.getAccountId()));
}

The bean is scoped to the logged in user, but may also be created multiple times for each user..

rhinds
  • 9,976
  • 13
  • 68
  • 111

2 Answers2

1

Still some things to look at (though you have a good start with the constraints and calling from the same bean):

  • is <tx:annotation-driven /> present in your xml file
  • is it certain that a transaction is not started? Check with TransactionSynchronizationManager.isActualTransactionActive(). It might be a a different (not transaction related issue)
Bozho
  • 588,226
  • 146
  • 1,060
  • 1,140
  • yep, have the annotation-driven config (using aspectJ as the mode rather than proxy). I had previously tried adding entityManager.flush(); after the persist call and I had the error "transaction not in progress" - but will check with your suggested code. Thanks - will let you know how that works – rhinds Mar 26 '12 at 21:33
  • Ok, have checked using the Transaction Sync manager - definitely no Transaction. However, it gets stranger.. I added entityManager.flush() just to test it earlier (and got the no transaction error), I then removed the flush call and cleaned projects/restarted tomcat in eclipse, and the first time I'm in the app it manages to commit the data (i have the row in the DB to prove it) - but further attempts to re-create the functionalit fail and cannot persist anything else (have tried re-cleaning/restarting etc).. Any idea why the transactional would be started sometimes but not always? – rhinds Mar 26 '12 at 21:38
  • not until I look through the whole project, which I can't do. But you mentioned aspectJ - try using the proxy mode instead. – Bozho Mar 26 '12 at 21:40
  • Did try removing the aspectJ but then some standard autowiring started failing in other parts of the project. Maybe I will try again with that approach. – rhinds Mar 26 '12 at 21:43
  • I have updated my original question with some details about how the calling bean is being configured - being handled in a @Configuration class, not sure if that has an effect? – rhinds Mar 26 '12 at 21:48
  • I am still trying to get to the bottom of this - and trying to investigate whether or not having config in both XML and an Configuration class is going to cause any issues (doesnt seem to according to the documents) - I have the tx:annotation-driven config in my XML, will this apply to beans configured in my Configuration class? or do I need to do anything to ensure that classes there are picked up by the annotation-driven config? – rhinds Mar 27 '12 at 16:54
  • generally, they don't interfere. We are using them together without problems – Bozho Mar 27 '12 at 21:34
0

The error was a problem with the aspects not firing properly.

Related to this problem: Let eclipse use maven to compile/weave my code that occurs using new versions of Eclipse and M2E.

The Eclipse clean wasnt weaving the aspects, so the transactional annotations werent being woven. It obviosuly worked intermittently because when i did a normal maven clean install (command line etc) then the weaving would be done (the Eclipse clean then un-did the weaving, so if i did maven clean install then an eclipse re-build it would not work).

I fixed this by adding an AspectJ builder to my project in Eclipse, and now when I run clean/build automatically it weaves it correctly.

Community
  • 1
  • 1
rhinds
  • 9,976
  • 13
  • 68
  • 111