Friday, December 2, 2011

Adding user data to a timer thread

I had the quite usual requirement to add user info to a timer.
Some code was retrieving user date from the request scope in order to log the data with each change in the database.
Unfortunately, the timer has no request scope associated with it. And of course no user object attached to the request scope.

With Spring you can user the RunAs mechanism to add rights to a user. This is exactly what I did.

1. First I use the thread scope found www.springbyexample.org/examples/custom-thread-scope-module.html which I configure as
  
      
          
              
                  
              
          
      
  


Now the authentication itself gets configured:
    
    
        
        
    


The third element of configuration is the proxy configuration after the timer.
    
        
        
        
            
                threadScopeAfterAdvice
                threadAuthenticationInterceptor
            
        
    


the threadScopeAfterAdvice only cleans the scope after the thread execution is done.

the threadAuthenticationInterceptor is a org.aopalliance.intercept.MethodInterceptor

public Object invoke(MethodInvocation invocation) throws Throwable {
        UserDetails userDetail = userDetailService.loadUserByUsername(userId);
        RunAsUserToken runAsUserToken = new RunAsUserToken("mykey", userDetail, USER_CREDENTIALS,
                userDetail.getAuthorities(), null);

        Authentication authentication = authenticationManager.authenticate(runAsUserToken);
        if (authentication.isAuthenticated()) {
            SecurityContext sc = new SecurityContextImpl();
            sc.setAuthentication(authentication);
            SecurityContextHolder.setContext(sc);
        }

        try {
            return invocation.proceed();
        } finally {
            SecurityContextHolder.clearContext();

        }
    }