Announcement Announcement Module
Collapse
No announcement yet.
Autowiring in Aspects Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Autowiring in Aspects

    I am using Spring MVC for web applications and for Audit logging I am using AOP and it works when I log the changes using log4j. I want to dump these changes to database and for this I am using Autowired DAO inside my Aspect bean as below.

    Can somebody let me know why it fails? I am really not sure about the sequence of things when aspects come in to play at runtime.


    Code:
    @Aspect
    public class LoggingInterceptor
    {
        Log log = LogFactory.getLog(LoggingInterceptor.class);
    
        @Autowired
        private AuditData auditData;
    
        @Around("@annotation(com.xx.yy.util.audit.Auditable)")
        public Object profile(ProceedingJoinPoint pjp) throws Throwable
        {
            final String currentUser = SecurityContextHolder.getContext().getAuthentication().getName();
            try
            {
    
                Object resultValue = pjp.proceed();
                if (log.isErrorEnabled())
                {
                    logInfo(currentUser, pjp);
                    System.out.println("dao: " + auditData); // am getting this as null
                    // logAudit(currentUser, pjp); //dump changes to db 
                }
                return resultValue;
            }
            finally
            {
                // sw.stop();
    
            }
        }
        
    }
    Last edited by ketankhairnar; Dec 31st, 2009, 01:50 PM.

  • #2
    The aspect itself looks fine. It is probably your configuration that is causing the problem. Do you have other non-aspect beans with the DAO as an autowired dependency? Does that work?

    -Ramnivas

    Comment


    • #3
      I do have a Service bean/Controller bean with with this dao as Autowired dependency and that works fine. I tried these combination just for testing.
      Configuration is as below:

      Code:
      	<!-- Turn on AspectJ @Configurable support -->
      	<aop:aspectj-autoproxy proxy-target-class="false" />
      	<bean id="logInterceptor" class="com.xx.yy.util.audit.LoggingInterceptor" >
      		<property name="dao">
      			<ref bean="auditData"/>
      		</property>
      	</bean>
      Also myDAO don't have interface. is that a problem
      Last edited by ketankhairnar; Jan 1st, 2010, 11:17 PM.

      Comment


      • #4
        First, the comment is incorrect :-) <aop:aspectj-autoproxy> does NOT turn on @Configurable support.

        You don't have property named "dao" in your aspect (it is named "auditData"). Did you not get an error for this?

        -Ramnivas

        Comment


        • #5
          my bad, sorry for the confusion
          I tried both approaches :

          1) putting "dao" in Aspect and configuration is done as mentioned above. So I had getter and setter for dao

          2) using @Autowired annotation as in the very first snippet.

          Comment


          • #6
            It may help if you put together exact code that doesn't work. What you describe is a common scenario, so it must be a combination of how you put things together that causes it not to work.

            -Ramnivas

            Comment


            • #7
              Aspect:
              Code:
              @Aspect
              public class LoggingInterceptor
              {
                  Log log = LogFactory.getLog(LoggingInterceptor.class);
              
                  @Autowired
                  private AuditData auditData;
              
                  @Around("@annotation(com.xx.yy.util.audit.Auditable)")
                  public Object profile(ProceedingJoinPoint pjp) throws Throwable
                  {
                      final String currentUser = SecurityContextHolder.getContext().getAuthentication().getName();
                      try
                      {
              
                          Object resultValue = pjp.proceed();
                          if (log.isErrorEnabled())
                          {
                              logInfo(currentUser, pjp);
                              System.out.println("dao: " + auditData); // am getting this as null
                              // logAudit(currentUser, pjp); //dump changes to db 
                          }
                          return resultValue;
                      }
                      finally
                      {
                          // sw.stop();
              
                      }
                  }
              applicationContext.xml
              Code:
              	<aop:aspectj-autoproxy proxy-target-class="false" />
              	<bean id="logInterceptor" class="com.xx.yy.util.audit.LoggingInterceptor"  />
              DAO
              Code:
              @Repository
              public class AuditData extends HibernateDaoSupport
              {
                  
                  @SuppressWarnings("unused")
                  private HibernateTemplate template;
              
                  public List<AuditInformation> findAll()
                  {
                      return getHibernateTemplate().loadAll(AuditInformation.class);
                  }
                  
                  public void makePersistent(AuditInformation auditInformation)
                  {
                      getHibernateTemplate().save(auditInformation);
                  }
              }
              Annotation Usage:

              Code:
                  @Auditable
                     @RequestMapping(value = "index.html", method = RequestMethod.GET)
                  public String index(HttpServletRequest request, HttpServletResponse response)
                  {
                      final String currentUser = SecurityContextHolder.getContext().getAuthentication().getName();
                      Users user = (Users)usersData.getUser(currentUser);
                      final String userName = user.getFirstName() + " " + user.getLastName();
                      request.getSession().setAttribute("loggedInUser", currentUser);
                      request.getSession().setAttribute("userName", userName);
                      //        System.out.println("Audit Data : " + auditData);
                    // autowired auditData is available here but not in aspect
                      return "login/index";
                  }

              thanks for helping ramnivas. am reading available material on this stuff. Am sure its configuration issue as logging activity is working fine.

              Startup Log:
              Code:
              Jan 01 23:05:49 DEBUG ort.DefaultListableBeanFactory getSingleton              Creating shared instance of singleton bean 'logInterceptor'
              Jan 01 23:05:49 DEBUG ort.DefaultListableBeanFactory run                       Creating instance of bean 'logInterceptor'
              Jan 01 23:05:49 DEBUG ort.DefaultListableBeanFactory doGetBean                 Returning cached instance of singleton bean 'org.springframework.aop.support.DefaultBeanFactoryPointcutAdvisor#0'
              Jan 01 23:05:49 DEBUG y.annotation.InjectionMetadata addInjectedField          Found injected field on class [com.xx.yy.util.audit.LoggingInterceptor]: AutowiredFieldElement for private com.xx.yy.audit.dao.AuditData com.xx.yy.util.audit.LoggingInterceptor.dao
              Jan 01 23:05:49 DEBUG y.annotation.InjectionMetadata addInjectedField          Found injected field on class [com.xx.yy.util.audit.LoggingInterceptor]: AutowiredFieldElement for private com.xx.yy.audit.dao.AuditData com.xx.yy.util.audit.LoggingInterceptor.dao
              Jan 01 23:05:49 DEBUG ort.DefaultListableBeanFactory doCreateBean              Eagerly caching bean 'logInterceptor' to allow for resolving potential circular references
              Jan 01 23:05:49 DEBUG y.annotation.InjectionMetadata injectFields              Processing injected field of bean 'logInterceptor': AutowiredFieldElement for private com.xx.yy.audit.dao.AuditData com.xx.yy.util.audit.LoggingInterceptor.dao
              Jan 01 23:05:49 DEBUG ort.DefaultListableBeanFactory doGetBean                 Returning cached instance of singleton bean 'auditData'
              Jan 01 23:05:49 DEBUG redAnnotationBeanPostProcessor registerDependentBeans    Autowiring by type from bean name 'logInterceptor' to bean named 'auditData'
              Jan 01 23:05:49 DEBUG ort.DefaultListableBeanFactory doGetBean                 Returning cached instance of singleton bean 'org.springframework.aop.support.DefaultBeanFactoryPointcutAdvisor#0'
              Jan 01 23:05:49 DEBUG ort.DefaultListableBeanFactory doGetBean                 Returning cached instance of singleton bean 'org.springframework.aop.support.DefaultBeanFactoryPointcutAdvisor#0'
              Jan 01 23:05:49 DEBUG ort.DefaultListableBeanFactory run                       Finished creating instance of bean 'logInterceptor'
              Last edited by ketankhairnar; Jan 2nd, 2010, 12:09 AM.

              Comment


              • #8
                I don't see <context:annotation-config/> that would trigger autowiring.

                -Ramnivas

                Comment


                • #9
                  Autowiring works in my application as I have context-component-scan declaration.

                  I got it working by marking my aspect @Configurable

                  Code:
                  @Configurable 
                  @Aspect
                  public class LoggingInterceptor
                  {
                      
                      @Autowired
                      private AuditData dao;
                      
                      @Around("@annotation(com.xx.yy.util.audit.Auditable)")
                      public Object profile(ProceedingJoinPoint pjp) throws Throwable
                      {
                         ..........
                      }
                  and with following entries in applicationContext xml.

                  Code:
                  	<context:spring-configured/>	
                  	<aop:aspectj-autoproxy proxy-target-class="true" />
                  	<bean id="logInterceptor" class="com.xx.yy.util.audit.LoggingInterceptor" >
                  	</bean>	
                  	
                  	<context:component-scan base-package="com.xx.yy">
                  	</context:component-scan>
                  As of now am using Spring 3.0.0.M3 and aspect J version 1.6.3.RELEASE

                  Comment


                  • #10
                    If I use the @Component annotation I get a BeanCurrentlyInCreationException.
                    Last edited by ferranmc; Jul 15th, 2011, 12:15 PM.

                    Comment


                    • #11
                      This worked for me, thank you for posting your solution! I was stuck on the same problem for hours. In particular, I think it was the <context:spring-configured/> that made the difference. Without this, I noticed that the Aspect class does not get instantiated until the pointcut occurs, and therefore Spring was not able to inject the Autowired dependencies. But with the spring-configured tag in place, it gets instantiated in the beginning and the dependencies get injected properly.

                      Comment


                      • #12
                        Same Configurations not working for me

                        I am not able to @Autowire the Service Layer Instance in Aspect. In Aspect the reference to the Autowired bean is NULL and it throws NullPointerException. Any help will be much appreciated. I think, I messed up with configuration.

                        Following is my servlet-context.xml:

                        Code:
                         
                        	<!-- Activates various annotations to be detected in bean classes -->
                        	<context:annotation-config />
                        	<context:spring-configured />		
                        		
                        	<!-- Scans the classpath of this application for @Components to deploy as beans -->
                        	<context:component-scan base-package="xx.yy" />
                        	
                        	<!--  an @AspectJ aspect will be interpreted as an aspect by Spring AOP and beans in the context will be advised accordingly -->
                        	<aop:aspectj-autoproxy />
                        	
                        	<beans:bean id="loggingAspect" class="xx.yy.aop.aspects.LoggingAspect" />
                        	<beans:bean id="authenticationAspect" class="xx.yy.aop.aspects.AuthenticationAspect" />
                        	
                        	<!-- Enables the Spring MVC @Controller programming model -->
                        	<annotation-driven />
                        Following is my Aspect:

                        Code:
                        @Configurable
                        @Component
                        @Aspect
                        public class AuthenticationAspect {
                        	private static final Logger logger = LoggerFactory.getLogger(AuthenticationAspect.class);
                        	
                        	@Autowired
                        	private LoginService loginService;
                        	
                                //.... 
                        }
                        Here is my controller using the @Authentication Annotation defined above:

                        Code:
                        @Controller
                        @RequestMapping("/user")
                        public class UsersController {
                        	
                        	@Autowired
                        	private UserService userService;
                        	
                        	@Authenticate
                        	@RequestMapping(value="/{userId}/profile", method=RequestMethod.GET)	
                        	public String displayUser(WebRequest webRequest, @PathVariable("userId") String userId, Model model) {
                        		User user = userService.findUser(Long.valueOf(userId));  
                        		model.addAttribute("user", user);
                        		model.addAttribute("AccordionMenuTab","5");
                        		model.addAttribute("selectedLink","profile");
                        		return "profile";
                        	}
                        I am getting following exception:

                        Code:
                        Oct 8, 2011 3:12:48 AM org.apache.catalina.core.StandardWrapperValve invoke
                        SEVERE: Servlet.service() for servlet appServlet threw exception
                        java.lang.NullPointerException
                        	at xx.yy.controller.UsersController.displayUser_aroundBody1$advice(UsersController.java:28)
                        	at xx.yy.controller.UsersController.displayUser(UsersController.java:1)
                        	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
                        	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
                        	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
                        	at java.lang.reflect.Method.invoke(Method.java:597)
                        	at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.invokeHandlerMethod(HandlerMethodInvoker.java:176)
                        	at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.java:426)
                        	at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(AnnotationMethodHandlerAdapter.java:414)
                        	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:790)
                        	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:719)
                        	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:644)
                        	at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:549)
                        	at javax.servlet.http.HttpServlet.service(HttpServlet.java:617)
                        	at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
                        	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
                        	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
                        	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
                        	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
                        	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
                        	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
                        	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
                        	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298)
                        	at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:859)
                        	at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:588)
                        	at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
                        	at java.lang.Thread.run(Thread.java:662)

                        Comment

                        Working...
                        X