Вы можете использовать applicationContext
в вашем обработчике для поиска notificationService
.У меня была та же проблема, когда я использовал @Autowired
для обработчика, который, в свою очередь, ввел мой LogService
.Посмотрев журналы, я увидел, что TransactionSynchronizationManager
очищает синхронизацию транзакций после отката исключения и ничего кроме ошибки no transaction for ......
.
После использования applicationContext
для поиска logService
bean и меняя свой обработчик, я увидел желаемый результат в логах.
- begin
- Инициализация синхронизации транзакций
- Получение транзакции для [.... AsyncService.doAsync]
- Исключение
- откат
Очистка синхронизации транзакций
начало
- Инициализация синхронизации транзакций
- Получение транзакции для [..... LogService.save]
Измените конфигурацию, включив в нее интерфейс ApplicationContextAware
, который предоставит вам удобный способ доступа к applicationContext
.Установите его как переменную экземпляра.
См. Мой класс конфигурации ниже.
@Configuration
@EnableAsync
public class AsyncConfig implements AsyncConfigurer, ApplicationContextAware {
private static final int CORE_POOL_SIZE = 3;
private static final int MAX_POOL_SIZE = 3;
private static final int QUEUE_CAPACITY = 24;
private static final String THREAD_NAME_PREFIX = "AsynchThread-";
private ApplicationContext applicationContext;
@Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(CORE_POOL_SIZE);
executor.setMaxPoolSize(MAX_POOL_SIZE);
executor.setQueueCapacity(QUEUE_CAPACITY);
executor.setThreadNamePrefix(THREAD_NAME_PREFIX);
executor.initialize();
return executor;
}
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return new AsyncExceptionHandler(this.applicationContext);
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
}
Я удалил @Component
из обработчика и использую его как POJO.Каждый раз, когда getAsyncUncaughtExceptionHandler
вызывается с исключением, создается новый экземпляр обработчика с applicationContext
в качестве зависимости.
public class AsyncExceptionHandler implements AsyncUncaughtExceptionHandler {
private final ApplicationContext applicationContext;
public AsyncExceptionHandler(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
@Override
public void handleUncaughtException(Throwable ex, Method method, Object... params) {
Log log = new Log();
log.setEntry(ex.getMessage());
LogService logService = this.applicationContext.getBean(LogService.class);
logService.save(log);
}
}
Метод save
в logService
требует новой транзакции при каждом вызове.
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void save(Log log)