1

I have the following code:

package com.cooldomain.coolapp.application.rest.session;

import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class SessionAspect
{
    @Autowired
    private HttpServletRequest request;

    @Autowired
    private SessionService sessionService;

    @PostConstruct
    public void init()
    {
        /*
        * XXX Note: On application startup this piece of code prints the right values and I can see that they have been autowired correctly:
        * ------------------------------------------------------------------------------------------------
        * request: Current HttpServletRequest
        * sessionService: com.cooldomain.coolapp.application.rest.session.SessionService@3700511f
        * ------------------------------------------------------------------------------------------------
        */
        System.out.println("request: " + request);
        System.out.println("sessionService: " + sessionService);
    }

    @Around("@annotation(com.cooldomain.coolapp.application.rest.session.SessionRequired) && within(com.cooldomain.coolapp.application..*)")
    public Object proceedWithValidSession(ProceedingJoinPoint joinPoint) throws Throwable
    {
        /*
        * XXX Note: But when I make a request to the annotated with @SessionRequired method i get the following output and hence a nullpointer exception afterwards:
        * ------------------------------------------------------------------------------------------------
        * request: null
        * sessionService: null
        * ------------------------------------------------------------------------------------------------
        */
        System.out.println("request: " + request);
        System.out.println("sessionService: " + sessionService);

        return setSessionAsFirstArgument(joinPoint);
    }

    private Object setSessionAsFirstArgument(ProceedingJoinPoint joinPoint) throws Throwable
    {
        Object[] args = joinPoint.getArgs();
        args[0] = sessionService.getSession(request);

        return joinPoint.proceed(args);
    }
}

So the problem is that when I start the application everything gets autowired correctly, but when I make a request to the annotated method, which refernces the aspect, the autowired fields magically get set to null. I am not sure if spring uses this bean or is trying to create another one...

Note: this piece of code exists in two other projects and it's absolutley the same (copy/pasted) and there it works perfectly, but here it breaks...I am using spring version 4.1.5 and aspectjrt 1.8.5 like in the two other projects.

I've done the following workaround, which WORKS, but it's ugly and I want to remove it:

package com.cooldomain.coolapp.application.rest.session;

import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class SessionAspect
{
    @Autowired
    private HttpServletRequest request;

    @Autowired
    private SessionService sessionService;

    // WORKAROUND
    private static SessionAspect sessionAspect;

    @PostConstruct
    public void init()
    {
        /*
         * Note: On application startup this piece of code prints the right values and I can see that they have been autowired correctly:
         * ------------------------------------------------------------------------------------------------
         * request: Current HttpServletRequest
         * sessionService: com.cooldomain.coolapp.application.rest.session.SessionService@3700511f
         * ------------------------------------------------------------------------------------------------
         */
        System.out.println("request: " + request);
        System.out.println("sessionService: " + sessionService);

        // WORKAROUND
        sessionAspect = this;
    }

    @Around("@annotation(com.cooldomain.coolapp.application.rest.session.SessionRequired) && within(com.cooldomain.coolapp.application..*)")
    public Object proceedWithValidSession(ProceedingJoinPoint joinPoint) throws Throwable
    {
        /*
         * XXX Note: But when I make a request to the annotated with @SessionRequired method i get the following output and hence a nullpointer exception afterwards:
         * ------------------------------------------------------------------------------------------------
         * request: null
         * sessionService: null
         * ------------------------------------------------------------------------------------------------
         */
        System.out.println("request: " + request);
        System.out.println("sessionService: " + sessionService);

        // WORKAROUND
        return sessionAspect.setSessionAsFirstArgument(joinPoint);
    }

    private Object setSessionAsFirstArgument(ProceedingJoinPoint joinPoint) throws Throwable
    {
        Object[] args = joinPoint.getArgs();
        args[0] = sessionService.getSession(request);

        return joinPoint.proceed(args);
    }
}

Does someone have any idea how to fix this?

Artem Bilan
  • 113,505
  • 11
  • 91
  • 118
Mr. Smith
  • 53
  • 3

2 Answers2

0

.OK so it turns out that Spring is not to blame and it only creates one bean. I saw the project xml and there's a plugin aspectj-maven-plugin (aspectj-maven-plugin) that creates another instance of the class outside spring context and @Aspect uses this instance - not the spring one Will look for soltion in the net if can make only spring bean, without removing the plugin...perhaps there is an exclude option in the configuration

Mr. Smith
  • 53
  • 3
  • You do not need AspectJ Maven plugin for Spring AOP, only Spring configuration. Only if you want to use the full power of AspectJ (with or without Spring) via load-time or compile-time weaving you need the plugin. – kriegaex Jul 02 '16 at 08:31
0

I dont know why you are not using joinPoint.proceed(); in your around advice. It is essential to make around advice to work.

@Around("@annotation(com.cooldomain.coolapp.application.rest.session.SessionRequired) && within(com.cooldomain.coolapp.application..*)")
    public Object proceedWithValidSession(ProceedingJoinPoint joinPoint) throws Throwable
    {
//your code

//solution
joinPoint.proceed(); 
    }

Please try this, and say what is happening.

user2929
  • 21
  • 6