Index: quartz/src/main/java/org/quartz/core/QuartzScheduler.java =================================================================== --- quartz/src/main/java/org/quartz/core/QuartzScheduler.java (revision 1676) +++ quartz/src/main/java/org/quartz/core/QuartzScheduler.java (working copy) @@ -831,7 +831,7 @@ resources.getJobStore().storeJobAndTrigger(jobDetail, trig); notifySchedulerListenersJobAdded(jobDetail); - notifySchedulerThread(trigger.getNextFireTime().getTime()); + notifySchedulerThreadViaJobStore(trigger.getNextFireTime().getTime()); notifySchedulerListenersSchduled(trigger); return ft; @@ -1757,6 +1757,12 @@ } } + private void notifySchedulerThreadViaJobStore(long candidateNewNextFireTime) { + if (isSignalOnSchedulingChange()) { + resources.getJobStore().signalSchedulingChange(candidateNewNextFireTime); + } + } + private List buildTriggerListenerList() throws SchedulerException { List allListeners = new LinkedList(); Index: quartz/src/main/java/org/quartz/impl/jdbcjobstore/JobStoreCMT.java =================================================================== --- quartz/src/main/java/org/quartz/impl/jdbcjobstore/JobStoreCMT.java (revision 1676) +++ quartz/src/main/java/org/quartz/impl/jdbcjobstore/JobStoreCMT.java (working copy) @@ -27,6 +27,10 @@ import org.quartz.spi.SchedulerSignaler; import org.quartz.utils.DBConnectionManager; +import javax.naming.InitialContext; +import javax.naming.NamingException; +import javax.transaction.*; + /** *

* JobStoreCMT is meant to be used in an application-server @@ -39,7 +43,14 @@ * org.quartz.impl.jdbcjobstore.JobStoreTX} * instead. *

- * + * + *

+ * By default, this class looks for the {@link javax.transaction.TransactionSynchronizationRegistry} + * in JNDI under name "java:TransactionSynchronizationRegistry". If this is not where your Application Server + * registers it, you can modify the JNDI lookup location using the + * "org.quartz.jobStore.transactionSynchronizationRegistryJNDIName" property. + *

+ * * @author Jeffrey Wescott * @author James House * @author Srinivas Venkatarangaiah @@ -62,14 +73,16 @@ protected boolean setTxIsolationLevelReadCommitted = false; - + private TransactionSynchronizationRegistry transactionSynchronizationRegistry; + private String transactionSynchronizationRegistryJNDIName = "java:TransactionSynchronizationRegistry"; + /* - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * Interface. - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - */ + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * Interface. + * + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + */ /** *

@@ -119,8 +132,15 @@ public void setTxIsolationLevelReadCommitted(boolean b) { setTxIsolationLevelReadCommitted = b; } - + /** + * Set the JNDI location of TransactionSynchronizationRegistry object + * @param transactionSynchronizationRegistryJNDIName + */ + public void setTransactionSynchronizationRegistryJNDIName(String transactionSynchronizationRegistryJNDIName) { + this.transactionSynchronizationRegistryJNDIName = transactionSynchronizationRegistryJNDIName; + } + @Override public void initialize(ClassLoadHelper loadHelper, SchedulerSignaler signaler) throws SchedulerConfigException { @@ -140,6 +160,23 @@ setUseDBLocks(true); } + InitialContext ic = null; + try { + ic = new InitialContext(); + transactionSynchronizationRegistry = (TransactionSynchronizationRegistry) ic.lookup(transactionSynchronizationRegistryJNDIName); + } + catch (NamingException e) { + getLog().warn("Failed to find TransactionSynchronizationRegistry in JNDI under name: " + transactionSynchronizationRegistryJNDIName); + } + finally { + if (ic != null) { + try { + ic.close(); + } catch (NamingException ignored) { + } + } + } + super.initialize(loadHelper, signaler); getLog().info("JobStoreCMT initialized."); @@ -251,6 +288,24 @@ } } } + + @Override + public void signalSchedulingChange(final long candidateNewNextFireTime) { + if (transactionSynchronizationRegistry == null) { + super.signalSchedulingChange(candidateNewNextFireTime); + } else { + transactionSynchronizationRegistry.registerInterposedSynchronization(new Synchronization() { + public void beforeCompletion() { + } + + public void afterCompletion(int i) { + if (Status.STATUS_COMMITTED == i) { + JobStoreCMT.super.signalSchedulingChange(candidateNewNextFireTime); + } + } + }); + } + } } // EOF Index: quartz/src/main/java/org/quartz/impl/jdbcjobstore/JobStoreSupport.java =================================================================== --- quartz/src/main/java/org/quartz/impl/jdbcjobstore/JobStoreSupport.java (revision 1676) +++ quartz/src/main/java/org/quartz/impl/jdbcjobstore/JobStoreSupport.java (working copy) @@ -268,8 +268,12 @@ public void setThreadPoolSize(final int poolSize) { // } - - public void setThreadExecutor(ThreadExecutor threadExecutor) { + + public void signalSchedulingChange(long candidateNewNextFireTime) { + schedSignaler.signalSchedulingChange(candidateNewNextFireTime); + } + + public void setThreadExecutor(ThreadExecutor threadExecutor) { this.threadExecutor = threadExecutor; } @@ -604,7 +608,7 @@ boolean doubleCheckLockMisfireHandler) { this.doubleCheckLockMisfireHandler = doubleCheckLockMisfireHandler; } - + //--------------------------------------------------------------------------- // interface methods //--------------------------------------------------------------------------- Index: quartz/src/main/java/org/quartz/simpl/RAMJobStore.java =================================================================== --- quartz/src/main/java/org/quartz/simpl/RAMJobStore.java (revision 1676) +++ quartz/src/main/java/org/quartz/simpl/RAMJobStore.java (working copy) @@ -1704,7 +1704,11 @@ // } - public long getEstimatedTimeToReleaseAndAcquireTrigger() { + public void signalSchedulingChange(long candidateNewNextFireTime) { + signaler.signalSchedulingChange(candidateNewNextFireTime); + } + + public long getEstimatedTimeToReleaseAndAcquireTrigger() { return 5; } Index: quartz/src/main/java/org/quartz/spi/JobStore.java =================================================================== --- quartz/src/main/java/org/quartz/spi/JobStore.java (revision 1676) +++ quartz/src/main/java/org/quartz/spi/JobStore.java (working copy) @@ -636,4 +636,10 @@ * @since 2.0 */ void setThreadPoolSize(int poolSize); + + /** + * + * @param candidateNewNextFireTime of trigger + */ + void signalSchedulingChange(long candidateNewNextFireTime); }