#jpa #cdi #entitymanager #java-ee-8
#jpa #cdi #entitymanager #java-ee-8
Вопрос:
Я пытаюсь разработать класс, который выполняется с определенными интервалами и выполняет некоторые модификации БД.
код, который мне удалось запустить с определенным интервалом, извлекает записи из БД, но когда я хочу зафиксировать изменения в БД, я получаю следующую ошибку.
WFLYEE0110: Failed to run scheduled task: javax.persistence.TransactionRequiredException: WFLYJPA0060: Transaction is required to perform this operation (either use a transaction or extended persistence context)
разрешено ли @ApplicationScoped создавать транзакции?
Спасибо!
@ApplicationScoped
@ActivateRequestContext
public class TaskRunner {
@PersistenceContext(type = PersistenceContextType.EXTENDED)
EntityManager em;
@Resource private ManagedScheduledExecutorService scheduler;
private ScheduledFuture<?> TaskRunnerScheduler;
private boolean initialized = false;
private void init(@Observes @Initialized(ApplicationScoped.class) Object init) {
if (initialized) return;
initialized = true;
try {
// Execute at startup
TaskRunner = scheduler.schedule(this::runSchedule, getSchedule());
} catch (Throwable throwable) {
}
}
@Transactional
private void runSchedule() {
//retrieve db records
//make changes and commit
//sample
//em.persist(someEntity)
}
private Trigger getSchedule() {
return new Trigger() {
@Override
public Date getNextRunTime(LastExecution lastExecutionInfo, Date taskScheduledTime) {
return Date.from(
ZonedDateTime.now().withSecond(0).withNano(0).plusHours("4").toInstant());
}
@Override
public boolean skipRun(LastExecution lastExecutionInfo, Date scheduledRunTime)
{return false;}};
}
}
Ответ №1:
Транзакции запускаются с помощью перехватчиков. Когда вы вызываете метод компонента изнутри этого компонента, вызов метода не перехватывается, и транзакция не может быть запущена.
Вам нужен другой компонент и сохраняться там
@RequestScoped
@Transactional(value = TxType.REQUIRES_NEW)
public class SomeOtherBean{
@PersistenceContext(type = PersistenceContextType.EXTENDED)
EntityManager em;
public void doSomething(){
//retrieve db records
//make changes and commit
//sample
//em.persist(someEntity)
}
}
затем вы можете внедрить этот компонент в свой TaskRunner
@ApplicationScoped
@ActivateRequestContext
public class TaskRunner {
@Inject
SomeOtherBean someBean;
...
private void runSchedule() {
someBean.doSomething()
}
}
Комментарии:
1. Я внес изменения, но получаю новую ошибку. Не удалось запустить запланированную задачу: org.jboss.weld.contexts. ContextNotActiveException: WELD-001303: нет активных контекстов для области видимости типа javax.enterprise.context.RequestScoped
2. Затем, пожалуйста, попробуйте изменить область видимости на @Dependent