Tuesday, June 23, 2009

Spring JPA annotation transaction.

It has been weeks I could not figure out why I can not use annotation based transaction control, and it forced me to use programmatic transaction control. Today I found this post from theserverside, which explains everything.

it's caused by the use of the BeanFactory instead of an ApplicationContext, which is used inside the unit test, behind the scene when using the AbstractJpaTests base class.

If you change your Main class to

public class Main {

public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("context/testContext.xml");
PersonDAO dao=(PersonDAO)ctx.getBean("personDAO");

Person p=new Person();
it will work.

The reason for that is a slightly different behavior between a BeanFactory and an ApplicationContext when it comes to BeanPostProcessors. From the Spring reference manual:

It is important to know that a BeanFactory treats bean post-processors slightly differently than an ApplicationContext. An ApplicationContext will automatically detect any beans which are defined in the configuration metadata which is supplied to it that implement the BeanPostProcessor interface, and register them as post-processors, to be then called appropriately by the container on bean creation. Nothing else needs to be done other than deploying the post-processor in a similar fashion to any other bean. On the other hand,
when using a BeanFactory implementation, bean post-processors explicitly have to be registered, with code
like this:

ConfigurableBeanFactory factory = new XmlBeanFactory(...);
// now register any needed BeanPostProcessor instances
MyBeanPostProcessor postProcessor = new MyBeanPostProcessor();
// now start using the factory

This explicit registration step is not convenient, and this is one of the reasons why the various
ApplicationContext implementations are preferred above plain BeanFactory implementations in the vast majority of Spring-backed applications, especially when using BeanPostProcessors

That's the whole reason, why your PersistenceAnnotationBeanPostProcessor never got loaded and therefore couldn't do its work!

No comments:

Post a Comment