Question

There are 3 classes in my Spring MVC app: a UserDetailsInterceptor class, an MyAdvice class and a UserDetails class (session scoped).

What I want to accomplish is simple:

  1. UserDetailsInterceptor intercepts requests and set user's id in a session scoped UserDetails bean.
  2. Later on, when the method in AOP advice class is called, retrieve user's id from the session scoped UserDetails bean.

Problem (also marked in the code below):

  1. UserDetails object is null in MyAdvice class.
  2. In UserDetailsInterceptor, userDetails.setUserID(request.getRemoteUser()); does nothing.

Code:

UserDetailsInterceptor class:

public class UserDetailsInterceptor extends HandlerInterceptorAdapter {

    @Autowired
    private UserDetails userDetails;

    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //set user ID, but next line doesn't do anything for some reason (e.g. `userID` is still null)
        userDetails.setUserID(request.getRemoteUser());
        return true;
    }
}

MyAdvice class:

public class MyAdvice implements MethodInterceptor {

    @Autowired
    private UserDetails userDetails; //It's null

    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        //Print user ID
        System.out.println(userDetails.getID());
        return invocation.proceed();
    }
}

UserDetails class:

public class UserDetails {

    private String userID;

    public void setUserID(String userID) {
        this.userID= userID;
    }

    public String getUserID() {
        return this.userID;
    }
}

In dispatcher-servlet.xml:

<bean id="userDetails " class="package.UserDetails " scope="session">
    <aop:scoped-proxy/>
</bean>

MyPointcutAdvisor class:

public class MyPointcutAdvisor implements PointcutAdvisor {

    private MyPointcut pointcut = new MyPointcut();
    private MyAdvice advice = new MyAdvice();

    @Override
    public Pointcut getPointcut() {
        return this.pointcut;
    }

    @Override
    public Advice getAdvice() {
        return this.advice;
    }

    @Override
    public boolean isPerInstance() {
        return false;
    }
}

Any ideas please? Thanks in advance.

Update:

By registering MyAdvice class, userDetails object in it is no longer null. However it is not the same object as the one in UserDetailsInterceptor. So the bean is not actually "session scoped"?

Answer:

The problem lies in following code:

private MyPointcut pointcut = new MyPointcut();
private MyAdvice advice = new MyAdvice();

Neither of them are managed by spring. As a result, things are being wired and not working the way we expected.

Was it helpful?

Solution

This

UserDetails object is null in MyAdvice class.

is not possible if the MyAdvice instance is managed by Spring. You must be instantiating it yourself instead of getting it from the context.

If Spring doesn't manage the object, it can't inject anything into @Autowired targets, so your field remains null.

If Spring was managing your object, a bean, and couldn't resolve the dependency, it would throw exceptions.

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