Announcement Announcement Module
Collapse
No announcement yet.
Cannot get the simplest AOP example working Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Cannot get the simplest AOP example working

    Hello,

    I'm new to AOP and trying to create a very simple example based on the reference guide. I'm at the point of not getting any errors but my advice method does not get called. I already spent 10 hours finding the problem but without an error message, I have no clue how to figure this out. Please help. Is there a way to dump a list of created proxies so I can find out why is mine not getting created? Or is there any global XML tag I'm missing. I have seen various proxy creation methods in the reference but it was not clear whether I have to use them or it is automatic with the use of the <aop:config> tag.

    This is a web application running on Tomcat 5.5 and I'm using Eclipse to redeploy and launch it.

    Let me know if you need any more information.

    web.xml:
    Code:
    <?xml version="1.0" encoding="UTF-8"?>
    <web-app id="WebApp_ID" version="2.4"
    	xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
    	<display-name>test4</display-name>
    
    	<listener>
      		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    	</listener>
    
    	<servlet>
    		<servlet-name>test4</servlet-name>
    		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    		<load-on-startup>1</load-on-startup>
    	</servlet>
    
    	<servlet-mapping>
    		<servlet-name>test4</servlet-name>
    		<url-pattern>*.htm</url-pattern>
    	</servlet-mapping>
    
    
    	<welcome-file-list>
    		<welcome-file>index.jsp</welcome-file>
    	</welcome-file-list>
    
    	<jsp-config>
    		<taglib>
    			<taglib-uri>/spring</taglib-uri>
    			<taglib-location>/WEB-INF/tld/spring-form.tld</taglib-location>
    		</taglib>
    	</jsp-config>
    
    
    </web-app>
    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"
    	   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">
    
    	<aop:config>
    		<aop:pointcut id="logging" expression="execution(* db.Product.*(..))"/> 
    		<aop:aspect ref="loggerBean">
    		    <aop:before pointcut-ref="logging" method="logSaveMethods"/>
    		</aop:aspect>
    	</aop:config>
    
    	<bean id="loggerBean" class="service.Logger"/>
     
    </beans>
    db.Product:
    Code:
    package db;
    
    public class Product {
    	int id = -1;
    	String name = "";
    	String desc = "";
    	double price = 0;
    
    	public String getName() {
    		return name;
    	}
    
    	public void setName(String name) {
    		this.name = name;
    		System.out.println("setName called");
    	}
            ...
    }
    service.Logger:
    Code:
    package service;
    
    public class Logger
    {
    	public void logSaveMethods()
    	{
    		System.out.println("AOP: Saving record");
    	}
    }
    Program output includes "setName called" but never "AOP: Saving record".

  • #2
    Hi,

    You need to add the below entry in web.xml just before the listener(org.springframework.web.context.ContextLo aderListener).

    <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/applicationContext.xml</param-value>
    </context-param>

    This entry will tell the Spring Container where the applicationContext is placed on basis of which Spring will instantiate the beans in applicationContext.xml.

    Hope this helps.

    kartik

    Comment


    • #3
      Originally posted by nsomlai View Post
      ...
      Program output includes "setName called" but never "AOP: Saving record".
      Your snippets don't show either 'Product' bean definition on how it's 'setName()' method is called. You can't expect the method to be aop advised it it's called by the spring container.

      Comment


      • #4
        kravicha: thanks, I tried to add that but as far as I know this is the default location and filename and the listener should load the XML automatically.

        denis: You are right, I was using a class that is not defined as a bean. I made the necessary changes and now trying to intercept something in an XML-defined singleton bean:


        The result is still the same though: no error, no intercepts with this definition:

        Code:
        	<aop:config>
        		<aop:pointcut id="logging" expression="execution(public void service.ProductManager.saveProduct(..))"/> 
        		<aop:aspect ref="loggerBean">
        		    <aop:before pointcut-ref="logging" method="logSaveMethods"/>
        		</aop:aspect>
        	</aop:config>
        Changing the definition to this (which, to my knowledge, is equivalent)
        Code:
        <aop:config>
        		<aop:aspect ref="loggerBean">
        		    <aop:before pointcut="execution(public void service.ProductManager.saveProduct(..))" method="logSaveMethods"/>
        		</aop:aspect>
        	</aop:config>
        results in an exception:
        Code:
        SEVERE: Context initialization failed
        org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'productManager' defined in ServletContext resource [/WEB-INF/test4-servlet.xml]: Initialization of bean failed; nested exception is java.lang.NoSuchMethodError: net.sf.cglib.proxy.Enhancer.setInterceptDuringConstruction(Z)V
        	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:480)
        	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory$1.run(AbstractAutowireCapableBeanFactory.java:409)
        	at java.security.AccessController.doPrivileged(Native Method)
        	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:380)
        	at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:264)
        	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
        	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:261)
        	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:185)
        	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:164)
        	at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:429)
        	at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:728)
        	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:380)
        	at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:402)
        	at org.springframework.web.servlet.FrameworkServlet.initWebApplicationContext(FrameworkServlet.java:316)
        	at org.springframework.web.servlet.FrameworkServlet.initServletBean(FrameworkServlet.java:282)
        	at org.springframework.web.servlet.HttpServletBean.init(HttpServletBean.java:126)
        	at javax.servlet.GenericServlet.init(GenericServlet.java:212)
        	at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1139)
        	at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:966)
        	at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:3996)
        	at org.apache.catalina.core.StandardContext.start(StandardContext.java:4266)
        	at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1014)
        	at org.apache.catalina.core.StandardHost.start(StandardHost.java:736)
        	at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1014)
        	at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:443)
        	at org.apache.catalina.core.StandardService.start(StandardService.java:448)
        	at org.apache.catalina.core.StandardServer.start(StandardServer.java:700)
        	at org.apache.catalina.startup.Catalina.start(Catalina.java:552)
        	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        	at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
        	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
        	at java.lang.reflect.Method.invoke(Unknown Source)
        	at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:295)
        	at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:433)

        applicationContext.xml is empty. test4-servlet.xml is as follows:
        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"
               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">
        
          <bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
            <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
            <property name="url" value="jdbc:mysql://localhost/test4"/>
          </bean>
          
         <bean id="mySessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
            <property name="dataSource" ref="myDataSource"/>
            <property name="mappingResources">
              <list>
                <value>db/Product.hbm.xml</value>
              </list>
            </property>
            <property name="hibernateProperties">
              <value>
                hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
                hibernate.current_session_context_class=thread
              </value>
            </property>
          </bean>
        
            <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
                <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"></property>
                <property name="prefix" value="/WEB-INF/jsp/"></property>
                <property name="suffix" value=".jsp"></property>        
            </bean>
        
            <bean id="productManager" class="service.ProductManager" init-method="init">
            	<property name="sessionFactory" ref="mySessionFactory"/>
            </bean>
        
        	<aop:config>
        		<aop:pointcut id="logging" expression="execution(public void service.ProductManager.saveProduct(..))"/> 
        		<aop:aspect ref="loggerBean">
        		    <aop:before pointcut-ref="logging" method="logSaveMethods"/>
        		</aop:aspect>
        	</aop:config>
        
        	<bean id="loggerBean" class="service.Logger"/>
        
        	<bean name="/list.htm" class="web.ListController">
                <property name="manager" ref="productManager"/>
            </bean>
            
           <bean name="/edit.htm" class="web.EditController">
                <property name="sessionForm" value="true"/>
                <property name="commandName" value="Product"/>
                <property name="commandClass" value="db.Product"/>
                <property name="validator">
                    <bean class="service.ProductValidator"/>
                </property>
                <property name="formView" value="edit"/>
                <property name="successView" value="list.htm"/>
                <property name="productManager" ref="productManager"/>
            </bean>
        
             <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
                <property name="basename" value="messages"/>
            </bean>
        </beans>
        One more attempt tomorrow to fix this then I will have to give up on AOP, it's taking too much time to understand the concept.

        Comment


        • #5
          Not sure about exact reason of your problem but 'java.lang.NoSuchMethodError: net.sf.cglib.proxy.Enhancer.setInterceptDuringCons truction(Z)V' makes me think that you use inconsistent spring and cglib versions.

          Comment


          • #6
            I checked and CGLIB was OK but it gave me an idea. I rechecked the libs I'm using for Hibernate3 and found that the distribution contains commons-collections-3.1.jar but I have copied the 3.2 version to my app. Replacing that fixed the problem and the advice is now called.

            Thanks a lot for your help.

            Comment

            Working...
            X