ThreadLocalAwareBackgroundTaskExecutor extends DelegatingBackgroundTaskExecutor { @Override public BackgroundTaskResult execute(BackgroundTask backgroundTask) throws Exception { Map<String, Serializable> threadLocalValues = _backgroundTaskThreadLocalManager.getThreadLocalValues(); try { try { _backgroundTaskThreadLocalManager.deserializeThreadLocals( backgroundTask.getTaskContextMap()); } catch (StaleBackgroundTaskException staleBackgroundTaskException) { if (_log.isInfoEnabled()) { _log.info( "Skipped stale background task " + backgroundTask, staleBackgroundTaskException); } return BackgroundTaskResult.SUCCESS; } return super.execute(backgroundTask); } finally { _backgroundTaskThreadLocalManager.setThreadLocalValues( threadLocalValues); } } ThreadLocalAwareBackgroundTaskExecutor(
		BackgroundTaskExecutor backgroundTaskExecutor,
		BackgroundTaskThreadLocalManager backgroundTaskThreadLocalManager); @Override BackgroundTaskExecutor clone(); @Override BackgroundTaskResult execute(BackgroundTask backgroundTask);  }
@Test public void testStaleBackgroundTaskIsSkipped() throws Exception { CompanyLocalService companyLocalService = Mockito.mock( CompanyLocalService.class); Mockito.when( companyLocalService.fetchCompany(Mockito.anyLong()) ).thenReturn( null ); backgroundTaskThreadLocalManagerImpl.companyLocalService = companyLocalService; BackgroundTaskExecutor backgroundTaskExecutor = Mockito.mock( BackgroundTaskExecutor.class); ThreadLocalAwareBackgroundTaskExecutor threadLocalAwareBackgroundTaskExecutor = new ThreadLocalAwareBackgroundTaskExecutor( backgroundTaskExecutor, backgroundTaskThreadLocalManagerImpl); BackgroundTask backgroundTask = Mockito.mock(BackgroundTask.class); Mockito.when( backgroundTask.getTaskContextMap() ).thenReturn( Collections.singletonMap( BackgroundTaskThreadLocalManagerImpl.KEY_THREAD_LOCAL_VALUES, (Serializable)new HashMap<>( Collections.singletonMap("companyId", 1))) ); BackgroundTaskResult backgroundTaskResult = threadLocalAwareBackgroundTaskExecutor.execute(backgroundTask); Assert.assertTrue(backgroundTaskResult.isSuccessful()); Mockito.verifyZeroInteractions(backgroundTaskExecutor); }