Results 1 to 8 of 8

Thread: AOP advices in conjuction with TX

Hybrid View

  1. #1

    Question AOP advices in conjuction with TX

    need a little mental help to get my brain oriented right with AOP/TX in spring....

    recently ran into an error that popped up while using a service inside an AOP advice. namely that the service might not be initialized prior to injecting into the advice/pointcut (typical allowInit warning). the service is proxied as transactional by using the autoproxy on a transactionManager pairing up methods with transaction types. assuming AOP is used behind the scenes. and that when I define my AOP advice the order of which advice (the spring ready made transaction AOP and my own) is unknown.

    to get around the problem i simply marked the service bean with lazy-init equal to true so that it is built only when needed. not at init time (i assume?).

    wondering when using the TX advices with spring 2.0 if one can specify order precedence so the there isn't a conflict of when the service is made into a transactional bean? or am i off the deep end? assuming that the root cause of my origal error was due to unknown order in kicking off AOP advices (trans/my own).

    guess i am looking for a general blueprint for how to configure transactional beans (services) and AOP advices acting on those services (beans).


    thanks in advance / matthew

  2. #2
    Join Date
    Mar 2007
    Posts
    515

    Default

    Can you post your config, please, and the stack trace ?

  3. #3

    Default configuration

    below are clips from the Spring XML configuration files and the stack trace:

    service XML file
    Code:
    <bean 
    		id="installingSoftwareService" class="matrix.v.dataaccess.services.activity.InstallingSoftwareServiceImpl">  
                    <!-- adding lazy-init="true" fixes the advice problem -->
    		<property name="installingSoftwareDAO" ref="installingSoftwareDAO"/>
    </bean>

    AOP XML file
    Code:
    <aop:config>
    		<aop:aspect ref="statusControllerAOP">
    			<aop:pointcut id="persist" expression="execution(matrix.v.dataaccess.pojo.activity.InstallingSoftware matrix.v.dataaccess.services.activity.InstallingSoftwareService.setInstallingSoftware(..))"/>
    			<aop:after-returning pointcut-ref="persist" method="afterCompleting" returning="installingSoftware" arg-names="installingSoftware"/>
    		</aop:aspect>
    	</aop:config>
    
    	<aop:config>
    		<aop:aspect ref="statusControllerAOP">
    			<aop:pointcut id="transitory" expression="execution(matrix.v.dataaccess.pojo.activity.InstallingSoftware matrix.v.dataaccess.services.activity.InstallingSoftwareService.setInstallingSoftware(..)) and args(installingSoftware)"/>
    			<aop:before pointcut-ref="transitory" method="beforePersisting" arg-names="installingSoftware"/>
    			<aop:before pointcut-ref="transitory" method="beforeCompleting" arg-names="installingSoftware"/>
    		</aop:aspect>
    	</aop:config>
    
    	<bean id="statusControllerAOP" class="matrix.v.dataaccess.aop.activity.StatusController">
    		<property name="activityPrecedenceService" ref="activityPrecedenceService"/>
    		<property name="installingSoftwareService" ref="installingSoftwareService"/>
    		<property name="hostedSoftwareService" ref="hostedSoftwareService"/>
    		<property name="softwarePackageService" ref="softwarePackageService"/>
    		<property name="environmentService" ref="environmentService"/>
    </bean>

    stack trace
    Code:
    org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'installingSoftwareService': Bean with name 'installingSoftwareService' has been injected into other beans [statusControllerAOP] in its raw version as part of a circular reference, but has eventually been wrapped (for example as part of auto-proxy creation). This means that said other beans do not use the final version of the bean. This is often the result of over-eager type matching - consider using 'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:435)
    	at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:254)
    	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:144)
    	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:251)
    	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:163)
    	at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:284)
    	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:352)
    	at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:91)
    	at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:75)
    	at matrix.v.dataaccess.utilities.SpringUtil.<init>(SpringUtil.java:13)
    	at matrix.v.dataaccess.utilities.SpringUtil.getInstance(SpringUtil.java:18)
    	at matrix.v.dataaccess.services.activity.InstallingSoftwareServiceTest.setUp(InstallingSoftwareServiceTest.java:21)
    	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    	at java.lang.reflect.Method.invoke(Method.java:585)
    	at org.junit.internal.runners.BeforeAndAfterRunner.invokeMethod(BeforeAndAfterRunner.java:74)
    	at org.junit.internal.runners.BeforeAndAfterRunner.runBefores(BeforeAndAfterRunner.java:50)
    	at org.junit.internal.runners.BeforeAndAfterRunner.runProtected(BeforeAndAfterRunner.java:33)
    	at org.junit.internal.runners.TestMethodRunner.runMethod(TestMethodRunner.java:75)
    	at org.junit.internal.runners.TestMethodRunner.run(TestMethodRunner.java:45)
    	at org.junit.internal.runners.TestClassMethodsRunner.invokeTestMethod(TestClassMethodsRunner.java:71)
    	at org.junit.internal.runners.TestClassMethodsRunner.run(TestClassMethodsRunner.java:35)
    	at org.junit.internal.runners.TestClassRunner$1.runUnprotected(TestClassRunner.java:42)
    	at org.junit.internal.runners.BeforeAndAfterRunner.runProtected(BeforeAndAfterRunner.java:34)
    	at org.junit.internal.runners.TestClassRunner.run(TestClassRunner.java:52)
    	at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:38)
    	at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:460)
    	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:673)
    	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:386)
    	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:196)

    hope this helps. just let me know if i need to supply more info (using spring 2.0.3, java 150_04 from Bea, hibernate 3.2, and testing on windows XP).

  4. #4

    Default forgot to post the most important part (transaction)

    forgot the most important configuration (namely the transaction advices):

    management XML file
    Code:
            <!-- Hibernate TM (active in non-container) *installation parameter -->
    	<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    		<property name="sessionFactory" ref="sessionFactory"/>
    	</bean>
    	<!--:Transaction attributes for Services -->
    	<bean id="transactionAttributes" class="org.springframework.transaction.interceptor.NameMatchTransactionAttributeSource">
    		<property name="properties">
    			<props>
    				<prop key="get*">PROPAGATION_REQUIRED</prop>
    				<prop key="find*">PROPAGATION_REQUIRED</prop>
    				<prop key="set*">PROPAGATION_REQUIRED</prop>
    				<prop key="create*">PROPAGATION_REQUIRED</prop>
    				<prop key="page*">PROPAGATION_REQUIRED</prop>
    				<prop key="batch*">PROPAGATION_REQUIRED</prop>
    			</props>
    		</property>
    	</bean>
    	<!-- Transaction Interceptor for Services -->
    	<bean id="transactionInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor">
    		<property name="transactionManager">
    			<ref bean="transactionManager"/>
    		</property>
    		<property name="transactionAttributeSource">
    			<ref bean="transactionAttributes"/>
    		</property>
    	</bean>
    	<!-- AutoProxy for Services -->
    	<bean id="autoProxyCreator" class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
    		<property name="interceptorNames">
    			<value>transactionInterceptor</value>
    		</property>
    		<property name="beanNames">
    			<value>*Service</value>
    		</property>
    	</bean>

  5. #5
    Join Date
    Mar 2007
    Posts
    515

    Default

    It is pretty unusual what are you doing there: using 'installingSoftwareService' to add custom behavior (using aop:aspect) to itself.
    As a suggestion, try using 'order' attribute of aop:aspect tag and also 'order' property from BeanNameAutoProxyCreator.

  6. #6

    Default suggestions for reworking

    any suggestions for reworking the configuration?

    thought at the Order interface might be the problem. but basically i want to apply business logic dynamically to the service without coding directly in the service implementation. ie. the extra logic that the advice adds against the service may not be necessary in 4/5 months so there is no point in adding it inside the service implementation.


    / matthew

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •