Page 2 of 2 FirstFirst 12
Results 11 to 18 of 18

Thread: newbie: AOP question

  1. #11
    Join Date
    Jan 2008
    Location
    Mohnton, PA USA (that's near Philadelphia)
    Posts
    2,148

    Default

    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>

  2. #12

    Default 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;
    	}
    }

  3. #13
    Join Date
    Jan 2008
    Location
    Mohnton, PA USA (that's near Philadelphia)
    Posts
    2,148

    Default

    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

  4. #14

    Default 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)

  5. #15
    Join Date
    Feb 2005
    Location
    Boston, MA
    Posts
    1,142

    Default

    Quote 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.
    Bill

  6. #16
    Join Date
    Jan 2008
    Location
    Mohnton, PA USA (that's near Philadelphia)
    Posts
    2,148

    Default

    Yes, if you are not letting Spring manage your class, then SpringAOP could be an issue. You could use @Configurable for the class that is not managed by the Spring container, but that would only work if you had access to the source code (which in your case you don't).

    The best thing about Spring is that there is more then 1 way to do anything which means you can still do it.
    In your situation AspectJ would be a solution (as some of the guys have pointed out earlier).

    Below you'll find a working example, but i would seriously suggest to read up on chapters 6 and 7 of Spring reference manual.



    Aspect:

    Code:
    import org.apache.log4j.Logger;
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.Signature;
    import org.aspectj.lang.annotation.Around;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Pointcut;
    
    @Aspect
    public class FooAspect {
    	Logger logger = Logger.getLogger(FooAdvice.class);
    	
    	@Pointcut("execution(public Object org.apache.commons.beanutils.PropertyUtilsBean.getProperty(..))")
    	public void getProperty() {
    	}
    
    	@Around("getProperty()")
    	public Object profile(ProceedingJoinPoint pjp) throws Throwable {
    		Object returnValue = null;
    		Signature signature = pjp.getStaticPart().getSignature();
    		Object parameter = (Object) pjp.getArgs()[0];
    		if (parameter != null){
    			logger.debug(">>> Proceeding with execution");
    			returnValue = pjp.proceed();
    		} else {
    			logger.debug(">>> Hijacking the execution");
    			returnValue = "Hijacked execution of " + signature.getName() + " method";
    		}
    		return returnValue;
    	}
    }
    META-INF/aop.xml


    Code:
    <!DOCTYPE aspectj PUBLIC
    "-//AspectJ//DTD//EN" "http://www.eclipse.org/aspectj/dtd/aspectj.dtd">
    <aspectj>
    	<weaver>
    		<!-- only weave classes in our application-specific packages -->
    		<include within="org.apache.commons.beanutils.*" />
    	</weaver>
    	
    	<aspects>
    		<!-- weave in just this aspect -->
    		<aspect name="org.oz.spring.prototype.thread49824.FooAspect" />
    	</aspects>
    </aspectj>
    applicationcontext.xml

    Code:
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
    	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xmlns:aop="http://www.springframework.org/schema/aop"  
    	xmlns:context="http://www.springframework.org/schema/context"
    	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
                            http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd 
                            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd">
    	
    	
    	<context:load-time-weaver/>
    </beans>
    Test:

    Code:
    public void testSpringAOP() throws IllegalAccessException, InvocationTargetException, NoSuchMethodException{
    		PropertyUtilsBean utilBean = new PropertyUtilsBean();
    		utilBean.getProperty(null, null);
    }
    Good luck

  7. #17

    Default re:

    Hi,
    Thanks for the info I am trying to get it to work, but I think the error I am getting is just some with the environment I am trying to get it to work in (grails)

    2008-02-15 17:46:32.519::WARN: Failed startup of context org.mortbay.jetty.webapp.WebAppContext@94cbe2{/,C:\zem\grails_projects\op
    enmrm/web-app}
    org.springframework.beans.factory.BeanCreationExce ption: Error creating bean with name 'org.springframework.context.weaving.AspectJWeav
    ingEnabler#0': Initialization of bean failed; nested exception is org.springframework.beans.factory.BeanCreationExce ption: Error creati
    ng bean with name 'loadTimeWeaver': Initialization of bean failed; nested exception is java.lang.IllegalStateException: ClassLoader [ja
    va.net.URLClassLoader] does NOT provide an 'addTransformer(ClassFileTransformer)' method. Specify a custom LoadTimeWeaver or start your
    Java virtual machine with Spring's agent: -javaagent:spring-agent.jar
    at java.security.AccessController.doPrivileged(Native Method)
    at RunApp_groovy$_run_closure2_closure7.doCall(RunApp _groovy:74)
    at RunApp_groovy$_run_closure2_closure7.doCall(RunApp _groovy)
    at Init_groovy$_run_closure6.doCall(Init_groovy:127)
    at RunApp_groovy$_run_closure2.doCall(RunApp_groovy:7 3)
    at RunApp_groovy$_run_closure2.doCall(RunApp_groovy)
    at RunApp_groovy$_run_closure1.doCall(RunApp_groovy:6 5)
    at RunApp_groovy$_run_closure1.doCall(RunApp_groovy)
    at gant.Gant.dispatch(Gant.groovy:271)
    at gant.Gant.this$2$dispatch(Gant.groovy)
    at gant.Gant.invokeMethod(Gant.groovy)
    at gant.Gant.processTargets(Gant.groovy:436)
    at gant.Gant.processArgs(Gant.groovy:372)
    Caused by: org.springframework.beans.factory.BeanCreationExce ption: Error creating bean with name 'loadTimeWeaver': Initialization of b
    ean failed; nested exception is java.lang.IllegalStateException: ClassLoader [java.net.URLClassLoader] does NOT provide an 'addTransfor
    mer(ClassFileTransformer)' method. Specify a custom LoadTimeWeaver or start your Java virtual machine with Spring's agent: -javaagent:s
    pring-agent.jar

  8. #18
    Join Date
    Nov 2006
    Posts
    12

    Thumbs up

    I've had a similar problem. Starting my Spring application without Jetty:

    Code:
    	public static void main(String[] args) {
    		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-configuration/demoQuartz-applicationContext.xml");
    works fine. With VM argument given as follows:

    Code:
    -javaagent:~/tools/spring-framework-2.5/dist/weaving/spring-agent.jar
    Starting the same application inside Jetty

    Code:
    	public static void main(String[] args) {
    		// start spring container
    		String[] configLocations = new String[] { "classpath:spring-configuration/demoQuartz-applicationContext-jetty.xml" };
    
    		ApplicationContext context = new FileSystemXmlApplicationContext(configLocations);
    		Server server = (Server) context.getBean("jettyServer");
    		// get host
    		String host = server.getConnectors()[0].getHost();
    		if (host == null) {
    			host = "localhost";
    		}
    		// get port
    		int port = server.getConnectors()[0].getPort();
    		// get context path
    		Handler[] handlers = ((ContextHandlerCollection) server.getHandlers()[0]).getHandlers();
    		String contextPath = ((WebAppContext) handlers[0]).getContextPath();
    		if (LOG.isInfoEnabled()) {
    			LOG.info("server started - 'http://" + host + ":" + port + contextPath + "'");
    		}
    
    	}
    fails:

    Code:
    java.lang.IllegalStateException: ClassLoader [org.mortbay.jetty.webapp.WebAppClassLoader] does NOT provide an 'addTransformer(ClassFileTransformer)' method.
    	at org.springframework.instrument.classloading.ReflectiveLoadTimeWeaver.<init>(ReflectiveLoadTimeWeaver.java:103)
    	at org.springframework.instrument.classloading.ReflectiveLoadTimeWeaver.<init>(ReflectiveLoadTimeWeaver.java:86)
    	at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    I started Jetty with the following Spring configuration:

    Code:
    	<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    		<property name="locations">
    			<list>
    				<value>classpath:/spring-configuration/jetty.properties</value>
    			</list>
    		</property>
    		<property name="ignoreResourceNotFound" value="true"/>
    		<property name="propertiesArray">
    			<props>
    				<prop key="jetty.port">8080</prop>
    				<prop key="jetty.contextPath">/</prop>
    				<prop key="jetty.war">src/main/webapp</prop>
    			</props>
    		</property>
    	</bean>
    
        <bean id="jettyServer" class="org.mortbay.jetty.Server" init-method="start" destroy-method="stop">
            <property name="connectors">
                <list>
                    <bean id="Connector" class="org.mortbay.jetty.nio.SelectChannelConnector">
                        <property name="port" value="${jetty.port}"/>
                    </bean>
                </list>
            </property>
    
            <property name="handler">
                <bean id="handlers" class="org.mortbay.jetty.handler.HandlerCollection">
                    <property name="handlers">
                        <list>
                            <bean id="contexts" class="org.mortbay.jetty.handler.ContextHandlerCollection">
                                <property name="handlers">
                                    <list>
                                        <bean class="org.mortbay.jetty.webapp.WebAppContext">
                                            <property name="contextPath" value="${jetty.contextPath}"/>
                                            <property name="war" value="${jetty.war}">
                                            </property>
                                        </bean>
                                    </list>
                                </property>
                            </bean>
                        </list>
                    </property>
                </bean>
            </property>
        </bean>
    The problem was one missing line of configuration in the jetty-XML above. After i added the load-time-weaver configuration to the jetty running the Spring application everything runs as smoothly as outside the container.

    Code:
        <context:load-time-weaver />
    Now all my @Configurable beans get @Autowired inside Jetty, too.

    Spring is

Posting Permissions

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