From aab59d0f39f6165a23b58673769b63148164d7f2 Mon Sep 17 00:00:00 2001 From: lahma Date: Thu, 31 Jul 2008 10:49:48 +0000 Subject: [PATCH] Syncing with Java Spring integration, polishing --- .../JobMethodInvocationFailedException.cs | 46 +++++++++++++++++++ .../Scheduling/Quartz/CronTriggerObject.cs | 6 +-- .../Scheduling/Quartz/DelegatingJob.cs | 22 +++------ .../Scheduling/Quartz/MethodInvokingJob.cs | 11 +++-- .../Quartz/SchedulerFactoryObject.cs | 45 ++++++++++-------- .../Spring.Scheduling.Quartz.2003.csproj | 5 ++ .../Spring.Scheduling.Quartz.2005.csproj | 1 + .../Quartz/SchedulerFactoryObjectTest.cs | 5 +- 8 files changed, 91 insertions(+), 50 deletions(-) create mode 100644 src/Spring/Spring.Scheduling.Quartz/JobMethodInvocationFailedException.cs diff --git a/src/Spring/Spring.Scheduling.Quartz/JobMethodInvocationFailedException.cs b/src/Spring/Spring.Scheduling.Quartz/JobMethodInvocationFailedException.cs new file mode 100644 index 00000000..3e869e43 --- /dev/null +++ b/src/Spring/Spring.Scheduling.Quartz/JobMethodInvocationFailedException.cs @@ -0,0 +1,46 @@ +/* + * Copyright 2002-2008 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +using System; + +using Spring.Objects.Support; + +namespace Spring.Scheduling.Quartz +{ + /// + /// Exception that wraps an exception thrown from a target method. + /// Propagated to the Quartz scheduler from a Job that reflectively invokes + /// an arbitrary target method. + /// + /// Juergen Hoeller + /// + public class JobMethodInvocationFailedException : Exception // TODO, in Java NestedRuntimeException + { + /// + /// Constructor for JobMethodInvocationFailedException. + /// + /// the MethodInvoker used for reflective invocation + /// the root cause (as thrown from the target method) + public JobMethodInvocationFailedException(MethodInvoker methodInvoker, Exception cause) : + base("Invocation of method '" + methodInvoker.TargetMethod + + "' on target class [" + methodInvoker.TargetType + "] failed", cause) + { + + } + + } +} + diff --git a/src/Spring/Spring.Scheduling.Quartz/Scheduling/Quartz/CronTriggerObject.cs b/src/Spring/Spring.Scheduling.Quartz/Scheduling/Quartz/CronTriggerObject.cs index c29ffd71..9bff8c7e 100644 --- a/src/Spring/Spring.Scheduling.Quartz/Scheduling/Quartz/CronTriggerObject.cs +++ b/src/Spring/Spring.Scheduling.Quartz/Scheduling/Quartz/CronTriggerObject.cs @@ -56,7 +56,6 @@ namespace Spring.Scheduling.Quartz private string objectName; private readonly Constants constants = new Constants(typeof(MisfireInstruction.CronTrigger), typeof(MisfireInstruction)); - /// /// Register objects in the JobDataMap via a given Map. /// @@ -80,10 +79,7 @@ namespace Spring.Scheduling.Quartz /// public virtual string MisfireInstructionName { - set - { - MisfireInstruction = constants.AsNumber(value); - } + set { MisfireInstruction = constants.AsNumber(value); } } /// diff --git a/src/Spring/Spring.Scheduling.Quartz/Scheduling/Quartz/DelegatingJob.cs b/src/Spring/Spring.Scheduling.Quartz/Scheduling/Quartz/DelegatingJob.cs index afd67c1e..c5708054 100644 --- a/src/Spring/Spring.Scheduling.Quartz/Scheduling/Quartz/DelegatingJob.cs +++ b/src/Spring/Spring.Scheduling.Quartz/Scheduling/Quartz/DelegatingJob.cs @@ -18,6 +18,8 @@ using System.Threading; using Quartz; +using Spring.Util; + namespace Spring.Scheduling.Quartz { /// @@ -35,7 +37,7 @@ namespace Spring.Scheduling.Quartz /// public class DelegatingJob : IJob { - private ThreadStart delegateInstance; + private readonly ThreadStart delegateInstance; /// /// Return the wrapped Runnable implementation. @@ -54,29 +56,17 @@ namespace Spring.Scheduling.Quartz /// public DelegatingJob(ThreadStart delegateInstance) { - if (delegateInstance == null) - { - throw new ArgumentException("Delegate must not be null", "delegateInstance"); - } + AssertUtils.ArgumentNotNull(delegateInstance, "delegateInstance", "Delegate must not be null"); this.delegateInstance = delegateInstance; } /// - /// Delegates execution to the underlying ThreadStart, - /// converting any Exception thrown to a Quartz JobExecutionException - /// (as required by the Job contract). + /// Delegates execution to the underlying ThreadStart. /// public virtual void Execute(JobExecutionContext context) { - try - { - delegateInstance.Invoke(); - } - catch (Exception ex) - { - throw new JobExecutionException(ex); - } + delegateInstance.Invoke(); } } } \ No newline at end of file diff --git a/src/Spring/Spring.Scheduling.Quartz/Scheduling/Quartz/MethodInvokingJob.cs b/src/Spring/Spring.Scheduling.Quartz/Scheduling/Quartz/MethodInvokingJob.cs index ba59c7c6..7a97176c 100644 --- a/src/Spring/Spring.Scheduling.Quartz/Scheduling/Quartz/MethodInvokingJob.cs +++ b/src/Spring/Spring.Scheduling.Quartz/Scheduling/Quartz/MethodInvokingJob.cs @@ -70,18 +70,19 @@ namespace Spring.Scheduling.Quartz } catch (TargetInvocationException ex) { - logger.Warn(errorMessage, ex.GetBaseException()); + logger.Error(errorMessage, ex.GetBaseException()); if (ex.GetBaseException() is JobExecutionException) { + // -> JobExecutionException, to be logged at info level by Quartz throw ex.GetBaseException(); } - throw new JobExecutionException(errorMessage, ex.GetBaseException()); - + // -> "unhandled exception", to be logged at error level by Quartz + throw new JobMethodInvocationFailedException(methodInvoker, ex.GetBaseException()); } catch (Exception ex) { - logger.Warn(errorMessage, ex); - throw new JobExecutionException(errorMessage, ex); + // -> "unhandled exception", to be logged at error level by Quartz + throw new JobMethodInvocationFailedException(methodInvoker, ex.GetBaseException()); } } } diff --git a/src/Spring/Spring.Scheduling.Quartz/Scheduling/Quartz/SchedulerFactoryObject.cs b/src/Spring/Spring.Scheduling.Quartz/Scheduling/Quartz/SchedulerFactoryObject.cs index 4044df54..4dd3e9e2 100644 --- a/src/Spring/Spring.Scheduling.Quartz/Scheduling/Quartz/SchedulerFactoryObject.cs +++ b/src/Spring/Spring.Scheduling.Quartz/Scheduling/Quartz/SchedulerFactoryObject.cs @@ -18,7 +18,6 @@ using System; using System.Collections; using System.Collections.Specialized; using System.IO; -using System.Threading; using Common.Logging; @@ -104,20 +103,21 @@ namespace Spring.Scheduling.Quartz private ITriggerListener[] globalTriggerListeners; private ArrayList jobDetails; private IJobFactory jobFactory; + private bool jobFactorySet; private IJobListener[] jobListeners; private string[] jobSchedulingDataLocations; - private bool overwriteExistingJobs = false; + private bool overwriteExistingJobs; private NameValueCollection quartzProperties; private IScheduler scheduler; private IDictionary schedulerContextMap; private Type schedulerFactoryType; private ISchedulerListener[] schedulerListeners; private string schedulerName; - private int startupDelay = 0; + private int startupDelay; private ITaskExecutor taskExecutor; private ITriggerListener[] triggerListeners; private ArrayList triggers; - private bool waitForJobsToCompleteOnShutdown = false; + private bool waitForJobsToCompleteOnShutdown; /// /// Initializes a new instance of the class. @@ -126,7 +126,6 @@ namespace Spring.Scheduling.Quartz { logger = LogManager.GetLogger(GetType()); schedulerFactoryType = typeof (StdSchedulerFactory); - jobFactory = new AdaptableJobFactory(); } @@ -265,20 +264,25 @@ namespace Spring.Scheduling.Quartz /// ///

/// Default is Spring's , which supports - /// standard Quartz instances. + /// standard Quartz instances. Note that this default only applies + /// to a local Scheduler, not to a RemoteScheduler (where setting + /// a custom JobFactory is not supported by Quartz). ///

///

/// Specify an instance of Spring's here - /// (typically as an inner object definition) to automatically populate a - /// job's object properties from the specified job data map and scheduler - /// context. + /// (typically as an inner object definition) to automatically populate a job's + /// object properties from the specified job data map and scheduler context. ///

///
/// /// public virtual IJobFactory JobFactory { - set { jobFactory = value; } + set + { + jobFactory = value; + jobFactorySet = true; + } } /// @@ -636,6 +640,15 @@ namespace Spring.Scheduling.Quartz // Get Scheduler instance from SchedulerFactory. scheduler = CreateScheduler(schedulerFactory, schedulerName); + PopulateSchedulerContext(); + + if (!jobFactorySet && !(scheduler is RemoteScheduler)) + { + // Use AdaptableJobFactory as default for a local Scheduler, unless when + // explicitly given a null value through the "jobFactory" bean property. + jobFactory = new AdaptableJobFactory(); + } + if (jobFactory != null) { if (jobFactory is ISchedulerContextAware) @@ -645,8 +658,6 @@ namespace Spring.Scheduling.Quartz scheduler.JobFactory = jobFactory; } - - PopulateSchedulerContext(); RegisterListeners(); RegisterJobsAndTriggers(); @@ -911,10 +922,7 @@ namespace Spring.Scheduling.Quartz scheduler.AddJob(jobDetail, true); return true; } - else - { - return false; - } + return false; } /// @@ -969,10 +977,7 @@ namespace Spring.Scheduling.Quartz } return true; } - else - { - return false; - } + return false; } diff --git a/src/Spring/Spring.Scheduling.Quartz/Spring.Scheduling.Quartz.2003.csproj b/src/Spring/Spring.Scheduling.Quartz/Spring.Scheduling.Quartz.2003.csproj index cc9fe1c0..8306550a 100644 --- a/src/Spring/Spring.Scheduling.Quartz/Spring.Scheduling.Quartz.2003.csproj +++ b/src/Spring/Spring.Scheduling.Quartz/Spring.Scheduling.Quartz.2003.csproj @@ -133,6 +133,11 @@ SubType = "Code" BuildAction = "Compile" /> + + diff --git a/test/Spring/Spring.Scheduling.Quartz.Tests/Scheduling/Quartz/SchedulerFactoryObjectTest.cs b/test/Spring/Spring.Scheduling.Quartz.Tests/Scheduling/Quartz/SchedulerFactoryObjectTest.cs index 8b54011e..c0665e66 100644 --- a/test/Spring/Spring.Scheduling.Quartz.Tests/Scheduling/Quartz/SchedulerFactoryObjectTest.cs +++ b/test/Spring/Spring.Scheduling.Quartz.Tests/Scheduling/Quartz/SchedulerFactoryObjectTest.cs @@ -198,16 +198,13 @@ namespace Spring.Scheduling.Quartz // set expectations TestSchedulerFactory.MockScheduler.JobFactory = null; LastCall.IgnoreArguments(); - Expect.Call(TestSchedulerFactory.MockScheduler.SchedulerName).Return("schedName"); - TestSchedulerFactory.MockScheduler.Start(); + TestSchedulerFactory.MockScheduler.StartDelayed(2); TestSchedulerFactory.Mockery.ReplayAll(); factory.SchedulerFactoryType = typeof(TestSchedulerFactory); factory.AutoStartup = true; factory.StartupDelay = 2; factory.AfterPropertiesSet(); - Thread.Sleep(TimeSpan.FromSeconds(3)); - } [Test]