Currently, My AuditorAware
Implementation uses Spring's SecurityContextHolder
to retrieve the current Auditor for saving creation/modification usernames:
@Service
public class AuditorAwareImpl implements AuditorAware<UserDetails> {
private final UserDetailsService userDetailsService;
@Autowired
public AuditorAwareImpl(UserDetailsService userDetailsService){
this.userDetailsService = userDetailsService;
}
@Override
public UserDetails getCurrentAuditor() {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
return userDetailsService.loadUserByUsername(authentication.getName());
}
}
This works fine for most operations except for asynchronous tasks executed by Spring batch's SimpleAsyncTaskExecutor
.
By the time entities need saving, since the SecurityContextHolder
is wiped after the request has been processed, and the jobLauncher.run(...)
returns asynchrnously, the AuditorAwareImpl.getCurrentAuditor()
method throws a NullPointerException
due to a null getAuthentication()
:
java.lang.NullPointerException: null
at com.example.services.AuditorAwareImpl.getCurrentAuditor(AuditorAwareImpl.java:31)
at com.example.services.AuditorAwareImpl.getCurrentAuditor(AuditorAwareImpl.java:18)
So far I have included the request-invoking user as a non-identifying parameter to the Job but don't know where to proceed from here.
What is a recommended way of leveraging spring's inbuilt auditing when the SecurityContextHolder
is not appropriate for finding the invoking "auditor"?