Announcement Announcement Module
Collapse
No announcement yet.
TransactionProxyFactoryBean: beans created more than once Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • TransactionProxyFactoryBean: beans created more than once

    I have a problem with the TransactionProxyFactoryBean. It looks like he is creating my KlantService two times.

    This is my code..

    Code:
     <bean   id="klantService"            class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
    
            <property name="transactionManager">
                <ref bean="transactionManager"/>
            </property>
    
            <property name="target">
                 <bean class="anchormen.urenAdmin.services.KlantService"/>            
            </property>
    
            <property name="transactionAttributes">
                <props>
                    <prop key="*">PROPAGATION_REQUIRED</prop>
                </props>
            </property>
        </bean>
    This is the only location in my application context I create an instance of the KlantService. I have added a log statement with the constructor, and it is called twice..

    Code:
    13&#58;12&#58;34,951 INFO  &#91;DefaultListableBeanFactory&#93; Creating shared instance of singleton bean 'klantServiceTarget'
    13&#58;12&#58;34,951 INFO  &#91;KlantService&#93; KlantService created - no arg constructor
    13&#58;12&#58;34,951 INFO  &#91;DefaultListableBeanFactory&#93; Creating shared instance of singleton bean 'klantService'
    13&#58;12&#58;34,998 INFO  &#91;KlantService&#93; KlantService created - no arg constructor
    13&#58;12&#58;35,091 INFO  &#91;KlantService&#93; KlantService created - no arg constructor
    13&#58;12&#58;35,091 INFO  &#91;DefaultListableBeanFactory&#93; Creating shared instance of singleton bean 'werknemerService'
    13&#58;12&#58;35,107 INFO  &#91;WerknemerService&#93; WerknemerService created


    if I do the following:
    Code:
     <bean   id="klantServiceTarget"
                class="anchormen.urenAdmin.services.KlantService"/>
    
        <bean   id="klantService"
                class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
    
            <property name="transactionManager">
                <ref bean="transactionManager"/>
            </property>
    
            <property name="target">
                 <ref bean="klantServiceTarget"/>       
            </property>
    
            <property name="transactionAttributes">
                <props>
                    <prop key="*">PROPAGATION_REQUIRED</prop>
                </props>
            </property>
        </bean>
    It is only called once.


    Code:
    fef6&#93; from Hibernate SessionFactory for HibernateTransactionManager
    13&#58;10&#58;39,766 INFO  &#91;DefaultListableBeanFactory&#93; Creating shared instance of singleton bean 'klantServiceTarget'
    13&#58;10&#58;39,766 INFO  &#91;KlantService&#93; KlantService created - no arg constructor
    13&#58;10&#58;39,766 INFO  &#91;DefaultListableBeanFactory&#93; Creating shared instance of singleton bean 'klantService'
    13&#58;10&#58;39,907 INFO  &#91;KlantService&#93; KlantService created - no arg constructor
    13&#58;10&#58;39,907 INFO  &#91;DefaultListableBeanFactory&#93; Creating shared instance of singleton bean 'werknemerService'
    13&#58;10&#58;39,907 INFO  &#91;WerknemerService&#93; WerknemerService created
    It should not make a difference???

    [edit]
    I have added a static instance counter and the KlantService is created 2 times:

    Code:
    13&#58;17&#58;43,424 INFO  &#91;KlantService&#93; KlantService created - no arg constructor&#58; 1
    13&#58;17&#58;43,533 INFO  &#91;KlantService&#93; KlantService created - no arg constructor&#58; 2

  • #2
    The problem here is that you are creating a proxy of a class not an interface. When proxying a class we (currently) have to create a dynamic subclass and then create an instance of that which causes constructors on your class to be fired again. To avoid this you should proxy to an interface rather than a concrete class.

    To proxy an interface use the proxyInterfaces property of TransactionProxyFactoryBean to specofy the interfaces that should be used to generate the proxy.

    Rob

    Comment


    • #3
      Originally posted by robh
      The problem here is that you are creating a proxy of a class not an interface. When proxying a class we (currently) have to create a dynamic subclass and then create an instance of that which causes constructors on your class to be fired again. To avoid this you should proxy to an interface rather than a concrete class.

      To proxy an interface use the proxyInterfaces property of TransactionProxyFactoryBean to specofy the interfaces that should be used to generate the proxy.

      Rob
      Oh that is a difference that I wasn't aware of (constructur fired again).

      Is this documented in the reference document?

      Comment


      • #4
        Claus,

        This is not something that is documented, but we have been working towards a fix for quite some time. With CGLIB it works by creating a dynamic subclass of your bean's class. Whilst we can't get it stop creating the 2nd instance, the new version of CGLIB allows us to skip calls to constructors during proxy creation so you can avoid resetting any bean state.

        This fix will be released in 1.1.5.

        Rob

        Comment


        • #5
          Proxy behaviour with Quartz?

          Hi,

          I've got a similar issue, I am storing state in a bean(foo) and then invoking a method on that bean that updates the state using a MethodInvokingJobDetailFactoryBean. I have noticed that the reference of foo that is used by the quartz job is different than the foo used by the rest of the application.

          I have also used a Job class with a job Map and had the same issue.

          I would like to add that I know using state in a bean is bad design - but this is a quick fix/optimisation.

          How do I persuade Spring to hand out the same instance?

          Cheers,

          James

          PS already got pro spring - very handy.

          Comment


          • #6
            Originally posted by robh
            The problem here is that you are creating a proxy of a class not an interface. When proxying a class we (currently) have to create a dynamic subclass and then create an instance of that which causes constructors on your class to be fired again. To avoid this you should proxy to an interface rather than a concrete class.

            To proxy an interface use the proxyInterfaces property of TransactionProxyFactoryBean to specofy the interfaces that should be used to generate the proxy.

            Rob
            Ok, but the interesting fact is that it works differently with bean reference vs nested bean definition.

            Comment


            • #7
              If the fix for this has been delayed for some time, then why is the problem not documented?

              Comment


              • #8
                Cannot proxy classes lacking no-arg constructor using CGLIB

                It looks like this issue from 2004 is still present in Spring 2 M2 in 2006, as I recently posted:
                http://forum.springframework.org/showthread.php?t=22553

                It looks like the relevant Jira issue was market as "won't fix" without any realy technical
                explanation:

                Cannot proxy classes lacking no-arg constructor using CGLIB

                Is it ok for me to open/re-open a Jira issue for this?

                I could look into implementing an alternate proxy creator myself, but it would be nice if
                it were included in the framework.

                Thank you,
                Armando

                Comment

                Working...
                X