Announcement Announcement Module
Collapse
No announcement yet.
Dynamic Proxy Problem Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Dynamic Proxy Problem

    Hi all

    I have a proxy problem which is driving me nuts, and hope someone can help resolve it.

    I have a data access object which is dynamically proxied and contains several other wired beans.

    I need one of these other beans to also be proxied, so that I can apply an advice. The trouble is when I proxy the contained bean I get the following exception

    Code:
    Caused by: org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'routerDAO': org.springframework.bea
    ns.factory.FactoryBeanNotInitializedException: Cannot determine target class for proxy
    I've tried setting the target class's proxyTargetClass value to true, but I get the same problem.

    Any help would be much appreciated.

    Many thanks
    Nick
    Last edited by wagdey; May 28th, 2008, 07:06 AM.

  • #2
    Ok, I've worked this one out. This was caused because a bean had a reference to a bean which had a reference to another bean which had a reference back to the original bean.

    Two interesting things.

    1) This only seems to be an issue when proxies are involved. Without proxies, it worked fine.

    2) Re-ordering entries in the XML configuration file resolved the error, which is odd as I didn't think ordering was significant.

    Anyhow I've broken the kind of circular dependency and it now works.

    Nick

    Comment


    • #3
      If you could create a minimal testcase showing that problem (i.e. how it fails and how it works) it might be worthwile to post it to Jira. That way it could be inspected and probably corrected.

      Regards,
      Andreas

      Comment


      • #4
        Circularity problems in with Spring beans when using proxies

        Actually I encountered the same problem in my projects:

        When having multiple service beans which contain references to each other, and these service beans are proxied (for transaction management for example), this problem always appear, no matter in which order the beans are declared, and no matter if you use lazy-init for (some of) them.
        (And of course I am proxying interfaces, not the service implementation class)

        To give you an example:

        Code:
        <bean id="myService1Target" class="my.company.service.impl.MyService1Impl">
            <property name="myService2" ref="myService2"/>
        </bean>
        
        <bean id="myService1" class="org.springframework.aop.framework.ProxyFactoryBean">
            <property name="target" ref="documentManagementServiceTarget"/>
            <property name="proxyTargetClass" value="false"/>
            <property name="proxyInterfaces">
                <list>
                <value>my.company.service.interfaces.MyService1</value>
                </list>
            </property>
            <property name="interceptorNames">
                <value>transactionInterceptor</value>
            </property>
        </bean>
        
        <bean id="myService2Target" class="my.company.service.impl.MyService2Impl">
            <property name="myService1" ref="myService1"/>
            <property name="myService3" ref="myService3"/>
        </bean>
        
        <bean id="myService2" class="org.springframework.aop.framework.ProxyFactoryBean">
            <property name="target" ref="documentManagementServiceTarget"/>
            <property name="proxyTargetClass" value="false"/>
            <property name="proxyInterfaces">
                <list>
                <value>my.company.service.interfaces.MyService2</value>
                </list>
            </property>
            <property name="interceptorNames">
                <value>transactionInterceptor</value>
            </property>
        </bean>
        
        <bean id="myService3Target" class="my.company.service.impl.MyService3Impl">
            <property name="myService1" ref="myService1"/>
            <property name="myService2" ref="myService2"/>
        </bean>
        
        <bean id="myService3" class="org.springframework.aop.framework.ProxyFactoryBean">
            <property name="target" ref="documentManagementServiceTarget"/>
            <property name="proxyTargetClass" value="false"/>
            <property name="proxyInterfaces">
                <list>
                <value>my.company.service.interfaces.MyService3</value>
                </list>
            </property>
            <property name="interceptorNames">
                <value>transactionInterceptor</value>
            </property>
        </bean>
        The solution is to declare a "third-party" lazy bean that contains references to the actual service interfaces (some kind of "services repository"), and set it to lazy-init="true".
        And then change all the other service implementations to access the other services only through this services repository bean, not directly.

        In the given example this will become:

        Code:
        <bean id="myService1Target" class="my.company.service.impl.MyService1Impl">
            <property name="myServicesRepository" ref="myServicesRepository"/>
        </bean>
        
        <bean id="myService1" class="org.springframework.aop.framework.ProxyFactoryBean">
            <property name="target" ref="documentManagementServiceTarget"/>
            <property name="proxyTargetClass" value="false"/>
            <property name="proxyInterfaces">
                <list>
                <value>my.company.service.interfaces.MyService1</value>
                </list>
            </property>
            <property name="interceptorNames">
                <value>transactionInterceptor</value>
            </property>
        </bean>
        
        <bean id="myService2Target" class="my.company.service.impl.MyService2Impl">
            <property name="myServicesRepository" ref="myServicesRepository"/>
        </bean>
        
        <bean id="myService2" class="org.springframework.aop.framework.ProxyFactoryBean">
            <property name="target" ref="documentManagementServiceTarget"/>
            <property name="proxyTargetClass" value="false"/>
            <property name="proxyInterfaces">
                <list>
                <value>my.company.service.interfaces.MyService2</value>
                </list>
            </property>
            <property name="interceptorNames">
                <value>transactionInterceptor</value>
            </property>
        </bean>
        
        <bean id="myService3Target" class="my.company.service.impl.MyService3Impl">
            <property name="myServicesRepository" ref="myServicesRepository"/>
        </bean>
        
        <bean id="myService3" class="org.springframework.aop.framework.ProxyFactoryBean">
            <property name="target" ref="documentManagementServiceTarget"/>
            <property name="proxyTargetClass" value="false"/>
            <property name="proxyInterfaces">
                <list>
                <value>my.company.service.interfaces.MyService3</value>
                </list>
            </property>
            <property name="interceptorNames">
                <value>transactionInterceptor</value>
            </property>
        </bean>
        
        <bean id="myServicesRepository" class="my.company.service.impl.MyServicesRepository" lazy-init="true">
            <property name="myService1" ref="myService1"/>
            <property name="myService2" ref="myService2"/>
            <property name="myService3" ref="myService3"/>
        </bean>
        Unfortunately this kinda defeats the whole idea of automatic wiring of beans, because now you will have to manually declare all the wiring of beans...

        And also, by creating this type of "services repository" you will get to tight-coupling of beans, instead of loose-coupling...
        Maybe a more elegant solution would be to identify groups of related services (maybe based on the packages or modules), and create multiple "service repositories": documentManagementServicesRepository, usersManagementServicesRepository, etc.
        (Of course I am speaking of complex applications, with tens of packages and hundreds of service interfaces/classes)


        Note that the same problem (and solution) applies even if you are using the newer style of declarative transaction management:

        Code:
        <aop:config>
            <aop:pointcut id="myService1Operation" expression="execution(* my.company.service.interfaces.MyService1.*(..))"/>
            <aop:advisor advice-ref="txAdvice" pointcut-ref="myService1Operation"/>
        </aop:config>

        Comment

        Working...
        X