Page 1 of 2 12 LastLast
Results 1 to 10 of 20

Thread: Advice called twice (once for the implementation and once for the proxy)

  1. #1
    Join Date
    Mar 2006
    Location
    A place to call home
    Posts
    76

    Default 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. #2
    Join Date
    Aug 2004
    Posts
    2,715

    Default

    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

  3. #3
    Join Date
    Mar 2006
    Location
    A place to call home
    Posts
    76

    Default

    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

  4. #4
    Join Date
    Aug 2004
    Posts
    2,715

    Default

    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

  5. #5
    Join Date
    Mar 2006
    Location
    A place to call home
    Posts
    76

    Default

    Done!
    Jira issue

  6. #6
    Join Date
    Aug 2004
    Location
    Southampton, UK
    Posts
    826

    Default

    When using the Spring 2.0 <aop:*/> tags to apply AOP advice, you should not use the ProxyFactoryBean at the same time.
    Rob Harrop
    Lead Engineer, dm Server
    SpringSource
    http://www.springsource.com

    Co-Author - Pro Spring

  7. #7
    Join Date
    Mar 2006
    Location
    A place to call home
    Posts
    76

    Default

    Quote 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

  8. #8
    Join Date
    Aug 2004
    Location
    Southampton, UK
    Posts
    826

    Default

    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
    Rob Harrop
    Lead Engineer, dm Server
    SpringSource
    http://www.springsource.com

    Co-Author - Pro Spring

  9. #9
    Join Date
    Mar 2006
    Location
    A place to call home
    Posts
    76

    Lightbulb

    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

    Quote 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

  10. #10
    Join Date
    Sep 2005
    Location
    Chicago, IL
    Posts
    143

    Default 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?
    Grant Gochnauer
    Vodori Inc.
    Personal Blog

Posting Permissions

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