diff --git a/jbpm-services/jbpm-services-ejb/jbpm-services-ejb-timer/src/main/java/org/jbpm/services/ejb/timer/EJBTimerScheduler.java b/jbpm-services/jbpm-services-ejb/jbpm-services-ejb-timer/src/main/java/org/jbpm/services/ejb/timer/EJBTimerScheduler.java index 10f7da7613..3a563c3e64 100644 --- a/jbpm-services/jbpm-services-ejb/jbpm-services-ejb-timer/src/main/java/org/jbpm/services/ejb/timer/EJBTimerScheduler.java +++ b/jbpm-services/jbpm-services-ejb/jbpm-services-ejb-timer/src/main/java/org/jbpm/services/ejb/timer/EJBTimerScheduler.java @@ -26,6 +26,7 @@ import java.time.ZonedDateTime; import java.time.temporal.ChronoUnit; import java.util.Date; +import java.util.List; import java.util.concurrent.Callable; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; @@ -45,13 +46,20 @@ import javax.ejb.TimerHandle; import javax.ejb.TransactionManagement; import javax.ejb.TransactionManagementType; +import javax.persistence.EntityManager; +import javax.persistence.EntityManagerFactory; import javax.transaction.RollbackException; +import javax.transaction.Transactional; +import javax.transaction.Transactional.TxType; import javax.transaction.UserTransaction; import org.drools.core.time.JobHandle; import org.drools.core.time.impl.TimerJobInstance; import org.jbpm.persistence.timer.GlobalJpaTimerJobInstance; import org.jbpm.process.core.timer.TimerServiceRegistry; +import org.jbpm.runtime.manager.impl.jpa.EntityManagerFactoryManager; +import org.jbpm.runtime.manager.impl.jpa.TimerMappingInfo; +import org.kie.internal.runtime.manager.InternalRuntimeManager; import org.kie.internal.runtime.manager.SessionNotFoundException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -389,6 +397,37 @@ public TimerJobInstance getTimerByName(String jobName) { return found; } + @Transactional(value = TxType.REQUIRES_NEW) + public Timer getEjbTimer(InternalRuntimeManager manager, String uuid) { + try { + TimerMappingInfo timerMappingInfo = getTimerMappinInfo(manager, uuid); + if(timerMappingInfo == null || timerMappingInfo.getInfo() == null) { + return null; + } + byte[] data = timerMappingInfo.getInfo(); + return ((TimerHandle) new ObjectInputStream(new ByteArrayInputStream(data)).readObject()).getTimer(); + } catch (Exception e) { + logger.warn("wast not able to deserialize info field from timer info for uuid: {}", uuid); + return null; + } + } + + private TimerMappingInfo getTimerMappinInfo(InternalRuntimeManager manager, String uuid) { + String pu = ((InternalRuntimeManager) manager).getDeploymentDescriptor().getPersistenceUnit(); + EntityManagerFactory emf = EntityManagerFactoryManager.get().getOrCreate(pu); + EntityManager em = emf.createEntityManager(); + try { + List info = em.createQuery("SELECT o FROM TimerMappingInfo o WHERE o.uuid = :uuid", TimerMappingInfo.class).setParameter("uuid", uuid).getResultList(); + if (!info.isEmpty()) { + return info.get(0); + } else { + return null; + } + } finally { + em.close(); + } + } + public void evictCache(JobHandle jobHandle) { String jobName = ((EjbGlobalJobHandle) jobHandle).getUuid(); logger.debug("Invalidate job {} with job name {} in cache", jobName, localCache.remove(jobName)); diff --git a/jbpm-services/jbpm-services-ejb/jbpm-services-ejb-timer/src/main/java/org/jbpm/services/ejb/timer/EjbSchedulerService.java b/jbpm-services/jbpm-services-ejb/jbpm-services-ejb-timer/src/main/java/org/jbpm/services/ejb/timer/EjbSchedulerService.java index 1bad1ae27b..2b03eda13a 100644 --- a/jbpm-services/jbpm-services-ejb/jbpm-services-ejb-timer/src/main/java/org/jbpm/services/ejb/timer/EjbSchedulerService.java +++ b/jbpm-services/jbpm-services-ejb/jbpm-services-ejb-timer/src/main/java/org/jbpm/services/ejb/timer/EjbSchedulerService.java @@ -101,12 +101,17 @@ public JobHandle scheduleJob(Job job, JobContext ctx, Trigger trigger) { @Override public boolean removeJob(JobHandle jobHandle) { String uuid = ((EjbGlobalJobHandle) jobHandle).getUuid(); - final Timer ejbTimer = getEjbTimer(getTimerMappinInfo(uuid)); + InternalRuntimeManager manager = ((GlobalTimerService) globalTimerService).getRuntimeManager(); + final Timer ejbTimer = scheduler.getEjbTimer(manager, uuid); if (TRANSACTIONAL && ejbTimer == null) { // this situation needs to be avoided as it should not happen + logger.debug("ejbTimer not found for {} and tx. This should not be possible.", jobHandle); return false; } + JtaTransactionManager tm = (JtaTransactionManager) TransactionManagerFactory.get().newTransactionManager(); + logger.debug("Found ejbTimer in TimerMappingInfo {}, removing it. tx status is {}", ejbTimer, tm.getStatus()); + try { tm.registerTransactionSynchronization(new TransactionSynchronization() { @Override @@ -197,6 +202,7 @@ private TimerJobInstance unwrapTimerJobInstance(Timer timer) { } } + @Override public void invalidate(JobHandle jobHandle) { scheduler.evictCache(jobHandle);