Announcement Announcement Module
Collapse
No announcement yet.
newbie: AOP question Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • newbie: AOP question

    Hi,
    Is it possible in spring to introduce an aspect that would intercept calls to a commons-beanutils method?

  • #2
    As long as you use AspectJ code weaving (which Spring 2.0/2.5 supports) you can.

    Comment


    • #3
      Even if I am just referencing a class that resides in the commons-beanutils JAR file? (i don't have access to the source)

      Comment


      • #4
        I pretty sure you need to use AspectJ to do the weaving of jar files. I'm not 100% sure you can do it in spring, cos spring won't have control of the jar...someone can correct me if i'm wrong.

        Comment


        • #5
          Originally posted by borfnorton View Post
          Even if I am just referencing a class that resides in the commons-beanutils JAR file? (i don't have access to the source)
          Yes. Source access isn't necessary. AspectJ byte code weaving is very slick. And once you understand how it works, is very powerful. Check out the Spring reference manual for more detail.

          Comment


          • #6
            Just wanted to add few more clarification points:

            SpringAOP is Proxy based AOP. In other words it's Spring implementation of Java Dynamic Proxy API. With CGLIB Proxies it became even more flexible by allowing you to intercept methods on the classes that do not implement any interfaces. But with all the benefits of elegant OO approach to AOP paradigm it also has some limitations. One of them is limitations on the pointcuts supported by the Spring AOP. Keep in mind Spring AOP was never in the business of competing with byte-code-injection style of AOP represented by AspectJ and JBossAOP.

            Now, back to your question. Could you use Spring AOP on the class to which you have no source code? The answer is yes, regardless of which AOP technique (byte code injection or dynamic proxies) you are using. The only limitations would be standard JDK packages (you can not weave/inject anything into them), but you can write "call" pointcuts to intercept calls to them.

            So unless you have more specific question about what exactly you are trying to do, the answer is within Spring Application Context you can use Spring AOP or AspectJ to intercept calls to commons-beanutils methods.

            Comment


            • #7
              exactly what I am trying to do

              Hi,
              Thanks for the replies.

              Basically we use struts 1.x and struts uses Apache commons beanutils internally for getting/setting properties on Forms. All of the get/sets go through a class in Apache beanutils called PropertyUtilsBean. This class is in the Apache Commons beanutils JAR.

              We would like to intercept calls to PropertyUtilsBean.getProperty(bean, propName) and before it is called:

              a) if the bean is an "instanceof" a particular class, call a method on on of our classes instead of entering the getProperty() method

              b) if the bean is NOT an "instanceof" this particular class, simply continue execution of the getProperty() method.

              Comment


              • #8
                Here is an aspect (in @AspectJ style) to do something like you are talking about:

                Code:
                @Aspect
                public class OverridePropertyUtilsBeanAspect {
                  @Pointcut("call(* org.apache.commons.beanutils.PropertyUtilsBean.getProperty(Object, String))")
                  public void getProperty() {}
                
                  @Around("getProperty && args(bean, name)")
                  public void override(ProceedingJoinPoint called, Object obj, String name) throws Throwable {
                    if (obj instanceof MyClass) {
                      // Do your stuff
                    } else {
                      called.proceed();
                    }
                  }
                }
                Take a look at the Spring reference manual on how you would weave this into your application. Keep in mind you can't use Spring AOP for this aspect, you need to use AspectJ bytecode weaving.

                Comment


                • #9
                  Similar using XML configuration

                  Code:
                  <bean id="commonsBean" class="org.apache.commons.beanutils.PropertyUtilsBean"/>
                    
                  <bean id="commonsAdvice" class="org.oz.spring.springaop.FooAdvice"/>
                  <aop:config>
                  	<aop:pointcut id="commonsPointcut"
                  			expression="execution(public void org.apache.commons.beanutils.PropertyUtilsBean.getProperty(..))" />    
                  	<aop:advisor pointcut-ref="commonsPointcut" advice-ref="commonsAdvice" />
                  </aop:config>
                  Code:
                  public class FooAdvice implements MethodInterceptor {
                      public Object invoke(MethodInvocation invocation) throws Throwable {
                  		Object returnValue = null;
                  		ReflectiveMethodInvocation mInvocation = (ReflectiveMethodInvocation) invocation;
                  		String parameter = (String) mInvocation.getArguments()[0];
                  		if (parameter instanceof Whatever){
                  			logger.debug(">>> Proceeding with execution");
                  			returnValue = invocation.proceed();
                  		} else {
                  			logger.debug(">>> Hijacking the execution");
                  			returnValue = "Hijacked execution of " + invocation.getMethod().getName() + " method";
                  		}
                  		return returnValue;
                  	}
                  }
                  Keep in mind that what you are gonna be doing is Hijacking the execution of the method based on some condition. Could be dangerous if there is no structure and "rules of engagement" are established.

                  Comment


                  • #10
                    Re;

                    Thanks for the replies.

                    I created and modified this example, spring is booting ok, however I don't see the expected results and am not sure its working.

                    One question I have is what is the reason for the following definition as it is not refereced in the aop:config section?

                    <bean id="commonsBean" class="org.apache.commons.beanutils.PropertyUtilsB ean"/>


                    Also do I need to modify the actual method signature of this declaration?

                    <aopointcut id="commonsPointcut"
                    expression="execution(public void org.apache.commons.beanutils.PropertyUtilsBean.get Property(..))" />

                    Comment


                    • #11
                      You have to take some if these posting with the "grain of salt". Some of them are not complete or accurate enough and should be treated more as pseudo code or a guide. . .

                      There is no
                      Code:
                      public void org.apache.commons.beanutils.PropertyUtilsBean.get Property(..)
                      but there is
                      Code:
                      public Object org.apache.commons.beanutils.PropertyUtilsBean.get Property
                      so it should look like this:

                      Code:
                      <aop:config>
                      	<aop:pointcut id="commonsPointcut"
                      			expression="execution(public Object org.apache.commons.beanutils.PropertyUtilsBean.getProperty(..))" />    
                      	<aop:advisor pointcut-ref="commonsPointcut" advice-ref="commonsAdvice" />
                      </aop:config>

                      Comment


                      • #12
                        re:

                        ah, yep I do have that in there (Object vs. void) now, but still don't see any results, not sure whats going on. Here is my declaration XML

                        HTML Code:
                        	<bean id="commonsBean" class="org.apache.commons.beanutils.PropertyUtilsBean"/>
                        	  
                        	<bean id="commonsAdvice" class="org.oz.spring.springaop.FooAdvice"/>
                           	<aop:config>
                        		<aop:pointcut id="commonsPointcut"
                        				expression="execution(public Object org.apache.commons.beanutils.PropertyUtilsBean.getProperty(..))" />    
                        		<aop:advisor pointcut-ref="commonsPointcut" advice-ref="commonsAdvice" />
                        	</aop:config>
                        here is the code;
                        -------------------

                        Code:
                        package org.oz.spring.springaop;
                        
                        import org.aopalliance.intercept.MethodInterceptor;
                        import org.springframework.aop.framework.ReflectiveMethodInvocation;
                        import org.aopalliance.intercept.MethodInvocation;
                        import org.openmrm.core.util.MrmDynaBean;
                        
                        public class FooAdvice implements MethodInterceptor {
                            public Object invoke(MethodInvocation invocation) throws Throwable {
                        
                        System.out.println("FOO ADVICE CALLED");
                        
                        		Object returnValue = null;
                        		ReflectiveMethodInvocation mInvocation = (ReflectiveMethodInvocation) invocation;
                        		Object parameter =  mInvocation.getArguments()[0];
                        		if (parameter instanceof MrmDynaBean){
                        			System.out.println(">>> Hijacking the execution");
                        			returnValue = "Hijacked execution of " + invocation.getMethod().getName() + " method";
                        		
                        		} else {
                        			System.out.println(">>> Proceeding with execution");
                        			returnValue = invocation.proceed();
                        		}
                        		return returnValue;
                        	}
                        }

                        Comment


                        • #13
                          I am not sure how you are calling it but here is working sample:
                          Code:
                          <bean id="commonsUtil" class="org.apache.commons.beanutils.PropertyUtilsBean"/>
                          
                          <bean id="fooAdvice" class="org.oz.spring.springaop.FooAdvice"/>
                          <aop:config>
                          	<aop:pointcut id="fooPointcut" 
                          		expression="execution(public Object org.apache.commons.beanutils.PropertyUtilsBean.getProperty(..))" />    
                          		<aop:advisor pointcut-ref="fooPointcut" advice-ref="fooAdvice" />
                          </aop:config>
                          Code:
                          public class FooAdvice implements MethodInterceptor {
                          	Logger logger = Logger.getLogger(FooAdvice.class);
                          
                          	/* (non-Javadoc)
                          	 * @see org.aopalliance.intercept.MethodInterceptor#invoke(org.aopalliance.intercept.MethodInvocation)
                          	 */
                          	public Object invoke(MethodInvocation invocation) throws Throwable {
                          		Object returnValue = null;
                          		ReflectiveMethodInvocation mInvocation = (ReflectiveMethodInvocation) invocation;
                          		Object parameter = (String) mInvocation.getArguments()[0];
                          		if (parameter != null){
                          			logger.debug(">>> Proceeding with execution");
                          			returnValue = invocation.proceed();
                          		} else {
                          			logger.debug(">>> Hijacking the execution");
                          			returnValue = "Hijacked execution of " + invocation.getMethod().getName() + " method";
                          		}
                          		return returnValue;
                          	}
                          
                          }
                          Test Case:

                          Code:
                          public void testSpringAOP() throws IllegalAccessException, InvocationTargetException, NoSuchMethodException{
                          		ApplicationContext ac = new ClassPathXmlApplicationContext("org/oz/spring/springaop/springaop.xml");
                          		PropertyUtilsBean utilBean = (PropertyUtilsBean) ac.getBean("commonsUtil");
                          		utilBean.getProperty(null, null);
                          }
                          Output:

                          2008-02-15 15:08:13,843 0 [main] DEBUG org.oz.spring.springaop.FooAdvice - >>> Hijacking the execution


                          Let me know if it worked

                          Comment


                          • #14
                            re:

                            Thanks for your reply. Appreciate your help.

                            I've double checked everything and it all looks ok. I think the difference here is that I never fetch the "bean" via spring. This PropertyUtilsBean class simply lives in the commons jar and is called as low-level Struts code executes. Maybe it isn't working for me because the PropertyUtilsBean is not directly managed by spring and created within it but instead is just being used by another library? (struts)

                            Comment


                            • #15
                              Originally posted by borfnorton View Post
                              I've double checked everything and it all looks ok. I think the difference here is that I never fetch the "bean" via spring. This PropertyUtilsBean class simply lives in the commons jar and is called as low-level Struts code executes.
                              That's correct. That's why you need to use AspectJ bytecode weaving to apply aspects to code not managed by Spring.

                              Comment

                              Working...
                              X