@Transactional on @PostConstruct method

Inject self and call through it the @Transactional method

public class AccountService {

    @Autowired
    private AccountService self;

    @Transactional
    public void resetAllAccounts(){
        //... 
    }

    @PostConstruct
    private void init(){
        self.resetAllAccounts();
    }

}

For older Spring versions which do not support self-injection, inject BeanFactory and get self as beanFactory.getBean(AccountService.class)

EDIT

It looks like that since this solution has been posted 1.5 years ago developers are still under impression that if a method, annotated with @Transactional, is called from a @PostContruct-annotated method invoked upon the Bean initialization, it won't be actually executed inside of Spring Transaction, and awkward (obsolete?) solutions get discussed and accepted instead of this very simple and straightforward one and the latter even gets downvoted.

The Doubting Thomases :) are welcome to check out an example Spring Boot application at GitHub which implements the described above solution.

What actually causes, IMHO, the confusion: the call to @Transactional method should be done through a proxied version of a Bean where such method is defined.

  1. When a @Transactional method is called from another Bean, that another Bean usually injects this one and invokes its proxied (e.g. through @Autowired) version of it, and everything is fine.

  2. When a @Transactional method is called from the same Bean directly, through usual Java call, the Spring AOP/Proxy machinery is not involved and the method is not executed inside of Transaction.

  3. When, as in the suggested solution, a @Transactional method is called from the same Bean through self-injected proxy (self field), the situation is basically equivalent to a case 1.


As an update, from Spring 4.2 the @EventListener annotation allows a cleaner implementation:

@Service
public class InitService {

    @Autowired
    MyDAO myDAO;

    @EventListener(ContextRefreshedEvent.class)
        public void onApplicationEvent(ContextRefreshedEvent event) {
        event.getApplicationContext().getBean(InitService.class).initialize();
    }

    @Transactional
    public void initialize() {
        // use the DAO
    }

}


Quote from legacy (closed) Spring forum:

In the @PostConstruct (as with the afterPropertiesSet from the InitializingBean interface) there is no way to ensure that all the post processing is already done, so (indeed) there can be no Transactions. The only way to ensure that that is working is by using a TransactionTemplate.

So if you would like something in your @PostConstruct to be executed within transaction you have to do something like this:

@Service("something")
public class Something {
    
    @Autowired
    @Qualifier("transactionManager")
    protected PlatformTransactionManager txManager;

    @PostConstruct
    private void init(){
        TransactionTemplate tmpl = new TransactionTemplate(txManager);
        tmpl.execute(new TransactionCallbackWithoutResult() {
            @Override
            protected void doInTransactionWithoutResult(TransactionStatus status) {
                //PUT YOUR CALL TO SERVICE HERE
            }
        });
   }
}

I think @PostConstruct only ensures the preprocessing/injection of your current class is finished. It does not mean that the initialization of the whole application context is finished.

However you can use the spring event system to receive an event when the initialization of the application context is finished:

public class MyApplicationListener implements ApplicationListener<ContextRefreshedEvent> {
  public void onApplicationEvent(ContextRefreshedEvent event) {
    // do startup code ..
  }    
}

See the documentation section Standard and Custom Events for more details.