Announcement Announcement Module
Collapse
No announcement yet.
Advice called twice (once for the implementation and once for the proxy) Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Advice called twice (once for the implementation and once for the proxy)

    Using Spring 2.0-m3.
    I have an advice that is called twice but I (of course) only would like to have it called once. The problem is that it's called when the proxy is called too.

    XML:


    Code:
       <bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
          <property name="host" value="${mail.host}" />
          <property name="username" value="${mail.user}" />
          <property name="password" value="${mail.password}" />
       </bean>
    
       <bean id="emailUserAdvice" class="com.foo.RegisterUserEmailAdvice">
          <property name="mailSender" ref="mailSender" />
          <property name="mailFrom" value="${mail.from}" />
          <property name="subject" value="${mail.subject}" />
       </bean>
    
       <aop:config>
          <aop:advisor
                  pointcut="execution(* *..UserMgr.createUser(*..User))"
                  advice-ref="emailUserAdvice" />
       </aop:config>
    
       <bean id="abstractMgrTarget" abstract="true">
          <property name="entityManagerFactory" ref="entityManagerFactory" />
       </bean>
       <bean id="userMgr" class="org.springframework.aop.framework.ProxyFactoryBean" parent="abstractMgr">
          <property name="target" ref="userMgrTarget" />
       </bean>
       <bean id="userMgrTarget"
             class="com.foo.impl.UserMgrJpa" parent="abstractMgrTarget">
       </bean>
    and the class for the advice:

    Code:
    public class RegisterUserEmailAdminAdvice
            implements AfterReturningAdvice, InitializingBean {
    ...
       public void afterReturning(Object returnValue, Method m, Object[] args, Object target) throws Throwable {
    ...
    }
    I debugged my app and I discovered that emailUserAdvice is called twice, first for the implementation and then for the proxy.
    Code:
    First call:
    target: java.lang.Object = 
    {se.wesslan.shoppinglist.business.session.impl.UserMgrJpa@3834}
    
    Second call:
    target: java.lang.Object = {$Proxy57@3842}"se.wesslan.shoppinglist.business.session.impl.UserMgrJpa@3f9ad"
    Any ideas how to solve this?

    Regards

  • #2
    You could declare the target as inner bean of the proxy. So it is not visible in the context and thus no subject for the advice.

    Regards,
    Andreas

    Comment


    • #3
      Thanks for the reply Andreas!

      I changed
      Code:
         <bean id="userMgr" class="org.springframework.aop.framework.ProxyFactoryBean" parent="abstractMgr">
            <property name="target" ref="userMgrTarget" />
         </bean>
         <bean id="userMgrTarget"
               class="se.wesslan.shoppinglist.business.session.impl.UserMgrJpa" parent="abstractMgrTarget">
         </bean>
      to
      Code:
         <bean id="userMgr" class="org.springframework.aop.framework.ProxyFactoryBean" parent="abstractMgr">
            <property name="target">
               <bean class="se.wesslan.shoppinglist.business.session.impl.UserMgrJpa" parent="abstractMgrTarget" />
            </property>
         </bean>
      But my advice is still called twice.

      Regards

      Comment


      • #4
        Hmm. I wonder if the advice is applied to inner beans, too. I would consider this not being consistent to the "traditional" approach.

        If no one else comes up with an idea, maybe you could raise an issue in Jira to clarify this.

        Regards,
        Andreas

        Comment


        • #5
          Done!
          Jira issue

          Comment


          • #6
            When using the Spring 2.0 <aop:*/> tags to apply AOP advice, you should not use the ProxyFactoryBean at the same time.

            Comment


            • #7
              Originally posted by robh
              When using the Spring 2.0 <aop:*/> tags to apply AOP advice, you should not use the ProxyFactoryBean at the same time.
              I suspected it was something like that...
              So, how do I set up my app with both JPA, tx and advice for something else (email this time)?

              Regards,
              Peter

              Comment


              • #8
                Peter,

                For this you want to define your target bean and advice beans as you would normally (with plain <bean/> tags). For TX you *may* choose to use the convenient <tx:advice/> tag.

                Then you can simply apply all of these using the <aop:config/>:

                <aop:config>
                <aopointcut id="myPointcut" expression="execution(* *..UserMgr.createUser(*..User))"/>
                <aop:advisor pointcut-ref="myPointcut" advice-ref="txAdvice"/>
                <aop:advisor pointcut-ref="myPointcut" advice-ref="securityAdvice"/>
                <aop:advisor pointcut-ref="myPointcut" advice-ref="mailAdvice"/>
                </aop:config>

                There is definitely no need for a ProxyFactoryBean.

                Hope this helps...

                Rob

                Comment


                • #9
                  Thanks for the info Rob. I really appreciate it!
                  I'm new to Spring and I followed an example using JPA to build my application.
                  I'll give your suggestions a try and I promise to come back to this list if I get more problems...

                  Regards,
                  Peter

                  Originally posted by robh
                  Peter,

                  For this you want to define your target bean and advice beans as you would normally (with plain <bean/> tags). For TX you *may* choose to use the convenient <tx:advice/> tag.

                  ...
                  There is definitely no need for a ProxyFactoryBean.

                  Hope this helps...

                  Rob

                  Comment


                  • #10
                    Same problem

                    I seem to be having the same problem but am not able to figure out the work around.

                    I have a TransactionProxyFactoryBean for my Hibernate managers (like you would do in Spring 1.2) and then some <aop:*> advice configured like:

                    Code:
                            <aop:pointcut id="containerAddUserPointcut"
                                          expression="execution(* com.vodori.bluebird.component.user.service.VodoriUserManager.addUser(com.vodori.bluebird.component.user.model.User)) and args(user)"/>
                    
                    <aop:aspect id="userManagement" ref="userManagerAdvice">
                                <aop:before method="addUser" pointcut-ref="containerAddUserPointcut"/>
                            </aop:aspect>
                    The problem is that when I call my user manager interface, the advice is getting called on the call to the Interface and the call to the implementing method.

                    You can see the output here:
                    Code:
                    First call:
                    PJP:org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint: execution: [invocation: method 'addUser', arguments[...]; target is of class [$Proxy13]]
                    
                    Second Call:
                    PJP:org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint: execution: [invocation: method 'addUser', arguments [...]; target is of class [com.vodori.bluebird.component.user.service.impl.VodoriUserManagerImpl]]
                    I'm not quite sure how to get around this problem. Any ideas?

                    Comment


                    • #11
                      For TransactionProxyFactoryBean the same points should be valid as for ProxyFactoryBean, mentioned above by Rob. Try using the new namespaces also for transaction management, then things should work out right.

                      Regards,
                      Andreas

                      Comment


                      • #12
                        I guess I need more of a complete example to see how it works since I am unable to find documentation about it. It seems that the latest documentation in PDF does not include much information about the new AOP in 2.0 yet. There are lots of blank spaces and TODO notes in there still..

                        Does anyone have an example that gets rid of the TransactionProxyFactory and uses the <tx:advice> tag?

                        Thanks in advance.
                        Grant

                        Comment


                        • #13
                          Nevermind -- I just started looking through the JPetstore example in the Spring 2.0 nightly and they are using these new tags so I'm going to give it a whirl

                          Thanks

                          Comment


                          • #14
                            So looking at the example -- I have one question... How is the transactionManager specified using the new <tx:advice> tags?

                            For example, in the old TransactionProxyFactoryBean, you explicitly set the reference to the transaction manager you are using but looking at the JPetStore example, I don't see where this is specified. Is this using auto-proxying to do this? If so, is there a way to explicitly define your transactionManager?

                            Thanks,
                            Grant

                            Comment


                            • #15
                              I have no example, but I think the documentation on that topic will be available in RC1, which will ship soon. From Jira I can see that the according task is finished.

                              Regards,
                              Andreas

                              Comment

                              Working...
                              X