4

I'm experimenting with Java EE 7, CDI, JPA and JSF.

When the webapp starts, I would like to run an initialization method in my CDI bean (marked with @PostConstruct) that does some work with the database (inserts some rows etc..). For this I need a transaction, but this wasn't as easy as I expected.

I have tried adding @Transactional annotation to my method, but apparently it only works with EJB. I actually tried converting my bean to EJB instead of CDI bean, but I still didn't get transaction to my @PostConstruct method. It worked with other methods in the bean, but not with my @PostConstruct initialization method.

Then I read about creating method interceptor to get transactions to CDI beans:

http://eubauer.de/kingsware/2012/01/16/cdi-and-transactions-e-g-in-jboss-7-0-2/

I tried this too, but no luck. It doesnt work either.

So how does one get transactions to a @PostConstruct initialization method in a CDI bean?

StrangeLoop
  • 521
  • 1
  • 6
  • 17
  • Why do you say that it only works with EJB? Java EE 7 added `@Transactional` support for CDI as well, moving transactions to its own spec. – John Ament Nov 10 '13 at 01:59
  • You're right about regular methods, but it doesn't seem to be working with `@PostConstruct` initializer method for some reason. It would seem like a natural place to do some database related initialization work requiring a transaction. Maybe there is some other way to do this kind of thing? – StrangeLoop Nov 10 '13 at 08:52
  • This sounds like a bug then in your app server. What app server are you using? – John Ament Nov 10 '13 at 13:58
  • Forgot to mention that, its GlassFish Server Open Source Edition 4.0 (build 89) – StrangeLoop Nov 10 '13 at 14:09
  • confirm that trying to call an EJB to persist or do any operation on the database from a postConstruct() method inside CDI bean doesn't work. I am also using GlassFish Server 4.0 – dendini Dec 23 '13 at 09:03

1 Answers1

2

Apparently it seems that:

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 the only way to do something with the database from the @PostConstruct is 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
            }
        });
   }
}

NOTE: similar thread but referencing Spring framework @Transactional on @PostConstruct method

Community
  • 1
  • 1
dendini
  • 3,842
  • 9
  • 37
  • 74
  • In a managed bean with application scope with `@ManagedBean(eager = true)` queries and persisting seems to work with EclipseLink 2.4.2, but not Hibernate 5.2.10.Final (causes `LazyInitializationException`). – Kalle Richter Jun 04 '17 at 23:57