Announcement Announcement Module
Collapse
No announcement yet.
Problem getting @Transaction annotations injected Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Problem getting @Transaction annotations injected

    I've been trying to troubleshoot an issue where directly injecting transaction attributes is working in my code, but the Transactional Annotation tag will not. During that I switched from proxy to aspectj as the mode and got the following problem.

    This spring configuration:
    Code:
        <jee:jndi-lookup id="DataSource" jndi-name="jdbc/db" resource-ref="true"/>
        <bean id="txManager" class="org.springframework.transaction.jta.JtaTransactionManager" />
        
        <tx:annotation-driven 
        	mode="aspectj" 
        	transaction-manager="txManager" 
        	proxy-target-class="false" 
        	order="2"/>

    Is resulting in this exception:
    Code:
    java.lang.IllegalArgumentException: Cannot convert value of type [org.springframework.transaction.jta.JtaTransactionManager] to required type [org.springframework.transaction.PlatformTransactionManager] for property 'transactionManager': no matching editors or conversion strategy found
    	at org.springframework.beans.TypeConverterDelegate.convertIfNecessary(TypeConverterDelegate.java:231)
    	at org.springframework.beans.TypeConverterDelegate.convertIfNecessary(TypeConverterDelegate.java:138)
    	at org.springframework.beans.BeanWrapperImpl.convertForProperty(BeanWrapperImpl.java:386)
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.convertForProperty(AbstractAutowireCapableBeanFactory.java:1289)
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1250)
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1010)
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:472)
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory$1.run(AbstractAutowireCapableBeanFactory.java:409)
    	at java.security.AccessController.doPrivileged(Native Method)
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:380)
    	at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:264)
    	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
    	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:261)
    	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:185)
    	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:164)
    	at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:429)
    	at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:728)
    	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:380)
    	at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:139)
    	at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:93)
    	at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    	at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
    ...

    Same thing actually applies if I use DataSourceTransactionManager too.

    Any ideas?

    Edit: Looking like this might have been some classloading issues. In process restructuring things now. Would still appreciate any other ideas anyone has.

    Note: See Post #11 for resolution.
    Last edited by res; Jul 21st, 2009, 10:11 PM.

  • #2
    My setup included several WAR files which use a main application context. This is a fairly complicated setup and this turned out to be some kind of conflict between the WAR and main application. To resolve it I ultimately cleared out the spring stuff from the WEB-INF/lib of the WAR and pointed all of it back to the EAR.

    It still doesn't pick up the @Transactional annotations and honor them from the main application context. Directly AOP driven transactions delineated by pointcuts seem to work but the @Transaction tag from what I can tell is being completely ignored. I'm adding the code:

    Code:
        <tx:annotation-driven 
        	mode="proxy" 
        	transaction-manager="transactionManager" 
        	proxy-target-class="false" 
        	order="2" />
    but it doesn't seem to make it down. This code is in the spring bean definition that's using the annotation tags (part of the main application context). I've also tried to add that into the WAR file which references that based on the documentation about @Transactional scope; however that also doesn't seem to make any difference.

    At least the odd casting issues are gone.

    Comment


    • #3
      What type of aspectj weaving do you use? Load-time or compile-time?

      Comment


      • #4
        Originally posted by denis.zhdanov View Post
        What type of aspectj weaving do you use? Load-time or compile-time?
        Should be compile-time. I'm not telling the JVM anything about aspectJ on any command line and I've included all the spring-aspects, etc...

        What are your thoughts behind that question?

        Comment


        • #5
          Originally posted by res View Post
          Should be compile-time. I'm not telling the JVM anything about aspectJ on any command line and I've included all the spring-aspects, etc...

          What are your thoughts behind that question?
          Nothing concrete, just thought that load time weaving may somehow exploit additional class loaders problem.

          So, you say that @Transactional doesn't spawns new transactions and tx-schema-based transaction setup for the same methods + proxy-based aop works fine?

          Comment


          • #6
            Here's specifically what I'm seeing. If I create an aspect with tx-advice
            Code:
                <tx:advice id="txAdvice">
                    <tx:attributes>
                        <tx:method name="*" propagation="REQUIRED" />
                    </tx:attributes>
                </tx:advice>
            
                <aop:config proxy-target-class="false">
                    <aop:pointcut id="autotx"
                                  expression="execution(* services..*(..))"/>
                    <aop:advisor pointcut-ref="autotx" advice-ref="txAdvice" order="2"/>
                </aop:config>
            Then it works fine. However when I'm using the @Transactional tag, even when specifying the tx:annotation-driven portion, nothing happens. I'm currently testing this by making the DAO layer have a propagation of MANDATORY. It throws the exception that no transaction exists when using the @Transactional tags but when I specify the aspect and tx-advice everything goes through properly. Based on that my assumption is that the @Transactional tags just aren't being picked up.

            In the tx:annotation-driven I've tried both modes 2.5 has to offer - proxy and aspectj. Once I got over the class loading issue, which I had initially thought might be providing more of a clue, both modes behave the same (which is basically that they don't do anything). Since prior to the classloading issue the mode was causing it to blow up I further conclude that spring is reading the definition from it's config file.

            Appreciate the help. I know the annotation method is supposed to be pretty simple but if you see something about my usage that's wrong or have any ideas about how I might debug or throw additional output at it to see what's happening that would be great.

            Comment


            • #7
              Originally posted by res View Post
              Here's specifically what I'm seeing. If I create an aspect with tx-advice
              Code:
                  <tx:advice id="txAdvice">
                      <tx:attributes>
                          <tx:method name="*" propagation="REQUIRED" />
                      </tx:attributes>
                  </tx:advice>
              
                  <aop:config proxy-target-class="false">
                      <aop:pointcut id="autotx"
                                    expression="execution(* services..*(..))"/>
                      <aop:advisor pointcut-ref="autotx" advice-ref="txAdvice" order="2"/>
                  </aop:config>
              Then it works fine. However when I'm using the @Transactional tag, even when specifying the tx:annotation-driven portion, nothing happens. I'm currently testing this by making the DAO layer have a propagation of MANDATORY. It throws the exception that no transaction exists when using the @Transactional tags but when I specify the aspect and tx-advice everything goes through properly. Based on that my assumption is that the @Transactional tags just aren't being picked up.

              In the tx:annotation-driven I've tried both modes 2.5 has to offer - proxy and aspectj. Once I got over the class loading issue, which I had initially thought might be providing more of a clue, both modes behave the same (which is basically that they don't do anything). Since prior to the classloading issue the mode was causing it to blow up I further conclude that spring is reading the definition from it's config file.

              Appreciate the help. I know the annotation method is supposed to be pretty simple but if you see something about my usage that's wrong or have any ideas about how I might debug or throw additional output at it to see what's happening that would be great.
              I see that there is no 1-to-1 relation between transaction boundaries defined via @Transaction and tx-schema at your config. I.e. provided config doesn't show that the transactions are started exactly during calling the methods that you tried to annotate with @Transactional.

              So, there is a possible case that you call that methods already in transactional context.

              I suggest to refine your tx-schema config in order for pointcut to cover only the methods that you tried to mark with @Transactional and check if transactions are applied.

              If you create complete standalone example that reproduces the problem and post it here I think it's possible to sort it out.

              Comment


              • #8
                I have tried to narrow it down to the specific class with the aspect, though not at a method level with the aspect. I stopped there because even the class level prorogation of REQUIRED isn't being picked up though anything other than the aspect. Will try it on an individual method layer as well and verify.

                Just FYI - The project I have right now is actually a mix between aspects against some generated iBatis code narrowed to method names and an attempt to use @Transactional on some of the upstream service methods. i.e., in that case I have pointcuts like expression="execution(* services..select*(..))" going on and they are working.

                I'll see about trying to create something standalone. That'll probably take me more than 30 min though so will get back soon as I can on it.

                Comment


                • #9
                  I tried the individual method like you suggested and it produces the same result. I've created a little standalone version EAR which has the basic framework and can reproduce the problem in my Eclipse setup.

                  The attached Eclipse archive file with source runs on JBoss 4.2 - JDK 6 (should run 5+). Be aware that in order to upload it I had to remove the spring jars, but I left blank files in there for the ones required. Just replace them with the 2.5.6-SEC01 jars to reproduce my workspace.

                  If you're running it standard, use the test URL to invoke:
                  http://localhost:8080/ServicesTestWeb/test/go


                  If this runs successfully you will see the message:

                  Service A Test Method
                  Service B Test Method


                  What happens when I run it with the Transactional Annotations (the way it's set up) is I get the message:
                  No existing transaction found for transaction marked with propagation 'mandatory'


                  To see the differences or play around with the transactions, look at the svcTestapplicationContext.xml in the ServicesTest project.

                  Hopefully this will help shed some light on why things aren't happening. Appreciate the help in advance.

                  Comment


                  • #10
                    Ok, I'll take a look at home.

                    Comment


                    • #11
                      After fiddling for a few more hours and a few bangs of the head, I've realized what was happening and how to fix this issue. Ultimately (as one may be able to figure out from the attached example) the issue is a class loading problem. Though this does not throw any kind of error, if you are using the shared context as in the example (web project which has access to a parent application context with services beans) then you cannot export any of the spring jars without causing problems. Turns out that this is what I was doing and as a result the @Transactional annotations were being ignored.

                      Basically from inside Eclipse I did two things to resolve this, both on the WAR(s) which inherits from the main application context:
                      From WAR properties:

                      1) Java Build Path -> Order and Export -> Make sure everything spring related (except perhaps spring-webmvc.jar) is not checked to be exported.

                      2) Java EE Module Dependencies -> Web Libraries -> Make sure everything (except perhaps spring-webmvc.jar) is not checked. You should check any relevant required JARs in the J2EE modules directory instead.

                      Comment

                      Working...
                      X