No Session Hibernate in @PostConstruct
Asked Answered
C

3

3

MyDao class have the methods to do whole persistence tasks through Hibernate SessionFactory, it works fine.

I inject MyDao in MyService as can see above, but when @PostConstruct init() method is called after injected MyDao (debugging I can see MyDao well injected) get the next Hibernate exception:

org.hibernate.HibernateException: No Session found for current thread

My service implementation.

@Service("myService")
@Transactional(readOnly = true)
public class MyServiceImpl implements MyService {

    @Autowired
    private MyDao myDao;
    private CacheList cacheList;

    @PostConstruct
    public void init() {

        this.cacheList = new CacheList();
        this.cacheList.reloadCache(this.myDao.getAllFromServer());
    }

    ...
}

WAY TO SOLVE

As @Yogi recommended above to me, I have used TransactionTemplate to get one valid/active transaction session, in this case I have implemented throught constructor and works fine for me.

@Service("myService")
@Transactional(readOnly = true)
public class MyServiceImpl implements MyService {

    @Autowired
    private MyDao myDao;
    private CacheList cacheList;

    @Autowired
    public void MyServiceImpl(PlatformTransactionManager transactionManager) {

        this.cacheList = (CacheList) new TransactionTemplate(transactionManager).execute(new TransactionCallback(){

            @Override
            public Object doInTransaction(TransactionStatus transactionStatus) {

                CacheList cacheList = new CacheList();
                cacheList.reloadCache(MyServiceImpl.this.myDao.getAllFromServer());

                return cacheList;
            }

        });
    }

    ...
}
Caudad answered 5/3, 2014 at 9:27 Comment(1)
Your code has a 'void' where I would not expect one: public void MyServiceImpl. Should this be a constructor or is this a method that you call from somewhere else?Bluma
P
6

I don't think there is any transaction allowed on @PostConstruct level so @Transactional won't do much here unless mode is set to aspectj in <tx:annotation-driven mode="aspectj" />.

As per this discussion you can use TransactionTemplate to start manual transaction inside init() to bind session but if you intend to strictly adhere to declarative transaction you need to use ApplicationListener to register event and user ContextRefreshedEvent to initiate transaction.

Pudency answered 5/3, 2014 at 9:56 Comment(1)
Thank you very much, TransactionTemplate work fine for me. ;)Caudad
A
0

Make sure you are running under transaction. I can see the transaction annotation but looks like you missed to activate the transaction management using annotation through the use of using <tx:annotation-driven/> tag in spring context.

Apoplexy answered 5/3, 2014 at 9:45 Comment(0)
O
0

This happens because MyServiceImpl.init() is called by Spring after MyServiceImpl related bean construction and @Transaction annotation is not used to manage session lifecycle.
A solution might be consider Spring AOP around methods that use the cache instead of @PostConstruct

Orfinger answered 5/3, 2014 at 9:46 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.