Question

I'm just now trying to enable AOP on my Spring project. I want to execute code (a session cleaning) AFTER the @RequestMapping has completed. Here is my applicationContext.xml (simply load referenced resources

<?xml version="1.0" encoding="UTF-8" standalone="no"?><beans 
xmlns="http://www.springframework.org/schema/beans"  
xmlns:aop="http://www.springframework.org/schema/aop"  
xmlns:context="http://www.springframework.org/schema/context"  
xmlns:jee="http://www.springframework.org/schema/jee" 
xmlns:tx="http://www.springframework.org/schema/tx" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
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/tx
http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/jee
http://www.springframework.org/schema/jee/spring-jee-2.5.xsd">

    <!-- ******************************************************************** -->
    <!-- Include context files from different layers -->
    <!-- ******************************************************************** -->
    <import resource="classpath:appname-security-context.xml"/>
    <import resource="classpath:appname-service-context.xml"/>
    <import resource="classpath:appname-dao-context.xml"/>

</beans>

the security context:

<?xml version="1.0" encoding="UTF-8"?>
    <beans:beans xmlns="http://www.springframework.org/schema/security"
    xmlns:beans="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:security="http://www.springframework.org/schema/security" 
    xmlns:lang="http://www.springframework.org/schema/lang"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://www.springframework.org/schema/security    http://www.springframework.org/schema/security/spring-security-3.0.xsd
    http://www.springframework.org/schema/context 
    http://www.springframework.org/schema/context/spring-context-3.0.xsd">

<http auto-config="true">
<intercept-url pattern='/pages/login.jsp' />
<intercept-url pattern="/secure/*" access="IS_AUTHENTICATED_REMEMBERED" />
<intercept-url pattern="/admin/**" access="ROLE_ADMIN" />
<form-login login-page="/pages/login.jsp" authentication-failure-url="/pages/login.jsp?login_error=true"  /> 
        <logout logout-success-url="/pages/logout-redirect.jsp" invalidate-session="true" />
        <remember-me key="appnameRMKey" user-service-ref="userDetailsService" />
    </http>
    <authentication-manager alias="authenticationManager" >
    <authentication-provider user-service-ref='userDetailsService' >
        <password-encoder hash="plaintext"/>
    </authentication-provider>
    </authentication-manager>

    <beans:bean id="userDetailsService" class="org.springframework.security.core.userdetails.jdbc.JdbcDaoImpl">
        <beans:property name="rolePrefix" value="ROLE_" />
        <beans:property name="dataSource" ref="springSecurityDataSource" />
        <beans:property name="usersByUsernameQuery" value="SELECT username,password,enabled FROM Users WHERE username = ?" />
        <beans:property name="authoritiesByUsernameQuery" value="SELECT u.username, a.authorityname FROM Users u JOIN Users_Authorities ua on u.id = ua.user_id JOIN Authorities a on ua.authorities_id = a.id WHERE u.username = ?" />
    </beans:bean>   

    <!-- ******************************************************************** -->
    <!-- Apply security for all beans where security was set -->
    <!-- ******************************************************************** -->

    <global-method-security jsr250-annotations="enabled" proxy-target-class = "true" secured-annotations="enabled">
        <protect-pointcut expression="execution(* appname.UsersDAO.*(..))" access="IS_AUTHENTICATED_REMEMBERED"/>
        <protect-pointcut expression="execution(* appname.AuthoritiesDAO.*(..))" access="IS_AUTHENTICATED_REMEMBERED"/>
    </global-method-security>
</beans:beans>

my service context:

<?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:tx="http://www.springframework.org/schema/tx" 
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:jee="http://www.springframework.org/schema/jee" 
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:lang="http://www.springframework.org/schema/lang"
      xsi:schemaLocation="http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/aop 
        http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
        http://www.springframework.org/schema/tx 
        http://www.springframework.org/schema/tx/spring-tx-3.0.xsd   
        http://www.springframework.org/schema/context 
        http://www.springframework.org/schema/context/spring-context-3.0.xsd   
        http://www.springframework.org/schema/jee 
        http://www.springframework.org/schema/jee/spring-jee-3.0.xsd
        http://www.springframework.org/schema/lang
        http://www.springframework.org/schema/lang/spring-lang-3.0.xsd">
    <!-- ******************************************************************** -->
    <!-- Scan for service layer annotated beans -->
    <!-- ******************************************************************** -->
<context:component-scan base-package="appname" scoped-proxy="interfaces" />
<aop:config  proxy-target-class="true">
    </aop:config>
    <aop:aspectj-autoproxy proxy-target-class="true">
    </aop:aspectj-autoproxy>
    <!-- ******************************************************************** -->
    <!-- Mark bean transactions as annotation driven -->
    <!-- ******************************************************************** -->
    <tx:annotation-driven transaction-manager="transactionManager" />

</beans>

my web context:(BEAN DEFINITION OMITTED FOR SHORTNESS!!)

<mvc:annotation-driven/>
    <mvc:default-servlet-handler/>    
    <tx:annotation-driven transaction-manager="transactionManager" />
    <bean id="multipartResolver" class="org.skyway.spring.util.web.binary.ModelBindingMultipartResolver" />
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver" />
    <bean id="streamedBinaryContentView" class="org.skyway.spring.util.web.binary.ModelAttributeStreamer" />
    <bean id="beanNameViewResolver" class="org.springframework.web.servlet.view.BeanNameViewResolver" />
    <bean id="viewResolver" class="org.springframework.web.servlet.view.UrlBasedViewResolver">
    <property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
    <property name="prefix" value="/WEB-INF/pages/" />
    </bean>
    <bean id="iPhoneUserAgentViewResolver" class="org.skyway.spring.util.viewresolution.UserAgentViewResolver">
    <property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
    <property name="agentSubstring" value="iPhone" />
    <property name="prefix" value="/WEB-INF/iphone/" />
    <property name="order" value="0" />
    </bean><bean id="webInfViewResolver" class="org.skyway.spring.util.viewresolution.AbsolutePathViewResolver">
    <property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
    <property name="order" value="-1" />
    </bean>
    <context:component-scan base-package="appname" scoped-proxy="interfaces" />
    <aop:config  proxy-target-class="true">
    </aop:config>
    <aop:aspectj-autoproxy proxy-target-class="true">
    </aop:aspectj-autoproxy>
    </beans>

this is the interface of aspect class

package appname;
import it.pstmarche.model.HibernateSessionFactory;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
@Component
@Aspect
public interface SessionInterceptor {

@Pointcut("execution(public * appname.ImplantManager+.*(..))")
public void pc() ;

@Before("pc()")
public void print();
}

the implementation is trivial @Before("pc()") public void print(){ System.out.println("About to make call to print Hello World" }

I also tried some other expressions like:

  • @Pointcut("execution(@org.springframework.web.bind.annotation.RequestMapping public * appname.*(..))")
  • and many others

with no luck. I start thinking the problem is not the expression (i already tried about 10-15 types...) but the class not being considered in the context.

For answer, take in consideration:

  • the name appname is intended for example, obviusly
  • inserting the aop:config and aop:aspectj-autoproxy are only a try because i also readed in other threads that the config must be enabled in every file that is loaded by applicationContext. I also tried inserting only in one but no result
  • the controller has the annotated interface + annotated implementation. i also tried without annotating the interface or removing completely with no result

any help? :)

EDIT: in response to axtavt .. sorry i forgot to add my web.xml, here is a piece of it

<servlet>
<description>context-servlet</description>
    <servlet-name>appname Servlet</servlet-name>
    <servlet-class>
        org.springframework.web.servlet.DispatcherServlet
    </servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            classpath:appname-web-context.xml
        </param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

i correctly load the contextConfigLocation via web-context.xml file. Sorry i forgot it :-(

EDIT2: I got the answer following my mistake by the suggestion of axtavt! thanks!

Was it helpful?

Solution

AOP is configured at per-context basis.

You have two contexts - root web application context (applicationContext.xml, which includes config files imported into it), and application context of DispatcherServlet, where controllers beans are declared.

So, in order to apply aspects to controllers you need to add <aop:aspectj-autoproxy> to servlet-specific context.

Also note that you shouldn't use <context:component-scan> over the same base package in different contexts, see @Service are constructed twice.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top