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

  • Problem getting started

    I am having trouble getting a aop demo working in SPRING.

    My test program starts a ClassPathXmlApplicationContext which loads the folling applicationContext;

    <bean id="beforeAdvice" class="MyBeforeAdvice"/>

    <bean id="beforeAdvisor"
    class="org.springframework.aop.support.RegexpMetho dPointcutAdvisor">
    <property name="advice"><ref local="beforeAdvice"/></property>
    <property name="pattern"><value>.*</value></property>
    </bean>

    <bean id="test1" class="org.springframework.aop.framework.ProxyFact oryBean">
    <property name="proxyInterfaces"><value>TestBean</value></property>
    <property name="target"><bean class="TestBeanImpl"/></property>
    <property name="interceptorNames">
    <list>
    <value>beforeAdvisor</value>
    </list>
    </property>
    </bean>

    beforeAdvice just prints a message so I know it is called.

    The first time I run test app to get the 'test1' bean and call its methods I got

    NoClassDefFoundError: net/sf/cglib/proxy/MethodInterceptor

    I expected it to proxy the TestBean interface supplied to proxyInterfaces and not use cglib to proxy the TestBeanImpl class, but I go along with this anyway and put cglib on the classpath.

    Now I have the following exception, any help with this would be greatly appreciated.

    - Jeff


    org.springframework.aop.framework.AopConfigExcepti on: Cannot create AopProxy with no advisors and no target source
    at org.springframework.aop.framework.Cglib2AopProxy.< init>(Cglib2AopProxy.java:77)
    at org.springframework.aop.framework.DefaultAopProxyF actory$CglibProxyFactory.createCglibProxy(DefaultA opProxyFactory.java:47)
    at org.springframework.aop.framework.DefaultAopProxyF actory$CglibProxyFactory.access$000(DefaultAopProx yFactory.java:44)
    at org.springframework.aop.framework.DefaultAopProxyF actory.createAopProxy(DefaultAopProxyFactory.java: 32)
    at org.springframework.aop.framework.AdvisedSupport.c reateAopProxy(AdvisedSupport.java:454)
    at org.springframework.aop.framework.ProxyFactoryBean .getSingletonInstance(ProxyFactoryBean.java:210)
    at org.springframework.aop.framework.ProxyFactoryBean .getObject(ProxyFactoryBean.java:194)
    at org.springframework.beans.factory.support.Abstract BeanFactory.getObjectForSharedInstance(AbstractBea nFactory.java:469)
    at org.springframework.beans.factory.support.Abstract BeanFactory.getBean(AbstractBeanFactory.java:137)
    at org.springframework.beans.factory.support.DefaultL istableBeanFactory.getBeansOfType(DefaultListableB eanFactory.java:144)
    at org.springframework.beans.factory.BeanFactoryUtils .beansOfTypeIncludingAncestors(BeanFactoryUtils.ja va:109)
    at org.springframework.beans.factory.support.DefaultL istableBeanFactory.findMatchingBeans(DefaultListab leBeanFactory.java:268)
    at org.springframework.beans.factory.support.Abstract AutowireCapableBeanFactory.autowireByType(Abstract AutowireCapableBeanFactory.java:519)
    at org.springframework.beans.factory.support.Abstract AutowireCapableBeanFactory.populateBean(AbstractAu towireCapableBeanFactory.java:460)
    at org.springframework.beans.factory.support.Abstract AutowireCapableBeanFactory.createBean(AbstractAuto wireCapableBeanFactory.java:232)
    at org.springframework.beans.factory.support.Abstract AutowireCapableBeanFactory.createBean(AbstractAuto wireCapableBeanFactory.java:177)
    at org.springframework.beans.factory.support.Abstract BeanFactory.getBean(AbstractBeanFactory.java:159)
    at org.springframework.beans.factory.support.DefaultL istableBeanFactory.preInstantiateSingletons(Defaul tListableBeanFactory.java:177)
    at org.springframework.context.support.AbstractApplic ationContext.refresh(AbstractApplicationContext.ja va:268)
    at org.springframework.context.support.ClassPathXmlAp plicationContext.<init>(ClassPathXmlApplicationCon text.java:58)
    at RunTest.main(RunTest.java:14)
    Ex

  • #2
    If you want to make sure the JDK proxy are used, you have to specify the interfaces you want to be implemented by the proxy. I don't know why you got that error with CGLIB though.

    Guillaume

    Comment


    • #3
      Jeff Gager,

      Could you provide the source code for your classes?

      Comment


      • #4
        OK this is my advisor

        public class MyAdvisor implements PointcutAdvisor {

        private Advice advice;
        private Pointcut pointcut;

        /*
        * @see org.springframework.aop.PointcutAdvisor#getPointcu t()
        */
        public Pointcut getPointcut() {
        if (pointcut == null) {
        pointcut = new Pointcut() {
        public ClassFilter getClassFilter() {
        return new ClassFilter() {
        public boolean matches(Class arg0) {
        return true;
        }
        };
        }
        public MethodMatcher getMethodMatcher() {
        return new MethodMatcher() {
        public boolean matches(Method arg0, Class arg1) {
        if (arg0.getName().indexOf("meth") == 0)
        return true;
        return false;
        }
        public boolean isRuntime() {
        return false;
        }
        public boolean matches(Method arg0, Class arg1, Object[] arg2) {
        return false;
        }
        };
        }
        };
        }
        return pointcut;
        }

        /*
        * @see org.springframework.aop.Advisor#getAdvice()
        */
        public Advice getAdvice() {
        if (advice == null) {

        advice = new MethodBeforeAdvice() {
        private boolean initialised = false;
        public void before(Method arg0, Object[] arg1, Object arg2) throws Throwable {
        Object o = arg2;
        if (o instanceof Initializable && !initialised) {
        Initializable i = (Initializable)o;
        i.init();
        initialised = true;
        }
        }
        };
        }
        return advice;
        }

        /*
        * @see org.springframework.aop.Advisor#isPerInstance()
        */
        public boolean isPerInstance() {
        return true;
        }

        }

        Comment


        • #5
          Jeff,

          I do not know where interface Initializable comes from, so I created a simple one for testing:
          Code:
            public interface Initializable &#123;
              void init&#40;&#41;;
            &#125;
          TestBean interface:
          Code:
            public interface TestBean &#123;
              int methodSum&#40;int a, int b&#41;;
            &#125;
          TestBeanImpl class:
          Code:
            public class TestBeanImpl implements TestBean, Initializable &#123;
              public void init &#40;&#41; &#123;
                System.out.println &#40;"initializing..."&#41;;
              &#125;
          
              public int methodSum&#40;int a, int b&#41; &#123;
                return a + b;
              &#125;
            &#125;
          and my applicationContext.xml
          Code:
          <beans>
            <bean id="beforeAdvice" class="MyAdvisor"/>
          
            <bean id="testBean" class="org.springframework.aop.framework.ProxyFactoryBean">
              <property name="proxyInterfaces"><value>TestBean</value></property>
              <property name="target"><bean class="TestBeanImpl"/></property>
              <property name="interceptorNames">
               <list>
                <value>beforeAdvice</value>
               </list>
              </property>
            </bean>
          </beans>
          This sample runs using JDK1.4, Jakarta commons logging, aopalliance.jar and of course spring.jar (no CGLIB).

          Comment


          • #6
            Jeff,

            Looking at your code, there's some redundant stuff in there. First, when you provide an interceptor/advice that you want to apply to all methods of the instance, there's no need to wrap it in a RegexMethodPointcutAdvisor like you did. ProxyFactoryBean accept interceptors/advices, and providing one directly avoid the regexp layer which wouls make things slower.

            Also, instead of implementing PointcutAdvisor, you can simply implement MethodBeforeAdvice, and pass that bean's name to the ProxyFactoryBean.

            From your code, I don't see that any of it should fail, but eliminating the redundancy should probably make things easier to debug.

            Guillaume

            Comment


            • #7
              Originally posted by gpoirier
              Also, instead of implementing PointcutAdvisor, you can simply implement MethodBeforeAdvice, and pass that bean's name to the ProxyFactoryBean.
              I have a different opinion here . I have noticed the flow as
              ProxyFactoryBean ------> createAdvisorChain() -----> addAdvisor() -----> namedBeanToAdvisorOrTargetSource() ----------------------------------------> DefaultAdvisorAdapterRegistry.wrap()
              So the wrap does always make sure that your Advise is Wrapped . The following code shows that :
              public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException {
              if (adviceObject instanceof Advisor) {
              return (Advisor) adviceObject;
              }

              if (!(adviceObject instanceof Advice)) {
              throw new UnknownAdviceTypeException(adviceObject);
              }
              Advice advice = (Advice) adviceObject;

              if (advice instanceof Interceptor) {
              // So well-known it doesn't even need an adapter
              return new DefaultPointcutAdvisor(advice);
              }
              for (int i = 0; i < this.adapters.size(); i++) {
              // Check that it is supported
              AdvisorAdapter adapter = (AdvisorAdapter) this.adapters.get(i);
              if (adapter.supportsAdvice(advice)) {
              return new DefaultPointcutAdvisor(advice);
              }
              }
              throw new UnknownAdviceTypeException(advice);
              }
              Jeff Gager , can you post all the code here ? I mean the Interface , the Target class TestBean .

              Regards
              Vicky

              Comment


              • #8
                Originally posted by vickyk
                I have a different opinion here . I have noticed the flow as
                ProxyFactoryBean ------> createAdvisorChain() -----> addAdvisor() -----> namedBeanToAdvisorOrTargetSource() ----------------------------------------> DefaultAdvisorAdapterRegistry.wrap()
                So the wrap does always make sure that your Advise is Wrapped . The following code shows that :
                I'm not sure how what you're saying is any different than what I said? My point was that you don't have to make your own Advisor, you can just pass an Advice to ProxyFactoryBean and it will nicely wraps it in an Advisor.

                Jeff,

                I also noticed your code is not synchronized. If your TestBeanImpl was to be called in concurrent threads, then the init method might be called twice.

                Comment


                • #9
                  Originally posted by gpoirier
                  I'm not sure how what you're saying is any different than what I said? My point was that you don't have to make your own Advisor, you can just pass an Advice to ProxyFactoryBean and it will nicely wraps it in an Advisor.
                  Ya that is correct , I have interpreted it wrongly .In this case he could use the DefaultPointcutAdvisor.
                  Originally posted by gpoirier
                  ProxyFactoryBean accept interceptors/advices, and providing one directly avoid the regexp layer which wouls make things slower.
                  Do you mean the slower Development or Slower Execution here ?

                  Regards
                  Vicky

                  Comment


                  • #10
                    I meant slower Execution. Using a regular expression is slower then just returning true. Might not be a huge difference, especially if the method's gonna do DB stuff, but there's no real gain for using RegexpMethodPointcutAdvisor when you want to match all methods. It also adds uneeded configuration code.

                    Comment


                    • #11
                      Originally posted by gpoirier
                      I meant slower Execution. Using a regular expression is slower then just returning true. Might not be a huge difference, especially if the method's gonna do DB stuff, but there's no real gain for using RegexpMethodPointcutAdvisor when you want to match all methods. It also adds uneeded configuration code.
                      I am sure about the RegexpMethodPointcutAdvisor , I have not been aware of regular expression as the word . Do you mean the following snippet
                      return new MethodMatcher() {
                      public boolean matches(Method arg0, Class arg1) {
                      if (arg0.getName().indexOf("meth") == 0)
                      return true;
                      return false;
                      }
                      can be replaced by
                      return new MethodMatcher() {
                      public boolean matches(Method arg0, Class arg1) {
                      //if (arg0.getName().indexOf("meth") == 0)
                      return true;
                      }
                      Rgds
                      Vicky

                      Comment


                      • #12
                        Originally posted by gpoirier
                        I meant slower Execution. Using a regular expression is slower then just returning true. Might not be a huge difference, especially if the method's gonna do DB stuff, but there's no real gain for using RegexpMethodPointcutAdvisor when you want to match all methods. It also adds uneeded configuration code.
                        Should not the Introduciton Advisor be used in the case of matching all the methods ?

                        Rgds
                        Vicky

                        Comment


                        • #13
                          Solution

                          Wow this is a great forum - thanks to everyone for the help and advice.

                          It's working fine now

                          Comment


                          • #14
                            Jeff,

                            I'm glad we could help you. However, I also forgot a last thing that I'm not sure
                            you were aware. For your MyBeforeAdvice to work on multiple target instances, your
                            advice/advisor must be a prototype, otherwise the same advice instance will be used
                            for each target, thus only on one of your targets would init be called.


                            Vickyk,

                            Originally posted by vickyk
                            I am sure about the RegexpMethodPointcutAdvisor , I have not been aware of regular expression as the word . Do you mean the following snippet
                            [...]
                            can be replaced by
                            [...]
                            No, what I meant is replacing the XML code:

                            Code:
                            <bean id="beforeAdvice" class="MyBeforeAdvice"/>
                            
                            <bean id="beforeAdvisor"
                            class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
                            <property name="advice"><ref local="beforeAdvice"/></property>
                            <property name="pattern"><value>.*</value></property>
                            </bean>
                            
                            <bean id="test1" class="org.springframework.aop.framework.ProxyFactoryBean">
                            <property name="proxyInterfaces"><value>TestBean</value></property>
                            <property name="target"><bean class="TestBeanImpl"/></property>
                            <property name="interceptorNames">
                            <list>
                            <value>beforeAdvisor</value>
                            </list>
                            </property>
                            </bean>
                            by
                            Code:
                            <bean id="beforeAdvice" class="MyBeforeAdvice"/>
                            
                            <bean id="test1" class="org.springframework.aop.framework.ProxyFactoryBean">
                            <property name="proxyInterfaces"><value>TestBean</value></property>
                            <property name="target"><bean class="TestBeanImpl"/></property>
                            <property name="interceptorNames">
                            <list>
                            <value>beforeAdvice</value>
                            </list>
                            </property>
                            </bean>
                            And previously, for the Advice/Advisor thing, I meant that instead of the
                            MyAdvisor defined in Jeff's post, he could use the following code, with the
                            new XML snippet I mentionned above. But I considering the name change from
                            MyBeforeAdvice in the first post, to MyAdvisor in the second, I guess it's
                            what he did at first, except with the XML snippet using the RegexpMethodPointcutAdvisor.

                            Code:
                            public class MyBeforeAdvice implements MethodBeforeAdvice &#123;
                              private boolean initialised = false;
                              
                              public synchronized void before&#40;Method method, Object&#91;&#93; args, Object target&#41; throws Throwable &#123;
                                if &#40;!initialised && target instanceof Initializable&#41; &#123;
                                  Initializable i = &#40;Initializable&#41;o;
                                  i.init&#40;&#41;;
                                  initialised = true;
                                &#125;
                              &#125;
                            &#125;
                            Originally posted by vickyk
                            Should not the Introduciton Advisor be used in the case of matching all the methods ?
                            The purpose of the Introduction Advisor is to add interfaces to a target, it isn't for interception of existing methods.

                            Comment

                            Working...
                            X