Why @Configurable and @Transactional don’t belong to into the same class

When using the Spring framework, one can still benefit from dependency injection etc. even if a bean is not obtained from a bean factory by using the @Configurable annotation, f.e.:

@Configurable(value = "myBean")
public class MyBean {
   ...
}

Where myBean is the bean id in the spring context.

This approach can be somewhat problematic, though, when used in conjunction with aspect-oriented features.
Say, for example, you also want to use JPA and require a transactional behavior.

You would usually do the following:

@Configurable(value = "myBean")
public class MyBean {
   @Transactional
    public void foo() {
    ...
    }
}

This will not work, but lead to an exception like this:


java.lang.IllegalStateException: Post-processor tried to replace bean instance of type [my.package.MyBean] with (proxy) object of type [my.package.MyBean$$EnhancerByCGLIB$$c029ddbf] - not supported for aspect-configured classes!

The reason is that @Configurable will ask spring to configure the current bean during constructor invokation. During configuration, a number of bean post processors will be invoked on the bean, and one of them, namely the InfrastructureAdvisorAutoProxyCreator will find the @Transactional annotation – which advices the post processor to proxy the bean in order to manage the required transaction’s context.

But you cannot override the expected outcome of a class instanciation with new with a proxy object – since it is not of the same type as the expected object!

Thus, @Configurable and @Transactional – together with any other advice that leads to a proxy object – cannot coexist in your class.

This entry was posted on Wednesday, March 26th, 2008 at 19:57. Posted in: J2EE, JPA, System architecture, java, spring. You can follow any responses to this entry through the RSS 2.0feed. You can leave a response, or trackback from your own site.

5 Responses to “Why @Configurable and @Transactional don’t belong to into the same class”

  1. Allard says:

    Olaf, you can use AspectJ to wire transactionality into your bean. The aspect required is in the spring-aspects jar, where the aspect treating @Configurable is placed too. If you use AspectJ, there is no problem using @Configurable and @Transactional in the same bean.
    See Spring’s documentation here: http://static.springframework.org/spring/docs/2.5.x/reference/aop.html#aop-using-aspectj.

  2. olaf says:

    Hi Allard, you certainly do have a point.

    @Transactional and @Configurable are a problem when creating proxy classes rather than directly advising the code. It should indeed be feasible with using the reference you posted.

    Thanks a lot!

  3. Manju says:

    Hi, I am having the exact same issue. Poted on: http://forum.springsource.org/showthread.php?t=103203
    I went thru the link that you provided, I am using AspectJ, still couldn’t get this to work. Can you suggest me some solution?

  4. olaf says:

    Hi Manju,

    The basic solution is not to use @Configurable. Using this means that you using new GenericJpaDao() somewhere but still want the spring application context to be the factory for the resulting instance. This is not a safe concept, thus the conflicts you are experiencing.
    I think @Configurable is somewhat a legacy workaround provided by spring. Where exactly are you using new GenericJpaDao()? If it is for testing, spring-test can provide you with cool solutions to use dependency injection in JUnit-based tests.

    Best,
    Olaf

  5. [...] concern is that @Configurable and @Transactional do not work together.  I cannot declare method in my domain to be transactional while having that bean also being [...]

Leave a Reply